seroval 0.1.0 → 0.2.0
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/LICENSE +1 -1
- package/README.md +35 -4
- package/dist/cjs/development/index.cjs +423 -255
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +2 -2
- package/dist/esm/development/index.mjs +423 -255
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +2 -2
- package/dist/types/async.d.ts +4 -0
- package/dist/types/context.d.ts +33 -0
- package/dist/types/index.d.ts +6 -5
- package/dist/types/is-primitive.d.ts +2 -0
- package/dist/types/is-promise.d.ts +1 -0
- package/dist/types/serialize-primitive.d.ts +2 -0
- package/dist/types/sync.d.ts +4 -0
- package/dist/types/types.d.ts +9 -0
- package/package.json +2 -2
- package/src/async.ts +229 -0
- package/src/context.ts +200 -0
- package/src/get-identifier.ts +1 -0
- package/src/index.ts +69 -453
- package/src/is-primitive.ts +14 -0
- package/src/is-promise.ts +6 -0
- package/src/serialize-primitive.ts +32 -0
- package/src/sync.ts +199 -0
- package/src/types.ts +32 -0
|
@@ -34,73 +34,26 @@ function getIdentifier(index) {
|
|
|
34
34
|
return ref;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
// src/
|
|
38
|
-
function quote(str) {
|
|
39
|
-
let result = "";
|
|
40
|
-
let lastPos = 0;
|
|
41
|
-
for (let i = 0, len = str.length; i < len; i++) {
|
|
42
|
-
let replacement;
|
|
43
|
-
switch (str[i]) {
|
|
44
|
-
case '"':
|
|
45
|
-
replacement = '\\"';
|
|
46
|
-
break;
|
|
47
|
-
case "\\":
|
|
48
|
-
replacement = "\\\\";
|
|
49
|
-
break;
|
|
50
|
-
case "<":
|
|
51
|
-
replacement = "\\x3C";
|
|
52
|
-
break;
|
|
53
|
-
case "\n":
|
|
54
|
-
replacement = "\\n";
|
|
55
|
-
break;
|
|
56
|
-
case "\r":
|
|
57
|
-
replacement = "\\r";
|
|
58
|
-
break;
|
|
59
|
-
case "\u2028":
|
|
60
|
-
replacement = "\\u2028";
|
|
61
|
-
break;
|
|
62
|
-
case "\u2029":
|
|
63
|
-
replacement = "\\u2029";
|
|
64
|
-
break;
|
|
65
|
-
default:
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
result += str.slice(lastPos, i) + replacement;
|
|
69
|
-
lastPos = i + 1;
|
|
70
|
-
}
|
|
71
|
-
if (lastPos === 0) {
|
|
72
|
-
result = str;
|
|
73
|
-
} else {
|
|
74
|
-
result += str.slice(lastPos);
|
|
75
|
-
}
|
|
76
|
-
return `"${result}"`;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// src/index.ts
|
|
37
|
+
// src/context.ts
|
|
80
38
|
var EMPTY_SET = "new Set";
|
|
81
39
|
var EMPTY_MAP = "new Map";
|
|
82
40
|
var EMPTY_ARRAY = "[]";
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
SET_ADDS = [];
|
|
95
|
-
VARS = [];
|
|
96
|
-
REF_COUNT.clear();
|
|
97
|
-
REFS.clear();
|
|
98
|
-
ASSIGNED_REFS.clear();
|
|
41
|
+
function createSerializationContext() {
|
|
42
|
+
return {
|
|
43
|
+
refCount: /* @__PURE__ */ new Map(),
|
|
44
|
+
stack: /* @__PURE__ */ new Set(),
|
|
45
|
+
refs: /* @__PURE__ */ new Map(),
|
|
46
|
+
assignedRefs: /* @__PURE__ */ new Set(),
|
|
47
|
+
vars: [],
|
|
48
|
+
assignments: [],
|
|
49
|
+
mapSets: [],
|
|
50
|
+
setAdds: []
|
|
51
|
+
};
|
|
99
52
|
}
|
|
100
|
-
function resolveAssignments() {
|
|
101
|
-
if (
|
|
53
|
+
function resolveAssignments(ctx) {
|
|
54
|
+
if (ctx.assignments.length) {
|
|
102
55
|
const result = {};
|
|
103
|
-
forEach(
|
|
56
|
+
forEach(ctx.assignments, ([source, value]) => {
|
|
104
57
|
if (value in result) {
|
|
105
58
|
result[value] = `${source}=${result[value]}`;
|
|
106
59
|
} else {
|
|
@@ -111,10 +64,10 @@ function resolveAssignments() {
|
|
|
111
64
|
}
|
|
112
65
|
return "";
|
|
113
66
|
}
|
|
114
|
-
function resolveMapSets() {
|
|
115
|
-
if (
|
|
67
|
+
function resolveMapSets(ctx) {
|
|
68
|
+
if (ctx.mapSets.length) {
|
|
116
69
|
const result = {};
|
|
117
|
-
forEach(
|
|
70
|
+
forEach(ctx.mapSets, ([source, key, value]) => {
|
|
118
71
|
if (source in result) {
|
|
119
72
|
result[source] = `${result[source]}.set(${key},${value})`;
|
|
120
73
|
} else {
|
|
@@ -125,10 +78,10 @@ function resolveMapSets() {
|
|
|
125
78
|
}
|
|
126
79
|
return "";
|
|
127
80
|
}
|
|
128
|
-
function resolveSetAdds() {
|
|
129
|
-
if (
|
|
81
|
+
function resolveSetAdds(ctx) {
|
|
82
|
+
if (ctx.setAdds.length) {
|
|
130
83
|
const result = {};
|
|
131
|
-
forEach(
|
|
84
|
+
forEach(ctx.setAdds, ([source, value]) => {
|
|
132
85
|
if (source in result) {
|
|
133
86
|
result[source] = `${result[source]}.add(${value})`;
|
|
134
87
|
} else {
|
|
@@ -139,88 +92,114 @@ function resolveSetAdds() {
|
|
|
139
92
|
}
|
|
140
93
|
return "";
|
|
141
94
|
}
|
|
142
|
-
function resolvePatches() {
|
|
143
|
-
return `${resolveAssignments()}${resolveMapSets()}${resolveSetAdds()}`;
|
|
95
|
+
function resolvePatches(ctx) {
|
|
96
|
+
return `${resolveAssignments(ctx)}${resolveMapSets(ctx)}${resolveSetAdds(ctx)}`;
|
|
144
97
|
}
|
|
145
|
-
function insertRef(current) {
|
|
146
|
-
const count =
|
|
147
|
-
|
|
98
|
+
function insertRef(ctx, current) {
|
|
99
|
+
const count = ctx.refCount.get(current) || 0;
|
|
100
|
+
ctx.refCount.set(current, count + 1);
|
|
148
101
|
return count === 0;
|
|
149
102
|
}
|
|
150
103
|
function constructorCheck(value, constructor) {
|
|
151
104
|
return value.constructor === constructor;
|
|
152
105
|
}
|
|
153
|
-
function
|
|
154
|
-
|
|
155
|
-
return true;
|
|
156
|
-
}
|
|
157
|
-
const type = typeof current;
|
|
158
|
-
const classConst = current.constructor;
|
|
159
|
-
return type === "number" || type === "string" || type === "bigint" || classConst === Date || classConst === RegExp;
|
|
160
|
-
}
|
|
161
|
-
function lookupRefs(current) {
|
|
162
|
-
if (isPrimitive(current)) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
if (Array.isArray(current)) {
|
|
166
|
-
if (insertRef(current)) {
|
|
167
|
-
forEach(current, lookupRefs);
|
|
168
|
-
}
|
|
169
|
-
} else if (constructorCheck(current, Set)) {
|
|
170
|
-
if (insertRef(current)) {
|
|
171
|
-
for (const item of current.keys()) {
|
|
172
|
-
lookupRefs(item);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
} else if (constructorCheck(current, Map)) {
|
|
176
|
-
if (insertRef(current)) {
|
|
177
|
-
for (const [key, value] of current.entries()) {
|
|
178
|
-
lookupRefs(key);
|
|
179
|
-
lookupRefs(value);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
} else if (current.constructor === Object && insertRef(current)) {
|
|
183
|
-
forEach(Object.values(current), lookupRefs);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
function createRef(value) {
|
|
187
|
-
const current = REFS.get(value);
|
|
106
|
+
function createRef(ctx, value) {
|
|
107
|
+
const current = ctx.refs.get(value);
|
|
188
108
|
if (current != null) {
|
|
189
109
|
return current;
|
|
190
110
|
}
|
|
191
|
-
const id =
|
|
192
|
-
|
|
111
|
+
const id = ctx.refs.size;
|
|
112
|
+
ctx.refs.set(value, id);
|
|
193
113
|
return id;
|
|
194
114
|
}
|
|
195
|
-
function getRefParam(index) {
|
|
196
|
-
if (
|
|
197
|
-
return
|
|
115
|
+
function getRefParam(ctx, index) {
|
|
116
|
+
if (ctx.vars[index]) {
|
|
117
|
+
return ctx.vars[index];
|
|
198
118
|
}
|
|
199
119
|
const result = getIdentifier(index);
|
|
200
|
-
|
|
120
|
+
ctx.vars[index] = result;
|
|
201
121
|
return result;
|
|
202
122
|
}
|
|
203
|
-
function assignRef(index, value) {
|
|
204
|
-
return `${getRefParam(index)}=${value}`;
|
|
123
|
+
function assignRef(ctx, index, value) {
|
|
124
|
+
return `${getRefParam(ctx, index)}=${value}`;
|
|
125
|
+
}
|
|
126
|
+
function createAssignment(ctx, source, value) {
|
|
127
|
+
ctx.assignments.push([source, value]);
|
|
205
128
|
}
|
|
206
|
-
function
|
|
207
|
-
|
|
129
|
+
function createSetAdd(ctx, ref, value) {
|
|
130
|
+
ctx.setAdds.push([getRefParam(ctx, ref), value]);
|
|
208
131
|
}
|
|
209
|
-
function
|
|
210
|
-
|
|
132
|
+
function createMapSet(ctx, ref, key, value) {
|
|
133
|
+
ctx.mapSets.push([getRefParam(ctx, ref), key, value]);
|
|
211
134
|
}
|
|
212
|
-
function
|
|
213
|
-
|
|
135
|
+
function createArrayAssign(ctx, ref, index, value) {
|
|
136
|
+
createAssignment(ctx, `${getRefParam(ctx, ref)}[${index}]`, value);
|
|
214
137
|
}
|
|
215
|
-
function
|
|
216
|
-
createAssignment(`${getRefParam(ref)}
|
|
138
|
+
function createObjectIdentifierAssign(ctx, ref, key, value) {
|
|
139
|
+
createAssignment(ctx, `${getRefParam(ctx, ref)}.${key}`, value);
|
|
217
140
|
}
|
|
218
|
-
function
|
|
219
|
-
createAssignment(`${getRefParam(ref)}
|
|
141
|
+
function createObjectComputedAssign(ctx, ref, key, value) {
|
|
142
|
+
createAssignment(ctx, `${getRefParam(ctx, ref)}[${key}]`, value);
|
|
220
143
|
}
|
|
221
|
-
|
|
222
|
-
|
|
144
|
+
|
|
145
|
+
// src/is-primitive.ts
|
|
146
|
+
function isPrimitive(current) {
|
|
147
|
+
if (!current || current === true) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
const type = typeof current;
|
|
151
|
+
const classConst = current.constructor;
|
|
152
|
+
return type === "number" || type === "string" || type === "bigint" || classConst === Date || classConst === RegExp;
|
|
223
153
|
}
|
|
154
|
+
|
|
155
|
+
// src/is-promise.ts
|
|
156
|
+
function isPromise(obj) {
|
|
157
|
+
return !!obj && (typeof obj === "object" || typeof obj === "function") && "then" in obj && typeof obj.then === "function";
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/quote.ts
|
|
161
|
+
function quote(str) {
|
|
162
|
+
let result = "";
|
|
163
|
+
let lastPos = 0;
|
|
164
|
+
for (let i = 0, len = str.length; i < len; i++) {
|
|
165
|
+
let replacement;
|
|
166
|
+
switch (str[i]) {
|
|
167
|
+
case '"':
|
|
168
|
+
replacement = '\\"';
|
|
169
|
+
break;
|
|
170
|
+
case "\\":
|
|
171
|
+
replacement = "\\\\";
|
|
172
|
+
break;
|
|
173
|
+
case "<":
|
|
174
|
+
replacement = "\\x3C";
|
|
175
|
+
break;
|
|
176
|
+
case "\n":
|
|
177
|
+
replacement = "\\n";
|
|
178
|
+
break;
|
|
179
|
+
case "\r":
|
|
180
|
+
replacement = "\\r";
|
|
181
|
+
break;
|
|
182
|
+
case "\u2028":
|
|
183
|
+
replacement = "\\u2028";
|
|
184
|
+
break;
|
|
185
|
+
case "\u2029":
|
|
186
|
+
replacement = "\\u2029";
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
result += str.slice(lastPos, i) + replacement;
|
|
192
|
+
lastPos = i + 1;
|
|
193
|
+
}
|
|
194
|
+
if (lastPos === 0) {
|
|
195
|
+
result = str;
|
|
196
|
+
} else {
|
|
197
|
+
result += str.slice(lastPos);
|
|
198
|
+
}
|
|
199
|
+
return `"${result}"`;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/serialize-primitive.ts
|
|
224
203
|
function serializePrimitive(value) {
|
|
225
204
|
if (value === true) {
|
|
226
205
|
return "!0";
|
|
@@ -248,122 +227,294 @@ function serializePrimitive(value) {
|
|
|
248
227
|
}
|
|
249
228
|
return String(value);
|
|
250
229
|
}
|
|
251
|
-
|
|
230
|
+
|
|
231
|
+
// src/async.ts
|
|
232
|
+
async function lookupRefsAsync(ctx, current) {
|
|
233
|
+
if (isPrimitive(current)) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (isPromise(current)) {
|
|
237
|
+
if (insertRef(ctx, current)) {
|
|
238
|
+
await current.then((value) => lookupRefsAsync(ctx, value));
|
|
239
|
+
}
|
|
240
|
+
} else if (Array.isArray(current)) {
|
|
241
|
+
if (insertRef(ctx, current)) {
|
|
242
|
+
for (const value of current) {
|
|
243
|
+
await lookupRefsAsync(ctx, value);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
} else if (constructorCheck(current, Set)) {
|
|
247
|
+
if (insertRef(ctx, current)) {
|
|
248
|
+
for (const item of current.keys()) {
|
|
249
|
+
await lookupRefsAsync(ctx, item);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
} else if (constructorCheck(current, Map)) {
|
|
253
|
+
if (insertRef(ctx, current)) {
|
|
254
|
+
for (const [key, value] of current.entries()) {
|
|
255
|
+
await lookupRefsAsync(ctx, key);
|
|
256
|
+
await lookupRefsAsync(ctx, value);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} else if ((current.constructor === Object || current.constructor == null) && insertRef(ctx, current)) {
|
|
260
|
+
for (const value of Object.values(current)) {
|
|
261
|
+
await lookupRefsAsync(ctx, value);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async function traverseAsync(ctx, current) {
|
|
252
266
|
if (isPrimitive(current)) {
|
|
253
267
|
return serializePrimitive(current);
|
|
254
268
|
}
|
|
255
|
-
let refResult =
|
|
269
|
+
let refResult = ctx.refs.get(current);
|
|
256
270
|
if (refResult != null) {
|
|
257
|
-
if (
|
|
258
|
-
return
|
|
271
|
+
if (ctx.assignedRefs.has(refResult)) {
|
|
272
|
+
return getRefParam(ctx, refResult);
|
|
259
273
|
}
|
|
260
|
-
|
|
274
|
+
ctx.assignedRefs.add(refResult);
|
|
275
|
+
}
|
|
276
|
+
function getCurrentRef() {
|
|
277
|
+
if (refResult == null) {
|
|
278
|
+
refResult = createRef(ctx, current);
|
|
279
|
+
}
|
|
280
|
+
return refResult;
|
|
281
|
+
}
|
|
282
|
+
function processRef(value) {
|
|
283
|
+
if (refResult != null) {
|
|
284
|
+
return assignRef(ctx, refResult, value);
|
|
285
|
+
}
|
|
286
|
+
return value;
|
|
287
|
+
}
|
|
288
|
+
if (isPromise(current)) {
|
|
289
|
+
return current.then(async (value) => {
|
|
290
|
+
ctx.stack.add(current);
|
|
291
|
+
let result;
|
|
292
|
+
if (ctx.stack.has(value)) {
|
|
293
|
+
const refParam = getRefParam(ctx, createRef(ctx, value));
|
|
294
|
+
result = `Promise.resolve().then(()=>${refParam})`;
|
|
295
|
+
} else {
|
|
296
|
+
result = `Promise.resolve(${await traverseAsync(ctx, value)})`;
|
|
297
|
+
}
|
|
298
|
+
ctx.stack.delete(current);
|
|
299
|
+
return processRef(result);
|
|
300
|
+
});
|
|
261
301
|
}
|
|
262
302
|
if (constructorCheck(current, Set)) {
|
|
263
303
|
if (current.size) {
|
|
264
304
|
const values = [];
|
|
265
|
-
|
|
266
|
-
for (const
|
|
267
|
-
if (
|
|
268
|
-
|
|
269
|
-
refResult = createRef(current);
|
|
270
|
-
}
|
|
271
|
-
createSetAdd(refResult, getRefParam(createRef(value2)));
|
|
305
|
+
ctx.stack.add(current);
|
|
306
|
+
for (const value of current.keys()) {
|
|
307
|
+
if (ctx.stack.has(value)) {
|
|
308
|
+
createSetAdd(ctx, getCurrentRef(), getRefParam(ctx, createRef(ctx, value)));
|
|
272
309
|
} else {
|
|
273
|
-
|
|
274
|
-
if (typeof result === "string") {
|
|
275
|
-
values.push(result);
|
|
276
|
-
} else {
|
|
277
|
-
values.push(result.referred);
|
|
278
|
-
}
|
|
310
|
+
values.push(await traverseAsync(ctx, value));
|
|
279
311
|
}
|
|
280
312
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (refResult != null) {
|
|
284
|
-
return assignRef(refResult, value);
|
|
285
|
-
}
|
|
286
|
-
return value;
|
|
313
|
+
ctx.stack.delete(current);
|
|
314
|
+
return processRef(values.length ? `new Set([${join(values, ",")}])` : EMPTY_SET);
|
|
287
315
|
}
|
|
288
316
|
return EMPTY_SET;
|
|
289
317
|
}
|
|
290
318
|
if (constructorCheck(current, Map)) {
|
|
291
319
|
if (current.size) {
|
|
292
320
|
const values = [];
|
|
293
|
-
|
|
294
|
-
for (const [key,
|
|
295
|
-
if (
|
|
296
|
-
|
|
297
|
-
|
|
321
|
+
ctx.stack.add(current);
|
|
322
|
+
for (const [key, value] of current.entries()) {
|
|
323
|
+
if (ctx.stack.has(key)) {
|
|
324
|
+
const ref = getCurrentRef();
|
|
325
|
+
const keyRef = getRefParam(ctx, createRef(ctx, key));
|
|
326
|
+
if (ctx.stack.has(value)) {
|
|
327
|
+
const valueRef = getRefParam(ctx, createRef(ctx, value));
|
|
328
|
+
createMapSet(ctx, ref, keyRef, valueRef);
|
|
329
|
+
} else {
|
|
330
|
+
const valueResult = await traverseAsync(ctx, value);
|
|
331
|
+
createMapSet(ctx, ref, keyRef, valueResult);
|
|
298
332
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
333
|
+
} else if (ctx.stack.has(value)) {
|
|
334
|
+
const valueRef = getRefParam(ctx, createRef(ctx, value));
|
|
335
|
+
const keyResult = await traverseAsync(ctx, key);
|
|
336
|
+
createMapSet(ctx, getCurrentRef(), keyResult, valueRef);
|
|
337
|
+
} else {
|
|
338
|
+
const keyResult = await traverseAsync(ctx, key);
|
|
339
|
+
const valueResult = await traverseAsync(ctx, value);
|
|
340
|
+
values.push(`[${keyResult},${valueResult}]`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
ctx.stack.delete(current);
|
|
344
|
+
return processRef(values.length ? `new Map([${join(values, ",")}])` : EMPTY_MAP);
|
|
345
|
+
}
|
|
346
|
+
return EMPTY_MAP;
|
|
347
|
+
}
|
|
348
|
+
if (Array.isArray(current)) {
|
|
349
|
+
if (current.length) {
|
|
350
|
+
let values = "";
|
|
351
|
+
ctx.stack.add(current);
|
|
352
|
+
for (let i = 0, len = current.length; i < len; i += 1) {
|
|
353
|
+
if (i in current) {
|
|
354
|
+
const item = current[i];
|
|
355
|
+
if (ctx.stack.has(item)) {
|
|
356
|
+
const refParam = getRefParam(ctx, createRef(ctx, item));
|
|
357
|
+
createArrayAssign(ctx, getCurrentRef(), i, refParam);
|
|
358
|
+
values += ",";
|
|
302
359
|
} else {
|
|
303
|
-
|
|
304
|
-
if (
|
|
305
|
-
|
|
306
|
-
} else {
|
|
307
|
-
createMapSet(refResult, keyRef, valueResult.referred);
|
|
360
|
+
values += await traverseAsync(ctx, item);
|
|
361
|
+
if (i < current.length - 1) {
|
|
362
|
+
values += ",";
|
|
308
363
|
}
|
|
309
364
|
}
|
|
310
|
-
} else
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
365
|
+
} else {
|
|
366
|
+
values += ",";
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
ctx.stack.delete(current);
|
|
370
|
+
return processRef(`[${values}]`);
|
|
371
|
+
}
|
|
372
|
+
return EMPTY_ARRAY;
|
|
373
|
+
}
|
|
374
|
+
const empty = current.constructor == null;
|
|
375
|
+
if (current.constructor === Object || empty) {
|
|
376
|
+
const values = [];
|
|
377
|
+
ctx.stack.add(current);
|
|
378
|
+
for (const [key, value2] of Object.entries(current)) {
|
|
379
|
+
const check = Number(key);
|
|
380
|
+
if (check >= 0 || Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key)) {
|
|
381
|
+
if (ctx.stack.has(value2)) {
|
|
382
|
+
const ref = getCurrentRef();
|
|
383
|
+
const refParam = getRefParam(ctx, createRef(ctx, value2));
|
|
384
|
+
if (Number.isNaN(check)) {
|
|
385
|
+
createObjectIdentifierAssign(ctx, ref, key, refParam);
|
|
318
386
|
} else {
|
|
319
|
-
|
|
387
|
+
createObjectComputedAssign(ctx, ref, key, refParam);
|
|
320
388
|
}
|
|
321
389
|
} else {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
390
|
+
const valueResult = await traverseAsync(ctx, value2);
|
|
391
|
+
values.push(`${key}:${valueResult}`);
|
|
392
|
+
}
|
|
393
|
+
} else if (ctx.stack.has(value2)) {
|
|
394
|
+
const refParam = getRefParam(ctx, createRef(ctx, value2));
|
|
395
|
+
createObjectComputedAssign(ctx, getCurrentRef(), quote(key), refParam);
|
|
396
|
+
} else {
|
|
397
|
+
const valueResult = await traverseAsync(ctx, value2);
|
|
398
|
+
values.push(`${quote(key)}:${valueResult}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
ctx.stack.delete(current);
|
|
402
|
+
const value = `{${join(values, ",")}}`;
|
|
403
|
+
if (empty) {
|
|
404
|
+
return processRef(`Object.assign(Object.create(null),${value})`);
|
|
405
|
+
}
|
|
406
|
+
return processRef(value);
|
|
407
|
+
}
|
|
408
|
+
throw new Error("Unserializable value");
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// src/sync.ts
|
|
412
|
+
function lookupRefs(ctx, current) {
|
|
413
|
+
if (isPrimitive(current)) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (Array.isArray(current)) {
|
|
417
|
+
if (insertRef(ctx, current)) {
|
|
418
|
+
forEach(current, (value) => {
|
|
419
|
+
lookupRefs(ctx, value);
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
} else if (constructorCheck(current, Set)) {
|
|
423
|
+
if (insertRef(ctx, current)) {
|
|
424
|
+
for (const item of current.keys()) {
|
|
425
|
+
lookupRefs(ctx, item);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
} else if (constructorCheck(current, Map)) {
|
|
429
|
+
if (insertRef(ctx, current)) {
|
|
430
|
+
for (const [key, value] of current.entries()) {
|
|
431
|
+
lookupRefs(ctx, key);
|
|
432
|
+
lookupRefs(ctx, value);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
} else if ((current.constructor === Object || current.constructor == null) && insertRef(ctx, current)) {
|
|
436
|
+
forEach(Object.values(current), (value) => {
|
|
437
|
+
lookupRefs(ctx, value);
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function traverseSync(ctx, current) {
|
|
442
|
+
if (isPrimitive(current)) {
|
|
443
|
+
return serializePrimitive(current);
|
|
444
|
+
}
|
|
445
|
+
let refResult = ctx.refs.get(current);
|
|
446
|
+
if (refResult != null) {
|
|
447
|
+
if (ctx.assignedRefs.has(refResult)) {
|
|
448
|
+
return getRefParam(ctx, refResult);
|
|
449
|
+
}
|
|
450
|
+
ctx.assignedRefs.add(refResult);
|
|
451
|
+
}
|
|
452
|
+
function getCurrentRef() {
|
|
453
|
+
if (refResult == null) {
|
|
454
|
+
refResult = createRef(ctx, current);
|
|
455
|
+
}
|
|
456
|
+
return refResult;
|
|
457
|
+
}
|
|
458
|
+
function processRef(value) {
|
|
459
|
+
if (refResult != null) {
|
|
460
|
+
return assignRef(ctx, refResult, value);
|
|
461
|
+
}
|
|
462
|
+
return value;
|
|
463
|
+
}
|
|
464
|
+
if (constructorCheck(current, Set)) {
|
|
465
|
+
if (current.size) {
|
|
466
|
+
const values = [];
|
|
467
|
+
ctx.stack.add(current);
|
|
468
|
+
for (const value of current.keys()) {
|
|
469
|
+
if (ctx.stack.has(value)) {
|
|
470
|
+
createSetAdd(ctx, getCurrentRef(), getRefParam(ctx, createRef(ctx, value)));
|
|
471
|
+
} else {
|
|
472
|
+
values.push(traverseSync(ctx, value));
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
ctx.stack.delete(current);
|
|
476
|
+
return processRef(values.length ? `new Set([${join(values, ",")}])` : EMPTY_SET);
|
|
477
|
+
}
|
|
478
|
+
return EMPTY_SET;
|
|
479
|
+
}
|
|
480
|
+
if (constructorCheck(current, Map)) {
|
|
481
|
+
if (current.size) {
|
|
482
|
+
const values = [];
|
|
483
|
+
ctx.stack.add(current);
|
|
484
|
+
for (const [key, value] of current.entries()) {
|
|
485
|
+
if (ctx.stack.has(key)) {
|
|
486
|
+
const ref = getCurrentRef();
|
|
487
|
+
const keyRef = getRefParam(ctx, createRef(ctx, key));
|
|
488
|
+
if (ctx.stack.has(value)) {
|
|
489
|
+
const valueRef = getRefParam(ctx, createRef(ctx, value));
|
|
490
|
+
createMapSet(ctx, ref, keyRef, valueRef);
|
|
330
491
|
} else {
|
|
331
|
-
|
|
332
|
-
values.push(`[${keyResult.referred},${valueResult}]`);
|
|
333
|
-
} else {
|
|
334
|
-
values.push(`[${keyResult.referred},${valueResult.referred}]`);
|
|
335
|
-
}
|
|
492
|
+
createMapSet(ctx, ref, keyRef, traverseSync(ctx, value));
|
|
336
493
|
}
|
|
494
|
+
} else if (ctx.stack.has(value)) {
|
|
495
|
+
const valueRef = getRefParam(ctx, createRef(ctx, value));
|
|
496
|
+
createMapSet(ctx, getCurrentRef(), traverseSync(ctx, key), valueRef);
|
|
497
|
+
} else {
|
|
498
|
+
values.push(`[${traverseSync(ctx, key)},${traverseSync(ctx, value)}]`);
|
|
337
499
|
}
|
|
338
500
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
if (refResult != null) {
|
|
342
|
-
return assignRef(refResult, value);
|
|
343
|
-
}
|
|
344
|
-
return value;
|
|
501
|
+
ctx.stack.delete(current);
|
|
502
|
+
return processRef(values.length ? `new Map([${join(values, ",")}])` : EMPTY_MAP);
|
|
345
503
|
}
|
|
346
504
|
return EMPTY_MAP;
|
|
347
505
|
}
|
|
348
506
|
if (Array.isArray(current)) {
|
|
349
507
|
if (current.length) {
|
|
350
508
|
let values = "";
|
|
351
|
-
|
|
509
|
+
ctx.stack.add(current);
|
|
352
510
|
forEach(current, (item, i) => {
|
|
353
511
|
if (i in current) {
|
|
354
|
-
if (
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
-
createArrayAssign(refResult, i, getRefParam(createRef(item)));
|
|
512
|
+
if (ctx.stack.has(item)) {
|
|
513
|
+
const refParam = getRefParam(ctx, createRef(ctx, item));
|
|
514
|
+
createArrayAssign(ctx, getCurrentRef(), i, refParam);
|
|
359
515
|
values += ",";
|
|
360
516
|
} else {
|
|
361
|
-
|
|
362
|
-
if (typeof result === "string") {
|
|
363
|
-
values += result;
|
|
364
|
-
} else {
|
|
365
|
-
values += result.referred;
|
|
366
|
-
}
|
|
517
|
+
values += traverseSync(ctx, item);
|
|
367
518
|
if (i < current.length - 1) {
|
|
368
519
|
values += ",";
|
|
369
520
|
}
|
|
@@ -372,87 +523,104 @@ function traverse(current) {
|
|
|
372
523
|
values += ",";
|
|
373
524
|
}
|
|
374
525
|
});
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (refResult != null) {
|
|
378
|
-
return assignRef(refResult, value);
|
|
379
|
-
}
|
|
380
|
-
return value;
|
|
526
|
+
ctx.stack.delete(current);
|
|
527
|
+
return processRef(`[${values}]`);
|
|
381
528
|
}
|
|
382
529
|
return EMPTY_ARRAY;
|
|
383
530
|
}
|
|
384
|
-
|
|
531
|
+
const empty = current.constructor == null;
|
|
532
|
+
if (current.constructor === Object || empty) {
|
|
385
533
|
const values = [];
|
|
386
|
-
|
|
534
|
+
ctx.stack.add(current);
|
|
387
535
|
forEach(Object.entries(current), ([key, value2]) => {
|
|
388
536
|
const check = Number(key);
|
|
389
|
-
if (Number.isNaN(check)
|
|
390
|
-
if (
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
} else {
|
|
396
|
-
const result = traverse(value2);
|
|
397
|
-
if (typeof result === "string") {
|
|
398
|
-
values.push(`${key}:${result}`);
|
|
537
|
+
if (check >= 0 || Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key)) {
|
|
538
|
+
if (ctx.stack.has(value2)) {
|
|
539
|
+
const ref = getCurrentRef();
|
|
540
|
+
const refParam = getRefParam(ctx, createRef(ctx, value2));
|
|
541
|
+
if (!Number.isNaN(check)) {
|
|
542
|
+
createObjectComputedAssign(ctx, ref, key, refParam);
|
|
399
543
|
} else {
|
|
400
|
-
|
|
544
|
+
createObjectIdentifierAssign(ctx, ref, key, refParam);
|
|
401
545
|
}
|
|
402
|
-
}
|
|
403
|
-
} else if (STACK.has(value2)) {
|
|
404
|
-
if (refResult == null) {
|
|
405
|
-
refResult = createRef(current);
|
|
406
|
-
}
|
|
407
|
-
createObjectStringAssign(refResult, key, getRefParam(createRef(value2)));
|
|
408
|
-
} else {
|
|
409
|
-
const result = traverse(value2);
|
|
410
|
-
if (typeof result === "string") {
|
|
411
|
-
values.push(`${quote(key)}:${result}`);
|
|
412
546
|
} else {
|
|
413
|
-
values.push(`${
|
|
547
|
+
values.push(`${key}:${traverseSync(ctx, value2)}`);
|
|
414
548
|
}
|
|
549
|
+
} else if (ctx.stack.has(value2)) {
|
|
550
|
+
const refParam = getRefParam(ctx, createRef(ctx, value2));
|
|
551
|
+
createObjectComputedAssign(ctx, getCurrentRef(), quote(key), refParam);
|
|
552
|
+
} else {
|
|
553
|
+
values.push(`${quote(key)}:${traverseSync(ctx, value2)}`);
|
|
415
554
|
}
|
|
416
555
|
});
|
|
417
|
-
|
|
556
|
+
ctx.stack.delete(current);
|
|
418
557
|
const value = `{${join(values, ",")}}`;
|
|
419
|
-
if (
|
|
420
|
-
return
|
|
558
|
+
if (empty) {
|
|
559
|
+
return processRef(`Object.assign(Object.create(null),${value})`);
|
|
421
560
|
}
|
|
422
|
-
return value;
|
|
561
|
+
return processRef(value);
|
|
423
562
|
}
|
|
424
563
|
throw new Error("Unserializable value");
|
|
425
564
|
}
|
|
565
|
+
|
|
566
|
+
// src/index.ts
|
|
567
|
+
function finalize(ctx, source, result) {
|
|
568
|
+
if (ctx.vars.length) {
|
|
569
|
+
const index = getRefParam(ctx, createRef(ctx, source));
|
|
570
|
+
const patches = resolvePatches(ctx);
|
|
571
|
+
const params = ctx.vars.length > 1 ? `(${join(ctx.vars, ",")})` : ctx.vars[0];
|
|
572
|
+
if (result.startsWith(`${index}=`)) {
|
|
573
|
+
return `(${params}=>(${result},${patches}${index}))()`;
|
|
574
|
+
}
|
|
575
|
+
return `(${params}=>(${index}=${result},${patches}${index}))()`;
|
|
576
|
+
}
|
|
577
|
+
if (source.constructor === Object) {
|
|
578
|
+
return `(${result})`;
|
|
579
|
+
}
|
|
580
|
+
return result;
|
|
581
|
+
}
|
|
426
582
|
function serialize(source) {
|
|
427
583
|
if (isPrimitive(source)) {
|
|
428
584
|
return serializePrimitive(source);
|
|
429
585
|
}
|
|
430
|
-
|
|
431
|
-
lookupRefs(source);
|
|
432
|
-
for (const [key, value] of
|
|
586
|
+
const ctx = createSerializationContext();
|
|
587
|
+
lookupRefs(ctx, source);
|
|
588
|
+
for (const [key, value] of ctx.refCount.entries()) {
|
|
433
589
|
if (value > 1) {
|
|
434
|
-
createRef(key);
|
|
590
|
+
createRef(ctx, key);
|
|
435
591
|
}
|
|
436
592
|
}
|
|
437
|
-
const result =
|
|
593
|
+
const result = traverseSync(ctx, source);
|
|
438
594
|
if (typeof result !== "string") {
|
|
439
595
|
throw new Error("Unreachable error");
|
|
440
596
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
597
|
+
return finalize(ctx, source, result);
|
|
598
|
+
}
|
|
599
|
+
async function serializeAsync(source) {
|
|
600
|
+
if (isPrimitive(source)) {
|
|
601
|
+
return serializePrimitive(source);
|
|
602
|
+
}
|
|
603
|
+
const ctx = createSerializationContext();
|
|
604
|
+
await lookupRefsAsync(ctx, source);
|
|
605
|
+
for (const [key, value] of ctx.refCount.entries()) {
|
|
606
|
+
if (value > 1) {
|
|
607
|
+
createRef(ctx, key);
|
|
447
608
|
}
|
|
448
|
-
return `(${params}=>(${index}=${result},${patches}${index}))()`;
|
|
449
609
|
}
|
|
450
|
-
|
|
451
|
-
|
|
610
|
+
const result = await traverseAsync(ctx, source);
|
|
611
|
+
if (typeof result !== "string") {
|
|
612
|
+
throw new Error("Unreachable error");
|
|
452
613
|
}
|
|
453
|
-
return result;
|
|
614
|
+
return finalize(ctx, source, result);
|
|
615
|
+
}
|
|
616
|
+
function deserialize(source) {
|
|
617
|
+
return (0, eval)(source);
|
|
454
618
|
}
|
|
619
|
+
var src_default = serialize;
|
|
455
620
|
export {
|
|
456
|
-
|
|
621
|
+
src_default as default,
|
|
622
|
+
deserialize,
|
|
623
|
+
serialize,
|
|
624
|
+
serializeAsync
|
|
457
625
|
};
|
|
458
626
|
//# sourceMappingURL=index.mjs.map
|