@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.
Files changed (125) hide show
  1. package/.claude-plugin/plugin.json +2 -2
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/.mcp.json +1 -1
  4. package/dist/cli-command-map.d.ts.map +1 -1
  5. package/dist/cli-command-map.js +1 -0
  6. package/dist/cli-command-map.js.map +1 -1
  7. package/dist/cli-contract.d.ts.map +1 -1
  8. package/dist/cli-contract.js +11 -3
  9. package/dist/cli-contract.js.map +1 -1
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/cli.js +115 -10
  12. package/dist/cli.js.map +1 -1
  13. package/dist/index.d.ts +3 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/mcp.d.ts +1 -1
  18. package/dist/mcp.d.ts.map +1 -1
  19. package/dist/mcp.js +1 -0
  20. package/dist/mcp.js.map +1 -1
  21. package/dist/runtime/identity/index.d.ts +1 -1
  22. package/dist/runtime/identity/index.d.ts.map +1 -1
  23. package/dist/runtime/identity/index.js +1 -1
  24. package/dist/runtime/identity/index.js.map +1 -1
  25. package/dist/runtime/identity/live.d.ts +4 -0
  26. package/dist/runtime/identity/live.d.ts.map +1 -1
  27. package/dist/runtime/identity/live.js +3 -3
  28. package/dist/runtime/identity/live.js.map +1 -1
  29. package/dist/runtime/mcp/agent-launch.d.ts +2 -0
  30. package/dist/runtime/mcp/agent-launch.d.ts.map +1 -1
  31. package/dist/runtime/mcp/agent-launch.js +11 -0
  32. package/dist/runtime/mcp/agent-launch.js.map +1 -1
  33. package/dist/runtime/mcp/handlers.d.ts +5 -0
  34. package/dist/runtime/mcp/handlers.d.ts.map +1 -1
  35. package/dist/runtime/mcp/handlers.js +19 -0
  36. package/dist/runtime/mcp/handlers.js.map +1 -1
  37. package/dist/runtime/mcp/server.d.ts +3 -0
  38. package/dist/runtime/mcp/server.d.ts.map +1 -1
  39. package/dist/runtime/mcp/server.js +3 -1
  40. package/dist/runtime/mcp/server.js.map +1 -1
  41. package/dist/runtime/mcp/stdio.d.ts +3 -0
  42. package/dist/runtime/mcp/stdio.d.ts.map +1 -1
  43. package/dist/runtime/mcp/stdio.js +1 -0
  44. package/dist/runtime/mcp/stdio.js.map +1 -1
  45. package/dist/runtime/mcp/tools.d.ts.map +1 -1
  46. package/dist/runtime/mcp/tools.js +17 -0
  47. package/dist/runtime/mcp/tools.js.map +1 -1
  48. package/dist/runtime/send.d.ts +40 -0
  49. package/dist/runtime/send.d.ts.map +1 -0
  50. package/dist/runtime/send.js +108 -0
  51. package/dist/runtime/send.js.map +1 -0
  52. package/focus-app/client/_app/immutable/chunks/BgBtu3IQ.js +2 -0
  53. package/focus-app/client/_app/immutable/chunks/BgBtu3IQ.js.br +0 -0
  54. package/focus-app/client/_app/immutable/chunks/BgBtu3IQ.js.gz +0 -0
  55. package/focus-app/client/_app/immutable/entry/{app.D1IjBbSs.js → app.D_yfk55R.js} +2 -2
  56. package/focus-app/client/_app/immutable/entry/app.D_yfk55R.js.br +0 -0
  57. package/focus-app/client/_app/immutable/entry/app.D_yfk55R.js.gz +0 -0
  58. package/focus-app/client/_app/immutable/entry/start.CoQWYNTs.js +1 -0
  59. package/focus-app/client/_app/immutable/entry/start.CoQWYNTs.js.br +2 -0
  60. package/focus-app/client/_app/immutable/entry/start.CoQWYNTs.js.gz +0 -0
  61. package/focus-app/client/_app/immutable/nodes/{1.CcZFi3uA.js → 1.Jo1uWTw0.js} +1 -1
  62. package/focus-app/client/_app/immutable/nodes/1.Jo1uWTw0.js.br +4 -0
  63. package/focus-app/client/_app/immutable/nodes/1.Jo1uWTw0.js.gz +0 -0
  64. package/focus-app/client/_app/version.json +1 -1
  65. package/focus-app/client/_app/version.json.br +0 -0
  66. package/focus-app/client/_app/version.json.gz +0 -0
  67. package/focus-app/h2a-focus.json +61 -61
  68. package/focus-app/handler.js +8 -8
  69. package/focus-app/index.js +8 -8
  70. package/focus-app/server/chunks/chunks/{AppShell.js-BDEpw0ai.js → AppShell.js-BoWxjmfr.js} +2 -2
  71. package/focus-app/server/chunks/chunks/{AppShell.js-BDEpw0ai.js.map → AppShell.js-BoWxjmfr.js.map} +1 -1
  72. package/focus-app/server/chunks/chunks/{exports.js-BZfNcFtJ.js → exports.js-D45A8dcc.js} +3 -3
  73. package/focus-app/server/chunks/chunks/{exports.js-BZfNcFtJ.js.map → exports.js-D45A8dcc.js.map} +1 -1
  74. package/focus-app/server/chunks/chunks/{index.js--xmWq8-W.js → index.js-e3L5MwfB.js} +2 -2
  75. package/focus-app/server/chunks/chunks/{index.js--xmWq8-W.js.map → index.js-e3L5MwfB.js.map} +1 -1
  76. package/focus-app/server/chunks/chunks/{internal.js-o4rWftwV.js → internal.js-DAV-A6NO.js} +3 -3
  77. package/focus-app/server/chunks/chunks/{internal.js-o4rWftwV.js.map → internal.js-DAV-A6NO.js.map} +1 -1
  78. package/focus-app/server/chunks/chunks/{root.js-ve7Sv8eD.js → root.js-CEypm32A.js} +2 -2
  79. package/focus-app/server/chunks/chunks/{root.js-ve7Sv8eD.js.map → root.js-CEypm32A.js.map} +1 -1
  80. package/focus-app/server/chunks/chunks/{utils.js-h3jETFNR.js → utils.js-Bzpr6vQU.js} +406 -141
  81. package/focus-app/server/chunks/chunks/utils.js-Bzpr6vQU.js.map +1 -0
  82. package/focus-app/server/chunks/entries/endpoints/api/actions/launch/{_server.ts.js-DVeNoSe-.js → _server.ts.js-Cah_Ivgw.js} +2 -2
  83. 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
  84. package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/{_server.ts.js-CLfZIM0I.js → _server.ts.js-DW5wvcgH.js} +2 -2
  85. package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/{_server.ts.js-CLfZIM0I.js.map → _server.ts.js-DW5wvcgH.js.map} +1 -1
  86. package/focus-app/server/chunks/entries/endpoints/api/dossiers/agent-memory/include/{_server.ts.js-DNQwbxOr.js → _server.ts.js-C2jIx8Jr.js} +2 -2
  87. 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
  88. package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/{_server.ts.js-BqneXTTN.js → _server.ts.js-BkAMLcHu.js} +2 -2
  89. package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/{_server.ts.js-BqneXTTN.js.map → _server.ts.js-BkAMLcHu.js.map} +1 -1
  90. package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-VpNJnNVG.js → error.svelte.js-BWuS92Wk.js} +5 -5
  91. package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-VpNJnNVG.js.map → error.svelte.js-BWuS92Wk.js.map} +1 -1
  92. package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-D_Rgb6oH.js → _layout.svelte.js-CKspI0Bw.js} +3 -3
  93. package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-D_Rgb6oH.js.map → _layout.svelte.js-CKspI0Bw.js.map} +1 -1
  94. package/focus-app/server/chunks/entries/pages/{_page.svelte.js-2a7ZxK1n.js → _page.svelte.js-B8EWZmZj.js} +4 -4
  95. package/focus-app/server/chunks/entries/pages/{_page.svelte.js-2a7ZxK1n.js.map → _page.svelte.js-B8EWZmZj.js.map} +1 -1
  96. package/focus-app/server/chunks/entries/pages/dossier/agent-memory/{_page.svelte.js-Bl_4XjaL.js → _page.svelte.js-BZvcKeya.js} +4 -4
  97. 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
  98. package/focus-app/server/chunks/{handler-B897YV9_.js → handler-BCBpURX0.js} +4 -4
  99. package/focus-app/server/chunks/{handler-B897YV9_.js.map → handler-BCBpURX0.js.map} +1 -1
  100. package/focus-app/server/chunks/{index.js-BkPsDsTn.js → index.js-CZWB6FqQ.js} +5 -5
  101. package/focus-app/server/chunks/{index.js-BkPsDsTn.js.map → index.js-CZWB6FqQ.js.map} +1 -1
  102. package/focus-app/server/chunks/{manifest.js-DZ6J-aM3.js → manifest.js-C2CyTiUe.js} +10 -10
  103. package/focus-app/server/chunks/{manifest.js-DZ6J-aM3.js.map → manifest.js-C2CyTiUe.js.map} +1 -1
  104. package/focus-app/server/chunks/nodes/{0.js-tlwNtUnO.js → 0.js-Cp9RMJ1x.js} +2 -2
  105. package/focus-app/server/chunks/nodes/{0.js-tlwNtUnO.js.map → 0.js-Cp9RMJ1x.js.map} +1 -1
  106. package/focus-app/server/chunks/nodes/1.js-DMWmTj0d.js +9 -0
  107. package/focus-app/server/chunks/nodes/{1.js-mLYMqMM3.js.map → 1.js-DMWmTj0d.js.map} +1 -1
  108. package/focus-app/server/chunks/nodes/{2.js-C_y8BeMm.js → 2.js-Dv8Q6LQc.js} +2 -2
  109. package/focus-app/server/chunks/nodes/{2.js-C_y8BeMm.js.map → 2.js-Dv8Q6LQc.js.map} +1 -1
  110. package/focus-app/server/chunks/nodes/{3.js-13r5MUAa.js → 3.js-DJH-zOae.js} +2 -2
  111. package/focus-app/server/chunks/nodes/{3.js-13r5MUAa.js.map → 3.js-DJH-zOae.js.map} +1 -1
  112. package/package.json +3 -3
  113. package/skills/h2a/SKILL.md +11 -33
  114. package/focus-app/client/_app/immutable/chunks/DAAR3e-c.js +0 -2
  115. package/focus-app/client/_app/immutable/chunks/DAAR3e-c.js.br +0 -0
  116. package/focus-app/client/_app/immutable/chunks/DAAR3e-c.js.gz +0 -0
  117. package/focus-app/client/_app/immutable/entry/app.D1IjBbSs.js.br +0 -0
  118. package/focus-app/client/_app/immutable/entry/app.D1IjBbSs.js.gz +0 -0
  119. package/focus-app/client/_app/immutable/entry/start.DHa1k4dG.js +0 -1
  120. package/focus-app/client/_app/immutable/entry/start.DHa1k4dG.js.br +0 -2
  121. package/focus-app/client/_app/immutable/entry/start.DHa1k4dG.js.gz +0 -0
  122. package/focus-app/client/_app/immutable/nodes/1.CcZFi3uA.js.br +0 -0
  123. package/focus-app/client/_app/immutable/nodes/1.CcZFi3uA.js.gz +0 -0
  124. package/focus-app/server/chunks/chunks/utils.js-h3jETFNR.js.map +0 -1
  125. 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
- * Finds the populated indices of an array.
497
- * @param {unknown[]} array
496
+ * Returns the length of the leading run of valid array indices in `keys`.
497
+ * @param {readonly string[]} keys
498
498
  */
499
- function valid_array_indices(array) {
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
- keys.length = i + 1;
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
- const array = new thing.constructor(thing.buffer);
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.startOffset},${thing.byteLength}`;
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
- statements.push(
916
- `${name}.${Array.from(thing)
917
- .map((v) => `add(${stringify(v)})`)
918
- .join('.')}`
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
- statements.push(
925
- `${name}.${Array.from(thing)
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
- const array = new thing.constructor(thing.buffer);
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
- statements.push(`${name}=${str}`);
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
- statements.push(`${name}=${str}`);
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
- return `(function(${params.join(',')}){${statements.join(';')}}(${values.join(',')}))`;
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] = new Date(value[1]);
1453
+ hydrated[index] = ops.fromISOString(value[1]);
1195
1454
  break;
1196
1455
 
1197
1456
  case 'Set':
1198
- const set = new Set();
1457
+ const set = ops.createSet();
1199
1458
  hydrated[index] = set;
1200
1459
  for (let i = 1; i < value.length; i += 1) {
1201
- set.add(hydrate(value[i]));
1460
+ ops.addValue(set, hydrate(value[i]));
1202
1461
  }
1203
1462
  break;
1204
1463
 
1205
1464
  case 'Map':
1206
- const map = new Map();
1465
+ const map = ops.createMap();
1207
1466
  hydrated[index] = map;
1208
1467
  for (let i = 1; i < value.length; i += 2) {
1209
- map.set(hydrate(value[i]), hydrate(value[i + 1]));
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] = new RegExp(value[1], value[2]);
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] = Object(hydrate(wrapped_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 = Object.create(null);
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[value[i]] = hydrate(value[i + 1]);
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
- const arraybuffer = decode64(base64);
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
- const temporalName = type.slice(9);
1298
- // @ts-expect-error TS doesn't know about Temporal yet
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
- /** @type {any[]} */
1327
- const array = [];
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[idx] = hydrate(value[i + 1]);
1582
+ ops.set(array, idx, hydrate(value[i + 1]));
1348
1583
  }
1349
-
1350
- array.length = len;
1351
1584
  } else {
1352
- const array = new Array(value.length);
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[i] = hydrate(n);
1592
+ ops.set(array, i, hydrate(n));
1360
1593
  }
1361
1594
  }
1362
1595
  } else {
1363
- /** @type {Record<string, any>} */
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
- const n = value[key];
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
- if (thing === undefined) return UNDEFINED;
1424
- if (Number.isNaN(thing)) return NAN;
1425
- if (thing === Infinity) return POSITIVE_INFINITY;
1426
- if (thing === -Infinity) return NEGATIVE_INFINITY;
1427
- if (thing === 0 && 1 / thing < 0) return NEGATIVE_ZERO;
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
- if (indexes.has(thing)) return /** @type {number} */ (indexes.get(thing));
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(thing, index);
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 (typeof thing === 'function') {
1691
+ if (type === 'function') {
1443
1692
  throw new DevalueError(`Cannot stringify a function`, keys, thing, value);
1444
- } else if (typeof thing === 'symbol') {
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 (is_primitive(thing)) {
1452
- str = stringify_primitive(thing);
1453
- } else if (typeof thing.then === 'function') {
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 type = get_type(thing);
1712
+ const tag = ops.tagOf(thing);
1464
1713
 
1465
- switch (type) {
1714
+ switch (tag) {
1466
1715
  case 'Number':
1467
1716
  case 'String':
1468
1717
  case 'Boolean':
1469
1718
  case 'BigInt':
1470
- str = `["Object",${flatten(thing.valueOf())}]`;
1719
+ str = `["Object",${flatten(ops.unbox(thing))}]`;
1471
1720
  break;
1472
1721
 
1473
1722
  case 'Date':
1474
- const valid = !isNaN(thing.getDate());
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(thing.toString())}]`;
1727
+ str = `["URL",${stringify_string(ops.toStringValue(thing))}]`;
1480
1728
  break;
1481
1729
 
1482
1730
  case 'URLSearchParams':
1483
- str = `["URLSearchParams",${stringify_string(thing.toString())}]`;
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 < thing.length; i += 1) {
1755
+ for (let i = 0; i < length; i += 1) {
1506
1756
  if (i > 0) str += ',';
1507
1757
 
1508
- if (Object.hasOwn(thing, i)) {
1758
+ if (ops.hasOwn(thing, i)) {
1509
1759
  keys.push(`[${i}]`);
1510
- str += flatten(thing[i]);
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 = valid_array_indices(/** @type {any[]} */ (thing));
1799
+ const populated_keys = ops.indicesOf(thing);
1550
1800
  const population = populated_keys.length;
1551
- const d = String(thing.length).length;
1801
+ const d = String(length).length;
1552
1802
 
1553
- const hole_cost = (thing.length - population) * 3;
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 + ',' + thing.length;
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[key]);
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
- keys.push(`.get(${is_primitive(key) ? stringify_primitive(key) : '...'})`);
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
- case 'DataView': {
1612
- /** @type {import("./types.js").TypedArray} */
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 (typedArray.byteLength !== typedArray.buffer.byteLength) {
1618
- // to be used with `new TypedArray(buffer, byteOffset, length)`
1619
- str += `,${typedArray.byteOffset},${typedArray.length}`;
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
- /** @type {ArrayBuffer} */
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 = `["${type}",${stringify_string(thing.toString())}]`;
1905
+ str = `["${tag}",${stringify_string(ops.toStringValue(thing))}]`;
1644
1906
  break;
1645
1907
 
1646
- default:
1647
- if (!is_plain_object(thing)) {
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 (enumerable_symbols(thing).length > 0) {
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 (Object.getPrototypeOf(thing) === null) {
1919
+ if (shape.kind === 'null-proto') {
1656
1920
  str = '["null"';
1657
- for (const key of Object.keys(thing)) {
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[key])}`;
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 Object.keys(thing)) {
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[key])}`;
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-h3jETFNR.js.map
2810
+ //# sourceMappingURL=utils.js-Bzpr6vQU.js.map