@sentropic/h2a 0.97.0 → 0.97.2
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/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +1 -1
- package/.mcp.json +1 -1
- package/dist/cli-command-map.d.ts.map +1 -1
- package/dist/cli-command-map.js +1 -0
- package/dist/cli-command-map.js.map +1 -1
- package/dist/cli-contract.d.ts.map +1 -1
- package/dist/cli-contract.js +11 -3
- package/dist/cli-contract.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +115 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +1 -0
- package/dist/mcp.js.map +1 -1
- package/dist/runtime/identity/index.d.ts +1 -1
- package/dist/runtime/identity/index.d.ts.map +1 -1
- package/dist/runtime/identity/index.js +1 -1
- package/dist/runtime/identity/index.js.map +1 -1
- package/dist/runtime/identity/live.d.ts +4 -0
- package/dist/runtime/identity/live.d.ts.map +1 -1
- package/dist/runtime/identity/live.js +3 -3
- package/dist/runtime/identity/live.js.map +1 -1
- package/dist/runtime/mcp/agent-launch.d.ts +2 -0
- package/dist/runtime/mcp/agent-launch.d.ts.map +1 -1
- package/dist/runtime/mcp/agent-launch.js +11 -0
- package/dist/runtime/mcp/agent-launch.js.map +1 -1
- package/dist/runtime/mcp/handlers.d.ts +5 -0
- package/dist/runtime/mcp/handlers.d.ts.map +1 -1
- package/dist/runtime/mcp/handlers.js +19 -0
- package/dist/runtime/mcp/handlers.js.map +1 -1
- package/dist/runtime/mcp/server.d.ts +3 -0
- package/dist/runtime/mcp/server.d.ts.map +1 -1
- package/dist/runtime/mcp/server.js +3 -1
- package/dist/runtime/mcp/server.js.map +1 -1
- package/dist/runtime/mcp/stdio.d.ts +3 -0
- package/dist/runtime/mcp/stdio.d.ts.map +1 -1
- package/dist/runtime/mcp/stdio.js +1 -0
- package/dist/runtime/mcp/stdio.js.map +1 -1
- package/dist/runtime/mcp/tools.d.ts.map +1 -1
- package/dist/runtime/mcp/tools.js +17 -0
- package/dist/runtime/mcp/tools.js.map +1 -1
- package/dist/runtime/send.d.ts +40 -0
- package/dist/runtime/send.d.ts.map +1 -0
- package/dist/runtime/send.js +108 -0
- package/dist/runtime/send.js.map +1 -0
- package/focus-app/client/_app/immutable/chunks/BgBtu3IQ.js +2 -0
- package/focus-app/client/_app/immutable/chunks/BgBtu3IQ.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/BgBtu3IQ.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/{app.D1IjBbSs.js → app.D_yfk55R.js} +2 -2
- package/focus-app/client/_app/immutable/entry/app.D_yfk55R.js.br +0 -0
- package/focus-app/client/_app/immutable/entry/app.D_yfk55R.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/start.CoQWYNTs.js +1 -0
- package/focus-app/client/_app/immutable/entry/start.CoQWYNTs.js.br +2 -0
- package/focus-app/client/_app/immutable/entry/start.CoQWYNTs.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/{1.CcZFi3uA.js → 1.Jo1uWTw0.js} +1 -1
- package/focus-app/client/_app/immutable/nodes/1.Jo1uWTw0.js.br +4 -0
- package/focus-app/client/_app/immutable/nodes/1.Jo1uWTw0.js.gz +0 -0
- package/focus-app/client/_app/version.json +1 -1
- package/focus-app/client/_app/version.json.br +0 -0
- package/focus-app/client/_app/version.json.gz +0 -0
- package/focus-app/h2a-focus.json +61 -61
- package/focus-app/handler.js +8 -8
- package/focus-app/index.js +8 -8
- package/focus-app/server/chunks/chunks/{AppShell.js-BDEpw0ai.js → AppShell.js-BoWxjmfr.js} +2 -2
- package/focus-app/server/chunks/chunks/{AppShell.js-BDEpw0ai.js.map → AppShell.js-BoWxjmfr.js.map} +1 -1
- package/focus-app/server/chunks/chunks/{exports.js-BZfNcFtJ.js → exports.js-D45A8dcc.js} +3 -3
- package/focus-app/server/chunks/chunks/{exports.js-BZfNcFtJ.js.map → exports.js-D45A8dcc.js.map} +1 -1
- package/focus-app/server/chunks/chunks/{index.js--xmWq8-W.js → index.js-e3L5MwfB.js} +2 -2
- package/focus-app/server/chunks/chunks/{index.js--xmWq8-W.js.map → index.js-e3L5MwfB.js.map} +1 -1
- package/focus-app/server/chunks/chunks/{internal.js-o4rWftwV.js → internal.js-DAV-A6NO.js} +3 -3
- package/focus-app/server/chunks/chunks/{internal.js-o4rWftwV.js.map → internal.js-DAV-A6NO.js.map} +1 -1
- package/focus-app/server/chunks/chunks/{root.js-ve7Sv8eD.js → root.js-CEypm32A.js} +2 -2
- package/focus-app/server/chunks/chunks/{root.js-ve7Sv8eD.js.map → root.js-CEypm32A.js.map} +1 -1
- package/focus-app/server/chunks/chunks/{utils.js-h3jETFNR.js → utils.js-Bzpr6vQU.js} +406 -141
- package/focus-app/server/chunks/chunks/utils.js-Bzpr6vQU.js.map +1 -0
- package/focus-app/server/chunks/entries/endpoints/api/actions/launch/{_server.ts.js-DVeNoSe-.js → _server.ts.js-Cah_Ivgw.js} +2 -2
- package/focus-app/server/chunks/entries/endpoints/api/actions/launch/{_server.ts.js-DVeNoSe-.js.map → _server.ts.js-Cah_Ivgw.js.map} +1 -1
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/{_server.ts.js-CLfZIM0I.js → _server.ts.js-DW5wvcgH.js} +2 -2
- package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/{_server.ts.js-CLfZIM0I.js.map → _server.ts.js-DW5wvcgH.js.map} +1 -1
- package/focus-app/server/chunks/entries/endpoints/api/dossiers/agent-memory/include/{_server.ts.js-DNQwbxOr.js → _server.ts.js-C2jIx8Jr.js} +2 -2
- package/focus-app/server/chunks/entries/endpoints/api/dossiers/agent-memory/include/{_server.ts.js-DNQwbxOr.js.map → _server.ts.js-C2jIx8Jr.js.map} +1 -1
- package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/{_server.ts.js-BqneXTTN.js → _server.ts.js-BkAMLcHu.js} +2 -2
- package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/{_server.ts.js-BqneXTTN.js.map → _server.ts.js-BkAMLcHu.js.map} +1 -1
- package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-VpNJnNVG.js → error.svelte.js-BWuS92Wk.js} +5 -5
- package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-VpNJnNVG.js.map → error.svelte.js-BWuS92Wk.js.map} +1 -1
- package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-D_Rgb6oH.js → _layout.svelte.js-CKspI0Bw.js} +3 -3
- package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-D_Rgb6oH.js.map → _layout.svelte.js-CKspI0Bw.js.map} +1 -1
- package/focus-app/server/chunks/entries/pages/{_page.svelte.js-2a7ZxK1n.js → _page.svelte.js-B8EWZmZj.js} +4 -4
- package/focus-app/server/chunks/entries/pages/{_page.svelte.js-2a7ZxK1n.js.map → _page.svelte.js-B8EWZmZj.js.map} +1 -1
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/{_page.svelte.js-Bl_4XjaL.js → _page.svelte.js-BZvcKeya.js} +4 -4
- package/focus-app/server/chunks/entries/pages/dossier/agent-memory/{_page.svelte.js-Bl_4XjaL.js.map → _page.svelte.js-BZvcKeya.js.map} +1 -1
- package/focus-app/server/chunks/{handler-B897YV9_.js → handler-BCBpURX0.js} +4 -4
- package/focus-app/server/chunks/{handler-B897YV9_.js.map → handler-BCBpURX0.js.map} +1 -1
- package/focus-app/server/chunks/{index.js-BkPsDsTn.js → index.js-CZWB6FqQ.js} +5 -5
- package/focus-app/server/chunks/{index.js-BkPsDsTn.js.map → index.js-CZWB6FqQ.js.map} +1 -1
- package/focus-app/server/chunks/{manifest.js-DZ6J-aM3.js → manifest.js-C2CyTiUe.js} +10 -10
- package/focus-app/server/chunks/{manifest.js-DZ6J-aM3.js.map → manifest.js-C2CyTiUe.js.map} +1 -1
- package/focus-app/server/chunks/nodes/{0.js-tlwNtUnO.js → 0.js-Cp9RMJ1x.js} +2 -2
- package/focus-app/server/chunks/nodes/{0.js-tlwNtUnO.js.map → 0.js-Cp9RMJ1x.js.map} +1 -1
- package/focus-app/server/chunks/nodes/1.js-DMWmTj0d.js +9 -0
- package/focus-app/server/chunks/nodes/{1.js-mLYMqMM3.js.map → 1.js-DMWmTj0d.js.map} +1 -1
- package/focus-app/server/chunks/nodes/{2.js-C_y8BeMm.js → 2.js-Dv8Q6LQc.js} +2 -2
- package/focus-app/server/chunks/nodes/{2.js-C_y8BeMm.js.map → 2.js-Dv8Q6LQc.js.map} +1 -1
- package/focus-app/server/chunks/nodes/{3.js-13r5MUAa.js → 3.js-DJH-zOae.js} +2 -2
- package/focus-app/server/chunks/nodes/{3.js-13r5MUAa.js.map → 3.js-DJH-zOae.js.map} +1 -1
- package/package.json +3 -3
- package/skills/h2a/SKILL.md +11 -33
- package/focus-app/client/_app/immutable/chunks/DAAR3e-c.js +0 -2
- package/focus-app/client/_app/immutable/chunks/DAAR3e-c.js.br +0 -0
- package/focus-app/client/_app/immutable/chunks/DAAR3e-c.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/app.D1IjBbSs.js.br +0 -0
- package/focus-app/client/_app/immutable/entry/app.D1IjBbSs.js.gz +0 -0
- package/focus-app/client/_app/immutable/entry/start.DHa1k4dG.js +0 -1
- package/focus-app/client/_app/immutable/entry/start.DHa1k4dG.js.br +0 -2
- package/focus-app/client/_app/immutable/entry/start.DHa1k4dG.js.gz +0 -0
- package/focus-app/client/_app/immutable/nodes/1.CcZFi3uA.js.br +0 -0
- package/focus-app/client/_app/immutable/nodes/1.CcZFi3uA.js.gz +0 -0
- package/focus-app/server/chunks/chunks/utils.js-h3jETFNR.js.map +0 -1
- package/focus-app/server/chunks/nodes/1.js-mLYMqMM3.js +0 -9
|
@@ -493,17 +493,25 @@ function is_valid_array_index_string(s) {
|
|
|
493
493
|
}
|
|
494
494
|
|
|
495
495
|
/**
|
|
496
|
-
*
|
|
497
|
-
* @param {
|
|
496
|
+
* Returns the length of the leading run of valid array indices in `keys`.
|
|
497
|
+
* @param {readonly string[]} keys
|
|
498
498
|
*/
|
|
499
|
-
function
|
|
500
|
-
const keys = Object.keys(array);
|
|
499
|
+
function array_index_cut(keys) {
|
|
501
500
|
for (var i = keys.length - 1; i >= 0; i--) {
|
|
502
501
|
if (is_valid_array_index_string(keys[i])) {
|
|
503
502
|
break;
|
|
504
503
|
}
|
|
505
504
|
}
|
|
506
|
-
|
|
505
|
+
return i + 1;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Finds the populated indices of an array.
|
|
510
|
+
* @param {unknown[]} array
|
|
511
|
+
*/
|
|
512
|
+
function valid_array_indices(array) {
|
|
513
|
+
const keys = Object.keys(array);
|
|
514
|
+
keys.length = array_index_cut(keys);
|
|
507
515
|
return keys;
|
|
508
516
|
}
|
|
509
517
|
|
|
@@ -576,6 +584,7 @@ function uneval(value, replacer) {
|
|
|
576
584
|
case 'Map':
|
|
577
585
|
for (const [key, value] of thing) {
|
|
578
586
|
keys.push(`.get(${is_primitive(key) ? stringify_primitive$1(key) : '...'})`);
|
|
587
|
+
walk(key);
|
|
579
588
|
walk(value);
|
|
580
589
|
keys.pop();
|
|
581
590
|
}
|
|
@@ -757,9 +766,7 @@ function uneval(value, replacer) {
|
|
|
757
766
|
return `Object.assign(Array(${thing.length}),{${entries}})`;
|
|
758
767
|
}
|
|
759
768
|
|
|
760
|
-
// Re-process this index as a hole in the array literal
|
|
761
769
|
has_holes = true;
|
|
762
|
-
i -= 1;
|
|
763
770
|
}
|
|
764
771
|
// else: already decided on array literal, hole is just an empty slot
|
|
765
772
|
// (the comma separator is all we need — no content for this position)
|
|
@@ -788,8 +795,7 @@ function uneval(value, replacer) {
|
|
|
788
795
|
let str = `new ${type}`;
|
|
789
796
|
|
|
790
797
|
if (!names.has(thing.buffer)) {
|
|
791
|
-
|
|
792
|
-
str += `([${array}])`;
|
|
798
|
+
str += `([${stringify_typed_array_elements(type, thing.buffer)}])`;
|
|
793
799
|
} else {
|
|
794
800
|
str += `(${stringify(thing.buffer)})`;
|
|
795
801
|
}
|
|
@@ -815,7 +821,7 @@ function uneval(value, replacer) {
|
|
|
815
821
|
|
|
816
822
|
// handle subviews
|
|
817
823
|
if (thing.byteLength !== thing.buffer.byteLength) {
|
|
818
|
-
str += `,${thing.
|
|
824
|
+
str += `,${thing.byteOffset},${thing.byteLength}`;
|
|
819
825
|
}
|
|
820
826
|
|
|
821
827
|
return str + ')';
|
|
@@ -860,6 +866,13 @@ function uneval(value, replacer) {
|
|
|
860
866
|
/** @type {string[]} */
|
|
861
867
|
const values = [];
|
|
862
868
|
|
|
869
|
+
// Reconstructions (e.g. `b = new Uint8Array(...)`) reassign a placeholder
|
|
870
|
+
// parameter. They must run before the `statements` that reference them,
|
|
871
|
+
// otherwise those statements capture the placeholder. They only depend on
|
|
872
|
+
// IIFE arguments (never on each other), so emitting them first is safe.
|
|
873
|
+
/** @type {string[]} */
|
|
874
|
+
const reconstructions = [];
|
|
875
|
+
|
|
863
876
|
names.forEach((name, thing) => {
|
|
864
877
|
params.push(name);
|
|
865
878
|
|
|
@@ -910,23 +923,23 @@ function uneval(value, replacer) {
|
|
|
910
923
|
});
|
|
911
924
|
break;
|
|
912
925
|
|
|
913
|
-
case 'Set':
|
|
926
|
+
case 'Set': {
|
|
914
927
|
values.push(`new Set`);
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
);
|
|
928
|
+
const adds = Array.from(thing).map((v) => `.add(${stringify(v)})`);
|
|
929
|
+
// An empty Set is fully built by `new Set`; a chained statement would
|
|
930
|
+
// otherwise be a dangling `name.`.
|
|
931
|
+
if (adds.length > 0) statements.push(name + adds.join(''));
|
|
920
932
|
break;
|
|
933
|
+
}
|
|
921
934
|
|
|
922
|
-
case 'Map':
|
|
935
|
+
case 'Map': {
|
|
923
936
|
values.push(`new Map`);
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
.map(([k, v]) => `set(${stringify(k)}, ${stringify(v)})`)
|
|
927
|
-
.join('.')}`
|
|
937
|
+
const sets = Array.from(thing).map(
|
|
938
|
+
([k, v]) => `.set(${stringify(k)}, ${stringify(v)})`
|
|
928
939
|
);
|
|
940
|
+
if (sets.length > 0) statements.push(name + sets.join(''));
|
|
929
941
|
break;
|
|
942
|
+
}
|
|
930
943
|
|
|
931
944
|
case 'Int8Array':
|
|
932
945
|
case 'Uint8Array':
|
|
@@ -943,8 +956,7 @@ function uneval(value, replacer) {
|
|
|
943
956
|
let str = `new ${type}`;
|
|
944
957
|
|
|
945
958
|
if (!names.has(thing.buffer)) {
|
|
946
|
-
|
|
947
|
-
str += `([${array}])`;
|
|
959
|
+
str += `([${stringify_typed_array_elements(type, thing.buffer)}])`;
|
|
948
960
|
} else {
|
|
949
961
|
str += `(${stringify(thing.buffer)})`;
|
|
950
962
|
}
|
|
@@ -957,7 +969,7 @@ function uneval(value, replacer) {
|
|
|
957
969
|
}
|
|
958
970
|
|
|
959
971
|
values.push(`{}`);
|
|
960
|
-
|
|
972
|
+
reconstructions.push(`${name}=${str}`);
|
|
961
973
|
break;
|
|
962
974
|
}
|
|
963
975
|
|
|
@@ -978,7 +990,7 @@ function uneval(value, replacer) {
|
|
|
978
990
|
str += ')';
|
|
979
991
|
|
|
980
992
|
values.push(`{}`);
|
|
981
|
-
|
|
993
|
+
reconstructions.push(`${name}=${str}`);
|
|
982
994
|
break;
|
|
983
995
|
}
|
|
984
996
|
|
|
@@ -986,6 +998,17 @@ function uneval(value, replacer) {
|
|
|
986
998
|
values.push(`new Uint8Array([${new Uint8Array(thing)}]).buffer`);
|
|
987
999
|
break;
|
|
988
1000
|
|
|
1001
|
+
case 'Temporal.Duration':
|
|
1002
|
+
case 'Temporal.Instant':
|
|
1003
|
+
case 'Temporal.PlainDate':
|
|
1004
|
+
case 'Temporal.PlainTime':
|
|
1005
|
+
case 'Temporal.PlainDateTime':
|
|
1006
|
+
case 'Temporal.PlainMonthDay':
|
|
1007
|
+
case 'Temporal.PlainYearMonth':
|
|
1008
|
+
case 'Temporal.ZonedDateTime':
|
|
1009
|
+
values.push(`${type}.from(${stringify_string(thing.toString())})`);
|
|
1010
|
+
break;
|
|
1011
|
+
|
|
989
1012
|
default:
|
|
990
1013
|
values.push(Object.getPrototypeOf(thing) === null ? 'Object.create(null)' : '{}');
|
|
991
1014
|
Object.keys(thing).forEach((key) => {
|
|
@@ -996,12 +1019,51 @@ function uneval(value, replacer) {
|
|
|
996
1019
|
|
|
997
1020
|
statements.push(`return ${str}`);
|
|
998
1021
|
|
|
999
|
-
|
|
1022
|
+
const body = [...reconstructions, ...statements].join(';');
|
|
1023
|
+
// A function may have at most 65535 parameters (and a call at most that
|
|
1024
|
+
// many arguments). For very large graphs, pass the hoisted values as a
|
|
1025
|
+
// single array argument and destructure them into the placeholder names,
|
|
1026
|
+
// so the emitted code stays within the engine limit (#93).
|
|
1027
|
+
if (params.length > 65534) {
|
|
1028
|
+
return `(function(){var[${params.join(',')}]=arguments[0];${body}}([${values.join(',')}]))`;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
return `(function(${params.join(',')}){${body}}(${values.join(',')}))`;
|
|
1000
1032
|
} else {
|
|
1001
1033
|
return str;
|
|
1002
1034
|
}
|
|
1003
1035
|
}
|
|
1004
1036
|
|
|
1037
|
+
/**
|
|
1038
|
+
* Serialize the elements of `buffer`, read as `type`, as a comma-separated list.
|
|
1039
|
+
* The view is created from `type` rather than from the serialized value's own
|
|
1040
|
+
* constructor, which may be a subclass like Node's `Buffer` whose `toString`
|
|
1041
|
+
* decodes the bytes instead of listing them.
|
|
1042
|
+
* `BigInt64Array`/`BigUint64Array` elements are bigints and must be written
|
|
1043
|
+
* with an `n` suffix, otherwise the emitted `new BigInt64Array([...])` throws.
|
|
1044
|
+
* @param {string} type
|
|
1045
|
+
* @param {ArrayBufferLike} buffer
|
|
1046
|
+
*/
|
|
1047
|
+
function stringify_typed_array_elements(type, buffer) {
|
|
1048
|
+
const array = new (/** @type {any} */ (globalThis)[type])(buffer);
|
|
1049
|
+
|
|
1050
|
+
if (type === 'BigInt64Array' || type === 'BigUint64Array') {
|
|
1051
|
+
return Array.from(array, (element) => `${element}n`).join(',');
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// Float arrays can hold `-0`, which `toString()` collapses to `"0"`, silently
|
|
1055
|
+
// losing the sign on round-trip. Emit `-0` explicitly for those elements.
|
|
1056
|
+
if (
|
|
1057
|
+
array instanceof Float32Array ||
|
|
1058
|
+
array instanceof Float64Array ||
|
|
1059
|
+
(typeof Float16Array !== 'undefined' && array instanceof Float16Array)
|
|
1060
|
+
) {
|
|
1061
|
+
return Array.from(array, (element) => (Object.is(element, -0) ? '-0' : `${element}`)).join(',');
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
return array.toString();
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1005
1067
|
/** @param {number} num */
|
|
1006
1068
|
function get_name(num) {
|
|
1007
1069
|
let name = '';
|
|
@@ -1109,12 +1171,191 @@ const buffer = typeof process === 'object' && process.versions?.node !== undefin
|
|
|
1109
1171
|
const encode64 = native ? encode_native : buffer ? encode_buffer : encode_legacy;
|
|
1110
1172
|
const decode64 = native ? decode_native : buffer ? decode_buffer : decode_legacy;
|
|
1111
1173
|
|
|
1174
|
+
/**
|
|
1175
|
+
* Merges caller-provided operation overrides over the defaults. Iterating the
|
|
1176
|
+
* default keys (rather than the override's own keys) means nullish members
|
|
1177
|
+
* fall back to the default, and inherited members — e.g. from a class
|
|
1178
|
+
* instance — are picked up.
|
|
1179
|
+
*
|
|
1180
|
+
* @template {Record<string, any>} T
|
|
1181
|
+
* @param {T} defaults
|
|
1182
|
+
* @param {Partial<T> | undefined} overrides
|
|
1183
|
+
* @returns {T}
|
|
1184
|
+
*/
|
|
1185
|
+
function merge_operations(defaults, overrides) {
|
|
1186
|
+
return defaults;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
/** @type {{ kind: 'not-plain' }} */
|
|
1190
|
+
const NOT_PLAIN = Object.freeze({ kind: 'not-plain' });
|
|
1191
|
+
|
|
1192
|
+
/** @type {{ kind: 'symbol-keys' }} */
|
|
1193
|
+
const SYMBOL_KEYS = Object.freeze({ kind: 'symbol-keys' });
|
|
1194
|
+
|
|
1195
|
+
/**
|
|
1196
|
+
* The default implementations of every introspection/extraction operation
|
|
1197
|
+
* `stringify` performs on the value being serialized. Each one uses native
|
|
1198
|
+
* JavaScript semantics (property access, iteration, prototype methods, etc).
|
|
1199
|
+
*
|
|
1200
|
+
* Pass overrides via the `operations` option of `stringify`/`stringifyAsync`
|
|
1201
|
+
* to customize how values are inspected — e.g. to serialize values without
|
|
1202
|
+
* triggering getters, proxy traps, or patched prototype methods, or to
|
|
1203
|
+
* serialize values that live in a different JavaScript runtime (a `node:vm`
|
|
1204
|
+
* context, a WASM-hosted engine, a remote process) through handle objects.
|
|
1205
|
+
*
|
|
1206
|
+
* The object is frozen — it is shared by every `stringify` call that does
|
|
1207
|
+
* not override a given operation.
|
|
1208
|
+
*
|
|
1209
|
+
*/
|
|
1210
|
+
/** @type {import('./types.js').DefaultStringifyOperations} */
|
|
1211
|
+
const stringify_operations = {
|
|
1212
|
+
identify: (value) => value,
|
|
1213
|
+
|
|
1214
|
+
typeOf: (value) => (value === null ? 'null' : typeof value),
|
|
1215
|
+
|
|
1216
|
+
toPrimitive: (value) => value,
|
|
1217
|
+
|
|
1218
|
+
tagOf: (value) => get_type(value),
|
|
1219
|
+
|
|
1220
|
+
isThenable: (value) => typeof value.then === 'function',
|
|
1221
|
+
|
|
1222
|
+
toPromise: (thenable) => Promise.resolve(thenable),
|
|
1223
|
+
|
|
1224
|
+
unbox: (boxed) => boxed.valueOf(),
|
|
1225
|
+
|
|
1226
|
+
toISOString: (date) => (isNaN(date.getDate()) ? '' : date.toISOString()),
|
|
1227
|
+
|
|
1228
|
+
toStringValue: (value) => value.toString(),
|
|
1229
|
+
|
|
1230
|
+
regExpInfo: (regexp) => ({ source: regexp.source, flags: regexp.flags }),
|
|
1231
|
+
|
|
1232
|
+
valuesOf: (set) => set,
|
|
1233
|
+
|
|
1234
|
+
entriesOf: (map) => map,
|
|
1235
|
+
|
|
1236
|
+
viewInfo: (view) => ({
|
|
1237
|
+
buffer: view.buffer,
|
|
1238
|
+
byteOffset: view.byteOffset,
|
|
1239
|
+
byteLength: view.byteLength,
|
|
1240
|
+
length: view.length,
|
|
1241
|
+
bufferByteLength: view.buffer.byteLength
|
|
1242
|
+
}),
|
|
1243
|
+
|
|
1244
|
+
toArrayBuffer: (buffer) => buffer,
|
|
1245
|
+
|
|
1246
|
+
lengthOf: (array) => array.length,
|
|
1247
|
+
|
|
1248
|
+
hasOwn: (value, key) => Object.hasOwn(value, key),
|
|
1249
|
+
|
|
1250
|
+
indicesOf: (array) => valid_array_indices(array),
|
|
1251
|
+
|
|
1252
|
+
shapeOf: (value) => {
|
|
1253
|
+
if (!is_plain_object(value)) return NOT_PLAIN;
|
|
1254
|
+
if (enumerable_symbols(value).length > 0) return SYMBOL_KEYS;
|
|
1255
|
+
|
|
1256
|
+
return {
|
|
1257
|
+
kind: Object.getPrototypeOf(value) === null ? 'null-proto' : 'plain',
|
|
1258
|
+
keys: Object.keys(value)
|
|
1259
|
+
};
|
|
1260
|
+
},
|
|
1261
|
+
|
|
1262
|
+
get: (value, key) => value[key]
|
|
1263
|
+
};
|
|
1264
|
+
|
|
1265
|
+
const default_stringify_operations = Object.freeze(stringify_operations);
|
|
1266
|
+
|
|
1267
|
+
/**
|
|
1268
|
+
* The default implementations of every construction operation `parse` and
|
|
1269
|
+
* `unflatten` perform while reviving a value. Each one uses native
|
|
1270
|
+
* JavaScript semantics (built-in constructors, property assignment, etc).
|
|
1271
|
+
*
|
|
1272
|
+
* Pass overrides via the `operations` option of `parse`/`unflatten` to
|
|
1273
|
+
* customize how values are built — e.g. to construct them from the
|
|
1274
|
+
* intrinsics of a different realm (a `node:vm` context), or to build up
|
|
1275
|
+
* values inside another JavaScript runtime (a WASM-hosted engine, a remote
|
|
1276
|
+
* process) through handle objects.
|
|
1277
|
+
*
|
|
1278
|
+
* The object is frozen — it is shared by every `parse` call that does not
|
|
1279
|
+
* override a given operation.
|
|
1280
|
+
*
|
|
1281
|
+
*/
|
|
1282
|
+
/** @type {import('./types.js').DefaultParseOperations} */
|
|
1283
|
+
const parse_operations = {
|
|
1284
|
+
fromPrimitive: (primitive) => primitive,
|
|
1285
|
+
|
|
1286
|
+
fromISOString: (iso) => new Date(iso),
|
|
1287
|
+
|
|
1288
|
+
fromStringValue: (tag, text) => {
|
|
1289
|
+
if (tag === 'URL') return new URL(text);
|
|
1290
|
+
if (tag === 'URLSearchParams') return new URLSearchParams(text);
|
|
1291
|
+
// 'Temporal.Instant', 'Temporal.PlainDate', ...
|
|
1292
|
+
// @ts-expect-error TS doesn't know about Temporal yet
|
|
1293
|
+
return Temporal[tag.slice(9)].from(text);
|
|
1294
|
+
},
|
|
1295
|
+
|
|
1296
|
+
fromArrayBuffer: (buffer) => buffer,
|
|
1297
|
+
|
|
1298
|
+
fromRegExpInfo: (source, flags) => new RegExp(source, flags),
|
|
1299
|
+
|
|
1300
|
+
fromViewInfo: (tag, buffer, byteOffset, length) => {
|
|
1301
|
+
const Constructor = /** @type {any} */ (globalThis)[tag];
|
|
1302
|
+
return byteOffset !== undefined
|
|
1303
|
+
? new Constructor(buffer, byteOffset, length)
|
|
1304
|
+
: new Constructor(buffer);
|
|
1305
|
+
},
|
|
1306
|
+
|
|
1307
|
+
box: (value) => Object(value),
|
|
1308
|
+
|
|
1309
|
+
createArray: (length) => new Array(length),
|
|
1310
|
+
|
|
1311
|
+
createSparseArray: (length) => {
|
|
1312
|
+
/** @type {any[]} */
|
|
1313
|
+
const array = [];
|
|
1314
|
+
|
|
1315
|
+
// Setting `array.length = length` (or equivalently calling
|
|
1316
|
+
// `new Array(length)`) on an untrusted length is a DoS vector: V8
|
|
1317
|
+
// eagerly allocates a contiguous backing store for array lengths below
|
|
1318
|
+
// ~10^8, so a small payload with a huge declared length can force
|
|
1319
|
+
// arbitrary memory allocation. Touching the largest-possible index
|
|
1320
|
+
// first forces V8 into dictionary-elements mode, where `length` is
|
|
1321
|
+
// just a number and no contiguous allocation occurs.
|
|
1322
|
+
array[MAX_ARRAY_INDEX] = undefined;
|
|
1323
|
+
delete array[MAX_ARRAY_INDEX];
|
|
1324
|
+
array.length = length;
|
|
1325
|
+
|
|
1326
|
+
return array;
|
|
1327
|
+
},
|
|
1328
|
+
|
|
1329
|
+
createObject: () => ({}),
|
|
1330
|
+
|
|
1331
|
+
createNullPrototypeObject: () => Object.create(null),
|
|
1332
|
+
|
|
1333
|
+
createSet: () => new Set(),
|
|
1334
|
+
|
|
1335
|
+
createMap: () => new Map(),
|
|
1336
|
+
|
|
1337
|
+
set: (target, key, value) => {
|
|
1338
|
+
target[key] = value;
|
|
1339
|
+
},
|
|
1340
|
+
|
|
1341
|
+
addValue: (set, value) => {
|
|
1342
|
+
set.add(value);
|
|
1343
|
+
},
|
|
1344
|
+
|
|
1345
|
+
addEntry: (map, key, value) => {
|
|
1346
|
+
map.set(key, value);
|
|
1347
|
+
}
|
|
1348
|
+
};
|
|
1349
|
+
|
|
1350
|
+
const default_parse_operations = Object.freeze(parse_operations);
|
|
1351
|
+
|
|
1112
1352
|
/**
|
|
1113
1353
|
* Revive a value serialized with `devalue.stringify`
|
|
1114
1354
|
* @param {string} serialized
|
|
1115
1355
|
* @param {Record<string, (value: any) => any>} [revivers]
|
|
1356
|
+
* @param {import('./types.js').ParseOptions} [options]
|
|
1116
1357
|
*/
|
|
1117
|
-
function parse(serialized, revivers) {
|
|
1358
|
+
function parse(serialized, revivers, options) {
|
|
1118
1359
|
return unflatten(JSON.parse(serialized), revivers);
|
|
1119
1360
|
}
|
|
1120
1361
|
|
|
@@ -1122,8 +1363,12 @@ function parse(serialized, revivers) {
|
|
|
1122
1363
|
* Revive a value flattened with `devalue.stringify`
|
|
1123
1364
|
* @param {number | any[]} parsed
|
|
1124
1365
|
* @param {Record<string, (value: any) => any>} [revivers]
|
|
1366
|
+
* @param {import('./types.js').ParseOptions} [options]
|
|
1125
1367
|
*/
|
|
1126
|
-
function unflatten(parsed, revivers) {
|
|
1368
|
+
function unflatten(parsed, revivers, options) {
|
|
1369
|
+
/** @type {import('./types.js').ParseOperations} */
|
|
1370
|
+
const ops = merge_operations(default_parse_operations);
|
|
1371
|
+
|
|
1127
1372
|
if (typeof parsed === 'number') return hydrate(parsed, true);
|
|
1128
1373
|
|
|
1129
1374
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
@@ -1146,11 +1391,11 @@ function unflatten(parsed, revivers) {
|
|
|
1146
1391
|
* @returns {any}
|
|
1147
1392
|
*/
|
|
1148
1393
|
function hydrate(index, standalone = false) {
|
|
1149
|
-
if (index === UNDEFINED) return undefined;
|
|
1150
|
-
if (index === NAN) return NaN;
|
|
1151
|
-
if (index === POSITIVE_INFINITY) return Infinity;
|
|
1152
|
-
if (index === NEGATIVE_INFINITY) return -Infinity;
|
|
1153
|
-
if (index === NEGATIVE_ZERO) return -0;
|
|
1394
|
+
if (index === UNDEFINED) return ops.fromPrimitive(undefined);
|
|
1395
|
+
if (index === NAN) return ops.fromPrimitive(NaN);
|
|
1396
|
+
if (index === POSITIVE_INFINITY) return ops.fromPrimitive(Infinity);
|
|
1397
|
+
if (index === NEGATIVE_INFINITY) return ops.fromPrimitive(-Infinity);
|
|
1398
|
+
if (index === NEGATIVE_ZERO) return ops.fromPrimitive(-0);
|
|
1154
1399
|
|
|
1155
1400
|
if (standalone || typeof index !== 'number') {
|
|
1156
1401
|
throw new Error(`Invalid input`);
|
|
@@ -1158,10 +1403,14 @@ function unflatten(parsed, revivers) {
|
|
|
1158
1403
|
|
|
1159
1404
|
if (index in hydrated) return hydrated[index];
|
|
1160
1405
|
|
|
1406
|
+
if (index >= values.length) {
|
|
1407
|
+
throw new Error(`Invalid input`);
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1161
1410
|
const value = values[index];
|
|
1162
1411
|
|
|
1163
1412
|
if (!value || typeof value !== 'object') {
|
|
1164
|
-
hydrated[index] = value;
|
|
1413
|
+
hydrated[index] = ops.fromPrimitive(value);
|
|
1165
1414
|
} else if (Array.isArray(value)) {
|
|
1166
1415
|
if (typeof value[0] === 'string') {
|
|
1167
1416
|
const type = value[0];
|
|
@@ -1176,6 +1425,16 @@ function unflatten(parsed, revivers) {
|
|
|
1176
1425
|
i = values.push(value[1]) - 1;
|
|
1177
1426
|
}
|
|
1178
1427
|
|
|
1428
|
+
// If the payload is already hydrated, its recursion has already
|
|
1429
|
+
// terminated (e.g. a self-referential object cached itself before
|
|
1430
|
+
// following its own back-reference), so revive it directly. Falling
|
|
1431
|
+
// through to the `hydrating` guard here would wrongly reject a valid
|
|
1432
|
+
// cycle. An actually infinite payload (e.g. `[["Custom", 0]]`) is never
|
|
1433
|
+
// cached, so it still hits the guard below.
|
|
1434
|
+
if (Object.hasOwn(hydrated, i)) {
|
|
1435
|
+
return (hydrated[index] = reviver(hydrated[i]));
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1179
1438
|
hydrating ??= new Set();
|
|
1180
1439
|
|
|
1181
1440
|
if (hydrating.has(i)) {
|
|
@@ -1191,27 +1450,27 @@ function unflatten(parsed, revivers) {
|
|
|
1191
1450
|
|
|
1192
1451
|
switch (type) {
|
|
1193
1452
|
case 'Date':
|
|
1194
|
-
hydrated[index] =
|
|
1453
|
+
hydrated[index] = ops.fromISOString(value[1]);
|
|
1195
1454
|
break;
|
|
1196
1455
|
|
|
1197
1456
|
case 'Set':
|
|
1198
|
-
const set =
|
|
1457
|
+
const set = ops.createSet();
|
|
1199
1458
|
hydrated[index] = set;
|
|
1200
1459
|
for (let i = 1; i < value.length; i += 1) {
|
|
1201
|
-
|
|
1460
|
+
ops.addValue(set, hydrate(value[i]));
|
|
1202
1461
|
}
|
|
1203
1462
|
break;
|
|
1204
1463
|
|
|
1205
1464
|
case 'Map':
|
|
1206
|
-
const map =
|
|
1465
|
+
const map = ops.createMap();
|
|
1207
1466
|
hydrated[index] = map;
|
|
1208
1467
|
for (let i = 1; i < value.length; i += 2) {
|
|
1209
|
-
|
|
1468
|
+
ops.addEntry(map, hydrate(value[i]), hydrate(value[i + 1]));
|
|
1210
1469
|
}
|
|
1211
1470
|
break;
|
|
1212
1471
|
|
|
1213
1472
|
case 'RegExp':
|
|
1214
|
-
hydrated[index] =
|
|
1473
|
+
hydrated[index] = ops.fromRegExpInfo(value[1], value[2]);
|
|
1215
1474
|
break;
|
|
1216
1475
|
|
|
1217
1476
|
case 'Object': {
|
|
@@ -1225,23 +1484,23 @@ function unflatten(parsed, revivers) {
|
|
|
1225
1484
|
throw new Error('Invalid input');
|
|
1226
1485
|
}
|
|
1227
1486
|
|
|
1228
|
-
hydrated[index] =
|
|
1487
|
+
hydrated[index] = ops.box(hydrate(wrapped_index));
|
|
1229
1488
|
break;
|
|
1230
1489
|
}
|
|
1231
1490
|
|
|
1232
1491
|
case 'BigInt':
|
|
1233
|
-
hydrated[index] = BigInt(value[1]);
|
|
1492
|
+
hydrated[index] = ops.fromPrimitive(BigInt(value[1]));
|
|
1234
1493
|
break;
|
|
1235
1494
|
|
|
1236
1495
|
case 'null':
|
|
1237
|
-
const obj =
|
|
1496
|
+
const obj = ops.createNullPrototypeObject();
|
|
1238
1497
|
hydrated[index] = obj;
|
|
1239
1498
|
for (let i = 1; i < value.length; i += 2) {
|
|
1240
1499
|
if (value[i] === '__proto__') {
|
|
1241
1500
|
throw new Error('Cannot parse an object with a `__proto__` property');
|
|
1242
1501
|
}
|
|
1243
1502
|
|
|
1244
|
-
obj
|
|
1503
|
+
ops.set(obj, value[i], hydrate(value[i + 1]));
|
|
1245
1504
|
}
|
|
1246
1505
|
break;
|
|
1247
1506
|
|
|
@@ -1265,13 +1524,9 @@ function unflatten(parsed, revivers) {
|
|
|
1265
1524
|
throw new Error('Invalid data');
|
|
1266
1525
|
}
|
|
1267
1526
|
|
|
1268
|
-
const TypedArrayConstructor = globalThis[type];
|
|
1269
1527
|
const buffer = hydrate(value[1]);
|
|
1270
1528
|
|
|
1271
|
-
hydrated[index] =
|
|
1272
|
-
value[2] !== undefined
|
|
1273
|
-
? new TypedArrayConstructor(buffer, value[2], value[3])
|
|
1274
|
-
: new TypedArrayConstructor(buffer);
|
|
1529
|
+
hydrated[index] = ops.fromViewInfo(type, buffer, value[2], value[3]);
|
|
1275
1530
|
|
|
1276
1531
|
break;
|
|
1277
1532
|
}
|
|
@@ -1281,11 +1536,12 @@ function unflatten(parsed, revivers) {
|
|
|
1281
1536
|
if (typeof base64 !== 'string') {
|
|
1282
1537
|
throw new Error('Invalid ArrayBuffer encoding');
|
|
1283
1538
|
}
|
|
1284
|
-
|
|
1285
|
-
hydrated[index] = arraybuffer;
|
|
1539
|
+
hydrated[index] = ops.fromArrayBuffer(decode64(base64));
|
|
1286
1540
|
break;
|
|
1287
1541
|
}
|
|
1288
1542
|
|
|
1543
|
+
case 'URL':
|
|
1544
|
+
case 'URLSearchParams':
|
|
1289
1545
|
case 'Temporal.Duration':
|
|
1290
1546
|
case 'Temporal.Instant':
|
|
1291
1547
|
case 'Temporal.PlainDate':
|
|
@@ -1294,21 +1550,8 @@ function unflatten(parsed, revivers) {
|
|
|
1294
1550
|
case 'Temporal.PlainMonthDay':
|
|
1295
1551
|
case 'Temporal.PlainYearMonth':
|
|
1296
1552
|
case 'Temporal.ZonedDateTime': {
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
hydrated[index] = Temporal[temporalName].from(value[1]);
|
|
1300
|
-
break;
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
case 'URL': {
|
|
1304
|
-
const url = new URL(value[1]);
|
|
1305
|
-
hydrated[index] = url;
|
|
1306
|
-
break;
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
case 'URLSearchParams': {
|
|
1310
|
-
const url = new URLSearchParams(value[1]);
|
|
1311
|
-
hydrated[index] = url;
|
|
1553
|
+
// the same tags `toStringValue` serializes on the stringify side
|
|
1554
|
+
hydrated[index] = ops.fromStringValue(type, value[1]);
|
|
1312
1555
|
break;
|
|
1313
1556
|
}
|
|
1314
1557
|
|
|
@@ -1323,20 +1566,12 @@ function unflatten(parsed, revivers) {
|
|
|
1323
1566
|
throw new Error('Invalid input');
|
|
1324
1567
|
}
|
|
1325
1568
|
|
|
1326
|
-
|
|
1327
|
-
|
|
1569
|
+
// `len` comes from the input rather than being bounded by it, so
|
|
1570
|
+
// `createSparseArray` is responsible for not allocating storage
|
|
1571
|
+
// proportional to it.
|
|
1572
|
+
const array = ops.createSparseArray(len);
|
|
1328
1573
|
hydrated[index] = array;
|
|
1329
1574
|
|
|
1330
|
-
// Setting `array.length = len` (or equivalently calling `new Array(len)`)
|
|
1331
|
-
// on an untrusted `len` is a DoS vector: V8 eagerly allocates a
|
|
1332
|
-
// contiguous backing store for array lengths below ~10^8, so a
|
|
1333
|
-
// small payload with a huge declared length can force arbitrary
|
|
1334
|
-
// memory allocation. Touching the largest-possible index first
|
|
1335
|
-
// forces V8 into dictionary-elements mode, where `length` is
|
|
1336
|
-
// just a number and no contiguous allocation occurs.
|
|
1337
|
-
array[MAX_ARRAY_INDEX] = undefined;
|
|
1338
|
-
delete array[MAX_ARRAY_INDEX];
|
|
1339
|
-
|
|
1340
1575
|
for (let i = 2; i < value.length; i += 2) {
|
|
1341
1576
|
const idx = value[i];
|
|
1342
1577
|
|
|
@@ -1344,24 +1579,21 @@ function unflatten(parsed, revivers) {
|
|
|
1344
1579
|
throw new Error('Invalid input');
|
|
1345
1580
|
}
|
|
1346
1581
|
|
|
1347
|
-
array
|
|
1582
|
+
ops.set(array, idx, hydrate(value[i + 1]));
|
|
1348
1583
|
}
|
|
1349
|
-
|
|
1350
|
-
array.length = len;
|
|
1351
1584
|
} else {
|
|
1352
|
-
const array =
|
|
1585
|
+
const array = ops.createArray(value.length);
|
|
1353
1586
|
hydrated[index] = array;
|
|
1354
1587
|
|
|
1355
1588
|
for (let i = 0; i < value.length; i += 1) {
|
|
1356
1589
|
const n = value[i];
|
|
1357
1590
|
if (n === HOLE) continue;
|
|
1358
1591
|
|
|
1359
|
-
array
|
|
1592
|
+
ops.set(array, i, hydrate(n));
|
|
1360
1593
|
}
|
|
1361
1594
|
}
|
|
1362
1595
|
} else {
|
|
1363
|
-
|
|
1364
|
-
const object = {};
|
|
1596
|
+
const object = ops.createObject();
|
|
1365
1597
|
hydrated[index] = object;
|
|
1366
1598
|
|
|
1367
1599
|
for (const key of Object.keys(value)) {
|
|
@@ -1369,8 +1601,7 @@ function unflatten(parsed, revivers) {
|
|
|
1369
1601
|
throw new Error('Cannot parse an object with a `__proto__` property');
|
|
1370
1602
|
}
|
|
1371
1603
|
|
|
1372
|
-
|
|
1373
|
-
object[key] = hydrate(n);
|
|
1604
|
+
ops.set(object, key, hydrate(value[key]));
|
|
1374
1605
|
}
|
|
1375
1606
|
}
|
|
1376
1607
|
|
|
@@ -1384,8 +1615,9 @@ function unflatten(parsed, revivers) {
|
|
|
1384
1615
|
* Turn a value into a JSON string that can be parsed with `devalue.parse`
|
|
1385
1616
|
* @param {any} value
|
|
1386
1617
|
* @param {Record<string, (value: any) => any>} [reducers]
|
|
1618
|
+
* @param {import('./types.js').StringifyOptions} [options]
|
|
1387
1619
|
*/
|
|
1388
|
-
function stringify$1(value, reducers) {
|
|
1620
|
+
function stringify$1(value, reducers, options) {
|
|
1389
1621
|
const stringified = run(false, value, reducers);
|
|
1390
1622
|
return typeof stringified === 'string' ? stringified : `[${stringified.join(',')}]`;
|
|
1391
1623
|
}
|
|
@@ -1394,8 +1626,11 @@ function stringify$1(value, reducers) {
|
|
|
1394
1626
|
* @param {boolean} async
|
|
1395
1627
|
* @param {any} value
|
|
1396
1628
|
* @param {Record<string, (value: any) => any>} [reducers]
|
|
1629
|
+
* @param {import('./types.js').StringifyOptions} [options]
|
|
1397
1630
|
*/
|
|
1398
|
-
function run(async, value, reducers) {
|
|
1631
|
+
function run(async, value, reducers, options) {
|
|
1632
|
+
const ops = merge_operations(default_stringify_operations);
|
|
1633
|
+
|
|
1399
1634
|
/** @type {any[]} */
|
|
1400
1635
|
const stringified = [];
|
|
1401
1636
|
|
|
@@ -1420,16 +1655,30 @@ function run(async, value, reducers) {
|
|
|
1420
1655
|
* @param {number} [index]
|
|
1421
1656
|
*/
|
|
1422
1657
|
function flatten(thing, index) {
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
if (
|
|
1426
|
-
|
|
1427
|
-
|
|
1658
|
+
const type = ops.typeOf(thing);
|
|
1659
|
+
|
|
1660
|
+
if (type === 'undefined') return UNDEFINED;
|
|
1661
|
+
|
|
1662
|
+
/** @type {number | undefined} */
|
|
1663
|
+
let number;
|
|
1664
|
+
|
|
1665
|
+
// `ops.toPrimitive` is the boundary between the value being serialized and
|
|
1666
|
+
// plain host JavaScript: everything below operates on the extracted host
|
|
1667
|
+
// primitive, so native comparisons and arithmetic are correct there.
|
|
1668
|
+
if (type === 'number') {
|
|
1669
|
+
number = /** @type {number} */ (ops.toPrimitive(thing));
|
|
1670
|
+
if (Number.isNaN(number)) return NAN;
|
|
1671
|
+
if (number === Infinity) return POSITIVE_INFINITY;
|
|
1672
|
+
if (number === -Infinity) return NEGATIVE_INFINITY;
|
|
1673
|
+
if (number === 0 && 1 / number < 0) return NEGATIVE_ZERO;
|
|
1674
|
+
}
|
|
1428
1675
|
|
|
1429
|
-
|
|
1676
|
+
const id = ops.identify(thing);
|
|
1677
|
+
|
|
1678
|
+
if (indexes.has(id)) return /** @type {number} */ (indexes.get(id));
|
|
1430
1679
|
|
|
1431
1680
|
index ??= p++;
|
|
1432
|
-
indexes.set(
|
|
1681
|
+
indexes.set(id, index);
|
|
1433
1682
|
|
|
1434
1683
|
for (const { key, fn } of custom) {
|
|
1435
1684
|
const value = fn(thing);
|
|
@@ -1439,18 +1688,18 @@ function run(async, value, reducers) {
|
|
|
1439
1688
|
}
|
|
1440
1689
|
}
|
|
1441
1690
|
|
|
1442
|
-
if (
|
|
1691
|
+
if (type === 'function') {
|
|
1443
1692
|
throw new DevalueError(`Cannot stringify a function`, keys, thing, value);
|
|
1444
|
-
} else if (
|
|
1693
|
+
} else if (type === 'symbol') {
|
|
1445
1694
|
throw new DevalueError(`Cannot stringify a Symbol primitive`, keys, thing, value);
|
|
1446
1695
|
}
|
|
1447
1696
|
|
|
1448
1697
|
/** @type {string | Promise<any>} */
|
|
1449
1698
|
let str = '';
|
|
1450
1699
|
|
|
1451
|
-
if (
|
|
1452
|
-
str = stringify_primitive(thing);
|
|
1453
|
-
} else if (
|
|
1700
|
+
if (type !== 'object') {
|
|
1701
|
+
str = stringify_primitive(type === 'number' ? number : ops.toPrimitive(thing));
|
|
1702
|
+
} else if (ops.isThenable(thing)) {
|
|
1454
1703
|
{
|
|
1455
1704
|
throw new DevalueError(
|
|
1456
1705
|
`Cannot stringify a Promise or thenable — use stringifyAsync instead`,
|
|
@@ -1460,31 +1709,30 @@ function run(async, value, reducers) {
|
|
|
1460
1709
|
);
|
|
1461
1710
|
}
|
|
1462
1711
|
} else {
|
|
1463
|
-
const
|
|
1712
|
+
const tag = ops.tagOf(thing);
|
|
1464
1713
|
|
|
1465
|
-
switch (
|
|
1714
|
+
switch (tag) {
|
|
1466
1715
|
case 'Number':
|
|
1467
1716
|
case 'String':
|
|
1468
1717
|
case 'Boolean':
|
|
1469
1718
|
case 'BigInt':
|
|
1470
|
-
str = `["Object",${flatten(
|
|
1719
|
+
str = `["Object",${flatten(ops.unbox(thing))}]`;
|
|
1471
1720
|
break;
|
|
1472
1721
|
|
|
1473
1722
|
case 'Date':
|
|
1474
|
-
|
|
1475
|
-
str = `["Date","${valid ? thing.toISOString() : ''}"]`;
|
|
1723
|
+
str = `["Date","${ops.toISOString(thing)}"]`;
|
|
1476
1724
|
break;
|
|
1477
1725
|
|
|
1478
1726
|
case 'URL':
|
|
1479
|
-
str = `["URL",${stringify_string(
|
|
1727
|
+
str = `["URL",${stringify_string(ops.toStringValue(thing))}]`;
|
|
1480
1728
|
break;
|
|
1481
1729
|
|
|
1482
1730
|
case 'URLSearchParams':
|
|
1483
|
-
str = `["URLSearchParams",${stringify_string(
|
|
1731
|
+
str = `["URLSearchParams",${stringify_string(ops.toStringValue(thing))}]`;
|
|
1484
1732
|
break;
|
|
1485
1733
|
|
|
1486
1734
|
case 'RegExp':
|
|
1487
|
-
const { source, flags } = thing;
|
|
1735
|
+
const { source, flags } = ops.regExpInfo(thing);
|
|
1488
1736
|
str = flags
|
|
1489
1737
|
? `["RegExp",${stringify_string(source)},"${flags}"]`
|
|
1490
1738
|
: `["RegExp",${stringify_string(source)}]`;
|
|
@@ -1500,14 +1748,16 @@ function run(async, value, reducers) {
|
|
|
1500
1748
|
// is what protects against the DoS of e.g. `arr[1000000] = 1`.
|
|
1501
1749
|
let mostly_dense = false;
|
|
1502
1750
|
|
|
1751
|
+
const length = ops.lengthOf(thing);
|
|
1752
|
+
|
|
1503
1753
|
str = '[';
|
|
1504
1754
|
|
|
1505
|
-
for (let i = 0; i <
|
|
1755
|
+
for (let i = 0; i < length; i += 1) {
|
|
1506
1756
|
if (i > 0) str += ',';
|
|
1507
1757
|
|
|
1508
|
-
if (
|
|
1758
|
+
if (ops.hasOwn(thing, i)) {
|
|
1509
1759
|
keys.push(`[${i}]`);
|
|
1510
|
-
str += flatten(thing
|
|
1760
|
+
str += flatten(ops.get(thing, i));
|
|
1511
1761
|
keys.pop();
|
|
1512
1762
|
} else if (mostly_dense) {
|
|
1513
1763
|
// Use dense encoding. The heuristic guarantees the
|
|
@@ -1546,19 +1796,19 @@ function run(async, value, reducers) {
|
|
|
1546
1796
|
//
|
|
1547
1797
|
// Sparse encoding is cheaper when:
|
|
1548
1798
|
// (4 + d) + P * (d + 1) < (L - P) * 3
|
|
1549
|
-
const populated_keys =
|
|
1799
|
+
const populated_keys = ops.indicesOf(thing);
|
|
1550
1800
|
const population = populated_keys.length;
|
|
1551
|
-
const d = String(
|
|
1801
|
+
const d = String(length).length;
|
|
1552
1802
|
|
|
1553
|
-
const hole_cost = (
|
|
1803
|
+
const hole_cost = (length - population) * 3;
|
|
1554
1804
|
const sparse_cost = 4 + d + population * (d + 1);
|
|
1555
1805
|
|
|
1556
1806
|
if (hole_cost > sparse_cost) {
|
|
1557
|
-
str = '[' + SPARSE + ',' +
|
|
1807
|
+
str = '[' + SPARSE + ',' + length;
|
|
1558
1808
|
for (let j = 0; j < populated_keys.length; j++) {
|
|
1559
1809
|
const key = populated_keys[j];
|
|
1560
1810
|
keys.push(`[${key}]`);
|
|
1561
|
-
str += ',' + key + ',' + flatten(thing
|
|
1811
|
+
str += ',' + key + ',' + flatten(ops.get(thing, key));
|
|
1562
1812
|
keys.pop();
|
|
1563
1813
|
}
|
|
1564
1814
|
break;
|
|
@@ -1577,7 +1827,7 @@ function run(async, value, reducers) {
|
|
|
1577
1827
|
case 'Set':
|
|
1578
1828
|
str = '["Set"';
|
|
1579
1829
|
|
|
1580
|
-
for (const value of thing) {
|
|
1830
|
+
for (const value of ops.valuesOf(thing)) {
|
|
1581
1831
|
str += `,${flatten(value)}`;
|
|
1582
1832
|
}
|
|
1583
1833
|
|
|
@@ -1587,8 +1837,13 @@ function run(async, value, reducers) {
|
|
|
1587
1837
|
case 'Map':
|
|
1588
1838
|
str = '["Map"';
|
|
1589
1839
|
|
|
1590
|
-
for (const [key, value] of thing) {
|
|
1591
|
-
|
|
1840
|
+
for (const [key, value] of ops.entriesOf(thing)) {
|
|
1841
|
+
const key_type = ops.typeOf(key);
|
|
1842
|
+
const key_is_primitive =
|
|
1843
|
+
key_type !== 'object' && key_type !== 'function' && key_type !== 'symbol';
|
|
1844
|
+
keys.push(
|
|
1845
|
+
`.get(${key_is_primitive ? stringify_primitive(ops.toPrimitive(key)) : '...'})`
|
|
1846
|
+
);
|
|
1592
1847
|
str += `,${flatten(key)},${flatten(value)}`;
|
|
1593
1848
|
keys.pop();
|
|
1594
1849
|
}
|
|
@@ -1607,16 +1862,25 @@ function run(async, value, reducers) {
|
|
|
1607
1862
|
case 'Float32Array':
|
|
1608
1863
|
case 'Float64Array':
|
|
1609
1864
|
case 'BigInt64Array':
|
|
1610
|
-
case 'BigUint64Array':
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
const typedArray = thing;
|
|
1614
|
-
str = '["' + type + '",' + flatten(typedArray.buffer);
|
|
1865
|
+
case 'BigUint64Array': {
|
|
1866
|
+
const info = ops.viewInfo(thing);
|
|
1867
|
+
str = '["' + tag + '",' + flatten(info.buffer);
|
|
1615
1868
|
|
|
1616
1869
|
// handle subarrays
|
|
1617
|
-
if (
|
|
1618
|
-
|
|
1619
|
-
|
|
1870
|
+
if (info.byteLength !== info.bufferByteLength) {
|
|
1871
|
+
str += `,${info.byteOffset},${info.length}`;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
str += ']';
|
|
1875
|
+
break;
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
case 'DataView': {
|
|
1879
|
+
const info = ops.viewInfo(thing);
|
|
1880
|
+
str = '["' + tag + '",' + flatten(info.buffer);
|
|
1881
|
+
|
|
1882
|
+
if (info.byteLength !== info.bufferByteLength) {
|
|
1883
|
+
str += `,${info.byteOffset},${info.byteLength}`;
|
|
1620
1884
|
}
|
|
1621
1885
|
|
|
1622
1886
|
str += ']';
|
|
@@ -1624,9 +1888,7 @@ function run(async, value, reducers) {
|
|
|
1624
1888
|
}
|
|
1625
1889
|
|
|
1626
1890
|
case 'ArrayBuffer': {
|
|
1627
|
-
|
|
1628
|
-
const arraybuffer = thing;
|
|
1629
|
-
const base64 = encode64(arraybuffer);
|
|
1891
|
+
const base64 = encode64(ops.toArrayBuffer(thing));
|
|
1630
1892
|
|
|
1631
1893
|
str = `["ArrayBuffer","${base64}"]`;
|
|
1632
1894
|
break;
|
|
@@ -1640,21 +1902,23 @@ function run(async, value, reducers) {
|
|
|
1640
1902
|
case 'Temporal.PlainMonthDay':
|
|
1641
1903
|
case 'Temporal.PlainYearMonth':
|
|
1642
1904
|
case 'Temporal.ZonedDateTime':
|
|
1643
|
-
str = `["${
|
|
1905
|
+
str = `["${tag}",${stringify_string(ops.toStringValue(thing))}]`;
|
|
1644
1906
|
break;
|
|
1645
1907
|
|
|
1646
|
-
default:
|
|
1647
|
-
|
|
1908
|
+
default: {
|
|
1909
|
+
const shape = ops.shapeOf(thing);
|
|
1910
|
+
|
|
1911
|
+
if (shape.kind === 'not-plain') {
|
|
1648
1912
|
throw new DevalueError(`Cannot stringify arbitrary non-POJOs`, keys, thing, value);
|
|
1649
1913
|
}
|
|
1650
1914
|
|
|
1651
|
-
if (
|
|
1915
|
+
if (shape.kind === 'symbol-keys') {
|
|
1652
1916
|
throw new DevalueError(`Cannot stringify POJOs with symbolic keys`, keys, thing, value);
|
|
1653
1917
|
}
|
|
1654
1918
|
|
|
1655
|
-
if (
|
|
1919
|
+
if (shape.kind === 'null-proto') {
|
|
1656
1920
|
str = '["null"';
|
|
1657
|
-
for (const key of
|
|
1921
|
+
for (const key of shape.keys) {
|
|
1658
1922
|
if (key === '__proto__') {
|
|
1659
1923
|
throw new DevalueError(
|
|
1660
1924
|
`Cannot stringify objects with __proto__ keys`,
|
|
@@ -1665,14 +1929,14 @@ function run(async, value, reducers) {
|
|
|
1665
1929
|
}
|
|
1666
1930
|
|
|
1667
1931
|
keys.push(stringify_key(key));
|
|
1668
|
-
str += `,${stringify_string(key)},${flatten(thing
|
|
1932
|
+
str += `,${stringify_string(key)},${flatten(ops.get(thing, key))}`;
|
|
1669
1933
|
keys.pop();
|
|
1670
1934
|
}
|
|
1671
1935
|
str += ']';
|
|
1672
1936
|
} else {
|
|
1673
1937
|
str = '{';
|
|
1674
1938
|
let started = false;
|
|
1675
|
-
for (const key of
|
|
1939
|
+
for (const key of shape.keys) {
|
|
1676
1940
|
if (key === '__proto__') {
|
|
1677
1941
|
throw new DevalueError(
|
|
1678
1942
|
`Cannot stringify objects with __proto__ keys`,
|
|
@@ -1685,11 +1949,12 @@ function run(async, value, reducers) {
|
|
|
1685
1949
|
if (started) str += ',';
|
|
1686
1950
|
started = true;
|
|
1687
1951
|
keys.push(stringify_key(key));
|
|
1688
|
-
str += `${stringify_string(key)}:${flatten(thing
|
|
1952
|
+
str += `${stringify_string(key)}:${flatten(ops.get(thing, key))}`;
|
|
1689
1953
|
keys.pop();
|
|
1690
1954
|
}
|
|
1691
1955
|
str += '}';
|
|
1692
1956
|
}
|
|
1957
|
+
}
|
|
1693
1958
|
}
|
|
1694
1959
|
}
|
|
1695
1960
|
|
|
@@ -2542,4 +2807,4 @@ function create_replacer(transport) {
|
|
|
2542
2807
|
}
|
|
2543
2808
|
|
|
2544
2809
|
export { escape_html as A, create_remote_key as B, error as C, parse_remote_arg as D, ENDPOINT_METHODS as E, deserialize_binary_form as F, stringify as G, HttpError as H, INVALIDATED_PARAM as I, stringify$1 as J, ActionFailure as K, split_remote_key as L, SVELTE_KIT_ASSETS as M, splitCookiesString as N, PAGE_METHODS as P, Redirect as R, SvelteKitError as S, TRAILING_SLASH_PARAM as T, handle_fatal_error as a, negotiate as b, method_not_allowed as c, handle_error_and_jsonify as d, get_status as e, format_server_error as f, get_set_cookies as g, has_prerendered_path as h, is_form_content_type as i, json as j, get_global_name as k, create_replacer as l, merge_tracing as m, noop as n, serialize_uses as o, parseString as p, clarify_devalue_error as q, redirect_response as r, static_error_page as s, text as t, uneval as u, once as v, with_request_store as w, normalize_error as x, get_node_type as y, isRedirect as z };
|
|
2545
|
-
//# sourceMappingURL=utils.js-
|
|
2810
|
+
//# sourceMappingURL=utils.js-Bzpr6vQU.js.map
|