json-as 1.1.16 → 1.1.18
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/__tests__/namespace.spec.ts +63 -0
- package/assembly/index.ts +1 -1
- package/assembly/test.tmp.ts +18 -23
- package/assembly/test.ts +0 -2
- package/package.json +5 -5
- package/run-bench.as.sh +1 -1
- package/run-tests.sh +17 -13
- package/transform/lib/index.js +47 -54
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/types.js +103 -2
- package/transform/lib/types.js.map +1 -1
- package/transform/src/index.ts +51 -54
- package/transform/src/types.ts +182 -4
- package/transform/src/linkers/classes.ts +0 -50
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 2025-06-30 - 1.1.18
|
|
4
|
+
|
|
5
|
+
- fix: [#150](https://github.com/JairusSW/json-as/issues/150)
|
|
6
|
+
|
|
7
|
+
## 2025-06-17 - 1.1.17
|
|
8
|
+
|
|
9
|
+
- fix: add support for classes within namespaces [#147](https://github.com/JairusSW/json-as/pull/147)
|
|
10
|
+
|
|
3
11
|
## 2025-06-12 - 1.1.16
|
|
4
12
|
|
|
5
13
|
- tests: properly support nulls (in testing lib)
|
package/README.md
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { describe, expect } from "./lib";
|
|
3
|
+
|
|
4
|
+
describe("Should serialize namespaced derived structs", () => {
|
|
5
|
+
const obj: Namespace.DerivedObject = { a: "foo", b: "bar" };
|
|
6
|
+
expect(JSON.stringify(obj)).toBe(`{"a":"foo","b":"bar"}`);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
describe("Should serialize namespaced derived structs with nested object", () => {
|
|
10
|
+
const bar: Namespace.Bar = { value: "baz" };
|
|
11
|
+
const obj: Namespace.DerivedObjectWithNestedObject = { a: "foo", b: "bar", c: bar };
|
|
12
|
+
expect(JSON.stringify(obj)).toBe(`{"a":"foo","b":"bar","c":{"value":"baz"}}`);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("Should deserialize namespaced object with alias property", () => {
|
|
16
|
+
expect(JSON.stringify(JSON.parse<Namespace.ObjectWithAliasProperty>(`{"a":"foo","value":42}`))).toBe(`{"a":"foo","value":42}`);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("Should deserialize namespaced derived structs", () => {
|
|
20
|
+
expect(JSON.stringify(JSON.parse<Namespace.DerivedObject>(`{"a":"foo","b":"bar"}`))).toBe(`{"a":"foo","b":"bar"}`);
|
|
21
|
+
expect(JSON.stringify(JSON.parse<Namespace.DerivedObject>(`{"b":"bar","a":"foo"}`))).toBe(`{"a":"foo","b":"bar"}`);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe("Should deserialize namespaced derived structs with nested object", () => {
|
|
25
|
+
expect(JSON.stringify(JSON.parse<Namespace.DerivedObjectWithNestedObject>(`{"a":"foo","b":"bar","c":{"value":"baz"}}`))).toBe(`{"a":"foo","b":"bar","c":{"value":"baz"}}`);
|
|
26
|
+
expect(JSON.stringify(JSON.parse<Namespace.DerivedObjectWithNestedObject>(`{"c":{"value":"baz"},"a":"foo","b":"bar"}`))).toBe(`{"a":"foo","b":"bar","c":{"value":"baz"}}`);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
type NumberAlias = i64;
|
|
30
|
+
|
|
31
|
+
namespace Namespace {
|
|
32
|
+
|
|
33
|
+
@json
|
|
34
|
+
export class Base {
|
|
35
|
+
a: string = "";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@json
|
|
40
|
+
export class Bar {
|
|
41
|
+
value: string = "";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@json
|
|
46
|
+
export class ObjectWithAliasProperty {
|
|
47
|
+
a: string = "";
|
|
48
|
+
value: NumberAlias = 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@json
|
|
53
|
+
export class DerivedObject extends Base {
|
|
54
|
+
b: string = "";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@json
|
|
59
|
+
export class DerivedObjectWithNestedObject extends Base {
|
|
60
|
+
b: string = "";
|
|
61
|
+
c: Bar = new Bar();
|
|
62
|
+
}
|
|
63
|
+
}
|
package/assembly/index.ts
CHANGED
|
@@ -605,7 +605,7 @@ export namespace JSON {
|
|
|
605
605
|
if (isDefined(type.__DESERIALIZE)) {
|
|
606
606
|
const out = changetype<nonnull<T>>(dst || __new(offsetof<nonnull<T>>(), idof<nonnull<T>>()));
|
|
607
607
|
// @ts-ignore: Defined by transform
|
|
608
|
-
if (isDefined(type.__INITIALIZE)) out.__INITIALIZE();
|
|
608
|
+
if (isNullable<T>() && isDefined(type.__INITIALIZE)) out.__INITIALIZE();
|
|
609
609
|
// @ts-ignore: Defined by transform
|
|
610
610
|
return out.__DESERIALIZE(srcStart, srcEnd, out);
|
|
611
611
|
} else if (type instanceof Map) {
|
package/assembly/test.tmp.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { JSON } from "../assembly/index";
|
|
1
2
|
import { bs } from "../lib/as-bs";
|
|
2
|
-
import { JSON } from ".";
|
|
3
3
|
|
|
4
4
|
@json
|
|
5
5
|
class Vec3 {
|
|
@@ -214,13 +214,10 @@ class Player {
|
|
|
214
214
|
|
|
215
215
|
@omitif((self: this): boolean => self.age < 18)
|
|
216
216
|
age!: i32;
|
|
217
|
-
|
|
218
|
-
@omitnull()
|
|
219
217
|
pos!: Vec3 | null;
|
|
220
218
|
isVerified!: boolean;
|
|
221
219
|
__SERIALIZE(ptr: usize): void {
|
|
222
|
-
bs.proposeSize(
|
|
223
|
-
let block: usize = 0;
|
|
220
|
+
bs.proposeSize(158);
|
|
224
221
|
store<u16>(bs.offset, 123, 0);
|
|
225
222
|
bs.offset += 2;
|
|
226
223
|
if (!((self: this): boolean => self.age < 18)(this)) {
|
|
@@ -231,14 +228,6 @@ class Player {
|
|
|
231
228
|
store<u16>(bs.offset, 44, 0);
|
|
232
229
|
bs.offset += 2;
|
|
233
230
|
}
|
|
234
|
-
if ((block = load<usize>(ptr, offsetof<this>("pos"))) !== 0) {
|
|
235
|
-
store<u64>(bs.offset, 32370099070435362, 0);
|
|
236
|
-
store<u32>(bs.offset, 3801122, 8);
|
|
237
|
-
bs.offset += 12;
|
|
238
|
-
JSON.__serialize<Vec3 | null>(load<Vec3 | null>(ptr, offsetof<this>("pos")));
|
|
239
|
-
store<u16>(bs.offset, 44, 0);
|
|
240
|
-
bs.offset += 2;
|
|
241
|
-
}
|
|
242
231
|
store<u64>(bs.offset, 32088598323265570, 0);
|
|
243
232
|
store<u64>(bs.offset, 30962384884727923, 8);
|
|
244
233
|
store<u64>(bs.offset, 9570583007002721, 16);
|
|
@@ -256,6 +245,11 @@ class Player {
|
|
|
256
245
|
store<u32>(bs.offset, 3801122, 24);
|
|
257
246
|
bs.offset += 28;
|
|
258
247
|
JSON.__serialize<Array<i32>>(load<Array<i32>>(ptr, offsetof<this>("lastActive")));
|
|
248
|
+
store<u64>(bs.offset, 31244203453448236, 0);
|
|
249
|
+
store<u32>(bs.offset, 2228339, 8);
|
|
250
|
+
store<u16>(bs.offset, 58, 12);
|
|
251
|
+
bs.offset += 14;
|
|
252
|
+
JSON.__serialize<Vec3 | null>(load<Vec3 | null>(ptr, offsetof<this>("pos")));
|
|
259
253
|
store<u64>(bs.offset, 32370073295519788, 0);
|
|
260
254
|
store<u64>(bs.offset, 29555362187509846, 8);
|
|
261
255
|
store<u64>(bs.offset, 28147931469643878, 16);
|
|
@@ -552,10 +546,12 @@ class Player {
|
|
|
552
546
|
if (load<u64>(srcStart) == 30399761348886638) {
|
|
553
547
|
srcStart += 8;
|
|
554
548
|
switch (<u32>keyEnd - <u32>keyStart) {
|
|
555
|
-
case
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
549
|
+
case 20: {
|
|
550
|
+
const codeS8 = load<u64>(keyStart, 0);
|
|
551
|
+
const codeS16 = load<u64>(keyStart, 8);
|
|
552
|
+
const codeS20 = load<u32>(keyStart, 16);
|
|
553
|
+
if (codeS8 == 32370111954878566 && codeS16 == 27303545189433460 && codeS20 == 6619245) {
|
|
554
|
+
store<usize>(changetype<usize>(out), 0, offsetof<this>("firstName"));
|
|
559
555
|
srcStart += 2;
|
|
560
556
|
keyStart = 0;
|
|
561
557
|
break;
|
|
@@ -566,12 +562,10 @@ class Player {
|
|
|
566
562
|
}
|
|
567
563
|
}
|
|
568
564
|
|
|
569
|
-
case
|
|
570
|
-
const
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
if (codeS8 == 32370111954878566 && codeS16 == 27303545189433460 && codeS20 == 6619245) {
|
|
574
|
-
store<usize>(changetype<usize>(out), 0, offsetof<this>("firstName"));
|
|
565
|
+
case 6: {
|
|
566
|
+
const code48 = load<u64>(keyStart) & 281474976710655;
|
|
567
|
+
if (code48 == 493928513648) {
|
|
568
|
+
store<usize>(changetype<usize>(out), 0, offsetof<this>("pos"));
|
|
575
569
|
srcStart += 2;
|
|
576
570
|
keyStart = 0;
|
|
577
571
|
break;
|
|
@@ -598,6 +592,7 @@ class Player {
|
|
|
598
592
|
}
|
|
599
593
|
}
|
|
600
594
|
const player: Player = {
|
|
595
|
+
firstName: "Jairus",
|
|
601
596
|
lastName: "Tanaka",
|
|
602
597
|
lastActive: [3, 9, 2025],
|
|
603
598
|
age: 18,
|
package/assembly/test.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-as",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.18",
|
|
4
4
|
"author": "Jairus Tanaka",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"main": "transform/lib/index.js",
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@assemblyscript/wasi-shim": "^0.1.0",
|
|
12
|
-
"@types/node": "^22.15.
|
|
13
|
-
"assemblyscript": "^0.28.
|
|
12
|
+
"@types/node": "^22.15.34",
|
|
13
|
+
"assemblyscript": "^0.28.2",
|
|
14
14
|
"assemblyscript-prettier": "^3.0.1",
|
|
15
|
-
"prettier": "^3.
|
|
16
|
-
"tsx": "^4.
|
|
15
|
+
"prettier": "^3.6.2",
|
|
16
|
+
"tsx": "^4.20.3",
|
|
17
17
|
"typescript": "^5.8.3"
|
|
18
18
|
},
|
|
19
19
|
"bugs": {
|
package/run-bench.as.sh
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
RUNTIMES=${RUNTIMES:-"minimal stub"}
|
|
3
3
|
ENGINES=${ENGINES:-"liftoff ignition sparkplug turbofan llvm"}
|
|
4
|
-
for file in ./assembly/__benches__/
|
|
4
|
+
for file in ./assembly/__benches__/medium.bench.ts; do
|
|
5
5
|
filename=$(basename -- "$file")
|
|
6
6
|
output_wasi=
|
|
7
7
|
for runtime in $RUNTIMES; do
|
package/run-tests.sh
CHANGED
|
@@ -4,24 +4,28 @@ mkdir -p ./build
|
|
|
4
4
|
|
|
5
5
|
for file in ./assembly/__tests__/*.spec.ts; do
|
|
6
6
|
filename=$(basename -- "$file")
|
|
7
|
-
|
|
7
|
+
if [ -z "$1" ] || [ "$1" = "$filename" ]; then
|
|
8
|
+
output="./build/${filename%.ts}.wasm"
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
start_time=$(date +%s%3N)
|
|
11
|
+
npx asc "$file" --transform ./transform -o "$output" --enable simd --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json --disableWarning 226 || { echo "Tests failed"; exit 1; }
|
|
12
|
+
end_time=$(date +%s%3N)
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
build_time=$((end_time - start_time))
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
if [ "$build_time" -ge 60000 ]; then
|
|
17
|
+
formatted_time="$(bc <<< "scale=2; $build_time/60000")m"
|
|
18
|
+
elif [ "$build_time" -ge 1000 ]; then
|
|
19
|
+
formatted_time="$(bc <<< "scale=2; $build_time/1000")s"
|
|
20
|
+
else
|
|
21
|
+
formatted_time="${build_time}ms"
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
echo " -> $filename (built in $formatted_time)"
|
|
25
|
+
wasmtime "$output" || { echo "Tests failed"; exit 1; }
|
|
19
26
|
else
|
|
20
|
-
|
|
27
|
+
echo " -> $filename (skipped)"
|
|
21
28
|
fi
|
|
22
|
-
|
|
23
|
-
echo " -> $filename (built in $formatted_time)"
|
|
24
|
-
wasmtime "$output" || { echo "Tests failed"; exit 1; }
|
|
25
29
|
done
|
|
26
30
|
|
|
27
31
|
echo "All tests passed"
|
package/transform/lib/index.js
CHANGED
|
@@ -4,14 +4,13 @@ import { Visitor } from "./visitor.js";
|
|
|
4
4
|
import { isStdlib, removeExtension, SimpleParser, toString } from "./util.js";
|
|
5
5
|
import * as path from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
|
-
import { Property, PropertyFlags, Schema,
|
|
8
|
-
import {
|
|
9
|
-
import { writeFileSync } from "fs";
|
|
7
|
+
import { Property, PropertyFlags, Schema, SourceSet } from "./types.js";
|
|
8
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
10
9
|
import { CustomTransform } from "./linkers/custom.js";
|
|
11
10
|
let indent = " ";
|
|
12
11
|
let id = 0;
|
|
13
|
-
const WRITE = process.env["JSON_WRITE"];
|
|
14
|
-
const rawValue = process.env["JSON_DEBUG"];
|
|
12
|
+
const WRITE = process.env["JSON_WRITE"]?.trim();
|
|
13
|
+
const rawValue = process.env["JSON_DEBUG"]?.trim();
|
|
15
14
|
const DEBUG = rawValue === "true" ? 1 : rawValue === "false" || rawValue === "" ? 0 : isNaN(Number(rawValue)) ? 0 : Number(rawValue);
|
|
16
15
|
const STRICT = process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "true";
|
|
17
16
|
export class JSONTransform extends Visitor {
|
|
@@ -21,8 +20,7 @@ export class JSONTransform extends Visitor {
|
|
|
21
20
|
parser;
|
|
22
21
|
schemas = new Map();
|
|
23
22
|
schema;
|
|
24
|
-
|
|
25
|
-
sources = new Map();
|
|
23
|
+
sources = new SourceSet();
|
|
26
24
|
imports = [];
|
|
27
25
|
simdStatements = [];
|
|
28
26
|
visitedClasses = new Set();
|
|
@@ -43,14 +41,9 @@ export class JSONTransform extends Visitor {
|
|
|
43
41
|
return name === "json" || name === "serializable";
|
|
44
42
|
}))
|
|
45
43
|
return;
|
|
46
|
-
const source = node.range.source;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
this.sources.set(source.internalPath, this.src);
|
|
50
|
-
}
|
|
51
|
-
else
|
|
52
|
-
this.src = this.sources.get(source.internalPath);
|
|
53
|
-
if (this.visitedClasses.has(source.internalPath + node.name.text))
|
|
44
|
+
const source = this.sources.get(node.range.source);
|
|
45
|
+
const fullClassPath = source.getFullPath(node);
|
|
46
|
+
if (this.visitedClasses.has(fullClassPath))
|
|
54
47
|
return;
|
|
55
48
|
if (!this.schemas.has(source.internalPath))
|
|
56
49
|
this.schemas.set(source.internalPath, []);
|
|
@@ -59,9 +52,9 @@ export class JSONTransform extends Visitor {
|
|
|
59
52
|
const deserializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "deserializer"))];
|
|
60
53
|
const schema = new Schema();
|
|
61
54
|
schema.node = node;
|
|
62
|
-
schema.name = node
|
|
55
|
+
schema.name = source.getQualifiedName(node);
|
|
63
56
|
if (node.extendsType) {
|
|
64
|
-
const extendsName = node
|
|
57
|
+
const extendsName = source.resolveExtendsName(node);
|
|
65
58
|
if (!schema.parent) {
|
|
66
59
|
const depSearch = schema.deps.find((v) => v.name == extendsName);
|
|
67
60
|
if (depSearch) {
|
|
@@ -72,36 +65,37 @@ export class JSONTransform extends Visitor {
|
|
|
72
65
|
schema.parent = depSearch;
|
|
73
66
|
}
|
|
74
67
|
else {
|
|
75
|
-
const internalSearch = getClass(extendsName
|
|
68
|
+
const internalSearch = source.getClass(extendsName);
|
|
76
69
|
if (internalSearch) {
|
|
77
70
|
if (DEBUG > 0)
|
|
78
71
|
console.log("Found " + extendsName + " internally from " + source.internalPath);
|
|
79
|
-
if (!this.visitedClasses.has(
|
|
72
|
+
if (!this.visitedClasses.has(source.getFullPath(internalSearch))) {
|
|
80
73
|
this.visitClassDeclarationRef(internalSearch);
|
|
81
74
|
this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
|
|
82
75
|
this.visitClassDeclaration(node);
|
|
83
76
|
return;
|
|
84
77
|
}
|
|
85
|
-
const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name ==
|
|
78
|
+
const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name == extendsName);
|
|
86
79
|
if (!schem)
|
|
87
80
|
throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
|
|
88
81
|
schema.deps.push(schem);
|
|
89
82
|
schema.parent = schem;
|
|
90
83
|
}
|
|
91
84
|
else {
|
|
92
|
-
const externalSearch = getImportedClass(extendsName,
|
|
85
|
+
const externalSearch = source.getImportedClass(extendsName, this.parser);
|
|
93
86
|
if (externalSearch) {
|
|
94
87
|
if (DEBUG > 0)
|
|
95
88
|
console.log("Found " + externalSearch.name.text + " externally from " + source.internalPath);
|
|
96
|
-
|
|
89
|
+
const externalSource = this.sources.get(externalSearch.range.source);
|
|
90
|
+
if (!this.visitedClasses.has(externalSource.getFullPath(externalSearch))) {
|
|
97
91
|
this.visitClassDeclarationRef(externalSearch);
|
|
98
|
-
this.schemas.get(
|
|
92
|
+
this.schemas.get(externalSource.internalPath).push(this.schema);
|
|
99
93
|
this.visitClassDeclaration(node);
|
|
100
94
|
return;
|
|
101
95
|
}
|
|
102
|
-
const schem = this.schemas.get(
|
|
96
|
+
const schem = this.schemas.get(externalSource.internalPath)?.find((s) => s.name == extendsName);
|
|
103
97
|
if (!schem)
|
|
104
|
-
throw new Error("Could not find schema for " + externalSearch.name.text + " in " +
|
|
98
|
+
throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSource.internalPath);
|
|
105
99
|
schema.deps.push(schem);
|
|
106
100
|
schema.parent = schem;
|
|
107
101
|
}
|
|
@@ -119,7 +113,7 @@ export class JSONTransform extends Visitor {
|
|
|
119
113
|
}
|
|
120
114
|
const getUnknownTypes = (type, types = []) => {
|
|
121
115
|
type = stripNull(type);
|
|
122
|
-
type =
|
|
116
|
+
type = source.aliases.find((v) => stripNull(v.name) == type)?.getBaseType() || type;
|
|
123
117
|
if (type.startsWith("Array<")) {
|
|
124
118
|
return getUnknownTypes(type.slice(6, -1));
|
|
125
119
|
}
|
|
@@ -155,39 +149,40 @@ export class JSONTransform extends Visitor {
|
|
|
155
149
|
}
|
|
156
150
|
}
|
|
157
151
|
else {
|
|
158
|
-
const internalSearch = getClass(unknownType
|
|
152
|
+
const internalSearch = source.getClass(unknownType);
|
|
159
153
|
if (internalSearch) {
|
|
160
154
|
if (DEBUG > 0)
|
|
161
155
|
console.log("Found " + unknownType + " internally from " + source.internalPath);
|
|
162
|
-
if (!this.visitedClasses.has(
|
|
156
|
+
if (!this.visitedClasses.has(source.getFullPath(internalSearch))) {
|
|
163
157
|
this.visitClassDeclarationRef(internalSearch);
|
|
164
|
-
const internalSchema = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name ==
|
|
158
|
+
const internalSchema = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name == unknownType);
|
|
165
159
|
schema.deps.push(internalSchema);
|
|
166
160
|
this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
|
|
167
161
|
this.visitClassDeclaration(node);
|
|
168
162
|
return;
|
|
169
163
|
}
|
|
170
|
-
const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name ==
|
|
164
|
+
const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name == unknownType);
|
|
171
165
|
if (!schem)
|
|
172
166
|
throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
|
|
173
167
|
schema.deps.push(schem);
|
|
174
168
|
}
|
|
175
169
|
else {
|
|
176
|
-
const externalSearch = getImportedClass(unknownType,
|
|
170
|
+
const externalSearch = source.getImportedClass(unknownType, this.parser);
|
|
177
171
|
if (externalSearch) {
|
|
178
172
|
if (DEBUG > 0)
|
|
179
173
|
console.log("Found " + externalSearch.name.text + " externally from " + source.internalPath);
|
|
180
|
-
|
|
174
|
+
const externalSource = this.sources.get(externalSearch.range.source);
|
|
175
|
+
if (!this.visitedClasses.has(externalSource.getFullPath(externalSearch))) {
|
|
181
176
|
this.visitClassDeclarationRef(externalSearch);
|
|
182
|
-
const externalSchema = this.schemas.get(
|
|
177
|
+
const externalSchema = this.schemas.get(externalSource.internalPath)?.find((s) => s.name == unknownType);
|
|
183
178
|
schema.deps.push(externalSchema);
|
|
184
|
-
this.schemas.get(
|
|
179
|
+
this.schemas.get(externalSource.internalPath).push(this.schema);
|
|
185
180
|
this.visitClassDeclaration(node);
|
|
186
181
|
return;
|
|
187
182
|
}
|
|
188
|
-
const schem = this.schemas.get(
|
|
183
|
+
const schem = this.schemas.get(externalSource.internalPath)?.find((s) => s.name == unknownType);
|
|
189
184
|
if (!schem)
|
|
190
|
-
throw new Error("Could not find schema for " + externalSearch.name.text + " in " +
|
|
185
|
+
throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSource.internalPath);
|
|
191
186
|
schema.deps.push(schem);
|
|
192
187
|
}
|
|
193
188
|
}
|
|
@@ -196,7 +191,7 @@ export class JSONTransform extends Visitor {
|
|
|
196
191
|
}
|
|
197
192
|
this.schemas.get(source.internalPath).push(schema);
|
|
198
193
|
this.schema = schema;
|
|
199
|
-
this.visitedClasses.add(
|
|
194
|
+
this.visitedClasses.add(fullClassPath);
|
|
200
195
|
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
|
|
201
196
|
let INITIALIZE = "@inline __INITIALIZE(): this {\n";
|
|
202
197
|
let DESERIALIZE = "__DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n";
|
|
@@ -257,7 +252,7 @@ export class JSONTransform extends Visitor {
|
|
|
257
252
|
if (!member.type)
|
|
258
253
|
throwError("Fields must be strongly typed", node.range);
|
|
259
254
|
let type = toString(member.type);
|
|
260
|
-
type =
|
|
255
|
+
type = source.aliases.find((v) => stripNull(v.name) == stripNull(type))?.getBaseType() || type;
|
|
261
256
|
const name = member.name;
|
|
262
257
|
const value = member.initializer ? toString(member.initializer) : null;
|
|
263
258
|
if (type.startsWith("(") && type.includes("=>"))
|
|
@@ -324,8 +319,8 @@ export class JSONTransform extends Visitor {
|
|
|
324
319
|
const aliasName = JSON.stringify(member.alias || member.name);
|
|
325
320
|
const realName = member.name;
|
|
326
321
|
const isLast = i == this.schema.members.length - 1;
|
|
327
|
-
if (member.value
|
|
328
|
-
if (
|
|
322
|
+
if (member.value) {
|
|
323
|
+
if (member.value != "null" && member.value != "0" && member.value != "0.0" && member.value != "false") {
|
|
329
324
|
INITIALIZE += ` store<${member.type}>(changetype<usize>(this), ${member.value}, offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
330
325
|
}
|
|
331
326
|
}
|
|
@@ -938,7 +933,7 @@ export class JSONTransform extends Visitor {
|
|
|
938
933
|
generateEmptyMethods(node) {
|
|
939
934
|
let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
|
|
940
935
|
let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
|
|
941
|
-
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return
|
|
936
|
+
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return out;\n}";
|
|
942
937
|
if (DEBUG > 0) {
|
|
943
938
|
console.log(SERIALIZE_EMPTY);
|
|
944
939
|
console.log(INITIALIZE_EMPTY);
|
|
@@ -965,14 +960,22 @@ export class JSONTransform extends Visitor {
|
|
|
965
960
|
addImports(node) {
|
|
966
961
|
this.baseCWD = this.baseCWD.replaceAll("/", path.sep);
|
|
967
962
|
const baseDir = path.resolve(fileURLToPath(import.meta.url), "..", "..", "..");
|
|
968
|
-
const pkgPath = path.join(this.baseCWD, "node_modules");
|
|
969
963
|
let fromPath = node.range.source.normalizedPath.replaceAll("/", path.sep);
|
|
964
|
+
const isLib = path.dirname(baseDir).endsWith("node_modules");
|
|
965
|
+
if (!isLib && !this.parser.sources.some((s) => s.normalizedPath.startsWith("assembly/index"))) {
|
|
966
|
+
const newPath = "./assembly/index.ts";
|
|
967
|
+
this.parser.parseFile(readFileSync(path.join(...newPath.split("/"))).toString(), newPath, false);
|
|
968
|
+
}
|
|
969
|
+
else if (isLib && !this.parser.sources.some((s) => s.normalizedPath.startsWith("~lib/json-as/assembly/index"))) {
|
|
970
|
+
const newPath = "~lib/json-as/assembly/index.ts";
|
|
971
|
+
this.parser.parseFile(readFileSync(path.join(...newPath.split("/"))).toString(), newPath, false);
|
|
972
|
+
}
|
|
970
973
|
fromPath = fromPath.startsWith("~lib") ? fromPath.slice(5) : path.join(this.baseCWD, fromPath);
|
|
971
974
|
const bsImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "bs" || d.name.text == "bs"));
|
|
972
975
|
const jsonImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "JSON" || d.name.text == "JSON"));
|
|
973
976
|
let baseRel = path.posix.join(...path.relative(path.dirname(fromPath), path.join(baseDir)).split(path.sep));
|
|
974
|
-
if (baseRel.endsWith("
|
|
975
|
-
baseRel = "json-as" + baseRel.slice(baseRel.indexOf("
|
|
977
|
+
if (baseRel.endsWith("json-as")) {
|
|
978
|
+
baseRel = "json-as" + baseRel.slice(baseRel.indexOf("json-as") + 7);
|
|
976
979
|
}
|
|
977
980
|
else if (!baseRel.startsWith(".") && !baseRel.startsWith("/") && !baseRel.startsWith("json-as")) {
|
|
978
981
|
baseRel = "./" + baseRel;
|
|
@@ -1217,16 +1220,6 @@ function isPrimitive(type) {
|
|
|
1217
1220
|
function isBoolean(type) {
|
|
1218
1221
|
return type == "bool" || type == "boolean";
|
|
1219
1222
|
}
|
|
1220
|
-
function isStruct(type) {
|
|
1221
|
-
type = stripNull(type);
|
|
1222
|
-
const schema = JSONTransform.SN.schema;
|
|
1223
|
-
if (schema.name == type)
|
|
1224
|
-
return true;
|
|
1225
|
-
const depSearch = schema.deps.some((v) => v.name == type);
|
|
1226
|
-
if (depSearch)
|
|
1227
|
-
return true;
|
|
1228
|
-
return false;
|
|
1229
|
-
}
|
|
1230
1223
|
function isString(type) {
|
|
1231
1224
|
return stripNull(type) == "string" || stripNull(type) == "String";
|
|
1232
1225
|
}
|