Skip to content

Commit 6f90257

Browse files
authored
Merge pull request webpack#7507 from webpack/feature/dependency-order
add order to dependency reference
2 parents a1e79ab + dabbfa7 commit 6f90257

16 files changed

+141
-40
lines changed

lib/ContextModule.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const Module = require("./Module");
1010
const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
1111
const Template = require("./Template");
1212

13+
/** @typedef {import("./dependencies/ContextElementDependency")} ContextElementDependency */
14+
1315
class ContextModule extends Module {
1416
// type ContextMode = "sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"
1517
// type ContextOptions = { resource: string, recursive: boolean, regExp: RegExp, addon?: string, mode?: ContextMode, chunkName?: string, include?: RegExp, exclude?: RegExp, groupOptions?: Object }
@@ -684,10 +686,10 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
684686
const initialSize = 160;
685687

686688
// if we dont have dependencies we stop here.
687-
return this.dependencies.reduce(
688-
(size, dependency) => size + 5 + dependency.userRequest.length,
689-
initialSize
690-
);
689+
return this.dependencies.reduce((size, dependency) => {
690+
const element = /** @type {ContextElementDependency} */ (dependency);
691+
return size + 5 + element.userRequest.length;
692+
}, initialSize);
691693
}
692694
}
693695

lib/DelegatedModule.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class DelegatedModule extends Module {
5656
}
5757

5858
source(depTemplates, runtime) {
59-
const dep = this.dependencies[0];
59+
const dep = /** @type {DelegatedSourceDependency} */ (this.dependencies[0]);
6060
const sourceModule = dep.module;
6161
let str;
6262

lib/DependenciesBlock.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
const DependenciesBlockVariable = require("./DependenciesBlockVariable");
88

99
/** @typedef {import("./ChunkGroup")} ChunkGroup */
10+
/** @typedef {import("./Dependency")} Dependency */
1011

1112
class DependenciesBlock {
1213
constructor() {
14+
/** @type {Dependency[]} */
1315
this.dependencies = [];
1416
this.blocks = [];
1517
this.variables = [];

lib/Dependency.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const DependencyReference = require("./dependencies/DependencyReference");
1010
class Dependency {
1111
constructor() {
1212
this.module = null;
13+
// TODO remove in webpack 5
1314
this.weak = false;
1415
this.optional = false;
1516
this.loc = undefined;

lib/FlagDependencyUsagePlugin.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class FlagDependencyUsagePlugin {
7272
};
7373

7474
const processDependency = dep => {
75+
// TODO remove dep.getReference existance check in webpack 5
7576
const reference = dep.getReference && dep.getReference();
7677
if (!reference) return;
7778
const module = reference.module;

lib/dependencies/DependencyReference.js

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,56 @@
44
*/
55
"use strict";
66

7+
/** @typedef {import("../Module")} Module */
8+
79
class DependencyReference {
8-
constructor(module, importedNames, weak) {
10+
/**
11+
*
12+
* @param {Module} module the referenced module
13+
* @param {string[] | boolean} importedNames imported named from the module
14+
* @param {boolean=} weak if this is a weak reference
15+
* @param {number} order the order information or NaN if don't care
16+
*/
17+
constructor(module, importedNames, weak = false, order = NaN) {
918
this.module = module;
1019
// true: full object
1120
// false: only sideeffects/no export
1221
// array of strings: the exports with this names
1322
this.importedNames = importedNames;
14-
this.weak = weak;
23+
this.weak = !!weak;
24+
this.order = order;
25+
}
26+
27+
/**
28+
* @param {DependencyReference[]} array an array (will be modified)
29+
* @returns {DependencyReference[]} the array again
30+
*/
31+
static sort(array) {
32+
/** @type {WeakMap<DependencyReference, number>} */
33+
const originalOrder = new WeakMap();
34+
let i = 0;
35+
for (const ref of array) {
36+
originalOrder.set(ref, i++);
37+
}
38+
return array.sort((a, b) => {
39+
const aOrder = a.order;
40+
const bOrder = b.order;
41+
if (isNaN(aOrder)) {
42+
if (!isNaN(bOrder)) {
43+
return 1;
44+
}
45+
} else {
46+
if (isNaN(bOrder)) {
47+
return -1;
48+
}
49+
if (aOrder !== bOrder) {
50+
return aOrder - bOrder;
51+
}
52+
}
53+
const aOrg = originalOrder.get(a);
54+
const bOrg = originalOrder.get(b);
55+
return aOrg - bOrg;
56+
});
1557
}
1658
}
1759

lib/dependencies/HarmonyExportImportedSpecifierDependency.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,23 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
221221

222222
case "reexport-non-harmony-default":
223223
case "reexport-named-default":
224-
return new DependencyReference(mode.module, ["default"], false);
224+
return new DependencyReference(
225+
mode.module,
226+
["default"],
227+
false,
228+
this.sourceOrder
229+
);
225230

226231
case "reexport-namespace-object":
227232
case "reexport-non-harmony-default-strict":
228233
case "reexport-fake-namespace-object":
229234
case "rexport-non-harmony-undefined":
230-
return new DependencyReference(mode.module, true, false);
235+
return new DependencyReference(
236+
mode.module,
237+
true,
238+
false,
239+
this.sourceOrder
240+
);
231241

232242
case "safe-reexport":
233243
case "checked-reexport":
@@ -238,7 +248,12 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
238248
);
239249

240250
case "dynamic-reexport":
241-
return new DependencyReference(mode.module, true, false);
251+
return new DependencyReference(
252+
mode.module,
253+
true,
254+
false,
255+
this.sourceOrder
256+
);
242257

243258
default:
244259
throw new Error(`Unknown mode ${mode.type}`);

lib/dependencies/HarmonyImportDependency.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ class HarmonyImportDependency extends ModuleDependency {
2323

2424
getReference() {
2525
if (!this._module) return null;
26-
return new DependencyReference(this._module, false, this.weak);
26+
return new DependencyReference(
27+
this._module,
28+
false,
29+
this.weak,
30+
this.sourceOrder
31+
);
2732
}
2833

2934
getImportVar() {

lib/dependencies/HarmonyImportSpecifierDependency.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
4545
return new DependencyReference(
4646
this._module,
4747
this._id && !this.namespaceObjectAsContext ? [this._id] : true,
48-
false
48+
false,
49+
this.sourceOrder
4950
);
5051
}
5152

lib/optimize/ConcatenatedModule.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const Template = require("../Template");
99
const Parser = require("../Parser");
1010
const eslintScope = require("eslint-scope");
1111
const { ConcatSource, ReplaceSource } = require("webpack-sources");
12+
const DependencyReference = require("../dependencies/DependencyReference");
1213
const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
1314
const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency");
1415
const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
@@ -18,6 +19,8 @@ const HarmonyExportImportedSpecifierDependency = require("../dependencies/Harmon
1819
const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency");
1920
const createHash = require("../util/createHash");
2021

22+
/** @typedef {import("../Dependency")} Dependency */
23+
2124
const ensureNsObjSource = (
2225
info,
2326
moduleToInfoMap,
@@ -410,14 +413,26 @@ class ConcatenatedModule extends Module {
410413
const list = [];
411414
const set = new Set();
412415

416+
/**
417+
* @param {Module} module a module
418+
* @returns {(function(): Module)[]} imported modules in order
419+
*/
413420
const getConcatenatedImports = module => {
414-
return module.dependencies
421+
/** @type {WeakMap<DependencyReference, Dependency>} */
422+
const map = new WeakMap();
423+
const references = module.dependencies
415424
.filter(dep => dep instanceof HarmonyImportDependency)
416-
.sort((a, b) => a.sourceOrder - b.sourceOrder)
417-
.map(dep => () => {
425+
.map(dep => {
418426
const ref = dep.getReference();
419-
return ref && ref.module;
420-
});
427+
if (ref) map.set(ref, dep);
428+
return ref;
429+
})
430+
.filter(ref => ref);
431+
DependencyReference.sort(references);
432+
return references.map(ref => {
433+
const dep = map.get(ref);
434+
return () => dep.getReference().module;
435+
});
421436
};
422437

423438
const enterModule = getModule => {

lib/optimize/ModuleConcatenationPlugin.js

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -321,29 +321,27 @@ class ModuleConcatenationPlugin {
321321
}
322322

323323
getImports(module) {
324-
return Array.from(
325-
new Set(
326-
module.dependencies
327-
328-
// Only harmony Dependencies
329-
.filter(dep => dep instanceof HarmonyImportDependency)
330-
331-
// Get reference info for this dependency
332-
.map(dep => dep.getReference())
333-
334-
// Reference is valid and has a module
335-
.filter(ref => ref && ref.module)
336-
337-
// Dependencies are simple enough to concat them
338-
.filter(
339-
ref =>
340-
Array.isArray(ref.importedNames) ||
341-
Array.isArray(ref.module.buildMeta.providedExports)
342-
)
343-
344-
// Take the imported module
345-
.map(ref => ref.module)
346-
)
324+
return new Set(
325+
module.dependencies
326+
327+
// Get reference info only for harmony Dependencies
328+
.map(
329+
dep =>
330+
dep instanceof HarmonyImportDependency ? dep.getReference() : null
331+
)
332+
333+
// Reference is valid and has a module
334+
// Dependencies are simple enough to concat them
335+
.filter(
336+
ref =>
337+
ref &&
338+
ref.module &&
339+
(Array.isArray(ref.importedNames) ||
340+
Array.isArray(ref.module.buildMeta.providedExports))
341+
)
342+
343+
// Take the imported module
344+
.map(ref => ref.module)
347345
);
348346
}
349347

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { array } from "./tracker";
2+
array.push("a");
3+
export var a = 1;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { array } from "./tracker";
2+
array.push("b");
3+
export var b = 2;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { array } from "./tracker";
2+
import { a } from "./a";
3+
import { b } from "./b";
4+
5+
it("should concatenate in correct order", function() {
6+
expect(b).toBe(2);
7+
expect(a).toBe(1);
8+
expect(array).toEqual(["a", "b"]);
9+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"sideEffects": false
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export var array = [];

0 commit comments

Comments
 (0)