seroval 1.6.5 → 1.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -147,6 +147,8 @@ const NEG_INFINITY_NODE = /* @__PURE__ */ createConstantNode(6);
147
147
  const NAN_NODE = /* @__PURE__ */ createConstantNode(7);
148
148
  //#endregion
149
149
  //#region src/core/string.ts
150
+ const MIN_JSON_STRINGIFY_LENGTH = 64;
151
+ const JSON_ESCAPE_DIFFERENCES = /[\x00-\x07\x0b\x0e-\x1f<\u2028\u2029\ud800-\udfff]/;
150
152
  function serializeChar(str) {
151
153
  switch (str) {
152
154
  case "\"": return "\\\"";
@@ -163,6 +165,7 @@ function serializeChar(str) {
163
165
  }
164
166
  }
165
167
  function serializeString(str) {
168
+ if (str.length >= MIN_JSON_STRINGIFY_LENGTH && !JSON_ESCAPE_DIFFERENCES.test(str)) return JSON.stringify(str).slice(1, -1);
166
169
  let result = "";
167
170
  let lastPos = 0;
168
171
  let replacement;
@@ -193,6 +196,7 @@ function deserializeReplacer(str) {
193
196
  }
194
197
  }
195
198
  function deserializeString(str) {
199
+ if (typeof str === "string" && !str.includes("\\")) return str;
196
200
  return str.replace(/(\\\\|\\"|\\n|\\r|\\b|\\t|\\f|\\u2028|\\u2029|\\x3C)/g, deserializeReplacer);
197
201
  }
198
202
  //#endregion
@@ -516,7 +520,10 @@ const STREAM_CONSTRUCTOR = () => {
516
520
  let count = 0;
517
521
  const internal = {
518
522
  flush(value, mode, x) {
519
- for (x = 0; x < count; x++) if (listeners[x]) listeners[x][mode](value);
523
+ for (x = 0; x < count; x++) {
524
+ const listener = listeners[x];
525
+ if (listener) listener[mode](value);
526
+ }
520
527
  },
521
528
  up(listener, x, z, current) {
522
529
  for (x = 0, z = buffer.length; x < z; x++) {
@@ -525,16 +532,20 @@ const STREAM_CONSTRUCTOR = () => {
525
532
  else listener.next(current);
526
533
  }
527
534
  },
528
- on(listener, temp) {
535
+ on(listener, temp = 0) {
536
+ let subscribed = alive;
529
537
  if (alive) {
530
- temp = count++;
538
+ for (temp = 0; temp < count; temp++) if (!listeners[temp]) break;
539
+ if (temp === count) count++;
531
540
  listeners[temp] = listener;
532
541
  }
533
542
  internal.up(listener);
534
543
  return () => {
535
- if (alive) {
536
- listeners[temp] = listeners[count];
537
- listeners[count--] = void 0;
544
+ if (alive && subscribed) {
545
+ subscribed = false;
546
+ listeners[temp] = void 0;
547
+ while (count > 0 && !listeners[count - 1]) count--;
548
+ listeners.length = count;
538
549
  }
539
550
  };
540
551
  }
@@ -745,19 +756,35 @@ function isStream(value) {
745
756
  function createStream() {
746
757
  return STREAM_CONSTRUCTOR();
747
758
  }
748
- function createStreamFromAsyncIterable(iterable) {
759
+ function createStreamFromAsyncIterable(iterable, cleanups) {
749
760
  const stream = createStream();
750
761
  const iterator = iterable[SYM_ASYNC_ITERATOR]();
762
+ let cancelled = false;
763
+ let done = false;
764
+ cleanups === null || cleanups === void 0 || cleanups.push(() => {
765
+ if (!(done || cancelled)) {
766
+ cancelled = true;
767
+ Promise.resolve().then(() => {
768
+ var _iterator$return;
769
+ return (_iterator$return = iterator.return) === null || _iterator$return === void 0 ? void 0 : _iterator$return.call(iterator);
770
+ }).catch(() => {});
771
+ }
772
+ });
751
773
  async function push() {
752
774
  try {
753
- const value = await iterator.next();
754
- if (value.done) stream.return(value.value);
755
- else {
775
+ while (!cancelled) {
776
+ const value = await iterator.next();
777
+ if (cancelled) return;
778
+ if (value.done) {
779
+ done = true;
780
+ stream.return(value.value);
781
+ break;
782
+ }
756
783
  stream.next(value.value);
757
- await push();
758
784
  }
759
785
  } catch (error) {
760
- stream.throw(error);
786
+ done = true;
787
+ if (!cancelled) stream.throw(error);
761
788
  }
762
789
  }
763
790
  push().catch(() => {});
@@ -779,13 +806,15 @@ async function promiseToResult(current) {
779
806
  //#endregion
780
807
  //#region src/core/context/parser.ts
781
808
  function createBaseParserContext(mode, options) {
809
+ var _options$compactArray;
782
810
  return {
783
811
  plugins: options.plugins,
784
812
  mode,
785
813
  marked: /* @__PURE__ */ new Set(),
786
814
  features: 127 ^ (options.disabledFeatures || 0),
787
815
  refs: options.refs || /* @__PURE__ */ new Map(),
788
- depthLimit: options.depthLimit || 1e3
816
+ depthLimit: options.depthLimit || 1e3,
817
+ compactArrayBufferViews: (_options$compactArray = options.compactArrayBufferViews) !== null && _options$compactArray !== void 0 ? _options$compactArray : false
789
818
  };
790
819
  }
791
820
  /**
@@ -865,11 +894,22 @@ function createMapNode(ctx, id, k, v) {
865
894
  function createPromiseConstructorNode(ctx, id, resolver) {
866
895
  return createSerovalNode(22, id, resolver, void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 1), void 0, void 0, void 0);
867
896
  }
868
- function createArrayBufferNode(ctx, id, current) {
897
+ function getArrayBufferView(ctx, current) {
898
+ if (!ctx.compactArrayBufferViews) return current;
899
+ const buffer = new Uint8Array(current.buffer, current.byteOffset, current.byteLength).slice().buffer;
900
+ const Constructor = current.constructor;
901
+ return new Constructor(buffer);
902
+ }
903
+ function encodeArrayBuffer(current) {
904
+ if (typeof Buffer !== "undefined") return Buffer.from(current).toString("base64");
869
905
  const bytes = new Uint8Array(current);
906
+ if (typeof bytes.toBase64 === "function") return bytes.toBase64();
870
907
  let result = "";
871
908
  for (let i = 0, len = bytes.length; i < len; i++) result += String.fromCharCode(bytes[i]);
872
- return createSerovalNode(19, id, serializeString(btoa(result)), void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 5), void 0, void 0, void 0);
909
+ return btoa(result);
910
+ }
911
+ function createArrayBufferNode(ctx, id, current) {
912
+ return createSerovalNode(19, id, encodeArrayBuffer(current), void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 5), void 0, void 0, void 0);
873
913
  }
874
914
  //#endregion
875
915
  //#region src/core/context/async-parser.ts
@@ -933,12 +973,15 @@ async function parseBoxed$1(ctx, depth, id, current) {
933
973
  return createBoxedNode(id, await parseAsync(ctx, depth, current.valueOf()));
934
974
  }
935
975
  async function parseTypedArray$1(ctx, depth, id, current) {
976
+ current = getArrayBufferView(ctx.base, current);
936
977
  return createTypedArrayNode(id, current, await parseAsync(ctx, depth, current.buffer));
937
978
  }
938
979
  async function parseBigIntTypedArray$1(ctx, depth, id, current) {
980
+ current = getArrayBufferView(ctx.base, current);
939
981
  return createBigIntTypedArrayNode(id, current, await parseAsync(ctx, depth, current.buffer));
940
982
  }
941
983
  async function parseDataView$1(ctx, depth, id, current) {
984
+ current = getArrayBufferView(ctx.base, current);
942
985
  return createDataViewNode(id, current, await parseAsync(ctx, depth, current.buffer));
943
986
  }
944
987
  async function parseError$1(ctx, depth, id, current) {
@@ -1183,7 +1226,8 @@ function isValidSymbol(symbol) {
1183
1226
  }
1184
1227
  //#endregion
1185
1228
  //#region src/core/context/deserializer.ts
1186
- const MAX_BASE64_LENGTH = 1e6;
1229
+ const DEFAULT_MAX_BASE64_LENGTH = 1e6;
1230
+ const MIN_NATIVE_BASE64_LENGTH = 512;
1187
1231
  const MAX_BIGINT_LENGTH = 1e4;
1188
1232
  const MAX_REGEXP_SOURCE_LENGTH = 2e4;
1189
1233
  function applyObjectFlag(obj, flag) {
@@ -1196,7 +1240,9 @@ function applyObjectFlag(obj, flag) {
1196
1240
  }
1197
1241
  const DEFAULT_DEPTH_LIMIT = 1e3;
1198
1242
  function createBaseDeserializerContext(mode, options) {
1199
- var _options$features;
1243
+ var _options$maxBase64Len, _options$features;
1244
+ const maxBase64Length = (_options$maxBase64Len = options.maxBase64Length) !== null && _options$maxBase64Len !== void 0 ? _options$maxBase64Len : DEFAULT_MAX_BASE64_LENGTH;
1245
+ if (!Number.isSafeInteger(maxBase64Length) || maxBase64Length < 0) throw new RangeError("maxBase64Length must be a non-negative safe integer");
1200
1246
  const refs = options.refs || /* @__PURE__ */ new Map();
1201
1247
  if (!("types" in refs)) Object.assign(refs, { types: /* @__PURE__ */ new Map() });
1202
1248
  return {
@@ -1204,7 +1250,8 @@ function createBaseDeserializerContext(mode, options) {
1204
1250
  plugins: options.plugins,
1205
1251
  refs,
1206
1252
  features: (_options$features = options.features) !== null && _options$features !== void 0 ? _options$features : 127 ^ (options.disabledFeatures || 0),
1207
- depthLimit: options.depthLimit || DEFAULT_DEPTH_LIMIT
1253
+ depthLimit: options.depthLimit || DEFAULT_DEPTH_LIMIT,
1254
+ maxBase64Length
1208
1255
  };
1209
1256
  }
1210
1257
  function createVanillaDeserializerContext(options) {
@@ -1367,8 +1414,17 @@ function deserializeMap(ctx, depth, node) {
1367
1414
  return result;
1368
1415
  }
1369
1416
  function deserializeArrayBuffer(ctx, node) {
1370
- if (node.s.length > MAX_BASE64_LENGTH) throw new SerovalMalformedNodeError(node);
1371
- return assignIndexedValue$1(ctx, node.i, ARRAY_BUFFER_CONSTRUCTOR(deserializeString(node.s)));
1417
+ if (typeof node.s !== "string") throw new SerovalMalformedNodeError(node);
1418
+ if (node.s.length > ctx.base.maxBase64Length) throw new RangeError("ArrayBuffer exceeds maxBase64Length (" + ctx.base.maxBase64Length + ")");
1419
+ const source = deserializeString(node.s);
1420
+ let buffer;
1421
+ if (source.length < MIN_NATIVE_BASE64_LENGTH || typeof Buffer === "undefined") buffer = ARRAY_BUFFER_CONSTRUCTOR(source);
1422
+ else {
1423
+ const decoded = atob(source);
1424
+ buffer = new ArrayBuffer(decoded.length);
1425
+ Buffer.from(buffer).write(decoded, "latin1");
1426
+ }
1427
+ return assignIndexedValue$1(ctx, node.i, buffer);
1372
1428
  }
1373
1429
  function deserializeTypedArray(ctx, depth, node) {
1374
1430
  var _node$b;
@@ -1376,7 +1432,7 @@ function deserializeTypedArray(ctx, depth, node) {
1376
1432
  const source = deserialize$1(ctx, depth, node.f);
1377
1433
  if (!(source instanceof ArrayBuffer)) throw new SerovalMalformedNodeError(node);
1378
1434
  const offset = (_node$b = node.b) !== null && _node$b !== void 0 ? _node$b : 0;
1379
- if (offset < 0 || offset > source.byteLength || node.l > MAX_BASE64_LENGTH) throw new SerovalMalformedNodeError(node);
1435
+ if (offset < 0 || offset > source.byteLength) throw new SerovalMalformedNodeError(node);
1380
1436
  return assignIndexedValue$1(ctx, node.i, new construct(source, offset, node.l));
1381
1437
  }
1382
1438
  function deserializeDataView(ctx, depth, node) {
@@ -1384,7 +1440,7 @@ function deserializeDataView(ctx, depth, node) {
1384
1440
  const source = deserialize$1(ctx, depth, node.f);
1385
1441
  if (!(source instanceof ArrayBuffer)) throw new SerovalMalformedNodeError(node);
1386
1442
  const offset = (_node$b2 = node.b) !== null && _node$b2 !== void 0 ? _node$b2 : 0;
1387
- if (offset < 0 || offset > source.byteLength || node.l > MAX_BASE64_LENGTH) throw new SerovalMalformedNodeError(node);
1443
+ if (offset < 0 || offset > source.byteLength) throw new SerovalMalformedNodeError(node);
1388
1444
  return assignIndexedValue$1(ctx, node.i, new DataView(source, offset, node.l));
1389
1445
  }
1390
1446
  function deserializeDictionary(ctx, depth, node, result) {
@@ -2404,7 +2460,7 @@ function parseProperties(ctx, depth, properties) {
2404
2460
  }
2405
2461
  if (SYM_ASYNC_ITERATOR in properties) {
2406
2462
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ASYNC_ITERATOR));
2407
- valueNodes.push(createAsyncIteratorFactoryInstanceNode(parseAsyncIteratorFactory(ctx.base), parseSOS(ctx, depth, ctx.type === 1 ? createStream() : createStreamFromAsyncIterable(properties))));
2463
+ valueNodes.push(createAsyncIteratorFactoryInstanceNode(parseAsyncIteratorFactory(ctx.base), parseSOS(ctx, depth, ctx.type === 1 ? createStream() : createStreamFromAsyncIterable(properties, ctx.state.cleanups))));
2408
2464
  }
2409
2465
  if (SYM_TO_STRING_TAG in properties) {
2410
2466
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_TO_STRING_TAG));
@@ -2426,12 +2482,15 @@ function parseBoxed(ctx, depth, id, current) {
2426
2482
  return createBoxedNode(id, parseSOS(ctx, depth, current.valueOf()));
2427
2483
  }
2428
2484
  function parseTypedArray(ctx, depth, id, current) {
2485
+ current = getArrayBufferView(ctx.base, current);
2429
2486
  return createTypedArrayNode(id, current, parseSOS(ctx, depth, current.buffer));
2430
2487
  }
2431
2488
  function parseBigIntTypedArray(ctx, depth, id, current) {
2489
+ current = getArrayBufferView(ctx.base, current);
2432
2490
  return createBigIntTypedArrayNode(id, current, parseSOS(ctx, depth, current.buffer));
2433
2491
  }
2434
2492
  function parseDataView(ctx, depth, id, current) {
2493
+ current = getArrayBufferView(ctx.base, current);
2435
2494
  return createDataViewNode(id, current, parseSOS(ctx, depth, current.buffer));
2436
2495
  }
2437
2496
  function parseError(ctx, depth, id, current) {
@@ -2682,6 +2741,7 @@ function destroyStreamParse(ctx) {
2682
2741
  function crossSerialize(source, options = {}) {
2683
2742
  const plugins = resolvePlugins(options.plugins);
2684
2743
  const ctx = createSyncParserContext(2, {
2744
+ compactArrayBufferViews: options.compactArrayBufferViews,
2685
2745
  plugins,
2686
2746
  disabledFeatures: options.disabledFeatures,
2687
2747
  refs: options.refs
@@ -2697,6 +2757,7 @@ function crossSerialize(source, options = {}) {
2697
2757
  async function crossSerializeAsync(source, options = {}) {
2698
2758
  const plugins = resolvePlugins(options.plugins);
2699
2759
  const ctx = createAsyncParserContext(2, {
2760
+ compactArrayBufferViews: options.compactArrayBufferViews,
2700
2761
  plugins,
2701
2762
  disabledFeatures: options.disabledFeatures,
2702
2763
  refs: options.refs
@@ -2710,15 +2771,19 @@ async function crossSerializeAsync(source, options = {}) {
2710
2771
  }), tree);
2711
2772
  }
2712
2773
  function toCrossJSON(source, options = {}) {
2774
+ const plugins = resolvePlugins(options.plugins);
2713
2775
  return parseTop(createSyncParserContext(2, {
2714
- plugins: resolvePlugins(options.plugins),
2776
+ compactArrayBufferViews: options.compactArrayBufferViews,
2777
+ plugins,
2715
2778
  disabledFeatures: options.disabledFeatures,
2716
2779
  refs: options.refs
2717
2780
  }), source);
2718
2781
  }
2719
2782
  async function toCrossJSONAsync(source, options = {}) {
2783
+ const plugins = resolvePlugins(options.plugins);
2720
2784
  return await parseTopAsync(createAsyncParserContext(2, {
2721
- plugins: resolvePlugins(options.plugins),
2785
+ compactArrayBufferViews: options.compactArrayBufferViews,
2786
+ plugins,
2722
2787
  disabledFeatures: options.disabledFeatures,
2723
2788
  refs: options.refs
2724
2789
  }), source);
@@ -2726,6 +2791,7 @@ async function toCrossJSONAsync(source, options = {}) {
2726
2791
  function crossSerializeStream(source, options) {
2727
2792
  const plugins = resolvePlugins(options.plugins);
2728
2793
  const ctx = createStreamParserContext({
2794
+ compactArrayBufferViews: options.compactArrayBufferViews,
2729
2795
  plugins,
2730
2796
  refs: options.refs,
2731
2797
  disabledFeatures: options.disabledFeatures,
@@ -2752,8 +2818,10 @@ function crossSerializeStream(source, options) {
2752
2818
  return destroyStreamParse.bind(null, ctx);
2753
2819
  }
2754
2820
  function toCrossJSONStream(source, options) {
2821
+ const plugins = resolvePlugins(options.plugins);
2755
2822
  const ctx = createStreamParserContext({
2756
- plugins: resolvePlugins(options.plugins),
2823
+ compactArrayBufferViews: options.compactArrayBufferViews,
2824
+ plugins,
2757
2825
  refs: options.refs,
2758
2826
  disabledFeatures: options.disabledFeatures,
2759
2827
  depthLimit: options.depthLimit,
@@ -2765,8 +2833,10 @@ function toCrossJSONStream(source, options) {
2765
2833
  return destroyStreamParse.bind(null, ctx);
2766
2834
  }
2767
2835
  function fromCrossJSON(source, options) {
2836
+ const plugins = resolvePlugins(options.plugins);
2768
2837
  return deserializeTop(createCrossDeserializerContext({
2769
- plugins: resolvePlugins(options.plugins),
2838
+ maxBase64Length: options.maxBase64Length,
2839
+ plugins,
2770
2840
  refs: options.refs,
2771
2841
  features: options.features,
2772
2842
  disabledFeatures: options.disabledFeatures,
@@ -2797,6 +2867,7 @@ var Serializer = class {
2797
2867
  scopeId: this.options.scopeId,
2798
2868
  refs: this.refs,
2799
2869
  disabledFeatures: this.options.disabledFeatures,
2870
+ compactArrayBufferViews: this.options.compactArrayBufferViews,
2800
2871
  onError: this.options.onError,
2801
2872
  onSerialize: (data, initial) => {
2802
2873
  if (this.alive) this.options.onData(initial ? this.options.globalIdentifier + "[\"" + serializeString(key) + "\"]=" + data : data);
@@ -2847,6 +2918,7 @@ var Serializer = class {
2847
2918
  function serialize(source, options = {}) {
2848
2919
  const plugins = resolvePlugins(options.plugins);
2849
2920
  const ctx = createSyncParserContext(1, {
2921
+ compactArrayBufferViews: options.compactArrayBufferViews,
2850
2922
  plugins,
2851
2923
  disabledFeatures: options.disabledFeatures
2852
2924
  });
@@ -2860,6 +2932,7 @@ function serialize(source, options = {}) {
2860
2932
  async function serializeAsync(source, options = {}) {
2861
2933
  const plugins = resolvePlugins(options.plugins);
2862
2934
  const ctx = createAsyncParserContext(1, {
2935
+ compactArrayBufferViews: options.compactArrayBufferViews,
2863
2936
  plugins,
2864
2937
  disabledFeatures: options.disabledFeatures
2865
2938
  });
@@ -2874,8 +2947,10 @@ function deserialize(source) {
2874
2947
  return (0, eval)(source);
2875
2948
  }
2876
2949
  function toJSON(source, options = {}) {
2950
+ const plugins = resolvePlugins(options.plugins);
2877
2951
  const ctx = createSyncParserContext(1, {
2878
- plugins: resolvePlugins(options.plugins),
2952
+ compactArrayBufferViews: options.compactArrayBufferViews,
2953
+ plugins,
2879
2954
  disabledFeatures: options.disabledFeatures
2880
2955
  });
2881
2956
  return {
@@ -2885,8 +2960,10 @@ function toJSON(source, options = {}) {
2885
2960
  };
2886
2961
  }
2887
2962
  async function toJSONAsync(source, options = {}) {
2963
+ const plugins = resolvePlugins(options.plugins);
2888
2964
  const ctx = createAsyncParserContext(1, {
2889
- plugins: resolvePlugins(options.plugins),
2965
+ compactArrayBufferViews: options.compactArrayBufferViews,
2966
+ plugins,
2890
2967
  disabledFeatures: options.disabledFeatures
2891
2968
  });
2892
2969
  return {
@@ -2908,6 +2985,7 @@ function fromJSON(source, options = {}) {
2908
2985
  const disabledFeatures = options.disabledFeatures || 0;
2909
2986
  const sourceFeatures = (_source$f = source.f) !== null && _source$f !== void 0 ? _source$f : 127;
2910
2987
  return deserializeTop(createVanillaDeserializerContext({
2988
+ maxBase64Length: options.maxBase64Length,
2911
2989
  plugins,
2912
2990
  markedRefs: source.m,
2913
2991
  features: sourceFeatures & ~disabledFeatures,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "seroval",
3
3
  "type": "module",
4
- "version": "1.6.5",
4
+ "version": "1.6.7",
5
5
  "files": [
6
6
  "dist"
7
7
  ],