seroval 0.11.0 → 0.11.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.
@@ -96,7 +96,7 @@ function generateNodeList(
96
96
  for (let i = 0; i < size; i++) {
97
97
  if (i in current) {
98
98
  item = current[i];
99
- if (isIterable(item)) {
99
+ if (isIterable(ctx, item)) {
100
100
  deferred[i] = item;
101
101
  } else {
102
102
  nodes[i] = crossParseStream(ctx, item);
@@ -146,7 +146,7 @@ function generateMapNode(
146
146
  let nodeSize = 0;
147
147
  for (const [key, value] of current.entries()) {
148
148
  // Either key or value might be an iterable
149
- if (isIterable(key) || isIterable(value)) {
149
+ if (isIterable(ctx, key) || isIterable(ctx, value)) {
150
150
  deferredKey[deferredSize] = key;
151
151
  deferredValue[deferredSize] = value;
152
152
  deferredSize++;
@@ -188,7 +188,7 @@ function generateSetNode(
188
188
  let nodeSize = 0;
189
189
  for (const item of current.keys()) {
190
190
  // Iterables are lazy, so the evaluation must be deferred
191
- if (isIterable(item)) {
191
+ if (isIterable(ctx, item)) {
192
192
  deferred[deferredSize++] = item;
193
193
  } else {
194
194
  nodes[nodeSize++] = crossParseStream(ctx, item);
@@ -231,7 +231,7 @@ function generateProperties(
231
231
  for (const key of keys) {
232
232
  item = properties[key];
233
233
  escaped = serializeString(key);
234
- if (isIterable(item)) {
234
+ if (isIterable(ctx, item)) {
235
235
  deferredKeys[deferredSize] = escaped;
236
236
  deferredValues[deferredSize] = item;
237
237
  deferredSize++;
@@ -281,7 +281,7 @@ function generatePlainProperties(
281
281
  for (const key of keys) {
282
282
  item = properties[key];
283
283
  escaped = serializeString(key);
284
- if (isIterable(item)) {
284
+ if (isIterable(ctx, item)) {
285
285
  deferredKeys[deferredSize] = escaped;
286
286
  deferredValues[deferredSize] = item;
287
287
  deferredSize++;
@@ -507,57 +507,17 @@ function generateBoxedNode(
507
507
  };
508
508
  }
509
509
 
510
- function generateReadableStreamNode(
510
+ function pushReadableStreamState(
511
511
  ctx: StreamingCrossParserContext,
512
512
  id: number,
513
- current: ReadableStream<unknown>,
514
- ): SerovalReadableStreamConstructorNode {
515
- const reader = current.getReader();
516
- pushPendingState(ctx);
517
-
518
- function push(): void {
519
- reader.read().then(
520
- (data) => {
521
- if (ctx.alive) {
522
- if (data.done) {
523
- ctx.onParse({
524
- t: SerovalNodeType.ReadableStreamClose,
525
- i: id,
526
- s: undefined,
527
- l: undefined,
528
- c: undefined,
529
- m: undefined,
530
- p: undefined,
531
- e: undefined,
532
- a: undefined,
533
- f: undefined,
534
- b: undefined,
535
- o: undefined,
536
- }, false);
537
- popPendingState(ctx);
538
- } else {
539
- ctx.onParse({
540
- t: SerovalNodeType.ReadableStreamEnqueue,
541
- i: id,
542
- s: undefined,
543
- l: undefined,
544
- c: undefined,
545
- m: undefined,
546
- p: undefined,
547
- e: undefined,
548
- a: undefined,
549
- f: crossParseStream(ctx, data.value),
550
- b: undefined,
551
- o: undefined,
552
- }, false);
553
- push();
554
- }
555
- }
556
- },
557
- (value) => {
558
- if (ctx.alive) {
513
+ reader: ReadableStreamDefaultReader,
514
+ ): void {
515
+ reader.read().then(
516
+ (data) => {
517
+ if (ctx.alive) {
518
+ if (data.done) {
559
519
  ctx.onParse({
560
- t: SerovalNodeType.ReadableStreamError,
520
+ t: SerovalNodeType.ReadableStreamClose,
561
521
  i: id,
562
522
  s: undefined,
563
523
  l: undefined,
@@ -566,17 +526,59 @@ function generateReadableStreamNode(
566
526
  p: undefined,
567
527
  e: undefined,
568
528
  a: undefined,
569
- f: crossParseStream(ctx, value),
529
+ f: undefined,
570
530
  b: undefined,
571
531
  o: undefined,
572
532
  }, false);
573
533
  popPendingState(ctx);
534
+ } else {
535
+ ctx.onParse({
536
+ t: SerovalNodeType.ReadableStreamEnqueue,
537
+ i: id,
538
+ s: undefined,
539
+ l: undefined,
540
+ c: undefined,
541
+ m: undefined,
542
+ p: undefined,
543
+ e: undefined,
544
+ a: undefined,
545
+ f: crossParseStream(ctx, data.value),
546
+ b: undefined,
547
+ o: undefined,
548
+ }, false);
549
+ pushReadableStreamState(ctx, id, reader);
574
550
  }
575
- },
576
- );
577
- }
551
+ }
552
+ },
553
+ (value) => {
554
+ if (ctx.alive) {
555
+ ctx.onParse({
556
+ t: SerovalNodeType.ReadableStreamError,
557
+ i: id,
558
+ s: undefined,
559
+ l: undefined,
560
+ c: undefined,
561
+ m: undefined,
562
+ p: undefined,
563
+ e: undefined,
564
+ a: undefined,
565
+ f: crossParseStream(ctx, value),
566
+ b: undefined,
567
+ o: undefined,
568
+ }, false);
569
+ popPendingState(ctx);
570
+ }
571
+ },
572
+ );
573
+ }
578
574
 
579
- push();
575
+ function generateReadableStreamNode(
576
+ ctx: StreamingCrossParserContext,
577
+ id: number,
578
+ current: ReadableStream<unknown>,
579
+ ): SerovalReadableStreamConstructorNode {
580
+ pushPendingState(ctx);
581
+ pushReadableStreamState(ctx, id, current.getReader());
580
582
 
581
583
  return {
582
584
  t: SerovalNodeType.ReadableStreamConstructor,
@@ -845,7 +847,7 @@ export default function crossParseStream<T>(
845
847
  ): SerovalNode {
846
848
  const t = typeof current;
847
849
  if (ctx.features & Feature.BigInt && t === 'bigint') {
848
- return createBigIntNode(ctx, current as bigint);
850
+ return createBigIntNode(current as bigint);
849
851
  }
850
852
  switch (t) {
851
853
  case 'boolean':
@@ -71,7 +71,7 @@ function generateNodeList(ctx: CrossParserContext, current: unknown[]): SerovalS
71
71
  for (let i = 0; i < size; i++) {
72
72
  if (i in current) {
73
73
  item = current[i];
74
- if (isIterable(item)) {
74
+ if (isIterable(ctx, item)) {
75
75
  deferred[i] = item;
76
76
  } else {
77
77
  nodes[i] = crossParseSync(ctx, item);
@@ -121,7 +121,7 @@ function generateMapNode(
121
121
  let nodeSize = 0;
122
122
  for (const [key, value] of current.entries()) {
123
123
  // Either key or value might be an iterable
124
- if (isIterable(key) || isIterable(value)) {
124
+ if (isIterable(ctx, key) || isIterable(ctx, value)) {
125
125
  deferredKey[deferredSize] = key;
126
126
  deferredValue[deferredSize] = value;
127
127
  deferredSize++;
@@ -163,7 +163,7 @@ function generateSetNode(
163
163
  let nodeSize = 0;
164
164
  for (const item of current.keys()) {
165
165
  // Iterables are lazy, so the evaluation must be deferred
166
- if (isIterable(item)) {
166
+ if (isIterable(ctx, item)) {
167
167
  deferred[deferredSize++] = item;
168
168
  } else {
169
169
  nodes[nodeSize++] = crossParseSync(ctx, item);
@@ -206,7 +206,7 @@ function generateProperties(
206
206
  for (const key of keys) {
207
207
  item = properties[key];
208
208
  escaped = serializeString(key);
209
- if (isIterable(item)) {
209
+ if (isIterable(ctx, item)) {
210
210
  deferredKeys[deferredSize] = escaped;
211
211
  deferredValues[deferredSize] = item;
212
212
  deferredSize++;
@@ -252,7 +252,7 @@ function generatePlainProperties(
252
252
  for (const key of keys) {
253
253
  item = properties[key];
254
254
  escaped = serializeString(key);
255
- if (isIterable(item)) {
255
+ if (isIterable(ctx, item)) {
256
256
  deferredKeys[deferredSize] = escaped;
257
257
  deferredValues[deferredSize] = item;
258
258
  deferredSize++;
@@ -602,7 +602,7 @@ export default function crossParseSync<T>(
602
602
  ): SerovalSyncNode {
603
603
  const t = typeof current;
604
604
  if (ctx.features & Feature.BigInt && t === 'bigint') {
605
- return createBigIntNode(ctx, current as bigint);
605
+ return createBigIntNode(current as bigint);
606
606
  }
607
607
  switch (t) {
608
608
  case 'boolean':
@@ -1,8 +1,5 @@
1
- import assert from '../assert';
2
- import { Feature } from '../compat';
3
1
  import type { CrossParserContext } from './context';
4
2
  import { serializeString } from '../string';
5
- import UnsupportedTypeError from '../UnsupportedTypeError';
6
3
  import { serializeArrayBuffer } from './primitives';
7
4
  import type {
8
5
  SerovalBlobNode,
@@ -15,7 +12,6 @@ export async function createBlobNode(
15
12
  id: number,
16
13
  current: Blob,
17
14
  ): Promise<SerovalBlobNode> {
18
- assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
19
15
  return {
20
16
  t: SerovalNodeType.Blob,
21
17
  i: id,
@@ -37,7 +33,6 @@ export async function createFileNode(
37
33
  id: number,
38
34
  current: File,
39
35
  ): Promise<SerovalFileNode> {
40
- assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
41
36
  return {
42
37
  t: SerovalNodeType.File,
43
38
  i: id,
@@ -1,4 +1,4 @@
1
- import { Feature } from './compat';
1
+ import { BIGINT_FLAG, Feature } from './compat';
2
2
  import type {
3
3
  ErrorValue,
4
4
  } from '../types';
@@ -82,6 +82,7 @@ export function getErrorOptions(
82
82
  }
83
83
 
84
84
  export function isIterable(
85
+ ctx: BaseParserContext,
85
86
  value: unknown,
86
87
  ): value is Iterable<unknown> {
87
88
  if (!value || typeof value !== 'object') {
@@ -90,23 +91,48 @@ export function isIterable(
90
91
  if (Array.isArray(value)) {
91
92
  return false;
92
93
  }
93
- switch (value.constructor) {
94
- case Map:
95
- case Set:
96
- case Int8Array:
97
- case Int16Array:
98
- case Int32Array:
99
- case Uint8Array:
100
- case Uint16Array:
101
- case Uint32Array:
102
- case Uint8ClampedArray:
103
- case Float32Array:
104
- case Float64Array:
105
- case BigInt64Array:
106
- case BigUint64Array:
107
- return false;
108
- default:
109
- break;
94
+ const currentClass = value.constructor;
95
+ if (ctx.features & Feature.TypedArray) {
96
+ switch (currentClass) {
97
+ case Int8Array:
98
+ case Int16Array:
99
+ case Int32Array:
100
+ case Uint8Array:
101
+ case Uint16Array:
102
+ case Uint32Array:
103
+ case Uint8ClampedArray:
104
+ case Float32Array:
105
+ case Float64Array:
106
+ return false;
107
+ default:
108
+ break;
109
+ }
110
+ }
111
+ // BigInt Typed Arrays
112
+ if ((ctx.features & BIGINT_FLAG) === BIGINT_FLAG) {
113
+ switch (currentClass) {
114
+ case BigInt64Array:
115
+ case BigUint64Array:
116
+ return false;
117
+ default:
118
+ break;
119
+ }
120
+ }
121
+ // ES Collection
122
+ if (ctx.features & Feature.Map && currentClass === Map) {
123
+ return false;
124
+ }
125
+ if (ctx.features & Feature.Set && currentClass === Set) {
126
+ return false;
127
+ }
128
+ if (ctx.features & Feature.WebAPI) {
129
+ switch (currentClass) {
130
+ case Headers:
131
+ case File:
132
+ return false;
133
+ default:
134
+ break;
135
+ }
110
136
  }
111
137
  return Symbol.iterator in value;
112
138
  }
@@ -96,7 +96,7 @@ async function generateNodeList(
96
96
  for (let i = 0; i < size; i++) {
97
97
  if (i in current) {
98
98
  item = current[i];
99
- if (isIterable(item)) {
99
+ if (isIterable(ctx, item)) {
100
100
  deferred[i] = item;
101
101
  } else {
102
102
  nodes[i] = await parseAsync(ctx, item);
@@ -146,7 +146,7 @@ async function generateMapNode(
146
146
  let nodeSize = 0;
147
147
  for (const [key, value] of current.entries()) {
148
148
  // Either key or value might be an iterable
149
- if (isIterable(key) || isIterable(value)) {
149
+ if (isIterable(ctx, key) || isIterable(ctx, value)) {
150
150
  deferredKey[deferredSize] = key;
151
151
  deferredValue[deferredSize] = value;
152
152
  deferredSize++;
@@ -188,7 +188,7 @@ async function generateSetNode(
188
188
  let nodeSize = 0;
189
189
  for (const item of current.keys()) {
190
190
  // Iterables are lazy, so the evaluation must be deferred
191
- if (isIterable(item)) {
191
+ if (isIterable(ctx, item)) {
192
192
  deferred[deferredSize++] = item;
193
193
  } else {
194
194
  nodes[nodeSize++] = await parseAsync(ctx, item);
@@ -231,7 +231,7 @@ async function generateProperties(
231
231
  for (const key of keys) {
232
232
  item = properties[key];
233
233
  escaped = serializeString(key);
234
- if (isIterable(item)) {
234
+ if (isIterable(ctx, item)) {
235
235
  deferredKeys[deferredSize] = escaped;
236
236
  deferredValues[deferredSize] = item;
237
237
  deferredSize++;
@@ -281,7 +281,7 @@ async function generatePlainProperties(
281
281
  for (const key of keys) {
282
282
  item = properties[key];
283
283
  escaped = serializeString(key);
284
- if (isIterable(item)) {
284
+ if (isIterable(ctx, item)) {
285
285
  deferredKeys[deferredSize] = escaped;
286
286
  deferredValues[deferredSize] = item;
287
287
  deferredSize++;
@@ -721,7 +721,7 @@ export default async function parseAsync<T>(
721
721
  ): Promise<SerovalNode> {
722
722
  const t = typeof current;
723
723
  if (ctx.features & Feature.BigInt && t === 'bigint') {
724
- return createBigIntNode(ctx, current as bigint);
724
+ return createBigIntNode(current as bigint);
725
725
  }
726
726
  switch (t) {
727
727
  case 'boolean':
@@ -106,7 +106,7 @@ export function createSymbolNode(
106
106
  if (hasReferenceID(current)) {
107
107
  return createReferenceNode(id, current);
108
108
  }
109
- return createWKSymbolNode(ctx, id, current as WellKnownSymbols);
109
+ return createWKSymbolNode(id, current as WellKnownSymbols);
110
110
  }
111
111
 
112
112
  export function createFunctionNode(
@@ -72,7 +72,7 @@ function generateNodeList(ctx: ParserContext, current: unknown[]): SerovalSyncNo
72
72
  for (let i = 0; i < size; i++) {
73
73
  if (i in current) {
74
74
  item = current[i];
75
- if (isIterable(item)) {
75
+ if (isIterable(ctx, item)) {
76
76
  deferred[i] = item;
77
77
  } else {
78
78
  nodes[i] = parseSync(ctx, item);
@@ -122,7 +122,7 @@ function generateMapNode(
122
122
  let nodeSize = 0;
123
123
  for (const [key, value] of current.entries()) {
124
124
  // Either key or value might be an iterable
125
- if (isIterable(key) || isIterable(value)) {
125
+ if (isIterable(ctx, key) || isIterable(ctx, value)) {
126
126
  deferredKey[deferredSize] = key;
127
127
  deferredValue[deferredSize] = value;
128
128
  deferredSize++;
@@ -164,7 +164,7 @@ function generateSetNode(
164
164
  let nodeSize = 0;
165
165
  for (const item of current.keys()) {
166
166
  // Iterables are lazy, so the evaluation must be deferred
167
- if (isIterable(item)) {
167
+ if (isIterable(ctx, item)) {
168
168
  deferred[deferredSize++] = item;
169
169
  } else {
170
170
  nodes[nodeSize++] = parseSync(ctx, item);
@@ -207,7 +207,7 @@ function generateProperties(
207
207
  for (const key of keys) {
208
208
  item = properties[key];
209
209
  escaped = serializeString(key);
210
- if (isIterable(item)) {
210
+ if (isIterable(ctx, item)) {
211
211
  deferredKeys[deferredSize] = escaped;
212
212
  deferredValues[deferredSize] = item;
213
213
  deferredSize++;
@@ -254,7 +254,7 @@ function generatePlainProperties(
254
254
  for (const key of keys) {
255
255
  item = properties[key];
256
256
  escaped = serializeString(key);
257
- if (isIterable(item)) {
257
+ if (isIterable(ctx, item)) {
258
258
  deferredKeys[deferredSize] = escaped;
259
259
  deferredValues[deferredSize] = item;
260
260
  deferredSize++;
@@ -602,7 +602,7 @@ export default function parseSync<T>(
602
602
  ): SerovalSyncNode {
603
603
  const t = typeof current;
604
604
  if (ctx.features & Feature.BigInt && t === 'bigint') {
605
- return createBigIntNode(ctx, current as bigint);
605
+ return createBigIntNode(current as bigint);
606
606
  }
607
607
  switch (t) {
608
608
  case 'boolean':
@@ -1,8 +1,5 @@
1
- import assert from '../assert';
2
- import { Feature } from '../compat';
3
1
  import type { ParserContext } from './context';
4
2
  import { serializeString } from '../string';
5
- import UnsupportedTypeError from '../UnsupportedTypeError';
6
3
  import { serializeArrayBuffer } from './primitives';
7
4
  import type {
8
5
  SerovalBlobNode,
@@ -15,7 +12,6 @@ export async function createBlobNode(
15
12
  id: number,
16
13
  current: Blob,
17
14
  ): Promise<SerovalBlobNode> {
18
- assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
19
15
  return {
20
16
  t: SerovalNodeType.Blob,
21
17
  i: id,
@@ -37,7 +33,6 @@ export async function createFileNode(
37
33
  id: number,
38
34
  current: File,
39
35
  ): Promise<SerovalFileNode> {
40
- assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
41
36
  return {
42
37
  t: SerovalNodeType.File,
43
38
  i: id,
@@ -1,61 +0,0 @@
1
- /**
2
- * This file is used to represent the minified header script located at ./keys.ts
3
- * If anything, this code is the unminified, readable version of it.
4
- */
5
-
6
- // Global references array. Global because we (ideally) want <script> elements to share it.
7
- self._$ = self._$ || {
8
- // Promise constructor, used to construct deferred Promises
9
- P(success, failure, promise) {
10
- promise = new Promise(function (resolve, reject) {
11
- success = resolve;
12
- failure = reject;
13
- });
14
-
15
- promise.s = success;
16
- promise.f = failure;
17
-
18
- return promise;
19
- },
20
- // This unsets the custom properties of the Promise instance
21
- uP(promise) {
22
- delete promise.s;
23
- delete promise.f;
24
- },
25
- // Promise resolution
26
- Ps(promise, data) {
27
- promise.s(data);
28
- promise.value = data;
29
- this.uP(promise);
30
- },
31
- Pf(promise, data) {
32
- promise.f(data);
33
- this.uP(promise);
34
- },
35
- // Unset stream
36
- uS(stream) {
37
- delete stream.c;
38
- },
39
- Se(stream, type, data, controller) {
40
- controller = stream.c;
41
- switch (type) {
42
- case 0: return controller.enqueue(data);
43
- case 1:
44
- this.uS(stream);
45
- return controller.error(data);
46
- case 2:
47
- this.uS(stream);
48
- return controller.close();
49
- }
50
- },
51
- // ReadableStream constructor
52
- S(stream, controller) {
53
- stream = new ReadableStream({
54
- start: function (c) {
55
- controller = c;
56
- }
57
- });
58
- stream.c = controller;
59
- return stream;
60
- },
61
- };