seroval 0.4.0-alpha.2 → 0.4.0-alpha.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 +314 -217
- package/dist/cjs/development/index.cjs.map +2 -2
- package/dist/cjs/production/index.cjs +2 -2
- package/dist/esm/development/index.mjs +314 -217
- package/dist/esm/development/index.mjs.map +2 -2
- package/dist/esm/production/index.mjs +2 -2
- package/dist/types/compat.d.ts +13 -12
- package/dist/types/index.d.ts +4 -0
- package/dist/types/tree.d.ts +39 -29
- package/dist/types/types.d.ts +2 -2
- package/package.json +2 -2
- package/src/checks.ts +1 -2
- package/src/compat.ts +28 -14
- package/src/index.ts +74 -19
- package/src/tree.ts +260 -203
- package/src/types.ts +3 -3
package/dist/types/tree.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { AsyncServerValue, PrimitiveValue, ServerValue
|
|
2
|
-
import { Feature } from './compat';
|
|
1
|
+
import { AsyncServerValue, PrimitiveValue, ServerValue } from './types';
|
|
3
2
|
interface IndexAssignment {
|
|
4
3
|
type: 'index';
|
|
5
4
|
source: string;
|
|
@@ -17,24 +16,29 @@ interface SetAssignment {
|
|
|
17
16
|
value: string;
|
|
18
17
|
}
|
|
19
18
|
export type Assignment = IndexAssignment | MapAssignment | SetAssignment;
|
|
19
|
+
export interface ParserContext {
|
|
20
|
+
refs: Map<unknown, number>;
|
|
21
|
+
markedRefs: Set<number>;
|
|
22
|
+
features: number;
|
|
23
|
+
}
|
|
20
24
|
export interface SerializationContext {
|
|
21
25
|
stack: number[];
|
|
22
|
-
refs: Map<unknown, number>;
|
|
23
26
|
validRefs: Map<number, number>;
|
|
24
|
-
markedRefs:
|
|
27
|
+
markedRefs: Set<number>;
|
|
25
28
|
vars: string[];
|
|
26
29
|
assignments: Assignment[];
|
|
27
|
-
features:
|
|
30
|
+
features: number;
|
|
28
31
|
}
|
|
29
32
|
export interface Options {
|
|
30
33
|
target: string | string[];
|
|
31
34
|
}
|
|
32
|
-
export declare function
|
|
35
|
+
export declare function createParserContext(options?: Partial<Options>): ParserContext;
|
|
36
|
+
export interface SerializationOptions {
|
|
37
|
+
markedRefs: number[] | Set<number>;
|
|
38
|
+
features: number;
|
|
39
|
+
}
|
|
40
|
+
export declare function createSerializationContext(options: SerializationOptions): SerializationContext;
|
|
33
41
|
export declare function resolvePatches(ctx: SerializationContext): string | undefined;
|
|
34
|
-
/**
|
|
35
|
-
* Creates a reference ID from the given values
|
|
36
|
-
*/
|
|
37
|
-
export declare function createRef(ctx: SerializationContext, index: unknown): number;
|
|
38
42
|
/**
|
|
39
43
|
* Creates the reference param (identifier) from the given reference ID
|
|
40
44
|
* Calling this function means the value has been referenced somewhere
|
|
@@ -42,25 +46,31 @@ export declare function createRef(ctx: SerializationContext, index: unknown): nu
|
|
|
42
46
|
export declare function getRefParam(ctx: SerializationContext, index: number): string;
|
|
43
47
|
declare const enum SerovalNodeType {
|
|
44
48
|
Primitive = 0,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
BigInt = 1,
|
|
50
|
+
Reference = 2,
|
|
51
|
+
Date = 3,
|
|
52
|
+
RegExp = 4,
|
|
53
|
+
Set = 5,
|
|
54
|
+
Map = 6,
|
|
55
|
+
Array = 7,
|
|
56
|
+
Object = 8,
|
|
57
|
+
NullConstructor = 9,
|
|
58
|
+
Promise = 10,
|
|
59
|
+
Error = 11,
|
|
60
|
+
AggregateError = 12,
|
|
61
|
+
Iterable = 13,
|
|
62
|
+
TypedArray = 14,
|
|
63
|
+
BigIntTypedArray = 15
|
|
58
64
|
}
|
|
59
65
|
type SerovalPrimitiveNode = [type: SerovalNodeType.Primitive, value: PrimitiveValue];
|
|
60
66
|
type SerovalReferenceNode = [type: SerovalNodeType.Reference, value: number];
|
|
61
|
-
type SerovalSemiPrimitiveNode = [type: SerovalNodeType.
|
|
67
|
+
type SerovalSemiPrimitiveNode = [type: SerovalNodeType.BigInt, value: string] | [type: SerovalNodeType.Date, value: string, id: number] | [type: SerovalNodeType.RegExp, value: string, id: number] | [
|
|
62
68
|
type: SerovalNodeType.TypedArray,
|
|
63
|
-
value: [constructor: string, array:
|
|
69
|
+
value: [constructor: string, array: string, byteOffset: number],
|
|
70
|
+
id: number
|
|
71
|
+
] | [
|
|
72
|
+
type: SerovalNodeType.BigIntTypedArray,
|
|
73
|
+
value: [constructor: string, array: string, byteOffset: number],
|
|
64
74
|
id: number
|
|
65
75
|
];
|
|
66
76
|
type SerovalDictionaryNode = [key: string[], value: SerovalNode[], size: number];
|
|
@@ -104,9 +114,9 @@ type SerovalIterableNode = [
|
|
|
104
114
|
],
|
|
105
115
|
id: number
|
|
106
116
|
];
|
|
107
|
-
type SerovalNode = SerovalPrimitiveNode | SerovalReferenceNode | SerovalSemiPrimitiveNode | SerovalSetNode | SerovalMapNode | SerovalArrayNode | SerovalObjectNode | SerovalNullConstructorNode | SerovalPromiseNode | SerovalErrorNode | SerovalAggregateErrorNode | SerovalIterableNode;
|
|
108
|
-
export declare function
|
|
109
|
-
export declare function
|
|
110
|
-
export declare function serializePrimitive(
|
|
117
|
+
export type SerovalNode = SerovalPrimitiveNode | SerovalReferenceNode | SerovalSemiPrimitiveNode | SerovalSetNode | SerovalMapNode | SerovalArrayNode | SerovalObjectNode | SerovalNullConstructorNode | SerovalPromiseNode | SerovalErrorNode | SerovalAggregateErrorNode | SerovalIterableNode;
|
|
118
|
+
export declare function parseSync(ctx: ParserContext, current: ServerValue): readonly [SerovalNode, number, boolean];
|
|
119
|
+
export declare function parseAsync(ctx: ParserContext, current: AsyncServerValue): Promise<readonly [SerovalNode, number, boolean]>;
|
|
120
|
+
export declare function serializePrimitive(value: PrimitiveValue): string | number | null;
|
|
111
121
|
export declare function serializeTree(ctx: SerializationContext, [type, value, id]: SerovalNode): string;
|
|
112
122
|
export {};
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type PrimitiveValue = boolean | string | number | undefined | null
|
|
1
|
+
export type PrimitiveValue = boolean | string | number | undefined | null;
|
|
2
2
|
export type ErrorValue = Error | AggregateError | EvalError | RangeError | ReferenceError | TypeError | SyntaxError | URIError;
|
|
3
3
|
export type TypedArrayValue = Int8Array | Int16Array | Int32Array | Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array | BigInt64Array | BigUint64Array;
|
|
4
|
-
export type SemiPrimitiveValue = RegExp | Date | TypedArrayValue;
|
|
4
|
+
export type SemiPrimitiveValue = RegExp | Date | TypedArrayValue | bigint;
|
|
5
5
|
export type CommonServerValue = PrimitiveValue | SemiPrimitiveValue | ErrorValue;
|
|
6
6
|
export type ServerValue = CommonServerValue | Array<ServerValue> | readonly ServerValue[] | Iterable<ServerValue> | {
|
|
7
7
|
[key: string | number]: ServerValue;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "seroval",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.4.0-alpha.
|
|
4
|
+
"version": "0.4.0-alpha.4",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
7
7
|
"src"
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"typesVersions": {
|
|
65
65
|
"*": {}
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "1e96ac1ab8304fb09ac7a1bc451b7768f12b7f6b"
|
|
68
68
|
}
|
package/src/checks.ts
CHANGED
|
@@ -6,8 +6,7 @@ export function isPrimitive(current: unknown): current is PrimitiveValue {
|
|
|
6
6
|
}
|
|
7
7
|
const type = typeof current;
|
|
8
8
|
return type === 'number'
|
|
9
|
-
|| type === 'string'
|
|
10
|
-
|| type === 'bigint';
|
|
9
|
+
|| type === 'string';
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
export function isPromise<T>(obj: unknown): obj is PromiseLike<T> {
|
package/src/compat.ts
CHANGED
|
@@ -40,17 +40,18 @@ export interface PlatformVersion {
|
|
|
40
40
|
export type Platform = keyof PlatformVersion;
|
|
41
41
|
|
|
42
42
|
export const enum Feature {
|
|
43
|
-
AggregateError,
|
|
44
|
-
ArrayPrototypeValues,
|
|
45
|
-
ArrowFunction,
|
|
46
|
-
BigInt,
|
|
47
|
-
Map,
|
|
48
|
-
MethodShorthand,
|
|
49
|
-
ObjectAssign,
|
|
50
|
-
Promise,
|
|
51
|
-
Set,
|
|
52
|
-
SymbolIterator,
|
|
53
|
-
TypedArray,
|
|
43
|
+
AggregateError = 0x01,
|
|
44
|
+
ArrayPrototypeValues = 0x02,
|
|
45
|
+
ArrowFunction = 0x04,
|
|
46
|
+
BigInt = 0x08,
|
|
47
|
+
Map = 0x10,
|
|
48
|
+
MethodShorthand = 0x20,
|
|
49
|
+
ObjectAssign = 0x40,
|
|
50
|
+
Promise = 0x80,
|
|
51
|
+
Set = 0x100,
|
|
52
|
+
SymbolIterator = 0x200,
|
|
53
|
+
TypedArray = 0x400,
|
|
54
|
+
BigIntTypedArray = 0x800,
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
type VersionTable = {
|
|
@@ -201,6 +202,19 @@ const VERSION_TABLE: VersionTable = {
|
|
|
201
202
|
deno: [1, 0, 0],
|
|
202
203
|
node: [0, 10, 0],
|
|
203
204
|
},
|
|
205
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array#browser_compatibility
|
|
206
|
+
[Feature.BigIntTypedArray]: {
|
|
207
|
+
es: [2020, 0, 0],
|
|
208
|
+
chrome: [67, 0, 0],
|
|
209
|
+
edge: [79, 0, 0],
|
|
210
|
+
firefox: [68, 0, 0],
|
|
211
|
+
opera: [54, 6, 0],
|
|
212
|
+
safari: [15, 1, 0],
|
|
213
|
+
ios: [15, 2, 0],
|
|
214
|
+
samsung: [9, 0, 0],
|
|
215
|
+
deno: [1, 0, 0],
|
|
216
|
+
node: [10, 4, 0],
|
|
217
|
+
},
|
|
204
218
|
};
|
|
205
219
|
|
|
206
220
|
const TARGET_REGEX = /^(es|chrome|edge|safari|firefox|opera|ios|samsung|deno|node)([0-9]+(\.[0-9]+(\.[0-9]+)?)?)$/i;
|
|
@@ -226,9 +240,9 @@ function getTargetVersions(targets: string | string[]): Target[] {
|
|
|
226
240
|
return [parseTarget(targets)];
|
|
227
241
|
}
|
|
228
242
|
|
|
229
|
-
export function parseTargets(targets: string | string[]):
|
|
243
|
+
export function parseTargets(targets: string | string[]): number {
|
|
230
244
|
const parsed = getTargetVersions(targets);
|
|
231
|
-
|
|
245
|
+
let flags = 0;
|
|
232
246
|
|
|
233
247
|
for (const key in VERSION_TABLE) {
|
|
234
248
|
const base = VERSION_TABLE[key as unknown as Feature];
|
|
@@ -238,7 +252,7 @@ export function parseTargets(targets: string | string[]): Set<Feature> {
|
|
|
238
252
|
flag = flag && !!baseVersion && (compareVersion(baseVersion, version) <= 0);
|
|
239
253
|
}
|
|
240
254
|
if (flag) {
|
|
241
|
-
flags
|
|
255
|
+
flags |= Number(key);
|
|
242
256
|
}
|
|
243
257
|
}
|
|
244
258
|
|
package/src/index.ts
CHANGED
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
import { isPrimitive } from './checks';
|
|
3
3
|
import { Feature } from './compat';
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
createParserContext,
|
|
6
6
|
createSerializationContext,
|
|
7
|
-
generateTreeAsync,
|
|
8
|
-
generateTreeSync,
|
|
9
7
|
getRefParam,
|
|
10
8
|
Options,
|
|
9
|
+
parseAsync,
|
|
10
|
+
parseSync,
|
|
11
11
|
resolvePatches,
|
|
12
12
|
SerializationContext,
|
|
13
13
|
serializePrimitive,
|
|
14
14
|
serializeTree,
|
|
15
|
+
SerovalNode,
|
|
15
16
|
} from './tree';
|
|
16
17
|
import {
|
|
17
18
|
AsyncServerValue,
|
|
18
|
-
NonPrimitiveServerValue,
|
|
19
19
|
PrimitiveValue,
|
|
20
20
|
ServerValue,
|
|
21
21
|
CommonServerValue,
|
|
@@ -32,9 +32,10 @@ export {
|
|
|
32
32
|
ErrorValue,
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
function finalize
|
|
35
|
+
function finalize(
|
|
36
36
|
ctx: SerializationContext,
|
|
37
|
-
|
|
37
|
+
rootID: number,
|
|
38
|
+
isObject: boolean,
|
|
38
39
|
result: string,
|
|
39
40
|
) {
|
|
40
41
|
// Shared references detected
|
|
@@ -43,7 +44,7 @@ function finalize<T extends NonPrimitiveServerValue<ServerValue | AsyncServerVal
|
|
|
43
44
|
let body = result;
|
|
44
45
|
if (patches) {
|
|
45
46
|
// Get (or create) a ref from the source
|
|
46
|
-
const index = getRefParam(ctx,
|
|
47
|
+
const index = getRefParam(ctx, rootID);
|
|
47
48
|
if (result.startsWith(`${index}=`)) {
|
|
48
49
|
body = `${result},${patches}${index}`;
|
|
49
50
|
} else {
|
|
@@ -54,7 +55,7 @@ function finalize<T extends NonPrimitiveServerValue<ServerValue | AsyncServerVal
|
|
|
54
55
|
? ctx.vars.join(',')
|
|
55
56
|
: ctx.vars[0];
|
|
56
57
|
// Source is probably already assigned
|
|
57
|
-
if (ctx.features
|
|
58
|
+
if (ctx.features & Feature.ArrowFunction) {
|
|
58
59
|
params = ctx.vars.length > 1 || ctx.vars.length === 0
|
|
59
60
|
? `(${params})`
|
|
60
61
|
: params;
|
|
@@ -62,7 +63,7 @@ function finalize<T extends NonPrimitiveServerValue<ServerValue | AsyncServerVal
|
|
|
62
63
|
}
|
|
63
64
|
return `(function(${params}){return ${body}})()`;
|
|
64
65
|
}
|
|
65
|
-
if (
|
|
66
|
+
if (isObject) {
|
|
66
67
|
return `(${result})`;
|
|
67
68
|
}
|
|
68
69
|
return result;
|
|
@@ -72,26 +73,28 @@ export function serialize<T extends ServerValue>(
|
|
|
72
73
|
source: T,
|
|
73
74
|
options?: Partial<Options>,
|
|
74
75
|
) {
|
|
75
|
-
const ctx =
|
|
76
|
+
const ctx = createParserContext(options);
|
|
76
77
|
if (isPrimitive(source)) {
|
|
77
|
-
return serializePrimitive(
|
|
78
|
+
return String(serializePrimitive(source));
|
|
78
79
|
}
|
|
79
|
-
const tree =
|
|
80
|
-
const
|
|
81
|
-
|
|
80
|
+
const [tree, rootID, isObject] = parseSync(ctx, source);
|
|
81
|
+
const serial = createSerializationContext(ctx);
|
|
82
|
+
const result = serializeTree(serial, tree);
|
|
83
|
+
return finalize(serial, rootID, isObject, result);
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
export async function serializeAsync<T extends AsyncServerValue>(
|
|
85
87
|
source: T,
|
|
86
88
|
options?: Partial<Options>,
|
|
87
89
|
) {
|
|
88
|
-
const ctx =
|
|
90
|
+
const ctx = createParserContext(options);
|
|
89
91
|
if (isPrimitive(source)) {
|
|
90
|
-
return serializePrimitive(
|
|
92
|
+
return String(serializePrimitive(source));
|
|
91
93
|
}
|
|
92
|
-
const tree = await
|
|
93
|
-
const
|
|
94
|
-
|
|
94
|
+
const [tree, rootID, isObject] = await parseAsync(ctx, source);
|
|
95
|
+
const serial = createSerializationContext(ctx);
|
|
96
|
+
const result = serializeTree(serial, tree);
|
|
97
|
+
return finalize(serial, rootID, isObject, result);
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
export function deserialize<T extends AsyncServerValue>(source: string): T {
|
|
@@ -99,4 +102,56 @@ export function deserialize<T extends AsyncServerValue>(source: string): T {
|
|
|
99
102
|
return (0, eval)(source) as T;
|
|
100
103
|
}
|
|
101
104
|
|
|
105
|
+
type SerovalJSON = [
|
|
106
|
+
tree: SerovalNode,
|
|
107
|
+
root: number,
|
|
108
|
+
isObject: boolean,
|
|
109
|
+
feature: number,
|
|
110
|
+
markedRefs: number[],
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
export function toJSON<T extends ServerValue>(
|
|
114
|
+
source: T,
|
|
115
|
+
options?: Partial<Options>,
|
|
116
|
+
) {
|
|
117
|
+
const ctx = createParserContext(options);
|
|
118
|
+
const [tree, root, isObject] = parseSync(ctx, source);
|
|
119
|
+
return JSON.stringify([
|
|
120
|
+
tree,
|
|
121
|
+
root,
|
|
122
|
+
isObject,
|
|
123
|
+
ctx.features,
|
|
124
|
+
[...ctx.markedRefs],
|
|
125
|
+
]);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export async function toJSONAsync<T extends AsyncServerValue>(
|
|
129
|
+
source: T,
|
|
130
|
+
options?: Partial<Options>,
|
|
131
|
+
) {
|
|
132
|
+
const ctx = createParserContext(options);
|
|
133
|
+
const [tree, root, isObject] = await parseAsync(ctx, source);
|
|
134
|
+
return JSON.stringify([
|
|
135
|
+
tree,
|
|
136
|
+
root,
|
|
137
|
+
isObject,
|
|
138
|
+
ctx.features,
|
|
139
|
+
[...ctx.markedRefs],
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function compileJSON(source: string): string {
|
|
144
|
+
const parsed = JSON.parse(source) as SerovalJSON;
|
|
145
|
+
const serial = createSerializationContext({
|
|
146
|
+
features: parsed[3],
|
|
147
|
+
markedRefs: parsed[4],
|
|
148
|
+
});
|
|
149
|
+
const result = serializeTree(serial, parsed[0]);
|
|
150
|
+
return finalize(serial, parsed[1], parsed[2], result);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function fromJSON<T extends AsyncServerValue>(source: string): T {
|
|
154
|
+
return deserialize<T>(compileJSON(source));
|
|
155
|
+
}
|
|
156
|
+
|
|
102
157
|
export default serialize;
|