encode entry point export constraints in the graph

This commit is contained in:
Evan Wallace
2021-04-11 02:44:25 -07:00
parent ee8a5f694d
commit ff1e7b00a8
5 changed files with 112 additions and 85 deletions

View File

@@ -1379,6 +1379,57 @@ func (c *linkerContext) scanImportsAndExports() {
repr.Meta.WrapperPartIndex = ast.MakeIndex32(partIndex)
c.graph.GenerateSymbolImportAndUse(sourceIndex, partIndex, esmRef, 1, runtime.SourceIndex)
}
// If this is an entry point, depend on all exports so they are included
if file.IsEntryPoint() {
var dependencies []js_ast.Dependency
for _, alias := range repr.Meta.SortedAndFilteredExportAliases {
export := repr.Meta.ResolvedExports[alias]
targetSourceIndex := export.SourceIndex
targetRef := export.Ref
// If this is an import, then target what the import points to
targetRepr := c.graph.Files[targetSourceIndex].InputFile.Repr.(*graph.JSRepr)
if importData, ok := targetRepr.Meta.ImportsToBind[targetRef]; ok {
targetSourceIndex = importData.SourceIndex
targetRef = importData.Ref
targetRepr = c.graph.Files[targetSourceIndex].InputFile.Repr.(*graph.JSRepr)
dependencies = append(dependencies, importData.ReExports...)
}
// Pull in all declarations of this symbol
for _, partIndex := range targetRepr.AST.TopLevelSymbolToParts[targetRef] {
dependencies = append(dependencies, js_ast.Dependency{
SourceIndex: targetSourceIndex,
PartIndex: partIndex,
})
}
}
// Ensure "exports" is included if the current output format needs it
if repr.Meta.ForceIncludeExportsForEntryPoint {
dependencies = append(dependencies, js_ast.Dependency{
SourceIndex: sourceIndex,
PartIndex: repr.Meta.NSExportPartIndex,
})
}
// Include the wrapper if present
if repr.Meta.Wrap != graph.WrapNone {
dependencies = append(dependencies, js_ast.Dependency{
SourceIndex: sourceIndex,
PartIndex: repr.Meta.WrapperPartIndex.GetIndex(),
})
}
// Represent these constraints with a dummy part
entryPointPartIndex := c.graph.AddPartToFile(sourceIndex, js_ast.Part{
Dependencies: dependencies,
CanBeRemovedIfUnused: false,
})
repr.Meta.EntryPointPartIndex = ast.MakeIndex32(entryPointPartIndex)
}
}
}
@@ -2334,38 +2385,6 @@ func (c *linkerContext) markFileAsLive(sourceIndex uint32) {
}
}
// If this is an entry point, include all exports
if file.IsEntryPoint() {
for _, alias := range repr.Meta.SortedAndFilteredExportAliases {
export := repr.Meta.ResolvedExports[alias]
targetSourceIndex := export.SourceIndex
targetRef := export.Ref
// If this is an import, then target what the import points to
targetRepr := c.graph.Files[targetSourceIndex].InputFile.Repr.(*graph.JSRepr)
if importData, ok := targetRepr.Meta.ImportsToBind[targetRef]; ok {
targetSourceIndex = importData.SourceIndex
targetRef = importData.Ref
targetRepr = c.graph.Files[targetSourceIndex].InputFile.Repr.(*graph.JSRepr)
}
// Pull in all declarations of this symbol
for _, partIndex := range targetRepr.AST.TopLevelSymbolToParts[targetRef] {
c.markPartAsLive(targetSourceIndex, partIndex)
}
}
// Ensure "exports" is included if the current output format needs it
if repr.Meta.ForceIncludeExportsForEntryPoint {
c.markPartAsLive(sourceIndex, repr.Meta.NSExportPartIndex)
}
// Include the wrapper if present
if repr.Meta.Wrap != graph.WrapNone {
c.markPartAsLive(sourceIndex, repr.Meta.WrapperPartIndex.GetIndex())
}
}
case *graph.CSSRepr:
// Include all "@import" rules
for _, record := range repr.AST.ImportRecords {

View File

@@ -2847,26 +2847,26 @@ var import_es6_ns_export_abstract_class = __toModule(require_es6_ns_export_abstr
TestTopLevelAwaitAllowedImportWithSplitting
---------- /out/entry.js ----------
// entry.js
import("./a-ZK7H2YZU.js");
import("./b-MPIVDXIR.js");
import("./c-F7O26T5D.js");
import("./a-6SYMAPP6.js");
import("./b-A7BBMSAV.js");
import("./c-745DPZZ6.js");
require_entry();
await 0;
---------- /out/a-ZK7H2YZU.js ----------
import "./chunk-BYXBJQAS.js";
import "./chunk-34XDKUTO.js";
---------- /out/a-6SYMAPP6.js ----------
import "./chunk-QJYGFXJG.js";
import "./chunk-G3F22LPE.js";
---------- /out/b-MPIVDXIR.js ----------
import "./chunk-BYXBJQAS.js";
import "./chunk-34XDKUTO.js";
---------- /out/b-A7BBMSAV.js ----------
import "./chunk-QJYGFXJG.js";
import "./chunk-G3F22LPE.js";
---------- /out/chunk-BYXBJQAS.js ----------
---------- /out/chunk-QJYGFXJG.js ----------
---------- /out/c-F7O26T5D.js ----------
import "./chunk-34XDKUTO.js";
---------- /out/c-745DPZZ6.js ----------
import "./chunk-G3F22LPE.js";
---------- /out/chunk-34XDKUTO.js ----------
---------- /out/chunk-G3F22LPE.js ----------
// c.js
await 0;

View File

@@ -41,7 +41,7 @@ TestSplittingCircularReferenceIssue251
import {
p,
q
} from "./chunk-G2XWJIBP.js";
} from "./chunk-7MUWF4J7.js";
export {
p,
q
@@ -51,13 +51,13 @@ export {
import {
p,
q
} from "./chunk-G2XWJIBP.js";
} from "./chunk-7MUWF4J7.js";
export {
p,
q
};
---------- /out/chunk-G2XWJIBP.js ----------
---------- /out/chunk-7MUWF4J7.js ----------
// a.js
var p = 5;
@@ -205,19 +205,19 @@ TestSplittingDynamicAndNotDynamicCommonJSIntoES6
import {
__toModule,
require_foo
} from "./chunk-NAN7I22W.js";
} from "./chunk-DOF77JFX.js";
// entry.js
var import_foo = __toModule(require_foo());
import("./foo-GCHTONSU.js").then(({default: {bar: b}}) => console.log(import_foo.bar, b));
import("./foo-RHEBPILD.js").then(({default: {bar: b}}) => console.log(import_foo.bar, b));
---------- /out/foo-GCHTONSU.js ----------
---------- /out/foo-RHEBPILD.js ----------
import {
require_foo
} from "./chunk-NAN7I22W.js";
} from "./chunk-DOF77JFX.js";
export default require_foo();
---------- /out/chunk-NAN7I22W.js ----------
---------- /out/chunk-DOF77JFX.js ----------
// foo.js
var require_foo = __commonJS((exports) => {
exports.bar = 123;
@@ -233,20 +233,20 @@ TestSplittingDynamicAndNotDynamicES6IntoES6
---------- /out/entry.js ----------
import {
bar
} from "./chunk-A3NXEA7F.js";
} from "./chunk-FIX3TEVC.js";
// entry.js
import("./foo-ZFJDZWZM.js").then(({bar: b}) => console.log(bar, b));
import("./foo-WSZEPKL7.js").then(({bar: b}) => console.log(bar, b));
---------- /out/foo-ZFJDZWZM.js ----------
---------- /out/foo-WSZEPKL7.js ----------
import {
bar
} from "./chunk-A3NXEA7F.js";
} from "./chunk-FIX3TEVC.js";
export {
bar
};
---------- /out/chunk-A3NXEA7F.js ----------
---------- /out/chunk-FIX3TEVC.js ----------
// foo.js
var bar = 123;
@@ -258,9 +258,9 @@ export {
TestSplittingDynamicCommonJSIntoES6
---------- /out/entry.js ----------
// entry.js
import("./foo-2YYMPLZI.js").then(({default: {bar}}) => console.log(bar));
import("./foo-BQWGKGO4.js").then(({default: {bar}}) => console.log(bar));
---------- /out/foo-2YYMPLZI.js ----------
---------- /out/foo-BQWGKGO4.js ----------
// foo.js
var require_foo = __commonJS((exports) => {
exports.bar = 123;
@@ -271,9 +271,9 @@ export default require_foo();
TestSplittingDynamicES6IntoES6
---------- /out/entry.js ----------
// entry.js
import("./foo-F64I22OH.js").then(({bar}) => console.log(bar));
import("./foo-HLOHNJMC.js").then(({bar}) => console.log(bar));
---------- /out/foo-F64I22OH.js ----------
---------- /out/foo-HLOHNJMC.js ----------
// foo.js
var bar = 123;
export {
@@ -297,13 +297,13 @@ export {
TestSplittingDynamicImportOutsideSourceTreeIssue264
---------- /out/entry1.js ----------
// Users/user/project/src/entry1.js
import("./package-UW4GHB5S.js");
import("./package-L6SN4V3F.js");
---------- /out/entry2.js ----------
// Users/user/project/src/entry2.js
import("./package-UW4GHB5S.js");
import("./package-L6SN4V3F.js");
---------- /out/package-UW4GHB5S.js ----------
---------- /out/package-L6SN4V3F.js ----------
// Users/user/project/node_modules/package/index.js
console.log("imported");
@@ -313,7 +313,7 @@ TestSplittingHybridESMAndCJSIssue617
import {
foo,
init_a
} from "./chunk-UHVVO4ZE.js";
} from "./chunk-XSW6IF3B.js";
init_a();
export {
foo
@@ -323,7 +323,7 @@ export {
import {
a_exports,
init_a
} from "./chunk-UHVVO4ZE.js";
} from "./chunk-XSW6IF3B.js";
// b.js
var bar = (init_a(), a_exports);
@@ -331,7 +331,7 @@ export {
bar
};
---------- /out/chunk-UHVVO4ZE.js ----------
---------- /out/chunk-XSW6IF3B.js ----------
// a.js
var a_exports = {};
__export(a_exports, {
@@ -442,9 +442,9 @@ export {
TestSplittingPublicPathEntryName
---------- /out/a.js ----------
// a.js
import("/www/b-UNIUFLXI.js");
import("/www/b-EDTTWD26.js");
---------- /out/b-UNIUFLXI.js ----------
---------- /out/b-EDTTWD26.js ----------
// b.js
console.log("b");
@@ -453,7 +453,7 @@ TestSplittingReExportIssue273
---------- /out/a.js ----------
import {
a
} from "./chunk-OBLLZOHJ.js";
} from "./chunk-WJGWDRHM.js";
export {
a
};
@@ -461,12 +461,12 @@ export {
---------- /out/b.js ----------
import {
a
} from "./chunk-OBLLZOHJ.js";
} from "./chunk-WJGWDRHM.js";
export {
a
};
---------- /out/chunk-OBLLZOHJ.js ----------
---------- /out/chunk-WJGWDRHM.js ----------
// a.js
var a = 1;

View File

@@ -106,16 +106,24 @@ type JSReprMeta struct {
// This is the index to the automatically-generated part containing code that
// calls "__export(exports, { ... getters ... })". This is used to generate
// getters on an exports object for ES6 export statements, and is both for
// ES6 star imports and CommonJS-style modules.
// ES6 star imports and CommonJS-style modules. All files have one of these,
// although it may contain no statements if there is nothing to export.
NSExportPartIndex uint32
// The index of the automatically-generated part used to represent the
// CommonJS or ESM wrapper. This part is empty and is only useful for tree
// shaking and code splitting. The wrapper can't be inserted into the part
// because the wrapper contains other parts, which can't be represented by
// the current part system.
// the current part system. Only wrapped files have one of these.
WrapperPartIndex ast.Index32
// The index of the automatically-generated part used to handle entry point
// specific stuff. If a certain part is needed by the entry point, it's added
// as a dependency of this part. This is important for parts that are marked
// as removable when unused and that are not used by anything else. Only
// entry point files have one of these.
EntryPointPartIndex ast.Index32
IsAsyncOrHasAsyncDependency bool
DependsOnRuntimeSymbol bool
Wrap WrapKind

View File

@@ -958,8 +958,8 @@ body {
const inShared = makeInPath(shared);
const chunk = 'chunk-M3UIZNA6.js';
const outEntry = makeOutPath(path.relative(testDir, entry));
const outImport1 = makeOutPath('import1-RW4RT54M.js');
const outImport2 = makeOutPath('import2-QZ6YEQ7N.js');
const outImport1 = makeOutPath('import1-HDYVZ7NF.js');
const outImport2 = makeOutPath('import2-NBRXROVG.js');
const outChunk = makeOutPath(chunk);
assert.deepStrictEqual(json.inputs[inEntry], {
@@ -1006,8 +1006,8 @@ body {
assert.deepStrictEqual(json.outputs[outChunk].exports, [])
assert.deepStrictEqual(json.outputs[outEntry].inputs, { [inEntry]: { bytesInOutput: 72 } })
assert.deepStrictEqual(json.outputs[outImport1].inputs, {})
assert.deepStrictEqual(json.outputs[outImport2].inputs, {})
assert.deepStrictEqual(json.outputs[outImport1].inputs, { [inImport1]: { bytesInOutput: 0 } })
assert.deepStrictEqual(json.outputs[outImport2].inputs, { [inImport2]: { bytesInOutput: 0 } })
assert.deepStrictEqual(json.outputs[outChunk].inputs, { [inShared]: { bytesInOutput: 28 } })
},
@@ -1509,8 +1509,8 @@ export {
};
`)
const outputA = 'entry/name=demo/hash=QKCLTVYB.js'
const outputB = 'entry/name=demo/hash=7E3HRWSH.js'
const outputA = 'entry/name=demo/hash=XVIIHBIC.js'
const outputB = 'entry/name=demo/hash=VXSEQP3F.js'
assert.strictEqual(value.outputFiles[0].path, path.join(outdir, outputA))
assert.strictEqual(value.outputFiles[1].path, path.join(outdir, outputB))
assert.strictEqual(value.outputFiles[2].path, path.join(outdir, chunk))
@@ -2320,8 +2320,8 @@ console.log("success");
write: false,
})
assert.strictEqual(outputFiles.length, 2)
assert.strictEqual(outputFiles[0].path, path.join(testDir, 'entry', 'out', 'YMPAGTFY-1.cjs.js'))
assert.strictEqual(outputFiles[1].path, path.join(testDir, 'entry', 'out', 'MELA46K5-2.mjs.js'))
assert.strictEqual(outputFiles[0].path, path.join(testDir, 'entry', 'out', 'LDM7WUFR-1.cjs.js'))
assert.strictEqual(outputFiles[1].path, path.join(testDir, 'entry', 'out', '74SLWWSF-2.mjs.js'))
},
async customEntryPointOutputPathsAbs({ esbuild, testDir }) {
@@ -2341,8 +2341,8 @@ console.log("success");
write: false,
})
assert.strictEqual(outputFiles.length, 2)
assert.strictEqual(outputFiles[0].path, path.join(testDir, 'entry', 'out', 'E5ZZI63T-1.js'))
assert.strictEqual(outputFiles[1].path, path.join(testDir, 'entry', 'out', 'FZK5DQMJ-2.js'))
assert.strictEqual(outputFiles[0].path, path.join(testDir, 'entry', 'out', 'MQUIWIER-1.js'))
assert.strictEqual(outputFiles[1].path, path.join(testDir, 'entry', 'out', 'ATGPBOSJ-2.js'))
},
}