@scriptc/compiler 0.1.1 → 0.1.2
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/ambient/scriptc-node-fallback.d.ts +45 -17
- package/ambient/scriptc.d.ts +2 -1
- package/dist/backend/build-cache.js.map +1 -1
- package/dist/backend/c/async.js +24 -2
- package/dist/backend/c/async.js.map +1 -1
- package/dist/backend/c/c-emitter.d.ts +22 -10
- package/dist/backend/c/c-emitter.js +60 -15
- package/dist/backend/c/c-emitter.js.map +1 -1
- package/dist/backend/c/exprs.js +220 -10
- package/dist/backend/c/exprs.js.map +1 -1
- package/dist/backend/c/island.js.map +1 -1
- package/dist/backend/c/may-throw.js.map +1 -1
- package/dist/backend/c/stmts.d.ts +3 -5
- package/dist/backend/c/stmts.js +58 -17
- package/dist/backend/c/stmts.js.map +1 -1
- package/dist/backend/c/types.js.map +1 -1
- package/dist/backend/c/walkers.js +31 -5
- package/dist/backend/c/walkers.js.map +1 -1
- package/dist/backend/external-c.js.map +1 -1
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/dyn.js +56 -3
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +98 -19
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +85 -3
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +1 -0
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +6 -3
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +220 -9
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +2 -0
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +18 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +6 -3
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +2 -0
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/compat/fetch-profile.js +4 -2
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +12 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +6 -5
- package/dist/diagnostics/diagnostic.js +7 -6
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/ffi/ffi-manifest.js.map +1 -1
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +10 -0
- package/dist/frontend/input-tracker.js +26 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +8 -1
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +4 -0
- package/dist/frontend/lowering/array-values.js +18 -2
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/callback-arg.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.d.ts +35 -0
- package/dist/frontend/lowering/containers/bytes.js +1021 -0
- package/dist/frontend/lowering/containers/bytes.js.map +1 -0
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +17 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js +345 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.d.ts +13 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js +76 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.d.ts +44 -0
- package/dist/frontend/lowering/expressions/object-literals.js +1815 -0
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -0
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +31 -0
- package/dist/frontend/lowering/expressions/optional-chains.js +382 -0
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.d.ts +7 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js +26 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.js +7 -2
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +7 -0
- package/dist/frontend/lowering/lower-async-iteration.js +657 -0
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +18 -0
- package/dist/frontend/lowering/lower-builtins.js +219 -48
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +13 -4
- package/dist/frontend/lowering/lower-calls.js +407 -64
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +7 -13
- package/dist/frontend/lowering/lower-classes.js +128 -35
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +1 -47
- package/dist/frontend/lowering/lower-containers.js +135 -1467
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.js +51 -5
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +0 -78
- package/dist/frontend/lowering/lower-exprs.js +402 -2351
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +18 -3
- package/dist/frontend/lowering/lower-generators.js +145 -9
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +3 -3
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +6 -0
- package/dist/frontend/lowering/lower-island.js +37 -5
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +52 -15
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +18 -0
- package/dist/frontend/lowering/lower-node-module.js +302 -0
- package/dist/frontend/lowering/lower-node-module.js.map +1 -0
- package/dist/frontend/lowering/lower-server.js +1 -1
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +5 -24
- package/dist/frontend/lowering/lower-stmts.js +519 -253
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +4 -4
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +37 -34
- package/dist/frontend/lowering/lowerer.js +143 -57
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/optional-arguments.d.ts +9 -0
- package/dist/frontend/lowering/optional-arguments.js +57 -0
- package/dist/frontend/lowering/optional-arguments.js.map +1 -0
- package/dist/frontend/npm-static-declarations.d.ts +35 -0
- package/dist/frontend/npm-static-declarations.js +506 -0
- package/dist/frontend/npm-static-declarations.js.map +1 -0
- package/dist/frontend/npm-static-declarations.test.d.ts +1 -0
- package/dist/frontend/npm-static-declarations.test.js +122 -0
- package/dist/frontend/npm-static-declarations.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +2 -0
- package/dist/frontend/npm-static.js +26 -10
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +60 -0
- package/dist/frontend/npm.js +38 -4
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.d.ts +1 -0
- package/dist/frontend/npm.test.js +50 -0
- package/dist/frontend/npm.test.js.map +1 -0
- package/dist/frontend/program.d.ts +3 -2
- package/dist/frontend/program.js +495 -68
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.d.ts +10 -2
- package/dist/frontend/resolve.js +90 -14
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.js +4 -1
- package/dist/frontend/resolve.test.js.map +1 -1
- package/dist/frontend/runtime-resolve.d.ts +22 -0
- package/dist/frontend/runtime-resolve.js +101 -0
- package/dist/frontend/runtime-resolve.js.map +1 -0
- package/dist/frontend/runtime-resolve.test.d.ts +1 -0
- package/dist/frontend/runtime-resolve.test.js +18 -0
- package/dist/frontend/runtime-resolve.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.js +12 -13
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/census-check.js +3 -3
- package/dist/frontend/ts7/census-check.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +3 -0
- package/dist/frontend/ts7/checker.js +12 -3
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/program-adapter.js +42 -3
- package/dist/frontend/ts7/program-adapter.js.map +1 -1
- package/dist/frontend/type-mapper.js +120 -7
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/ir.d.ts +60 -30
- package/dist/ir/ir.js +57 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/validate.js +44 -59
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/cache-reset.test.js.map +1 -1
- package/dist/library/compiler-self-identity.js.map +1 -1
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.js.map +1 -1
- package/dist/startup-cache.js.map +1 -1
- package/dist/wasi-paths.js.map +1 -1
- package/package.json +18 -18
- package/surface-manifest.json +60 -4
package/dist/frontend/program.js
CHANGED
|
@@ -39,19 +39,20 @@
|
|
|
39
39
|
* JSON.parse's wording rather than tsc's, the one message-text delta on
|
|
40
40
|
* that path (no snapshot pins it). */
|
|
41
41
|
import { builtinModules } from "node:module";
|
|
42
|
-
import { dirname, resolve } from "node:path";
|
|
42
|
+
import { dirname, isAbsolute, resolve } from "node:path";
|
|
43
43
|
import * as ts from "./ts7/adapter.js";
|
|
44
44
|
import { commonJsModuleSyntaxDiag, invalidPackageConfigDiag, strictNullChecksFloorDiag, tscPassthroughDiag, unsupportedDiag, } from "../diagnostics/diagnostic.js";
|
|
45
|
-
import { isNodeModulesPath, nearestInvalidPackageJsonPath, nearestPackageType, nearestPkgJsonPath, projectDtsRuntimeSibling, resolveBareModule,
|
|
45
|
+
import { isNodeModulesPath, nearestInvalidPackageJsonPath, nearestPackageType, nearestPkgJsonPath, projectDtsRuntimeSibling, resolveBareModule, resolveProjectModule, resolveTypeDirective, setProjectPathMappings, setProjectRealm } from "./resolve.js";
|
|
46
46
|
import { probeNodeImportRefusal, probeNodeRequireRefusal } from "./npm.js";
|
|
47
|
-
import { isNpmStaticPackage, npmStaticActive, npmStaticFsShadow, npmStaticPackageOfPath, reportNpmStaticOffender, setNpmStaticPackages } from "./npm-static.js";
|
|
47
|
+
import { isNpmStaticPackage, npmStaticActive, npmStaticFsShadow, npmStaticPackageOfPath, reportNpmStaticOffender, setNpmStaticDeclarationOverloads, setNpmStaticPackages } from "./npm-static.js";
|
|
48
|
+
import { npmStaticDeclarationReexports, npmStaticRuntimeClassTargets, parseNpmStaticDeclarationOverloads, parseNpmStaticDeclarationProperties } from "./npm-static-declarations.js";
|
|
48
49
|
import { provenanceEntryFor, provenancePaths } from "./provenance-registry.js";
|
|
49
50
|
import { cjsLexerVisibleNames } from "./cjs-lexer.js";
|
|
50
51
|
import { ambientDtsPath, fallbackDtsPath, isNodeTypesPath, overridesDtsPath, tsgoPath, } from "./dts-paths.js";
|
|
51
52
|
import { builtinDefaultImportModule, canonicalBuiltinModule, SUPPORTED_NODE_MODULES, unsupportedModuleFeatureOf, } from "./builtin-modules.js";
|
|
52
|
-
import { clearWorkspacePackages, isRelativeSpecifier, isWorkspacePackageName, registerWorkspacePackage, workspacePackageOfPath, } from "./workspace-registry.js";
|
|
53
|
+
import { clearWorkspacePackages, isRelativeSpecifier, isWorkspacePackageName, npmPackageNameOf, registerWorkspacePackage, workspacePackageOfPath, } from "./workspace-registry.js";
|
|
53
54
|
import { ADOPTED_OPTIONS, isJsSourceFileName, JS_ANY_OPERATOR_CODES, JS_RELAXED_TSC_CODES, } from "./tsc-codes.js";
|
|
54
|
-
import { trackedFileExists } from "./input-tracker.js";
|
|
55
|
+
import { trackedFileExists, trackedReadFile, trackedRealpath } from "./input-tracker.js";
|
|
55
56
|
const BASE_OPTIONS = {
|
|
56
57
|
strict: true,
|
|
57
58
|
};
|
|
@@ -67,7 +68,10 @@ const FORCED_OPTIONS = {
|
|
|
67
68
|
// classification is intentionally independent below; this option is only
|
|
68
69
|
// the binder's scope decision.
|
|
69
70
|
moduleDetection: ts.ModuleDetectionKind.Force,
|
|
70
|
-
|
|
71
|
+
// Explicit resource management is an ESNext library slice in TS 7 even
|
|
72
|
+
// though Node 24 ships the runtime protocol. Include that focused lib
|
|
73
|
+
// without widening the rest of the standard-library target past ES2025.
|
|
74
|
+
lib: ["lib.es2025.d.ts", "lib.esnext.disposable.d.ts"],
|
|
71
75
|
types: [],
|
|
72
76
|
allowImportingTsExtensions: true,
|
|
73
77
|
allowJs: true,
|
|
@@ -142,6 +146,28 @@ function adoptProjectConfig7(host, entryPath) {
|
|
|
142
146
|
if (value !== undefined)
|
|
143
147
|
adopted[key] = value;
|
|
144
148
|
}
|
|
149
|
+
// TS 7 accepts `paths`, but no longer accepts `baseUrl` as a compiler
|
|
150
|
+
// option. Translate the established baseUrl+paths spelling into absolute
|
|
151
|
+
// targets: the synthesized config lives beside the entry rather than the
|
|
152
|
+
// real config, so preserving relative targets would silently change their
|
|
153
|
+
// meaning. The absolute map is also the own resolver's configuration.
|
|
154
|
+
const rawPaths = parsed.options["paths"];
|
|
155
|
+
if (rawPaths !== undefined && typeof rawPaths === "object" && rawPaths !== null) {
|
|
156
|
+
const configDir = dirname(configFile);
|
|
157
|
+
const rawBaseUrl = parsed.options["baseUrl"];
|
|
158
|
+
const base = typeof rawBaseUrl === "string"
|
|
159
|
+
? (isAbsolute(rawBaseUrl) ? rawBaseUrl : resolve(configDir, rawBaseUrl))
|
|
160
|
+
: configDir;
|
|
161
|
+
const paths = {};
|
|
162
|
+
for (const [key, targets] of Object.entries(rawPaths)) {
|
|
163
|
+
if (!Array.isArray(targets))
|
|
164
|
+
continue;
|
|
165
|
+
paths[key] = targets
|
|
166
|
+
.filter((target) => typeof target === "string")
|
|
167
|
+
.map((target) => isAbsolute(target) ? target : resolve(base, target));
|
|
168
|
+
}
|
|
169
|
+
adopted["paths"] = paths;
|
|
170
|
+
}
|
|
145
171
|
const nullChecks = adopted["strictNullChecks"] ?? adopted["strict"] ?? false;
|
|
146
172
|
if (nullChecks !== true) {
|
|
147
173
|
diags.push(strictNullChecksFloorDiag(configFile));
|
|
@@ -156,6 +182,94 @@ function resolveNodeTypes7(entryPath) {
|
|
|
156
182
|
const file = resolveTypeDirective("node", entryPath);
|
|
157
183
|
return file !== null && isNodeTypesPath(file) ? file : null;
|
|
158
184
|
}
|
|
185
|
+
function declarationReexportTarget(fromFile, specifier) {
|
|
186
|
+
const base = resolve(dirname(fromFile), specifier);
|
|
187
|
+
const candidates = [];
|
|
188
|
+
const extension = /\.(mjs|cjs|js)$/.exec(base)?.[1];
|
|
189
|
+
if (extension !== undefined) {
|
|
190
|
+
const stem = base.slice(0, -(extension.length + 1));
|
|
191
|
+
if (extension === "mjs")
|
|
192
|
+
candidates.push(`${stem}.d.mts`, `${stem}.d.ts`);
|
|
193
|
+
else if (extension === "cjs")
|
|
194
|
+
candidates.push(`${stem}.d.cts`, `${stem}.d.ts`);
|
|
195
|
+
else
|
|
196
|
+
candidates.push(`${stem}.d.ts`, `${stem}.d.mts`, `${stem}.d.cts`);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
candidates.push(base, `${base}.d.ts`, `${base}.d.mts`, `${base}.d.cts`);
|
|
200
|
+
}
|
|
201
|
+
candidates.push(resolve(base, "index.d.ts"), resolve(base, "index.d.mts"), resolve(base, "index.d.cts"));
|
|
202
|
+
return candidates.find((candidate) => trackedFileExists(candidate)) ?? null;
|
|
203
|
+
}
|
|
204
|
+
function runtimeReexportTarget(fromFile, specifier) {
|
|
205
|
+
const base = resolve(dirname(fromFile), specifier);
|
|
206
|
+
const candidates = [
|
|
207
|
+
base,
|
|
208
|
+
`${base}.js`,
|
|
209
|
+
`${base}.mjs`,
|
|
210
|
+
`${base}.cjs`,
|
|
211
|
+
resolve(base, "index.js"),
|
|
212
|
+
resolve(base, "index.mjs"),
|
|
213
|
+
resolve(base, "index.cjs"),
|
|
214
|
+
];
|
|
215
|
+
const target = candidates.find((candidate) => trackedFileExists(candidate) && isJsSourceFileName(candidate));
|
|
216
|
+
return target === undefined ? null : (trackedRealpath(target) ?? target);
|
|
217
|
+
}
|
|
218
|
+
/** Visits an opted package's own declaration entry and relative barrel
|
|
219
|
+
* closure. This is intentionally narrower than TypeScript module
|
|
220
|
+
* resolution: bare edges name other packages and never inherit trust. */
|
|
221
|
+
function visitNpmStaticDeclarationClosure(entryPath, onSource) {
|
|
222
|
+
const seen = new Set();
|
|
223
|
+
const packageJson = nearestPkgJsonPath(entryPath);
|
|
224
|
+
const packageRoot = (packageJson === null ? dirname(entryPath) : dirname(packageJson)).split("\\").join("/");
|
|
225
|
+
const visit = (path) => {
|
|
226
|
+
path = resolve(path);
|
|
227
|
+
const normalized = path.split("\\").join("/");
|
|
228
|
+
if (normalized !== packageRoot && !normalized.startsWith(packageRoot + "/"))
|
|
229
|
+
return;
|
|
230
|
+
if (seen.has(path))
|
|
231
|
+
return;
|
|
232
|
+
seen.add(path);
|
|
233
|
+
const source = trackedReadFile(path);
|
|
234
|
+
if (source === null)
|
|
235
|
+
return;
|
|
236
|
+
onSource(path, source);
|
|
237
|
+
for (const specifier of npmStaticDeclarationReexports(path, source)) {
|
|
238
|
+
const target = declarationReexportTarget(path, specifier);
|
|
239
|
+
if (target !== null)
|
|
240
|
+
visit(target);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
visit(entryPath);
|
|
244
|
+
}
|
|
245
|
+
function npmStaticDeclarationOverloadsOf(entryPath) {
|
|
246
|
+
const classes = new Map();
|
|
247
|
+
visitNpmStaticDeclarationClosure(entryPath, (path, source) => {
|
|
248
|
+
for (const [className, methods] of parseNpmStaticDeclarationOverloads(path, source)) {
|
|
249
|
+
const target = classes.get(className) ?? new Map();
|
|
250
|
+
classes.set(className, target);
|
|
251
|
+
for (const [methodName, signatures] of methods) {
|
|
252
|
+
if (!target.has(methodName))
|
|
253
|
+
target.set(methodName, signatures);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
return classes;
|
|
258
|
+
}
|
|
259
|
+
function npmStaticDeclarationPropertiesOf(entryPath) {
|
|
260
|
+
const classes = new Map();
|
|
261
|
+
visitNpmStaticDeclarationClosure(entryPath, (path, source) => {
|
|
262
|
+
for (const [className, properties] of parseNpmStaticDeclarationProperties(path, source)) {
|
|
263
|
+
const target = classes.get(className) ?? new Map();
|
|
264
|
+
classes.set(className, target);
|
|
265
|
+
for (const [propertyName, type] of properties) {
|
|
266
|
+
if (!target.has(propertyName))
|
|
267
|
+
target.set(propertyName, type);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
return classes;
|
|
272
|
+
}
|
|
159
273
|
/** True when a coverage mapping names one exact bare host module. TypeScript
|
|
160
274
|
* gives `paths` keys containing `*` pattern semantics, so accepting one here
|
|
161
275
|
* would silently broaden the mapping beyond the specifier the caller named. */
|
|
@@ -232,6 +346,10 @@ function externalTypeFileClosure7(program, externalTypes) {
|
|
|
232
346
|
}
|
|
233
347
|
function loadProgram7(host, entryPath, externalTypes = new Map()) {
|
|
234
348
|
const config = adoptProjectConfig7(host, entryPath);
|
|
349
|
+
const configuredPaths = config.options["paths"];
|
|
350
|
+
setProjectPathMappings(configuredPaths !== undefined && typeof configuredPaths === "object" && configuredPaths !== null
|
|
351
|
+
? configuredPaths
|
|
352
|
+
: null);
|
|
235
353
|
const nodeTypes = config.configFile ? resolveNodeTypes7(entryPath) : null;
|
|
236
354
|
// skipLibCheck is FORCED with @types/node in the program: checking a
|
|
237
355
|
// third-party lib's internals against OUR lib choice (es2025, no dyn) is
|
|
@@ -251,7 +369,10 @@ function loadProgram7(host, entryPath, externalTypes = new Map()) {
|
|
|
251
369
|
// driver against the package's real TypeScript, not its shipped .d.ts.
|
|
252
370
|
const provenance = provenancePaths();
|
|
253
371
|
if (provenance !== null || externalTypes.size > 0) {
|
|
254
|
-
const paths = {
|
|
372
|
+
const paths = {
|
|
373
|
+
...configuredPaths,
|
|
374
|
+
...(provenance ?? {}),
|
|
375
|
+
};
|
|
255
376
|
for (const [specifier, declarationPath] of externalTypes) {
|
|
256
377
|
paths[specifier] = [declarationPath];
|
|
257
378
|
}
|
|
@@ -303,7 +424,60 @@ export function loadProgram(entryPath, opts) {
|
|
|
303
424
|
}
|
|
304
425
|
externalTypes.set(specifier, declarationPath);
|
|
305
426
|
}
|
|
306
|
-
|
|
427
|
+
const npmStaticPackages = [...new Set(opts?.npmStatic ?? [])];
|
|
428
|
+
// Resolve authored declaration entries before enabling the JS-only
|
|
429
|
+
// package resolver. Safe overload metadata binds through the runtime
|
|
430
|
+
// entry to one exact implementation file; it never contributes values
|
|
431
|
+
// or executable module edges.
|
|
432
|
+
const declarationOverloads = new Map();
|
|
433
|
+
const declarationProperties = new Map();
|
|
434
|
+
for (const pkg of npmStaticPackages) {
|
|
435
|
+
const resolved = resolveBareModule(entryPath, pkg, "types-only");
|
|
436
|
+
if (resolved === null ||
|
|
437
|
+
resolved.packageName !== pkg ||
|
|
438
|
+
!/\.d\.(?:ts|mts|cts)$/.test(resolved.typesFile)) {
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
const overloads = npmStaticDeclarationOverloadsOf(resolved.typesFile);
|
|
442
|
+
const properties = npmStaticDeclarationPropertiesOf(resolved.typesFile);
|
|
443
|
+
const classNames = new Set([...overloads.keys(), ...properties.keys()]);
|
|
444
|
+
if (classNames.size === 0)
|
|
445
|
+
continue;
|
|
446
|
+
const runtime = resolveBareModule(entryPath, pkg, "js-only");
|
|
447
|
+
if (runtime === null || !isJsSourceFileName(runtime.typesFile))
|
|
448
|
+
continue;
|
|
449
|
+
const runtimeSource = trackedReadFile(runtime.typesFile);
|
|
450
|
+
if (runtimeSource === null)
|
|
451
|
+
continue;
|
|
452
|
+
const targets = npmStaticRuntimeClassTargets(runtime.typesFile, runtimeSource, classNames);
|
|
453
|
+
for (const [className, specifier] of targets) {
|
|
454
|
+
const methods = overloads.get(className);
|
|
455
|
+
const fields = properties.get(className);
|
|
456
|
+
if (methods === undefined && fields === undefined)
|
|
457
|
+
continue;
|
|
458
|
+
const target = specifier === null ? runtime.typesFile : runtimeReexportTarget(runtime.typesFile, specifier);
|
|
459
|
+
if (target === null)
|
|
460
|
+
continue;
|
|
461
|
+
const targetPackage = npmPackageNameOf(target);
|
|
462
|
+
const targetNorm = target.split("\\").join("/");
|
|
463
|
+
const insideWorkspace = runtime.workspaceDir !== undefined &&
|
|
464
|
+
targetNorm.startsWith(runtime.workspaceDir.split("\\").join("/") + "/");
|
|
465
|
+
if (targetPackage !== pkg && !insideWorkspace)
|
|
466
|
+
continue;
|
|
467
|
+
if (methods !== undefined) {
|
|
468
|
+
const byClass = new Map(declarationOverloads.get(targetNorm) ?? []);
|
|
469
|
+
byClass.set(className, methods);
|
|
470
|
+
declarationOverloads.set(targetNorm, byClass);
|
|
471
|
+
}
|
|
472
|
+
if (fields !== undefined) {
|
|
473
|
+
const byClass = new Map(declarationProperties.get(targetNorm) ?? []);
|
|
474
|
+
byClass.set(className, fields);
|
|
475
|
+
declarationProperties.set(targetNorm, byClass);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
setNpmStaticPackages(npmStaticPackages);
|
|
480
|
+
setNpmStaticDeclarationOverloads(declarationOverloads, declarationProperties);
|
|
307
481
|
// Workspace-package registrations reset per load (same discipline as the
|
|
308
482
|
// npm-static set), then the opted-in names are probed UP FRONT: a
|
|
309
483
|
// workspace-linked opt-in resolves to files whose realpaths carry no
|
|
@@ -1327,7 +1501,7 @@ export function makeCycleAdmission(program, edgesOf) {
|
|
|
1327
1501
|
* resolveImport) for the lowering: CommonJS require statements lower to
|
|
1328
1502
|
* guarded %init calls of exactly the module preflight resolved here. */
|
|
1329
1503
|
function resolveImport7(program, from, specifier) {
|
|
1330
|
-
const resolved =
|
|
1504
|
+
const resolved = resolveProjectModule(from.fileName, specifier);
|
|
1331
1505
|
if (resolved === null)
|
|
1332
1506
|
return null;
|
|
1333
1507
|
return program.getSourceFile(resolved) ?? null;
|
|
@@ -1342,7 +1516,7 @@ function resolveNpmImport7(fromFileName, specifier) {
|
|
|
1342
1516
|
return null;
|
|
1343
1517
|
}
|
|
1344
1518
|
// --provenance-sources: a registered specifier is NOT an npm import —
|
|
1345
|
-
// its attested source compiles as program modules (
|
|
1519
|
+
// its attested source compiles as program modules (resolveProjectModule
|
|
1346
1520
|
// answers the entry), so no island embed and no .d.ts type surface.
|
|
1347
1521
|
if (provenanceEntryFor(specifier) !== null)
|
|
1348
1522
|
return null;
|
|
@@ -1888,9 +2062,15 @@ function preflight7(load) {
|
|
|
1888
2062
|
pos: stmt.getStart(sf),
|
|
1889
2063
|
});
|
|
1890
2064
|
};
|
|
2065
|
+
// Project modules win before npm fallback: this is the source graph
|
|
2066
|
+
// tsgo type-checked for tsconfig paths, package imports/self-references,
|
|
2067
|
+
// and provenance entries. Ordinary packages still answer null here.
|
|
2068
|
+
const projDep = isBare ? resolveImport7(program, sf, spec) : null;
|
|
1891
2069
|
// "#" specifiers can never name an npm package — they are the
|
|
1892
|
-
// imports-field family, resolved
|
|
1893
|
-
const npm = isBare && !spec.startsWith("#")
|
|
2070
|
+
// imports-field family, resolved by the project arm above.
|
|
2071
|
+
const npm = isBare && projDep === null && !spec.startsWith("#")
|
|
2072
|
+
? resolveNpmImport7(sf.fileName, spec)
|
|
2073
|
+
: null;
|
|
1894
2074
|
if (npm && isNodeTypesPath(npm.typesFile)) {
|
|
1895
2075
|
diags.push(unsupportedDiag("SC1010", locOf7(stmt), unsupportedModuleFeatureOf(spec)));
|
|
1896
2076
|
continue;
|
|
@@ -1922,19 +2102,13 @@ function preflight7(load) {
|
|
|
1922
2102
|
continue;
|
|
1923
2103
|
}
|
|
1924
2104
|
}
|
|
1925
|
-
// PROJECT imports: package.json-mediated specifiers
|
|
1926
|
-
// the program's own sources
|
|
1927
|
-
//
|
|
1928
|
-
//
|
|
1929
|
-
//
|
|
1930
|
-
//
|
|
1931
|
-
// exact message; what keeps a compile fence: the unsupported
|
|
1932
|
-
// builtin and the types-only resolution (Node-hostable or ambiguous
|
|
1933
|
-
// — scriptc's own limitations, named as such).
|
|
1934
|
-
let projDep = null;
|
|
2105
|
+
// PROJECT imports: tsconfig paths and package.json-mediated specifiers
|
|
2106
|
+
// that resolve to the program's own sources. A source answer is an
|
|
2107
|
+
// ordinary user-module edge, exactly like a relative import (the
|
|
2108
|
+
// checker resolved the bindings the same way); a refused resolution is
|
|
2109
|
+
// Node's startup crash with Node's exact message; what keeps a compile
|
|
2110
|
+
// fence is unsupported builtin or types-only surface.
|
|
1935
2111
|
if (isBare && npmStaticDep === null) {
|
|
1936
|
-
const resolved = resolveProjectImport(sf.fileName, spec);
|
|
1937
|
-
projDep = resolved !== null ? (program.getSourceFile(resolved) ?? null) : null;
|
|
1938
2112
|
if (projDep !== null && projDep.isDeclarationFile) {
|
|
1939
2113
|
diags.push(unsupportedDiag("SC1010", locOf7(stmt), `the '${spec}' import (it resolves only to type declarations — there is no runtime implementation to compile)`));
|
|
1940
2114
|
continue;
|
|
@@ -2077,8 +2251,8 @@ function preflight7(load) {
|
|
|
2077
2251
|
}
|
|
2078
2252
|
}
|
|
2079
2253
|
const isRelative = isRelativeSpecifier(req.spec);
|
|
2080
|
-
let dep =
|
|
2081
|
-
if (!isRelative) {
|
|
2254
|
+
let dep = resolveImport7(program, sf, req.spec);
|
|
2255
|
+
if (dep === null && !isRelative) {
|
|
2082
2256
|
// --npm-static: a require() of an OPTED-IN package is a
|
|
2083
2257
|
// program-module edge exactly like the import-declaration
|
|
2084
2258
|
// form above (bundle dists require their workspace siblings —
|
|
@@ -2106,9 +2280,6 @@ function preflight7(load) {
|
|
|
2106
2280
|
continue;
|
|
2107
2281
|
}
|
|
2108
2282
|
}
|
|
2109
|
-
else {
|
|
2110
|
-
dep = resolveImport7(program, sf, req.spec);
|
|
2111
|
-
}
|
|
2112
2283
|
if (dep && dep.fileName.endsWith(".json")) {
|
|
2113
2284
|
diags.push(unsupportedDiag("SC1012", loc, "require() of JSON modules"));
|
|
2114
2285
|
continue;
|
|
@@ -2139,6 +2310,15 @@ function preflight7(load) {
|
|
|
2139
2310
|
if (load.externalTypes.has(spec)) {
|
|
2140
2311
|
continue;
|
|
2141
2312
|
}
|
|
2313
|
+
const projectDep = resolveImport7(program, sf, spec);
|
|
2314
|
+
if (projectDep !== null) {
|
|
2315
|
+
if (projectDep.fileName.endsWith(".json")) {
|
|
2316
|
+
diags.push(unsupportedDiag("SC1012", loc, "require() of JSON modules"));
|
|
2317
|
+
continue;
|
|
2318
|
+
}
|
|
2319
|
+
deps.push({ dep: projectDep });
|
|
2320
|
+
continue;
|
|
2321
|
+
}
|
|
2142
2322
|
if (!isRelativeSpecifier(spec)) {
|
|
2143
2323
|
// --npm-static: opted-in packages ride the program-module edge
|
|
2144
2324
|
// (the statement-level require branch above).
|
|
@@ -2158,13 +2338,6 @@ function preflight7(load) {
|
|
|
2158
2338
|
}
|
|
2159
2339
|
continue;
|
|
2160
2340
|
}
|
|
2161
|
-
const dep = resolveImport7(program, sf, spec);
|
|
2162
|
-
if (dep && dep.fileName.endsWith(".json")) {
|
|
2163
|
-
diags.push(unsupportedDiag("SC1012", loc, "require() of JSON modules"));
|
|
2164
|
-
continue;
|
|
2165
|
-
}
|
|
2166
|
-
if (dep)
|
|
2167
|
-
deps.push({ dep });
|
|
2168
2341
|
}
|
|
2169
2342
|
}
|
|
2170
2343
|
}
|
|
@@ -2263,7 +2436,9 @@ function preflight7(load) {
|
|
|
2263
2436
|
}
|
|
2264
2437
|
}
|
|
2265
2438
|
}
|
|
2266
|
-
const linkCrash = resolveCrash !== null
|
|
2439
|
+
const linkCrash = resolveCrash !== null
|
|
2440
|
+
? null
|
|
2441
|
+
: earlierLinkCrash(order, cjsNamedImportLinkCheck(program, entry, order, diags), esmNamedImportLinkCheck(program, entry, order, diags));
|
|
2267
2442
|
return { diags, moduleOrder: order, startupCrash: resolveCrash ?? linkCrash };
|
|
2268
2443
|
}
|
|
2269
2444
|
/** Walks the entry's ESM instantiate graph exactly as V8 does — children
|
|
@@ -2278,21 +2453,18 @@ function preflight7(load) {
|
|
|
2278
2453
|
* not modeled: those get a pointed fence instead. */
|
|
2279
2454
|
function cjsNamedImportLinkCheck(program, entry, moduleOrder, diags) {
|
|
2280
2455
|
const lexMemo = new Map();
|
|
2281
|
-
|
|
2282
|
-
//
|
|
2283
|
-
// — the same package.json-mediated edges preflight admits) join them so
|
|
2456
|
+
// Project specifiers resolve as ever; aliases and package.json-mediated
|
|
2457
|
+
// edges (#alias/self-name) join relative imports so
|
|
2284
2458
|
// a named import THROUGH one of a CommonJS module keeps Node's lexer
|
|
2285
2459
|
// check. Builtin/npm targets contribute nothing here — except opted-in
|
|
2286
2460
|
// --npm-static packages, whose CJS entries face Node's lexer exactly
|
|
2287
2461
|
// like program CJS files (their JS IS the program now).
|
|
2288
2462
|
const resolveEdge = (from, spec) => {
|
|
2289
|
-
|
|
2290
|
-
|
|
2463
|
+
const project = resolveImport7(program, from, spec);
|
|
2464
|
+
if (project !== null)
|
|
2465
|
+
return project;
|
|
2291
2466
|
const npmStatic = npmStaticDepSf7(program, from, spec);
|
|
2292
|
-
|
|
2293
|
-
return npmStatic;
|
|
2294
|
-
const p = resolveProjectImport(from.fileName, spec);
|
|
2295
|
-
return p !== null ? (program.getSourceFile(p) ?? null) : null;
|
|
2467
|
+
return npmStatic;
|
|
2296
2468
|
};
|
|
2297
2469
|
// Reexport targets union in only when they resolve to CommonJS program
|
|
2298
2470
|
// files (Node's cjsPreparseModuleExports rule).
|
|
@@ -2447,6 +2619,279 @@ function cjsNamedImportLinkCheck(program, entry, moduleOrder, diags) {
|
|
|
2447
2619
|
loc,
|
|
2448
2620
|
};
|
|
2449
2621
|
}
|
|
2622
|
+
/** Node's strip-only loader exposes an empty `default` export for a default
|
|
2623
|
+
* interface only when the `.ts` file is in an ambiguous (typeless) package
|
|
2624
|
+
* scope. Explicitly ESM files (`.mts` and `.mjs`) and `.ts` files in a
|
|
2625
|
+
* `"type": "module"` package do not get that placeholder. */
|
|
2626
|
+
function hasNodeTsDefaultInterfacePlaceholder7(sf) {
|
|
2627
|
+
return sf.fileName.endsWith(".ts") && nearestPackageType(sf.fileName) === null;
|
|
2628
|
+
}
|
|
2629
|
+
/** Finds the first native-ESM link failure in the static module graph rooted
|
|
2630
|
+
* at `entry`. This is used both for startup linking of the entry graph and
|
|
2631
|
+
* for dynamic imports: a dynamically loaded graph rejects its import promise
|
|
2632
|
+
* at this same link point instead of running any module body. */
|
|
2633
|
+
function analyzeEsmNamedImportLinks(program, entry) {
|
|
2634
|
+
const checker = program.getTypeChecker();
|
|
2635
|
+
const resolveEdge = (from, spec) => {
|
|
2636
|
+
const project = resolveImport7(program, from, spec);
|
|
2637
|
+
if (project !== null)
|
|
2638
|
+
return project;
|
|
2639
|
+
return npmStaticDepSf7(program, from, spec);
|
|
2640
|
+
};
|
|
2641
|
+
const runtimeExport = (dep, name, seenModules = new Set()) => {
|
|
2642
|
+
if (seenModules.has(dep))
|
|
2643
|
+
return undefined;
|
|
2644
|
+
const nextSeen = new Set(seenModules);
|
|
2645
|
+
nextSeen.add(dep);
|
|
2646
|
+
const module = checker.getSymbolAtLocation(dep);
|
|
2647
|
+
const exported = module?.getExports().get(name);
|
|
2648
|
+
if (exported !== undefined) {
|
|
2649
|
+
let resolved = exported;
|
|
2650
|
+
const seenSymbols = new Set();
|
|
2651
|
+
while ((resolved.flags & ts.SymbolFlags.Alias) !== 0 && !seenSymbols.has(resolved)) {
|
|
2652
|
+
seenSymbols.add(resolved);
|
|
2653
|
+
resolved = checker.getAliasedSymbol(resolved);
|
|
2654
|
+
}
|
|
2655
|
+
if (resolved.flags & ts.SymbolFlags.Value)
|
|
2656
|
+
return resolved;
|
|
2657
|
+
// Node's strip-only TypeScript loader materializes a direct `export
|
|
2658
|
+
// default interface X {}` as an empty default export in an ambiguous
|
|
2659
|
+
// `.ts` file. The checker correctly classifies the declaration as
|
|
2660
|
+
// type-only, but the native ESM linker sees the runtime placeholder.
|
|
2661
|
+
if (name === "default" &&
|
|
2662
|
+
hasNodeTsDefaultInterfacePlaceholder7(dep) &&
|
|
2663
|
+
checker.declarationsOf(resolved).some((declaration) => ts.isInterfaceDeclaration(declaration) &&
|
|
2664
|
+
ts.getModifiers(declaration)?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword) === true &&
|
|
2665
|
+
ts.getModifiers(declaration)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) === true)) {
|
|
2666
|
+
return resolved;
|
|
2667
|
+
}
|
|
2668
|
+
return undefined;
|
|
2669
|
+
}
|
|
2670
|
+
// TypeScript 7's client-side module symbol exposes the module's own
|
|
2671
|
+
// export table but not names contributed by `export *`. Follow those
|
|
2672
|
+
// source edges explicitly, applying the ESM ambiguity rule: the same
|
|
2673
|
+
// resolved symbol may arrive through multiple stars, while distinct
|
|
2674
|
+
// symbols make the name unavailable. `default` never star-reexports.
|
|
2675
|
+
if (name === "default")
|
|
2676
|
+
return undefined;
|
|
2677
|
+
let starExport;
|
|
2678
|
+
for (const stmt of dep.statements) {
|
|
2679
|
+
if (!ts.isExportDeclaration(stmt) || stmt.isTypeOnly || stmt.exportClause !== undefined)
|
|
2680
|
+
continue;
|
|
2681
|
+
if (stmt.moduleSpecifier === undefined || !ts.isStringLiteral(stmt.moduleSpecifier))
|
|
2682
|
+
continue;
|
|
2683
|
+
const target = resolveEdge(dep, stmt.moduleSpecifier.text);
|
|
2684
|
+
if (target === null || target.fileName.endsWith(".json") || !isNodeEsmFile7(target))
|
|
2685
|
+
continue;
|
|
2686
|
+
const candidate = runtimeExport(target, name, nextSeen);
|
|
2687
|
+
if (candidate === undefined)
|
|
2688
|
+
continue;
|
|
2689
|
+
if (starExport !== undefined && starExport !== candidate)
|
|
2690
|
+
return undefined;
|
|
2691
|
+
starExport = candidate;
|
|
2692
|
+
}
|
|
2693
|
+
return starExport;
|
|
2694
|
+
};
|
|
2695
|
+
const firstMissingOf = (sf) => {
|
|
2696
|
+
const imports = [];
|
|
2697
|
+
for (const stmt of sf.statements) {
|
|
2698
|
+
if (!ts.isImportDeclaration(stmt) || !ts.isStringLiteral(stmt.moduleSpecifier))
|
|
2699
|
+
continue;
|
|
2700
|
+
const clause = stmt.importClause;
|
|
2701
|
+
if (clause === undefined || clause.phaseModifier === ts.SyntaxKind.TypeKeyword)
|
|
2702
|
+
continue;
|
|
2703
|
+
const spec = stmt.moduleSpecifier.text;
|
|
2704
|
+
const dep = resolveEdge(sf, spec);
|
|
2705
|
+
if (dep === null || dep.fileName.endsWith(".json") || !isNodeEsmFile7(dep))
|
|
2706
|
+
continue;
|
|
2707
|
+
if (clause.name !== undefined) {
|
|
2708
|
+
imports.push({ local: clause.name.text, exportName: "default", spec, nameNode: clause.name, dep });
|
|
2709
|
+
}
|
|
2710
|
+
if (clause.namedBindings === undefined || !ts.isNamedImports(clause.namedBindings))
|
|
2711
|
+
continue;
|
|
2712
|
+
for (const element of clause.namedBindings.elements) {
|
|
2713
|
+
if (element.isTypeOnly)
|
|
2714
|
+
continue;
|
|
2715
|
+
const nameNode = element.propertyName ?? element.name;
|
|
2716
|
+
imports.push({
|
|
2717
|
+
local: element.name.text,
|
|
2718
|
+
exportName: nameNode.text,
|
|
2719
|
+
spec,
|
|
2720
|
+
nameNode,
|
|
2721
|
+
dep,
|
|
2722
|
+
});
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
// Node checks regular named requests in local-binding order. Keeping the
|
|
2726
|
+
// same order as the CommonJS linker matters when one statement asks for
|
|
2727
|
+
// more than one erased TypeScript export.
|
|
2728
|
+
imports.sort((a, b) => (a.local < b.local ? -1 : a.local > b.local ? 1 : 0));
|
|
2729
|
+
for (const request of imports) {
|
|
2730
|
+
if (runtimeExport(request.dep, request.exportName) === undefined) {
|
|
2731
|
+
return {
|
|
2732
|
+
exportName: request.exportName,
|
|
2733
|
+
spec: request.spec,
|
|
2734
|
+
nameNode: request.nameNode,
|
|
2735
|
+
sf,
|
|
2736
|
+
};
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
for (const stmt of sf.statements) {
|
|
2740
|
+
if (!ts.isExportDeclaration(stmt) || stmt.isTypeOnly)
|
|
2741
|
+
continue;
|
|
2742
|
+
const moduleSpecifier = stmt.moduleSpecifier;
|
|
2743
|
+
const exportClause = stmt.exportClause;
|
|
2744
|
+
if (moduleSpecifier === undefined || exportClause === undefined)
|
|
2745
|
+
continue;
|
|
2746
|
+
if (!ts.isStringLiteral(moduleSpecifier) || !ts.isNamedExports(exportClause))
|
|
2747
|
+
continue;
|
|
2748
|
+
const spec = moduleSpecifier.text;
|
|
2749
|
+
const dep = resolveEdge(sf, spec);
|
|
2750
|
+
if (dep === null || dep.fileName.endsWith(".json") || !isNodeEsmFile7(dep))
|
|
2751
|
+
continue;
|
|
2752
|
+
for (const element of exportClause.elements) {
|
|
2753
|
+
if (element.isTypeOnly)
|
|
2754
|
+
continue;
|
|
2755
|
+
const nameNode = element.propertyName ?? element.name;
|
|
2756
|
+
if (runtimeExport(dep, nameNode.text) === undefined) {
|
|
2757
|
+
return { exportName: nameNode.text, spec, nameNode, sf };
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
return null;
|
|
2762
|
+
};
|
|
2763
|
+
// The ESM instantiate graph is the same depth-first graph used by the CJS
|
|
2764
|
+
// linker: dependencies are linked before the importing module, and a
|
|
2765
|
+
// CommonJS/JSON target is a leaf for this native-export check.
|
|
2766
|
+
const visited = new Set();
|
|
2767
|
+
const dfs = (sf) => {
|
|
2768
|
+
if (visited.has(sf))
|
|
2769
|
+
return null;
|
|
2770
|
+
visited.add(sf);
|
|
2771
|
+
for (const stmt of sf.statements) {
|
|
2772
|
+
if (!ts.isImportDeclaration(stmt) && !(ts.isExportDeclaration(stmt) && !stmt.isTypeOnly))
|
|
2773
|
+
continue;
|
|
2774
|
+
if (ts.isImportDeclaration(stmt) && stmt.importClause?.phaseModifier === ts.SyntaxKind.TypeKeyword)
|
|
2775
|
+
continue;
|
|
2776
|
+
const moduleSpecifier = stmt.moduleSpecifier;
|
|
2777
|
+
if (moduleSpecifier === undefined || !ts.isStringLiteral(moduleSpecifier))
|
|
2778
|
+
continue;
|
|
2779
|
+
const dep = resolveEdge(sf, moduleSpecifier.text);
|
|
2780
|
+
if (dep === null || dep.fileName.endsWith(".json") || !isNodeEsmFile7(dep))
|
|
2781
|
+
continue;
|
|
2782
|
+
const bad = dfs(dep);
|
|
2783
|
+
if (bad !== null)
|
|
2784
|
+
return bad;
|
|
2785
|
+
}
|
|
2786
|
+
return firstMissingOf(sf);
|
|
2787
|
+
};
|
|
2788
|
+
// Native ESM linking itself starts only from an ESM entry. The caller
|
|
2789
|
+
// supplies dynamic-only roots here too; each such root gets its own
|
|
2790
|
+
// promise rejection rather than a startup crash.
|
|
2791
|
+
const bad = isNodeEsmFile7(entry) ? dfs(entry) : null;
|
|
2792
|
+
if (bad !== null) {
|
|
2793
|
+
return {
|
|
2794
|
+
crash: {
|
|
2795
|
+
message: `The requested module '${bad.spec}' does not provide an export named '${bad.exportName}'`,
|
|
2796
|
+
className: "%SyntaxError",
|
|
2797
|
+
loc: locOf7(bad.nameNode),
|
|
2798
|
+
},
|
|
2799
|
+
visited,
|
|
2800
|
+
firstMissingOf,
|
|
2801
|
+
};
|
|
2802
|
+
}
|
|
2803
|
+
return { crash: null, visited, firstMissingOf };
|
|
2804
|
+
}
|
|
2805
|
+
export function esmNamedImportLinkCrash(program, entry) {
|
|
2806
|
+
return analyzeEsmNamedImportLinks(program, entry).crash;
|
|
2807
|
+
}
|
|
2808
|
+
function esmNamedImportLinkCheck(program, entry, moduleOrder, diags) {
|
|
2809
|
+
const analysis = analyzeEsmNamedImportLinks(program, entry);
|
|
2810
|
+
if (analysis.crash !== null)
|
|
2811
|
+
return analysis.crash;
|
|
2812
|
+
// A CommonJS entry can synchronously require an ESM graph. Node links that
|
|
2813
|
+
// graph at the require site, after the CommonJS module has already begun
|
|
2814
|
+
// evaluating, so this cannot use startupCrash (which would move the error
|
|
2815
|
+
// before earlier output). Keep the compile-time fence used by the CJS link
|
|
2816
|
+
// checker for the analogous mid-evaluation failure instead.
|
|
2817
|
+
for (const sf of moduleOrder) {
|
|
2818
|
+
if (!isNodeEsmFile7(sf) || analysis.visited.has(sf))
|
|
2819
|
+
continue;
|
|
2820
|
+
const childFailure = analysis.firstMissingOf(sf);
|
|
2821
|
+
if (childFailure !== null) {
|
|
2822
|
+
diags.push(unsupportedDiag("SC1013", locOf7(childFailure.nameNode), "a named import of an unavailable export in an ES module reached through require() (Node throws its SyntaxError mid-evaluation at that require; make the import match the module's runtime exports)"));
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
return null;
|
|
2826
|
+
}
|
|
2827
|
+
/** Both named-export link checks run independently because their export
|
|
2828
|
+
* questions are different (Node's CJS lexer versus TypeScript's value
|
|
2829
|
+
* symbols). Their first failures still share one Node instantiate order: the
|
|
2830
|
+
* module postorder established by preflight, then regular named imports by
|
|
2831
|
+
* local binding name, then source-order re-exports. Pick the earlier result
|
|
2832
|
+
* so a native ESM failure in a child cannot be hidden by a CJS failure in a
|
|
2833
|
+
* later parent. */
|
|
2834
|
+
function earlierLinkCrash(moduleOrder, first, second) {
|
|
2835
|
+
if (first === null)
|
|
2836
|
+
return second;
|
|
2837
|
+
if (second === null)
|
|
2838
|
+
return first;
|
|
2839
|
+
const moduleIndex = new Map(moduleOrder.map((sf, index) => [sf.fileName, index]));
|
|
2840
|
+
const firstIndex = moduleIndex.get(first.loc.file) ?? Number.MAX_SAFE_INTEGER;
|
|
2841
|
+
const secondIndex = moduleIndex.get(second.loc.file) ?? Number.MAX_SAFE_INTEGER;
|
|
2842
|
+
if (firstIndex !== secondIndex)
|
|
2843
|
+
return firstIndex < secondIndex ? first : second;
|
|
2844
|
+
if (first.loc.start !== second.loc.start) {
|
|
2845
|
+
const sf = moduleOrder[firstIndex];
|
|
2846
|
+
if (sf === undefined)
|
|
2847
|
+
return first.loc.start < second.loc.start ? first : second;
|
|
2848
|
+
const rank = (crash) => {
|
|
2849
|
+
const entries = [];
|
|
2850
|
+
for (const stmt of sf.statements) {
|
|
2851
|
+
if (ts.isImportDeclaration(stmt) && ts.isStringLiteral(stmt.moduleSpecifier)) {
|
|
2852
|
+
const clause = stmt.importClause;
|
|
2853
|
+
if (clause?.phaseModifier === ts.SyntaxKind.TypeKeyword)
|
|
2854
|
+
continue;
|
|
2855
|
+
if (clause?.namedBindings && ts.isNamedImports(clause.namedBindings)) {
|
|
2856
|
+
for (const element of clause.namedBindings.elements) {
|
|
2857
|
+
if (!element.isTypeOnly) {
|
|
2858
|
+
entries.push({
|
|
2859
|
+
local: element.name.text,
|
|
2860
|
+
start: (element.propertyName ?? element.name).getStart(sf),
|
|
2861
|
+
kind: 0,
|
|
2862
|
+
});
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
entries.sort((a, b) => (a.local < b.local ? -1 : a.local > b.local ? 1 : 0));
|
|
2869
|
+
const direct = entries.findIndex((entry) => entry.start === crash.loc.start);
|
|
2870
|
+
if (direct >= 0)
|
|
2871
|
+
return [0, direct];
|
|
2872
|
+
let reexport = 0;
|
|
2873
|
+
for (const stmt of sf.statements) {
|
|
2874
|
+
const exportClause = ts.isExportDeclaration(stmt) ? stmt.exportClause : undefined;
|
|
2875
|
+
if (!ts.isExportDeclaration(stmt) || stmt.isTypeOnly || exportClause === undefined || !ts.isNamedExports(exportClause))
|
|
2876
|
+
continue;
|
|
2877
|
+
for (const element of exportClause.elements) {
|
|
2878
|
+
if (!element.isTypeOnly && (element.propertyName ?? element.name).getStart(sf) === crash.loc.start) {
|
|
2879
|
+
return [1, reexport];
|
|
2880
|
+
}
|
|
2881
|
+
if (!element.isTypeOnly)
|
|
2882
|
+
reexport++;
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
return [2, crash.loc.start];
|
|
2886
|
+
};
|
|
2887
|
+
const firstRank = rank(first);
|
|
2888
|
+
const secondRank = rank(second);
|
|
2889
|
+
if (firstRank[0] !== secondRank[0])
|
|
2890
|
+
return firstRank[0] < secondRank[0] ? first : second;
|
|
2891
|
+
return firstRank[1] <= secondRank[1] ? first : second;
|
|
2892
|
+
}
|
|
2893
|
+
return first;
|
|
2894
|
+
}
|
|
2450
2895
|
/* node's builtin-module name list, for the SC1010 wording decision ("the
|
|
2451
2896
|
* 'fs' module" vs the generic package message) — shared verbatim with the
|
|
2452
2897
|
* retired 5.9.3 lane's builtinModules use. */
|
|
@@ -2521,16 +2966,11 @@ export function orderedImportsOf(program, sf) {
|
|
|
2521
2966
|
if (!stmt.moduleSpecifier || !ts.isStringLiteral(stmt.moduleSpecifier))
|
|
2522
2967
|
continue;
|
|
2523
2968
|
const spec = stmt.moduleSpecifier.text;
|
|
2524
|
-
|
|
2525
|
-
//
|
|
2526
|
-
//
|
|
2527
|
-
// edges) resolve to the same dep so the importer's %init header calls
|
|
2528
|
-
// theirs. Builtin and npm bare specifiers stay null (resolveProjectImport
|
|
2529
|
-
// answers only inside the project) — EXCEPT opted-in --npm-static
|
|
2969
|
+
// Every project edge (relative, tsconfig alias, #alias, or self-name)
|
|
2970
|
+
// resolves to the same dep so the importer's %init header calls theirs.
|
|
2971
|
+
// Builtin and npm bare specifiers stay null — EXCEPT opted-in --npm-static
|
|
2530
2972
|
// packages, whose entries are program modules the header must init.
|
|
2531
|
-
const dep =
|
|
2532
|
-
? resolveImport7(program, sf, spec)
|
|
2533
|
-
: (npmStaticDepSf7(program, sf, spec) ?? resolveProjectImportSf7(program, sf, spec));
|
|
2973
|
+
const dep = resolveImport7(program, sf, spec) ?? npmStaticDepSf7(program, sf, spec);
|
|
2534
2974
|
const isJson = dep !== null && dep.fileName.endsWith(".json");
|
|
2535
2975
|
out.push({ stmt, dep: isJson ? null : dep });
|
|
2536
2976
|
}
|
|
@@ -2553,19 +2993,6 @@ export function npmStaticDepSf7(program, sf, spec) {
|
|
|
2553
2993
|
return null;
|
|
2554
2994
|
return program.getSourceFile(npm.typesFile) ?? null;
|
|
2555
2995
|
}
|
|
2556
|
-
/** resolveProjectImport lifted to SourceFile answers: the program's file
|
|
2557
|
-
* for a `#alias`/self-name resolution, or null (unresolved, or resolved
|
|
2558
|
-
* outside the program — declaration files included; callers that admit
|
|
2559
|
-
* d.ts answers probe resolveProjectImport directly). */
|
|
2560
|
-
function resolveProjectImportSf7(program, sf, spec) {
|
|
2561
|
-
if (spec.startsWith("node:"))
|
|
2562
|
-
return null;
|
|
2563
|
-
const p = resolveProjectImport(sf.fileName, spec);
|
|
2564
|
-
if (p === null)
|
|
2565
|
-
return null;
|
|
2566
|
-
const dep = program.getSourceFile(p) ?? null;
|
|
2567
|
-
return dep !== null && !dep.isDeclarationFile ? dep : null;
|
|
2568
|
-
}
|
|
2569
2996
|
/** True when `expr` is the `module.exports` property access. */
|
|
2570
2997
|
export function isModuleExportsAccess(expr) {
|
|
2571
2998
|
return (ts.isPropertyAccessExpression(expr) &&
|