mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-28 06:53:42 +08:00
Merge branch 'opt/npm-polyfill-shims' into opt/npm-esm-class-hoist
Renumbers this branch's npm case 2572 to 2588, after the renumbered polyfill cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -111,6 +111,98 @@ console.log(require_named().name);
|
||||
expect(chunk).toContain("var __defProp = Object.defineProperty;");
|
||||
});
|
||||
|
||||
test("a helper travels with a chunk whose nested scopes declare its name", () => {
|
||||
const answer = expectSameBehavior(`${keyedHelper}function label(n) {
|
||||
return "label " + n;
|
||||
}
|
||||
function wrap(n) {
|
||||
function inner() {
|
||||
var label = "inner";
|
||||
return label;
|
||||
}
|
||||
return label(n) + " " + inner();
|
||||
}
|
||||
var require_e = __commonJS({
|
||||
"e.js"(exports2, module2) {
|
||||
function nested() {
|
||||
var label = "nested";
|
||||
return label;
|
||||
}
|
||||
var seen = [];
|
||||
for (let label of ["loop"]) seen.push(label);
|
||||
try {
|
||||
throw "caught";
|
||||
} catch (label) {
|
||||
seen.push(label);
|
||||
}
|
||||
{
|
||||
const label = "block";
|
||||
seen.push(label);
|
||||
}
|
||||
module2.exports = { outer: label(1), indirect: (0, label)(3), wrapped: wrap(2), nested: nested(), seen };
|
||||
}
|
||||
});
|
||||
var e = require_e();
|
||||
console.log(e.outer, e.indirect, e.wrapped, e.nested, e.seen.join(","));
|
||||
`);
|
||||
const chunk = answer.chunks[0]!.source;
|
||||
expect(chunk).toContain("function label(n)");
|
||||
expect(chunk).toContain("function wrap(n)");
|
||||
});
|
||||
|
||||
test("a named function expression that only calls itself travels with a chunk", () => {
|
||||
const answer = expectSameBehavior(`${keyedHelper}var fact = function self(n) {
|
||||
return n <= 1 ? 1 : n * self(n - 1);
|
||||
};
|
||||
var kind = function self(self) {
|
||||
return typeof self;
|
||||
};
|
||||
var outer = function self() {
|
||||
var self = 2;
|
||||
return self;
|
||||
};
|
||||
var require_g = __commonJS({
|
||||
"g.js"(exports2, module2) {
|
||||
module2.exports = [fact(5), kind(1), outer()];
|
||||
}
|
||||
});
|
||||
console.log(require_g().join(","));
|
||||
`);
|
||||
const chunk = answer.chunks[0]!.source;
|
||||
expect(chunk).toContain("var fact = function self(n)");
|
||||
});
|
||||
|
||||
test.each([
|
||||
["exports it", `function tally() {}`, `module2.exports = { tally };`],
|
||||
["reads its properties", `function tally() {}`, `exports2.calls = tally.calls;`],
|
||||
["constructs it", `function tally() {}`, `exports2.made = new tally();`],
|
||||
["stores an arrow helper", `var tally = () => 1;`, `exports2.fn = tally;`],
|
||||
[
|
||||
"calls a function that reads its own name as a value",
|
||||
`var tally = function self() { self.n = (self.n || 0) + 1; return self.n; };`,
|
||||
`exports2.count = tally();`,
|
||||
],
|
||||
[
|
||||
"calls a function whose parameter default reads its own name",
|
||||
`var tally = function self(box = self) { box.n = (box.n || 0) + 1; return box.n; };`,
|
||||
`exports2.count = tally();`,
|
||||
],
|
||||
])("a chunk that %s keeps the package refused", (_, declaration, statement) => {
|
||||
const result = split(`${keyedHelper}${declaration}
|
||||
var require_f = __commonJS({
|
||||
"f.js"(exports2, module2) {
|
||||
${statement}
|
||||
}
|
||||
});
|
||||
require_f();
|
||||
`);
|
||||
expect(result).toEqual({
|
||||
degrade: expect.stringContaining(
|
||||
"uses the bundle's top-level function 'tally' as a value",
|
||||
) as string,
|
||||
});
|
||||
});
|
||||
|
||||
test.each([
|
||||
["reads its factory's receiver", `console.log(this);`],
|
||||
["reads its factory's arguments object", `console.log(arguments.length);`],
|
||||
|
||||
@@ -111,6 +111,128 @@ export function declaredNames(root: ts.Node): Set<string> {
|
||||
return names;
|
||||
}
|
||||
|
||||
/** Adds the identifiers a binding name (an identifier or a destructuring
|
||||
* pattern) declares. */
|
||||
function addBindingNames(name: ts.BindingName, out: Set<string>): void {
|
||||
if (ts.isIdentifier(name)) {
|
||||
out.add(name.text);
|
||||
return;
|
||||
}
|
||||
for (const element of name.elements.nodes) {
|
||||
if (!ts.isOmittedExpression(element) && element.name !== undefined)
|
||||
addBindingNames(element.name, out);
|
||||
}
|
||||
}
|
||||
|
||||
function isFunctionScope(n: ts.Node): n is ts.SignatureDeclaration {
|
||||
return (
|
||||
ts.isFunctionDeclaration(n) ||
|
||||
ts.isFunctionExpression(n) ||
|
||||
ts.isArrowFunction(n) ||
|
||||
ts.isMethodDeclaration(n) ||
|
||||
ts.isGetAccessorDeclaration(n) ||
|
||||
ts.isSetAccessorDeclaration(n) ||
|
||||
ts.isConstructorDeclaration(n)
|
||||
);
|
||||
}
|
||||
|
||||
/** The `var` names a function body declares, without entering nested
|
||||
* functions. Function declarations in nested blocks count as block-scoped
|
||||
* here; treating one as free only adds an unused helper copy. */
|
||||
function varScopedNames(body: ts.Node): Set<string> {
|
||||
const out = new Set<string>();
|
||||
ts.walkPreorder(body, (n) => {
|
||||
if (n !== body && (isFunctionScope(n) || ts.isClassDeclaration(n) || ts.isClassExpression(n)))
|
||||
return "skip";
|
||||
if (ts.isVariableDeclarationList(n) && (n.flags & ts.NodeFlags.BlockScoped) === 0) {
|
||||
for (const d of n.declarations.nodes) addBindingNames(d.name, out);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
/** The names one scope node binds for the references inside it. */
|
||||
function scopeNames(scope: ts.Node): Set<string> {
|
||||
const out = new Set<string>();
|
||||
if (isFunctionScope(scope)) {
|
||||
for (const param of scope.parameters.nodes) addBindingNames(param.name, out);
|
||||
if (ts.isFunctionExpression(scope) && scope.name !== undefined) out.add(scope.name.text);
|
||||
if (scope.body !== undefined) for (const name of varScopedNames(scope.body)) out.add(name);
|
||||
} else if (ts.isBlock(scope) || ts.isSourceFile(scope) || ts.isCaseBlock(scope)) {
|
||||
const statements = ts.isCaseBlock(scope)
|
||||
? scope.clauses.nodes.flatMap((clause) => clause.statements.nodes)
|
||||
: scope.statements.nodes;
|
||||
for (const stmt of statements) {
|
||||
if ((ts.isFunctionDeclaration(stmt) || ts.isClassDeclaration(stmt)) && stmt.name)
|
||||
out.add(stmt.name.text);
|
||||
else if (
|
||||
ts.isVariableStatement(stmt) &&
|
||||
(stmt.declarationList.flags & ts.NodeFlags.BlockScoped) !== 0
|
||||
) {
|
||||
for (const d of stmt.declarationList.declarations.nodes) addBindingNames(d.name, out);
|
||||
}
|
||||
}
|
||||
} else if (ts.isCatchClause(scope) && scope.variableDeclaration !== undefined) {
|
||||
addBindingNames(scope.variableDeclaration.name, out);
|
||||
} else if (
|
||||
(ts.isForStatement(scope) || ts.isForInStatement(scope) || ts.isForOfStatement(scope)) &&
|
||||
scope.initializer !== undefined &&
|
||||
ts.isVariableDeclarationList(scope.initializer) &&
|
||||
(scope.initializer.flags & ts.NodeFlags.BlockScoped) !== 0
|
||||
) {
|
||||
for (const d of scope.initializer.declarations.nodes) addBindingNames(d.name, out);
|
||||
} else if (
|
||||
(ts.isClassDeclaration(scope) || ts.isClassExpression(scope)) &&
|
||||
scope.name !== undefined
|
||||
) {
|
||||
out.add(scope.name.text);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Resolves references against one bundle's scopes, keeping each scope's
|
||||
* names for the bundle's split. */
|
||||
class BundleScopes {
|
||||
private readonly names = new Map<ts.Node, Set<string>>();
|
||||
|
||||
private of(scope: ts.Node): Set<string> {
|
||||
let names = this.names.get(scope);
|
||||
if (names === undefined) {
|
||||
names = scopeNames(scope);
|
||||
this.names.set(scope, names);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
/** True when a scope between the reference and `root` (inclusive)
|
||||
* binds its name. */
|
||||
boundWithin(id: ts.Identifier, root: ts.Node): boolean {
|
||||
for (let n = id.parent; n !== undefined; n = n.parent) {
|
||||
if (this.of(n).has(id.text)) return true;
|
||||
if (n === root) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** True when a scope inside `root` (exclusive) binds the reference's
|
||||
* name. */
|
||||
boundInside(id: ts.Identifier, root: ts.Node): boolean {
|
||||
for (let n = id.parent; n !== undefined && n !== root; n = n.parent) {
|
||||
if (this.of(n).has(id.text)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** True when the reference resolves to a top-level binding of `sf`. */
|
||||
topLevel(id: ts.Identifier, sf: ts.SourceFile): boolean {
|
||||
for (let n = id.parent; n !== undefined && n !== sf; n = n.parent) {
|
||||
if (this.of(n).has(id.text)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/** Every binding reference inside a subtree. */
|
||||
export function references(root: ts.Node): ts.Identifier[] {
|
||||
const out: ts.Identifier[] = [];
|
||||
@@ -236,6 +358,52 @@ function copyableInitializer(init: ts.Expression | undefined): boolean {
|
||||
return depth > 0 && ts.isIdentifier(walk) && walk.text === "Object";
|
||||
}
|
||||
|
||||
/** A top-level declaration whose value is a function. */
|
||||
function isFunctionValued(node: ts.VariableDeclaration | ts.FunctionDeclaration): boolean {
|
||||
if (ts.isFunctionDeclaration(node)) return true;
|
||||
const init = node.initializer && unparen(node.initializer);
|
||||
return init !== undefined && (ts.isArrowFunction(init) || ts.isFunctionExpression(init));
|
||||
}
|
||||
|
||||
/** True when a named function expression initializer (`var f = function
|
||||
* self() {}`) uses its own name only as a callee: `self` is the copied
|
||||
* function, so it is as observable as the top-level binding. */
|
||||
function selfCalledOnly(
|
||||
node: ts.VariableDeclaration | ts.FunctionDeclaration,
|
||||
scopes: BundleScopes,
|
||||
): boolean {
|
||||
if (!ts.isVariableDeclaration(node) || node.initializer === undefined) return true;
|
||||
const fn = unparen(node.initializer);
|
||||
if (!ts.isFunctionExpression(fn) || fn.name === undefined || fn.body === undefined) return true;
|
||||
const self = fn.name.text;
|
||||
// A parameter or `var` of the same name hides the function's own name.
|
||||
const own = varScopedNames(fn.body);
|
||||
for (const param of fn.parameters.nodes) addBindingNames(param.name, own);
|
||||
if (own.has(self)) return true;
|
||||
// Its parameter initializers see the name too.
|
||||
return references(fn).every((r) => r.text !== self || scopes.boundInside(r, fn) || isCallee(r));
|
||||
}
|
||||
|
||||
/** True when a reference is the function a call invokes: `f(...)`, or the
|
||||
* `(0, f)(...)` form that drops the receiver. */
|
||||
function isCallee(id: ts.Identifier): boolean {
|
||||
let callee: ts.Node = id;
|
||||
const p = id.parent;
|
||||
if (
|
||||
p !== undefined &&
|
||||
ts.isBinaryExpression(p) &&
|
||||
p.operatorToken.kind === ts.SyntaxKind.CommaToken &&
|
||||
p.right === id &&
|
||||
p.parent !== undefined &&
|
||||
ts.isParenthesizedExpression(p.parent)
|
||||
)
|
||||
callee = p.parent;
|
||||
while (callee.parent !== undefined && ts.isParenthesizedExpression(callee.parent))
|
||||
callee = callee.parent;
|
||||
const call = callee.parent;
|
||||
return call !== undefined && ts.isCallExpression(call) && call.expression === callee;
|
||||
}
|
||||
|
||||
/** One recognized chunk declaration. */
|
||||
interface Chunk {
|
||||
name: string;
|
||||
@@ -310,6 +478,12 @@ export function splitBundledChunks(
|
||||
if (declaredAnywhere.has("Object") || written.has("Object"))
|
||||
return { degrade: CHUNK_SHAPE_DEGRADE };
|
||||
const stable = (name: string): boolean => !duplicate.has(name) && !written.has(name);
|
||||
// Names whose every reference in the bundle is a callee: `f(...)` or the
|
||||
// `(0, f)(...)` form.
|
||||
const scopes = new BundleScopes();
|
||||
const valueUsed = new Set<string>();
|
||||
for (const r of allRefs) if (!isCallee(r) && scopes.topLevel(r, sf)) valueUsed.add(r.text);
|
||||
const calledOnly = (name: string): boolean => !valueUsed.has(name);
|
||||
const ownNames = (name: string): boolean => {
|
||||
const t = top.get(name);
|
||||
if (t === undefined || !stable(name) || !ts.isVariableDeclaration(t.node)) return false;
|
||||
@@ -463,7 +637,17 @@ export function splitBundledChunks(
|
||||
bundleEdits.push({ start: chunk.stmt.getStart(sf), end: chunk.stmt.getEnd(), text: "" });
|
||||
continue;
|
||||
}
|
||||
const result = chunkSource(sf, chunk, chunks, top, stable, callEdits, bundleStrict);
|
||||
const result = chunkSource(
|
||||
sf,
|
||||
chunk,
|
||||
chunks,
|
||||
top,
|
||||
stable,
|
||||
calledOnly,
|
||||
scopes,
|
||||
callEdits,
|
||||
bundleStrict,
|
||||
);
|
||||
if (typeof result !== "string") return result;
|
||||
out.push({ path: chunk.path, source: result });
|
||||
bundleEdits.push({ start: chunk.stmt.getStart(sf), end: chunk.stmt.getEnd(), text: "" });
|
||||
@@ -692,6 +876,8 @@ function chunkSource(
|
||||
chunks: ReadonlyMap<string, Chunk>,
|
||||
top: ReadonlyMap<string, TopLevel>,
|
||||
stable: (name: string) => boolean,
|
||||
calledOnly: (name: string) => boolean,
|
||||
scopes: BundleScopes,
|
||||
callEdits: readonly Edit[],
|
||||
bundleStrict: boolean,
|
||||
): string | { degrade: string } {
|
||||
@@ -738,7 +924,8 @@ function chunkSource(
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (local.has(name)) continue;
|
||||
// The factory function itself binds the parameters and `var`s.
|
||||
if (scopes.boundWithin(r, body.parent ?? body)) continue;
|
||||
if (name === "exports" || name === "module")
|
||||
return why(`reads the bundle's own '${name}' binding`);
|
||||
if (name === "__filename") return why("reads __filename, which names the bundle file");
|
||||
@@ -762,9 +949,14 @@ function chunkSource(
|
||||
(ts.isVariableDeclaration(node) && copyableInitializer(node.initializer)));
|
||||
if (!pure || chunks.has(name))
|
||||
return why(`reads the bundle's top-level binding '${name}', which it cannot carry along`);
|
||||
const own = declaredNames(node);
|
||||
// Each chunk gets its own copy, so a function's identity and its
|
||||
// properties must stay unobservable: the bundle only ever calls it.
|
||||
if (isFunctionValued(node) && (!calledOnly(name) || !selfCalledOnly(node, scopes)))
|
||||
return why(
|
||||
`uses the bundle's top-level function '${name}' as a value, which its chunks cannot share`,
|
||||
);
|
||||
for (const r of references(node)) {
|
||||
if (own.has(r.text) || !top.has(r.text) || copied.has(r.text)) continue;
|
||||
if (scopes.boundWithin(r, node) || !top.has(r.text) || copied.has(r.text)) continue;
|
||||
copied.add(r.text);
|
||||
copyQueue.push(r.text);
|
||||
}
|
||||
|
||||
@@ -108,6 +108,42 @@ console.log(load(), (init_lazy(), __toCommonJS(lazy_exports)).value());
|
||||
expect(lowered).toContain('(require("os")).EOL');
|
||||
});
|
||||
|
||||
test("calls of exported functions that never read their own `this` still lower", () => {
|
||||
const lowered = expectSameBehavior(`${helpers}var t_exports = {};
|
||||
__export(t_exports, { plain: () => plain, inner: () => inner });
|
||||
function plain(x) { return "plain " + x; }
|
||||
function inner() {
|
||||
function own() { return typeof this; }
|
||||
return "inner " + own.call(1);
|
||||
}
|
||||
var init_t = __esm({ "t.ts"() {} });
|
||||
const t = (init_t(), __toCommonJS(t_exports));
|
||||
console.log(t.plain(1), (t.plain)(2), t.inner());
|
||||
`);
|
||||
expect(lowered).not.toContain("__toCommonJS(t_exports)");
|
||||
});
|
||||
|
||||
test.each([
|
||||
["a direct call", `NS.who()`],
|
||||
["a parenthesized callee", `(NS.who)()`],
|
||||
["a tagged template", "NS.who`x`"],
|
||||
["a call through a local", `(() => { const m = NS; return m.who(); })()`],
|
||||
["an arrow inside the function", `NS.arrow()()`],
|
||||
])("%s that passes the namespace as `this` keeps the package refused", (_, use) => {
|
||||
const result = lower(`${helpers}var w_exports = {};
|
||||
__export(w_exports, { who: () => who, arrow: () => arrow });
|
||||
function who() { return this.__esModule; }
|
||||
function arrow() { return () => this; }
|
||||
var init_w = __esm({ "w.ts"() {} });
|
||||
console.log(${use.replaceAll("NS", "(init_w(), __toCommonJS(w_exports))")});
|
||||
`);
|
||||
expect(result).toEqual({
|
||||
degrade: expect.stringContaining(
|
||||
"calls only of exported functions that do not read 'this'",
|
||||
) as string,
|
||||
});
|
||||
});
|
||||
|
||||
test("minified initializers sharing a var statement lower the same way", () => {
|
||||
expectSameBehavior(
|
||||
helpers +
|
||||
|
||||
@@ -211,6 +211,44 @@ function plainRead(access: ts.Expression): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** True when a member read is the callee of a call or a tag, which receives
|
||||
* the object it was read from as `this`. */
|
||||
function calledWithReceiver(access: ts.Expression): boolean {
|
||||
let callee: ts.Node = access;
|
||||
while (callee.parent !== undefined && ts.isParenthesizedExpression(callee.parent))
|
||||
callee = callee.parent;
|
||||
const p = callee.parent;
|
||||
return (
|
||||
p !== undefined &&
|
||||
((ts.isCallExpression(p) && p.expression === callee) ||
|
||||
(ts.isTaggedTemplateExpression(p) && p.tag === callee))
|
||||
);
|
||||
}
|
||||
|
||||
/** True when a function reads its own `this`: in its body, or in an arrow
|
||||
* function inside it. */
|
||||
function readsThis(fn: ts.FunctionDeclaration): boolean {
|
||||
let found = false;
|
||||
if (fn.body === undefined) return false;
|
||||
ts.walkPreorder(fn.body, (n) => {
|
||||
if (found) return "stop";
|
||||
if (
|
||||
ts.isFunctionDeclaration(n) ||
|
||||
ts.isFunctionExpression(n) ||
|
||||
ts.isMethodDeclaration(n) ||
|
||||
ts.isGetAccessorDeclaration(n) ||
|
||||
ts.isSetAccessorDeclaration(n) ||
|
||||
ts.isConstructorDeclaration(n) ||
|
||||
ts.isClassDeclaration(n) ||
|
||||
ts.isClassExpression(n)
|
||||
)
|
||||
return "skip";
|
||||
if (n.kind === ts.SyntaxKind.ThisKeyword) found = true;
|
||||
return undefined;
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
||||
/** The `__export(T, { name: () => value, … })` getter table of T, or null. */
|
||||
function exportTableOf(
|
||||
call: ts.CallExpression,
|
||||
@@ -633,7 +671,7 @@ export function lowerBundledEsmInits(
|
||||
p.parent === table.stmt
|
||||
)
|
||||
continue;
|
||||
const why = `reads the namespace of a bundled ES module ('${r.text}') in a way the static rewrite cannot follow (only member reads of its exports compile)`;
|
||||
const why = `reads the namespace of a bundled ES module ('${r.text}') in a way the static rewrite cannot follow (only member reads of its exports compile, and calls only of exported functions that do not read 'this')`;
|
||||
if (
|
||||
p === undefined ||
|
||||
!ts.isCallExpression(p) ||
|
||||
@@ -656,13 +694,25 @@ export function lowerBundledEsmInits(
|
||||
ns = up;
|
||||
else break;
|
||||
}
|
||||
const names = new Set(table.entries.map(([n]) => n));
|
||||
const values = new Map(table.entries);
|
||||
// A call through the namespace (`ns.fn()`) passes the object the read
|
||||
// came from as `this`; the lowered object differs from Node's module
|
||||
// object (`__esModule`, property attributes), so it must stay
|
||||
// unobservable: the callee is a top-level function that never reads
|
||||
// `this`.
|
||||
const receiverHidden = (name: string): boolean => {
|
||||
const value = values.get(name);
|
||||
if (value === undefined || !ts.isIdentifier(value) || !stable(value.text)) return false;
|
||||
const decl = top.get(value.text)?.node;
|
||||
return decl !== undefined && ts.isFunctionDeclaration(decl) && !readsThis(decl);
|
||||
};
|
||||
const memberRead = (access: ts.Node | undefined, of: ts.Node): boolean =>
|
||||
access !== undefined &&
|
||||
ts.isPropertyAccessExpression(access) &&
|
||||
access.expression === of &&
|
||||
names.has(access.name.text) &&
|
||||
plainRead(access);
|
||||
values.has(access.name.text) &&
|
||||
plainRead(access) &&
|
||||
(!calledWithReceiver(access) || receiverHidden(access.name.text));
|
||||
const holder = ns.parent;
|
||||
// `__reExport(main, ns, module.exports)`: a star re-export of the
|
||||
// module into the bundle's own exports (`export * from` in its entry).
|
||||
|
||||
@@ -3214,29 +3214,105 @@ function cjsCycleRefusal7(
|
||||
return null;
|
||||
}
|
||||
|
||||
/** True for a plain read `binding.name` (not a call, not a write) of the
|
||||
* cycle member `dep` whose export `name` is a top-level function
|
||||
* declaration nothing reassigns. Every member settles its exports before
|
||||
* entering the cycle, so Node reads that same function whenever the read
|
||||
* runs, and the compiled read resolves to the declaration itself. */
|
||||
/** True when `use` initializes a top-level const whose every other
|
||||
* reference is a value of an export statement (`module.exports = { … }`
|
||||
* or `exports.n = …`). */
|
||||
function publishedAlias7(use: ts.Node, decl: ts.Node | undefined): boolean {
|
||||
if (
|
||||
decl === undefined ||
|
||||
!ts.isVariableDeclaration(decl) ||
|
||||
decl.initializer !== use ||
|
||||
!ts.isIdentifier(decl.name)
|
||||
)
|
||||
return false;
|
||||
const list = decl.parent;
|
||||
const stmt = list?.parent;
|
||||
const sf = stmt?.parent;
|
||||
if (
|
||||
list === undefined ||
|
||||
(list.flags & ts.NodeFlags.Const) === 0 ||
|
||||
stmt === undefined ||
|
||||
!ts.isVariableStatement(stmt) ||
|
||||
sf === undefined ||
|
||||
!ts.isSourceFile(sf)
|
||||
)
|
||||
return false;
|
||||
const alias = decl.name;
|
||||
const published = new Set<ts.Node>();
|
||||
for (const st of sf.statements.nodes) {
|
||||
const cjs = cjsExportAssignmentOf(st);
|
||||
if (cjs === null) continue;
|
||||
if (cjs.kind === "member") published.add(cjs.value);
|
||||
else if (cjs.obj !== null) {
|
||||
for (const p of cjs.obj.properties.nodes) {
|
||||
if (ts.isPropertyAssignment(p) && !ts.isComputedPropertyName(p.name))
|
||||
published.add(p.initializer);
|
||||
else if (ts.isShorthandPropertyAssignment(p)) published.add(p.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
let kept = false;
|
||||
ts.walkPreorder(sf, (n) => {
|
||||
if (kept) return "stop";
|
||||
if (!ts.isIdentifier(n) || n === alias || n.text !== alias.text) return undefined;
|
||||
const p = n.parent;
|
||||
if (
|
||||
p !== undefined &&
|
||||
((ts.isPropertyAccessExpression(p) && p.name === n) ||
|
||||
(ts.isPropertyAssignment(p) && p.name === n))
|
||||
)
|
||||
return undefined;
|
||||
if (!published.has(n)) kept = true;
|
||||
return undefined;
|
||||
});
|
||||
return !kept;
|
||||
}
|
||||
|
||||
/** True for a plain read `binding.name` (not a call, not a write, not a
|
||||
* value that is stored or passed on) of the cycle member `dep` whose
|
||||
* export `name` is a top-level function declaration nothing reassigns.
|
||||
* Every member settles its exports before entering the cycle, so Node
|
||||
* reads that same function whenever the read runs, and the compiled read
|
||||
* resolves to the declaration itself. */
|
||||
function functionExportRead7(id: ts.Identifier, dep: ts.SourceFile): boolean {
|
||||
const access = id.parent;
|
||||
if (!ts.isPropertyAccessExpression(access) || access.expression !== id) return false;
|
||||
// The value the read yields: through parentheses and the right operand
|
||||
// of a comma, so `(0, binding.name)(...)` is the call it spells.
|
||||
let use: ts.Node = access;
|
||||
while (ts.isParenthesizedExpression(use.parent)) use = use.parent;
|
||||
for (;;) {
|
||||
const p = use.parent;
|
||||
if (ts.isParenthesizedExpression(p)) use = p;
|
||||
else if (
|
||||
ts.isBinaryExpression(p) &&
|
||||
p.operatorToken.kind === ts.SyntaxKind.CommaToken &&
|
||||
p.right === use
|
||||
)
|
||||
use = p;
|
||||
else break;
|
||||
}
|
||||
const parent = use.parent;
|
||||
if (
|
||||
(ts.isCallExpression(parent) && parent.expression === use) ||
|
||||
ts.isDeleteExpression(parent) ||
|
||||
((ts.isPrefixUnaryExpression(parent) || ts.isPostfixUnaryExpression(parent)) &&
|
||||
(parent.operator === ts.SyntaxKind.PlusPlusToken ||
|
||||
parent.operator === ts.SyntaxKind.MinusMinusToken)) ||
|
||||
// Only a use that neither runs the function nor keeps it is a read: a
|
||||
// stored alias (`const f = binding.name`, `{ f: binding.name }`) or an
|
||||
// argument can be called while the cycle initializes. A top-level const
|
||||
// that only publishes it (`module.exports = { name: f }`, the static
|
||||
// rewrite's re-export spelling) runs nothing: a module that reads the
|
||||
// export back checks that read itself.
|
||||
const observes =
|
||||
publishedAlias7(use, parent) ||
|
||||
ts.isExpressionStatement(parent) ||
|
||||
ts.isTypeOfExpression(parent) ||
|
||||
ts.isVoidExpression(parent) ||
|
||||
(ts.isPrefixUnaryExpression(parent) && parent.operator === ts.SyntaxKind.ExclamationToken) ||
|
||||
(ts.isBinaryExpression(parent) &&
|
||||
parent.left === use &&
|
||||
parent.operatorToken.kind >= ts.SyntaxKind.FirstAssignment &&
|
||||
parent.operatorToken.kind <= ts.SyntaxKind.LastAssignment)
|
||||
)
|
||||
return false;
|
||||
(parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken ||
|
||||
parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
|
||||
parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken ||
|
||||
parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken)) ||
|
||||
((ts.isIfStatement(parent) || ts.isWhileStatement(parent) || ts.isDoStatement(parent)) &&
|
||||
parent.expression === use) ||
|
||||
(ts.isConditionalExpression(parent) && parent.condition === use);
|
||||
if (!observes) return false;
|
||||
const name = access.name.text;
|
||||
// The exported value's identifier: a table entry or a member export.
|
||||
const values: ts.Expression[] = [];
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2564-chunk-helper-shadowing/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2564-lazy-barrel/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2565-chunk-shared-function/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2565-lazy-barrel-require/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2566-cjs-cycle-indirect-call/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2566-npm-alias-two-releases/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2567-cjs-function-exports/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2567-esm-namespace-this/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2568-cjs-conditional-exports/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2569-builtin-polyfill-aliases/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2570-readable-stream-builtin/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2571-bundled-polyfill-aliases/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2571-cjs-cycle-stored-function/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2572-bundled-esm-classes/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2580-lazy-barrel/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2581-lazy-barrel-require/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2582-npm-alias-two-releases/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2583-cjs-function-exports/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2584-cjs-conditional-exports/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2585-builtin-polyfill-aliases/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2586-readable-stream-builtin/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2587-bundled-polyfill-aliases/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/fixtures/npm/cases/2588-bundled-esm-classes/main.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// A bundled CommonJS chunk that calls the bundle's top-level `label` while
|
||||
// a nested function of the chunk declares its own `label`: the chunk
|
||||
// carries the top-level function along, and each reference keeps its own
|
||||
// binding.
|
||||
import { inner, outer } from "gtchunkshadow";
|
||||
|
||||
console.log(outer(), inner());
|
||||
@@ -0,0 +1,7 @@
|
||||
// Two bundled CommonJS chunks export the bundle's top-level `tally` and
|
||||
// count calls on a property of it. Node prints "1 2 true": both chunks
|
||||
// share one function. A per-chunk copy would split its identity and its
|
||||
// properties, so the package stays refused.
|
||||
import { counts, same } from "gtchunkshared";
|
||||
|
||||
console.log(counts(), same());
|
||||
@@ -0,0 +1,7 @@
|
||||
// A require cycle whose partner calls an export of index.js with esbuild's
|
||||
// `(0, import_index.peek)()` spelling while index is still initializing:
|
||||
// peek reads a const in its temporal dead zone, so Node throws a
|
||||
// ReferenceError, and scriptc refuses the cycle.
|
||||
import { show } from "gtcyclecall";
|
||||
|
||||
console.log(show());
|
||||
@@ -0,0 +1,7 @@
|
||||
// A lazily initialized ES module export that reads `this`, called through
|
||||
// the module's namespace (`lazy.who()`): Node passes the namespace object,
|
||||
// whose `__esModule` is true. A lowered namespace object would differ, so
|
||||
// the package stays refused.
|
||||
import { load } from "gtesmthis";
|
||||
|
||||
console.log(load());
|
||||
@@ -0,0 +1,8 @@
|
||||
// Require cycles whose partner stores an export of index.js (in a const,
|
||||
// or in an object literal) and calls it while index is still
|
||||
// initializing: the export reads a const in its temporal dead zone, so
|
||||
// Node throws a ReferenceError, and scriptc refuses both cycles.
|
||||
import { show } from "gtcyclealias";
|
||||
import { show as showBox } from "gtcyclebox";
|
||||
|
||||
console.log(show(), showBox());
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
export declare function outer(): string;
|
||||
export declare function inner(): string;
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
function label(n) {
|
||||
return "label " + n;
|
||||
}
|
||||
|
||||
// chunk/vendor/shadow.js
|
||||
var require_shadow = __commonJS({
|
||||
"chunk/vendor/shadow.js"(exports2, module2) {
|
||||
function nested() {
|
||||
var label = "nested";
|
||||
return label;
|
||||
}
|
||||
module2.exports = { outer: label(1), inner: nested() };
|
||||
}
|
||||
});
|
||||
|
||||
// chunk/src/index.ts
|
||||
var index_exports = {};
|
||||
__export(index_exports, {
|
||||
inner: () => inner,
|
||||
outer: () => outer
|
||||
});
|
||||
module.exports = __toCommonJS(index_exports);
|
||||
function outer() {
|
||||
return require_shadow().outer;
|
||||
}
|
||||
function inner() {
|
||||
return require_shadow().inner;
|
||||
}
|
||||
0 && (module.exports = {
|
||||
inner,
|
||||
outer
|
||||
});
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "gtchunkshadow",
|
||||
"version": "1.0.0",
|
||||
"description": "esbuild's CommonJS bundle shape: a chunk calls a top-level function whose name a nested scope of the chunk also declares",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export declare function same(): boolean;
|
||||
export declare function counts(): string;
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
function tally() {
|
||||
tally.calls = (tally.calls || 0) + 1;
|
||||
return tally.calls;
|
||||
}
|
||||
|
||||
// chunk/vendor/a.js
|
||||
var require_a = __commonJS({
|
||||
"chunk/vendor/a.js"(exports2, module2) {
|
||||
module2.exports = { tally, first: tally() };
|
||||
}
|
||||
});
|
||||
|
||||
// chunk/vendor/b.js
|
||||
var require_b = __commonJS({
|
||||
"chunk/vendor/b.js"(exports2, module2) {
|
||||
module2.exports = { tally, second: tally() };
|
||||
}
|
||||
});
|
||||
|
||||
// chunk/src/index.ts
|
||||
var index_exports = {};
|
||||
__export(index_exports, {
|
||||
counts: () => counts,
|
||||
same: () => same
|
||||
});
|
||||
module.exports = __toCommonJS(index_exports);
|
||||
function same() {
|
||||
return require_a().tally === require_b().tally;
|
||||
}
|
||||
function counts() {
|
||||
return require_a().first + " " + require_b().second;
|
||||
}
|
||||
0 && (module.exports = {
|
||||
counts,
|
||||
same
|
||||
});
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "gtchunkshared",
|
||||
"version": "1.0.0",
|
||||
"description": "esbuild's CommonJS bundle shape: two chunks export one top-level function and count calls on a property of it",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export declare const LIMIT = 3;
|
||||
export declare function show(): string;
|
||||
export declare function peek(): number;
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var index_exports = {};
|
||||
__export(index_exports, {
|
||||
LIMIT: () => LIMIT,
|
||||
peek: () => peek,
|
||||
show: () => show
|
||||
});
|
||||
module.exports = __toCommonJS(index_exports);
|
||||
var import_reader = require("./reader");
|
||||
const LIMIT = 3;
|
||||
function peek() {
|
||||
return LIMIT;
|
||||
}
|
||||
function show() {
|
||||
return (0, import_reader.describe)();
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
LIMIT,
|
||||
show
|
||||
});
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var reader_exports = {};
|
||||
__export(reader_exports, {
|
||||
captured: () => captured,
|
||||
describe: () => describe
|
||||
});
|
||||
module.exports = __toCommonJS(reader_exports);
|
||||
var import_index = require("./index");
|
||||
const read = import_index.peek;
|
||||
const captured = read();
|
||||
function describe() {
|
||||
return "limit " + captured;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
captured,
|
||||
describe
|
||||
});
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "gtcyclealias",
|
||||
"version": "1.0.0",
|
||||
"description": "esbuild 0.25.10 per-file CommonJS output shape of a cycle whose partner stores an exported function in a const and calls it while that function's const binding is uninitialized",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export declare const LIMIT = 3;
|
||||
export declare function show(): string;
|
||||
export declare function peek(): number;
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var index_exports = {};
|
||||
__export(index_exports, {
|
||||
LIMIT: () => LIMIT,
|
||||
peek: () => peek,
|
||||
show: () => show
|
||||
});
|
||||
module.exports = __toCommonJS(index_exports);
|
||||
var import_reader = require("./reader");
|
||||
const LIMIT = 3;
|
||||
function peek() {
|
||||
return LIMIT;
|
||||
}
|
||||
function show() {
|
||||
return (0, import_reader.describe)();
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
LIMIT,
|
||||
show
|
||||
});
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var reader_exports = {};
|
||||
__export(reader_exports, {
|
||||
captured: () => captured,
|
||||
describe: () => describe
|
||||
});
|
||||
module.exports = __toCommonJS(reader_exports);
|
||||
var import_index = require("./index");
|
||||
const box = { read: import_index.peek };
|
||||
const captured = box.read();
|
||||
function describe() {
|
||||
return "limit " + captured;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
captured,
|
||||
describe
|
||||
});
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "gtcyclebox",
|
||||
"version": "1.0.0",
|
||||
"description": "esbuild 0.25.10 per-file CommonJS output shape of a cycle whose partner stores an exported function in an object literal and calls it while that function's const binding is uninitialized",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export declare const LIMIT = 3;
|
||||
export declare function show(): string;
|
||||
export declare function peek(): number;
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var index_exports = {};
|
||||
__export(index_exports, {
|
||||
LIMIT: () => LIMIT,
|
||||
peek: () => peek,
|
||||
show: () => show
|
||||
});
|
||||
module.exports = __toCommonJS(index_exports);
|
||||
var import_reader = require("./reader");
|
||||
const LIMIT = 3;
|
||||
function peek() {
|
||||
return LIMIT;
|
||||
}
|
||||
function show() {
|
||||
return (0, import_reader.describe)();
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
LIMIT,
|
||||
show
|
||||
});
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var reader_exports = {};
|
||||
__export(reader_exports, {
|
||||
captured: () => captured,
|
||||
describe: () => describe
|
||||
});
|
||||
module.exports = __toCommonJS(reader_exports);
|
||||
var import_index = require("./index");
|
||||
const captured = (0, import_index.peek)();
|
||||
function describe() {
|
||||
return "limit " + captured;
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
captured,
|
||||
describe
|
||||
});
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "gtcyclecall",
|
||||
"version": "1.0.0",
|
||||
"description": "esbuild 0.25.10 per-file CommonJS output shape of a cycle whose partner calls an exported function through (0, binding.fn)() while that function's const binding is uninitialized",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export declare function describe(): string;
|
||||
export declare function load(): string;
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __esm = (fn, res) => function __init() {
|
||||
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
||||
};
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
// If the importer is in node compatibility mode or this is not an ESM
|
||||
// file that has been converted to a CommonJS file using a Babel-
|
||||
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/helper.ts
|
||||
function helper(x) {
|
||||
COUNT++;
|
||||
return "[" + x + "]";
|
||||
}
|
||||
var COUNT;
|
||||
var init_helper = __esm({
|
||||
"src/helper.ts"() {
|
||||
console.log("helper init");
|
||||
COUNT = 0;
|
||||
}
|
||||
});
|
||||
|
||||
// src/lazy.ts
|
||||
var lazy_exports = {};
|
||||
__export(lazy_exports, {
|
||||
VALUE: () => VALUE,
|
||||
value: () => value,
|
||||
who: () => who
|
||||
});
|
||||
function who() {
|
||||
return [typeof this, this.__esModule, Object.getOwnPropertyNames(this).join(","), Object.keys(this).join(",")].join(" ");
|
||||
}
|
||||
function value() {
|
||||
return VALUE + ":" + import_gtcore.default.tag + ":" + COUNT;
|
||||
}
|
||||
var path, import_gtcore, VALUE;
|
||||
var init_lazy = __esm({
|
||||
"src/lazy.ts"() {
|
||||
path = __toESM(require("path"));
|
||||
import_gtcore = __toESM(require("gtcore"));
|
||||
init_helper();
|
||||
console.log("lazy init");
|
||||
VALUE = helper(path.basename("/a/b.txt"));
|
||||
}
|
||||
});
|
||||
|
||||
// src/index.ts
|
||||
var index_exports = {};
|
||||
__export(index_exports, {
|
||||
describe: () => describe,
|
||||
load: () => load
|
||||
});
|
||||
module.exports = __toCommonJS(index_exports);
|
||||
|
||||
// src/greet.ts
|
||||
function greet(name) {
|
||||
return "hello " + name;
|
||||
}
|
||||
|
||||
// src/index.ts
|
||||
function describe() {
|
||||
return greet("main");
|
||||
}
|
||||
function load() {
|
||||
const lazy = (init_lazy(), __toCommonJS(lazy_exports));
|
||||
return lazy.value() + " " + lazy.VALUE + " | " + lazy.who() + " | " + (init_lazy(), __toCommonJS(lazy_exports)).who();
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
describe,
|
||||
load
|
||||
});
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "gtesmthis",
|
||||
"version": "1.0.0",
|
||||
"description": "gtesm's esbuild 0.25.10 output shape with a lazily initialized ES module export that reads `this`, called through the module's namespace",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"dependencies": {
|
||||
"gtcore": "1.0.0"
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,12 @@ export function npmCases(fixturesRoot: string): NpmCase[] {
|
||||
return [
|
||||
...globSync(join(fixturesRoot, "npm/cases/*/main.ts"))
|
||||
.sort()
|
||||
// 2465-2469 and 2556-2572 are the --npm-static bundler-emitted-CJS
|
||||
// 2465-2469, 2556-2567, 2571 and 2580-2588 are the --npm-static bundler-emitted-CJS
|
||||
// cases (npm-static.test.ts drives them with the opt-in): their
|
||||
// consumers exercise the static rewrite's surface (lexer-visible
|
||||
// names the shipped .d.ts never declares, the __toESM interop
|
||||
// family), so they stay out of the flagless island lane by design.
|
||||
.filter((entry) => !/\/(246[5-9]|255[6-9]|256[0-9]|257[0-2])-[^/]+\/main\.ts$/.test(entry))
|
||||
.filter((entry) => !/\/(246[5-9]|255[6-9]|256[0-7]|2571|258[0-8])-[^/]+\/main\.ts$/.test(entry))
|
||||
.map((entry) => ({
|
||||
name: entry.split("/").at(-2)!,
|
||||
entry,
|
||||
|
||||
@@ -76,7 +76,7 @@ async function buildStatic(entry: string, npmStatic: string[] | "auto"): Promise
|
||||
...globSync(
|
||||
join(fixturesRoot, "npm/node_modules/cryptozoo/**/*.{js,mjs,cjs,json,d.ts}"),
|
||||
).sort(),
|
||||
// the bundler-emitted-CJS mini packages (cases 2465-2469, 2556-2572)
|
||||
// the bundler-emitted-CJS mini packages (cases 2465-2469, 2556-2567, 2571, 2580-2588)
|
||||
...globSync(join(fixturesRoot, "npm/node_modules/gt*/**/*.{js,cjs,json}")).sort(),
|
||||
...globSync(join(fixturesRoot, "npm/store/gt*/**/*.{js,cjs,json}")).sort(),
|
||||
];
|
||||
@@ -1479,13 +1479,13 @@ describe(`npm-static pilots${sanitize ? " (sanitized)" : ""}`, () => {
|
||||
]);
|
||||
}, 180_000);
|
||||
|
||||
// 2564-2565: a barrel whose re-exports are memoized lazy loaders of
|
||||
// 2580-2581: a barrel whose re-exports are memoized lazy loaders of
|
||||
// lazily initialized ES modules (a bundle plugin's shape): ES-module
|
||||
// importers copy every export when they link (Node's CommonJS import),
|
||||
// require() reads each export's getter at the read.
|
||||
test.each([
|
||||
["2564-lazy-barrel", ["gtlazy", "gtlazyws"]],
|
||||
["2565-lazy-barrel-require", ["gtlazyuser", "gtlazy"]],
|
||||
["2580-lazy-barrel", ["gtlazy", "gtlazyws"]],
|
||||
["2581-lazy-barrel-require", ["gtlazyuser", "gtlazy"]],
|
||||
])(
|
||||
"the lazy barrel %s compiles statically and byte-matches Node",
|
||||
async (name, packages) => {
|
||||
@@ -1494,10 +1494,10 @@ describe(`npm-static pilots${sanitize ? " (sanitized)" : ""}`, () => {
|
||||
180_000,
|
||||
);
|
||||
|
||||
// 2566: two releases of one package in a pnpm store, the newer through
|
||||
// 2582: two releases of one package in a pnpm store, the newer through
|
||||
// an npm alias directory; the default selection compiles both copies.
|
||||
test("an npm alias of a selected package compiles from its JavaScript", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2566-npm-alias-two-releases/main.ts");
|
||||
const entry = join(fixturesRoot, "npm/cases/2582-npm-alias-two-releases/main.ts");
|
||||
const { coverage } = analyze(entry);
|
||||
expect(coverage.npmStatic).toEqual(
|
||||
expect.arrayContaining([
|
||||
@@ -1514,11 +1514,11 @@ describe(`npm-static pilots${sanitize ? " (sanitized)" : ""}`, () => {
|
||||
expect(nativeRes.exitCode).toBe(nodeRes.exitCode);
|
||||
}, 180_000);
|
||||
|
||||
// 2567: a module whose export object is one of its functions (semver
|
||||
// 2583: a module whose export object is one of its functions (semver
|
||||
// 5/6's `exports = module.exports = Version`), under both values of the
|
||||
// environment variable the module reads.
|
||||
test("function export objects 2567-cjs-function-exports compile statically and byte-match Node", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2567-cjs-function-exports/main.ts");
|
||||
test("function export objects 2583-cjs-function-exports compile statically and byte-match Node", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2583-cjs-function-exports/main.ts");
|
||||
await expectNodeParity(entry, ["gtfnexports", "gtfnmembers"]);
|
||||
const binary = await buildStatic(entry, ["gtfnexports", "gtfnmembers"]);
|
||||
const env = { ...process.env, GT_LABEL: "x" };
|
||||
@@ -1530,19 +1530,34 @@ describe(`npm-static pilots${sanitize ? " (sanitized)" : ""}`, () => {
|
||||
expect(nativeRes.stdout.toString("utf8")).toContain("[x]");
|
||||
}, 180_000);
|
||||
|
||||
// 2568: an export object replaced inside an environment-dependent branch
|
||||
// 2584: an export object replaced inside an environment-dependent branch
|
||||
// (readable-stream 2.x) is named precisely.
|
||||
test("an environment-dependent export object is refused by name", () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2568-cjs-conditional-exports/main.ts");
|
||||
const entry = join(fixturesRoot, "npm/cases/2584-cjs-conditional-exports/main.ts");
|
||||
const { coverage } = analyze(entry, { npmStatic: ["gtcondexports"] });
|
||||
expect(JSON.stringify(coverage)).toContain(
|
||||
"replacing module.exports outside a top-level statement (a conditional or environment-dependent export object)",
|
||||
);
|
||||
}, 120_000);
|
||||
|
||||
/* 2569-2571: polyfill packages whose module IS a Node builtin on Node 24
|
||||
// 2567: an export that reads `this`, called through its namespace, sees
|
||||
// Node's module object; the lowered namespace would differ, so the
|
||||
// package stays refused.
|
||||
test("a namespace call to an export that reads `this` stays refused", () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2567-esm-namespace-this/main.ts");
|
||||
const { coverage } = analyze(entry, { npmStatic: ["gtesmthis", "gtcore"] });
|
||||
expect(coverage.npmStatic).toContainEqual({
|
||||
package: "gtesmthis",
|
||||
status: "refused",
|
||||
detail: expect.stringMatching(
|
||||
/calls only of exported functions that do not read 'this'/,
|
||||
) as string,
|
||||
});
|
||||
}, 120_000);
|
||||
|
||||
/* 2585-2587: polyfill packages whose module IS a Node builtin on Node 24
|
||||
* compile as the builtins (builtin-package-aliases.ts), installed
|
||||
* (2569, 2570) and bundled as versioned __commonJS chunks (2571).
|
||||
* (2585, 2586) and bundled as versioned __commonJS chunks (2587).
|
||||
* readable-stream compiles as its own READABLE_STREAM=disable behavior,
|
||||
* so the Node side runs with that variable; util-deprecate's warning
|
||||
* reaches stderr on both sides (Node's carries its pid). */
|
||||
@@ -1572,25 +1587,25 @@ describe(`npm-static pilots${sanitize ? " (sanitized)" : ""}`, () => {
|
||||
}
|
||||
const disabled = { ...process.env, READABLE_STREAM: "disable" };
|
||||
|
||||
test("installed polyfill packages 2569-builtin-polyfill-aliases compile as the Node builtins", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2569-builtin-polyfill-aliases/main.ts");
|
||||
test("installed polyfill packages 2585-builtin-polyfill-aliases compile as the Node builtins", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2585-builtin-polyfill-aliases/main.ts");
|
||||
await expectAliasParity(entry, ["gtpolyfills"], process.env);
|
||||
}, 180_000);
|
||||
|
||||
test("readable-stream 2.x and 4.x 2570-readable-stream-builtin compile as node:stream", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2570-readable-stream-builtin/main.ts");
|
||||
test("readable-stream 2.x and 4.x 2586-readable-stream-builtin compile as node:stream", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2586-readable-stream-builtin/main.ts");
|
||||
await expectAliasParity(entry, ["gtrs2", "gtrs4"], disabled);
|
||||
}, 180_000);
|
||||
|
||||
test("bundled polyfill chunks 2571-bundled-polyfill-aliases compile as the Node builtins", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2571-bundled-polyfill-aliases/main.ts");
|
||||
test("bundled polyfill chunks 2587-bundled-polyfill-aliases compile as the Node builtins", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2587-bundled-polyfill-aliases/main.ts");
|
||||
await expectAliasParity(entry, ["gtpolybundle"], disabled);
|
||||
}, 180_000);
|
||||
|
||||
// 2572: classes a bundled ES module defines inside its lazy initializer,
|
||||
// 2588: classes a bundled ES module defines inside its lazy initializer,
|
||||
// over stream.Readable and over each other, compile as declarations.
|
||||
test("bundled ES module classes 2572-bundled-esm-classes compile statically and byte-match Node", async () => {
|
||||
await expectNodeParity(join(fixturesRoot, "npm/cases/2572-bundled-esm-classes/main.ts"), [
|
||||
test("bundled ES module classes 2588-bundled-esm-classes compile statically and byte-match Node", async () => {
|
||||
await expectNodeParity(join(fixturesRoot, "npm/cases/2588-bundled-esm-classes/main.ts"), [
|
||||
"gtesmclass",
|
||||
]);
|
||||
}, 180_000);
|
||||
@@ -1604,6 +1619,61 @@ describe(`npm-static pilots${sanitize ? " (sanitized)" : ""}`, () => {
|
||||
]);
|
||||
}, 180_000);
|
||||
|
||||
// 2566: the same early read through esbuild's `(0, binding.fn)()` call
|
||||
// spelling also keeps SC1016.
|
||||
test("a CommonJS cycle that calls an export during initialization stays refused", () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2566-cjs-cycle-indirect-call/main.ts");
|
||||
const { coverage } = analyze(entry, { npmStatic: ["gtcyclecall"] });
|
||||
expect(coverage.npmStatic).toEqual([
|
||||
{
|
||||
package: "gtcyclecall",
|
||||
status: "refused",
|
||||
detail: expect.stringMatching(
|
||||
/circular imports .*can use its binding 'import_index' of a module of the cycle/,
|
||||
) as string,
|
||||
},
|
||||
]);
|
||||
}, 120_000);
|
||||
|
||||
// 2571: the partner stores the export (in a const, or in an object
|
||||
// literal) and calls it while the cycle initializes; both keep SC1016.
|
||||
test("a CommonJS cycle that stores an export and calls it stays refused", () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2571-cjs-cycle-stored-function/main.ts");
|
||||
const { coverage } = analyze(entry, { npmStatic: ["gtcyclealias", "gtcyclebox"] });
|
||||
for (const pkg of ["gtcyclealias", "gtcyclebox"])
|
||||
expect(coverage.npmStatic).toContainEqual({
|
||||
package: pkg,
|
||||
status: "refused",
|
||||
detail: expect.stringMatching(
|
||||
/circular imports .*can use its binding 'import_index' of a module of the cycle/,
|
||||
) as string,
|
||||
});
|
||||
}, 120_000);
|
||||
|
||||
// 2564: a chunk reads a top-level function whose name a nested scope of
|
||||
// the chunk also declares; the function still travels with the chunk.
|
||||
test("a chunk carries a top-level function its nested scopes shadow", async () => {
|
||||
await expectNodeParity(join(fixturesRoot, "npm/cases/2564-chunk-helper-shadowing/main.ts"), [
|
||||
"gtchunkshadow",
|
||||
]);
|
||||
}, 180_000);
|
||||
|
||||
// 2565: Node shares one function between the chunks that export it; a
|
||||
// per-chunk copy would not, so the package stays refused.
|
||||
test("chunks that export a shared top-level function stay refused", () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2565-chunk-shared-function/main.ts");
|
||||
const { coverage } = analyze(entry, { npmStatic: ["gtchunkshared"] });
|
||||
expect(coverage.npmStatic).toEqual([
|
||||
{
|
||||
package: "gtchunkshared",
|
||||
status: "refused",
|
||||
detail: expect.stringMatching(
|
||||
/uses the bundle's top-level function 'tally' as a value, which its chunks cannot share/,
|
||||
) as string,
|
||||
},
|
||||
]);
|
||||
}, 120_000);
|
||||
|
||||
test("published type-only declarations coexist with a static runtime bundle", async () => {
|
||||
const entry = join(fixturesRoot, "npm/cases/2469-bundle-offender/main.ts");
|
||||
const { coverage } = analyze(entry, { npmStatic: ["gtghost"] });
|
||||
|
||||
Reference in New Issue
Block a user