json-as 1.0.7 → 1.0.9
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/CHANGELOG.md +15 -0
- package/README.md +18 -2
- package/asconfig.json +1 -2
- package/assembly/__benches__/abc.bench.ts +5 -5
- package/assembly/__benches__/large.bench.ts +5 -51
- package/assembly/{custom → __benches__/lib}/bench.ts +4 -0
- package/assembly/__benches__/medium.bench.ts +3 -3
- package/assembly/__benches__/small.bench.ts +1 -1
- package/assembly/__benches__/vec3.bench.ts +3 -49
- package/assembly/__tests__/custom.spec.ts +4 -3
- package/assembly/__tests__/hierarchy.spec.ts +55 -0
- package/assembly/__tests__/lib/index.ts +1 -0
- package/assembly/custom/util.ts +0 -4
- package/assembly/deserialize/simple/array/box.ts +45 -0
- package/assembly/deserialize/simple/array/object.ts +28 -0
- package/assembly/deserialize/simple/array.ts +8 -0
- package/assembly/index.ts +39 -41
- package/assembly/serialize/simd/string.ts +12 -12
- package/assembly/test.ts +46 -133
- package/assembly/util/idofd.ts +6 -0
- package/bench/abc.bench.ts +1 -1
- package/bench/large.bench.ts +3 -3
- package/bench/lib/bench.ts +12 -0
- package/bench/medium.bench.ts +1 -1
- package/bench/runners/assemblyscript.js +28 -0
- package/bench/small.bench.ts +1 -1
- package/bench/tsconfig.json +12 -0
- package/bench/vec3.bench.ts +1 -1
- package/package.json +3 -4
- package/run-bench.as.sh +44 -18
- package/run-bench.js.sh +32 -6
- package/run-tests.sh +1 -1
- package/transform/lib/index.js +381 -122
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/types.js +1 -0
- package/transform/lib/types.js.map +1 -1
- package/transform/src/index.ts +430 -117
- package/transform/src/types.ts +1 -0
- package/assembly/__benches__/lib/index.ts +0 -26
- package/assembly/custom/memory.ts +0 -25
- package/assembly/custom/sink.ts +0 -231
- package/assembly/custom/types.ts +0 -5
package/transform/lib/index.js
CHANGED
|
@@ -7,7 +7,9 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
import { Property, PropertyFlags, Schema } from "./types.js";
|
|
8
8
|
import { getClasses, getImportedClass } from "./linker.js";
|
|
9
9
|
let indent = " ";
|
|
10
|
+
const DEBUG = process.env["JSON_DEBUG"];
|
|
10
11
|
class JSONTransform extends Visitor {
|
|
12
|
+
static SN = new JSONTransform();
|
|
11
13
|
program;
|
|
12
14
|
baseDir;
|
|
13
15
|
parser;
|
|
@@ -29,7 +31,12 @@ class JSONTransform extends Visitor {
|
|
|
29
31
|
this.schema.node = node;
|
|
30
32
|
this.schema.name = node.name.text;
|
|
31
33
|
this.schemas.push(this.schema);
|
|
32
|
-
|
|
34
|
+
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
|
|
35
|
+
let INITIALIZE = "@inline __INITIALIZE(): this {\n";
|
|
36
|
+
let DESERIALIZE = "__DESERIALIZE<T>(srcStart: usize, srcEnd: usize, out: T): T {\n";
|
|
37
|
+
let DESERIALIZE_CUSTOM = "";
|
|
38
|
+
let SERIALIZE_CUSTOM = "";
|
|
39
|
+
if (DEBUG)
|
|
33
40
|
console.log("Created schema: " + this.schema.name + " in file " + node.range.source.normalizedPath);
|
|
34
41
|
const members = [...node.members.filter((v) => v.kind === 54 && v.flags !== 32 && v.flags !== 512 && v.flags !== 1024 && !v.decorators?.some((decorator) => decorator.name.text === "omit"))];
|
|
35
42
|
const serializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "serializer"))];
|
|
@@ -39,6 +46,7 @@ class JSONTransform extends Visitor {
|
|
|
39
46
|
if (deserializers.length > 1)
|
|
40
47
|
throwError("Multiple deserializers detected for class " + node.name.text + " but schemas can only have one deserializer!", deserializers[1].range);
|
|
41
48
|
if (serializers.length) {
|
|
49
|
+
this.schema.custom = true;
|
|
42
50
|
const serializer = serializers[0];
|
|
43
51
|
if (serializer.signature.parameters.length > 1)
|
|
44
52
|
throwError("Found too many parameters in custom serializer for " + this.schema.name + ", but serializers can only accept one parameter of type '" + this.schema.name + "'!", serializer.signature.parameters[1].range);
|
|
@@ -49,20 +57,15 @@ class JSONTransform extends Visitor {
|
|
|
49
57
|
if (!serializer.decorators.some((v) => v.name.text == "inline")) {
|
|
50
58
|
serializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", serializer.range), null, serializer.range));
|
|
51
59
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
SERIALIZER += " }\n";
|
|
59
|
-
if (process.env["JSON_DEBUG"])
|
|
60
|
-
console.log(SERIALIZER);
|
|
61
|
-
const SERIALIZER_METHOD = SimpleParser.parseClassMember(SERIALIZER, node);
|
|
62
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE_CUSTOM"))
|
|
63
|
-
node.members.push(SERIALIZER_METHOD);
|
|
60
|
+
SERIALIZE_CUSTOM += " __SERIALIZE(ptr: usize): void {\n";
|
|
61
|
+
SERIALIZE_CUSTOM += " const data = this." + serializer.name.text + "(" + (serializer.signature.parameters.length ? "this" : "") + ");\n";
|
|
62
|
+
SERIALIZE_CUSTOM += " const dataSize = data.length << 1;\n";
|
|
63
|
+
SERIALIZE_CUSTOM += " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
|
|
64
|
+
SERIALIZE_CUSTOM += " bs.offset += dataSize;\n";
|
|
65
|
+
SERIALIZE_CUSTOM += " }\n";
|
|
64
66
|
}
|
|
65
67
|
if (deserializers.length) {
|
|
68
|
+
this.schema.custom = true;
|
|
66
69
|
const deserializer = deserializers[0];
|
|
67
70
|
if (!deserializer.signature.parameters.length)
|
|
68
71
|
throwError("Could not find any parameters in custom deserializer for " + this.schema.name + ". Deserializers must have one parameter like 'deserializer(data: string): " + this.schema.name + " {}'", deserializer.range);
|
|
@@ -75,15 +78,9 @@ class JSONTransform extends Visitor {
|
|
|
75
78
|
if (!deserializer.decorators.some((v) => v.name.text == "inline")) {
|
|
76
79
|
deserializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", deserializer.range), null, deserializer.range));
|
|
77
80
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
DESERIALIZER += " }\n";
|
|
82
|
-
if (process.env["JSON_DEBUG"])
|
|
83
|
-
console.log(DESERIALIZER);
|
|
84
|
-
const DESERIALIZER_METHOD = SimpleParser.parseClassMember(DESERIALIZER, node);
|
|
85
|
-
if (!node.members.find((v) => v.name.text == "__DESERIALIZE_CUSTOM"))
|
|
86
|
-
node.members.push(DESERIALIZER_METHOD);
|
|
81
|
+
DESERIALIZE_CUSTOM += " __DESERIALIZE<T>(srcStart: usize, srcEnd: usize, out: T): T {\n";
|
|
82
|
+
DESERIALIZE_CUSTOM += " return inline.always(this." + deserializer.name.text + "(changetype<string>(srcStart)));\n";
|
|
83
|
+
DESERIALIZE_CUSTOM += " }\n";
|
|
87
84
|
}
|
|
88
85
|
if (node.extendsType) {
|
|
89
86
|
const extendsName = node.extendsType?.name.identifier.text;
|
|
@@ -91,7 +88,7 @@ class JSONTransform extends Visitor {
|
|
|
91
88
|
if (!this.schema.parent) {
|
|
92
89
|
const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
|
|
93
90
|
if (internalSearch) {
|
|
94
|
-
if (
|
|
91
|
+
if (DEBUG)
|
|
95
92
|
console.log("Found " + extendsName + " internally");
|
|
96
93
|
this.visitClassDeclaration(internalSearch);
|
|
97
94
|
this.visitClassDeclaration(node);
|
|
@@ -99,7 +96,7 @@ class JSONTransform extends Visitor {
|
|
|
99
96
|
}
|
|
100
97
|
const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
|
|
101
98
|
if (externalSearch) {
|
|
102
|
-
if (
|
|
99
|
+
if (DEBUG)
|
|
103
100
|
console.log("Found " + extendsName + " externally");
|
|
104
101
|
this.visitClassDeclaration(externalSearch);
|
|
105
102
|
this.visitClassDeclaration(node);
|
|
@@ -172,9 +169,6 @@ class JSONTransform extends Visitor {
|
|
|
172
169
|
}
|
|
173
170
|
if (!this.schema.static)
|
|
174
171
|
this.schema.members = sortMembers(this.schema.members);
|
|
175
|
-
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
|
|
176
|
-
let INITIALIZE = "@inline __INITIALIZE(): this {\n";
|
|
177
|
-
let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (<u32>keyEnd - <u32>keyStart) {\n";
|
|
178
172
|
indent = " ";
|
|
179
173
|
if (this.schema.static == false) {
|
|
180
174
|
if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
|
|
@@ -282,88 +276,315 @@ class JSONTransform extends Visitor {
|
|
|
282
276
|
}
|
|
283
277
|
}
|
|
284
278
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
DESERIALIZE += `${indent}case ${memberLen}: {\n`;
|
|
305
|
-
indentInc();
|
|
306
|
-
if (memberLen == 2)
|
|
307
|
-
DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`;
|
|
308
|
-
else if (memberLen == 4)
|
|
309
|
-
DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`;
|
|
310
|
-
else if (memberLen == 6)
|
|
311
|
-
DESERIALIZE += `${indent}let code = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n`;
|
|
312
|
-
else if (memberLen == 8)
|
|
313
|
-
DESERIALIZE += `${indent}let code = load<u64>(keyStart);\n`;
|
|
279
|
+
const sortedMembers = {
|
|
280
|
+
string: [],
|
|
281
|
+
number: [],
|
|
282
|
+
boolean: [],
|
|
283
|
+
null: [],
|
|
284
|
+
array: [],
|
|
285
|
+
object: [],
|
|
286
|
+
};
|
|
287
|
+
for (const member of this.schema.members) {
|
|
288
|
+
if (member.type.endsWith(" | null"))
|
|
289
|
+
sortedMembers.null.push(member);
|
|
290
|
+
if (isString(member.type) || member.type == "JSON.Raw")
|
|
291
|
+
sortedMembers.string.push(member);
|
|
292
|
+
else if (isBoolean(member.type) || member.type.startsWith("JSON.Box<bool"))
|
|
293
|
+
sortedMembers.boolean.push(member);
|
|
294
|
+
else if (isPrimitive(member.type) || member.type.startsWith("JSON.Box<"))
|
|
295
|
+
sortedMembers.number.push(member);
|
|
296
|
+
else if (isArray(member.type))
|
|
297
|
+
sortedMembers.array.push(member);
|
|
314
298
|
else
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
299
|
+
sortedMembers.object.push(member);
|
|
300
|
+
}
|
|
301
|
+
indent = "";
|
|
302
|
+
let shouldGroup = false;
|
|
303
|
+
DESERIALIZE += indent + " let keyStart: usize = 0;\n";
|
|
304
|
+
if (shouldGroup || DEBUG)
|
|
305
|
+
DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
|
|
306
|
+
DESERIALIZE += indent + " let isKey = false;\n";
|
|
307
|
+
if (sortedMembers.object.length || sortedMembers.array.length)
|
|
308
|
+
DESERIALIZE += indent + " let depth: i32 = 0;\n";
|
|
309
|
+
DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
|
|
310
|
+
DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
|
|
311
|
+
DESERIALIZE += indent + " while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;\n";
|
|
312
|
+
DESERIALIZE += indent + ' if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");\n';
|
|
313
|
+
DESERIALIZE += indent + " if (load<u16>(srcStart) != 123) throw new Error(\"Expected '{' at start of object at position \" + (srcEnd - srcStart).toString());\n";
|
|
314
|
+
DESERIALIZE += indent + " if (load<u16>(srcEnd - 2) != 125) throw new Error(\"Expected '}' at end of object at position \" + (srcEnd - srcStart).toString());\n";
|
|
315
|
+
DESERIALIZE += indent + " srcStart += 2;\n\n";
|
|
316
|
+
DESERIALIZE += indent + " while (srcStart < srcEnd) {\n";
|
|
317
|
+
DESERIALIZE += indent + " let code = load<u16>(srcStart);\n";
|
|
318
|
+
DESERIALIZE += indent + " while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);\n";
|
|
319
|
+
DESERIALIZE += indent + " if (keyStart == 0) {\n";
|
|
320
|
+
DESERIALIZE += indent + " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
|
|
321
|
+
DESERIALIZE += indent + " if (isKey) {\n";
|
|
322
|
+
DESERIALIZE += indent + " keyStart = lastIndex;\n";
|
|
323
|
+
if (shouldGroup || DEBUG)
|
|
324
|
+
DESERIALIZE += indent + " keyEnd = srcStart;\n";
|
|
325
|
+
DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
|
|
326
|
+
DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
|
|
327
|
+
DESERIALIZE += indent + " isKey = false;\n";
|
|
328
|
+
DESERIALIZE += indent + " } else {\n";
|
|
329
|
+
DESERIALIZE += indent + " isKey = true;\n";
|
|
330
|
+
DESERIALIZE += indent + " lastIndex = srcStart + 2;\n";
|
|
331
|
+
DESERIALIZE += indent + " }\n";
|
|
332
|
+
DESERIALIZE += indent + " }\n";
|
|
333
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
334
|
+
DESERIALIZE += indent + " } else {\n";
|
|
335
|
+
const groupMembers = (members) => {
|
|
336
|
+
let sorted = [];
|
|
337
|
+
let len = -1;
|
|
338
|
+
members
|
|
339
|
+
.slice()
|
|
340
|
+
.sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
|
|
341
|
+
.forEach((member) => {
|
|
342
|
+
const _nameLength = member.alias?.length || member.name.length;
|
|
343
|
+
if (_nameLength === len) {
|
|
344
|
+
sorted[sorted.length - 1].push(member);
|
|
347
345
|
}
|
|
348
346
|
else {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
352
|
-
DESERIALIZE += `${indent} return;\n`;
|
|
353
|
-
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
|
|
347
|
+
sorted.push([member]);
|
|
348
|
+
len = _nameLength;
|
|
354
349
|
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
350
|
+
});
|
|
351
|
+
sorted = sorted.sort((a, b) => b.length - a.length);
|
|
352
|
+
return sorted;
|
|
353
|
+
};
|
|
354
|
+
const generateComparisions = (members) => {
|
|
355
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
|
|
356
|
+
DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
|
|
357
|
+
}
|
|
358
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 4)) {
|
|
359
|
+
DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
|
|
360
|
+
}
|
|
361
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 6)) {
|
|
362
|
+
DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
|
|
363
|
+
}
|
|
364
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 8)) {
|
|
365
|
+
DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
|
|
366
|
+
}
|
|
367
|
+
if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
|
|
368
|
+
DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
369
|
+
}
|
|
370
|
+
const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
|
|
371
|
+
const firstMemberName = members[0].alias || members[0].name;
|
|
372
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
373
|
+
DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(firstMemberName) + "));\n";
|
|
374
|
+
if (!complex)
|
|
375
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
376
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
377
|
+
DESERIALIZE += indent + " break;\n";
|
|
378
|
+
DESERIALIZE += indent + " }";
|
|
379
|
+
for (let i = 1; i < members.length; i++) {
|
|
380
|
+
const member = members[i];
|
|
381
|
+
const memberName = member.alias || member.name;
|
|
382
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
383
|
+
DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(memberName) + "));\n";
|
|
384
|
+
if (isString(members[0].type))
|
|
385
|
+
DESERIALIZE += indent + " srcStart += 4;\n";
|
|
386
|
+
else if (!complex)
|
|
387
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
388
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
389
|
+
DESERIALIZE += indent + " break;\n";
|
|
390
|
+
DESERIALIZE += indent + " }";
|
|
391
|
+
}
|
|
392
|
+
DESERIALIZE += " else {\n";
|
|
393
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
394
|
+
DESERIALIZE += indent + " }\n";
|
|
395
|
+
};
|
|
396
|
+
let mbElse = " ";
|
|
397
|
+
if (sortedMembers.string.length) {
|
|
398
|
+
DESERIALIZE += mbElse + "if (code == 34) {\n";
|
|
399
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
400
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
401
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
402
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
403
|
+
DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
|
|
404
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
405
|
+
generateComparisions(sortedMembers.string);
|
|
406
|
+
DESERIALIZE += " }\n";
|
|
407
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
408
|
+
DESERIALIZE += " }\n";
|
|
409
|
+
DESERIALIZE += " }\n";
|
|
410
|
+
mbElse = " else ";
|
|
411
|
+
}
|
|
412
|
+
if (sortedMembers.number.length) {
|
|
413
|
+
DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
|
|
414
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
415
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
416
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
417
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
418
|
+
DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
|
|
419
|
+
generateComparisions(sortedMembers.number);
|
|
420
|
+
DESERIALIZE += " }\n";
|
|
421
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
422
|
+
DESERIALIZE += " }\n";
|
|
423
|
+
DESERIALIZE += " }";
|
|
424
|
+
mbElse = " else ";
|
|
425
|
+
}
|
|
426
|
+
if (sortedMembers.object.length) {
|
|
427
|
+
DESERIALIZE += mbElse + "if (code == 123) {\n";
|
|
428
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
429
|
+
DESERIALIZE += " depth++;\n";
|
|
430
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
431
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
432
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
433
|
+
DESERIALIZE += " if (code == 34) {\n";
|
|
434
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
435
|
+
DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
|
|
436
|
+
DESERIALIZE += " } else if (code == 125) {\n";
|
|
437
|
+
DESERIALIZE += " if (--depth == 0) {\n";
|
|
438
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
439
|
+
indent = " ";
|
|
440
|
+
generateComparisions(sortedMembers.object);
|
|
441
|
+
indent = "";
|
|
442
|
+
DESERIALIZE += " }\n";
|
|
443
|
+
DESERIALIZE += " } else if (code == 123) depth++;\n";
|
|
444
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
445
|
+
DESERIALIZE += " }\n";
|
|
446
|
+
DESERIALIZE += " }";
|
|
447
|
+
mbElse = " else ";
|
|
448
|
+
}
|
|
449
|
+
if (sortedMembers.array.length) {
|
|
450
|
+
DESERIALIZE += mbElse + "if (code == 91) {\n";
|
|
451
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
452
|
+
DESERIALIZE += " depth++;\n";
|
|
453
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
454
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
455
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
456
|
+
DESERIALIZE += " if (code == 34) {\n";
|
|
457
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
458
|
+
DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
|
|
459
|
+
DESERIALIZE += " } else if (code == 93) {\n";
|
|
460
|
+
DESERIALIZE += " if (--depth == 0) {\n";
|
|
461
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
462
|
+
indent = " ";
|
|
463
|
+
generateComparisions(sortedMembers.array);
|
|
464
|
+
indent = "";
|
|
465
|
+
DESERIALIZE += " }\n";
|
|
466
|
+
DESERIALIZE += " } else if (code == 91) depth++;\n";
|
|
467
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
468
|
+
DESERIALIZE += " }\n";
|
|
469
|
+
DESERIALIZE += " }";
|
|
470
|
+
mbElse = " else ";
|
|
471
|
+
}
|
|
472
|
+
if (sortedMembers.boolean.length) {
|
|
473
|
+
DESERIALIZE += mbElse + "if (code == 116) {\n";
|
|
474
|
+
DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
|
|
475
|
+
DESERIALIZE += " srcStart += 8;\n";
|
|
476
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 2)) {
|
|
477
|
+
DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
|
|
478
|
+
}
|
|
479
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 4)) {
|
|
480
|
+
DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
|
|
481
|
+
}
|
|
482
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 6)) {
|
|
483
|
+
DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
|
|
484
|
+
}
|
|
485
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 8)) {
|
|
486
|
+
DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
|
|
487
|
+
}
|
|
488
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 > 8)) {
|
|
489
|
+
DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.boolean.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
490
|
+
}
|
|
491
|
+
const firstMemberName = sortedMembers.boolean[0].alias || sortedMembers.boolean[0].name;
|
|
492
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
493
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
494
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
495
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
496
|
+
DESERIALIZE += indent + " break;\n";
|
|
497
|
+
DESERIALIZE += indent + " }";
|
|
498
|
+
for (let i = 1; i < sortedMembers.boolean.length; i++) {
|
|
499
|
+
const member = sortedMembers.boolean[i];
|
|
500
|
+
const memberName = member.alias || member.name;
|
|
501
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
502
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
503
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
504
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
505
|
+
DESERIALIZE += indent + " break;\n";
|
|
506
|
+
DESERIALIZE += indent + " }";
|
|
507
|
+
}
|
|
508
|
+
DESERIALIZE += " else {\n";
|
|
509
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
510
|
+
DESERIALIZE += indent + " }\n";
|
|
511
|
+
DESERIALIZE += " }";
|
|
512
|
+
mbElse = " else ";
|
|
513
|
+
DESERIALIZE += " else if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
|
|
514
|
+
DESERIALIZE += " srcStart += 10;\n";
|
|
515
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
516
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
517
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
518
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
519
|
+
DESERIALIZE += indent + " break;\n";
|
|
520
|
+
DESERIALIZE += indent + " }";
|
|
521
|
+
for (let i = 1; i < sortedMembers.boolean.length; i++) {
|
|
522
|
+
const member = sortedMembers.boolean[i];
|
|
523
|
+
const memberName = member.alias || member.name;
|
|
524
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
525
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
526
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
527
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
528
|
+
DESERIALIZE += indent + " break;\n";
|
|
529
|
+
DESERIALIZE += indent + " }";
|
|
530
|
+
}
|
|
531
|
+
DESERIALIZE += " else {\n";
|
|
532
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
533
|
+
DESERIALIZE += indent + " }\n";
|
|
534
|
+
DESERIALIZE += " }\n";
|
|
535
|
+
DESERIALIZE += " }";
|
|
362
536
|
}
|
|
537
|
+
if (sortedMembers.null.length) {
|
|
538
|
+
DESERIALIZE += mbElse + "if (code == 110) {\n";
|
|
539
|
+
DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
|
|
540
|
+
DESERIALIZE += " srcStart += 8;\n";
|
|
541
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 2)) {
|
|
542
|
+
DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
|
|
543
|
+
}
|
|
544
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 4)) {
|
|
545
|
+
DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
|
|
546
|
+
}
|
|
547
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 6)) {
|
|
548
|
+
DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
|
|
549
|
+
}
|
|
550
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 8)) {
|
|
551
|
+
DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
|
|
552
|
+
}
|
|
553
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 > 8)) {
|
|
554
|
+
DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.null.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
555
|
+
}
|
|
556
|
+
const firstMemberName = sortedMembers.null[0].alias || sortedMembers.null[0].name;
|
|
557
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
558
|
+
DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
|
|
559
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
560
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
561
|
+
DESERIALIZE += indent + " break;\n";
|
|
562
|
+
DESERIALIZE += indent + " }";
|
|
563
|
+
for (let i = 1; i < sortedMembers.null.length; i++) {
|
|
564
|
+
const member = sortedMembers.null[i];
|
|
565
|
+
const memberName = member.alias || member.name;
|
|
566
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
567
|
+
DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
|
|
568
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
569
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
570
|
+
DESERIALIZE += indent + " break;\n";
|
|
571
|
+
DESERIALIZE += indent + " }";
|
|
572
|
+
}
|
|
573
|
+
DESERIALIZE += " else {\n";
|
|
574
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
575
|
+
DESERIALIZE += indent + " }\n";
|
|
576
|
+
DESERIALIZE += " }";
|
|
577
|
+
DESERIALIZE += "\n }";
|
|
578
|
+
mbElse = " else ";
|
|
579
|
+
}
|
|
580
|
+
DESERIALIZE += " else {\n";
|
|
581
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
582
|
+
DESERIALIZE += "}\n";
|
|
583
|
+
DESERIALIZE += "\n }\n";
|
|
363
584
|
indentDec();
|
|
364
|
-
DESERIALIZE +=
|
|
585
|
+
DESERIALIZE += ` }\n`;
|
|
365
586
|
indentDec();
|
|
366
|
-
DESERIALIZE +=
|
|
587
|
+
DESERIALIZE += ` return out;\n}\n`;
|
|
367
588
|
indent = " ";
|
|
368
589
|
this.schema.byteSize += 2;
|
|
369
590
|
SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
|
|
@@ -372,14 +593,14 @@ class JSONTransform extends Visitor {
|
|
|
372
593
|
SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
|
|
373
594
|
INITIALIZE += " return this;\n";
|
|
374
595
|
INITIALIZE += "}";
|
|
375
|
-
if (
|
|
376
|
-
console.log(SERIALIZE);
|
|
596
|
+
if (DEBUG) {
|
|
597
|
+
console.log(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE);
|
|
377
598
|
console.log(INITIALIZE);
|
|
378
|
-
console.log(DESERIALIZE);
|
|
599
|
+
console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
|
|
379
600
|
}
|
|
380
|
-
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
|
|
601
|
+
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE, node);
|
|
381
602
|
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
382
|
-
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
|
|
603
|
+
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE_CUSTOM || DESERIALIZE, node);
|
|
383
604
|
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
384
605
|
node.members.push(SERIALIZE_METHOD);
|
|
385
606
|
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
@@ -391,8 +612,8 @@ class JSONTransform extends Visitor {
|
|
|
391
612
|
generateEmptyMethods(node) {
|
|
392
613
|
let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
|
|
393
614
|
let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
|
|
394
|
-
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(
|
|
395
|
-
if (
|
|
615
|
+
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(srcStart: usize, srcEnd: usize): this {\n return this;\n}";
|
|
616
|
+
if (DEBUG) {
|
|
396
617
|
console.log(SERIALIZE_EMPTY);
|
|
397
618
|
console.log(INITIALIZE_EMPTY);
|
|
398
619
|
console.log(DESERIALIZE_EMPTY);
|
|
@@ -429,7 +650,7 @@ class JSONTransform extends Visitor {
|
|
|
429
650
|
}
|
|
430
651
|
const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
|
|
431
652
|
this.topStatements.push(replaceNode);
|
|
432
|
-
if (
|
|
653
|
+
if (DEBUG)
|
|
433
654
|
console.log("Added as-bs import: " + toString(replaceNode) + "\n");
|
|
434
655
|
}
|
|
435
656
|
if (!jsonImport) {
|
|
@@ -438,7 +659,7 @@ class JSONTransform extends Visitor {
|
|
|
438
659
|
}
|
|
439
660
|
const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)], Node.createStringLiteralExpression(jsonPath, node.range), node.range);
|
|
440
661
|
this.topStatements.push(replaceNode);
|
|
441
|
-
if (
|
|
662
|
+
if (DEBUG)
|
|
442
663
|
console.log("Added json-as import: " + toString(replaceNode) + "\n");
|
|
443
664
|
}
|
|
444
665
|
}
|
|
@@ -490,7 +711,7 @@ class JSONTransform extends Visitor {
|
|
|
490
711
|
}
|
|
491
712
|
export default class Transformer extends Transform {
|
|
492
713
|
afterParse(parser) {
|
|
493
|
-
const transformer =
|
|
714
|
+
const transformer = JSONTransform.SN;
|
|
494
715
|
const sources = parser.sources
|
|
495
716
|
.filter((source) => {
|
|
496
717
|
const p = source.internalPath;
|
|
@@ -577,17 +798,17 @@ function toMemCDecl(n, indent) {
|
|
|
577
798
|
let offset = 0;
|
|
578
799
|
let index = 0;
|
|
579
800
|
while (n >= 8) {
|
|
580
|
-
out += `${indent}const
|
|
801
|
+
out += `${indent}const codeS${(index += 8)} = load<u64>(keyStart, ${offset});\n`;
|
|
581
802
|
offset += 8;
|
|
582
803
|
n -= 8;
|
|
583
804
|
}
|
|
584
805
|
while (n >= 4) {
|
|
585
|
-
out += `${indent}const
|
|
806
|
+
out += `${indent}const codeS${(index += 4)} = load<u32>(keyStart, ${offset});\n`;
|
|
586
807
|
offset += 4;
|
|
587
808
|
n -= 4;
|
|
588
809
|
}
|
|
589
810
|
if (n == 1)
|
|
590
|
-
out += `${indent}const
|
|
811
|
+
out += `${indent}const codeS${(index += 1)} = load<u16>(keyStart, ${offset});\n`;
|
|
591
812
|
return out;
|
|
592
813
|
}
|
|
593
814
|
function toMemCCheck(data) {
|
|
@@ -596,17 +817,17 @@ function toMemCCheck(data) {
|
|
|
596
817
|
let offset = 0;
|
|
597
818
|
let index = 0;
|
|
598
819
|
while (n >= 8) {
|
|
599
|
-
out += ` &&
|
|
820
|
+
out += ` && codeS${(index += 8)} == ${toU64(data, offset >> 1)}`;
|
|
600
821
|
offset += 8;
|
|
601
822
|
n -= 8;
|
|
602
823
|
}
|
|
603
824
|
while (n >= 4) {
|
|
604
|
-
out += ` &&
|
|
825
|
+
out += ` && codeS${(index += 4)} == ${toU32(data, offset >> 1)}`;
|
|
605
826
|
offset += 4;
|
|
606
827
|
n -= 4;
|
|
607
828
|
}
|
|
608
829
|
if (n == 1)
|
|
609
|
-
out += ` &&
|
|
830
|
+
out += ` && codeS${(index += 1)} == ${toU16(data, offset >> 1)}`;
|
|
610
831
|
return out.slice(4);
|
|
611
832
|
}
|
|
612
833
|
function strToNum(data, simd = false, offset = 0) {
|
|
@@ -635,10 +856,6 @@ function strToNum(data, simd = false, offset = 0) {
|
|
|
635
856
|
}
|
|
636
857
|
return out;
|
|
637
858
|
}
|
|
638
|
-
function isPrimitive(type) {
|
|
639
|
-
const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
|
|
640
|
-
return primitiveTypes.some((v) => type.startsWith(v));
|
|
641
|
-
}
|
|
642
859
|
function throwError(message, range) {
|
|
643
860
|
const err = new Error();
|
|
644
861
|
err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
|
|
@@ -672,4 +889,46 @@ function sizeof(type) {
|
|
|
672
889
|
else
|
|
673
890
|
return 0;
|
|
674
891
|
}
|
|
892
|
+
function isPrimitive(type) {
|
|
893
|
+
const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
|
|
894
|
+
return primitiveTypes.some((v) => type.startsWith(v));
|
|
895
|
+
}
|
|
896
|
+
function isBoolean(type) {
|
|
897
|
+
return type == "bool" || type == "boolean";
|
|
898
|
+
}
|
|
899
|
+
function isStruct(type) {
|
|
900
|
+
type = stripNull(type);
|
|
901
|
+
return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
|
|
902
|
+
}
|
|
903
|
+
function isString(type) {
|
|
904
|
+
return stripNull(type) == "string" || stripNull(type) == "String";
|
|
905
|
+
}
|
|
906
|
+
function isArray(type) {
|
|
907
|
+
return type.startsWith("Array<");
|
|
908
|
+
}
|
|
909
|
+
function stripNull(type) {
|
|
910
|
+
if (type.endsWith(" | null")) {
|
|
911
|
+
return type.slice(0, type.length - 7);
|
|
912
|
+
}
|
|
913
|
+
return type;
|
|
914
|
+
}
|
|
915
|
+
function getComparision(data) {
|
|
916
|
+
switch (data.length << 1) {
|
|
917
|
+
case 2: {
|
|
918
|
+
return "code16 == " + data.charCodeAt(0);
|
|
919
|
+
}
|
|
920
|
+
case 4: {
|
|
921
|
+
return "code32 == " + toU32(data);
|
|
922
|
+
}
|
|
923
|
+
case 6: {
|
|
924
|
+
return "code48 == " + toU48(data);
|
|
925
|
+
}
|
|
926
|
+
case 8: {
|
|
927
|
+
return "code64 == " + toU64(data);
|
|
928
|
+
}
|
|
929
|
+
default: {
|
|
930
|
+
return toMemCCheck(data);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
675
934
|
//# sourceMappingURL=index.js.map
|