• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Bnaya / objectbuffer / 1cc46d885c9a8c4464d8420dc6a68afe83ac9811

pending completion
1cc46d885c9a8c4464d8420dc6a68afe83ac9811

push

github

Bnaya Peretz
wip

458 of 552 branches covered (82.97%)

Branch coverage included in aggregate %.

1249 of 1361 relevant lines covered (91.77%)

277.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/src/internal/arrayHelpers.ts
1
import { incrementRefCount, handleArcForDeletedValuePointer } from "./store";
2
import type { ExternalArgs, GlobalCarrier } from "./interfaces";
3
import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
4
import { ENTRY_TYPE } from "./entry-types";
5
import {
6
  array_length_get,
7
  array_dataspacePointer_get,
8
  array_allocatedLength_get,
9
  array_length_set,
10
  array_set_all,
11
  array_refsCount_get,
12
} from "./generatedStructs";
13
import type { Heap } from "../structsGenerator/consts";
14
import { saveValueIterativeReturnPointer } from "./saveValue";
15
import { invariant } from "./utils";
16

17
export function arrayGetPointerToIndex(
18
  carrier: GlobalCarrier,
19
  pointerToArrayEntry: number,
20
  indexToGet: number
21
) {
22
  // out of bound
23
  invariant(
24
    indexToGet <= array_length_get(carrier.heap, pointerToArrayEntry),
25
    "must bound check array before calling"
26
  );
27

28
  const pointerToThePointer =
29
    array_dataspacePointer_get(carrier.heap, pointerToArrayEntry) +
30
    indexToGet * Uint32Array.BYTES_PER_ELEMENT;
31

32
  return pointerToThePointer;
33
}
34

35
export function arrayGetValuePointerInIndex(
36
  carrier: GlobalCarrier,
37
  pointerToArrayEntry: number,
38
  indexToGet: number
39
) {
40
  return carrier.heap.u32[
41
    arrayGetPointerToIndex(carrier, pointerToArrayEntry, indexToGet) /
42
      Uint32Array.BYTES_PER_ELEMENT
43
  ];
44
}
45

46
export function getFinalValueAtArrayIndex(
47
  externalArgs: ExternalArgs,
48
  globalCarrier: GlobalCarrier,
49
  pointerToArrayEntry: number,
50
  indexToGet: number
51
) {
52
  const pointer = arrayGetValuePointerInIndex(
53
    globalCarrier,
54
    pointerToArrayEntry,
55
    indexToGet
56
  );
57

58
  return entryToFinalJavaScriptValue(externalArgs, globalCarrier, pointer);
59
}
60

61
export function setValuePointerAtArrayIndex(
62
  carrier: GlobalCarrier,
63
  pointerToArrayEntry: number,
64
  indexToSet: number,
65
  pointerToEntry: number
66
) {
67
  const pointer = arrayGetPointerToIndex(
68
    carrier,
69
    pointerToArrayEntry,
70
    indexToSet
71
  );
72

73
  carrier.heap.u32[pointer / Uint32Array.BYTES_PER_ELEMENT] = pointerToEntry;
74
}
75

76
export function setValueAtArrayIndex(
77
  externalArgs: ExternalArgs,
78
  carrier: GlobalCarrier,
79
  pointerToArrayEntry: number,
80
  indexToSet: number,
81
  value: unknown
82
) {
83
  const refedPointers: number[] = [];
84

85
  const newValuePointer = saveValueIterativeReturnPointer(
86
    externalArgs,
87
    carrier,
88
    refedPointers,
89
    value
90
  );
91

92
  extendArrayIfNeeded(
93
    externalArgs,
94
    carrier,
95
    pointerToArrayEntry,
96
    indexToSet + 1
97
  );
98
  // no OOM is possible after this point
99

100
  for (const pointer of refedPointers) {
101
    incrementRefCount(carrier.heap, pointer);
102
  }
103

104
  const pointerToThePointer = arrayGetPointerToIndex(
105
    carrier,
106
    pointerToArrayEntry,
107
    indexToSet
108
  );
109

110
  handleArcForDeletedValuePointer(
111
    carrier,
112
    carrier.heap.u32[pointerToThePointer / Uint32Array.BYTES_PER_ELEMENT]
113
  );
114

115
  carrier.heap.u32[pointerToThePointer / Uint32Array.BYTES_PER_ELEMENT] =
116
    newValuePointer;
117
}
118

119
/**
120
 * Will not shrink the array!
121
 */
122
export function extendArrayIfNeeded(
123
  externalArgs: ExternalArgs,
124
  carrier: GlobalCarrier,
125
  pointerToArrayEntry: number,
126
  wishedLength: number
127
) {
128
  if (wishedLength > array_length_get(carrier.heap, pointerToArrayEntry)) {
42✔
129
    if (
31✔
130
      wishedLength >
131
      array_allocatedLength_get(carrier.heap, pointerToArrayEntry)
132
    ) {
133
      reallocateArray(
134
        carrier,
135
        pointerToArrayEntry,
136
        wishedLength + externalArgs.arrayAdditionalAllocation,
137
        wishedLength
138
      );
139
    } else {
140
      // no need to re-allocated, just push the length forward
141
      array_length_set(carrier.heap, pointerToArrayEntry, wishedLength);
142
    }
143
  }
144
}
145

146
/**
147
 * Will not empty memory or relocate the array!
148
 */
149
export function shrinkArray(
150
  heap: Heap,
151
  pointerToArrayEntry: number,
152
  wishedLength: number
153
) {
154
  array_length_set(heap, pointerToArrayEntry, wishedLength);
155
}
156

157
function reallocateArray(
158
  carrier: GlobalCarrier,
159
  pointerToArrayEntry: number,
160
  newAllocatedLength: number,
161
  newLength: number
162
): void {
163
  const dataspacePointer = array_dataspacePointer_get(
164
    carrier.heap,
165
    pointerToArrayEntry
166
  );
167

168
  // if array was zero length, dataspacePointer was zero
169
  const newArrayValueLocation =
170
    dataspacePointer !== 0
14✔
171
      ? carrier.allocator.realloc(
172
          dataspacePointer,
173
          newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT
174
        )
175
      : carrier.allocator.calloc(
176
          newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT
177
        );
178

179
  array_set_all(
180
    carrier.heap,
181
    pointerToArrayEntry,
182
    ENTRY_TYPE.ARRAY,
183
    array_refsCount_get(carrier.heap, pointerToArrayEntry),
184
    newArrayValueLocation,
185
    newLength,
186
    newAllocatedLength
187
  );
188
}
189

190
export function arraySort(
191
  externalArgs: ExternalArgs,
192
  carrier: GlobalCarrier,
193
  pointerToArrayEntry: number,
194
  sortComparator: (a: any, b: any) => 1 | -1 | 0 = defaultCompareFunction
1✔
195
) {
196
  const arrayDataSpace = array_dataspacePointer_get(
197
    carrier.heap,
198
    pointerToArrayEntry
199
  );
200
  const pointersToValues = [
201
    ...new Array(array_length_get(carrier.heap, pointerToArrayEntry)).keys(),
202
  ]
203
    .map((index) => arrayDataSpace + index * Uint32Array.BYTES_PER_ELEMENT)
204
    .map(
205
      (pointerToPointer) =>
206
        carrier.heap.u32[pointerToPointer / Uint32Array.BYTES_PER_ELEMENT]
207
    );
208

209
  const sortMe = pointersToValues.map((pointer) => {
210
    return [
211
      pointer,
212
      entryToFinalJavaScriptValue(externalArgs, carrier, pointer),
213
    ] as const;
214
  });
215

216
  sortMe.sort((a, b) => {
217
    return sortComparator(a[1], b[1]);
218
  });
219

220
  for (let i = 0; i < sortMe.length; i += 1) {
221
    carrier.heap.u32[
222
      (arrayDataSpace + i * Uint32Array.BYTES_PER_ELEMENT) /
223
        Uint32Array.BYTES_PER_ELEMENT
224
    ] = sortMe[i][0];
225
  }
226
}
227

228
// https://stackoverflow.com/a/47349064/711152
229
function defaultCompareFunction(x: any, y: any) {
230
  //INFO: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
231
  //ECMA specification: http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare
232

233
  if (x === undefined && y === undefined) return 0;
34!
234

235
  if (x === undefined) return 1;
16✔
236

237
  if (y === undefined) return -1;
14✔
238

239
  const xString = toString(x);
240
  const yString = toString(y);
241

242
  if (xString < yString) return -1;
13✔
243

244
  if (xString > yString) return 1;
7!
245

246
  return 0;
247
}
248

249
function toString(obj: any) {
250
  //ECMA specification: http://www.ecma-international.org/ecma-262/6.0/#sec-tostring
251

252
  if (obj === null) return "null";
26✔
253

254
  if (typeof obj === "boolean" || typeof obj === "number")
63!
255
    return obj.toString();
256

257
  if (typeof obj === "string") return obj;
×
258

259
  if (typeof obj === "symbol") throw new TypeError();
×
260

261
  //we know we have an object. perhaps return JSON.stringify?
262
  return obj.toString();
263
}
264

265
export function arrayReverse(
266
  carrier: GlobalCarrier,
267
  pointerToArrayEntry: number
268
) {
269
  for (
270
    let i = 0;
271
    i < Math.floor(array_length_get(carrier.heap, pointerToArrayEntry) / 2);
272
    i += 1
273
  ) {
274
    const theOtherIndex =
275
      array_length_get(carrier.heap, pointerToArrayEntry) - i - 1;
276

277
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
278
    const a = arrayGetValuePointerInIndex(carrier, pointerToArrayEntry, i)!;
279

280
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
281
    const b = arrayGetValuePointerInIndex(
282
      carrier,
283
      pointerToArrayEntry,
284
      theOtherIndex
285
    )!;
286

287
    setValuePointerAtArrayIndex(carrier, pointerToArrayEntry, i, b);
288

289
    setValuePointerAtArrayIndex(carrier, pointerToArrayEntry, theOtherIndex, a);
290
  }
291
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc