gofront 1.5.1 → 1.6.1
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/README.md +174 -466
- package/package.json +16 -20
- package/src/backend/js/expressions.js +288 -128
- package/src/backend/js/index.js +138 -56
- package/src/backend/js/runtime.js +1055 -53
- package/src/backend/js/source-map.js +32 -0
- package/src/backend/js/statements.js +151 -83
- package/src/backend/js/stdlib/base64.js +12 -0
- package/src/backend/js/stdlib/binary.js +102 -0
- package/src/backend/js/stdlib/bits.js +15 -1
- package/src/backend/js/stdlib/builder.js +28 -9
- package/src/backend/js/stdlib/bytes.js +75 -18
- package/src/backend/js/stdlib/errors.js +22 -3
- package/src/backend/js/stdlib/fmt.js +95 -20
- package/src/backend/js/stdlib/hex.js +17 -0
- package/src/backend/js/stdlib/html.js +1 -1
- package/src/backend/js/stdlib/index.js +19 -0
- package/src/backend/js/stdlib/io.js +105 -3
- package/src/backend/js/stdlib/maps.js +1 -1
- package/src/backend/js/stdlib/math.js +13 -1
- package/src/backend/js/stdlib/path.js +20 -6
- package/src/backend/js/stdlib/rand.js +10 -5
- package/src/backend/js/stdlib/sha256.js +12 -0
- package/src/backend/js/stdlib/shared.js +17 -0
- package/src/backend/js/stdlib/slices.js +53 -27
- package/src/backend/js/stdlib/sort.js +1 -1
- package/src/backend/js/stdlib/strconv.js +52 -11
- package/src/backend/js/stdlib/strings.js +152 -16
- package/src/backend/js/stdlib/sync.js +13 -0
- package/src/backend/js/stdlib/testing.js +2 -2
- package/src/backend/js/stdlib/time.js +93 -22
- package/src/backend/js/stdlib/unicode.js +2 -2
- package/src/backend/js/templ.js +1 -1
- package/src/backend/wasm/boundary.js +1677 -58
- package/src/backend/wasm/const-fold.js +205 -0
- package/src/backend/wasm/emit-builtins.js +1230 -0
- package/src/backend/wasm/emit-exprs.js +2096 -0
- package/src/backend/wasm/emit-maps.js +1999 -0
- package/src/backend/wasm/emit-shared.js +519 -0
- package/src/backend/wasm/emit-stdlib.js +13 -0
- package/src/backend/wasm/emit-stmts.js +2466 -0
- package/src/backend/wasm/emit.js +656 -5031
- package/src/backend/wasm/encode.js +259 -85
- package/src/backend/wasm/glue.js +19 -5
- package/src/backend/wasm/index.js +2432 -86
- package/src/backend/wasm/monomorph.js +711 -0
- package/src/backend/wasm/optimize.js +236 -0
- package/src/backend/wasm/stdlib/bytes.js +5039 -0
- package/src/backend/wasm/stdlib/core.js +8903 -0
- package/src/backend/wasm/stdlib/index.js +40 -0
- package/src/backend/wasm/stdlib/io.js +2161 -0
- package/src/backend/wasm/stdlib/packages.js +2400 -0
- package/src/backend/wasm/stdlib/pure.js +720 -0
- package/src/backend/wasm/stdlib/time.js +1200 -0
- package/src/backend/wasm/types.js +312 -36
- package/src/backend/wasm/wat.js +49 -2
- package/src/cli-core.js +276 -73
- package/src/compiler.js +162 -25
- package/src/dts-parser.js +79 -126
- package/src/index.js +88 -121
- package/src/lexer.js +80 -29
- package/src/lower/boxing.js +4 -6
- package/src/lower/captures.js +12 -23
- package/src/lower/escape.js +4 -9
- package/src/lower/functions.js +277 -5
- package/src/lower/globals.js +7 -15
- package/src/lower/index.js +5 -2
- package/src/lower/ownership.js +35 -19
- package/src/lower/range.js +2 -5
- package/src/lower/walk.js +25 -0
- package/src/minifier.js +20 -68
- package/src/parser/declarations.js +3 -6
- package/src/parser/expressions.js +3 -8
- package/src/parser/index.js +18 -3
- package/src/parser/statements.js +25 -38
- package/src/parser/types.js +1 -2
- package/src/resolver.js +3 -27
- package/src/templ-lexer.js +29 -63
- package/src/templ-parser.js +22 -45
- package/src/test-runner.js +20 -0
- package/src/typechecker/assignability.js +123 -14
- package/src/typechecker/expressions.js +244 -4
- package/src/typechecker/index.js +27 -1
- package/src/typechecker/resolve.js +71 -12
- package/src/typechecker/statements.js +0 -7
- package/src/typechecker/stdlib/core.js +292 -103
- package/src/typechecker/stdlib/extended.js +471 -4
- package/src/typechecker/stdlib/shared.js +53 -0
- package/src/typechecker/stdlib.js +2 -0
- package/src/typechecker/types.js +545 -8
- package/src/vendor.js +2 -2
package/src/compiler.js
CHANGED
|
@@ -18,9 +18,13 @@
|
|
|
18
18
|
// de-qualifies it because the dependency is inlined.
|
|
19
19
|
|
|
20
20
|
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
21
|
-
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
22
|
-
import {
|
|
23
|
-
|
|
21
|
+
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
22
|
+
import {
|
|
23
|
+
buildSourceMap,
|
|
24
|
+
buildWasmSourceMap,
|
|
25
|
+
CodeGen,
|
|
26
|
+
} from "./backend/js/index.js";
|
|
27
|
+
import { compileWasmModule, optimizeWasm } from "./backend/wasm/index.js";
|
|
24
28
|
import { log } from "./colors.js";
|
|
25
29
|
import { parseDts } from "./dts-parser.js";
|
|
26
30
|
import { Lexer } from "./lexer.js";
|
|
@@ -34,7 +38,7 @@ import {
|
|
|
34
38
|
} from "./resolver.js";
|
|
35
39
|
import { TemplLexer } from "./templ-lexer.js";
|
|
36
40
|
import { TemplParser } from "./templ-parser.js";
|
|
37
|
-
import { TypeChecker } from "./typechecker/index.js";
|
|
41
|
+
import { TypeCheckError, TypeChecker } from "./typechecker/index.js";
|
|
38
42
|
import { WASM_SUPPORTED_STDLIB } from "./typechecker/types.js";
|
|
39
43
|
|
|
40
44
|
// ── Parse cache ──────────────────────────────────────────────
|
|
@@ -67,6 +71,9 @@ function parseGoFrontFile(filePath) {
|
|
|
67
71
|
? new TemplParser(tokens, filename, source).parse()
|
|
68
72
|
: new Parser(tokens, filename, source).parse();
|
|
69
73
|
ast._source = source;
|
|
74
|
+
ast._path = resolve(filePath);
|
|
75
|
+
// compileFiles overwrites `target` with the resolved one; keep the directive.
|
|
76
|
+
ast._declaredTarget = ast.target;
|
|
70
77
|
_parseCache.set(filePath, { mtime, ast });
|
|
71
78
|
return ast;
|
|
72
79
|
}
|
|
@@ -163,6 +170,49 @@ function attachSourceMap(merged, outputDir) {
|
|
|
163
170
|
merged.js += `\n//# sourceMappingURL=data:application/json;base64,${b64}`;
|
|
164
171
|
}
|
|
165
172
|
|
|
173
|
+
const WASM_MAP_URL = "app.wasm.map";
|
|
174
|
+
|
|
175
|
+
// Function-level `app.wasm.map` (sources relative to the output dir).
|
|
176
|
+
function buildWasmMap(info, outputDir) {
|
|
177
|
+
if (!info || info.mappings.length === 0) return null;
|
|
178
|
+
return buildWasmSourceMap(
|
|
179
|
+
info.sources.map((f) => relative(outputDir, f)),
|
|
180
|
+
info.mappings,
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Shared tail of compileFiles / compileSingleFile: link `app.wasm`, run
|
|
185
|
+
// wasm-opt when requested and produce the wasm source map.
|
|
186
|
+
function finishWasm(options, merged, pkgTarget, outputDir) {
|
|
187
|
+
const wantMap = Boolean(options.sourceMap && !options.isDependency);
|
|
188
|
+
let { wasm, wat, sourceMapInfo } = linkIntoBundle(
|
|
189
|
+
options,
|
|
190
|
+
merged,
|
|
191
|
+
pkgTarget,
|
|
192
|
+
{
|
|
193
|
+
sourceMappingURL: wantMap ? WASM_MAP_URL : null,
|
|
194
|
+
},
|
|
195
|
+
);
|
|
196
|
+
let wasmOptInfo = null;
|
|
197
|
+
let wasmSourceMap =
|
|
198
|
+
wantMap && wasm ? buildWasmMap(sourceMapInfo, outputDir) : null;
|
|
199
|
+
|
|
200
|
+
if (wasm && options.wasmOpt) {
|
|
201
|
+
const opt = optimizeWasm(wasm, {
|
|
202
|
+
sourceMap: Boolean(wasmSourceMap),
|
|
203
|
+
inputSourceMap: wasmSourceMap,
|
|
204
|
+
sourceMapUrl: WASM_MAP_URL,
|
|
205
|
+
emitWat: Boolean(options.emitWat),
|
|
206
|
+
converge: Boolean(options.release),
|
|
207
|
+
});
|
|
208
|
+
wasm = opt.wasm;
|
|
209
|
+
if (opt.wat) wat = opt.wat;
|
|
210
|
+
wasmOptInfo = opt;
|
|
211
|
+
if (opt.sourceMap) wasmSourceMap = opt.sourceMap;
|
|
212
|
+
}
|
|
213
|
+
return { wasm, wat, wasmOptInfo, wasmSourceMap };
|
|
214
|
+
}
|
|
215
|
+
|
|
166
216
|
// ── WASM linking ──────────────────────────────────────────────
|
|
167
217
|
//
|
|
168
218
|
// Every `wasm`/`both` package reached during a build registers a unit in the
|
|
@@ -205,7 +255,10 @@ function registerPackageUnit(options, unit) {
|
|
|
205
255
|
return emitTarget;
|
|
206
256
|
}
|
|
207
257
|
|
|
208
|
-
function linkWasmUnits(
|
|
258
|
+
function linkWasmUnits(
|
|
259
|
+
units,
|
|
260
|
+
{ emitWat = false, rootTarget = "js", sourceMappingURL = null } = {},
|
|
261
|
+
) {
|
|
209
262
|
if (!units.some((u) => u.target === "wasm")) return null;
|
|
210
263
|
checkLinkCollisions(units);
|
|
211
264
|
|
|
@@ -217,13 +270,27 @@ function linkWasmUnits(units, { emitWat = false, rootTarget = "js" } = {}) {
|
|
|
217
270
|
for (const b of u.bundledPackages) bundledPackages.add(b);
|
|
218
271
|
programs.push(...u.programs);
|
|
219
272
|
}
|
|
220
|
-
const checker = {
|
|
273
|
+
const checker = {
|
|
274
|
+
types,
|
|
275
|
+
errors: [],
|
|
276
|
+
err(msg, node) {
|
|
277
|
+
const e = new TypeCheckError(
|
|
278
|
+
msg,
|
|
279
|
+
node,
|
|
280
|
+
this._currentFile,
|
|
281
|
+
this._currentSource,
|
|
282
|
+
);
|
|
283
|
+
this.errors.push(e);
|
|
284
|
+
return e;
|
|
285
|
+
},
|
|
286
|
+
};
|
|
221
287
|
const lowerRes = lower(programs, checker);
|
|
222
288
|
return compileWasmModule(programs, checker, lowerRes, {
|
|
223
289
|
boundary: true,
|
|
224
290
|
bundledPackages,
|
|
225
291
|
emitWat,
|
|
226
292
|
callMain: rootTarget === "wasm",
|
|
293
|
+
sourceMappingURL,
|
|
227
294
|
});
|
|
228
295
|
}
|
|
229
296
|
|
|
@@ -291,17 +358,23 @@ function spliceFacade(merged, facade) {
|
|
|
291
358
|
}
|
|
292
359
|
|
|
293
360
|
// Root compiles only: link every registered unit into app.wasm and splice the
|
|
294
|
-
// facade into the merged bundle. Returns `{ wasm, wat }`
|
|
295
|
-
// is nothing to link).
|
|
296
|
-
function linkIntoBundle(options, merged, pkgTarget) {
|
|
297
|
-
|
|
361
|
+
// facade into the merged bundle. Returns `{ wasm, wat, sourceMapInfo }`
|
|
362
|
+
// (nulls when there is nothing to link).
|
|
363
|
+
function linkIntoBundle(options, merged, pkgTarget, { sourceMappingURL } = {}) {
|
|
364
|
+
const none = { wasm: null, wat: null, sourceMapInfo: null };
|
|
365
|
+
if (options.isDependency) return none;
|
|
298
366
|
const linked = linkWasmUnits(options.wasmUnits, {
|
|
299
367
|
emitWat: options.emitWat,
|
|
300
368
|
rootTarget: pkgTarget,
|
|
369
|
+
sourceMappingURL,
|
|
301
370
|
});
|
|
302
|
-
if (!linked) return
|
|
371
|
+
if (!linked) return none;
|
|
303
372
|
spliceFacade(merged, linked.facade);
|
|
304
|
-
return {
|
|
373
|
+
return {
|
|
374
|
+
wasm: linked.wasm,
|
|
375
|
+
wat: linked.wat ?? null,
|
|
376
|
+
sourceMapInfo: linked.sourceMapInfo ?? null,
|
|
377
|
+
};
|
|
305
378
|
}
|
|
306
379
|
|
|
307
380
|
// ── Import resolution ─────────────────────────────────────────
|
|
@@ -309,7 +382,7 @@ function linkIntoBundle(options, merged, pkgTarget) {
|
|
|
309
382
|
// Shared by compileFiles (multi-file) and the single-file path in index.js.
|
|
310
383
|
// Mutates checker, jsImports, bundledPackages, and preambles in place.
|
|
311
384
|
|
|
312
|
-
|
|
385
|
+
function resolveImports(
|
|
313
386
|
programs,
|
|
314
387
|
fromFile,
|
|
315
388
|
checker,
|
|
@@ -350,6 +423,11 @@ export function resolveImports(
|
|
|
350
423
|
"package 'gom' is not available in wasm packages",
|
|
351
424
|
impNode,
|
|
352
425
|
);
|
|
426
|
+
} else if (path === "gofront/shared" && pkgTarget === "both") {
|
|
427
|
+
checker.err(
|
|
428
|
+
"'gofront/shared' requires a wasm-only package (//gofront:target wasm): a both package has no linear memory on the JS side",
|
|
429
|
+
impNode,
|
|
430
|
+
);
|
|
353
431
|
} else if (!isLocalPath(path)) {
|
|
354
432
|
if (!isBuiltinPackage(path)) {
|
|
355
433
|
checker.recordBlocker("js: import", path);
|
|
@@ -472,6 +550,7 @@ export function resolveImports(
|
|
|
472
550
|
nameUsed,
|
|
473
551
|
dep.exportedSymbols,
|
|
474
552
|
dep.exportedTypes,
|
|
553
|
+
dep.target,
|
|
475
554
|
);
|
|
476
555
|
checker.trackImport(nameUsed, { _line }, p._filename, p._source);
|
|
477
556
|
}
|
|
@@ -481,6 +560,29 @@ export function resolveImports(
|
|
|
481
560
|
|
|
482
561
|
// ── Main entry points ─────────────────────────────────────────
|
|
483
562
|
|
|
563
|
+
// Package target after build-time overrides (Task H6.3): `forceTarget`
|
|
564
|
+
// (`--js-only`) compiles every package to JS; `targetOverrides` maps package
|
|
565
|
+
// directories relative to the root source dir (`"engine/physics"`, `"."` for
|
|
566
|
+
// the root) to a target, replacing the `//gofront:target` directive.
|
|
567
|
+
const PACKAGE_TARGETS = new Set(["js", "wasm", "both"]);
|
|
568
|
+
|
|
569
|
+
export function resolvePackageTarget(declared, pkgDir, options = {}) {
|
|
570
|
+
if (options.forceTarget) return options.forceTarget;
|
|
571
|
+
const overrides = options.targetOverrides;
|
|
572
|
+
if (!overrides || !options.rootDir) return declared;
|
|
573
|
+
const rel = relative(resolve(options.rootDir), resolve(pkgDir))
|
|
574
|
+
.split(sep)
|
|
575
|
+
.join("/");
|
|
576
|
+
const key = rel === "" ? "." : rel;
|
|
577
|
+
const t = overrides[key] ?? (key === "." ? overrides[""] : undefined);
|
|
578
|
+
if (t === undefined) return declared;
|
|
579
|
+
if (!PACKAGE_TARGETS.has(t))
|
|
580
|
+
throw new Error(
|
|
581
|
+
`gofront.json: invalid target '${t}' for package '${key}' (expected js, wasm or both)`,
|
|
582
|
+
);
|
|
583
|
+
return t;
|
|
584
|
+
}
|
|
585
|
+
|
|
484
586
|
export function compileSingleFile(inputPath, options = {}) {
|
|
485
587
|
const {
|
|
486
588
|
sourceMap = false,
|
|
@@ -502,6 +604,7 @@ export function compileSingleFile(inputPath, options = {}) {
|
|
|
502
604
|
|
|
503
605
|
const ast = new Parser(tokens, basename(inputPath), source).parse();
|
|
504
606
|
ast._source = source;
|
|
607
|
+
ast._path = resolve(inputPath);
|
|
505
608
|
if (dumpAst) return { ast };
|
|
506
609
|
|
|
507
610
|
const outputDir =
|
|
@@ -513,7 +616,11 @@ export function compileSingleFile(inputPath, options = {}) {
|
|
|
513
616
|
const bundledPackages = new Set();
|
|
514
617
|
const preambles = [];
|
|
515
618
|
|
|
516
|
-
const pkgTarget =
|
|
619
|
+
const pkgTarget = resolvePackageTarget(
|
|
620
|
+
ast.target ?? options.target ?? "js",
|
|
621
|
+
dirname(resolve(inputPath)),
|
|
622
|
+
options,
|
|
623
|
+
);
|
|
517
624
|
ast.target = pkgTarget;
|
|
518
625
|
checker.target = pkgTarget;
|
|
519
626
|
checker.pkgName = ast.pkg?.name ?? "main";
|
|
@@ -534,6 +641,7 @@ export function compileSingleFile(inputPath, options = {}) {
|
|
|
534
641
|
if (errors.length > 0) {
|
|
535
642
|
throw new Error(errors.map((e) => e.message).join("\n"));
|
|
536
643
|
}
|
|
644
|
+
for (const w of checker.warnings) log.warn(w);
|
|
537
645
|
|
|
538
646
|
if (pkgTarget === "wasm" || pkgTarget === "both") {
|
|
539
647
|
registerWasmUnit(options, {
|
|
@@ -562,13 +670,26 @@ export function compileSingleFile(inputPath, options = {}) {
|
|
|
562
670
|
};
|
|
563
671
|
|
|
564
672
|
const merged = mergeCompilationChunks([...preambles, mainChunk]);
|
|
565
|
-
const { wasm, wat } =
|
|
673
|
+
const { wasm, wat, wasmOptInfo, wasmSourceMap } = finishWasm(
|
|
674
|
+
{ ...options, sourceMap },
|
|
675
|
+
merged,
|
|
676
|
+
pkgTarget,
|
|
677
|
+
outputDir,
|
|
678
|
+
);
|
|
566
679
|
|
|
567
680
|
if (sourceMap && !options.isDependency) {
|
|
568
681
|
attachSourceMap(merged, outputDir);
|
|
569
682
|
}
|
|
570
683
|
|
|
571
|
-
return {
|
|
684
|
+
return {
|
|
685
|
+
js: merged.js,
|
|
686
|
+
css: cg.getCss(),
|
|
687
|
+
target: pkgTarget,
|
|
688
|
+
wasm,
|
|
689
|
+
wat,
|
|
690
|
+
wasmOptInfo,
|
|
691
|
+
wasmSourceMap,
|
|
692
|
+
};
|
|
572
693
|
}
|
|
573
694
|
|
|
574
695
|
export function compileDir(dir, options = {}) {
|
|
@@ -591,8 +712,12 @@ export function compilePackageTestsWasm(dir, options = {}) {
|
|
|
591
712
|
}
|
|
592
713
|
|
|
593
714
|
export function compileFiles(files, options = {}) {
|
|
594
|
-
options = { ...options, wasmUnits: options.wasmUnits ?? [] };
|
|
595
715
|
const fromDir = options.fromDir ?? dirname(resolve(files[0]));
|
|
716
|
+
options = {
|
|
717
|
+
...options,
|
|
718
|
+
wasmUnits: options.wasmUnits ?? [],
|
|
719
|
+
rootDir: options.rootDir ?? fromDir,
|
|
720
|
+
};
|
|
596
721
|
const outputDir =
|
|
597
722
|
options.outputDir ??
|
|
598
723
|
(options.outputFile ? dirname(resolve(options.outputFile)) : fromDir);
|
|
@@ -622,9 +747,10 @@ export function compileFiles(files, options = {}) {
|
|
|
622
747
|
// Validate target directives across files in this package
|
|
623
748
|
const declaredTargets = new Map();
|
|
624
749
|
for (const p of programs) {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
declaredTargets.
|
|
750
|
+
const declared = p._declaredTarget;
|
|
751
|
+
if (declared) {
|
|
752
|
+
if (!declaredTargets.has(declared)) declaredTargets.set(declared, []);
|
|
753
|
+
declaredTargets.get(declared).push(p._filename);
|
|
628
754
|
}
|
|
629
755
|
}
|
|
630
756
|
if (declaredTargets.size > 1) {
|
|
@@ -635,10 +761,13 @@ export function compileFiles(files, options = {}) {
|
|
|
635
761
|
`Conflicting //gofront:target directives in package '${pkgName}': ${list}`,
|
|
636
762
|
);
|
|
637
763
|
}
|
|
638
|
-
const pkgTarget =
|
|
764
|
+
const pkgTarget = resolvePackageTarget(
|
|
639
765
|
declaredTargets.size === 1
|
|
640
766
|
? declaredTargets.keys().next().value
|
|
641
|
-
: (options.target ?? "js")
|
|
767
|
+
: (options.target ?? "js"),
|
|
768
|
+
fromDir,
|
|
769
|
+
options,
|
|
770
|
+
);
|
|
642
771
|
for (const p of programs) p.target = pkgTarget;
|
|
643
772
|
|
|
644
773
|
// ── 2. Resolve imports ────────────────────────────────────────
|
|
@@ -668,6 +797,7 @@ export function compileFiles(files, options = {}) {
|
|
|
668
797
|
const msgs = errors.map((e) => e.message).join("\n");
|
|
669
798
|
throw new Error(msgs);
|
|
670
799
|
}
|
|
800
|
+
for (const w of checker.warnings) log.warn(w);
|
|
671
801
|
|
|
672
802
|
// ── 4. Code generation ────────────────────────────────────────
|
|
673
803
|
const emitTarget = registerPackageUnit(options, {
|
|
@@ -693,13 +823,18 @@ export function compileFiles(files, options = {}) {
|
|
|
693
823
|
|
|
694
824
|
const mainChunk = {
|
|
695
825
|
js: mainJs,
|
|
696
|
-
sourceFiles:
|
|
697
|
-
sourcesContent:
|
|
826
|
+
sourceFiles: programs.map((p) => p._path),
|
|
827
|
+
sourcesContent: programs.map((p) => p._source),
|
|
698
828
|
mappings: emitTarget === "wasm" ? [] : codegen.getMappings(),
|
|
699
829
|
};
|
|
700
830
|
|
|
701
831
|
const merged = mergeCompilationChunks([...preambles, mainChunk]);
|
|
702
|
-
const { wasm, wat } =
|
|
832
|
+
const { wasm, wat, wasmOptInfo, wasmSourceMap } = finishWasm(
|
|
833
|
+
options,
|
|
834
|
+
merged,
|
|
835
|
+
pkgTarget,
|
|
836
|
+
outputDir,
|
|
837
|
+
);
|
|
703
838
|
|
|
704
839
|
if (options.sourceMap && !options.isDependency) {
|
|
705
840
|
attachSourceMap(merged, outputDir);
|
|
@@ -717,6 +852,8 @@ export function compileFiles(files, options = {}) {
|
|
|
717
852
|
css: allCss,
|
|
718
853
|
wasm,
|
|
719
854
|
wat,
|
|
855
|
+
wasmOptInfo,
|
|
856
|
+
wasmSourceMap,
|
|
720
857
|
programs,
|
|
721
858
|
exportedSymbols: checker.getExportedSymbols(),
|
|
722
859
|
exportedTypes: checker.getExportedTypes(),
|
package/src/dts-parser.js
CHANGED
|
@@ -109,10 +109,9 @@ export class DtsParser {
|
|
|
109
109
|
|
|
110
110
|
readIdent() {
|
|
111
111
|
this.skip();
|
|
112
|
-
|
|
113
|
-
while (!this.eof() && /[a-zA-Z0-9_$]/.test(this.ch()))
|
|
114
|
-
|
|
115
|
-
return s;
|
|
112
|
+
const start = this.pos;
|
|
113
|
+
while (!this.eof() && /[a-zA-Z0-9_$]/.test(this.ch())) this.pos++;
|
|
114
|
+
return this.src.slice(start, this.pos);
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
consume(ch) {
|
|
@@ -171,14 +170,14 @@ export class DtsParser {
|
|
|
171
170
|
}
|
|
172
171
|
|
|
173
172
|
_trackBracketDepth(c, depths) {
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
depths[open[c]]++;
|
|
173
|
+
const oi = "<([{".indexOf(c);
|
|
174
|
+
if (oi >= 0) {
|
|
175
|
+
depths[oi]++;
|
|
178
176
|
return true;
|
|
179
177
|
}
|
|
180
|
-
|
|
181
|
-
|
|
178
|
+
const ci = ">)]}".indexOf(c);
|
|
179
|
+
if (ci >= 0 && depths[ci] > 0) {
|
|
180
|
+
depths[ci]--;
|
|
182
181
|
return true;
|
|
183
182
|
}
|
|
184
183
|
return false;
|
|
@@ -392,7 +391,7 @@ export class DtsParser {
|
|
|
392
391
|
}
|
|
393
392
|
}
|
|
394
393
|
|
|
395
|
-
|
|
394
|
+
_parseFuncDecl() {
|
|
396
395
|
const name = this.readIdent();
|
|
397
396
|
this.skipGenerics();
|
|
398
397
|
const params = this.parseParams();
|
|
@@ -403,12 +402,14 @@ export class DtsParser {
|
|
|
403
402
|
ret = this.parseType();
|
|
404
403
|
}
|
|
405
404
|
this.consume(";");
|
|
406
|
-
|
|
407
|
-
|
|
405
|
+
return {
|
|
406
|
+
name,
|
|
407
|
+
val: {
|
|
408
408
|
kind: "func",
|
|
409
409
|
params: params.map((p) => p.type),
|
|
410
410
|
returns: [ret],
|
|
411
|
-
}
|
|
411
|
+
},
|
|
412
|
+
};
|
|
412
413
|
}
|
|
413
414
|
|
|
414
415
|
_parseMemberNewSig() {
|
|
@@ -422,7 +423,7 @@ export class DtsParser {
|
|
|
422
423
|
this.consume(";");
|
|
423
424
|
}
|
|
424
425
|
|
|
425
|
-
|
|
426
|
+
_parseTypeDecl() {
|
|
426
427
|
const name = this.readIdent();
|
|
427
428
|
this.skipGenerics();
|
|
428
429
|
this.skip();
|
|
@@ -432,10 +433,10 @@ export class DtsParser {
|
|
|
432
433
|
type = this.parseType();
|
|
433
434
|
}
|
|
434
435
|
this.consume(";");
|
|
435
|
-
|
|
436
|
+
return { name, type };
|
|
436
437
|
}
|
|
437
438
|
|
|
438
|
-
|
|
439
|
+
_parseClassDecl() {
|
|
439
440
|
const name = this.readIdent();
|
|
440
441
|
this.skipGenerics();
|
|
441
442
|
while (!this.eof() && this.ch() !== "{") this.pos++;
|
|
@@ -443,10 +444,20 @@ export class DtsParser {
|
|
|
443
444
|
const body = this.parseBody();
|
|
444
445
|
this.consume("}");
|
|
445
446
|
this.consume(";");
|
|
446
|
-
|
|
447
|
+
return { name, ns: { kind: "namespace", name, members: body } };
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
_parseNamespaceDecl() {
|
|
451
|
+
const name = this.readIdent() || this._readStringLit();
|
|
452
|
+
this.skip();
|
|
453
|
+
this.consume("{");
|
|
454
|
+
const body = this.parseBody();
|
|
455
|
+
this.consume("}");
|
|
456
|
+
this.consume(";");
|
|
457
|
+
return { name, ns: { kind: "namespace", name, members: body } };
|
|
447
458
|
}
|
|
448
459
|
|
|
449
|
-
|
|
460
|
+
_parseVarDecl() {
|
|
450
461
|
const name = this.readIdent();
|
|
451
462
|
this.skip();
|
|
452
463
|
this.consume("?");
|
|
@@ -461,7 +472,7 @@ export class DtsParser {
|
|
|
461
472
|
this.skipTypeExpr();
|
|
462
473
|
}
|
|
463
474
|
this.consume(";");
|
|
464
|
-
|
|
475
|
+
return { name, type };
|
|
465
476
|
}
|
|
466
477
|
|
|
467
478
|
_parseMember(out) {
|
|
@@ -477,28 +488,29 @@ export class DtsParser {
|
|
|
477
488
|
}
|
|
478
489
|
this.skip();
|
|
479
490
|
switch (kw) {
|
|
480
|
-
case "function":
|
|
481
|
-
this.
|
|
491
|
+
case "function": {
|
|
492
|
+
const { name, val } = this._parseFuncDecl();
|
|
493
|
+
if (name) out[name] = val;
|
|
482
494
|
break;
|
|
495
|
+
}
|
|
483
496
|
case "new":
|
|
484
497
|
this._parseMemberNewSig();
|
|
485
498
|
break;
|
|
486
|
-
case "type":
|
|
487
|
-
this.
|
|
499
|
+
case "type": {
|
|
500
|
+
const { name, type } = this._parseTypeDecl();
|
|
501
|
+
if (name) out[name] = type;
|
|
488
502
|
break;
|
|
503
|
+
}
|
|
489
504
|
case "interface":
|
|
490
|
-
case "class":
|
|
491
|
-
this.
|
|
505
|
+
case "class": {
|
|
506
|
+
const { name, ns } = this._parseClassDecl();
|
|
507
|
+
if (name) out[name] = ns;
|
|
492
508
|
break;
|
|
509
|
+
}
|
|
493
510
|
case "namespace":
|
|
494
511
|
case "module": {
|
|
495
|
-
const name
|
|
496
|
-
|
|
497
|
-
this.consume("{");
|
|
498
|
-
const body = this.parseBody();
|
|
499
|
-
this.consume("}");
|
|
500
|
-
this.consume(";");
|
|
501
|
-
if (name) out[name] = { kind: "namespace", name, members: body };
|
|
512
|
+
const { name, ns } = this._parseNamespaceDecl();
|
|
513
|
+
if (name) out[name] = ns;
|
|
502
514
|
break;
|
|
503
515
|
}
|
|
504
516
|
case "enum": {
|
|
@@ -509,9 +521,11 @@ export class DtsParser {
|
|
|
509
521
|
}
|
|
510
522
|
case "const":
|
|
511
523
|
case "let":
|
|
512
|
-
case "var":
|
|
513
|
-
this.
|
|
524
|
+
case "var": {
|
|
525
|
+
const { name, type } = this._parseVarDecl();
|
|
526
|
+
if (name) out[name] = type;
|
|
514
527
|
break;
|
|
528
|
+
}
|
|
515
529
|
default:
|
|
516
530
|
this._parseMemberDefault(kw, out);
|
|
517
531
|
break;
|
|
@@ -550,13 +564,15 @@ export class DtsParser {
|
|
|
550
564
|
this.consume(";");
|
|
551
565
|
}
|
|
552
566
|
}
|
|
567
|
+
|
|
553
568
|
_readStringLit() {
|
|
554
569
|
this.skip();
|
|
555
570
|
const c = this.ch();
|
|
556
571
|
if (c !== '"' && c !== "'") return null;
|
|
557
572
|
this.pos++;
|
|
558
|
-
|
|
559
|
-
while (!this.eof() && this.ch() !== c)
|
|
573
|
+
const start = this.pos;
|
|
574
|
+
while (!this.eof() && this.ch() !== c) this.pos++;
|
|
575
|
+
const s = this.src.slice(start, this.pos);
|
|
560
576
|
this.pos++;
|
|
561
577
|
return s;
|
|
562
578
|
}
|
|
@@ -612,85 +628,6 @@ export class DtsParser {
|
|
|
612
628
|
return { types, values };
|
|
613
629
|
}
|
|
614
630
|
|
|
615
|
-
_parseTopLevelTypeAlias(types) {
|
|
616
|
-
const name = this.readIdent();
|
|
617
|
-
this.skipGenerics();
|
|
618
|
-
this.skip();
|
|
619
|
-
let type = ANY;
|
|
620
|
-
if (this.ch() === "=") {
|
|
621
|
-
this.pos++;
|
|
622
|
-
type = this.parseType();
|
|
623
|
-
}
|
|
624
|
-
this.consume(";");
|
|
625
|
-
if (name) types.set(name, type);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
_parseTopLevelClassDecl(kw, types, values) {
|
|
629
|
-
const name = this.readIdent();
|
|
630
|
-
this.skipGenerics();
|
|
631
|
-
while (!this.eof() && this.ch() !== "{") this.pos++;
|
|
632
|
-
this.consume("{");
|
|
633
|
-
const body = this.parseBody();
|
|
634
|
-
this.consume("}");
|
|
635
|
-
this.consume(";");
|
|
636
|
-
if (name) {
|
|
637
|
-
const ns = { kind: "namespace", name, members: body };
|
|
638
|
-
types.set(name, ns);
|
|
639
|
-
if (kw === "class") values.set(name, ns);
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
_parseTopLevelNamespaceDecl(types, values) {
|
|
644
|
-
const name = this.readIdent() || this._readStringLit();
|
|
645
|
-
this.skip();
|
|
646
|
-
this.consume("{");
|
|
647
|
-
const body = this.parseBody();
|
|
648
|
-
this.consume("}");
|
|
649
|
-
this.consume(";");
|
|
650
|
-
if (name) {
|
|
651
|
-
const ns = { kind: "namespace", name, members: body };
|
|
652
|
-
types.set(name, ns);
|
|
653
|
-
values.set(name, ns);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
_parseTopLevelFuncDecl(values) {
|
|
658
|
-
const name = this.readIdent();
|
|
659
|
-
this.skipGenerics();
|
|
660
|
-
const params = this.parseParams();
|
|
661
|
-
this.skip();
|
|
662
|
-
let ret = VOID;
|
|
663
|
-
if (this.ch() === ":") {
|
|
664
|
-
this.pos++;
|
|
665
|
-
ret = this.parseType();
|
|
666
|
-
}
|
|
667
|
-
this.consume(";");
|
|
668
|
-
if (name)
|
|
669
|
-
values.set(name, {
|
|
670
|
-
kind: "func",
|
|
671
|
-
params: params.map((p) => p.type),
|
|
672
|
-
returns: [ret],
|
|
673
|
-
});
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
_parseTopLevelVarDecl(values) {
|
|
677
|
-
const name = this.readIdent();
|
|
678
|
-
this.skip();
|
|
679
|
-
this.consume("?");
|
|
680
|
-
let type = ANY;
|
|
681
|
-
if (this.ch() === ":") {
|
|
682
|
-
this.pos++;
|
|
683
|
-
type = this.parseType();
|
|
684
|
-
}
|
|
685
|
-
this.skip();
|
|
686
|
-
if (this.ch() === "=") {
|
|
687
|
-
this.pos++;
|
|
688
|
-
this.skipTypeExpr();
|
|
689
|
-
}
|
|
690
|
-
this.consume(";");
|
|
691
|
-
if (name) values.set(name, type);
|
|
692
|
-
}
|
|
693
|
-
|
|
694
631
|
_parseTopLevelDecl(kw, types, values) {
|
|
695
632
|
switch (kw) {
|
|
696
633
|
case "import":
|
|
@@ -698,17 +635,29 @@ export class DtsParser {
|
|
|
698
635
|
this.skipTypeExpr();
|
|
699
636
|
this.consume(";");
|
|
700
637
|
break;
|
|
701
|
-
case "type":
|
|
702
|
-
this.
|
|
638
|
+
case "type": {
|
|
639
|
+
const { name, type } = this._parseTypeDecl();
|
|
640
|
+
if (name) types.set(name, type);
|
|
703
641
|
break;
|
|
642
|
+
}
|
|
704
643
|
case "interface":
|
|
705
|
-
case "class":
|
|
706
|
-
this.
|
|
644
|
+
case "class": {
|
|
645
|
+
const { name, ns } = this._parseClassDecl();
|
|
646
|
+
if (name) {
|
|
647
|
+
types.set(name, ns);
|
|
648
|
+
if (kw === "class") values.set(name, ns);
|
|
649
|
+
}
|
|
707
650
|
break;
|
|
651
|
+
}
|
|
708
652
|
case "namespace":
|
|
709
|
-
case "module":
|
|
710
|
-
this.
|
|
653
|
+
case "module": {
|
|
654
|
+
const { name, ns } = this._parseNamespaceDecl();
|
|
655
|
+
if (name) {
|
|
656
|
+
types.set(name, ns);
|
|
657
|
+
values.set(name, ns);
|
|
658
|
+
}
|
|
711
659
|
break;
|
|
660
|
+
}
|
|
712
661
|
case "enum": {
|
|
713
662
|
const name = this.readIdent();
|
|
714
663
|
this.skipBlock();
|
|
@@ -719,14 +668,18 @@ export class DtsParser {
|
|
|
719
668
|
}
|
|
720
669
|
break;
|
|
721
670
|
}
|
|
722
|
-
case "function":
|
|
723
|
-
this.
|
|
671
|
+
case "function": {
|
|
672
|
+
const { name, val } = this._parseFuncDecl();
|
|
673
|
+
if (name) values.set(name, val);
|
|
724
674
|
break;
|
|
675
|
+
}
|
|
725
676
|
case "const":
|
|
726
677
|
case "let":
|
|
727
|
-
case "var":
|
|
728
|
-
this.
|
|
678
|
+
case "var": {
|
|
679
|
+
const { name, type } = this._parseVarDecl();
|
|
680
|
+
if (name) values.set(name, type);
|
|
729
681
|
break;
|
|
682
|
+
}
|
|
730
683
|
default:
|
|
731
684
|
this.skipTypeExpr();
|
|
732
685
|
this.consume(";");
|