Skip to content

Commit

Permalink
Extract execution order sorting, improve some names and clean up code
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Oct 15, 2018
1 parent 46ce95a commit 3be7f64
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 33 deletions.
23 changes: 14 additions & 9 deletions src/Chunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { Addons } from './utils/addons';
import { toBase64 } from './utils/base64';
import collapseSourcemaps from './utils/collapseSourcemaps';
import error from './utils/error';
import { sortByExecutionOrder } from './utils/execution-order';
import getIndentString from './utils/getIndentString';
import { makeLegal } from './utils/identifierHelpers';
import { basename, dirname, normalize, relative, resolve } from './utils/path';
Expand Down Expand Up @@ -111,7 +112,6 @@ export default class Chunk {
name: string;
graph: Graph;
orderedModules: Module[];
linked = false;
execIndex: number;

renderedModules: {
Expand Down Expand Up @@ -208,12 +208,14 @@ export default class Chunk {

link() {
this.dependencies = [];
for (const module of this.orderedModules) this.linkModule(module);
this.dependencies.sort((depA, depB) => (depA.execIndex > depB.execIndex ? 1 : -1));
this.linked = true;
for (const module of this.orderedModules) {
this.addModuleDependenciesToChunk(module);
this.setUpModuleImports(module);
}
sortByExecutionOrder(this.dependencies);
}

linkModule(module: Module) {
private addModuleDependenciesToChunk(module: Module) {
for (const depModule of module.dependencies) {
if (depModule.chunk === this) {
continue;
Expand All @@ -232,9 +234,12 @@ export default class Chunk {
this.dependencies.push(dependency);
}
}
}

private setUpModuleImports(module: Module) {
for (const importName of Object.keys(module.imports)) {
const declaration = module.imports[importName];
this.traceImport(declaration.name, declaration.module);
this.traceAndInitializeImport(declaration.name, declaration.module);
}
for (const { resolution } of module.dynamicImportResolutions) {
this.hasDynamicImport = true;
Expand Down Expand Up @@ -295,7 +300,7 @@ export default class Chunk {
}
}

private traceImport(exportName: string, module: Module | ExternalModule) {
private traceAndInitializeImport(exportName: string, module: Module | ExternalModule) {
const traced = this.traceExport(exportName, module);

if (!traced) return;
Expand All @@ -312,7 +317,7 @@ export default class Chunk {
// namespace exports could be imported themselves, so retrace
// this handles recursive namespace exported on namespace cases as well
if (traced.variable.module instanceof Module) {
this.traceImport(importName, traced.variable.module);
this.traceAndInitializeImport(importName, traced.variable.module);
} else {
const externalVariable = traced.variable.module.traceExport(importName);
if (externalVariable.included) this.imports.set(original, traced.variable.module);
Expand Down Expand Up @@ -357,7 +362,7 @@ export default class Chunk {
// if export binding is itself an import binding then continue tracing
const importDeclaration = module.imports[exportDeclaration.localName];
if (importDeclaration) {
return this.traceImport(importDeclaration.name, importDeclaration.module);
return this.traceAndInitializeImport(importDeclaration.name, importDeclaration.module);
}
return { variable: module.traceExport(name), module };
}
Expand Down
37 changes: 17 additions & 20 deletions src/Graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
Uint8ArrayXor
} from './utils/entryHashing';
import error from './utils/error';
import { sortByExecutionOrder } from './utils/execution-order';
import { isRelative, relative, resolve } from './utils/path';
import { createPluginDriver, PluginDriver } from './utils/pluginDriver';
import relativeId, { getAliasName } from './utils/relativeId';
Expand Down Expand Up @@ -432,8 +433,14 @@ export default class Graph {
// exposed as an unresolvable export * (to a graph external export *,
// either as a namespace import reexported or top-level export *)
// should be made to be its own entry point module before chunking
let chunkList: Chunk[] = [];
if (!preserveModules) {
let chunks: Chunk[] = [];
if (preserveModules) {
for (const module of orderedModules) {
const chunk = new Chunk(this, [module]);
if (module.isEntryPoint || !chunk.isEmpty) chunk.entryModule = module;
chunks.push(chunk);
}
} else {
const chunkModules: { [entryHashSum: string]: Module[] } = {};
for (const module of orderedModules) {
const entryPointsHashStr = Uint8ArrayToHexString(module.entryPointsHash);
Expand All @@ -445,35 +452,25 @@ export default class Graph {
}
}

// create each chunk
for (const entryHashSum in chunkModules) {
const chunkModulesOrdered = chunkModules[entryHashSum].sort(
(moduleA, moduleB) => (moduleA.execIndex > moduleB.execIndex ? 1 : -1)
);
const chunkModulesOrdered = chunkModules[entryHashSum];
sortByExecutionOrder(chunkModulesOrdered);
const chunk = new Chunk(this, chunkModulesOrdered);
chunkList.push(chunk);
}
} else {
for (const module of orderedModules) {
const chunkInstance = new Chunk(this, [module]);
if (module.isEntryPoint || !chunkInstance.isEmpty) chunkInstance.entryModule = module;
chunkList.push(chunkInstance);
chunks.push(chunk);
}
}

// for each chunk module, set up its imports to other
// chunks, if those variables are included after treeshaking
for (const chunk of chunkList) {
for (const chunk of chunks) {
chunk.link();
}

// filter out empty dependencies
chunkList = chunkList.filter(
chunk => !chunk.isEmpty || chunk.entryModule || chunk.isManualChunk
);
chunks = chunks.filter(chunk => !chunk.isEmpty || chunk.entryModule || chunk.isManualChunk);

// then go over and ensure all entry chunks export their variables
for (const chunk of chunkList) {
for (const chunk of chunks) {
if (preserveModules || chunk.entryModule) {
chunk.populateEntryExports(preserveModules);
}
Expand All @@ -485,15 +482,15 @@ export default class Graph {
if (!entryModule.chunk.isEntryModuleFacade) {
const entryPointFacade = new Chunk(this, []);
entryPointFacade.linkFacade(entryModule);
chunkList.push(entryPointFacade);
chunks.push(entryPointFacade);
}
}
}

timeEnd('generate chunks', 2);

this.finished = true;
return chunkList;
return chunks;
}
);
}
Expand Down
4 changes: 0 additions & 4 deletions src/Module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -641,9 +641,7 @@ export default class Module {
const namespace = this.getOrCreateNamespace();
if (namespace.needsNamespaceBlock) return;

let hasReexports = false;
for (const importName in this.reexports) {
hasReexports = true;
const reexport = this.reexports[importName];
this.imports[importName] = {
source: reexport.source,
Expand All @@ -653,8 +651,6 @@ export default class Module {
};
namespace.originals[importName] = reexport.module.traceExport(reexport.localName);
}

if (this.chunk && this.chunk.linked && hasReexports) this.chunk.linkModule(this);
}

render(options: RenderOptions): MagicString {
Expand Down
10 changes: 10 additions & 0 deletions src/utils/execution-order.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
interface OrderedExecutionUnit {
execIndex: number;
}

const compareExecIndex = <T extends OrderedExecutionUnit>(unitA: T, unitB: T) =>
unitA.execIndex > unitB.execIndex ? 1 : -1;

export function sortByExecutionOrder(units: OrderedExecutionUnit[]) {
units.sort(compareExecIndex);
}

0 comments on commit 3be7f64

Please sign in to comment.