mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-26 06:34:20 +08:00
Skip split require calls by identity and climb parentheses in early-read checks
This commit is contained in:
@@ -1563,6 +1563,14 @@ function splitRequireOfStatement7(
|
||||
return null;
|
||||
}
|
||||
|
||||
/** The top-level statement of a split require binding's assignment, from
|
||||
* its require call (`m = require("./x")` or `m = (require("./x"))`). */
|
||||
function splitRequireStatementOf7(call: ts.CallExpression): ts.Node | undefined {
|
||||
let node: ts.Node = call;
|
||||
while (node.parent !== undefined && ts.isParenthesizedExpression(node.parent)) node = node.parent;
|
||||
return node.parent?.parent;
|
||||
}
|
||||
|
||||
/** The require call of a split require binding's declaration, or null. */
|
||||
function splitRequireCallOf7(
|
||||
program: ts.Program,
|
||||
@@ -1877,7 +1885,7 @@ function requireEarlyReference7(
|
||||
const sf = ts.getSourceFileOfNode(decl);
|
||||
// A split require binding is bound at its assignment statement.
|
||||
const splitCall = splitRequireCallOf7(program, decl);
|
||||
const stmt = splitCall !== null ? splitCall.parent?.parent : decl.parent?.parent;
|
||||
const stmt = splitCall !== null ? splitRequireStatementOf7(splitCall) : decl.parent?.parent;
|
||||
if (
|
||||
stmt !== undefined &&
|
||||
(ts.isVariableStatement(stmt) || splitCall !== null) &&
|
||||
@@ -6184,15 +6192,12 @@ function preflight7(load: LoadResult): {
|
||||
// counts, and targets outside the compiled graph add nothing here:
|
||||
// their use sites keep their existing lowering fences.
|
||||
if (jsRequireFile && !isNodeEsmFile7(sf, program)) {
|
||||
// A split require binding's assignment is a statement-level require
|
||||
// edge (requiresOf7 above), parenthesized or not.
|
||||
const splitCalls = new Set(splitRequireBindings7(program, sf).values());
|
||||
for (const call of inlineRequiresOf7(sf)) {
|
||||
if (requireCallBindingKind7(program, call) !== "ambient") continue;
|
||||
// A split require binding's assignment is a statement-level
|
||||
// require edge (requiresOf7 above).
|
||||
if (
|
||||
call.parent?.parent !== undefined &&
|
||||
splitRequireOfStatement7(program, call.parent.parent as ts.Statement) !== null
|
||||
)
|
||||
continue;
|
||||
if (splitCalls.has(call)) continue;
|
||||
const spec = requireSpecOf7(call)!;
|
||||
if (load.externalTypes.has(spec) || canonicalBuiltinModule(spec) !== null) continue;
|
||||
const lazy = inDeferredPosition7(call);
|
||||
|
||||
+10
@@ -12,6 +12,16 @@
|
||||
"end": 415
|
||||
},
|
||||
"milestone": "later"
|
||||
},
|
||||
{
|
||||
"code": "SC1013",
|
||||
"message": "require() binding 'wrapped' assigned below code that can reach it (Node reads undefined before the assignment runs, which is not modeled — move the assignment above the code that can run first) is not supported yet",
|
||||
"loc": {
|
||||
"file": "<repo>/tests/diagnostics/split-cjs-require-early/main.js",
|
||||
"start": 530,
|
||||
"end": 549
|
||||
},
|
||||
"milestone": "later"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Split require bindings (`var m; m = require("./x.cjs")`) that close a
|
||||
// CommonJS cycle: each module publishes its exports before its require, and
|
||||
// reads the other module's binding only in functions that run after both
|
||||
// modules finish, the cycle shape the const form compiles too.
|
||||
// modules finish, the cycle shape the const form compiles too. One
|
||||
// assignment parenthesizes its require.
|
||||
console.log("main: start");
|
||||
var even, odd;
|
||||
even = require("./even.cjs");
|
||||
|
||||
@@ -8,5 +8,5 @@ exports.isOdd = function (n) {
|
||||
exports.calls = function () {
|
||||
return calls;
|
||||
};
|
||||
even = require("./even.cjs");
|
||||
even = (require("./even.cjs"));
|
||||
console.log("odd: loaded");
|
||||
|
||||
@@ -9,6 +9,11 @@ let lib;
|
||||
console.log('boot', helper());
|
||||
lib = require('./lib.js');
|
||||
|
||||
// The same with the require parenthesized.
|
||||
let wrapped;
|
||||
console.log('peek', wrapped === undefined);
|
||||
wrapped = (require('./lib.js'));
|
||||
|
||||
function helper() {
|
||||
return lib === undefined ? 'not loaded' : lib.greet('late');
|
||||
}
|
||||
|
||||
@@ -3,4 +3,11 @@ split-cjs-require-early/main.js:10:7 - error SC1013: require() binding 'lib' ass
|
||||
9 | console.log('boot', helper());
|
||||
10 | lib = require('./lib.js');
|
||||
| ^~~~~~~~~~~~~~~~~~~
|
||||
11 |
|
||||
11 |
|
||||
|
||||
split-cjs-require-early/main.js:15:12 - error SC1013: require() binding 'wrapped' assigned below code that can reach it (Node reads undefined before the assignment runs, which is not modeled — move the assignment above the code that can run first) is not supported yet
|
||||
|
||||
14 | console.log('peek', wrapped === undefined);
|
||||
15 | wrapped = (require('./lib.js'));
|
||||
| ^~~~~~~~~~~~~~~~~~~
|
||||
16 |
|
||||
Reference in New Issue
Block a user