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.
@@ -1,5 +1,4 @@
1
- import { AsyncServerValue, PrimitiveValue, ServerValue, TypedArrayValue } from './types';
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: boolean[];
27
+ markedRefs: Set<number>;
25
28
  vars: string[];
26
29
  assignments: Assignment[];
27
- features: Set<Feature>;
30
+ features: number;
28
31
  }
29
32
  export interface Options {
30
33
  target: string | string[];
31
34
  }
32
- export declare function createSerializationContext(options?: Partial<Options>): SerializationContext;
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
- Reference = 1,
46
- Date = 2,
47
- RegExp = 3,
48
- Set = 4,
49
- Map = 5,
50
- Array = 6,
51
- Object = 7,
52
- NullConstructor = 8,
53
- Promise = 9,
54
- Error = 10,
55
- AggregateError = 11,
56
- Iterable = 12,
57
- TypedArray = 13
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.Date, value: Date, id: number] | [type: SerovalNodeType.RegExp, value: RegExp, id: number] | [
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: TypedArrayValue],
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 generateTreeSync(ctx: SerializationContext, current: ServerValue): SerovalNode;
109
- export declare function generateTreeAsync(ctx: SerializationContext, current: AsyncServerValue): Promise<SerovalNode>;
110
- export declare function serializePrimitive(ctx: SerializationContext, value: PrimitiveValue): string;
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 {};
@@ -1,7 +1,7 @@
1
- export type PrimitiveValue = boolean | string | number | undefined | null | bigint;
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.2",
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": "cb379745d112d53472da3765b20fe5d28323cb47"
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[]): Set<Feature> {
243
+ export function parseTargets(targets: string | string[]): number {
230
244
  const parsed = getTargetVersions(targets);
231
- const flags = new Set<Feature>();
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.add(Number(key) as unknown as Feature);
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
- createRef,
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<T extends NonPrimitiveServerValue<ServerValue | AsyncServerValue>>(
35
+ function finalize(
36
36
  ctx: SerializationContext,
37
- source: T,
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, createRef(ctx, source));
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.has(Feature.ArrowFunction)) {
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 (source.constructor === Object) {
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 = createSerializationContext(options);
76
+ const ctx = createParserContext(options);
76
77
  if (isPrimitive(source)) {
77
- return serializePrimitive(ctx, source);
78
+ return String(serializePrimitive(source));
78
79
  }
79
- const tree = generateTreeSync(ctx, source);
80
- const result = serializeTree(ctx, tree);
81
- return finalize(ctx, source, result);
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 = createSerializationContext(options);
90
+ const ctx = createParserContext(options);
89
91
  if (isPrimitive(source)) {
90
- return serializePrimitive(ctx, source);
92
+ return String(serializePrimitive(source));
91
93
  }
92
- const tree = await generateTreeAsync(ctx, source);
93
- const result = serializeTree(ctx, tree);
94
- return finalize(ctx, source, result);
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;