Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort modules before binding, sort exports #2757

Merged
merged 2 commits into from Mar 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/Chunk.ts
Expand Up @@ -138,6 +138,7 @@ export default class Chunk {
private renderedModuleSources: MagicString[] = undefined;
private renderedSource: MagicStringBundle | null = null;
private renderedSourceLength: number = undefined;
private sortedExportNames: string[] | null = null;

constructor(graph: Graph, orderedModules: Module[]) {
this.graph = graph;
Expand Down Expand Up @@ -243,6 +244,7 @@ export default class Chunk {
let i = 0,
safeExportName: string;
this.exportNames = Object.create(null);
this.sortedExportNames = null;
const exportedVariables = Array.from(this.exports);
if (mangle) {
for (const variable of exportedVariables) {
Expand Down Expand Up @@ -275,7 +277,9 @@ export default class Chunk {
}

getExportNames(): string[] {
return Object.keys(this.exportNames);
return (
this.sortedExportNames || (this.sortedExportNames = Object.keys(this.exportNames).sort())
);
}

getImportIds(): string[] {
Expand All @@ -288,7 +292,7 @@ export default class Chunk {
const hash = sha256();
hash.update(this.renderedSource.toString());
hash.update(
Object.keys(this.exportNames)
this.getExportNames()
.map(exportName => {
const variable = this.exportNames[exportName];
return `${relativeId(variable.module.id).replace(/\\/g, '/')}:${
Expand Down Expand Up @@ -805,7 +809,7 @@ export default class Chunk {
): ChunkDependencies {
const reexportDeclarations = new Map<Chunk | ExternalModule, ReexportSpecifier[]>();

for (let exportName of Object.keys(this.exportNames)) {
for (let exportName of this.getExportNames()) {
let exportModule: Chunk | ExternalModule;
let importName: string;
if (exportName[0] === '*') {
Expand Down Expand Up @@ -901,7 +905,7 @@ export default class Chunk {

private getChunkExportDeclarations(): ChunkExports {
const exports: ChunkExports = [];
for (const exportName of Object.keys(this.exportNames)) {
for (const exportName of this.getExportNames()) {
if (exportName[0] === '*') continue;

const variable = this.exportNames[exportName];
Expand Down Expand Up @@ -991,7 +995,7 @@ export default class Chunk {
}

private setIdentifierRenderResolutions(options: OutputOptions) {
for (const exportName of Object.keys(this.exportNames)) {
for (const exportName of this.getExportNames()) {
const exportVariable = this.exportNames[exportName];
if (exportVariable) {
if (exportVariable instanceof ExportShimVariable) {
Expand Down
43 changes: 22 additions & 21 deletions src/Graph.ts
Expand Up @@ -49,23 +49,16 @@ export default class Graph {
acornOptions: acorn.Options;
acornParser: typeof acorn.Parser;
assetsById = new Map<string, Asset>();
cachedModules: Map<string, ModuleJSON>;
cacheExpiry: number;
context: string;
contextParse: (code: string, acornOptions?: acorn.Options) => ESTree.Program;
curChunkIndex = 0;
deoptimizationTracker: EntityPathTracker;
externalModules: ExternalModule[] = [];
// track graph build status as each graph instance is used only once
finished = false;
getModuleContext: (id: string) => string;
isExternal: IsExternal;
isPureExternalModule: (id: string) => boolean;
moduleById = new Map<string, Module | ExternalModule>();
modules: Module[] = [];
needsTreeshakingPass: boolean = false;
onwarn: WarningHandler;
pluginCache: Record<string, SerializablePluginCache>;
pluginDriver: PluginDriver;
preserveModules: boolean;
scope: GlobalScope;
Expand All @@ -75,6 +68,14 @@ export default class Graph {
treeshakingOptions: TreeshakingOptions;
watchFiles: Record<string, true> = Object.create(null);

private cachedModules: Map<string, ModuleJSON>;
private cacheExpiry: number;
private context: string;
private externalModules: ExternalModule[] = [];
private modules: Module[] = [];
private onwarn: WarningHandler;
private pluginCache: Record<string, SerializablePluginCache>;

constructor(options: InputOptions, watcher?: RollupWatcher) {
this.curChunkIndex = 0;
this.deoptimizationTracker = new EntityPathTracker();
Expand Down Expand Up @@ -225,16 +226,7 @@ export default class Graph {
}
}

this.link();

const { orderedModules, cyclePaths } = analyseModuleExecution(entryModules);
for (const cyclePath of cyclePaths) {
this.warn({
code: 'CIRCULAR_DEPENDENCY',
importer: cyclePath[0],
message: `Circular dependency: ${cyclePath.join(' -> ')}`
});
}
this.link(entryModules);

timeEnd('analyse dependency graph', 2);

Expand All @@ -248,7 +240,7 @@ export default class Graph {
);
}
for (const entryModule of entryModules) entryModule.includeAllExports();
this.includeMarked(orderedModules);
this.includeMarked(this.modules);

// check for unused external imports
for (const externalModule of this.externalModules) externalModule.warnUnusedImports();
Expand All @@ -275,7 +267,7 @@ export default class Graph {
// should be made to be its own entry point module before chunking
let chunks: Chunk[] = [];
if (this.preserveModules) {
for (const module of orderedModules) {
for (const module of this.modules) {
const chunk = new Chunk(this, [module]);
if (module.isEntryPoint || !chunk.isEmpty) {
chunk.entryModules = [module];
Expand All @@ -284,7 +276,7 @@ export default class Graph {
}
} else {
const chunkModules: { [entryHashSum: string]: Module[] } = {};
for (const module of orderedModules) {
for (const module of this.modules) {
const entryPointsHashStr = Uint8ArrayToHexString(module.entryPointsHash);
const curChunk = chunkModules[entryPointsHashStr];
if (curChunk) {
Expand Down Expand Up @@ -545,10 +537,19 @@ export default class Graph {
});
}

private link() {
private link(entryModules: Module[]) {
for (const module of this.modules) {
module.linkDependencies();
}
const { orderedModules, cyclePaths } = analyseModuleExecution(entryModules);
for (const cyclePath of cyclePaths) {
this.warn({
code: 'CIRCULAR_DEPENDENCY',
importer: cyclePath[0],
message: `Circular dependency: ${cyclePath.join(' -> ')}`
});
}
this.modules = orderedModules;
for (const module of this.modules) {
module.bindReferences();
}
Expand Down
Expand Up @@ -2,7 +2,7 @@ define(['exports'], function (exports) { 'use strict';

const foo = {};

exports.foo = foo;
exports.bar = foo;
exports.foo = foo;

});
Expand Up @@ -2,5 +2,5 @@

const foo = {};

exports.foo = foo;
exports.bar = foo;
exports.foo = foo;
Expand Up @@ -2,7 +2,7 @@ define(['exports'], function (exports) { 'use strict';

const foo = {};

exports.foo = foo;
exports.bar = foo;
exports.foo = foo;

});
Expand Up @@ -2,5 +2,5 @@

const foo = {};

exports.foo = foo;
exports.bar = foo;
exports.foo = foo;
Expand Up @@ -7,7 +7,7 @@ define(['exports'], function (exports) { 'use strict';
console.log('dynamic', dep);
const dynamic = 'dynamic';

exports.dynamic = dynamic;
exports.dep = dep;
exports.dynamic = dynamic;

});
Expand Up @@ -7,5 +7,5 @@ const dep = 'dep';
console.log('dynamic', dep);
const dynamic = 'dynamic';

exports.dynamic = dynamic;
exports.dep = dep;
exports.dynamic = dynamic;
Expand Up @@ -14,7 +14,7 @@ define(['require', 'exports'], function (require, exports) { 'use strict';
bar: bar
});

exports.foo = foo;
exports.bar = bar;
exports.foo = foo;

});
Expand Up @@ -14,5 +14,5 @@ var dep1 = /*#__PURE__*/Object.freeze({
bar: bar
});

exports.foo = foo;
exports.bar = bar;
exports.foo = foo;
Expand Up @@ -14,7 +14,7 @@ define(['require', 'exports'], function (require, exports) { 'use strict';
bar: bar
});

exports.foo = foo;
exports.bar = bar;
exports.foo = foo;

});
Expand Up @@ -14,5 +14,5 @@ var dep1 = /*#__PURE__*/Object.freeze({
bar: bar
});

exports.foo = foo;
exports.bar = bar;
exports.foo = foo;
Expand Up @@ -8,7 +8,7 @@ define(['exports'], function (exports) { 'use strict';
}
}

exports.log = log;
exports.dep = dep;
exports.log = log;

});
Expand Up @@ -8,5 +8,5 @@ function log (x) {
}
}

exports.log = log;
exports.dep = dep;
exports.log = log;
Expand Up @@ -8,7 +8,7 @@ define(['exports'], function (exports) { 'use strict';
}
}

exports.log = log;
exports.dep = dep;
exports.log = log;

});
Expand Up @@ -8,5 +8,5 @@ function log (x) {
}
}

exports.log = log;
exports.dep = dep;
exports.log = log;
Expand Up @@ -8,7 +8,7 @@ define(['exports'], function (exports) { 'use strict';
}
}

exports.log = log;
exports.dep = dep;
exports.log = log;

});

This file was deleted.

@@ -0,0 +1,5 @@
define(['./chunk-main2-6bb39c19-amd.js'], function (main2) { 'use strict';

main2.log(main2.dep);

});

This file was deleted.

@@ -0,0 +1,7 @@
define(['./chunk-main2-6bb39c19-amd.js'], function (main2) { 'use strict';



return main2.log;

});
Expand Up @@ -8,5 +8,5 @@ function log (x) {
}
}

exports.log = log;
exports.dep = dep;
exports.log = log;

This file was deleted.

@@ -0,0 +1,5 @@
'use strict';

var main2 = require('./chunk-main2-33c8b40d-cjs.js');

main2.log(main2.dep);
@@ -0,0 +1,7 @@
'use strict';

var main2 = require('./chunk-main2-33c8b40d-cjs.js');



module.exports = main2.log;

This file was deleted.

Expand Up @@ -8,8 +8,8 @@ define(['exports'], function (exports) { 'use strict';

const DYNAMIC_1 = 'DYNAMIC_1';

exports.DYNAMIC_1 = DYNAMIC_1;
exports.DEP = DEP;
exports.DYNAMIC_1 = DYNAMIC_1;
exports.DYNAMIC_2 = DYNAMIC_2;
exports.DYNAMIC_3 = DYNAMIC_3;

Expand Down
Expand Up @@ -8,7 +8,7 @@ const DYNAMIC_3 = 'DYNAMIC_3';

const DYNAMIC_1 = 'DYNAMIC_1';

exports.DYNAMIC_1 = DYNAMIC_1;
exports.DEP = DEP;
exports.DYNAMIC_1 = DYNAMIC_1;
exports.DYNAMIC_2 = DYNAMIC_2;
exports.DYNAMIC_3 = DYNAMIC_3;
Expand Up @@ -6,4 +6,4 @@ const DYNAMIC_3 = 'DYNAMIC_3';

const DYNAMIC_1 = 'DYNAMIC_1';

export { DYNAMIC_1, DEP, DYNAMIC_2, DYNAMIC_3 };
export { DEP, DYNAMIC_1, DYNAMIC_2, DYNAMIC_3 };
Expand Up @@ -2,7 +2,7 @@ define(['exports', './generated-dynamic.js'], function (exports, dynamic) { 'use



exports.DYNAMIC_B = dynamic.DYNAMIC_A;
exports.DYNAMIC_A = dynamic.DYNAMIC_B;
exports.DYNAMIC_B = dynamic.DYNAMIC_A;

});
Expand Up @@ -4,5 +4,5 @@ var dynamic = require('./generated-dynamic.js');



exports.DYNAMIC_B = dynamic.DYNAMIC_A;
exports.DYNAMIC_A = dynamic.DYNAMIC_B;
exports.DYNAMIC_B = dynamic.DYNAMIC_A;
@@ -1 +1 @@
export { DYNAMIC_A as DYNAMIC_B, DYNAMIC_B as DYNAMIC_A } from './generated-dynamic.js';
export { DYNAMIC_B as DYNAMIC_A, DYNAMIC_A as DYNAMIC_B } from './generated-dynamic.js';