Skip to content
Permalink
Browse files
Merge pull request #7408 from webpack/bugfix/side-effects-caching
SideEffectsPlugin don't modify cache entries
  • Loading branch information
sokra committed May 28, 2018
2 parents 29cbf98 + ae8d674 commit 1f2584e65f1723e5c0f08b236d4a47d675dbe48b
Show file tree
Hide file tree
Showing 23 changed files with 207 additions and 85 deletions.
@@ -20,7 +20,7 @@ const isSubset = (biggerSet, subset) => {
class FlagDependencyUsagePlugin {
apply(compiler) {
compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", compilation => {
compilation.hooks.optimizeModulesAdvanced.tap(
compilation.hooks.optimizeDependencies.tap(
"FlagDependencyUsagePlugin",
modules => {
const processModule = (module, usedExports) => {
@@ -86,9 +86,9 @@ class FlagDependencyUsagePlugin {
}

const queue = [];
for (const chunk of compilation.chunks) {
if (chunk.entryModule) {
processModule(chunk.entryModule, true);
for (const preparedEntrypoint of compilation._preparedEntrypoints) {
if (preparedEntrypoint.module) {
processModule(preparedEntrypoint.module, true);
}
}

@@ -65,10 +65,16 @@ module.exports = class RuntimeTemplate {
}

moduleId({ module, request }) {
if (!module)
if (!module) {
return this.missingModule({
request
});
}
if (module.id === null) {
throw new Error(
`RuntimeTemplate.moduleId(): Module ${module.identifier()} has no id. This should not happen.`
);
}
return `${this.comment({ request })}${JSON.stringify(module.id)}`;
}

@@ -105,10 +111,16 @@ module.exports = class RuntimeTemplate {
}

moduleNamespacePromise({ block, module, request, message, strict, weak }) {
if (!module)
if (!module) {
return this.missingModulePromise({
request
});
}
if (module.id === null) {
throw new Error(
`RuntimeTemplate.moduleNamespacePromise(): Module ${module.identifier()} has no id. This should not happen.`
);
}
const promise = this.blockPromise({
block,
message
@@ -151,10 +163,16 @@ module.exports = class RuntimeTemplate {
}

importStatement({ update, module, request, importVar, originModule }) {
if (!module)
if (!module) {
return this.missingModuleStatement({
request
});
}
if (module.id === null) {
throw new Error(
`RuntimeTemplate.importStatement(): Module ${module.identifier()} has no id. This should not happen.`
);
}
const comment = this.comment({
request
});
@@ -9,14 +9,27 @@ const HarmonyImportDependency = require("./HarmonyImportDependency");
const Template = require("../Template");
const HarmonyLinkingError = require("../HarmonyLinkingError");

/** @typedef {import("../Module")} Module */

/** @typedef {"missing"|"unused"|"empty-star"|"reexport-non-harmony-default"|"reexport-named-default"|"reexport-namespace-object"|"reexport-non-harmony-default-strict"|"reexport-fake-namespace-object"|"rexport-non-harmony-undefined"|"safe-reexport"|"checked-reexport"|"dynamic-reexport"} ExportModeType */

/** @type {Map<string, string>} */
const EMPTY_MAP = new Map();

class ExportMode {
/**
* @param {ExportModeType} type type of the mode
*/
constructor(type) {
/** @type {ExportModeType} */
this.type = type;
/** @type {string|null} */
this.name = null;
/** @type {Map<string, string>} */
this.map = EMPTY_MAP;
/** @type {Module|null} */
this.module = null;
/** @type {string|null} */
this.userRequest = null;
}
}
@@ -51,7 +64,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
const name = this.name;
const id = this.id;
const used = this.originModule.isUsed(name);
const importedModule = this.module;
const importedModule = this._module;

if (!importedModule) {
const mode = new ExportMode("missing");
@@ -237,7 +250,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
const result = new Set();
// try to learn impossible exports from other star exports with provided exports
for (const otherStarExport of this.otherStarExports) {
const otherImportedModule = otherStarExport.module;
const otherImportedModule = otherStarExport._module;
if (
otherImportedModule &&
Array.isArray(otherImportedModule.buildMeta.providedExports)
@@ -310,7 +323,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
}

_getErrors() {
const importedModule = this.module;
const importedModule = this._module;
if (!importedModule) {
return;
}
@@ -354,7 +367,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {

updateHash(hash) {
super.updateHash(hash);
const hashValue = this.getHashValue(this.module);
const hashValue = this.getHashValue(this._module);
hash.update(hashValue);
}

@@ -387,7 +400,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
const used = dep.originModule.isUsed(dep.name);
if (!used) return NaN;
} else {
const importedModule = dep.module;
const importedModule = dep._module;

const activeFromOtherStarExports = dep._discoverActiveExportsFromOtherStartExports();

@@ -424,7 +437,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
getContent(dep) {
const mode = dep.getMode(false);
const module = dep.originModule;
const importedModule = dep.module;
const importedModule = dep._module;
const importVar = dep.getImportVar();

switch (mode.type) {
@@ -11,32 +11,37 @@ const Template = require("../Template");
class HarmonyImportDependency extends ModuleDependency {
constructor(request, originModule, sourceOrder, parserScope) {
super(request);
this.redirectedModule = undefined;
this.originModule = originModule;
this.sourceOrder = sourceOrder;
this.parserScope = parserScope;
}

get _module() {
return this.redirectedModule || this.module;
}

getReference() {
if (!this.module) return null;
return new DependencyReference(this.module, false, this.weak);
if (!this._module) return null;
return new DependencyReference(this._module, false, this.weak);
}

getImportVar() {
let importVarMap = this.parserScope.importVarMap;
if (!importVarMap) this.parserScope.importVarMap = importVarMap = new Map();
let importVar = importVarMap.get(this.module);
let importVar = importVarMap.get(this._module);
if (importVar) return importVar;
importVar = `${Template.toIdentifier(
`${this.userRequest}`
)}__WEBPACK_IMPORTED_MODULE_${importVarMap.size}__`;
importVarMap.set(this.module, importVar);
importVarMap.set(this._module, importVar);
return importVar;
}

getImportStatement(update, runtime) {
return runtime.importStatement({
update,
module: this.module,
module: this._module,
importVar: this.getImportVar(),
request: this.request,
originModule: this.originModule
@@ -45,14 +50,19 @@ class HarmonyImportDependency extends ModuleDependency {

updateHash(hash) {
super.updateHash(hash);
const importedModule = this.module;
const importedModule = this._module;
hash.update(
(importedModule &&
(!importedModule.buildMeta || importedModule.buildMeta.exportsType)) +
""
);
hash.update((importedModule && importedModule.id) + "");
}

disconnect() {
super.disconnect();
this.redirectedModule = undefined;
}
}

module.exports = HarmonyImportDependency;
@@ -71,7 +81,7 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate {
static isImportEmitted(dep, source) {
let sourceInfo = importEmittedMap.get(source);
if (!sourceInfo) return false;
const key = dep.module || dep.request;
const key = dep._module || dep.request;
return key && sourceInfo.emittedImports.get(key);
}

@@ -85,7 +95,7 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate {
})
);
}
const key = dep.module || dep.request;
const key = dep._module || dep.request;
if (key && sourceInfo.emittedImports.get(key)) return;
sourceInfo.emittedImports.set(key, true);
const content = dep.getImportStatement(false, runtime);
@@ -11,7 +11,7 @@ class HarmonyImportSideEffectDependency extends HarmonyImportDependency {
}

getReference() {
if (this.module && this.module.factoryMeta.sideEffectFree) return null;
if (this._module && this._module.factoryMeta.sideEffectFree) return null;

return super.getReference();
}
@@ -23,7 +23,7 @@ class HarmonyImportSideEffectDependency extends HarmonyImportDependency {

HarmonyImportSideEffectDependency.Template = class HarmonyImportSideEffectDependencyTemplate extends HarmonyImportDependency.Template {
getHarmonyInitOrder(dep) {
if (dep.module && dep.module.factoryMeta.sideEffectFree) return NaN;
if (dep._module && dep._module.factoryMeta.sideEffectFree) return NaN;
return super.getHarmonyInitOrder(dep);
}
};
@@ -21,6 +21,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
) {
super(request, originModule, sourceOrder, parserScope);
this.id = id === null ? null : `${id}`;
this.redirectedId = undefined;
this.name = name;
this.range = range;
this.strictExportPresence = strictExportPresence;
@@ -35,11 +36,15 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
return "harmony import specifier";
}

get _id() {
return this.redirectedId || this.id;
}

getReference() {
if (!this.module) return null;
if (!this._module) return null;
return new DependencyReference(
this.module,
this.id && !this.namespaceObjectAsContext ? [this.id] : true,
this._module,
this._id && !this.namespaceObjectAsContext ? [this._id] : true,
false
);
}
@@ -65,7 +70,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
}

_getErrors() {
const importedModule = this.module;
const importedModule = this._module;
if (!importedModule) {
return;
}
@@ -74,11 +79,11 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
// It's not an harmony module
if (
this.originModule.buildMeta.strictHarmonyModule &&
this.id !== "default"
this._id !== "default"
) {
// In strict harmony modules we only support the default export
const exportName = this.id
? `the named export '${this.id}'`
const exportName = this._id
? `the named export '${this._id}'`
: "the namespace object";
return [
new HarmonyLinkingError(
@@ -89,20 +94,20 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
return;
}

if (!this.id) {
if (!this._id) {
return;
}

if (importedModule.isProvided(this.id) !== false) {
if (importedModule.isProvided(this._id) !== false) {
// It's provided or we are not sure
return;
}

// We are sure that it's not provided
const idIsNotNameMessage =
this.id !== this.name ? ` (imported as '${this.name}')` : "";
this._id !== this.name ? ` (imported as '${this.name}')` : "";
const errorMessage = `"export '${
this.id
this._id
}'${idIsNotNameMessage} was not found in '${this.userRequest}'`;
return [new HarmonyLinkingError(errorMessage)];
}
@@ -114,10 +119,10 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {

updateHash(hash) {
super.updateHash(hash);
const importedModule = this.module;
hash.update((importedModule && this.id) + "");
const importedModule = this._module;
hash.update((importedModule && this._id) + "");
hash.update(
(importedModule && this.id && importedModule.isUsed(this.id)) + ""
(importedModule && this._id && importedModule.isUsed(this._id)) + ""
);
hash.update(
(importedModule &&
@@ -129,6 +134,11 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
importedModule.used + JSON.stringify(importedModule.usedExports)) + ""
);
}

disconnect() {
super.disconnect();
this.redirectedId = undefined;
}
}

HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependencyTemplate extends HarmonyImportDependency.Template {
@@ -140,9 +150,9 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen

getContent(dep, runtime) {
const exportExpr = runtime.exportFromImport({
module: dep.module,
module: dep._module,
request: dep.request,
exportName: dep.id,
exportName: dep._id,
originModule: dep.originModule,
asiSafe: dep.shorthand,
isCall: dep.call,

0 comments on commit 1f2584e

Please sign in to comment.