as-test 1.3.0 → 1.4.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.
@@ -17,6 +17,7 @@ class DefaultReporter {
17
17
  this.fileHasWarning = false;
18
18
  this.verboseMode = false;
19
19
  this.cleanMode = false;
20
+ this.showLogsMode = false;
20
21
  this.hasRenderedTestFiles = false;
21
22
  this.hasRenderedFuzzFiles = false;
22
23
  }
@@ -127,6 +128,7 @@ class DefaultReporter {
127
128
  onRunStart(event) {
128
129
  this.verboseMode = Boolean(event.verbose);
129
130
  this.cleanMode = Boolean(event.clean);
131
+ this.showLogsMode = Boolean(event.showLogs);
130
132
  this.hasRenderedTestFiles = false;
131
133
  this.hasRenderedFuzzFiles = false;
132
134
  }
@@ -270,6 +272,9 @@ class DefaultReporter {
270
272
  }
271
273
  onLog(event) {
272
274
  if (this.cleanMode) return;
275
+ // With --show-logs we print one clean grouped block at the end instead of
276
+ // streaming inline, so suppress the inline emit here.
277
+ if (this.showLogsMode) return;
273
278
  if (this.verboseMode || !this.canRewriteLine()) {
274
279
  const depth = Math.max(event.depth, 0);
275
280
  this.context.stdout.write(
@@ -295,6 +300,35 @@ class DefaultReporter {
295
300
  }
296
301
  }
297
302
  renderTotals(event.stats, event);
303
+ this.renderLogs(event);
304
+ }
305
+ // After the totals: either point the user at the aggregated log file (default)
306
+ // or, with --show-logs, print the captured logs (the same cross-mode-deduped
307
+ // body that was written to latest.log). Skipped in clean mode. When logs were
308
+ // already streamed inline (verbose or a non-TTY stream), we only re-point at
309
+ // the file rather than printing them twice.
310
+ renderLogs(event) {
311
+ if (this.cleanMode) return;
312
+ const summary = event.logSummary;
313
+ if (!summary || summary.count <= 0) return;
314
+ const out = this.context.stdout;
315
+ const plural = summary.count === 1 ? "" : "s";
316
+ // --show-logs: print the clean, cross-mode-deduped block (inline streaming
317
+ // was suppressed in onLog). Otherwise just point at the aggregated file —
318
+ // unless logs were already streamed inline (verbose / non-TTY).
319
+ if (event.showLogs && summary.text) {
320
+ out.write(`\n${chalk.bold(`Logs (${summary.count})`)}\n\n`);
321
+ out.write(
322
+ summary.text.endsWith("\n") ? summary.text : `${summary.text}\n`,
323
+ );
324
+ return;
325
+ }
326
+ const shownInline = this.verboseMode || !this.canRewriteLine();
327
+ const where = summary.file ? ` → ${chalk.cyan(summary.file)}` : "";
328
+ out.write(`\n${summary.count} log${plural} captured${where}\n`);
329
+ if (!shownInline && summary.file) {
330
+ out.write(`${chalk.dim(" run with --show-logs to print them")}\n`);
331
+ }
298
332
  }
299
333
  onFuzzComplete(event) {
300
334
  renderFuzzSummary(this.context, event, this.hasRenderedTestFiles);
package/bin/util.js CHANGED
@@ -1554,6 +1554,15 @@ export function resolveArtifactPath(file, inputPatterns) {
1554
1554
  const rel = resolveSpecRelativePath(file, inputPatterns);
1555
1555
  return rel.replace(/\.ts$/i, ".wasm");
1556
1556
  }
1557
+ // Absolute path to the `.snap` file owned by a given spec.
1558
+ // assembly/__tests__/array.spec.ts -> <cwd>/<snapshotDir>/array.spec.snap
1559
+ export function resolveSnapshotPath(specFile, snapshotDir, inputPatterns) {
1560
+ const rel = resolveSpecRelativePath(specFile, inputPatterns).replace(
1561
+ /\.ts$/i,
1562
+ ".snap",
1563
+ );
1564
+ return resolve(process.cwd(), snapshotDir, rel);
1565
+ }
1557
1566
  function toComponents(absPath) {
1558
1567
  return absPath
1559
1568
  .split(/[\\/]+/)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "as-test",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "author": "Jairus Tanaka",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,9 +12,6 @@
12
12
  "typer-diff": "^1.1.1",
13
13
  "wipc-js": "^0.1.1"
14
14
  },
15
- "peerDependencies": {
16
- "json-as": ">=1.3.5"
17
- },
18
15
  "devDependencies": {
19
16
  "@assemblyscript/wasi-shim": "^0.1.0",
20
17
  "@eslint/js": "^10.0.1",
@@ -24,7 +21,6 @@
24
21
  "assemblyscript": "^0.28.17",
25
22
  "assemblyscript-prettier": "^3.0.4",
26
23
  "husky": "^9.1.7",
27
- "json-as": "^1.3.7",
28
24
  "playwright": "^1.60.0",
29
25
  "prettier": "3.8.3",
30
26
  "try-as": "^1.1.0",
@@ -92,8 +88,8 @@
92
88
  "typecheck": "tsc -p cli --noEmit && tsc -p tsconfig.lib.json --noEmit && tsc -p transform --noEmit",
93
89
  "lint": "eslint transform/src/**/*.ts tools/**/*.js eslint.config.js",
94
90
  "build:lib": "tsc -p ./tsconfig.lib.json",
95
- "build:transform": "tsc -p ./transform && prettier -w ./transform/",
96
- "build:cli": "tsc -p cli",
91
+ "build:transform": "rm -rf ./transform/lib && tsc -p ./transform && prettier -w ./transform/",
92
+ "build:cli": "rm -rf ./bin/ && tsc -p cli && prettier -w ./cli/ && chmod +x ./bin/index.js",
97
93
  "build:run": "npm run build:cli",
98
94
  "docs:dev": "vitepress dev docs",
99
95
  "docs:build": "vitepress build docs",
@@ -0,0 +1,388 @@
1
+ import { Source, Tokenizer, } from "assemblyscript/dist/assemblyscript.js";
2
+ import { NodeKind } from "./types.js";
3
+ import { readFileSync } from "fs";
4
+ import { join } from "path";
5
+ import { SimpleParser, isStdlib } from "./util.js";
6
+ const EQUALS_METHOD = "__AS_TEST_EQUALS";
7
+ const TOJSON_METHOD = "toJSON";
8
+ const REFLECT_LOCAL = "__AS_TEST_REFLECT_EQUALS_INTERNAL";
9
+ const STRINGIFY_LOCAL = "__AS_TEST_STRINGIFY_INTERNAL";
10
+ const ALREADY_INJECTED_EQUALS = new WeakSet();
11
+ const ALREADY_INJECTED_TOJSON = new WeakSet();
12
+ const JSON_DECORATORS = ["json", "serializable"];
13
+ export class EqualsTransform {
14
+ parser;
15
+ touchedSources = new Set();
16
+ classesByName = new Map();
17
+ constructor(parser) {
18
+ this.parser = parser;
19
+ }
20
+ apply(sources) {
21
+ for (const source of sources) {
22
+ if (isStdlib(source))
23
+ continue;
24
+ if (!isUserSource(source))
25
+ continue;
26
+ if (isAsTestInternal(source))
27
+ continue;
28
+ this.indexClasses(source.statements);
29
+ }
30
+ for (const source of this.parser.sources) {
31
+ if (isStdlib(source))
32
+ continue;
33
+ if (!isUserSource(source))
34
+ continue;
35
+ if (isAsTestInternal(source))
36
+ continue;
37
+ this.traverseStatements(source, source.statements);
38
+ }
39
+ for (const source of this.touchedSources) {
40
+ this.injectRuntimeImports(source);
41
+ }
42
+ }
43
+ indexClasses(statements) {
44
+ for (const stmt of statements) {
45
+ if (!stmt)
46
+ continue;
47
+ if (stmt.kind === NodeKind.ClassDeclaration) {
48
+ const klass = stmt;
49
+ const list = this.classesByName.get(klass.name.text);
50
+ if (list)
51
+ list.push(klass);
52
+ else
53
+ this.classesByName.set(klass.name.text, [klass]);
54
+ }
55
+ else if (stmt.kind === NodeKind.NamespaceDeclaration) {
56
+ const members = stmt.members;
57
+ if (members)
58
+ this.indexClasses(members);
59
+ }
60
+ }
61
+ }
62
+ traverseStatements(source, statements) {
63
+ for (const stmt of statements) {
64
+ if (!stmt)
65
+ continue;
66
+ if (stmt.kind === NodeKind.ClassDeclaration) {
67
+ const klass = stmt;
68
+ const injectedEquals = this.injectEqualsMethod(klass);
69
+ const injectedToJSON = this.injectToJSONMethod(klass);
70
+ if (injectedEquals || injectedToJSON) {
71
+ this.touchedSources.add(source);
72
+ }
73
+ }
74
+ else if (stmt.kind === NodeKind.NamespaceDeclaration) {
75
+ const members = stmt.members;
76
+ if (members)
77
+ this.traverseStatements(source, members);
78
+ }
79
+ }
80
+ }
81
+ injectEqualsMethod(klass) {
82
+ if (ALREADY_INJECTED_EQUALS.has(klass))
83
+ return false;
84
+ if (declaresMethod(klass, EQUALS_METHOD))
85
+ return false;
86
+ if (klass.typeParameters && klass.typeParameters.length)
87
+ return false;
88
+ const fieldNames = [];
89
+ for (const member of klass.members) {
90
+ if (member.kind !== NodeKind.FieldDeclaration)
91
+ continue;
92
+ const field = member;
93
+ if (!field.is(262144))
94
+ continue;
95
+ if ((field.flags & 32) !== 0)
96
+ continue;
97
+ if (!field.name || !field.name.text)
98
+ continue;
99
+ fieldNames.push(field.name.text);
100
+ }
101
+ const fieldHashes = fieldNames.map((n) => djb2Hash(n).toString());
102
+ const className = klass.name.text;
103
+ const otherType = this.pinnedOtherType(klass);
104
+ const lines = [];
105
+ lines.push(`const __o = changetype<${className}>(other);`);
106
+ for (let i = 0; i < fieldNames.length; i++) {
107
+ const name = fieldNames[i];
108
+ const hash = fieldHashes[i];
109
+ lines.push(`if (!ignore.includes(${hash}) && ` +
110
+ `!${REFLECT_LOCAL}(this.${name}, __o.${name}, stack, strict)) return false;`);
111
+ }
112
+ const ignoreLiteral = fieldHashes.length
113
+ ? `[${fieldHashes.join(", ")}] as StaticArray<i64>`
114
+ : `[] as StaticArray<i64>`;
115
+ lines.push(`if (isDefined(super.__AS_TEST_EQUALS)) {` +
116
+ ` if (!super.__AS_TEST_EQUALS(other, stack, ` +
117
+ `StaticArray.concat<i64>(ignore, ${ignoreLiteral}), strict)) return false;` +
118
+ ` }`);
119
+ lines.push(`return true;`);
120
+ const code = `${EQUALS_METHOD}(` +
121
+ `other: ${otherType}, ` +
122
+ `stack: usize[], ` +
123
+ `ignore: StaticArray<i64>, ` +
124
+ `strict: bool` +
125
+ `): bool { ${lines.join(" ")} }`;
126
+ try {
127
+ const method = SimpleParser.parseClassMember(code, klass);
128
+ klass.members.push(method);
129
+ ALREADY_INJECTED_EQUALS.add(klass);
130
+ return true;
131
+ }
132
+ catch {
133
+ return false;
134
+ }
135
+ }
136
+ pinnedOtherType(klass) {
137
+ const seen = new Set();
138
+ let current = klass;
139
+ let rootName = klass.name.text;
140
+ while (current && !seen.has(current)) {
141
+ seen.add(current);
142
+ const userType = userDeclaredEqualsOtherType(current);
143
+ if (userType)
144
+ return userType;
145
+ rootName = current.name.text;
146
+ const parentName = extendsName(current);
147
+ if (!parentName)
148
+ return rootName;
149
+ const parents = this.classesByName.get(parentName);
150
+ if (!parents || parents.length === 0)
151
+ return rootName;
152
+ current = parents[0];
153
+ }
154
+ return rootName;
155
+ }
156
+ injectRuntimeImports(source) {
157
+ const asTestPath = detectAsTestImportPath(source.text) ?? "as-test";
158
+ const importLine = `import { reflectEquals as ${REFLECT_LOCAL}, ` +
159
+ `__as_test_stringify as ${STRINGIFY_LOCAL} } from "${asTestPath}";`;
160
+ const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, importLine));
161
+ this.parser.currentSource = tokenizer.source;
162
+ source.statements.unshift(this.parser.parseTopLevelStatement(tokenizer));
163
+ this.parser.currentSource = source;
164
+ }
165
+ injectToJSONMethod(klass) {
166
+ if (ALREADY_INJECTED_TOJSON.has(klass))
167
+ return false;
168
+ if (declaresMethod(klass, TOJSON_METHOD))
169
+ return false;
170
+ if (hasAnyDecorator(klass, JSON_DECORATORS))
171
+ return false;
172
+ if (klass.typeParameters && klass.typeParameters.length)
173
+ return false;
174
+ const fieldNames = this.collectChainFieldNames(klass);
175
+ const chainNames = this.collectChainClassNames(klass);
176
+ const renderable = [];
177
+ for (const name of fieldNames) {
178
+ const fieldType = this.fieldTypeName(klass, name);
179
+ if (fieldType && chainNames.has(fieldType))
180
+ continue;
181
+ renderable.push(name);
182
+ }
183
+ const parts = [];
184
+ for (let i = 0; i < renderable.length; i++) {
185
+ const name = renderable[i];
186
+ const prefix = i === 0 ? "" : ",";
187
+ parts.push(`"${prefix}\\"${name}\\":" + ${STRINGIFY_LOCAL}(this.${name})`);
188
+ }
189
+ const body = parts.length
190
+ ? `return "{" + ${parts.join(" + ")} + "}";`
191
+ : `return "{}";`;
192
+ const code = `toJSON(): string { ${body} }`;
193
+ try {
194
+ const method = SimpleParser.parseClassMember(code, klass);
195
+ klass.members.push(method);
196
+ ALREADY_INJECTED_TOJSON.add(klass);
197
+ return true;
198
+ }
199
+ catch {
200
+ return false;
201
+ }
202
+ }
203
+ collectChainFieldNames(klass) {
204
+ const chain = [];
205
+ const seen = new Set();
206
+ let current = klass;
207
+ while (current && !seen.has(current)) {
208
+ seen.add(current);
209
+ chain.unshift(current);
210
+ const parentName = extendsName(current);
211
+ if (!parentName)
212
+ break;
213
+ const parents = this.classesByName.get(parentName);
214
+ if (!parents || parents.length === 0)
215
+ break;
216
+ current = parents[0];
217
+ }
218
+ const ordered = [];
219
+ const known = new Set();
220
+ for (const cls of chain) {
221
+ for (const member of cls.members) {
222
+ if (member.kind !== NodeKind.FieldDeclaration)
223
+ continue;
224
+ const field = member;
225
+ if (!field.is(262144))
226
+ continue;
227
+ if ((field.flags & 32) !== 0)
228
+ continue;
229
+ if (!field.name || !field.name.text)
230
+ continue;
231
+ const name = field.name.text;
232
+ if (known.has(name))
233
+ continue;
234
+ known.add(name);
235
+ ordered.push(name);
236
+ }
237
+ }
238
+ return ordered;
239
+ }
240
+ collectChainClassNames(klass) {
241
+ const out = new Set();
242
+ const seen = new Set();
243
+ let current = klass;
244
+ while (current && !seen.has(current)) {
245
+ seen.add(current);
246
+ out.add(current.name.text);
247
+ const parentName = extendsName(current);
248
+ if (!parentName)
249
+ break;
250
+ const parents = this.classesByName.get(parentName);
251
+ if (!parents || parents.length === 0)
252
+ break;
253
+ current = parents[0];
254
+ }
255
+ return out;
256
+ }
257
+ fieldTypeName(klass, fieldName) {
258
+ const seen = new Set();
259
+ let current = klass;
260
+ while (current && !seen.has(current)) {
261
+ seen.add(current);
262
+ for (const member of current.members) {
263
+ if (member.kind !== NodeKind.FieldDeclaration)
264
+ continue;
265
+ const field = member;
266
+ if (!field.name || field.name.text !== fieldName)
267
+ continue;
268
+ return namedTypeText(field.type);
269
+ }
270
+ const parentName = extendsName(current);
271
+ if (!parentName)
272
+ break;
273
+ const parents = this.classesByName.get(parentName);
274
+ if (!parents || parents.length === 0)
275
+ break;
276
+ current = parents[0];
277
+ }
278
+ return null;
279
+ }
280
+ }
281
+ function declaresMethod(klass, name) {
282
+ for (const member of klass.members) {
283
+ if (member.kind !== NodeKind.MethodDeclaration)
284
+ continue;
285
+ const method = member;
286
+ if (method.name && method.name.text === name)
287
+ return true;
288
+ }
289
+ return false;
290
+ }
291
+ function hasAnyDecorator(klass, names) {
292
+ if (!klass.decorators)
293
+ return false;
294
+ for (const dec of klass.decorators) {
295
+ const decName = dec.name.text;
296
+ if (decName && names.indexOf(decName) !== -1)
297
+ return true;
298
+ }
299
+ return false;
300
+ }
301
+ function userDeclaredEqualsOtherType(klass) {
302
+ for (const member of klass.members) {
303
+ if (member.kind !== NodeKind.MethodDeclaration)
304
+ continue;
305
+ const method = member;
306
+ if (!method.name || method.name.text !== EQUALS_METHOD)
307
+ continue;
308
+ const params = method.signature.parameters;
309
+ if (!params || params.length === 0)
310
+ return null;
311
+ return namedTypeText(params[0].type);
312
+ }
313
+ return null;
314
+ }
315
+ function extendsName(klass) {
316
+ const extendsType = klass
317
+ .extendsType;
318
+ if (!extendsType)
319
+ return null;
320
+ return namedTypeText(extendsType);
321
+ }
322
+ function namedTypeText(type) {
323
+ if (!type)
324
+ return null;
325
+ if (type.kind !== NodeKind.NamedType)
326
+ return null;
327
+ const named = type;
328
+ if (!named.name)
329
+ return null;
330
+ const ident = named.name
331
+ .identifier;
332
+ if (ident && typeof ident.text === "string")
333
+ return ident.text;
334
+ const text = named.name.text;
335
+ return text ?? null;
336
+ }
337
+ function isUserSource(source) {
338
+ return (source.sourceKind === 0 ||
339
+ source.sourceKind === 1);
340
+ }
341
+ let cachedIsAsTestCwd = null;
342
+ function isAsTestOwnCwd() {
343
+ if (cachedIsAsTestCwd !== null)
344
+ return cachedIsAsTestCwd;
345
+ try {
346
+ const raw = readFileSync(join(process.cwd(), "package.json"), "utf8");
347
+ const pkg = JSON.parse(raw);
348
+ cachedIsAsTestCwd = pkg.name === "as-test";
349
+ }
350
+ catch {
351
+ cachedIsAsTestCwd = false;
352
+ }
353
+ return cachedIsAsTestCwd;
354
+ }
355
+ function isAsTestInternal(source) {
356
+ const p = source.normalizedPath;
357
+ if (/(?:^|\/)as-test\/assembly\/(?!__tests__\/)/.test(p))
358
+ return true;
359
+ if (isAsTestOwnCwd() && /^assembly\/(?!__tests__\/)/.test(p))
360
+ return true;
361
+ return false;
362
+ }
363
+ function detectAsTestImportPath(sourceText) {
364
+ const text = sourceText
365
+ .replace(/\/\*[\s\S]*?\*\//g, "")
366
+ .replace(/\/\/.*$/gm, "");
367
+ const imports = text.matchAll(/import\s*\{([^}]+)\}\s*from\s*["']([^"']+)["']/g);
368
+ for (const match of imports) {
369
+ const specifiers = match[1] ?? "";
370
+ const modulePath = (match[2] ?? "").trim();
371
+ if (!modulePath.length)
372
+ continue;
373
+ if (modulePath === "as-test" || modulePath.endsWith("/as-test")) {
374
+ return modulePath;
375
+ }
376
+ if (/\b(?:describe|test|it|expect|beforeAll|afterAll|beforeEach|afterEach|mockFn|unmockFn|mockImport|unmockImport|snapshotFn|log|run)\b/.test(specifiers)) {
377
+ return modulePath;
378
+ }
379
+ }
380
+ return null;
381
+ }
382
+ function djb2Hash(s) {
383
+ let h = 5381;
384
+ for (let i = 0; i < s.length; i++) {
385
+ h = ((h << 5) + h + s.charCodeAt(i)) | 0;
386
+ }
387
+ return h >>> 0;
388
+ }
@@ -4,6 +4,7 @@ import { CoverageTransform } from "./coverage.js";
4
4
  import { MockTransform } from "./mock.js";
5
5
  import { LocationTransform } from "./location.js";
6
6
  import { LogTransform } from "./log.js";
7
+ import { EqualsTransform } from "./equals.js";
7
8
  import { isStdlib } from "./util.js";
8
9
  import { NodeKind } from "./types.js";
9
10
  export default class Transformer extends Transform {
@@ -81,6 +82,7 @@ export default class Transformer extends Transform {
81
82
  if (coverage) {
82
83
  coverage.globalStatements = [];
83
84
  }
85
+ new EqualsTransform(parser).apply(parser.sources);
84
86
  }
85
87
  }
86
88
  function patchModeName(parser, modeName) {
@@ -4,7 +4,7 @@ import { toString } from "./util.js";
4
4
  const LOG_CALL_FN = "__as_test_log_call";
5
5
  const LOG_ENABLED_IMPORT = "__as_test_log_is_enabled_internal";
6
6
  const LOG_SERIALIZED_IMPORT = "__as_test_log_serialized_internal";
7
- const LOG_JSON_IMPORT = "__as_test_log_json_internal";
7
+ const LOG_STRINGIFY_IMPORT = "__as_test_log_stringify_internal";
8
8
  export class LogTransform extends Visitor {
9
9
  parser;
10
10
  activeSource = null;
@@ -27,15 +27,11 @@ export class LogTransform extends Visitor {
27
27
  return;
28
28
  }
29
29
  const asTestPath = detectAsTestImportPath(node.text) ?? "as-test";
30
- const asTestTokenizer = new Tokenizer(new Source(0, node.normalizedPath, `import { __as_test_log_is_enabled as ${LOG_ENABLED_IMPORT}, __as_test_log_serialized as ${LOG_SERIALIZED_IMPORT} } from "${asTestPath}";`));
30
+ const asTestTokenizer = new Tokenizer(new Source(0, node.normalizedPath, `import { __as_test_log_is_enabled as ${LOG_ENABLED_IMPORT}, __as_test_log_serialized as ${LOG_SERIALIZED_IMPORT}, __as_test_stringify as ${LOG_STRINGIFY_IMPORT} } from "${asTestPath}";`));
31
31
  this.parser.currentSource = asTestTokenizer.source;
32
32
  node.statements.unshift(this.parser.parseTopLevelStatement(asTestTokenizer));
33
33
  this.parser.currentSource = node;
34
- const jsonTokenizer = new Tokenizer(new Source(0, node.normalizedPath, `import { JSON as ${LOG_JSON_IMPORT} } from "json-as/assembly";`));
35
- this.parser.currentSource = jsonTokenizer.source;
36
- node.statements.unshift(this.parser.parseTopLevelStatement(jsonTokenizer));
37
- this.parser.currentSource = node;
38
- const callTokenizer = new Tokenizer(new Source(0, node.normalizedPath, `function ${LOG_CALL_FN}<T>(value: T): void { if (!${LOG_ENABLED_IMPORT}()) return; ${LOG_SERIALIZED_IMPORT}(${LOG_JSON_IMPORT}.stringify<T>(value)); }`));
34
+ const callTokenizer = new Tokenizer(new Source(0, node.normalizedPath, `function ${LOG_CALL_FN}<T>(value: T): void { if (!${LOG_ENABLED_IMPORT}()) return; ${LOG_SERIALIZED_IMPORT}(${LOG_STRINGIFY_IMPORT}<T>(value)); }`));
39
35
  this.parser.currentSource = callTokenizer.source;
40
36
  node.statements.push(this.parser.parseTopLevelStatement(callTokenizer));
41
37
  this.parser.currentSource = node;
@@ -1,6 +1,8 @@
1
1
  import * as asc from "assemblyscript/dist/assemblyscript.js";
2
- export const NodeKind = asc
3
- .NodeKind;
2
+ const ascRuntime = asc;
3
+ export const NodeKind = {};
4
+ for (const key in ascRuntime.NodeKind)
5
+ NodeKind[key] = ascRuntime.NodeKind[key];
4
6
  export var PropertyFlags;
5
7
  (function (PropertyFlags) {
6
8
  PropertyFlags[PropertyFlags["OmitNull"] = 0] = "OmitNull";