Skip to content

Commit

Permalink
Add import specifiers to bundle information (#3722)
Browse files Browse the repository at this point in the history
* Add import specifiers to bundle information

* Rename to importedBindings
  • Loading branch information
lukastaegert committed Aug 15, 2020
1 parent 3ff0f81 commit cd64faf
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 14 deletions.
1 change: 1 addition & 0 deletions docs/02-javascript-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ async function build() {
// fileName: string, // the chunk file name
// implicitlyLoadedBefore: string[]; // entries that should only be loaded after this chunk
// imports: string[], // external modules imported statically by the chunk
// importedBindings: {[imported: string]: string[]} // imported bindings per dependency
// isDynamicEntry: boolean, // is this chunk a dynamic entry point
// isEntry: boolean, // is this chunk a static entry point
// isImplicitEntry: boolean, // should this chunk only be loaded after other chunks
Expand Down
1 change: 1 addition & 0 deletions docs/05-plugin-development.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ Called at the end of `bundle.generate()` or immediately before the files are wri
fileName: string,
implicitlyLoadedBefore: string[],
imports: string[],
importedBindings: {[imported: string]: string[]},
isDynamicEntry: boolean,
isEntry: boolean,
isImplicitEntry: boolean,
Expand Down
20 changes: 20 additions & 0 deletions src/Chunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ export default class Chunk {
dynamicImports: Array.from(this.dynamicDependencies, getId),
fileName: this.id!,
implicitlyLoadedBefore: Array.from(this.implicitlyLoadedBefore, getId),
importedBindings: this.getImportedBindingsPerDependency(),
imports: Array.from(this.dependencies, getId),
map: undefined,
referencedFiles: this.getReferencedFiles()
Expand Down Expand Up @@ -1029,6 +1030,25 @@ export default class Chunk {
return getAliasName(this.orderedModules[this.orderedModules.length - 1].id);
}

private getImportedBindingsPerDependency(): { [imported: string]: string[] } {
const importSpecifiers: { [imported: string]: string[] } = {};
for (const [dependency, declaration] of this.renderedDependencies!) {
const specifiers = new Set<string>();
if (declaration.imports) {
for (const { imported } of declaration.imports) {
specifiers.add(imported);
}
}
if (declaration.reexports) {
for (const { imported } of declaration.reexports) {
specifiers.add(imported);
}
}
importSpecifiers[dependency.id!] = [...specifiers];
}
return importSpecifiers;
}

private getImportSpecifiers(): Map<Chunk | ExternalModule, ImportSpecifier[]> {
const { interop } = this.outputOptions;
const importsByDependency = new Map<Chunk | ExternalModule, ImportSpecifier[]>();
Expand Down
3 changes: 3 additions & 0 deletions src/rollup/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,9 @@ export interface RenderedChunk extends PreRenderedChunk {
dynamicImports: string[];
fileName: string;
implicitlyLoadedBefore: string[];
importedBindings: {
[imported: string]: string[];
};
imports: string[];
map?: SourceMap;
referencedFiles: string[];
Expand Down
10 changes: 8 additions & 2 deletions test/incremental/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,14 @@ describe('incremental', () => {
asts[module.id] = module.ast;
});

assert.deepEqual(asts.entry, acorn.parse(modules.entry, { sourceType: 'module' }));
assert.deepEqual(asts.foo, acorn.parse(modules.foo, { sourceType: 'module' }));
assert.deepEqual(
asts.entry,
acorn.parse(modules.entry, { sourceType: 'module', ecmaVersion: 2020 })
);
assert.deepEqual(
asts.foo,
acorn.parse(modules.foo, { sourceType: 'module', ecmaVersion: 2020 })
);
});
});

Expand Down
134 changes: 122 additions & 12 deletions test/misc/bundle-information.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ describe('The bundle object', () => {
input: ['input1', 'input2'],
plugins: [
loader({
input1: 'import "shared";console.log("input1");export const out = true;',
input1:
'import shared, {used} from "shared";console.log("input1", used, shared);export const out = true;',
input2: 'import "shared";console.log("input2");export default 42',
shared: 'console.log("shared");export const unused = null;'
shared:
'console.log("shared");export const unused = null;export const used = "used"; export default "stuff";'
})
]
})
Expand All @@ -26,15 +28,15 @@ describe('The bundle object', () => {
.then(({ output }) => {
assert.deepEqual(
output.map(chunk => chunk.fileName),
['input1-3810e839.js', 'input2-14354d1f.js', 'generated-shared-f6027271.js'],
['input1-ff0de9c1.js', 'input2-28dc81ee.js', 'generated-shared-c4fdd061.js'],
'fileName'
);
assert.deepEqual(
output.map(chunk => chunk.code),
[
`import './generated-shared-f6027271.js';\n\nconsole.log("input1");const out = true;\n\nexport { out };\n`,
`import './generated-shared-f6027271.js';\n\nconsole.log("input2");var input2 = 42;\n\nexport default input2;\n`,
'console.log("shared");\n'
`import { u as used, s as shared } from './generated-shared-c4fdd061.js';\n\nconsole.log("input1", used, shared);const out = true;\n\nexport { out };\n`,
`import './generated-shared-c4fdd061.js';\n\nconsole.log("input2");var input2 = 42;\n\nexport default input2;\n`,
`console.log("shared");const used = "used"; var shared = "stuff";\n\nexport { shared as s, used as u };\n`
],
'code'
);
Expand All @@ -60,28 +62,37 @@ describe('The bundle object', () => {
);
assert.deepEqual(
output.map(chunk => chunk.imports),
[['generated-shared-f6027271.js'], ['generated-shared-f6027271.js'], []],
[['generated-shared-c4fdd061.js'], ['generated-shared-c4fdd061.js'], []],
'imports'
);
assert.deepEqual(
output.map(chunk => chunk.importedBindings),
[
{ 'generated-shared-c4fdd061.js': ['u', 's'] },
{ 'generated-shared-c4fdd061.js': [] },
{}
],
'importedBindings'
);
assert.deepEqual(
output.map(chunk => chunk.dynamicImports),
[[], [], []],
'dynamicImports'
);
assert.deepEqual(
output.map(chunk => chunk.exports),
[['out'], ['default'], []],
[['out'], ['default'], ['s', 'u']],
'exports'
);
assert.deepEqual(
output.map(chunk => chunk.modules),
[
{
input1: {
originalLength: 62,
originalLength: 96,
removedExports: [],
renderedExports: ['out'],
renderedLength: 39
renderedLength: 53
}
},
{
Expand All @@ -94,10 +105,99 @@ describe('The bundle object', () => {
},
{
shared: {
originalLength: 49,
originalLength: 100,
removedExports: ['unused'],
renderedExports: ['used', 'default'],
renderedLength: 64
}
}
],
'modules'
);
});
});

it('contains information about external imports and reexports', () => {
return rollup
.rollup({
input: ['input'],
external: ['external1', 'external2', 'external3'],
plugins: [
loader({
input:
'export {default as foo, bar} from "external1"; import * as external2 from "external2"; export * from "external3"; console.log(external2);'
})
]
})
.then(bundle =>
bundle.generate({
format: 'es',
dir: 'dist',
entryFileNames: '[name].js'
})
)
.then(({ output }) => {
assert.deepEqual(
output.map(chunk => chunk.fileName),
['input.js'],
'fileName'
);
assert.deepEqual(
output.map(chunk => chunk.code),
[
`export { bar, default as foo } from 'external1';\nimport * as external2 from 'external2';\nexport * from 'external3';\n\nconsole.log(external2);\n`
],
'code'
);
assert.deepEqual(
output.map(chunk => chunk.map),
[null],
'map'
);
assert.deepEqual(
output.map(chunk => chunk.isEntry),
[true],
'isEntry'
);
assert.deepEqual(
output.map(chunk => chunk.name),
['input'],
'name'
);
assert.deepEqual(
output.map(chunk => chunk.facadeModuleId),
['input'],
'facadeModuleId'
);
assert.deepEqual(
output.map(chunk => chunk.imports),
[['external1', 'external2', 'external3']],
'imports'
);
assert.deepEqual(
output.map(chunk => chunk.importedBindings),
[{ external1: ['bar', 'default'], external2: ['*'], external3: ['*'] }],
'importedBindings'
);
assert.deepEqual(
output.map(chunk => chunk.dynamicImports),
[[]],
'dynamicImports'
);
assert.deepEqual(
output.map(chunk => chunk.exports),
[['*external3', 'bar', 'foo']],
'exports'
);
assert.deepEqual(
output.map(chunk => chunk.modules),
[
{
input: {
originalLength: 137,
removedExports: [],
renderedExports: [],
renderedLength: 22
renderedLength: 23
}
}
],
Expand Down Expand Up @@ -323,6 +423,11 @@ describe('The bundle object', () => {
[[]],
'imports'
);
assert.deepEqual(
output.map(chunk => chunk.importedBindings),
[{}],
'importedBindings'
);
assert.deepEqual(
output.map(chunk => chunk.dynamicImports),
[[]],
Expand Down Expand Up @@ -400,6 +505,11 @@ console.log(other);Promise.all([import('./dynamic1'), import('./dynamic2')]).the
[['_virtual/other'], [], [], []],
'imports'
);
assert.deepEqual(
output.map(chunk => chunk.importedBindings),
[{ '_virtual/other': ['other'] }, {}, {}, {}],
'importedBindings'
);
assert.deepEqual(
output.map(chunk => chunk.exports),
[[], ['dynamic1'], ['other'], ['dynamic2']],
Expand Down

0 comments on commit cd64faf

Please sign in to comment.