Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/src/app/limitations/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ These are rejected at compile time with an `SC` code, a code frame, and usually
- Generics monomorphize when the target resolves statically. The remaining edges include generic functions declared inside another function, generic class expressions, generic classes whose base depends on their own type parameters, and generic methods that would require dynamic dispatch.
- Generic function values must be pinned at use to a concrete signature and come from a never-reassigned binding; unpinned or rebound values remain fenced. Immutable aliases of overloaded program functions retain per-call overload resolution and function identity. Typed rest-parameter functions are first-class values: indirect calls pack their surplus arguments into the function's typed array slot. Lowered `node:path` functions, including optional `basename` and variadic `join`/`resolve`, are first-class static values across the bare, POSIX, and win32 modules; the exact zero-argument `node:os` functions and `querystring.escape`/`unescape` are first-class too. The fixed-signature filesystem functions `existsSync`, `unlinkSync`, `chmodSync`, `chownSync`, `renameSync`, `closeSync`, and the `node:fs/promises` `unlink`, `chmod`, and `rename` functions are first-class as well. Filesystem APIs with behavior-bearing trailing arguments—including writers, open, directory creation/removal, metadata readers, and directory readers—remain call-only so function-width adaptation cannot discard modes, flags, encodings, or options. Other immutable aliases of table-backed Node builtins can be called directly, while escaping them remains fenced; `util.promisify` has compile-time projections for `child_process.execFile` and utf8 `fs.readFile`.
- Spread arguments compile when their arity is static: non-empty fixed tuples flatten into fixed signatures with left-to-right, evaluate-once semantics, while arrays, Sets, and statically represented class iterables spread into typed rest parameters. Runtime-length spreads into fixed signatures remain on the checked-dynamic or island paths in JavaScript and otherwise receive a compile-time diagnostic.
- Literal `import()` of compiled ESM/TypeScript modules and supported Node builtins compiles without the dynamic engine. Evaluation remains lazy and microtask-delayed, top-level `await` is honored, repeated imports share one namespace identity, exported mutable bindings stay live, and `Object.keys` on compiled-module namespaces uses Node's sorted key order. Computed specifiers, import attributes, CommonJS namespace synthesis, and shipped-JavaScript package imports remain explicitly fenced or require `--dynamic`.

**Types and shapes**

Expand Down
30 changes: 24 additions & 6 deletions internal/compatibility/generated/node-v24-backlog.json
Original file line number Diff line number Diff line change
Expand Up @@ -60628,7 +60628,10 @@
"source": "compiler-feature:esm.import",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -60667,7 +60670,10 @@
"source": "compiler-feature:esm.file:",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -60739,7 +60745,10 @@
"source": "compiler-feature:esm.node:",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -60778,7 +60787,10 @@
"source": "compiler-feature:esm.import",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -60817,7 +60829,10 @@
"source": "compiler-feature:esm.import",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -61120,7 +61135,10 @@
"source": "compiler-feature:esm.await",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down
33 changes: 27 additions & 6 deletions internal/compatibility/generated/node-v24-internal.json
Original file line number Diff line number Diff line change
Expand Up @@ -75230,6 +75230,9 @@
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2701-import-meta/main.mjs",
"tests/corpus/2858-import-meta-resolve/main.mjs",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts",
"tests/corpus/950-modules-basic/main.ts"
]
},
Expand Down Expand Up @@ -75531,7 +75534,10 @@
"evidence": "compiler-feature:esm.import",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -75647,7 +75653,10 @@
"evidence": "compiler-feature:esm.file:",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -75709,7 +75718,10 @@
"evidence": "compiler-feature:esm.node:",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -75798,7 +75810,10 @@
"evidence": "compiler-feature:esm.import",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -75860,7 +75875,10 @@
"evidence": "compiler-feature:esm.import",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down Expand Up @@ -76354,7 +76372,10 @@
"evidence": "compiler-feature:esm.await",
"tests": [
"tests/corpus/950-modules-basic/main.ts",
"tests/corpus/2646-top-level-await.ts"
"tests/corpus/2646-top-level-await.ts",
"tests/corpus/2933-static-dynamic-import/main.ts",
"tests/corpus/2934-static-import-stored.ts",
"tests/corpus/2935-module-namespace-values/main.ts"
]
},
"dynamic": {
Expand Down
2 changes: 1 addition & 1 deletion internal/compatibility/static-support.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
{ "chapter": "module", "symbols": ["module.isBuiltin", "module.syncBuiltinESMExports"], "status": "partial", "evidence": ["tests/corpus/2932-create-require-program/main.ts"] },
{ "chapter": "module", "symbols": ["builtinModules"], "status": "partial", "evidence": ["tests/corpus/2631-create-require/main.ts", "tests/corpus/2637-create-require-bare/main.ts", "tests/corpus/2932-create-require-program/main.ts"] },
{ "chapter": "modules", "symbols": ["node:", "node_modules"], "status": "partial", "evidence": ["tests/corpus/1598-cjs-builtin-require/main.js", "tests/corpus/1596-cjs-modules/main.js"] },
{ "chapter": "esm", "symbols": ["import", "file:", "node:", "await"], "status": "partial", "evidence": ["tests/corpus/950-modules-basic/main.ts", "tests/corpus/2646-top-level-await.ts"] },
{ "chapter": "esm", "symbols": ["import", "file:", "node:", "await"], "status": "partial", "evidence": ["tests/corpus/950-modules-basic/main.ts", "tests/corpus/2646-top-level-await.ts", "tests/corpus/2933-static-dynamic-import/main.ts", "tests/corpus/2934-static-import-stored.ts", "tests/corpus/2935-module-namespace-values/main.ts"] },
{ "chapter": "esm", "symbols": ["url", "dirname", "filename", "main"], "status": "partial", "evidence": ["tests/corpus/2701-import-meta/main.mjs"] },
{ "chapter": "esm", "symbols": ["import.meta.resolve"], "status": "partial", "evidence": ["tests/corpus/2858-import-meta-resolve/main.mjs"] },
{ "chapter": "esm", "symbols": ["meta", "data:", "require", "__filename", "require.main", "require.resolve", "NODE_PATH", "require.extensions", "require.cache"], "status": "not-implemented" },
Expand Down
7 changes: 6 additions & 1 deletion packages/compiler/src/backend/c/exprs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ type ExprOf<K extends IrExpr["kind"]> = Extract<IrExpr, { kind: K }>;

function emitLiteralExpr(
emitter: CEmitter,
e: ExprOf<"numLit" | "boolLit" | "strLit" | "unitLit" | "varRef">,
e: ExprOf<"numLit" | "boolLit" | "strLit" | "moduleNsRef" | "unitLit" | "varRef">,
): Temp {
switch (e.kind) {
case "numLit":
Expand All @@ -780,6 +780,10 @@ function emitLiteralExpr(
const sym = emitter.internLiteral(e.value);
return emitter.newTemp(e.type, retainCallC(e.type, `(ScrStr *)&${sym}`));
}
case "moduleNsRef": {
const sym = emitter.internLiteral(`module:${e.moduleId}`);
return emitter.newTemp(e.type, retainCallC(e.type, `(ScrStr *)&${sym}`));
}
case "unitLit":
// unitLits are consumed inline by the unionWrap case (a unit arm is
// tag-only); one reaching the generic dispatch escaped its wrap.
Expand Down Expand Up @@ -8638,6 +8642,7 @@ export function emitExpr(emitter: CEmitter, e: IrExpr): Temp {
case "numLit":
case "boolLit":
case "strLit":
case "moduleNsRef":
case "unitLit":
case "varRef":
return emitLiteralExpr(emitter, e);
Expand Down
2 changes: 2 additions & 0 deletions packages/compiler/src/backend/c/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export function cType(t: IrType): string {
return "bool";
case "string":
return "ScrStr *";
case "moduleNs":
return "ScrStr *";
case "bigint":
return "ScrBigInt *";
case "array":
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/src/backend/llvm/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4058,7 +4058,7 @@ class LlEmitter {
return this as unknown as LlvmEmitterContext;
}

private emitLiteralExpr(e: ExprOf<"numLit" | "boolLit" | "strLit" | "unitLit" | "varRef">): LlValue {
private emitLiteralExpr(e: ExprOf<"numLit" | "boolLit" | "strLit" | "moduleNsRef" | "unitLit" | "varRef">): LlValue {
return emitLiteralExpr(this.expressionContext(), e);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/src/backend/llvm/expr-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export interface LlvmEmitterContext extends ShapeHost {
emitJsMarshal(e: IrExpr & { kind: "jsMarshal" }): LlValue;
emitJsOp(e: IrExpr & { kind: "jsOp" }): LlValue;
emitLibCall(e: LibCallExpr): LlValue;
emitLiteralExpr(e: ExprOf<"numLit" | "boolLit" | "strLit" | "unitLit" | "varRef">): LlValue;
emitLiteralExpr(e: ExprOf<"numLit" | "boolLit" | "strLit" | "moduleNsRef" | "unitLit" | "varRef">): LlValue;
emitMapLikeIntrinsic(e: Extract<IrExpr, { kind: "mapIntrinsic" | "setIntrinsic" }>): LlValue;
emitMapNew(e: IrExpr & { kind: "mapNew" }): LlValue;
emitNetworkHttpLibCall(e: LibCallExpr): LlValue;
Expand Down
1 change: 1 addition & 0 deletions packages/compiler/src/backend/llvm/expr-dispatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export function emitExpr(host: LlvmEmitterContext, e: IrExpr): LlValue {
case "numLit":
case "boolLit":
case "strLit":
case "moduleNsRef":
case "unitLit":
case "varRef":
return host.emitLiteralExpr(e);
Expand Down
6 changes: 5 additions & 1 deletion packages/compiler/src/backend/llvm/expr-primitives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const BYTES_ELEM_NUM: Record<"u8" | "u32" | "f32" | "i32", number> = {
};
import { f64Lit } from "./common.js";

export function emitLiteralExpr(host: LlvmEmitterContext, e: ExprOf<"numLit" | "boolLit" | "strLit" | "unitLit" | "varRef">): LlValue {
export function emitLiteralExpr(host: LlvmEmitterContext, e: ExprOf<"numLit" | "boolLit" | "strLit" | "moduleNsRef" | "unitLit" | "varRef">): LlValue {
const B = host.B;
switch (e.kind) {
case "numLit":
Expand All @@ -27,6 +27,10 @@ export function emitLiteralExpr(host: LlvmEmitterContext, e: ExprOf<"numLit" | "
const sym = host.internLiteral(e.value);
return host.own({ name: host.retainValue(sym, e.type), type: e.type });
}
case "moduleNsRef": {
const sym = host.internLiteral(`module:${e.moduleId}`);
return host.own({ name: host.retainValue(sym, e.type), type: e.type });
}
case "unitLit":
// unitLits are consumed inline by the unionWrap case (a unit arm is
// tag-only); one reaching the generic dispatch escaped its wrap.
Expand Down
Loading
Loading