seroval 1.6.10 → 1.6.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev/index.cjs +71 -32
- package/dist/dev/index.js +71 -32
- package/dist/index.cjs +71 -32
- package/dist/index.js +71 -32
- package/package.json +1 -1
package/dist/dev/index.cjs
CHANGED
|
@@ -395,6 +395,29 @@ function getObjectFlag(obj) {
|
|
|
395
395
|
return 1;
|
|
396
396
|
}
|
|
397
397
|
//#endregion
|
|
398
|
+
//#region src/core/utils/typed-array.ts
|
|
399
|
+
function getTypedArrayConstructor(name) {
|
|
400
|
+
switch (name) {
|
|
401
|
+
case "Int8Array": return Int8Array;
|
|
402
|
+
case "Int16Array": return Int16Array;
|
|
403
|
+
case "Int32Array": return Int32Array;
|
|
404
|
+
case "Uint8Array": return Uint8Array;
|
|
405
|
+
case "Uint16Array": return Uint16Array;
|
|
406
|
+
case "Uint32Array": return Uint32Array;
|
|
407
|
+
case "Uint8ClampedArray": return Uint8ClampedArray;
|
|
408
|
+
case "Float32Array": return Float32Array;
|
|
409
|
+
case "Float64Array": return Float64Array;
|
|
410
|
+
case "BigInt64Array": return BigInt64Array;
|
|
411
|
+
case "BigUint64Array": return BigUint64Array;
|
|
412
|
+
default: throw new SerovalUnknownTypedArrayError(name);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
let typedArrayNameGetter;
|
|
416
|
+
function getTypedArrayName(value) {
|
|
417
|
+
if (!typedArrayNameGetter) typedArrayNameGetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Int8Array.prototype), Symbol.toStringTag).get;
|
|
418
|
+
return typedArrayNameGetter.call(value);
|
|
419
|
+
}
|
|
420
|
+
//#endregion
|
|
398
421
|
//#region src/core/base-primitives.ts
|
|
399
422
|
function createNumberNode(value) {
|
|
400
423
|
switch (value) {
|
|
@@ -442,11 +465,11 @@ function createBoxedNode(id, boxed) {
|
|
|
442
465
|
const MAX_TYPED_ARRAY_LENGTH = 1e6;
|
|
443
466
|
function createTypedArrayNode(id, current, buffer) {
|
|
444
467
|
if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
445
|
-
return createSerovalNode(15, id, void 0, current
|
|
468
|
+
return createSerovalNode(15, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
|
|
446
469
|
}
|
|
447
470
|
function createBigIntTypedArrayNode(id, current, buffer) {
|
|
448
471
|
if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
449
|
-
return createSerovalNode(16, id, void 0, current
|
|
472
|
+
return createSerovalNode(16, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
|
|
450
473
|
}
|
|
451
474
|
function createDataViewNode(id, current, buffer) {
|
|
452
475
|
if (current.byteLength > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
@@ -980,11 +1003,18 @@ function parseAsyncIteratorFactory(ctx) {
|
|
|
980
1003
|
function createObjectNode(id, current, empty, record) {
|
|
981
1004
|
return createSerovalNode(empty ? 11 : 10, id, void 0, void 0, void 0, record, void 0, void 0, void 0, void 0, getObjectFlag(current), void 0);
|
|
982
1005
|
}
|
|
983
|
-
|
|
1006
|
+
/**
|
|
1007
|
+
* Gets the sentinel node for a Map. Call it before parsing the entries, so
|
|
1008
|
+
* that an outer Map declares the sentinel before any Map inside it uses it.
|
|
1009
|
+
*/
|
|
1010
|
+
function parseMapSentinel(ctx) {
|
|
1011
|
+
return parseSpecialReference(ctx, 0);
|
|
1012
|
+
}
|
|
1013
|
+
function createMapNode(id, sentinel, k, v) {
|
|
984
1014
|
return createSerovalNode(8, id, void 0, void 0, void 0, void 0, {
|
|
985
1015
|
k,
|
|
986
1016
|
v
|
|
987
|
-
}, void 0,
|
|
1017
|
+
}, void 0, sentinel, void 0, void 0, void 0);
|
|
988
1018
|
}
|
|
989
1019
|
function createPromiseConstructorNode(ctx, id, resolver) {
|
|
990
1020
|
return createSerovalNode(22, id, resolver, void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 1), void 0, void 0, void 0);
|
|
@@ -992,8 +1022,7 @@ function createPromiseConstructorNode(ctx, id, resolver) {
|
|
|
992
1022
|
function getArrayBufferView(ctx, current) {
|
|
993
1023
|
if (!ctx.compactArrayBufferViews) return current;
|
|
994
1024
|
const buffer = new Uint8Array(current.buffer, current.byteOffset, current.byteLength).slice().buffer;
|
|
995
|
-
|
|
996
|
-
return new Constructor(buffer);
|
|
1025
|
+
return new (current instanceof DataView ? DataView : getTypedArrayConstructor(getTypedArrayName(current)))(buffer);
|
|
997
1026
|
}
|
|
998
1027
|
function encodeArrayBuffer(current) {
|
|
999
1028
|
if (typeof Buffer !== "undefined") return Buffer.from(current).toString("base64");
|
|
@@ -1088,13 +1117,14 @@ async function parseAggregateError$1(ctx, depth, id, current) {
|
|
|
1088
1117
|
return createAggregateErrorNode(id, current, options ? await parseProperties$1(ctx, depth, options) : void 0);
|
|
1089
1118
|
}
|
|
1090
1119
|
async function parseMap$1(ctx, depth, id, current) {
|
|
1120
|
+
const sentinel = parseMapSentinel(ctx.base);
|
|
1091
1121
|
const keyNodes = [];
|
|
1092
1122
|
const valueNodes = [];
|
|
1093
1123
|
for (const [key, value] of current.entries()) {
|
|
1094
1124
|
keyNodes.push(await parseAsync(ctx, depth, key));
|
|
1095
1125
|
valueNodes.push(await parseAsync(ctx, depth, value));
|
|
1096
1126
|
}
|
|
1097
|
-
return createMapNode(
|
|
1127
|
+
return createMapNode(id, sentinel, keyNodes, valueNodes);
|
|
1098
1128
|
}
|
|
1099
1129
|
async function parseSet$1(ctx, depth, id, current) {
|
|
1100
1130
|
const items = [];
|
|
@@ -1279,24 +1309,6 @@ function resolvePlugins(plugins) {
|
|
|
1279
1309
|
}
|
|
1280
1310
|
}
|
|
1281
1311
|
//#endregion
|
|
1282
|
-
//#region src/core/utils/typed-array.ts
|
|
1283
|
-
function getTypedArrayConstructor(name) {
|
|
1284
|
-
switch (name) {
|
|
1285
|
-
case "Int8Array": return Int8Array;
|
|
1286
|
-
case "Int16Array": return Int16Array;
|
|
1287
|
-
case "Int32Array": return Int32Array;
|
|
1288
|
-
case "Uint8Array": return Uint8Array;
|
|
1289
|
-
case "Uint16Array": return Uint16Array;
|
|
1290
|
-
case "Uint32Array": return Uint32Array;
|
|
1291
|
-
case "Uint8ClampedArray": return Uint8ClampedArray;
|
|
1292
|
-
case "Float32Array": return Float32Array;
|
|
1293
|
-
case "Float64Array": return Float64Array;
|
|
1294
|
-
case "BigInt64Array": return BigInt64Array;
|
|
1295
|
-
case "BigUint64Array": return BigUint64Array;
|
|
1296
|
-
default: throw new SerovalUnknownTypedArrayError(name);
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
//#endregion
|
|
1300
1312
|
//#region src/core/utils/valid-properties.ts
|
|
1301
1313
|
function isValidKey(key) {
|
|
1302
1314
|
switch (key) {
|
|
@@ -1766,30 +1778,36 @@ function getAssignmentExpression(assignment) {
|
|
|
1766
1778
|
case 4: return "Object.defineProperty(" + assignment.s + ",\"__proto__\",{value:" + assignment.k + ",configurable:!0,enumerable:!0,writable:!0})";
|
|
1767
1779
|
}
|
|
1768
1780
|
}
|
|
1781
|
+
const MAX_ASSIGNMENT_CHAIN_LENGTH = 100;
|
|
1769
1782
|
function mergeAssignments(assignments) {
|
|
1770
1783
|
const newAssignments = [];
|
|
1771
1784
|
let current = assignments[0];
|
|
1785
|
+
let chainLength = 1;
|
|
1772
1786
|
for (let i = 1, len = assignments.length, item, prev = current; i < len; i++) {
|
|
1773
1787
|
item = assignments[i];
|
|
1774
|
-
if (
|
|
1788
|
+
if (chainLength === MAX_ASSIGNMENT_CHAIN_LENGTH) {
|
|
1789
|
+
newAssignments.push(current);
|
|
1790
|
+
current = item;
|
|
1791
|
+
chainLength = 0;
|
|
1792
|
+
} else if (item.t === 0 && prev.t === 0 && item.v === prev.v) current = {
|
|
1775
1793
|
t: 0,
|
|
1776
1794
|
s: item.s,
|
|
1777
1795
|
k: void 0,
|
|
1778
1796
|
v: getAssignmentExpression(current)
|
|
1779
1797
|
};
|
|
1780
|
-
else if (item.t === 2 && item.s === prev.s) current = {
|
|
1798
|
+
else if (item.t === 2 && prev.t === 2 && item.s === prev.s) current = {
|
|
1781
1799
|
t: 2,
|
|
1782
1800
|
s: getAssignmentExpression(current),
|
|
1783
1801
|
k: item.k,
|
|
1784
1802
|
v: item.v
|
|
1785
1803
|
};
|
|
1786
|
-
else if (item.t === 1 && item.s === prev.s) current = {
|
|
1804
|
+
else if (item.t === 1 && prev.t === 1 && item.s === prev.s) current = {
|
|
1787
1805
|
t: 1,
|
|
1788
1806
|
s: getAssignmentExpression(current),
|
|
1789
1807
|
k: void 0,
|
|
1790
1808
|
v: item.v
|
|
1791
1809
|
};
|
|
1792
|
-
else if (item.t === 3 && item.s === prev.s) current = {
|
|
1810
|
+
else if (item.t === 3 && prev.t === 2 && item.s === prev.s) current = {
|
|
1793
1811
|
t: 3,
|
|
1794
1812
|
s: getAssignmentExpression(current),
|
|
1795
1813
|
k: item.k,
|
|
@@ -1798,7 +1816,9 @@ function mergeAssignments(assignments) {
|
|
|
1798
1816
|
else {
|
|
1799
1817
|
newAssignments.push(current);
|
|
1800
1818
|
current = item;
|
|
1819
|
+
chainLength = 0;
|
|
1801
1820
|
}
|
|
1821
|
+
chainLength++;
|
|
1802
1822
|
prev = item;
|
|
1803
1823
|
}
|
|
1804
1824
|
newAssignments.push(current);
|
|
@@ -1993,6 +2013,22 @@ function isIndexedValueInStack(ctx, node) {
|
|
|
1993
2013
|
return node.t === 4 && ctx.stack.includes(node.i);
|
|
1994
2014
|
}
|
|
1995
2015
|
/**
|
|
2016
|
+
* Checks if the node, or any node inside it, is read from more than one
|
|
2017
|
+
* place. Such a node must not be created inside a deferred assignment,
|
|
2018
|
+
* because the places that read it may run before the assignment does.
|
|
2019
|
+
*/
|
|
2020
|
+
function hasMarkedNode(ctx, node) {
|
|
2021
|
+
if (Array.isArray(node)) {
|
|
2022
|
+
for (let i = 0, len = node.length; i < len; i++) if (hasMarkedNode(ctx, node[i])) return true;
|
|
2023
|
+
return false;
|
|
2024
|
+
}
|
|
2025
|
+
if (node == null || typeof node !== "object") return false;
|
|
2026
|
+
const current = node;
|
|
2027
|
+
if (current.t !== 4 && typeof current.i === "number" && isSerializerRefMarked(ctx, current.i)) return true;
|
|
2028
|
+
for (const key in current) if (hasMarkedNode(ctx, current[key])) return true;
|
|
2029
|
+
return false;
|
|
2030
|
+
}
|
|
2031
|
+
/**
|
|
1996
2032
|
* Produces an assignment expression. `id` generates a reference
|
|
1997
2033
|
* parameter (through `getRefParam`) and has the option to
|
|
1998
2034
|
* return the reference parameter directly or assign a value to
|
|
@@ -2202,7 +2238,8 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
|
|
|
2202
2238
|
createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
|
|
2203
2239
|
return "";
|
|
2204
2240
|
}
|
|
2205
|
-
if (val.t !== 4 && val.i != null &&
|
|
2241
|
+
if (val.t !== 4 && val.i != null && hasMarkedNode(base, val)) {
|
|
2242
|
+
markSerializerRef(base, val.i);
|
|
2206
2243
|
const serialized = "(" + serialize$1(ctx, val) + ",[" + sentinel + "," + sentinel + "])";
|
|
2207
2244
|
createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
|
|
2208
2245
|
createDeleteAssignment(ctx, id, sentinel);
|
|
@@ -2217,7 +2254,8 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
|
|
|
2217
2254
|
if (isIndexedValueInStack(base, val)) {
|
|
2218
2255
|
const valueRef = getRefParam(ctx, val.i);
|
|
2219
2256
|
markSerializerRef(base, id);
|
|
2220
|
-
if (key.t !== 4 && key.i != null &&
|
|
2257
|
+
if (key.t !== 4 && key.i != null && hasMarkedNode(base, key)) {
|
|
2258
|
+
markSerializerRef(base, key.i);
|
|
2221
2259
|
const serialized = "(" + serialize$1(ctx, key) + ",[" + sentinel + "," + sentinel + "])";
|
|
2222
2260
|
createSetAssignment(ctx, id, getRefParam(ctx, key.i), valueRef);
|
|
2223
2261
|
createDeleteAssignment(ctx, id, sentinel);
|
|
@@ -2613,13 +2651,14 @@ function parseAggregateError(ctx, depth, id, current) {
|
|
|
2613
2651
|
return createAggregateErrorNode(id, current, options ? parseProperties(ctx, depth, options) : void 0);
|
|
2614
2652
|
}
|
|
2615
2653
|
function parseMap(ctx, depth, id, current) {
|
|
2654
|
+
const sentinel = parseMapSentinel(ctx.base);
|
|
2616
2655
|
const keyNodes = [];
|
|
2617
2656
|
const valueNodes = [];
|
|
2618
2657
|
for (const [key, value] of current.entries()) {
|
|
2619
2658
|
keyNodes.push(parseSOS(ctx, depth, key));
|
|
2620
2659
|
valueNodes.push(parseSOS(ctx, depth, value));
|
|
2621
2660
|
}
|
|
2622
|
-
return createMapNode(
|
|
2661
|
+
return createMapNode(id, sentinel, keyNodes, valueNodes);
|
|
2623
2662
|
}
|
|
2624
2663
|
function parseSet(ctx, depth, id, current) {
|
|
2625
2664
|
const items = [];
|
package/dist/dev/index.js
CHANGED
|
@@ -394,6 +394,29 @@ function getObjectFlag(obj) {
|
|
|
394
394
|
return 1;
|
|
395
395
|
}
|
|
396
396
|
//#endregion
|
|
397
|
+
//#region src/core/utils/typed-array.ts
|
|
398
|
+
function getTypedArrayConstructor(name) {
|
|
399
|
+
switch (name) {
|
|
400
|
+
case "Int8Array": return Int8Array;
|
|
401
|
+
case "Int16Array": return Int16Array;
|
|
402
|
+
case "Int32Array": return Int32Array;
|
|
403
|
+
case "Uint8Array": return Uint8Array;
|
|
404
|
+
case "Uint16Array": return Uint16Array;
|
|
405
|
+
case "Uint32Array": return Uint32Array;
|
|
406
|
+
case "Uint8ClampedArray": return Uint8ClampedArray;
|
|
407
|
+
case "Float32Array": return Float32Array;
|
|
408
|
+
case "Float64Array": return Float64Array;
|
|
409
|
+
case "BigInt64Array": return BigInt64Array;
|
|
410
|
+
case "BigUint64Array": return BigUint64Array;
|
|
411
|
+
default: throw new SerovalUnknownTypedArrayError(name);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
let typedArrayNameGetter;
|
|
415
|
+
function getTypedArrayName(value) {
|
|
416
|
+
if (!typedArrayNameGetter) typedArrayNameGetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Int8Array.prototype), Symbol.toStringTag).get;
|
|
417
|
+
return typedArrayNameGetter.call(value);
|
|
418
|
+
}
|
|
419
|
+
//#endregion
|
|
397
420
|
//#region src/core/base-primitives.ts
|
|
398
421
|
function createNumberNode(value) {
|
|
399
422
|
switch (value) {
|
|
@@ -441,11 +464,11 @@ function createBoxedNode(id, boxed) {
|
|
|
441
464
|
const MAX_TYPED_ARRAY_LENGTH = 1e6;
|
|
442
465
|
function createTypedArrayNode(id, current, buffer) {
|
|
443
466
|
if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
444
|
-
return createSerovalNode(15, id, void 0, current
|
|
467
|
+
return createSerovalNode(15, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
|
|
445
468
|
}
|
|
446
469
|
function createBigIntTypedArrayNode(id, current, buffer) {
|
|
447
470
|
if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
448
|
-
return createSerovalNode(16, id, void 0, current
|
|
471
|
+
return createSerovalNode(16, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
|
|
449
472
|
}
|
|
450
473
|
function createDataViewNode(id, current, buffer) {
|
|
451
474
|
if (current.byteLength > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
@@ -979,11 +1002,18 @@ function parseAsyncIteratorFactory(ctx) {
|
|
|
979
1002
|
function createObjectNode(id, current, empty, record) {
|
|
980
1003
|
return createSerovalNode(empty ? 11 : 10, id, void 0, void 0, void 0, record, void 0, void 0, void 0, void 0, getObjectFlag(current), void 0);
|
|
981
1004
|
}
|
|
982
|
-
|
|
1005
|
+
/**
|
|
1006
|
+
* Gets the sentinel node for a Map. Call it before parsing the entries, so
|
|
1007
|
+
* that an outer Map declares the sentinel before any Map inside it uses it.
|
|
1008
|
+
*/
|
|
1009
|
+
function parseMapSentinel(ctx) {
|
|
1010
|
+
return parseSpecialReference(ctx, 0);
|
|
1011
|
+
}
|
|
1012
|
+
function createMapNode(id, sentinel, k, v) {
|
|
983
1013
|
return createSerovalNode(8, id, void 0, void 0, void 0, void 0, {
|
|
984
1014
|
k,
|
|
985
1015
|
v
|
|
986
|
-
}, void 0,
|
|
1016
|
+
}, void 0, sentinel, void 0, void 0, void 0);
|
|
987
1017
|
}
|
|
988
1018
|
function createPromiseConstructorNode(ctx, id, resolver) {
|
|
989
1019
|
return createSerovalNode(22, id, resolver, void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 1), void 0, void 0, void 0);
|
|
@@ -991,8 +1021,7 @@ function createPromiseConstructorNode(ctx, id, resolver) {
|
|
|
991
1021
|
function getArrayBufferView(ctx, current) {
|
|
992
1022
|
if (!ctx.compactArrayBufferViews) return current;
|
|
993
1023
|
const buffer = new Uint8Array(current.buffer, current.byteOffset, current.byteLength).slice().buffer;
|
|
994
|
-
|
|
995
|
-
return new Constructor(buffer);
|
|
1024
|
+
return new (current instanceof DataView ? DataView : getTypedArrayConstructor(getTypedArrayName(current)))(buffer);
|
|
996
1025
|
}
|
|
997
1026
|
function encodeArrayBuffer(current) {
|
|
998
1027
|
if (typeof Buffer !== "undefined") return Buffer.from(current).toString("base64");
|
|
@@ -1087,13 +1116,14 @@ async function parseAggregateError$1(ctx, depth, id, current) {
|
|
|
1087
1116
|
return createAggregateErrorNode(id, current, options ? await parseProperties$1(ctx, depth, options) : void 0);
|
|
1088
1117
|
}
|
|
1089
1118
|
async function parseMap$1(ctx, depth, id, current) {
|
|
1119
|
+
const sentinel = parseMapSentinel(ctx.base);
|
|
1090
1120
|
const keyNodes = [];
|
|
1091
1121
|
const valueNodes = [];
|
|
1092
1122
|
for (const [key, value] of current.entries()) {
|
|
1093
1123
|
keyNodes.push(await parseAsync(ctx, depth, key));
|
|
1094
1124
|
valueNodes.push(await parseAsync(ctx, depth, value));
|
|
1095
1125
|
}
|
|
1096
|
-
return createMapNode(
|
|
1126
|
+
return createMapNode(id, sentinel, keyNodes, valueNodes);
|
|
1097
1127
|
}
|
|
1098
1128
|
async function parseSet$1(ctx, depth, id, current) {
|
|
1099
1129
|
const items = [];
|
|
@@ -1278,24 +1308,6 @@ function resolvePlugins(plugins) {
|
|
|
1278
1308
|
}
|
|
1279
1309
|
}
|
|
1280
1310
|
//#endregion
|
|
1281
|
-
//#region src/core/utils/typed-array.ts
|
|
1282
|
-
function getTypedArrayConstructor(name) {
|
|
1283
|
-
switch (name) {
|
|
1284
|
-
case "Int8Array": return Int8Array;
|
|
1285
|
-
case "Int16Array": return Int16Array;
|
|
1286
|
-
case "Int32Array": return Int32Array;
|
|
1287
|
-
case "Uint8Array": return Uint8Array;
|
|
1288
|
-
case "Uint16Array": return Uint16Array;
|
|
1289
|
-
case "Uint32Array": return Uint32Array;
|
|
1290
|
-
case "Uint8ClampedArray": return Uint8ClampedArray;
|
|
1291
|
-
case "Float32Array": return Float32Array;
|
|
1292
|
-
case "Float64Array": return Float64Array;
|
|
1293
|
-
case "BigInt64Array": return BigInt64Array;
|
|
1294
|
-
case "BigUint64Array": return BigUint64Array;
|
|
1295
|
-
default: throw new SerovalUnknownTypedArrayError(name);
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
//#endregion
|
|
1299
1311
|
//#region src/core/utils/valid-properties.ts
|
|
1300
1312
|
function isValidKey(key) {
|
|
1301
1313
|
switch (key) {
|
|
@@ -1765,30 +1777,36 @@ function getAssignmentExpression(assignment) {
|
|
|
1765
1777
|
case 4: return "Object.defineProperty(" + assignment.s + ",\"__proto__\",{value:" + assignment.k + ",configurable:!0,enumerable:!0,writable:!0})";
|
|
1766
1778
|
}
|
|
1767
1779
|
}
|
|
1780
|
+
const MAX_ASSIGNMENT_CHAIN_LENGTH = 100;
|
|
1768
1781
|
function mergeAssignments(assignments) {
|
|
1769
1782
|
const newAssignments = [];
|
|
1770
1783
|
let current = assignments[0];
|
|
1784
|
+
let chainLength = 1;
|
|
1771
1785
|
for (let i = 1, len = assignments.length, item, prev = current; i < len; i++) {
|
|
1772
1786
|
item = assignments[i];
|
|
1773
|
-
if (
|
|
1787
|
+
if (chainLength === MAX_ASSIGNMENT_CHAIN_LENGTH) {
|
|
1788
|
+
newAssignments.push(current);
|
|
1789
|
+
current = item;
|
|
1790
|
+
chainLength = 0;
|
|
1791
|
+
} else if (item.t === 0 && prev.t === 0 && item.v === prev.v) current = {
|
|
1774
1792
|
t: 0,
|
|
1775
1793
|
s: item.s,
|
|
1776
1794
|
k: void 0,
|
|
1777
1795
|
v: getAssignmentExpression(current)
|
|
1778
1796
|
};
|
|
1779
|
-
else if (item.t === 2 && item.s === prev.s) current = {
|
|
1797
|
+
else if (item.t === 2 && prev.t === 2 && item.s === prev.s) current = {
|
|
1780
1798
|
t: 2,
|
|
1781
1799
|
s: getAssignmentExpression(current),
|
|
1782
1800
|
k: item.k,
|
|
1783
1801
|
v: item.v
|
|
1784
1802
|
};
|
|
1785
|
-
else if (item.t === 1 && item.s === prev.s) current = {
|
|
1803
|
+
else if (item.t === 1 && prev.t === 1 && item.s === prev.s) current = {
|
|
1786
1804
|
t: 1,
|
|
1787
1805
|
s: getAssignmentExpression(current),
|
|
1788
1806
|
k: void 0,
|
|
1789
1807
|
v: item.v
|
|
1790
1808
|
};
|
|
1791
|
-
else if (item.t === 3 && item.s === prev.s) current = {
|
|
1809
|
+
else if (item.t === 3 && prev.t === 2 && item.s === prev.s) current = {
|
|
1792
1810
|
t: 3,
|
|
1793
1811
|
s: getAssignmentExpression(current),
|
|
1794
1812
|
k: item.k,
|
|
@@ -1797,7 +1815,9 @@ function mergeAssignments(assignments) {
|
|
|
1797
1815
|
else {
|
|
1798
1816
|
newAssignments.push(current);
|
|
1799
1817
|
current = item;
|
|
1818
|
+
chainLength = 0;
|
|
1800
1819
|
}
|
|
1820
|
+
chainLength++;
|
|
1801
1821
|
prev = item;
|
|
1802
1822
|
}
|
|
1803
1823
|
newAssignments.push(current);
|
|
@@ -1992,6 +2012,22 @@ function isIndexedValueInStack(ctx, node) {
|
|
|
1992
2012
|
return node.t === 4 && ctx.stack.includes(node.i);
|
|
1993
2013
|
}
|
|
1994
2014
|
/**
|
|
2015
|
+
* Checks if the node, or any node inside it, is read from more than one
|
|
2016
|
+
* place. Such a node must not be created inside a deferred assignment,
|
|
2017
|
+
* because the places that read it may run before the assignment does.
|
|
2018
|
+
*/
|
|
2019
|
+
function hasMarkedNode(ctx, node) {
|
|
2020
|
+
if (Array.isArray(node)) {
|
|
2021
|
+
for (let i = 0, len = node.length; i < len; i++) if (hasMarkedNode(ctx, node[i])) return true;
|
|
2022
|
+
return false;
|
|
2023
|
+
}
|
|
2024
|
+
if (node == null || typeof node !== "object") return false;
|
|
2025
|
+
const current = node;
|
|
2026
|
+
if (current.t !== 4 && typeof current.i === "number" && isSerializerRefMarked(ctx, current.i)) return true;
|
|
2027
|
+
for (const key in current) if (hasMarkedNode(ctx, current[key])) return true;
|
|
2028
|
+
return false;
|
|
2029
|
+
}
|
|
2030
|
+
/**
|
|
1995
2031
|
* Produces an assignment expression. `id` generates a reference
|
|
1996
2032
|
* parameter (through `getRefParam`) and has the option to
|
|
1997
2033
|
* return the reference parameter directly or assign a value to
|
|
@@ -2201,7 +2237,8 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
|
|
|
2201
2237
|
createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
|
|
2202
2238
|
return "";
|
|
2203
2239
|
}
|
|
2204
|
-
if (val.t !== 4 && val.i != null &&
|
|
2240
|
+
if (val.t !== 4 && val.i != null && hasMarkedNode(base, val)) {
|
|
2241
|
+
markSerializerRef(base, val.i);
|
|
2205
2242
|
const serialized = "(" + serialize$1(ctx, val) + ",[" + sentinel + "," + sentinel + "])";
|
|
2206
2243
|
createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
|
|
2207
2244
|
createDeleteAssignment(ctx, id, sentinel);
|
|
@@ -2216,7 +2253,8 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
|
|
|
2216
2253
|
if (isIndexedValueInStack(base, val)) {
|
|
2217
2254
|
const valueRef = getRefParam(ctx, val.i);
|
|
2218
2255
|
markSerializerRef(base, id);
|
|
2219
|
-
if (key.t !== 4 && key.i != null &&
|
|
2256
|
+
if (key.t !== 4 && key.i != null && hasMarkedNode(base, key)) {
|
|
2257
|
+
markSerializerRef(base, key.i);
|
|
2220
2258
|
const serialized = "(" + serialize$1(ctx, key) + ",[" + sentinel + "," + sentinel + "])";
|
|
2221
2259
|
createSetAssignment(ctx, id, getRefParam(ctx, key.i), valueRef);
|
|
2222
2260
|
createDeleteAssignment(ctx, id, sentinel);
|
|
@@ -2612,13 +2650,14 @@ function parseAggregateError(ctx, depth, id, current) {
|
|
|
2612
2650
|
return createAggregateErrorNode(id, current, options ? parseProperties(ctx, depth, options) : void 0);
|
|
2613
2651
|
}
|
|
2614
2652
|
function parseMap(ctx, depth, id, current) {
|
|
2653
|
+
const sentinel = parseMapSentinel(ctx.base);
|
|
2615
2654
|
const keyNodes = [];
|
|
2616
2655
|
const valueNodes = [];
|
|
2617
2656
|
for (const [key, value] of current.entries()) {
|
|
2618
2657
|
keyNodes.push(parseSOS(ctx, depth, key));
|
|
2619
2658
|
valueNodes.push(parseSOS(ctx, depth, value));
|
|
2620
2659
|
}
|
|
2621
|
-
return createMapNode(
|
|
2660
|
+
return createMapNode(id, sentinel, keyNodes, valueNodes);
|
|
2622
2661
|
}
|
|
2623
2662
|
function parseSet(ctx, depth, id, current) {
|
|
2624
2663
|
const items = [];
|
package/dist/index.cjs
CHANGED
|
@@ -388,6 +388,29 @@ function getObjectFlag(obj) {
|
|
|
388
388
|
return 1;
|
|
389
389
|
}
|
|
390
390
|
//#endregion
|
|
391
|
+
//#region src/core/utils/typed-array.ts
|
|
392
|
+
function getTypedArrayConstructor(name) {
|
|
393
|
+
switch (name) {
|
|
394
|
+
case "Int8Array": return Int8Array;
|
|
395
|
+
case "Int16Array": return Int16Array;
|
|
396
|
+
case "Int32Array": return Int32Array;
|
|
397
|
+
case "Uint8Array": return Uint8Array;
|
|
398
|
+
case "Uint16Array": return Uint16Array;
|
|
399
|
+
case "Uint32Array": return Uint32Array;
|
|
400
|
+
case "Uint8ClampedArray": return Uint8ClampedArray;
|
|
401
|
+
case "Float32Array": return Float32Array;
|
|
402
|
+
case "Float64Array": return Float64Array;
|
|
403
|
+
case "BigInt64Array": return BigInt64Array;
|
|
404
|
+
case "BigUint64Array": return BigUint64Array;
|
|
405
|
+
default: throw new SerovalUnknownTypedArrayError(name);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
let typedArrayNameGetter;
|
|
409
|
+
function getTypedArrayName(value) {
|
|
410
|
+
if (!typedArrayNameGetter) typedArrayNameGetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Int8Array.prototype), Symbol.toStringTag).get;
|
|
411
|
+
return typedArrayNameGetter.call(value);
|
|
412
|
+
}
|
|
413
|
+
//#endregion
|
|
391
414
|
//#region src/core/base-primitives.ts
|
|
392
415
|
function createNumberNode(value) {
|
|
393
416
|
switch (value) {
|
|
@@ -435,11 +458,11 @@ function createBoxedNode(id, boxed) {
|
|
|
435
458
|
const MAX_TYPED_ARRAY_LENGTH = 1e6;
|
|
436
459
|
function createTypedArrayNode(id, current, buffer) {
|
|
437
460
|
if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
438
|
-
return createSerovalNode(15, id, void 0, current
|
|
461
|
+
return createSerovalNode(15, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
|
|
439
462
|
}
|
|
440
463
|
function createBigIntTypedArrayNode(id, current, buffer) {
|
|
441
464
|
if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
442
|
-
return createSerovalNode(16, id, void 0, current
|
|
465
|
+
return createSerovalNode(16, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
|
|
443
466
|
}
|
|
444
467
|
function createDataViewNode(id, current, buffer) {
|
|
445
468
|
if (current.byteLength > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
@@ -973,11 +996,18 @@ function parseAsyncIteratorFactory(ctx) {
|
|
|
973
996
|
function createObjectNode(id, current, empty, record) {
|
|
974
997
|
return createSerovalNode(empty ? 11 : 10, id, void 0, void 0, void 0, record, void 0, void 0, void 0, void 0, getObjectFlag(current), void 0);
|
|
975
998
|
}
|
|
976
|
-
|
|
999
|
+
/**
|
|
1000
|
+
* Gets the sentinel node for a Map. Call it before parsing the entries, so
|
|
1001
|
+
* that an outer Map declares the sentinel before any Map inside it uses it.
|
|
1002
|
+
*/
|
|
1003
|
+
function parseMapSentinel(ctx) {
|
|
1004
|
+
return parseSpecialReference(ctx, 0);
|
|
1005
|
+
}
|
|
1006
|
+
function createMapNode(id, sentinel, k, v) {
|
|
977
1007
|
return createSerovalNode(8, id, void 0, void 0, void 0, void 0, {
|
|
978
1008
|
k,
|
|
979
1009
|
v
|
|
980
|
-
}, void 0,
|
|
1010
|
+
}, void 0, sentinel, void 0, void 0, void 0);
|
|
981
1011
|
}
|
|
982
1012
|
function createPromiseConstructorNode(ctx, id, resolver) {
|
|
983
1013
|
return createSerovalNode(22, id, resolver, void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 1), void 0, void 0, void 0);
|
|
@@ -985,8 +1015,7 @@ function createPromiseConstructorNode(ctx, id, resolver) {
|
|
|
985
1015
|
function getArrayBufferView(ctx, current) {
|
|
986
1016
|
if (!ctx.compactArrayBufferViews) return current;
|
|
987
1017
|
const buffer = new Uint8Array(current.buffer, current.byteOffset, current.byteLength).slice().buffer;
|
|
988
|
-
|
|
989
|
-
return new Constructor(buffer);
|
|
1018
|
+
return new (current instanceof DataView ? DataView : getTypedArrayConstructor(getTypedArrayName(current)))(buffer);
|
|
990
1019
|
}
|
|
991
1020
|
function encodeArrayBuffer(current) {
|
|
992
1021
|
if (typeof Buffer !== "undefined") return Buffer.from(current).toString("base64");
|
|
@@ -1081,13 +1110,14 @@ async function parseAggregateError$1(ctx, depth, id, current) {
|
|
|
1081
1110
|
return createAggregateErrorNode(id, current, options ? await parseProperties$1(ctx, depth, options) : void 0);
|
|
1082
1111
|
}
|
|
1083
1112
|
async function parseMap$1(ctx, depth, id, current) {
|
|
1113
|
+
const sentinel = parseMapSentinel(ctx.base);
|
|
1084
1114
|
const keyNodes = [];
|
|
1085
1115
|
const valueNodes = [];
|
|
1086
1116
|
for (const [key, value] of current.entries()) {
|
|
1087
1117
|
keyNodes.push(await parseAsync(ctx, depth, key));
|
|
1088
1118
|
valueNodes.push(await parseAsync(ctx, depth, value));
|
|
1089
1119
|
}
|
|
1090
|
-
return createMapNode(
|
|
1120
|
+
return createMapNode(id, sentinel, keyNodes, valueNodes);
|
|
1091
1121
|
}
|
|
1092
1122
|
async function parseSet$1(ctx, depth, id, current) {
|
|
1093
1123
|
const items = [];
|
|
@@ -1272,24 +1302,6 @@ function resolvePlugins(plugins) {
|
|
|
1272
1302
|
}
|
|
1273
1303
|
}
|
|
1274
1304
|
//#endregion
|
|
1275
|
-
//#region src/core/utils/typed-array.ts
|
|
1276
|
-
function getTypedArrayConstructor(name) {
|
|
1277
|
-
switch (name) {
|
|
1278
|
-
case "Int8Array": return Int8Array;
|
|
1279
|
-
case "Int16Array": return Int16Array;
|
|
1280
|
-
case "Int32Array": return Int32Array;
|
|
1281
|
-
case "Uint8Array": return Uint8Array;
|
|
1282
|
-
case "Uint16Array": return Uint16Array;
|
|
1283
|
-
case "Uint32Array": return Uint32Array;
|
|
1284
|
-
case "Uint8ClampedArray": return Uint8ClampedArray;
|
|
1285
|
-
case "Float32Array": return Float32Array;
|
|
1286
|
-
case "Float64Array": return Float64Array;
|
|
1287
|
-
case "BigInt64Array": return BigInt64Array;
|
|
1288
|
-
case "BigUint64Array": return BigUint64Array;
|
|
1289
|
-
default: throw new SerovalUnknownTypedArrayError(name);
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
//#endregion
|
|
1293
1305
|
//#region src/core/utils/valid-properties.ts
|
|
1294
1306
|
function isValidKey(key) {
|
|
1295
1307
|
switch (key) {
|
|
@@ -1759,30 +1771,36 @@ function getAssignmentExpression(assignment) {
|
|
|
1759
1771
|
case 4: return "Object.defineProperty(" + assignment.s + ",\"__proto__\",{value:" + assignment.k + ",configurable:!0,enumerable:!0,writable:!0})";
|
|
1760
1772
|
}
|
|
1761
1773
|
}
|
|
1774
|
+
const MAX_ASSIGNMENT_CHAIN_LENGTH = 100;
|
|
1762
1775
|
function mergeAssignments(assignments) {
|
|
1763
1776
|
const newAssignments = [];
|
|
1764
1777
|
let current = assignments[0];
|
|
1778
|
+
let chainLength = 1;
|
|
1765
1779
|
for (let i = 1, len = assignments.length, item, prev = current; i < len; i++) {
|
|
1766
1780
|
item = assignments[i];
|
|
1767
|
-
if (
|
|
1781
|
+
if (chainLength === MAX_ASSIGNMENT_CHAIN_LENGTH) {
|
|
1782
|
+
newAssignments.push(current);
|
|
1783
|
+
current = item;
|
|
1784
|
+
chainLength = 0;
|
|
1785
|
+
} else if (item.t === 0 && prev.t === 0 && item.v === prev.v) current = {
|
|
1768
1786
|
t: 0,
|
|
1769
1787
|
s: item.s,
|
|
1770
1788
|
k: void 0,
|
|
1771
1789
|
v: getAssignmentExpression(current)
|
|
1772
1790
|
};
|
|
1773
|
-
else if (item.t === 2 && item.s === prev.s) current = {
|
|
1791
|
+
else if (item.t === 2 && prev.t === 2 && item.s === prev.s) current = {
|
|
1774
1792
|
t: 2,
|
|
1775
1793
|
s: getAssignmentExpression(current),
|
|
1776
1794
|
k: item.k,
|
|
1777
1795
|
v: item.v
|
|
1778
1796
|
};
|
|
1779
|
-
else if (item.t === 1 && item.s === prev.s) current = {
|
|
1797
|
+
else if (item.t === 1 && prev.t === 1 && item.s === prev.s) current = {
|
|
1780
1798
|
t: 1,
|
|
1781
1799
|
s: getAssignmentExpression(current),
|
|
1782
1800
|
k: void 0,
|
|
1783
1801
|
v: item.v
|
|
1784
1802
|
};
|
|
1785
|
-
else if (item.t === 3 && item.s === prev.s) current = {
|
|
1803
|
+
else if (item.t === 3 && prev.t === 2 && item.s === prev.s) current = {
|
|
1786
1804
|
t: 3,
|
|
1787
1805
|
s: getAssignmentExpression(current),
|
|
1788
1806
|
k: item.k,
|
|
@@ -1791,7 +1809,9 @@ function mergeAssignments(assignments) {
|
|
|
1791
1809
|
else {
|
|
1792
1810
|
newAssignments.push(current);
|
|
1793
1811
|
current = item;
|
|
1812
|
+
chainLength = 0;
|
|
1794
1813
|
}
|
|
1814
|
+
chainLength++;
|
|
1795
1815
|
prev = item;
|
|
1796
1816
|
}
|
|
1797
1817
|
newAssignments.push(current);
|
|
@@ -1986,6 +2006,22 @@ function isIndexedValueInStack(ctx, node) {
|
|
|
1986
2006
|
return node.t === 4 && ctx.stack.includes(node.i);
|
|
1987
2007
|
}
|
|
1988
2008
|
/**
|
|
2009
|
+
* Checks if the node, or any node inside it, is read from more than one
|
|
2010
|
+
* place. Such a node must not be created inside a deferred assignment,
|
|
2011
|
+
* because the places that read it may run before the assignment does.
|
|
2012
|
+
*/
|
|
2013
|
+
function hasMarkedNode(ctx, node) {
|
|
2014
|
+
if (Array.isArray(node)) {
|
|
2015
|
+
for (let i = 0, len = node.length; i < len; i++) if (hasMarkedNode(ctx, node[i])) return true;
|
|
2016
|
+
return false;
|
|
2017
|
+
}
|
|
2018
|
+
if (node == null || typeof node !== "object") return false;
|
|
2019
|
+
const current = node;
|
|
2020
|
+
if (current.t !== 4 && typeof current.i === "number" && isSerializerRefMarked(ctx, current.i)) return true;
|
|
2021
|
+
for (const key in current) if (hasMarkedNode(ctx, current[key])) return true;
|
|
2022
|
+
return false;
|
|
2023
|
+
}
|
|
2024
|
+
/**
|
|
1989
2025
|
* Produces an assignment expression. `id` generates a reference
|
|
1990
2026
|
* parameter (through `getRefParam`) and has the option to
|
|
1991
2027
|
* return the reference parameter directly or assign a value to
|
|
@@ -2195,7 +2231,8 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
|
|
|
2195
2231
|
createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
|
|
2196
2232
|
return "";
|
|
2197
2233
|
}
|
|
2198
|
-
if (val.t !== 4 && val.i != null &&
|
|
2234
|
+
if (val.t !== 4 && val.i != null && hasMarkedNode(base, val)) {
|
|
2235
|
+
markSerializerRef(base, val.i);
|
|
2199
2236
|
const serialized = "(" + serialize$1(ctx, val) + ",[" + sentinel + "," + sentinel + "])";
|
|
2200
2237
|
createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
|
|
2201
2238
|
createDeleteAssignment(ctx, id, sentinel);
|
|
@@ -2210,7 +2247,8 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
|
|
|
2210
2247
|
if (isIndexedValueInStack(base, val)) {
|
|
2211
2248
|
const valueRef = getRefParam(ctx, val.i);
|
|
2212
2249
|
markSerializerRef(base, id);
|
|
2213
|
-
if (key.t !== 4 && key.i != null &&
|
|
2250
|
+
if (key.t !== 4 && key.i != null && hasMarkedNode(base, key)) {
|
|
2251
|
+
markSerializerRef(base, key.i);
|
|
2214
2252
|
const serialized = "(" + serialize$1(ctx, key) + ",[" + sentinel + "," + sentinel + "])";
|
|
2215
2253
|
createSetAssignment(ctx, id, getRefParam(ctx, key.i), valueRef);
|
|
2216
2254
|
createDeleteAssignment(ctx, id, sentinel);
|
|
@@ -2606,13 +2644,14 @@ function parseAggregateError(ctx, depth, id, current) {
|
|
|
2606
2644
|
return createAggregateErrorNode(id, current, options ? parseProperties(ctx, depth, options) : void 0);
|
|
2607
2645
|
}
|
|
2608
2646
|
function parseMap(ctx, depth, id, current) {
|
|
2647
|
+
const sentinel = parseMapSentinel(ctx.base);
|
|
2609
2648
|
const keyNodes = [];
|
|
2610
2649
|
const valueNodes = [];
|
|
2611
2650
|
for (const [key, value] of current.entries()) {
|
|
2612
2651
|
keyNodes.push(parseSOS(ctx, depth, key));
|
|
2613
2652
|
valueNodes.push(parseSOS(ctx, depth, value));
|
|
2614
2653
|
}
|
|
2615
|
-
return createMapNode(
|
|
2654
|
+
return createMapNode(id, sentinel, keyNodes, valueNodes);
|
|
2616
2655
|
}
|
|
2617
2656
|
function parseSet(ctx, depth, id, current) {
|
|
2618
2657
|
const items = [];
|
package/dist/index.js
CHANGED
|
@@ -387,6 +387,29 @@ function getObjectFlag(obj) {
|
|
|
387
387
|
return 1;
|
|
388
388
|
}
|
|
389
389
|
//#endregion
|
|
390
|
+
//#region src/core/utils/typed-array.ts
|
|
391
|
+
function getTypedArrayConstructor(name) {
|
|
392
|
+
switch (name) {
|
|
393
|
+
case "Int8Array": return Int8Array;
|
|
394
|
+
case "Int16Array": return Int16Array;
|
|
395
|
+
case "Int32Array": return Int32Array;
|
|
396
|
+
case "Uint8Array": return Uint8Array;
|
|
397
|
+
case "Uint16Array": return Uint16Array;
|
|
398
|
+
case "Uint32Array": return Uint32Array;
|
|
399
|
+
case "Uint8ClampedArray": return Uint8ClampedArray;
|
|
400
|
+
case "Float32Array": return Float32Array;
|
|
401
|
+
case "Float64Array": return Float64Array;
|
|
402
|
+
case "BigInt64Array": return BigInt64Array;
|
|
403
|
+
case "BigUint64Array": return BigUint64Array;
|
|
404
|
+
default: throw new SerovalUnknownTypedArrayError(name);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
let typedArrayNameGetter;
|
|
408
|
+
function getTypedArrayName(value) {
|
|
409
|
+
if (!typedArrayNameGetter) typedArrayNameGetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Int8Array.prototype), Symbol.toStringTag).get;
|
|
410
|
+
return typedArrayNameGetter.call(value);
|
|
411
|
+
}
|
|
412
|
+
//#endregion
|
|
390
413
|
//#region src/core/base-primitives.ts
|
|
391
414
|
function createNumberNode(value) {
|
|
392
415
|
switch (value) {
|
|
@@ -434,11 +457,11 @@ function createBoxedNode(id, boxed) {
|
|
|
434
457
|
const MAX_TYPED_ARRAY_LENGTH = 1e6;
|
|
435
458
|
function createTypedArrayNode(id, current, buffer) {
|
|
436
459
|
if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
437
|
-
return createSerovalNode(15, id, void 0, current
|
|
460
|
+
return createSerovalNode(15, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
|
|
438
461
|
}
|
|
439
462
|
function createBigIntTypedArrayNode(id, current, buffer) {
|
|
440
463
|
if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
441
|
-
return createSerovalNode(16, id, void 0, current
|
|
464
|
+
return createSerovalNode(16, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
|
|
442
465
|
}
|
|
443
466
|
function createDataViewNode(id, current, buffer) {
|
|
444
467
|
if (current.byteLength > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
|
|
@@ -972,11 +995,18 @@ function parseAsyncIteratorFactory(ctx) {
|
|
|
972
995
|
function createObjectNode(id, current, empty, record) {
|
|
973
996
|
return createSerovalNode(empty ? 11 : 10, id, void 0, void 0, void 0, record, void 0, void 0, void 0, void 0, getObjectFlag(current), void 0);
|
|
974
997
|
}
|
|
975
|
-
|
|
998
|
+
/**
|
|
999
|
+
* Gets the sentinel node for a Map. Call it before parsing the entries, so
|
|
1000
|
+
* that an outer Map declares the sentinel before any Map inside it uses it.
|
|
1001
|
+
*/
|
|
1002
|
+
function parseMapSentinel(ctx) {
|
|
1003
|
+
return parseSpecialReference(ctx, 0);
|
|
1004
|
+
}
|
|
1005
|
+
function createMapNode(id, sentinel, k, v) {
|
|
976
1006
|
return createSerovalNode(8, id, void 0, void 0, void 0, void 0, {
|
|
977
1007
|
k,
|
|
978
1008
|
v
|
|
979
|
-
}, void 0,
|
|
1009
|
+
}, void 0, sentinel, void 0, void 0, void 0);
|
|
980
1010
|
}
|
|
981
1011
|
function createPromiseConstructorNode(ctx, id, resolver) {
|
|
982
1012
|
return createSerovalNode(22, id, resolver, void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 1), void 0, void 0, void 0);
|
|
@@ -984,8 +1014,7 @@ function createPromiseConstructorNode(ctx, id, resolver) {
|
|
|
984
1014
|
function getArrayBufferView(ctx, current) {
|
|
985
1015
|
if (!ctx.compactArrayBufferViews) return current;
|
|
986
1016
|
const buffer = new Uint8Array(current.buffer, current.byteOffset, current.byteLength).slice().buffer;
|
|
987
|
-
|
|
988
|
-
return new Constructor(buffer);
|
|
1017
|
+
return new (current instanceof DataView ? DataView : getTypedArrayConstructor(getTypedArrayName(current)))(buffer);
|
|
989
1018
|
}
|
|
990
1019
|
function encodeArrayBuffer(current) {
|
|
991
1020
|
if (typeof Buffer !== "undefined") return Buffer.from(current).toString("base64");
|
|
@@ -1080,13 +1109,14 @@ async function parseAggregateError$1(ctx, depth, id, current) {
|
|
|
1080
1109
|
return createAggregateErrorNode(id, current, options ? await parseProperties$1(ctx, depth, options) : void 0);
|
|
1081
1110
|
}
|
|
1082
1111
|
async function parseMap$1(ctx, depth, id, current) {
|
|
1112
|
+
const sentinel = parseMapSentinel(ctx.base);
|
|
1083
1113
|
const keyNodes = [];
|
|
1084
1114
|
const valueNodes = [];
|
|
1085
1115
|
for (const [key, value] of current.entries()) {
|
|
1086
1116
|
keyNodes.push(await parseAsync(ctx, depth, key));
|
|
1087
1117
|
valueNodes.push(await parseAsync(ctx, depth, value));
|
|
1088
1118
|
}
|
|
1089
|
-
return createMapNode(
|
|
1119
|
+
return createMapNode(id, sentinel, keyNodes, valueNodes);
|
|
1090
1120
|
}
|
|
1091
1121
|
async function parseSet$1(ctx, depth, id, current) {
|
|
1092
1122
|
const items = [];
|
|
@@ -1271,24 +1301,6 @@ function resolvePlugins(plugins) {
|
|
|
1271
1301
|
}
|
|
1272
1302
|
}
|
|
1273
1303
|
//#endregion
|
|
1274
|
-
//#region src/core/utils/typed-array.ts
|
|
1275
|
-
function getTypedArrayConstructor(name) {
|
|
1276
|
-
switch (name) {
|
|
1277
|
-
case "Int8Array": return Int8Array;
|
|
1278
|
-
case "Int16Array": return Int16Array;
|
|
1279
|
-
case "Int32Array": return Int32Array;
|
|
1280
|
-
case "Uint8Array": return Uint8Array;
|
|
1281
|
-
case "Uint16Array": return Uint16Array;
|
|
1282
|
-
case "Uint32Array": return Uint32Array;
|
|
1283
|
-
case "Uint8ClampedArray": return Uint8ClampedArray;
|
|
1284
|
-
case "Float32Array": return Float32Array;
|
|
1285
|
-
case "Float64Array": return Float64Array;
|
|
1286
|
-
case "BigInt64Array": return BigInt64Array;
|
|
1287
|
-
case "BigUint64Array": return BigUint64Array;
|
|
1288
|
-
default: throw new SerovalUnknownTypedArrayError(name);
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
//#endregion
|
|
1292
1304
|
//#region src/core/utils/valid-properties.ts
|
|
1293
1305
|
function isValidKey(key) {
|
|
1294
1306
|
switch (key) {
|
|
@@ -1758,30 +1770,36 @@ function getAssignmentExpression(assignment) {
|
|
|
1758
1770
|
case 4: return "Object.defineProperty(" + assignment.s + ",\"__proto__\",{value:" + assignment.k + ",configurable:!0,enumerable:!0,writable:!0})";
|
|
1759
1771
|
}
|
|
1760
1772
|
}
|
|
1773
|
+
const MAX_ASSIGNMENT_CHAIN_LENGTH = 100;
|
|
1761
1774
|
function mergeAssignments(assignments) {
|
|
1762
1775
|
const newAssignments = [];
|
|
1763
1776
|
let current = assignments[0];
|
|
1777
|
+
let chainLength = 1;
|
|
1764
1778
|
for (let i = 1, len = assignments.length, item, prev = current; i < len; i++) {
|
|
1765
1779
|
item = assignments[i];
|
|
1766
|
-
if (
|
|
1780
|
+
if (chainLength === MAX_ASSIGNMENT_CHAIN_LENGTH) {
|
|
1781
|
+
newAssignments.push(current);
|
|
1782
|
+
current = item;
|
|
1783
|
+
chainLength = 0;
|
|
1784
|
+
} else if (item.t === 0 && prev.t === 0 && item.v === prev.v) current = {
|
|
1767
1785
|
t: 0,
|
|
1768
1786
|
s: item.s,
|
|
1769
1787
|
k: void 0,
|
|
1770
1788
|
v: getAssignmentExpression(current)
|
|
1771
1789
|
};
|
|
1772
|
-
else if (item.t === 2 && item.s === prev.s) current = {
|
|
1790
|
+
else if (item.t === 2 && prev.t === 2 && item.s === prev.s) current = {
|
|
1773
1791
|
t: 2,
|
|
1774
1792
|
s: getAssignmentExpression(current),
|
|
1775
1793
|
k: item.k,
|
|
1776
1794
|
v: item.v
|
|
1777
1795
|
};
|
|
1778
|
-
else if (item.t === 1 && item.s === prev.s) current = {
|
|
1796
|
+
else if (item.t === 1 && prev.t === 1 && item.s === prev.s) current = {
|
|
1779
1797
|
t: 1,
|
|
1780
1798
|
s: getAssignmentExpression(current),
|
|
1781
1799
|
k: void 0,
|
|
1782
1800
|
v: item.v
|
|
1783
1801
|
};
|
|
1784
|
-
else if (item.t === 3 && item.s === prev.s) current = {
|
|
1802
|
+
else if (item.t === 3 && prev.t === 2 && item.s === prev.s) current = {
|
|
1785
1803
|
t: 3,
|
|
1786
1804
|
s: getAssignmentExpression(current),
|
|
1787
1805
|
k: item.k,
|
|
@@ -1790,7 +1808,9 @@ function mergeAssignments(assignments) {
|
|
|
1790
1808
|
else {
|
|
1791
1809
|
newAssignments.push(current);
|
|
1792
1810
|
current = item;
|
|
1811
|
+
chainLength = 0;
|
|
1793
1812
|
}
|
|
1813
|
+
chainLength++;
|
|
1794
1814
|
prev = item;
|
|
1795
1815
|
}
|
|
1796
1816
|
newAssignments.push(current);
|
|
@@ -1985,6 +2005,22 @@ function isIndexedValueInStack(ctx, node) {
|
|
|
1985
2005
|
return node.t === 4 && ctx.stack.includes(node.i);
|
|
1986
2006
|
}
|
|
1987
2007
|
/**
|
|
2008
|
+
* Checks if the node, or any node inside it, is read from more than one
|
|
2009
|
+
* place. Such a node must not be created inside a deferred assignment,
|
|
2010
|
+
* because the places that read it may run before the assignment does.
|
|
2011
|
+
*/
|
|
2012
|
+
function hasMarkedNode(ctx, node) {
|
|
2013
|
+
if (Array.isArray(node)) {
|
|
2014
|
+
for (let i = 0, len = node.length; i < len; i++) if (hasMarkedNode(ctx, node[i])) return true;
|
|
2015
|
+
return false;
|
|
2016
|
+
}
|
|
2017
|
+
if (node == null || typeof node !== "object") return false;
|
|
2018
|
+
const current = node;
|
|
2019
|
+
if (current.t !== 4 && typeof current.i === "number" && isSerializerRefMarked(ctx, current.i)) return true;
|
|
2020
|
+
for (const key in current) if (hasMarkedNode(ctx, current[key])) return true;
|
|
2021
|
+
return false;
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
1988
2024
|
* Produces an assignment expression. `id` generates a reference
|
|
1989
2025
|
* parameter (through `getRefParam`) and has the option to
|
|
1990
2026
|
* return the reference parameter directly or assign a value to
|
|
@@ -2194,7 +2230,8 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
|
|
|
2194
2230
|
createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
|
|
2195
2231
|
return "";
|
|
2196
2232
|
}
|
|
2197
|
-
if (val.t !== 4 && val.i != null &&
|
|
2233
|
+
if (val.t !== 4 && val.i != null && hasMarkedNode(base, val)) {
|
|
2234
|
+
markSerializerRef(base, val.i);
|
|
2198
2235
|
const serialized = "(" + serialize$1(ctx, val) + ",[" + sentinel + "," + sentinel + "])";
|
|
2199
2236
|
createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
|
|
2200
2237
|
createDeleteAssignment(ctx, id, sentinel);
|
|
@@ -2209,7 +2246,8 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
|
|
|
2209
2246
|
if (isIndexedValueInStack(base, val)) {
|
|
2210
2247
|
const valueRef = getRefParam(ctx, val.i);
|
|
2211
2248
|
markSerializerRef(base, id);
|
|
2212
|
-
if (key.t !== 4 && key.i != null &&
|
|
2249
|
+
if (key.t !== 4 && key.i != null && hasMarkedNode(base, key)) {
|
|
2250
|
+
markSerializerRef(base, key.i);
|
|
2213
2251
|
const serialized = "(" + serialize$1(ctx, key) + ",[" + sentinel + "," + sentinel + "])";
|
|
2214
2252
|
createSetAssignment(ctx, id, getRefParam(ctx, key.i), valueRef);
|
|
2215
2253
|
createDeleteAssignment(ctx, id, sentinel);
|
|
@@ -2605,13 +2643,14 @@ function parseAggregateError(ctx, depth, id, current) {
|
|
|
2605
2643
|
return createAggregateErrorNode(id, current, options ? parseProperties(ctx, depth, options) : void 0);
|
|
2606
2644
|
}
|
|
2607
2645
|
function parseMap(ctx, depth, id, current) {
|
|
2646
|
+
const sentinel = parseMapSentinel(ctx.base);
|
|
2608
2647
|
const keyNodes = [];
|
|
2609
2648
|
const valueNodes = [];
|
|
2610
2649
|
for (const [key, value] of current.entries()) {
|
|
2611
2650
|
keyNodes.push(parseSOS(ctx, depth, key));
|
|
2612
2651
|
valueNodes.push(parseSOS(ctx, depth, value));
|
|
2613
2652
|
}
|
|
2614
|
-
return createMapNode(
|
|
2653
|
+
return createMapNode(id, sentinel, keyNodes, valueNodes);
|
|
2615
2654
|
}
|
|
2616
2655
|
function parseSet(ctx, depth, id, current) {
|
|
2617
2656
|
const items = [];
|