json-as 1.1.6 → 1.1.8
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 +8 -0
- package/README.md +1 -1
- package/assembly/index.ts +137 -2
- package/assembly/test.ts +233 -159
- package/lib/as-bs.ts +55 -0
- package/package.json +2 -2
- package/transform/lib/index.js +41 -7
- 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/lib/util.js +69 -0
- package/transform/lib/util.js.map +1 -1
- package/transform/src/index.ts +98 -10
- package/transform/src/types.ts +1 -0
- package/transform/src/util.ts +78 -1
package/transform/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ClassDeclaration, FieldDeclaration, IdentifierExpression, Parser, Source, NodeKind, CommonFlags, ImportStatement, Node, Tokenizer, SourceKind, NamedTypeNode, Range, FEATURE_SIMD, FunctionExpression, MethodDeclaration, Statement, Program, Feature } from "assemblyscript/dist/assemblyscript.js";
|
|
1
|
+
import { ClassDeclaration, FieldDeclaration, IdentifierExpression, Parser, Source, NodeKind, CommonFlags, ImportStatement, Node, Tokenizer, SourceKind, NamedTypeNode, Range, FEATURE_SIMD, FunctionExpression, MethodDeclaration, Statement, Program, Feature, CallExpression, PropertyAccessExpression } from "assemblyscript/dist/assemblyscript.js";
|
|
2
2
|
import { Transform } from "assemblyscript/dist/transform.js";
|
|
3
3
|
import { Visitor } from "./visitor.js";
|
|
4
|
-
import { isStdlib, SimpleParser, toString } from "./util.js";
|
|
4
|
+
import { cloneNode, isStdlib, replaceRef, SimpleParser, toString } from "./util.js";
|
|
5
5
|
import * as path from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { Property, PropertyFlags, Schema } from "./types.js";
|
|
@@ -12,6 +12,42 @@ let indent = " ";
|
|
|
12
12
|
const DEBUG = process.env["JSON_DEBUG"];
|
|
13
13
|
const STRICT = !(process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "false");
|
|
14
14
|
|
|
15
|
+
class CustomTransform extends Visitor {
|
|
16
|
+
static SN: CustomTransform = new CustomTransform();
|
|
17
|
+
|
|
18
|
+
private modify: boolean = false;
|
|
19
|
+
visitCallExpression(node: CallExpression) {
|
|
20
|
+
|
|
21
|
+
super.visit(node.args, node);
|
|
22
|
+
if (node.expression.kind != NodeKind.PropertyAccess || (node.expression as PropertyAccessExpression).property.text != "stringify") return;
|
|
23
|
+
if ((node.expression as PropertyAccessExpression).expression.kind != NodeKind.Identifier || ((node.expression as PropertyAccessExpression).expression as IdentifierExpression).text != "JSON") return;
|
|
24
|
+
|
|
25
|
+
if (this.modify) {
|
|
26
|
+
(node.expression as PropertyAccessExpression).expression = Node.createPropertyAccessExpression(
|
|
27
|
+
Node.createIdentifierExpression("JSON", node.expression.range),
|
|
28
|
+
Node.createIdentifierExpression("internal", node.expression.range),
|
|
29
|
+
node.expression.range
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
this.modify = true;
|
|
33
|
+
|
|
34
|
+
// console.log(toString(node));
|
|
35
|
+
// console.log(SimpleParser.parseStatement("JSON.internal.stringify").expression.expression)
|
|
36
|
+
}
|
|
37
|
+
static visit(node: Node | Node[], ref: Node | null = null): void {
|
|
38
|
+
if (!node) return;
|
|
39
|
+
CustomTransform.SN.modify = true;
|
|
40
|
+
CustomTransform.SN.visit(node, ref);
|
|
41
|
+
CustomTransform.SN.modify = false;
|
|
42
|
+
}
|
|
43
|
+
static hasCall(node: Node | Node[]): boolean {
|
|
44
|
+
if (!node) return;
|
|
45
|
+
CustomTransform.SN.modify = false;
|
|
46
|
+
CustomTransform.SN.visit(node);
|
|
47
|
+
return CustomTransform.SN.modify;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
15
51
|
class JSONTransform extends Visitor {
|
|
16
52
|
static SN: JSONTransform = new JSONTransform();
|
|
17
53
|
|
|
@@ -61,6 +97,10 @@ class JSONTransform extends Visitor {
|
|
|
61
97
|
if (serializers.length) {
|
|
62
98
|
this.schema.custom = true;
|
|
63
99
|
const serializer = serializers[0];
|
|
100
|
+
const hasCall = CustomTransform.hasCall(serializer);
|
|
101
|
+
|
|
102
|
+
CustomTransform.visit(serializer);
|
|
103
|
+
|
|
64
104
|
// if (!serializer.signature.parameters.length) throwError("Could not find any parameters in custom serializer for " + this.schema.name + ". Serializers must have one parameter like 'serializer(self: " + this.schema.name + "): string {}'", serializer.range);
|
|
65
105
|
if (serializer.signature.parameters.length > 1) 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);
|
|
66
106
|
if (serializer.signature.parameters.length > 0 && (<NamedTypeNode>serializer.signature.parameters[0].type).name.identifier.text != node.name.text && (<NamedTypeNode>serializer.signature.parameters[0].type).name.identifier.text != "this") throwError("Type of parameter for custom serializer does not match! It should be 'string'either be 'this' or '" + this.schema.name + "'", serializer.signature.parameters[0].type.range);
|
|
@@ -71,6 +111,7 @@ class JSONTransform extends Visitor {
|
|
|
71
111
|
}
|
|
72
112
|
SERIALIZE_CUSTOM += " __SERIALIZE(ptr: usize): void {\n";
|
|
73
113
|
SERIALIZE_CUSTOM += " const data = this." + serializer.name.text + "(" + (serializer.signature.parameters.length ? "this" : "") + ");\n";
|
|
114
|
+
if (hasCall) SERIALIZE_CUSTOM += " bs.resetState();\n";
|
|
74
115
|
SERIALIZE_CUSTOM += " const dataSize = data.length << 1;\n";
|
|
75
116
|
SERIALIZE_CUSTOM += " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
|
|
76
117
|
SERIALIZE_CUSTOM += " bs.offset += dataSize;\n";
|
|
@@ -199,13 +240,18 @@ class JSONTransform extends Visitor {
|
|
|
199
240
|
}
|
|
200
241
|
|
|
201
242
|
for (const member of this.schema.members) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
243
|
+
if (isStruct(member.type)) {
|
|
244
|
+
const schema = this.schemas.find((v) => v.name == stripNull(member.type));
|
|
245
|
+
if (!schema) continue;
|
|
246
|
+
|
|
247
|
+
if (!this.schema.deps.includes(schema)) {
|
|
206
248
|
this.schema.deps.push(schema);
|
|
207
249
|
this.schema.byteSize += schema.byteSize;
|
|
208
250
|
}
|
|
251
|
+
|
|
252
|
+
// if (schema.custom) {
|
|
253
|
+
// member.flags.set(PropertyFlags.Custom, null);
|
|
254
|
+
// }
|
|
209
255
|
}
|
|
210
256
|
}
|
|
211
257
|
|
|
@@ -360,6 +406,11 @@ class JSONTransform extends Visitor {
|
|
|
360
406
|
// if (shouldGroup) DESERIALIZE += " const keySize = keyEnd - keyStart;\n";
|
|
361
407
|
|
|
362
408
|
const groupMembers = (members: Property[]): Property[][] => {
|
|
409
|
+
// const customMembers = this.schema.members.filter((m) => m.flags.has(PropertyFlags.Custom));
|
|
410
|
+
// console.log("Custom members: ", customMembers.map((m) => m.name));
|
|
411
|
+
|
|
412
|
+
// members.push(...customMembers)
|
|
413
|
+
|
|
363
414
|
const groups = new Map<number, Property[]>();
|
|
364
415
|
|
|
365
416
|
for (const member of members) {
|
|
@@ -384,7 +435,44 @@ class JSONTransform extends Visitor {
|
|
|
384
435
|
.sort((a, b) => b.length - a.length);
|
|
385
436
|
};
|
|
386
437
|
|
|
387
|
-
const
|
|
438
|
+
// const groupMembers = (members: Property[]): Property[][] => {
|
|
439
|
+
// const customMembers = this.schema.members.filter((m) =>
|
|
440
|
+
// m.flags.has(PropertyFlags.Custom)
|
|
441
|
+
// );
|
|
442
|
+
// console.log("Custom members: ", customMembers.map((m) => m.name));
|
|
443
|
+
|
|
444
|
+
// const customSet = new Set(customMembers);
|
|
445
|
+
// members = members.filter((m) => !customSet.has(m));
|
|
446
|
+
// members.push(...customMembers);
|
|
447
|
+
|
|
448
|
+
// const groups = new Map<number, Property[]>();
|
|
449
|
+
|
|
450
|
+
// for (const member of members) {
|
|
451
|
+
// const name = member.alias || member.name;
|
|
452
|
+
// const length = name.length;
|
|
453
|
+
|
|
454
|
+
// if (!groups.has(length)) {
|
|
455
|
+
// groups.set(length, []);
|
|
456
|
+
// }
|
|
457
|
+
|
|
458
|
+
// groups.get(length)!.push(member);
|
|
459
|
+
// }
|
|
460
|
+
|
|
461
|
+
// return [...groups.entries()]
|
|
462
|
+
// .sort(([a], [b]) => a - b)
|
|
463
|
+
// .map(([_, group]) => {
|
|
464
|
+
// const regulars = group.filter((m) => !customSet.has(m));
|
|
465
|
+
// const customs = group.filter((m) => customSet.has(m));
|
|
466
|
+
|
|
467
|
+
// const sortByLength = (a: Property, b: Property) =>
|
|
468
|
+
// (a.alias || a.name).length - (b.alias || b.name).length;
|
|
469
|
+
|
|
470
|
+
// return [...regulars.sort(sortByLength), ...customs.sort(sortByLength)];
|
|
471
|
+
// });
|
|
472
|
+
// };
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
const generateGroups = (members: Property[], cb: (group: Property[]) => void, nil: boolean = false) => {
|
|
388
476
|
const groups = groupMembers(members);
|
|
389
477
|
DESERIALIZE += " switch (<u32>keyEnd - <u32>keyStart) {\n";
|
|
390
478
|
|
|
@@ -396,7 +484,7 @@ class JSONTransform extends Visitor {
|
|
|
396
484
|
}
|
|
397
485
|
|
|
398
486
|
DESERIALIZE += " }\n";
|
|
399
|
-
if (!
|
|
487
|
+
if (!members[0].node.type.isNullable && !isBoolean(members[0].type)) DESERIALIZE += " break;\n";
|
|
400
488
|
}
|
|
401
489
|
|
|
402
490
|
const generateComparisions = (members: Property[]) => {
|
|
@@ -677,7 +765,7 @@ class JSONTransform extends Visitor {
|
|
|
677
765
|
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
678
766
|
DESERIALIZE += indent + " }\n";
|
|
679
767
|
}
|
|
680
|
-
});
|
|
768
|
+
}, true);
|
|
681
769
|
|
|
682
770
|
DESERIALIZE += " }"; // Close first char check
|
|
683
771
|
DESERIALIZE += "\n }"; // Close first char check
|
|
@@ -1100,4 +1188,4 @@ function getComparision(data: string) {
|
|
|
1100
1188
|
return toMemCCheck(data);
|
|
1101
1189
|
}
|
|
1102
1190
|
}
|
|
1103
|
-
}
|
|
1191
|
+
}
|
package/transform/src/types.ts
CHANGED
package/transform/src/util.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Taken from https://github.com/as-pect/visitor-as/blob/master/src/simpleParser.ts
|
|
2
|
-
import { Parser, Tokenizer, Source, SourceKind, Expression, Statement, NamespaceDeclaration, ClassDeclaration, DeclarationStatement, Range, Node } from "assemblyscript/dist/assemblyscript.js";
|
|
2
|
+
import { Parser, Tokenizer, Source, SourceKind, Expression, Statement, NamespaceDeclaration, ClassDeclaration, DeclarationStatement, Range, Node, NodeKind } from "assemblyscript/dist/assemblyscript.js";
|
|
3
3
|
import { ASTBuilder } from "./builder.js";
|
|
4
4
|
|
|
5
5
|
export class SimpleParser {
|
|
@@ -54,3 +54,80 @@ export function isStdlib(s: Source | { range: Range }): boolean {
|
|
|
54
54
|
export function toString(node: Node): string {
|
|
55
55
|
return ASTBuilder.build(node);
|
|
56
56
|
}
|
|
57
|
+
|
|
58
|
+
export function replaceRef(
|
|
59
|
+
node: Node,
|
|
60
|
+
replacement: Node | Node[],
|
|
61
|
+
ref: Node | Node[] | null,
|
|
62
|
+
): void {
|
|
63
|
+
if (!node || !ref) return;
|
|
64
|
+
const nodeExpr = stripExpr(node);
|
|
65
|
+
|
|
66
|
+
if (Array.isArray(ref)) {
|
|
67
|
+
for (let i = 0; i < ref.length; i++) {
|
|
68
|
+
if (stripExpr(ref[i]) === nodeExpr) {
|
|
69
|
+
if (Array.isArray(replacement)) ref.splice(i, 1, ...replacement);
|
|
70
|
+
else ref.splice(i, 1, replacement);
|
|
71
|
+
return; // Exit early after replacement
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} else if (typeof ref === "object") {
|
|
75
|
+
for (const key of Object.keys(ref)) {
|
|
76
|
+
const current = ref[key] as Node | Node[];
|
|
77
|
+
if (Array.isArray(current)) {
|
|
78
|
+
for (let i = 0; i < current.length; i++) {
|
|
79
|
+
if (stripExpr(current[i]) === nodeExpr) {
|
|
80
|
+
if (Array.isArray(replacement))
|
|
81
|
+
current.splice(i, 1, ...replacement);
|
|
82
|
+
else current.splice(i, 1, replacement);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} else if (stripExpr(current) === nodeExpr) {
|
|
87
|
+
ref[key] = replacement;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function cloneNode(
|
|
95
|
+
input: Node | Node[] | null,
|
|
96
|
+
seen = new WeakMap(),
|
|
97
|
+
path = "",
|
|
98
|
+
): Node | Node[] | null {
|
|
99
|
+
if (input === null || typeof input !== "object") return input;
|
|
100
|
+
|
|
101
|
+
if (Array.isArray(input)) {
|
|
102
|
+
return input.map((item, index) =>
|
|
103
|
+
cloneNode(item, seen, `${path}[${index}]`),
|
|
104
|
+
) as Node | Node[] | null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (seen.has(input)) return seen.get(input);
|
|
108
|
+
|
|
109
|
+
const prototype = Object.getPrototypeOf(input);
|
|
110
|
+
const clone = Array.isArray(input) ? [] : Object.create(prototype);
|
|
111
|
+
seen.set(input, clone);
|
|
112
|
+
|
|
113
|
+
for (const key of Reflect.ownKeys(input)) {
|
|
114
|
+
const value = input[key];
|
|
115
|
+
const newPath = path ? `${path}.${String(key)}` : String(key);
|
|
116
|
+
|
|
117
|
+
if (newPath.endsWith(".source")) {
|
|
118
|
+
clone[key] = value;
|
|
119
|
+
} else if (value && typeof value === "object") {
|
|
120
|
+
clone[key] = cloneNode(value, seen, newPath);
|
|
121
|
+
} else {
|
|
122
|
+
clone[key] = value;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return clone as Node | Node[] | null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function stripExpr(node: Node): Node {
|
|
130
|
+
if (!node) return node;
|
|
131
|
+
if (node.kind == NodeKind.Expression) return node["expression"];
|
|
132
|
+
return node;
|
|
133
|
+
}
|