gofront 1.8.0 → 1.9.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.
- package/README.md +3 -3
- package/package.json +5 -4
- package/src/backend/js/expressions.js +849 -371
- package/src/backend/js/index.js +241 -147
- package/src/backend/js/natives.js +383 -0
- package/src/backend/js/runtime.js +512 -2547
- package/src/backend/js/statements.js +506 -103
- package/src/backend/js/stdlib/index.js +45 -93
- package/src/backend/js/templ.js +32 -45
- package/src/backend/js/type-info.js +177 -13
- package/src/backend/shared/fixed-float.js +20 -0
- package/src/backend/shared/fmt-types.js +63 -171
- package/src/backend/shared/host-unicode.js +36 -0
- package/src/backend/wasm/boundary.js +490 -965
- package/src/backend/wasm/emit-builtins.js +643 -256
- package/src/backend/wasm/emit-exprs.js +124 -57
- package/src/backend/wasm/emit-maps.js +17 -367
- package/src/backend/wasm/emit-stmts.js +325 -75
- package/src/backend/wasm/emit.js +104 -13
- package/src/backend/wasm/globals.js +47 -8
- package/src/backend/wasm/glue.js +2 -4
- package/src/backend/wasm/index.js +36 -530
- package/src/backend/wasm/method-expr.js +12 -1
- package/src/backend/wasm/module-emitter.js +92 -717
- package/src/backend/wasm/monomorph.js +103 -6
- package/src/backend/wasm/natives.js +596 -0
- package/src/backend/wasm/prescan.js +5 -153
- package/src/backend/wasm/prune-funcs.js +89 -0
- package/src/backend/wasm/stdlib/index.js +2 -32
- package/src/backend/wasm/types.js +68 -20
- package/src/backend/wasm/variadic.js +3 -3
- package/src/cli/cli-core.js +5 -1
- package/src/cli/test-runner.js +115 -342
- package/src/compiler.js +108 -130
- package/src/lexer/lexer.js +105 -11
- package/src/lexer/templ-lexer.js +61 -18
- package/src/lexer/tokens.js +1 -0
- package/src/link/stdlib.js +354 -132
- package/src/link/type-names.js +148 -0
- package/src/link/wasm.js +30 -6
- package/src/lower/bounds.js +153 -0
- package/src/lower/captures.js +92 -33
- package/src/lower/embedding.js +32 -3
- package/src/lower/errors-as.js +196 -0
- package/src/lower/fmt-formatters.js +905 -0
- package/src/lower/functions.js +2 -0
- package/src/lower/gen-types.js +274 -0
- package/src/lower/index.js +7 -1
- package/src/lower/json-codecs.js +228 -247
- package/src/lower/ownership.js +25 -7
- package/src/lower/reachability.js +69 -51
- package/src/lower/walk.js +12 -0
- package/src/parser/declarations.js +28 -5
- package/src/parser/expressions.js +86 -16
- package/src/parser/statements.js +1 -0
- package/src/parser/templ.js +44 -5
- package/src/parser/types.js +1 -0
- package/src/resolver.js +1 -2
- package/src/typechecker/assignability.js +124 -11
- package/src/typechecker/const-fold.js +70 -27
- package/src/typechecker/constants.js +32 -6
- package/src/typechecker/expressions.js +326 -98
- package/src/typechecker/index.js +208 -33
- package/src/typechecker/init-order.js +136 -40
- package/src/typechecker/operand-text.js +40 -0
- package/src/typechecker/resolve.js +192 -36
- package/src/typechecker/statements.js +122 -11
- package/src/typechecker/stdlib/excluded.js +9 -5
- package/src/typechecker/stdlib/index.js +25 -9
- package/src/typechecker/termination.js +10 -1
- package/src/typechecker/types.js +203 -573
- package/stdlib/bytes/buffer.go +479 -0
- package/stdlib/bytes/bytes.go +1010 -0
- package/stdlib/bytes/reader.go +161 -0
- package/stdlib/context/context.go +115 -0
- package/stdlib/crypto/rand/rand.go +34 -0
- package/stdlib/crypto/sha256/sha256.go +249 -0
- package/stdlib/encoding/base64/base64.go +331 -0
- package/stdlib/encoding/binary/binary.go +332 -0
- package/stdlib/encoding/hex/hex.go +140 -0
- package/stdlib/encoding/json/json.go +62 -0
- package/stdlib/errors/errors.go +174 -0
- package/stdlib/fmt/errors.go +110 -0
- package/stdlib/fmt/format.go +732 -0
- package/stdlib/fmt/print.go +1232 -0
- package/stdlib/gom/gom.go +293 -0
- package/stdlib/html/html.go +251 -0
- package/stdlib/internal/fmtrt/fmtrt.go +163 -0
- package/stdlib/internal/jsonrt/dec.go +171 -38
- package/stdlib/internal/jsonrt/enc.go +186 -36
- package/stdlib/internal/jsonrt/scanner.go +17 -8
- package/stdlib/io/io.go +157 -1
- package/stdlib/maps/maps.go +131 -0
- package/stdlib/math/bits/bits.go +507 -0
- package/stdlib/math/extra.go +16 -14
- package/stdlib/math/math.go +439 -0
- package/stdlib/math/rand/rand.go +297 -0
- package/stdlib/os/os.go +93 -0
- package/stdlib/path/filepath/filepath.go +47 -0
- package/stdlib/path/path.go +394 -0
- package/stdlib/regexp/regexp.go +231 -0
- package/stdlib/slices/slices.go +526 -0
- package/stdlib/slices/sort.go +209 -0
- package/stdlib/slices/zsort_cmp.go +480 -0
- package/stdlib/slices/zsort_ordered.go +482 -0
- package/stdlib/sort/sort.go +391 -452
- package/stdlib/sort/zsort_func.go +480 -0
- package/stdlib/sort/zsort_iface.go +480 -0
- package/stdlib/strconv/float.go +1699 -0
- package/stdlib/strconv/isprint.go +752 -0
- package/stdlib/strconv/quote.go +235 -50
- package/stdlib/strconv/strconv.go +616 -0
- package/stdlib/strings/builder.go +95 -0
- package/stdlib/strings/reader.go +163 -0
- package/stdlib/strings/replacer.go +102 -0
- package/stdlib/strings/strings.go +807 -0
- package/stdlib/sync/sync.go +268 -0
- package/stdlib/testing/async_js.go +61 -0
- package/stdlib/testing/benchmark.go +297 -0
- package/stdlib/testing/testing.go +523 -0
- package/stdlib/time/duration.go +233 -0
- package/stdlib/time/format.go +745 -0
- package/stdlib/time/parse.go +790 -0
- package/stdlib/time/sleep_js.go +63 -0
- package/stdlib/time/time.go +834 -0
- package/stdlib/unicode/unicode.go +141 -3
- package/stdlib/unicode/utf8/utf8.go +464 -0
- package/src/backend/js/fmt-runtime.js +0 -573
- package/src/backend/js/stdlib/base64.js +0 -12
- package/src/backend/js/stdlib/binary.js +0 -102
- package/src/backend/js/stdlib/bits.js +0 -119
- package/src/backend/js/stdlib/builder.js +0 -98
- package/src/backend/js/stdlib/bytes.js +0 -368
- package/src/backend/js/stdlib/errors.js +0 -45
- package/src/backend/js/stdlib/fmt.js +0 -517
- package/src/backend/js/stdlib/gom.js +0 -155
- package/src/backend/js/stdlib/hex.js +0 -17
- package/src/backend/js/stdlib/html.js +0 -20
- package/src/backend/js/stdlib/io.js +0 -137
- package/src/backend/js/stdlib/json.js +0 -1167
- package/src/backend/js/stdlib/maps.js +0 -37
- package/src/backend/js/stdlib/math.js +0 -85
- package/src/backend/js/stdlib/os.js +0 -13
- package/src/backend/js/stdlib/path.js +0 -48
- package/src/backend/js/stdlib/rand.js +0 -32
- package/src/backend/js/stdlib/regexp.js +0 -54
- package/src/backend/js/stdlib/sha256.js +0 -12
- package/src/backend/js/stdlib/shared.js +0 -17
- package/src/backend/js/stdlib/simd.js +0 -34
- package/src/backend/js/stdlib/slices.js +0 -107
- package/src/backend/js/stdlib/sort.js +0 -30
- package/src/backend/js/stdlib/strconv.js +0 -79
- package/src/backend/js/stdlib/strings.js +0 -301
- package/src/backend/js/stdlib/sync.js +0 -13
- package/src/backend/js/stdlib/testing.js +0 -41
- package/src/backend/js/stdlib/time.js +0 -152
- package/src/backend/js/stdlib/unicode.js +0 -25
- package/src/backend/js/stdlib/utf8.js +0 -26
- package/src/backend/wasm/stdlib/bytes.js +0 -6716
- package/src/backend/wasm/stdlib/core.js +0 -10278
- package/src/backend/wasm/stdlib/io.js +0 -3578
- package/src/backend/wasm/stdlib/packages.js +0 -2402
- package/src/backend/wasm/stdlib/pure.js +0 -720
- package/src/backend/wasm/stdlib/time.js +0 -2229
- package/src/typechecker/stdlib/core.js +0 -1079
- package/src/typechecker/stdlib/extended.js +0 -1210
- package/stdlib/bytes/iter.go +0 -192
- package/stdlib/bytes/search.go +0 -240
- package/stdlib/bytes/split.go +0 -218
- package/stdlib/errors/overlay.go +0 -12
- package/stdlib/maps/iter.go +0 -65
- package/stdlib/slices/extra.go +0 -73
- package/stdlib/slices/iter.go +0 -113
- package/stdlib/strings/extra.go +0 -35
- package/stdlib/strings/iter.go +0 -122
- package/stdlib/sync/extra.go +0 -105
- package/stdlib/unicode/utf8/bytes.go +0 -239
package/src/link/stdlib.js
CHANGED
|
@@ -9,17 +9,21 @@ import { readFileSync } from "node:fs";
|
|
|
9
9
|
import { basename, dirname, join, resolve } from "node:path";
|
|
10
10
|
import { CodeGen } from "../backend/js/index.js";
|
|
11
11
|
import { Lexer } from "../lexer/lexer.js";
|
|
12
|
+
import { generateErrorsAs } from "../lower/errors-as.js";
|
|
13
|
+
import { generateFmtFormatters } from "../lower/fmt-formatters.js";
|
|
12
14
|
import { generateJsonCodecs } from "../lower/json-codecs.js";
|
|
13
|
-
import { reachableStdlibDecls } from "../lower/reachability.js";
|
|
15
|
+
import { reachableStdlibDecls, StdlibReach } from "../lower/reachability.js";
|
|
14
16
|
import { forEachChild } from "../lower/walk.js";
|
|
15
17
|
import { Parser } from "../parser/index.js";
|
|
16
|
-
import {
|
|
17
|
-
isBuiltinPackage,
|
|
18
|
-
isLocalPath,
|
|
19
|
-
resolveStdlibSource,
|
|
20
|
-
} from "../resolver.js";
|
|
18
|
+
import { isLocalPath, resolveStdlibSource } from "../resolver.js";
|
|
21
19
|
import { lowerStdlibRefs, registerWasmUnit } from "./wasm.js";
|
|
22
20
|
|
|
21
|
+
export {
|
|
22
|
+
mangleCollidingTypes,
|
|
23
|
+
renameLocalTypes,
|
|
24
|
+
withOriginalTypeNames,
|
|
25
|
+
} from "./type-names.js";
|
|
26
|
+
|
|
23
27
|
// ── Go-source stdlib ──────────────────────────────────────────
|
|
24
28
|
//
|
|
25
29
|
// Packages under stdlib/<path>/ are GoFront Go. Each is type-checked
|
|
@@ -27,27 +31,56 @@ import { lowerStdlibRefs, registerWasmUnit } from "./wasm.js";
|
|
|
27
31
|
// is bundled for js/both importers and its programs are linked into app.wasm
|
|
28
32
|
// for wasm/both importers, never through the boundary facade. Top-level
|
|
29
33
|
// names are mangled to `Name$$path` so they cannot collide with user
|
|
30
|
-
// declarations in the flat JS bundle or the linked module.
|
|
31
|
-
// emitter-backed package (`errors`) is an overlay: its members join that
|
|
32
|
-
// namespace and unqualified references to emitter members become `errors.X`.
|
|
34
|
+
// declarations in the flat JS bundle or the linked module.
|
|
33
35
|
|
|
34
36
|
function stdlibSuffix(importPath) {
|
|
35
37
|
return `$$${importPath.replaceAll("/", "$")}`;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
// Each file keeps its own `//gofront:target` (default `both`). A package
|
|
41
|
+
// with `js` files is compiled whole for `js` importers (the `js` variant) and
|
|
42
|
+
// without those files for `wasm` and `both` importers (the `shared` variant).
|
|
43
|
+
function parseStdlibFiles(dir, deps, variant = "js", target = "both") {
|
|
44
|
+
return deps
|
|
45
|
+
.gwFilesIn(dir)
|
|
46
|
+
.map((f) => {
|
|
47
|
+
const source = readFileSync(f, "utf8");
|
|
48
|
+
const filename = basename(f);
|
|
49
|
+
const tokens = new Lexer(source, filename).tokenize();
|
|
50
|
+
const ast = new Parser(tokens, filename, source).parse();
|
|
51
|
+
ast._source = source;
|
|
52
|
+
ast._path = resolve(f);
|
|
53
|
+
ast._fileTarget = tokens.target ?? "both";
|
|
54
|
+
return ast;
|
|
55
|
+
})
|
|
56
|
+
.filter((ast) => variant === "js" || ast._fileTarget !== "js")
|
|
57
|
+
.map((ast) => Object.assign(ast, { target }));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Targets of the package's files, read without parsing.
|
|
61
|
+
function stdlibFileTargets(dir, deps) {
|
|
39
62
|
return deps.gwFilesIn(dir).map((f) => {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
const tokens = new Lexer(source, filename).tokenize();
|
|
43
|
-
const ast = new Parser(tokens, filename, source).parse();
|
|
44
|
-
ast._source = source;
|
|
45
|
-
ast._path = resolve(f);
|
|
46
|
-
ast.target = "both";
|
|
47
|
-
return ast;
|
|
63
|
+
const m = /^\/\/gofront:target\s+(\S+)/m.exec(readFileSync(f, "utf8"));
|
|
64
|
+
return m?.[1] ?? "both";
|
|
48
65
|
});
|
|
49
66
|
}
|
|
50
67
|
|
|
68
|
+
// Exported names declared by the `js` files (what a `wasm` or `both` importer
|
|
69
|
+
// cannot use).
|
|
70
|
+
function stdlibJsOnlyNames(dir, deps) {
|
|
71
|
+
const programs = parseStdlibFiles(dir, deps).filter(
|
|
72
|
+
(p) => p._fileTarget === "js",
|
|
73
|
+
);
|
|
74
|
+
const { values, types } = stdlibTopLevelNames(programs);
|
|
75
|
+
return new Set([...values, ...types].filter((n) => /^[A-Z]/.test(n)));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Whether every file of the package is `js`-only.
|
|
79
|
+
export function stdlibIsJsOnly(dir, deps) {
|
|
80
|
+
const targets = stdlibFileTargets(dir, deps);
|
|
81
|
+
return targets.length > 0 && targets.every((t) => t === "js");
|
|
82
|
+
}
|
|
83
|
+
|
|
51
84
|
// Top-level value and type names declared by the package.
|
|
52
85
|
function stdlibTopLevelNames(programs) {
|
|
53
86
|
const values = new Set();
|
|
@@ -68,13 +101,27 @@ function stdlibTopLevelNames(programs) {
|
|
|
68
101
|
// `refs` holds the `file:line:col` of identifiers the first type-check
|
|
69
102
|
// resolved to package scope; type names are resolved by name (GoFront types
|
|
70
103
|
// are package-flat) except where a type parameter shadows them.
|
|
71
|
-
|
|
104
|
+
// With `lazy`, function and method bodies are left alone: they are mangled
|
|
105
|
+
// by `mangleBody` once a lazily checked body is first reached.
|
|
106
|
+
export function mangleStdlibAst(programs, ctx, { lazy = false } = {}) {
|
|
72
107
|
for (const p of programs) {
|
|
73
108
|
for (const d of p.decls ?? []) mangleDeclNames(d, ctx);
|
|
74
|
-
|
|
109
|
+
for (const d of p.decls ?? []) {
|
|
110
|
+
const deferred =
|
|
111
|
+
lazy && (d.kind === "FuncDecl" || d.kind === "MethodDecl");
|
|
112
|
+
const body = d.body;
|
|
113
|
+
if (deferred) d.body = null;
|
|
114
|
+
mangleRefs(d, p._filename, new Set(), ctx);
|
|
115
|
+
if (deferred) d.body = body;
|
|
116
|
+
}
|
|
75
117
|
}
|
|
76
118
|
}
|
|
77
119
|
|
|
120
|
+
function mangleBody(decl, file, ctx) {
|
|
121
|
+
const tparams = new Set((decl.typeParams ?? []).map((t) => t.name));
|
|
122
|
+
mangleRefs(decl.body, file, tparams, ctx);
|
|
123
|
+
}
|
|
124
|
+
|
|
78
125
|
function mangleDeclNames(d, { suffix, values }) {
|
|
79
126
|
if (d.kind === "TypeDecl" || (d.kind === "FuncDecl" && values.has(d.name))) {
|
|
80
127
|
d.name += suffix;
|
|
@@ -123,43 +170,25 @@ function mangleRefs(node, file, tparams, ctx) {
|
|
|
123
170
|
forEachChild(node, (child) => mangleRefs(child, file, tp, ctx));
|
|
124
171
|
}
|
|
125
172
|
|
|
126
|
-
function mangleTypeRef(node, tparams, { suffix, types
|
|
173
|
+
function mangleTypeRef(node, tparams, { suffix, types }) {
|
|
127
174
|
if (types.has(node.name) && !tparams.has(node.name)) {
|
|
128
175
|
node.name += suffix;
|
|
129
|
-
} else if (overlay && node.name in overlay.members) {
|
|
130
|
-
node.name = `${overlay.name}.${node.name}`;
|
|
131
176
|
}
|
|
132
177
|
}
|
|
133
178
|
|
|
134
|
-
// A package-scope identifier: a package declaration gets the suffix
|
|
135
|
-
|
|
136
|
-
function mangleIdentRef(node, { suffix, values, types, overlay }) {
|
|
179
|
+
// A package-scope identifier: a package declaration gets the suffix.
|
|
180
|
+
function mangleIdentRef(node, { suffix, values, types }) {
|
|
137
181
|
if (values.has(node.name) || types.has(node.name)) {
|
|
138
182
|
node.name += suffix;
|
|
139
|
-
} else if (overlay && node.name in overlay.members) {
|
|
140
|
-
const field = node.name;
|
|
141
|
-
delete node.name;
|
|
142
|
-
Object.assign(node, {
|
|
143
|
-
kind: "SelectorExpr",
|
|
144
|
-
expr: { kind: "Ident", name: overlay.name, _line: node._line },
|
|
145
|
-
field,
|
|
146
|
-
});
|
|
147
183
|
}
|
|
148
184
|
}
|
|
149
185
|
|
|
150
|
-
function checkStdlibPrograms(programs, pkgName, options,
|
|
186
|
+
function checkStdlibPrograms(programs, pkgName, options, deps, target) {
|
|
151
187
|
const checker = new deps.TypeChecker();
|
|
152
|
-
checker.target =
|
|
188
|
+
checker.target = target;
|
|
153
189
|
checker.pkgName = pkgName;
|
|
154
190
|
checker.isStdlib = true;
|
|
155
|
-
|
|
156
|
-
for (const [name, t] of Object.entries(overlay.members)) {
|
|
157
|
-
checker.globals.define(name, t);
|
|
158
|
-
if (t.kind === "interface" || t.kind === "named" || t.kind === "struct") {
|
|
159
|
-
checker.types.set(name, t);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
191
|
+
checker.lazyBodies = true;
|
|
163
192
|
deps.resolveImports(
|
|
164
193
|
programs,
|
|
165
194
|
programs[0]._path,
|
|
@@ -176,49 +205,100 @@ function checkStdlibPrograms(programs, pkgName, options, overlay, deps) {
|
|
|
176
205
|
// Errors in stdlib source are compiler bugs; the importer reports them at its
|
|
177
206
|
// import (see reportStdlibLoadError), so only the message text is kept, never
|
|
178
207
|
// a location inside stdlib/.
|
|
179
|
-
function
|
|
180
|
-
if (errors.length === 0) return;
|
|
208
|
+
function stdlibErrorText(errors) {
|
|
181
209
|
const detail = (e) =>
|
|
182
210
|
e.message
|
|
183
211
|
.split("\n")[0]
|
|
184
212
|
.replace(/^Type error(?: in \S+)?(?: at line \d+:\d+)?:\s*/, "");
|
|
185
|
-
|
|
213
|
+
return [...new Set(errors.map(detail))].join("; ");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function throwStdlibErrors(errors) {
|
|
217
|
+
if (errors.length === 0) return;
|
|
218
|
+
throw new Error(stdlibErrorText(errors));
|
|
186
219
|
}
|
|
187
220
|
|
|
188
221
|
// Pass 1: type-check the package as written and record which identifiers
|
|
189
|
-
// refer to package scope.
|
|
190
|
-
function probeStdlibPackage(_importPath, dir, options,
|
|
191
|
-
const programs = parseStdlibFiles(dir, deps);
|
|
222
|
+
// refer to package scope.
|
|
223
|
+
function probeStdlibPackage(_importPath, dir, options, deps, v) {
|
|
224
|
+
const programs = parseStdlibFiles(dir, deps, v.variant, v.target);
|
|
192
225
|
const pkgName = programs[0].pkg.name;
|
|
193
226
|
const { values, types } = stdlibTopLevelNames(programs);
|
|
194
|
-
|
|
195
|
-
if (overlay && n in overlay.members)
|
|
196
|
-
throw new Error(`overlay redeclares ${overlay.name}.${n}`);
|
|
197
|
-
const probe = checkStdlibPrograms(programs, pkgName, options, overlay, deps);
|
|
227
|
+
const probe = checkStdlibPrograms(programs, pkgName, options, deps, v.target);
|
|
198
228
|
probe._pkgRefs = new Set();
|
|
199
229
|
throwStdlibErrors(probe.checkAll(programs));
|
|
200
|
-
return {
|
|
230
|
+
return {
|
|
231
|
+
pkgName,
|
|
232
|
+
values,
|
|
233
|
+
types,
|
|
234
|
+
refs: probe._pkgRefs,
|
|
235
|
+
probe,
|
|
236
|
+
probePrograms: programs,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Function and method bodies are checked when first reached (see
|
|
241
|
+
// `StdlibReach`), in both passes: the probe records which identifiers in the
|
|
242
|
+
// body name package scope, the body is mangled with them, and the mangled
|
|
243
|
+
// body is checked. `decl._ensure()` does all three once and returns the
|
|
244
|
+
// error text, or null.
|
|
245
|
+
function installLazyBodies(info, programs, checker) {
|
|
246
|
+
const { probe, probePrograms } = info;
|
|
247
|
+
programs.forEach((p, pi) => {
|
|
248
|
+
p.decls.forEach((decl, di) => {
|
|
249
|
+
if (decl.kind !== "FuncDecl" && decl.kind !== "MethodDecl") return;
|
|
250
|
+
const probeDecl = probePrograms[pi].decls[di];
|
|
251
|
+
let result;
|
|
252
|
+
decl._ensure = () => {
|
|
253
|
+
if (result !== undefined) return result;
|
|
254
|
+
result = null; // a body that reaches itself is in progress
|
|
255
|
+
const before = [probe.errors.length, checker.errors.length];
|
|
256
|
+
probe.checkBody(probeDecl);
|
|
257
|
+
if (probe.errors.length === before[0]) {
|
|
258
|
+
mangleBody(decl, p._filename, info);
|
|
259
|
+
checker.checkBody(decl);
|
|
260
|
+
lowerStdlibRefs(decl);
|
|
261
|
+
}
|
|
262
|
+
const errors = [
|
|
263
|
+
...probe.errors.slice(before[0]),
|
|
264
|
+
...checker.errors.slice(before[1]),
|
|
265
|
+
];
|
|
266
|
+
if (errors.length > 0) result = stdlibErrorText(errors);
|
|
267
|
+
return result;
|
|
268
|
+
};
|
|
269
|
+
});
|
|
270
|
+
});
|
|
201
271
|
}
|
|
202
272
|
|
|
203
273
|
// Exported members as seen by importers (original name -> type) and the
|
|
204
|
-
// original -> mangled name map
|
|
205
|
-
function stdlibNamespace(checker, { pkgName, values, types, suffix },
|
|
206
|
-
const members =
|
|
274
|
+
// original -> mangled name map.
|
|
275
|
+
function stdlibNamespace(checker, { pkgName, values, types, suffix }, jsOnly) {
|
|
276
|
+
const members = {};
|
|
207
277
|
const mangle = new Map();
|
|
278
|
+
const consts = new Map();
|
|
208
279
|
for (const name of [...values, ...types]) {
|
|
209
280
|
const t = checker.globals.symbols.get(name + suffix);
|
|
210
281
|
if (!/^[A-Z]/.test(name) || t === undefined) continue;
|
|
211
282
|
members[name] = t;
|
|
212
283
|
mangle.set(name, name + suffix);
|
|
284
|
+
// An exported constant's folded value, so importers fold `pkg.Name`.
|
|
285
|
+
if (checker.globals._consts.has(name + suffix)) {
|
|
286
|
+
const v = checker._constValue(
|
|
287
|
+
{ kind: "Ident", name: name + suffix },
|
|
288
|
+
checker.globals,
|
|
289
|
+
);
|
|
290
|
+
if (v) consts.set(name, v);
|
|
291
|
+
}
|
|
213
292
|
}
|
|
214
293
|
return {
|
|
215
|
-
...(overlay ?? {}),
|
|
216
294
|
kind: "namespace",
|
|
217
295
|
name: pkgName,
|
|
218
296
|
members,
|
|
219
|
-
_gofront:
|
|
297
|
+
_gofront: true,
|
|
220
298
|
_target: "both",
|
|
299
|
+
_jsOnly: jsOnly,
|
|
221
300
|
_mangle: mangle,
|
|
301
|
+
_consts: consts,
|
|
222
302
|
};
|
|
223
303
|
}
|
|
224
304
|
|
|
@@ -236,59 +316,94 @@ function stdlibExportedTypes(checker, { pkgName, suffix }) {
|
|
|
236
316
|
return out;
|
|
237
317
|
}
|
|
238
318
|
|
|
319
|
+
// The compilation a package gets for an importer: `js` importers see every
|
|
320
|
+
// file, `wasm` and `both` importers only the files for both targets (cached
|
|
321
|
+
// as `<path>#shared` when that differs). Returns { key, variant, target }.
|
|
322
|
+
function stdlibVariant(importPath, dir, importerTarget, deps) {
|
|
323
|
+
const hasJs = stdlibFileTargets(dir, deps).includes("js");
|
|
324
|
+
importerTarget ??= "js";
|
|
325
|
+
if (!hasJs) return { key: importPath, variant: "js", target: "both" };
|
|
326
|
+
if (importerTarget === "js")
|
|
327
|
+
return { key: importPath, variant: "js", target: "js" };
|
|
328
|
+
return { key: `${importPath}#shared`, variant: "shared", target: "both" };
|
|
329
|
+
}
|
|
330
|
+
|
|
239
331
|
// Loads (once per build) and compiles the Go-source package at `dir`. A
|
|
240
332
|
// failure is cached too, so every importer reports it.
|
|
241
|
-
function loadStdlibPackage(
|
|
333
|
+
function loadStdlibPackage(
|
|
334
|
+
importPath,
|
|
335
|
+
dir,
|
|
336
|
+
options,
|
|
337
|
+
deps,
|
|
338
|
+
importerTarget = "js",
|
|
339
|
+
) {
|
|
340
|
+
const v = stdlibVariant(importPath, dir, importerTarget, deps);
|
|
242
341
|
const cache = options.stdlibCache;
|
|
243
|
-
const cached = cache.get(
|
|
342
|
+
const cached = cache.get(v.key);
|
|
244
343
|
if (cached === null)
|
|
245
344
|
throw new Error(`import cycle in Go-source stdlib: ${importPath}`);
|
|
246
345
|
if (cached instanceof Error) throw cached;
|
|
247
346
|
if (cached) return cached;
|
|
248
|
-
cache.set(
|
|
347
|
+
cache.set(v.key, null);
|
|
249
348
|
try {
|
|
250
|
-
const pkg = buildStdlibPackage(importPath, dir, options, deps);
|
|
251
|
-
cache.set(
|
|
349
|
+
const pkg = buildStdlibPackage(importPath, dir, options, deps, v);
|
|
350
|
+
cache.set(v.key, pkg);
|
|
252
351
|
return pkg;
|
|
253
352
|
} catch (e) {
|
|
254
|
-
cache.set(
|
|
353
|
+
cache.set(v.key, e);
|
|
255
354
|
throw e;
|
|
256
355
|
}
|
|
257
356
|
}
|
|
258
357
|
|
|
259
|
-
function buildStdlibPackage(importPath, dir, options, deps) {
|
|
358
|
+
function buildStdlibPackage(importPath, dir, options, deps, v) {
|
|
260
359
|
const cache = options.stdlibCache;
|
|
261
|
-
const overlay = isBuiltinPackage(importPath)
|
|
262
|
-
? new deps.TypeChecker().globals.lookup(importPath.split("/").at(-1))
|
|
263
|
-
: null;
|
|
264
360
|
const info = {
|
|
265
|
-
...probeStdlibPackage(importPath, dir, options,
|
|
361
|
+
...probeStdlibPackage(importPath, dir, options, deps, v),
|
|
266
362
|
suffix: stdlibSuffix(importPath),
|
|
267
363
|
};
|
|
268
364
|
|
|
269
365
|
// Pass 2: mangle a fresh parse and check it again.
|
|
270
|
-
const programs = parseStdlibFiles(dir, deps);
|
|
271
|
-
mangleStdlibAst(programs,
|
|
366
|
+
const programs = parseStdlibFiles(dir, deps, v.variant, v.target);
|
|
367
|
+
mangleStdlibAst(programs, info, { lazy: true });
|
|
272
368
|
const checker = checkStdlibPrograms(
|
|
273
369
|
programs,
|
|
274
370
|
info.pkgName,
|
|
275
371
|
options,
|
|
276
|
-
null,
|
|
277
372
|
deps,
|
|
373
|
+
v.target,
|
|
278
374
|
);
|
|
279
375
|
throwStdlibErrors(checker.checkAll(programs));
|
|
280
376
|
lowerStdlibRefs(programs);
|
|
377
|
+
installLazyBodies(info, programs, checker);
|
|
378
|
+
|
|
379
|
+
// A user reference to a member checks the bodies it reaches, so a type
|
|
380
|
+
// error in the standard library surfaces at the call. Failures from other
|
|
381
|
+
// packages' bodies surface when the output is assembled.
|
|
382
|
+
const reach = new StdlibReach(programs);
|
|
383
|
+
const jsOnly =
|
|
384
|
+
v.variant === "shared" ? stdlibJsOnlyNames(dir, deps) : new Set();
|
|
385
|
+
const namespace = stdlibNamespace(checker, info, jsOnly);
|
|
386
|
+
namespace._path = importPath;
|
|
387
|
+
namespace._reach = (name) => {
|
|
388
|
+
const seen = reach.failures.length;
|
|
389
|
+
reach.add([{ kind: "Ident", name }]);
|
|
390
|
+
return reach.failures[seen] ?? null;
|
|
391
|
+
};
|
|
281
392
|
|
|
282
393
|
const pkg = {
|
|
283
394
|
importPath,
|
|
395
|
+
key: v.key,
|
|
284
396
|
checker,
|
|
285
397
|
pkgName: info.pkgName,
|
|
286
|
-
|
|
287
|
-
namespace: stdlibNamespace(checker, info, overlay),
|
|
398
|
+
namespace,
|
|
288
399
|
exportedTypes: stdlibExportedTypes(checker, info),
|
|
289
400
|
deps: programs
|
|
290
401
|
.flatMap((p) => p.imports.flatMap((imp) => imp.imports))
|
|
291
|
-
.map(({ path }) =>
|
|
402
|
+
.map(({ path }) =>
|
|
403
|
+
v.variant === "shared"
|
|
404
|
+
? (cache.get(`${path}#shared`) ?? cache.get(path))
|
|
405
|
+
: cache.get(path),
|
|
406
|
+
)
|
|
292
407
|
.filter(Boolean),
|
|
293
408
|
unit: {
|
|
294
409
|
key: `stdlib:${importPath}`,
|
|
@@ -307,19 +422,20 @@ function buildStdlibPackage(importPath, dir, options, deps) {
|
|
|
307
422
|
// emitted (see lower/reachability.js). Importers leave a marker line.
|
|
308
423
|
const STDLIB_MARKER_RE = /^\/\*__GOFRONT_STDLIB:([^*]*)\*\/$/;
|
|
309
424
|
|
|
310
|
-
function stdlibMarker(
|
|
311
|
-
return `/*__GOFRONT_STDLIB:${
|
|
425
|
+
function stdlibMarker(key) {
|
|
426
|
+
return `/*__GOFRONT_STDLIB:${key}*/`;
|
|
312
427
|
}
|
|
313
428
|
|
|
314
|
-
function stdlibJs(pkg, reached) {
|
|
429
|
+
function stdlibJs(pkg, reached, natives) {
|
|
315
430
|
const programs = pkg.unit.programs.map((p) => ({
|
|
316
431
|
...p,
|
|
317
432
|
decls: p.decls.filter((d) => reached.has(d)),
|
|
318
433
|
}));
|
|
319
434
|
if (programs.every((p) => p.decls.length === 0)) return "";
|
|
320
435
|
return new CodeGen(pkg.checker, new Map(), new Set(), {
|
|
321
|
-
target:
|
|
436
|
+
target: pkg.checker.target,
|
|
322
437
|
strict: true,
|
|
438
|
+
natives,
|
|
323
439
|
}).generateAll(programs, { isTest: false });
|
|
324
440
|
}
|
|
325
441
|
|
|
@@ -346,11 +462,15 @@ function spliceStdlibJs(merged, options) {
|
|
|
346
462
|
const pkgs = lines
|
|
347
463
|
.map((l) => l.match(STDLIB_MARKER_RE)?.[1])
|
|
348
464
|
.filter(Boolean)
|
|
349
|
-
.map((
|
|
465
|
+
.map((key) => options.stdlibCache.get(key));
|
|
350
466
|
if (pkgs.length === 0) return;
|
|
467
|
+
// The whole package carries everything its shared variant has.
|
|
468
|
+
const keys = new Set(pkgs.map((pkg) => pkg.key));
|
|
469
|
+
const emitted = (pkg) =>
|
|
470
|
+
pkg.key.endsWith("#shared") ? !keys.has(pkg.importPath) : true;
|
|
351
471
|
const reached = reachableStdlibDecls(
|
|
352
472
|
[options.jsRootPrograms, wasmExportedSignatures(options.wasmUnits)],
|
|
353
|
-
pkgs.flatMap((pkg) => pkg.unit.programs),
|
|
473
|
+
pkgs.filter(emitted).flatMap((pkg) => pkg.unit.programs),
|
|
354
474
|
);
|
|
355
475
|
const out = [];
|
|
356
476
|
const spliced = new Set();
|
|
@@ -362,7 +482,8 @@ function spliceStdlibJs(merged, options) {
|
|
|
362
482
|
}
|
|
363
483
|
if (spliced.has(path)) continue;
|
|
364
484
|
spliced.add(path);
|
|
365
|
-
const
|
|
485
|
+
const pkg = options.stdlibCache.get(path);
|
|
486
|
+
const js = emitted(pkg) ? stdlibJs(pkg, reached, options.natives) : "";
|
|
366
487
|
const code = js === "" ? [] : js.split("\n");
|
|
367
488
|
const delta = code.length - 1;
|
|
368
489
|
for (const m of merged.mappings)
|
|
@@ -392,10 +513,10 @@ function emitStdlibPackage(
|
|
|
392
513
|
emitStdlibPackage(dep, importerTarget, preambles, bundledDirs, options);
|
|
393
514
|
// Every importer leaves a JS marker: the facade of a wasm package may
|
|
394
515
|
// expose a stdlib type; unreachable code splices to nothing.
|
|
395
|
-
const key = `${pkg.
|
|
516
|
+
const key = `${pkg.key}:js`;
|
|
396
517
|
if (!bundledDirs.has(key)) {
|
|
397
518
|
bundledDirs.add(key);
|
|
398
|
-
preambles.push(stdlibMarker(pkg.
|
|
519
|
+
preambles.push(stdlibMarker(pkg.key));
|
|
399
520
|
}
|
|
400
521
|
if (importerTarget !== "js") registerWasmUnit(options, pkg.unit);
|
|
401
522
|
}
|
|
@@ -422,47 +543,75 @@ function bindStdlibImport(checker, p, spec, pkg) {
|
|
|
422
543
|
return;
|
|
423
544
|
}
|
|
424
545
|
const name = alias ?? pkg.pkgName;
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
if (pkg.overlay && name !== pkg.pkgName) {
|
|
428
|
-
errAtImport(
|
|
429
|
-
checker,
|
|
430
|
-
p,
|
|
431
|
-
spec,
|
|
432
|
-
`import alias for '${path}' is not supported`,
|
|
433
|
-
);
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
checker.globals.define(name, { ...pkg.namespace, name });
|
|
546
|
+
const ns = { ...pkg.namespace, name };
|
|
547
|
+
checker.globals.define(name, ns);
|
|
437
548
|
for (const [k, t] of pkg.exportedTypes) {
|
|
438
549
|
const dot = k.indexOf(".");
|
|
439
550
|
checker.types.set(dot < 0 ? k : `${name}${k.slice(dot)}`, t);
|
|
440
551
|
}
|
|
441
|
-
if (!
|
|
552
|
+
if (!spec._implicit)
|
|
442
553
|
checker.trackImport(name, importNode(spec), p._filename, p._source);
|
|
443
554
|
}
|
|
444
555
|
|
|
445
|
-
//
|
|
446
|
-
//
|
|
447
|
-
//
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
556
|
+
// The generators behind the package's `gofront_gen.go`: each scans the
|
|
557
|
+
// checked programs for its call sites, marks them with `_genEntry` and returns
|
|
558
|
+
// null (no sites) or { body, imports, diagnostics }.
|
|
559
|
+
const GENERATORS = [
|
|
560
|
+
generateJsonCodecs,
|
|
561
|
+
generateErrorsAs,
|
|
562
|
+
generateFmtFormatters,
|
|
563
|
+
];
|
|
564
|
+
|
|
565
|
+
// Generates, imports and checks the package's generated Go (json codecs,
|
|
566
|
+
// `errors.As` functions) as one more file. Returns the generated programs:
|
|
567
|
+
// none for a package with errors or one with no generated call sites.
|
|
568
|
+
export function checkGeneratedGo(
|
|
569
|
+
programs,
|
|
570
|
+
checker,
|
|
571
|
+
preambles,
|
|
572
|
+
options,
|
|
573
|
+
deps,
|
|
574
|
+
generators = GENERATORS,
|
|
575
|
+
) {
|
|
576
|
+
if (checker.errors.length > 0) return [];
|
|
577
|
+
const parts = generators
|
|
578
|
+
.map((gen) => gen(programs, checker, checker.pkgName, options))
|
|
579
|
+
.filter(Boolean);
|
|
580
|
+
if (parts.length === 0) return [];
|
|
581
|
+
let failed = false;
|
|
582
|
+
for (const { diagnostics } of parts)
|
|
583
|
+
for (const { program, node, message, hint } of diagnostics) {
|
|
584
|
+
failed = true;
|
|
585
|
+
checker._setCurrentFile(program);
|
|
586
|
+
checker.recordBlocker("unsupported stdlib member", message);
|
|
587
|
+
checker.err(message, node, hint);
|
|
588
|
+
}
|
|
589
|
+
if (failed) return [];
|
|
590
|
+
// An import is a path or { path, alias }.
|
|
591
|
+
const specs = new Map();
|
|
592
|
+
for (const imp of parts.flatMap((p) => p.imports)) {
|
|
593
|
+
const { path, alias } = typeof imp === "string" ? { path: imp } : imp;
|
|
594
|
+
specs.set(`${alias ?? ""} ${path}`, { path, alias });
|
|
457
595
|
}
|
|
458
|
-
|
|
459
|
-
const
|
|
596
|
+
const imports = [...specs.values()];
|
|
597
|
+
const source = [
|
|
598
|
+
`package ${checker.pkgName}`,
|
|
599
|
+
...(imports.length > 0
|
|
600
|
+
? [
|
|
601
|
+
`import (\n${imports.map(({ path, alias }) => `\t${alias ? `${alias} ` : ""}${JSON.stringify(path)}`).join("\n")}\n)`,
|
|
602
|
+
]
|
|
603
|
+
: []),
|
|
604
|
+
...parts.map((p) => p.body),
|
|
605
|
+
"",
|
|
606
|
+
].join("\n\n");
|
|
607
|
+
const filename = "gofront_gen.go";
|
|
460
608
|
const ast = new Parser(
|
|
461
|
-
new Lexer(
|
|
609
|
+
new Lexer(source, filename).tokenize(),
|
|
462
610
|
filename,
|
|
463
|
-
|
|
611
|
+
source,
|
|
464
612
|
).parse();
|
|
465
|
-
ast._source =
|
|
613
|
+
ast._source = source;
|
|
614
|
+
ast._generated = true;
|
|
466
615
|
ast._path = join(dirname(programs[0]._path ?? "."), filename);
|
|
467
616
|
ast.target = checker.target;
|
|
468
617
|
importStdlibPackages(
|
|
@@ -481,12 +630,94 @@ export function checkJsonCodecs(programs, checker, preambles, options, deps) {
|
|
|
481
630
|
.map((e) => e.message)
|
|
482
631
|
.join("\n");
|
|
483
632
|
throw new Error(
|
|
484
|
-
`internal error in the generated
|
|
633
|
+
`internal error in the generated Go; please report\n${detail}`,
|
|
485
634
|
);
|
|
486
635
|
}
|
|
636
|
+
for (const { link } of parts) link?.(checker);
|
|
487
637
|
return [ast];
|
|
488
638
|
}
|
|
489
639
|
|
|
640
|
+
// Packages a `js` package may use without importing them, as the compiler
|
|
641
|
+
// has always allowed: a program that selects from the identifier (or, for
|
|
642
|
+
// `gom`, declares a templ component, typed as `gom.Node`) without declaring
|
|
643
|
+
// or importing it gets the import.
|
|
644
|
+
const IMPLICIT_PACKAGES = ["fmt", "gom", "regexp"];
|
|
645
|
+
|
|
646
|
+
function implicitImports(programs) {
|
|
647
|
+
const declared = (name) =>
|
|
648
|
+
programs.some(
|
|
649
|
+
(p) =>
|
|
650
|
+
p.imports.some((imp) =>
|
|
651
|
+
imp.imports.some((s) => s.path === name || s.alias === name),
|
|
652
|
+
) || stdlibTopLevelNames([p]).values.has(name),
|
|
653
|
+
);
|
|
654
|
+
const used = new Set();
|
|
655
|
+
const visit = (node) => {
|
|
656
|
+
if (!node || typeof node !== "object") return;
|
|
657
|
+
if (Array.isArray(node)) return node.forEach(visit);
|
|
658
|
+
if (node.kind === "TemplDecl") used.add("gom");
|
|
659
|
+
else if (
|
|
660
|
+
node.kind === "SelectorExpr" &&
|
|
661
|
+
IMPLICIT_PACKAGES.includes(node.expr?.name)
|
|
662
|
+
)
|
|
663
|
+
used.add(node.expr.name);
|
|
664
|
+
else if (typeof node.name === "string" && node.kind?.endsWith("TypeName"))
|
|
665
|
+
for (const name of IMPLICIT_PACKAGES)
|
|
666
|
+
if (node.name.startsWith(`${name}.`)) used.add(name);
|
|
667
|
+
forEachChild(node, visit);
|
|
668
|
+
};
|
|
669
|
+
for (const p of programs) visit(p.decls);
|
|
670
|
+
return [...used]
|
|
671
|
+
.filter((name) => !declared(name))
|
|
672
|
+
.map((path) => ({ path, _line: 1, _col: 1, _implicit: true }));
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// Packages that keep their own wording for the unavailable-in-wasm error.
|
|
676
|
+
const NOT_IN_WASM = new Map([["gom", "gom usage"]]);
|
|
677
|
+
|
|
678
|
+
// Reports an import of a `js`-only package from a `wasm` or `both` package.
|
|
679
|
+
function errJsOnlyImport(checker, p, spec) {
|
|
680
|
+
// Its uses are not a second root cause.
|
|
681
|
+
checker._unavailableImports ??= new Set();
|
|
682
|
+
checker._unavailableImports.add(spec.alias ?? spec.path.split("/").at(-1));
|
|
683
|
+
const category = NOT_IN_WASM.get(spec.path);
|
|
684
|
+
if (category) {
|
|
685
|
+
checker.recordBlocker(category, spec.path);
|
|
686
|
+
const msg = `package '${spec.path}' is not available in wasm packages`;
|
|
687
|
+
return errAtImport(checker, p, spec, msg);
|
|
688
|
+
}
|
|
689
|
+
checker.recordBlocker("unsupported stdlib import", spec.path);
|
|
690
|
+
const msg = `package '${spec.path}' is only available in js packages`;
|
|
691
|
+
errAtImport(checker, p, spec, msg, "move this code to a js package");
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Loads and binds one import of program `p`.
|
|
695
|
+
function importStdlibSpec(
|
|
696
|
+
p,
|
|
697
|
+
spec,
|
|
698
|
+
checker,
|
|
699
|
+
preambles,
|
|
700
|
+
bundledDirs,
|
|
701
|
+
options,
|
|
702
|
+
deps,
|
|
703
|
+
) {
|
|
704
|
+
if (spec.path.startsWith("js:") || isLocalPath(spec.path)) return;
|
|
705
|
+
const dir = resolveStdlibSource(spec.path, options.stdlibRoot);
|
|
706
|
+
if (!dir) return;
|
|
707
|
+
const wasmImporter = checker.target === "wasm" || checker.target === "both";
|
|
708
|
+
if (wasmImporter && stdlibIsJsOnly(dir, deps))
|
|
709
|
+
return errJsOnlyImport(checker, p, spec);
|
|
710
|
+
let pkg;
|
|
711
|
+
try {
|
|
712
|
+
pkg = loadStdlibPackage(spec.path, dir, options, deps, checker.target);
|
|
713
|
+
} catch (e) {
|
|
714
|
+
const msg = `internal stdlib error in ${spec.path}; please report`;
|
|
715
|
+
return errAtImport(checker, p, spec, msg, e.message);
|
|
716
|
+
}
|
|
717
|
+
emitStdlibPackage(pkg, checker.target, preambles, bundledDirs, options);
|
|
718
|
+
bindStdlibImport(checker, p, spec, pkg);
|
|
719
|
+
}
|
|
720
|
+
|
|
490
721
|
export function importStdlibPackages(
|
|
491
722
|
programs,
|
|
492
723
|
checker,
|
|
@@ -495,21 +726,12 @@ export function importStdlibPackages(
|
|
|
495
726
|
options,
|
|
496
727
|
deps,
|
|
497
728
|
) {
|
|
729
|
+
const wasmImporter = checker.target === "wasm" || checker.target === "both";
|
|
730
|
+
const implicit = wasmImporter ? [] : implicitImports(programs);
|
|
498
731
|
for (const p of programs) {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
let pkg;
|
|
504
|
-
try {
|
|
505
|
-
pkg = loadStdlibPackage(spec.path, dir, options, deps);
|
|
506
|
-
} catch (e) {
|
|
507
|
-
const msg = `internal stdlib error in ${spec.path}; please report`;
|
|
508
|
-
errAtImport(checker, p, spec, msg, e.message);
|
|
509
|
-
continue;
|
|
510
|
-
}
|
|
511
|
-
emitStdlibPackage(pkg, checker.target, preambles, bundledDirs, options);
|
|
512
|
-
bindStdlibImport(checker, p, spec, pkg);
|
|
513
|
-
}
|
|
732
|
+
const specs = p.imports.flatMap((imp) => imp.imports);
|
|
733
|
+
if (p === programs[0]) specs.push(...implicit);
|
|
734
|
+
for (const spec of specs)
|
|
735
|
+
importStdlibSpec(p, spec, checker, preambles, bundledDirs, options, deps);
|
|
514
736
|
}
|
|
515
737
|
}
|