seroval 1.0.3 → 1.0.4
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/cjs/development/index.cjs +330 -225
- package/dist/cjs/development/index.cjs.map +3 -3
- package/dist/cjs/production/index.cjs +17 -3
- package/dist/esm/development/index.mjs +330 -225
- package/dist/esm/development/index.mjs.map +3 -3
- package/dist/esm/production/index.mjs +17 -3
- package/dist/types/core/base-primitives.d.ts.map +1 -1
- package/dist/types/core/context/deserializer.d.ts.map +1 -1
- package/dist/types/core/context/parser/async.d.ts.map +1 -1
- package/dist/types/core/context/parser/sync.d.ts.map +1 -1
- package/dist/types/core/context/parser.d.ts.map +1 -1
- package/dist/types/core/context/serializer.d.ts.map +1 -1
- package/dist/types/core/errors.d.ts +38 -0
- package/dist/types/core/errors.d.ts.map +1 -0
- package/dist/types/core/reference.d.ts.map +1 -1
- package/dist/types/core/tree/serializer.d.ts.map +1 -1
- package/dist/types/core/utils/typed-array.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/core/base-primitives.ts +0 -5
- package/src/core/context/deserializer.ts +86 -76
- package/src/core/context/parser/async.ts +30 -26
- package/src/core/context/parser/sync.ts +30 -26
- package/src/core/context/parser.ts +3 -10
- package/src/core/context/serializer.ts +104 -95
- package/src/core/errors.ts +99 -0
- package/src/core/reference.ts +6 -2
- package/src/core/tree/serializer.ts +4 -3
- package/src/core/utils/typed-array.ts +3 -1
- package/src/index.ts +1 -0
- package/dist/types/core/UnsupportedTypeError.d.ts +0 -5
- package/dist/types/core/UnsupportedTypeError.d.ts.map +0 -1
- package/src/core/UnsupportedTypeError.ts +0 -7
|
@@ -6,6 +6,11 @@ import {
|
|
|
6
6
|
SerovalNodeType,
|
|
7
7
|
SerovalObjectFlags,
|
|
8
8
|
} from '../constants';
|
|
9
|
+
import {
|
|
10
|
+
SerovalMissingPluginError,
|
|
11
|
+
SerovalSerializationError,
|
|
12
|
+
SerovalUnsupportedNodeError,
|
|
13
|
+
} from '../errors';
|
|
9
14
|
import { REFERENCES_KEY } from '../keys';
|
|
10
15
|
import type { Plugin, PluginAccessOptions, SerovalMode } from '../plugin';
|
|
11
16
|
import { SpecialReference } from '../special-reference';
|
|
@@ -446,19 +451,19 @@ export default abstract class BaseSerializerContext
|
|
|
446
451
|
): string {
|
|
447
452
|
if (typeof key === 'string') {
|
|
448
453
|
const check = Number(key);
|
|
449
|
-
const isIdentifier =
|
|
454
|
+
const isIdentifier =
|
|
450
455
|
// Test if key is a valid positive number or JS identifier
|
|
451
456
|
// so that we don't have to serialize the key and wrap with brackets
|
|
452
|
-
check >= 0
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
457
|
+
(check >= 0 &&
|
|
458
|
+
// It's also important to consider that if the key is
|
|
459
|
+
// indeed numeric, we need to make sure that when
|
|
460
|
+
// converted back into a string, it's still the same
|
|
461
|
+
// to the original key. This allows us to differentiate
|
|
462
|
+
// keys that has numeric formats but in a different
|
|
463
|
+
// format, which can cause unintentional key declaration
|
|
464
|
+
// Example: { 0x1: 1 } vs { '0x1': 1 }
|
|
465
|
+
check.toString() === key) ||
|
|
466
|
+
isValidIdentifier(key);
|
|
462
467
|
if (this.isIndexedValueInStack(val)) {
|
|
463
468
|
const refParam = this.getRefParam((val as SerovalIndexedValueNode).i);
|
|
464
469
|
this.markRef(source.i);
|
|
@@ -528,19 +533,19 @@ export default abstract class BaseSerializerContext
|
|
|
528
533
|
): void {
|
|
529
534
|
const serialized = this.serialize(value);
|
|
530
535
|
const check = Number(key);
|
|
531
|
-
const isIdentifier =
|
|
536
|
+
const isIdentifier =
|
|
532
537
|
// Test if key is a valid positive number or JS identifier
|
|
533
538
|
// so that we don't have to serialize the key and wrap with brackets
|
|
534
|
-
check >= 0
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
539
|
+
(check >= 0 &&
|
|
540
|
+
// It's also important to consider that if the key is
|
|
541
|
+
// indeed numeric, we need to make sure that when
|
|
542
|
+
// converted back into a string, it's still the same
|
|
543
|
+
// to the original key. This allows us to differentiate
|
|
544
|
+
// keys that has numeric formats but in a different
|
|
545
|
+
// format, which can cause unintentional key declaration
|
|
546
|
+
// Example: { 0x1: 1 } vs { '0x1': 1 }
|
|
547
|
+
check.toString() === key) ||
|
|
548
|
+
isValidIdentifier(key);
|
|
544
549
|
if (this.isIndexedValueInStack(value)) {
|
|
545
550
|
// Strict identifier check, make sure
|
|
546
551
|
// that it isn't numeric (except NaN)
|
|
@@ -899,7 +904,7 @@ export default abstract class BaseSerializerContext
|
|
|
899
904
|
}
|
|
900
905
|
}
|
|
901
906
|
}
|
|
902
|
-
throw new
|
|
907
|
+
throw new SerovalMissingPluginError(node.c);
|
|
903
908
|
}
|
|
904
909
|
|
|
905
910
|
private getConstructor(node: SerovalNodeWithID): string {
|
|
@@ -1155,78 +1160,82 @@ export default abstract class BaseSerializerContext
|
|
|
1155
1160
|
}
|
|
1156
1161
|
|
|
1157
1162
|
serialize(node: SerovalNode): string {
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1163
|
+
try {
|
|
1164
|
+
switch (node.t) {
|
|
1165
|
+
case SerovalNodeType.Constant:
|
|
1166
|
+
return CONSTANT_STRING[node.s];
|
|
1167
|
+
case SerovalNodeType.Number:
|
|
1168
|
+
return '' + node.s;
|
|
1169
|
+
case SerovalNodeType.String:
|
|
1170
|
+
return '"' + node.s + '"';
|
|
1171
|
+
case SerovalNodeType.BigInt:
|
|
1172
|
+
return node.s + 'n';
|
|
1173
|
+
case SerovalNodeType.IndexedValue:
|
|
1174
|
+
return this.getRefParam(node.i);
|
|
1175
|
+
case SerovalNodeType.Reference:
|
|
1176
|
+
return this.serializeReference(node);
|
|
1177
|
+
case SerovalNodeType.Array:
|
|
1178
|
+
return this.serializeArray(node);
|
|
1179
|
+
case SerovalNodeType.Object:
|
|
1180
|
+
return this.serializeObject(node);
|
|
1181
|
+
case SerovalNodeType.NullConstructor:
|
|
1182
|
+
return this.serializeNullConstructor(node);
|
|
1183
|
+
case SerovalNodeType.Date:
|
|
1184
|
+
return this.serializeDate(node);
|
|
1185
|
+
case SerovalNodeType.RegExp:
|
|
1186
|
+
return this.serializeRegExp(node);
|
|
1187
|
+
case SerovalNodeType.Set:
|
|
1188
|
+
return this.serializeSet(node);
|
|
1189
|
+
case SerovalNodeType.Map:
|
|
1190
|
+
return this.serializeMap(node);
|
|
1191
|
+
case SerovalNodeType.ArrayBuffer:
|
|
1192
|
+
return this.serializeArrayBuffer(node);
|
|
1193
|
+
case SerovalNodeType.BigIntTypedArray:
|
|
1194
|
+
case SerovalNodeType.TypedArray:
|
|
1195
|
+
return this.serializeTypedArray(node);
|
|
1196
|
+
case SerovalNodeType.DataView:
|
|
1197
|
+
return this.serializeDataView(node);
|
|
1198
|
+
case SerovalNodeType.AggregateError:
|
|
1199
|
+
return this.serializeAggregateError(node);
|
|
1200
|
+
case SerovalNodeType.Error:
|
|
1201
|
+
return this.serializeError(node);
|
|
1202
|
+
case SerovalNodeType.Promise:
|
|
1203
|
+
return this.serializePromise(node);
|
|
1204
|
+
case SerovalNodeType.WKSymbol:
|
|
1205
|
+
return this.serializeWellKnownSymbol(node);
|
|
1206
|
+
case SerovalNodeType.Boxed:
|
|
1207
|
+
return this.serializeBoxed(node);
|
|
1208
|
+
case SerovalNodeType.PromiseConstructor:
|
|
1209
|
+
return this.serializePromiseConstructor(node);
|
|
1210
|
+
case SerovalNodeType.PromiseResolve:
|
|
1211
|
+
return this.serializePromiseResolve(node);
|
|
1212
|
+
case SerovalNodeType.PromiseReject:
|
|
1213
|
+
return this.serializePromiseReject(node);
|
|
1214
|
+
case SerovalNodeType.Plugin:
|
|
1215
|
+
return this.serializePlugin(node);
|
|
1216
|
+
case SerovalNodeType.SpecialReference:
|
|
1217
|
+
return this.serializeSpecialReference(node);
|
|
1218
|
+
case SerovalNodeType.IteratorFactory:
|
|
1219
|
+
return this.serializeIteratorFactory(node);
|
|
1220
|
+
case SerovalNodeType.IteratorFactoryInstance:
|
|
1221
|
+
return this.serializeIteratorFactoryInstance(node);
|
|
1222
|
+
case SerovalNodeType.AsyncIteratorFactory:
|
|
1223
|
+
return this.serializeAsyncIteratorFactory(node);
|
|
1224
|
+
case SerovalNodeType.AsyncIteratorFactoryInstance:
|
|
1225
|
+
return this.serializeAsyncIteratorFactoryInstance(node);
|
|
1226
|
+
case SerovalNodeType.StreamConstructor:
|
|
1227
|
+
return this.serializeStreamConstructor(node);
|
|
1228
|
+
case SerovalNodeType.StreamNext:
|
|
1229
|
+
return this.serializeStreamNext(node);
|
|
1230
|
+
case SerovalNodeType.StreamThrow:
|
|
1231
|
+
return this.serializeStreamThrow(node);
|
|
1232
|
+
case SerovalNodeType.StreamReturn:
|
|
1233
|
+
return this.serializeStreamReturn(node);
|
|
1234
|
+
default:
|
|
1235
|
+
throw new SerovalUnsupportedNodeError(node);
|
|
1236
|
+
}
|
|
1237
|
+
} catch (error) {
|
|
1238
|
+
throw new SerovalSerializationError(error);
|
|
1230
1239
|
}
|
|
1231
1240
|
}
|
|
1232
1241
|
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { serializeString } from './string';
|
|
2
|
+
import { SerovalNode } from './types';
|
|
3
|
+
|
|
4
|
+
const { toString: objectToString } = /* @__PURE__ */ Object.prototype;
|
|
5
|
+
|
|
6
|
+
function getErrorMessage(type: string, cause: any): string {
|
|
7
|
+
if (cause instanceof Error) {
|
|
8
|
+
return `Seroval caught an error during the ${type} process.
|
|
9
|
+
|
|
10
|
+
${cause.name}
|
|
11
|
+
${cause.message}
|
|
12
|
+
|
|
13
|
+
- For more information, please check the "cause" property of this error.
|
|
14
|
+
- If you believe this is an error in Seroval, please submit an issue at https://github.com/lxsmnsyc/seroval/issues/new`;
|
|
15
|
+
}
|
|
16
|
+
return `Seroval caught an error during the ${type} process.
|
|
17
|
+
|
|
18
|
+
"${objectToString.call(cause)}"
|
|
19
|
+
|
|
20
|
+
For more information, please check the "cause" property of this error.`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class SerovalError extends Error {
|
|
24
|
+
constructor(type: string, public cause: any) {
|
|
25
|
+
super(getErrorMessage(type, cause));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class SerovalParserError extends SerovalError {
|
|
30
|
+
constructor(cause: any) {
|
|
31
|
+
super('parsing', cause);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class SerovalSerializationError extends SerovalError {
|
|
36
|
+
constructor(cause: any) {
|
|
37
|
+
super('serialization', cause);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class SerovalDeserializationError extends SerovalError {
|
|
42
|
+
constructor(cause: any) {
|
|
43
|
+
super('deserialization', cause);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class SerovalUnsupportedTypeError extends Error {
|
|
48
|
+
constructor(public value: unknown) {
|
|
49
|
+
super(
|
|
50
|
+
`The value ${objectToString.call(value)} of type "${typeof value}" cannot be parsed/serialized.
|
|
51
|
+
|
|
52
|
+
There are few workarounds for this problem:
|
|
53
|
+
- Transform the value in a way that it can be serialized.
|
|
54
|
+
- If the reference is present on multiple runtimes (isomorphic), you can use the Reference API to map the references.`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class SerovalUnsupportedNodeError extends Error {
|
|
60
|
+
constructor(node: SerovalNode) {
|
|
61
|
+
super('Unsupported node type "' + node.t + '".');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export class SerovalMissingPluginError extends Error {
|
|
66
|
+
constructor(tag: string) {
|
|
67
|
+
super('Missing plugin for tag "' + tag + '".');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export class SerovalMissingInstanceError extends Error {
|
|
72
|
+
constructor(tag: string) {
|
|
73
|
+
super('Missing "' + tag + '" instance.');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class SerovalMissingReferenceError extends Error {
|
|
78
|
+
constructor(public value: unknown) {
|
|
79
|
+
super(
|
|
80
|
+
'Missing reference for the value "' +
|
|
81
|
+
objectToString.call(value) +
|
|
82
|
+
'" of type "' +
|
|
83
|
+
typeof value +
|
|
84
|
+
'"',
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class SerovalMissingReferenceForIdError extends Error {
|
|
90
|
+
constructor(id: string) {
|
|
91
|
+
super('Missing reference for id "' + serializeString(id) + '"');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export class SerovalUnknownTypedArrayError extends Error {
|
|
96
|
+
constructor(name: string) {
|
|
97
|
+
super('Unknown TypedArray "' + name + '"');
|
|
98
|
+
}
|
|
99
|
+
}
|
package/src/core/reference.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import assert from './utils/assert';
|
|
2
2
|
import { REFERENCES_KEY } from './keys';
|
|
3
|
+
import {
|
|
4
|
+
SerovalMissingReferenceError,
|
|
5
|
+
SerovalMissingReferenceForIdError,
|
|
6
|
+
} from '..';
|
|
3
7
|
|
|
4
8
|
const REFERENCE = new Map<unknown, string>();
|
|
5
9
|
const INV_REFERENCE = new Map<string, unknown>();
|
|
@@ -19,12 +23,12 @@ export function hasReference(id: string): boolean {
|
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
export function getReferenceID<T>(value: T): string {
|
|
22
|
-
assert(hasReferenceID(value), new
|
|
26
|
+
assert(hasReferenceID(value), new SerovalMissingReferenceError(value));
|
|
23
27
|
return REFERENCE.get(value)!;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
export function getReference<T>(id: string): T {
|
|
27
|
-
assert(hasReference(id), new
|
|
31
|
+
assert(hasReference(id), new SerovalMissingReferenceForIdError(id));
|
|
28
32
|
return INV_REFERENCE.get(id) as T;
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -9,6 +9,7 @@ import BaseSerializerContext from '../context/serializer';
|
|
|
9
9
|
import getIdentifier from '../utils/get-identifier';
|
|
10
10
|
import type { SerovalMode } from '../plugin';
|
|
11
11
|
import { SerovalNodeType } from '../constants';
|
|
12
|
+
import { SerovalUnsupportedNodeError } from '../errors';
|
|
12
13
|
|
|
13
14
|
export type VanillaSerializerContextOptions = BaseSerializerContextOptions;
|
|
14
15
|
|
|
@@ -61,15 +62,15 @@ export default class VanillaSerializerContext extends BaseSerializerContext {
|
|
|
61
62
|
protected serializePromiseConstructor(
|
|
62
63
|
node: SerovalPromiseConstructorNode,
|
|
63
64
|
): string {
|
|
64
|
-
throw new
|
|
65
|
+
throw new SerovalUnsupportedNodeError(node);
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
protected serializePromiseResolve(node: SerovalPromiseResolveNode): string {
|
|
68
|
-
throw new
|
|
69
|
+
throw new SerovalUnsupportedNodeError(node);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
protected serializePromiseReject(node: SerovalPromiseRejectNode): string {
|
|
72
|
-
throw new
|
|
73
|
+
throw new SerovalUnsupportedNodeError(node);
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
serializeTop(tree: SerovalNode): string {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { SerovalUnknownTypedArrayError } from '../errors';
|
|
2
|
+
|
|
1
3
|
type TypedArrayConstructor =
|
|
2
4
|
| Int8ArrayConstructor
|
|
3
5
|
| Int16ArrayConstructor
|
|
@@ -49,6 +51,6 @@ export function getTypedArrayConstructor(name: string): TypedArrayConstructor {
|
|
|
49
51
|
case 'BigUint64Array':
|
|
50
52
|
return BigUint64Array;
|
|
51
53
|
default:
|
|
52
|
-
throw new
|
|
54
|
+
throw new SerovalUnknownTypedArrayError(name);
|
|
53
55
|
}
|
|
54
56
|
}
|
package/src/index.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UnsupportedTypeError.d.ts","sourceRoot":"","sources":["../../../src/core/UnsupportedTypeError.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,KAAK;IAClC,KAAK,EAAE,OAAO;gBAAd,KAAK,EAAE,OAAO;CAGlC"}
|