We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
1 parent 985e2fb commit 822a8c3Copy full SHA for 822a8c3
lib/internal/per_context/primordials.js
@@ -270,6 +270,8 @@ const {
270
Array: ArrayConstructor,
271
ArrayPrototypeForEach,
272
ArrayPrototypeMap,
273
+ ArrayPrototypePushApply,
274
+ ArrayPrototypeSlice,
275
FinalizationRegistry,
276
FunctionPrototypeCall,
277
Map,
@@ -720,5 +722,26 @@ primordials.SafeStringPrototypeSearch = (str, regexp) => {
720
722
return match ? match.index : -1;
721
723
};
724
725
+/**
726
+ * Variadic functions with lots of arguments will cause stack overflow errors.
727
+ * Use this function when `items` can be arbitrarily large, this function splits
728
+ * it into chunks of size 2**16 making stack overflow less likely.
729
+ * @param {Array<unknown>} arr
730
+ * @param {Parameters<typeof Array.prototype.push>} items
731
+ * @returns {ReturnType<typeof Array.prototype.push>}
732
+ */
733
+primordials.SafeArrayPrototypePushApply = (arr, items) => {
734
+ let end = 0x10000;
735
+ if (end < items.length) {
736
+ let start = 0;
737
+ do {
738
+ ArrayPrototypePushApply(arr, ArrayPrototypeSlice(items, start, start = end));
739
+ end += 0x10000;
740
+ } while (end < items.length);
741
+ items = ArrayPrototypeSlice(items, start);
742
+ }
743
+ return ArrayPrototypePushApply(arr, items);
744
+};
745
+
746
ObjectSetPrototypeOf(primordials, null);
747
ObjectFreeze(primordials);
lib/internal/perf/observe.js
@@ -6,14 +6,14 @@ const {
6
ArrayPrototypeFilter,
7
ArrayPrototypeIncludes,
8
ArrayPrototypePush,
9
- ArrayPrototypePushApply,
10
ArrayPrototypeSlice,
11
ArrayPrototypeSort,
12
Error,
13
MathMax,
14
MathMin,
15
ObjectDefineProperties,
16
ObjectFreeze,
+ SafeArrayPrototypePushApply,
17
SafeMap,
18
SafeSet,
19
Symbol,
@@ -300,7 +300,7 @@ class PerformanceObserver {
300
maybeIncrementObserverCount(type);
301
if (buffered) {
302
const entries = filterBufferMapByNameAndType(undefined, type);
303
- ArrayPrototypePushApply(this.#buffer, entries);
+ SafeArrayPrototypePushApply(this.#buffer, entries);
304
kPending.add(this);
305
if (kPending.size)
306
queuePending();
@@ -507,9 +507,9 @@ function filterBufferMapByNameAndType(name, type) {
507
return [];
508
} else {
509
bufferList = [];
510
- ArrayPrototypePushApply(bufferList, markEntryBuffer);
511
- ArrayPrototypePushApply(bufferList, measureEntryBuffer);
512
- ArrayPrototypePushApply(bufferList, resourceTimingBuffer);
+ SafeArrayPrototypePushApply(bufferList, markEntryBuffer);
+ SafeArrayPrototypePushApply(bufferList, measureEntryBuffer);
+ SafeArrayPrototypePushApply(bufferList, resourceTimingBuffer);
513
}
514
if (name !== undefined) {
515
bufferList = ArrayPrototypeFilter(bufferList, (buffer) => buffer.name === name);
test/parallel/test-performance-many-marks.js
@@ -0,0 +1,9 @@
1
+'use strict';
2
+require('../common');
3
4
+for (let i = 0; i < 1e6; i++) {
5
+ performance.mark(`mark-${i}`);
+}
+performance.getEntriesByName('mark-0');
+performance.clearMarks();
test/parallel/test-primordials-apply.js
@@ -10,6 +10,7 @@ const {
ArrayPrototypeUnshiftApply,
MathMaxApply,
MathMinApply,
StringPrototypeConcatApply,
TypedArrayOfApply,
} = require('internal/test/binding').primordials;
@@ -43,6 +44,26 @@ const {
43
44
assert.deepStrictEqual(arr1, expected);
45
46
47
+{
48
+ const arr1 = [1, 2, 3];
49
+ const arr2 = [4, 5, 6];
50
51
+ const expected = [...arr1, ...arr2];
52
53
+ assert.strictEqual(SafeArrayPrototypePushApply(arr1, arr2), expected.length);
54
+ assert.deepStrictEqual(arr1, expected);
55
56
57
58
59
+ const arr2 = Array.from({ length: 1e6 }, (_, i) => i);
60
61
62
63
64
65
66
67
{
68
const arr1 = [1, 2, 3];
69
const arr2 = [4, 5, 6];
typings/primordials.d.ts
@@ -374,6 +374,7 @@ declare namespace primordials {
374
export const RegExpPrototypeGetUnicode: UncurryGetter<typeof RegExp.prototype, "unicode">;
375
export const RegExpPrototypeSymbolReplace: UncurryMethod<typeof RegExp.prototype, typeof Symbol.replace>
376
export const RegExpPrototypeSymbolSplit: UncurryMethod<typeof RegExp.prototype, typeof Symbol.split>
377
+ export const SafeArrayPrototypePushApply: typeof ArrayPrototypePushApply;
378
export import Set = globalThis.Set;
379
export const SetLength: typeof Set.length
380
export const SetName: typeof Set.name
0 commit comments