diff --git a/examples/cjs-tree-shaking/README.md b/examples/cjs-tree-shaking/README.md
new file mode 100644
index 000000000..661b62185
--- /dev/null
+++ b/examples/cjs-tree-shaking/README.md
@@ -0,0 +1,282 @@
+# example.js
+
+```javascript
+const inc = require("./increment").increment;
+var a = 1;
+inc(a); // 2
+```
+
+# increment.js
+
+```javascript
+const add = require("./math").add;
+exports.increment = function increment(val) {
+ return add(val, 1);
+};
+exports.incrementBy2 = function incrementBy2(val) {
+ return add(val, 2);
+};
+exports.decrement = function decrement(val) {
+ return add(val, 1);
+};
+```
+
+# math.js
+
+```javascript
+exports.add = function add() {
+ var sum = 0,
+ i = 0,
+ args = arguments,
+ l = args.length;
+ while (i < l) {
+ sum += args[i++];
+ }
+ return sum;
+};
+
+exports.multiply = function multiply() {
+ var product = 0,
+ i = 0,
+ args = arguments,
+ l = args.length;
+ while (i < l) {
+ sum *= args[i++];
+ }
+ return sum;
+};
+```
+
+# dist/output.js
+
+```javascript
+/******/ (() => { // webpackBootstrap
+/******/ var __webpack_modules__ = ([
+/* 0 */,
+/* 1 */
+/*!**********************!*\
+ !*** ./increment.js ***!
+ \**********************/
+/*! exports type: default defaultObject: redirect */
+/*! export decrement [provided] [unused] [renamed to C] */
+/*! export default [provided] [unused] [no name, virtual] */
+/*! export decrement [provided] [unused] [renamed to C] */
+/*! export increment [provided] [used] [renamed to pD] */
+/*! export incrementBy2 [provided] [unused] [renamed to ju] */
+/*! other exports [not provided] [unused] */
+/*! export increment [provided] [used] [renamed to pD] */
+/*! export incrementBy2 [provided] [unused] [renamed to ju] */
+/*! other exports [not provided] [unused] */
+/*! runtime requirements: __webpack_require__, __webpack_exports__ */
+/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
+
+var __webpack_unused_export__;
+const add = __webpack_require__(/*! ./math */ 2)/* .add */ .K;
+exports.pD = function increment(val) {
+ return add(val, 1);
+};
+__webpack_unused_export__ = function incrementBy2(val) {
+ return add(val, 2);
+};
+__webpack_unused_export__ = function decrement(val) {
+ return add(val, 1);
+};
+
+
+/***/ }),
+/* 2 */
+/*!*****************!*\
+ !*** ./math.js ***!
+ \*****************/
+/*! exports type: default defaultObject: redirect */
+/*! export add [provided] [used] [renamed to K] */
+/*! export default [provided] [unused] [no name, virtual] */
+/*! export add [provided] [used] [renamed to K] */
+/*! export multiply [provided] [unused] [renamed to j] */
+/*! other exports [not provided] [unused] */
+/*! export multiply [provided] [unused] [renamed to j] */
+/*! other exports [not provided] [unused] */
+/*! runtime requirements: __webpack_exports__ */
+/***/ ((__unused_webpack_module, exports) => {
+
+var __webpack_unused_export__;
+exports.K = function add() {
+ var sum = 0,
+ i = 0,
+ args = arguments,
+ l = args.length;
+ while (i < l) {
+ sum += args[i++];
+ }
+ return sum;
+};
+
+__webpack_unused_export__ = function multiply() {
+ var product = 0,
+ i = 0,
+ args = arguments,
+ l = args.length;
+ while (i < l) {
+ sum *= args[i++];
+ }
+ return sum;
+};
+
+
+/***/ })
+/******/ ]);
+```
+
+/* webpack runtime code */
+
+``` js
+/************************************************************************/
+/******/ // The module cache
+/******/ var __webpack_module_cache__ = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/ // Check if module is in cache
+/******/ if(__webpack_module_cache__[moduleId]) {
+/******/ return __webpack_module_cache__[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = __webpack_module_cache__[moduleId] = {
+/******/ // no module.id needed
+/******/ // no module.loaded needed
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/************************************************************************/
+```
+
+
+
+``` js
+(() => {
+/*!********************!*\
+ !*** ./example.js ***!
+ \********************/
+/*! dynamic exports type */
+/*! exports [maybe provided (runtime-defined)] [unused] */
+/*! runtime requirements: __webpack_require__ */
+const inc = __webpack_require__(/*! ./increment */ 1)/* .increment */ .pD;
+var a = 1;
+inc(a); // 2
+
+})();
+
+/******/ })()
+;
+```
+
+# dist/output.js (production)
+
+```javascript
+/*! For license information please see output.js.LICENSE */
+(()=>{var r=[,(r,t,n)=>{const e=n(2).K;t.pD=function(r){return e(r,1)}},(r,t)=>{t.K=function(){for(var r=0,t=0,n=arguments,e=n.length;t{var n=[,(n,r,t)=>{const e=t(2).add;r.increment=function(n){return e(n,1)},r.incrementBy2=function(n){return e(n,2)},r.decrement=function(n){return e(n,1)}},(n,r)=>{r.add=function(){for(var n=0,r=0,t=arguments,e=t.length;r ./example.js main
+ ./example.js 70 bytes [built]
+ [no exports used]
+ entry ./example.js main
+ ./increment.js 251 bytes [built]
+ [exports: default, decrement, increment, incrementBy2]
+ [only some exports used: increment]
+ cjs full require ./increment ./example.js 1:12-44
+ ./math.js 313 bytes [built]
+ [exports: default, add, multiply]
+ [only some exports used: add]
+ cjs full require ./math ./increment.js 1:12-33
+Child
+ Hash: 0a1b2c3d4e5f6a7b8c9d
+ Asset Size
+ without.js 3.7 KiB [emitted] [name: main]
+ Entrypoint main = without.js
+ chunk without.js (main) 634 bytes [entry] [rendered]
+ > ./example.js main
+ ./example.js 70 bytes [built]
+ [used exports unknown]
+ entry ./example.js main
+ ./increment.js 251 bytes [built]
+ [exports: default, decrement, increment, incrementBy2]
+ [used exports unknown]
+ cjs full require ./increment ./example.js 1:12-44
+ ./math.js 313 bytes [built]
+ [exports: default, add, multiply]
+ [used exports unknown]
+ cjs full require ./math ./increment.js 1:12-33
+```
+
+## Production mode
+
+```
+Hash: 0a1b2c3d4e5f6a7b8c9d
+Version: webpack 5.0.0-beta.7
+Child
+ Hash: 0a1b2c3d4e5f6a7b8c9d
+ Asset Size
+ output.js 348 bytes [emitted] [name: main]
+ output.js.LICENSE 1.16 KiB [emitted]
+ Entrypoint main = output.js
+ chunk output.js (main) 634 bytes [entry] [rendered]
+ > ./example.js main
+ ./example.js 70 bytes [built]
+ [no exports used]
+ entry ./example.js main
+ ./increment.js 251 bytes [built]
+ [exports: default, decrement, increment, incrementBy2]
+ [only some exports used: increment]
+ cjs full require ./increment ./example.js 1:12-44
+ ./math.js 313 bytes [built]
+ [exports: default, add, multiply]
+ [only some exports used: add]
+ cjs full require ./math ./increment.js 1:12-33
+Child
+ Hash: 0a1b2c3d4e5f6a7b8c9d
+ Asset Size
+ without.js 534 bytes [emitted] [name: main]
+ without.js.LICENSE 1.49 KiB [emitted]
+ Entrypoint main = without.js
+ chunk without.js (main) 634 bytes [entry] [rendered]
+ > ./example.js main
+ ./example.js 70 bytes [built]
+ [used exports unknown]
+ entry ./example.js main
+ ./increment.js 251 bytes [built]
+ [exports: default, decrement, increment, incrementBy2]
+ [used exports unknown]
+ cjs full require ./increment ./example.js 1:12-44
+ ./math.js 313 bytes [built]
+ [exports: default, add, multiply]
+ [used exports unknown]
+ cjs full require ./math ./increment.js 1:12-33
+```
diff --git a/examples/cjs-tree-shaking/build.js b/examples/cjs-tree-shaking/build.js
new file mode 100644
index 000000000..7492e9f9f
--- /dev/null
+++ b/examples/cjs-tree-shaking/build.js
@@ -0,0 +1,2 @@
+global.NO_TARGET_ARGS = true;
+require("../build-common");
diff --git a/examples/cjs-tree-shaking/cases.txt b/examples/cjs-tree-shaking/cases.txt
new file mode 100644
index 000000000..34bc275e0
--- /dev/null
+++ b/examples/cjs-tree-shaking/cases.txt
@@ -0,0 +1,58 @@
+BAD:
+
+module.exports = abc; module.exports.xxx = abc; abc.xxx;
+exports = abc;
+module.exports
+exports
+this
+function f() { return this; } module.exports = { f }; module.exports.xxx = abc;
+
+
+EXPORTS:
+
+exports.xxx = abc;
+
+module.exports.xxx = abc;
+this.xxx = abc
+Object.defineProperty(exports, "xxx", { ... })
+Object.defineProperty(module.exports, "xxx", { ... })
+Object.defineProperty(this, "xxx", { ... })
+module.exports.xxx
+exports.xxx
+this.xxx
+module.exports = function() {}; module.exports.xxx = abc;
+module.exports = { ... }; module.exports.xxx = abc;
+
+OBJECTS:
+
+module.exports = { xxx: abc };
+
+IMPORT:
+
+require(x).xxx
+var { xxx } = require(x);
+var x = require(x); x.xxx;
+
+REEXPORT:
+
+module.exports.xxx = require(x);
+module.exports.xxx = require(x).xxx;
+exports.xxx = require(x);
+exports.xxx = require(x).xxx;
+module.exports = { xxx2: require(x) };
+module.exports = { xxx2: require(x).xxx };
+var xxx = require(x); exports.xxx = xxx;
+var xxx = require(x); exports.xxx = xxx.xxx;
+var xxx = require(x); module.exports = { xxx };
+var xxx = require(x); module.exports = { xxx: xxx.xxx };
+
+TRANSPILED:
+
+TypeScript:
+function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; }
+__export(require(x));
+
+Babel:
+var xxx = _interopRequireDefault(require(x));
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+xxx.xxx;
diff --git a/examples/cjs-tree-shaking/example.js b/examples/cjs-tree-shaking/example.js
new file mode 100644
index 000000000..824a4d22b
--- /dev/null
+++ b/examples/cjs-tree-shaking/example.js
@@ -0,0 +1,3 @@
+const inc = require("./increment").increment;
+var a = 1;
+inc(a); // 2
diff --git a/examples/cjs-tree-shaking/increment.js b/examples/cjs-tree-shaking/increment.js
new file mode 100644
index 000000000..df54369b9
--- /dev/null
+++ b/examples/cjs-tree-shaking/increment.js
@@ -0,0 +1,10 @@
+const add = require("./math").add;
+exports.increment = function increment(val) {
+ return add(val, 1);
+};
+exports.incrementBy2 = function incrementBy2(val) {
+ return add(val, 2);
+};
+exports.decrement = function decrement(val) {
+ return add(val, 1);
+};
diff --git a/examples/cjs-tree-shaking/math.js b/examples/cjs-tree-shaking/math.js
new file mode 100644
index 000000000..97a0ac866
--- /dev/null
+++ b/examples/cjs-tree-shaking/math.js
@@ -0,0 +1,21 @@
+exports.add = function add() {
+ var sum = 0,
+ i = 0,
+ args = arguments,
+ l = args.length;
+ while (i < l) {
+ sum += args[i++];
+ }
+ return sum;
+};
+
+exports.multiply = function multiply() {
+ var product = 0,
+ i = 0,
+ args = arguments,
+ l = args.length;
+ while (i < l) {
+ sum *= args[i++];
+ }
+ return sum;
+};
diff --git a/examples/cjs-tree-shaking/template.md b/examples/cjs-tree-shaking/template.md
new file mode 100644
index 000000000..68a8221b9
--- /dev/null
+++ b/examples/cjs-tree-shaking/template.md
@@ -0,0 +1,49 @@
+# example.js
+
+```javascript
+_{{example.js}}_
+```
+
+# increment.js
+
+```javascript
+_{{increment.js}}_
+```
+
+# math.js
+
+```javascript
+_{{math.js}}_
+```
+
+# dist/output.js
+
+```javascript
+_{{dist/output.js}}_
+```
+
+# dist/output.js (production)
+
+```javascript
+_{{production:dist/output.js}}_
+```
+
+# dist/without.js (same without tree shaking)
+
+```javascript
+_{{production:dist/without.js}}_
+```
+
+# Info
+
+## Unoptimized
+
+```
+_{{stdout}}_
+```
+
+## Production mode
+
+```
+_{{production:stdout}}_
+```
diff --git a/examples/cjs-tree-shaking/webpack.config.js b/examples/cjs-tree-shaking/webpack.config.js
new file mode 100644
index 000000000..b40c7be44
--- /dev/null
+++ b/examples/cjs-tree-shaking/webpack.config.js
@@ -0,0 +1,26 @@
+module.exports = [
+ {
+ entry: "./example.js",
+ output: {
+ pathinfo: true,
+ filename: "output.js"
+ },
+ optimization: {
+ moduleIds: "size",
+ usedExports: true,
+ mangleExports: true
+ }
+ },
+ {
+ entry: "./example.js",
+ output: {
+ pathinfo: true,
+ filename: "without.js"
+ },
+ optimization: {
+ moduleIds: "size",
+ usedExports: false,
+ mangleExports: false
+ }
+ }
+];
diff --git a/lib/CommonJsStuffPlugin.js b/lib/CommonJsStuffPlugin.js
deleted file mode 100644
index b1601cc79..000000000
--- a/lib/CommonJsStuffPlugin.js
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
-*/
-
-"use strict";
-
-const RuntimeGlobals = require("./RuntimeGlobals");
-const RuntimeModule = require("./RuntimeModule");
-const Template = require("./Template");
-const ModuleDecoratorDependency = require("./dependencies/ModuleDecoratorDependency");
-const RuntimeRequirementsDependency = require("./dependencies/RuntimeRequirementsDependency");
-const {
- evaluateToIdentifier,
- expressionIsUnsupported,
- toConstantDependency
-} = require("./javascript/JavascriptParserHelpers");
-
-class CommonJsStuffPlugin {
- apply(compiler) {
- compiler.hooks.compilation.tap(
- "CommonJsStuffPlugin",
- (compilation, { normalModuleFactory }) => {
- compilation.dependencyFactories.set(
- ModuleDecoratorDependency,
- normalModuleFactory
- );
- compilation.dependencyTemplates.set(
- ModuleDecoratorDependency,
- new ModuleDecoratorDependency.Template()
- );
-
- compilation.hooks.runtimeRequirementInModule
- .for(RuntimeGlobals.harmonyModuleDecorator)
- .tap("CommonJsStuffPlugin", (module, set) => {
- set.add(RuntimeGlobals.module);
- set.add(RuntimeGlobals.requireScope);
- });
-
- compilation.hooks.runtimeRequirementInModule
- .for(RuntimeGlobals.nodeModuleDecorator)
- .tap("CommonJsStuffPlugin", (module, set) => {
- set.add(RuntimeGlobals.module);
- set.add(RuntimeGlobals.requireScope);
- });
-
- compilation.hooks.runtimeRequirementInTree
- .for(RuntimeGlobals.harmonyModuleDecorator)
- .tap("CommonJsStuffPlugin", (chunk, set) => {
- compilation.addRuntimeModule(
- chunk,
- new HarmonyModuleDecoratorRuntimeModule()
- );
- });
-
- compilation.hooks.runtimeRequirementInTree
- .for(RuntimeGlobals.nodeModuleDecorator)
- .tap("CommonJsStuffPlugin", (chunk, set) => {
- compilation.addRuntimeModule(
- chunk,
- new NodeModuleDecoratorRuntimeModule()
- );
- });
-
- const handler = (parser, parserOptions) => {
- parser.hooks.expression
- .for("require.main.require")
- .tap(
- "CommonJsStuffPlugin",
- expressionIsUnsupported(
- parser,
- "require.main.require is not supported by webpack."
- )
- );
- parser.hooks.expression
- .for("module.parent.require")
- .tap(
- "CommonJsStuffPlugin",
- expressionIsUnsupported(
- parser,
- "module.parent.require is not supported by webpack."
- )
- );
- parser.hooks.expression
- .for("require.main")
- .tap(
- "CommonJsStuffPlugin",
- toConstantDependency(
- parser,
- `${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}]`,
- [RuntimeGlobals.moduleCache, RuntimeGlobals.entryModuleId]
- )
- );
- parser.hooks.expression
- .for("module.loaded")
- .tap("CommonJsStuffPlugin", expr => {
- parser.state.module.buildMeta.moduleConcatenationBailout =
- "module.loaded";
- return toConstantDependency(
- parser,
- `${RuntimeGlobals.module}.l`,
- [RuntimeGlobals.module]
- )(expr);
- });
- parser.hooks.expression
- .for("module.id")
- .tap("CommonJsStuffPlugin", expr => {
- parser.state.module.buildMeta.moduleConcatenationBailout =
- "module.id";
- return toConstantDependency(
- parser,
- `${RuntimeGlobals.module}.i`,
- [RuntimeGlobals.module]
- )(expr);
- });
- parser.hooks.expression
- .for("module.exports")
- .tap("CommonJsStuffPlugin", expr => {
- const module = parser.state.module;
- const isHarmony =
- module.buildMeta && module.buildMeta.exportsType;
- if (!isHarmony) {
- if (module.moduleArgument === "module") {
- // avoid rewriting module.exports for backward-compat
- const dep = new RuntimeRequirementsDependency([
- RuntimeGlobals.module
- ]);
- dep.loc = expr.loc;
- module.addPresentationalDependency(dep);
- return true;
- }
- return toConstantDependency(
- parser,
- `${module.moduleArgument}.exports`,
- [RuntimeGlobals.module]
- )(expr);
- }
- });
- parser.hooks.expression
- .for("this")
- .tap("CommonJsStuffPlugin", expr => {
- if (!parser.scope.topLevelScope) return;
- const module = parser.state.module;
- const isHarmony =
- module.buildMeta && module.buildMeta.exportsType;
- if (!isHarmony) {
- return toConstantDependency(parser, "this", [
- RuntimeGlobals.thisAsExports
- ])(expr);
- }
- });
- parser.hooks.evaluateIdentifier.for("module.hot").tap(
- "CommonJsStuffPlugin",
- evaluateToIdentifier("module.hot", "module", () => ["hot"], false)
- );
- parser.hooks.expression
- .for("module")
- .tap("CommonJsStuffPlugin", expr => {
- const isHarmony =
- parser.state.module.buildMeta &&
- parser.state.module.buildMeta.exportsType;
- const dep = new ModuleDecoratorDependency(
- isHarmony
- ? RuntimeGlobals.harmonyModuleDecorator
- : RuntimeGlobals.nodeModuleDecorator
- );
- dep.loc = expr.loc;
- parser.state.module.addPresentationalDependency(dep);
- return true;
- });
- };
-
- normalModuleFactory.hooks.parser
- .for("javascript/auto")
- .tap("CommonJsStuffPlugin", handler);
- normalModuleFactory.hooks.parser
- .for("javascript/dynamic")
- .tap("CommonJsStuffPlugin", handler);
- }
- );
- }
-}
-
-class HarmonyModuleDecoratorRuntimeModule extends RuntimeModule {
- constructor() {
- super("harmony module decorator");
- }
-
- /**
- * @returns {string} runtime code
- */
- generate() {
- const { runtimeTemplate } = this.compilation;
- return Template.asString([
- `${
- RuntimeGlobals.harmonyModuleDecorator
- } = ${runtimeTemplate.basicFunction("module", [
- "module = Object.create(module);",
- "if (!module.children) module.children = [];",
- "Object.defineProperty(module, 'loaded', {",
- Template.indent([
- "enumerable: true,",
- `get: ${runtimeTemplate.returningFunction("module.l")}`
- ]),
- "});",
- "Object.defineProperty(module, 'id', {",
- Template.indent([
- "enumerable: true,",
- `get: ${runtimeTemplate.returningFunction("module.i")}`
- ]),
- "});",
- "Object.defineProperty(module, 'exports', {",
- Template.indent([
- "enumerable: true,",
- `set: ${runtimeTemplate.basicFunction("", [
- "throw new Error('ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id);"
- ])}`
- ]),
- "});",
- "return module;"
- ])};`
- ]);
- }
-}
-
-class NodeModuleDecoratorRuntimeModule extends RuntimeModule {
- constructor() {
- super("node module decorator");
- }
-
- /**
- * @returns {string} runtime code
- */
- generate() {
- const { runtimeTemplate } = this.compilation;
- return Template.asString([
- `${
- RuntimeGlobals.nodeModuleDecorator
- } = ${runtimeTemplate.basicFunction("module", [
- "module.paths = [];",
- "if (!module.children) module.children = [];",
- "Object.defineProperty(module, 'loaded', {",
- Template.indent([
- "enumerable: true,",
- `get: ${runtimeTemplate.returningFunction("module.l")}`
- ]),
- "});",
- "Object.defineProperty(module, 'id', {",
- Template.indent([
- "enumerable: true,",
- `get: ${runtimeTemplate.returningFunction("module.i")}`
- ]),
- "});",
- "return module;"
- ])};`
- ]);
- }
-}
-
-module.exports = CommonJsStuffPlugin;
diff --git a/lib/ContextModule.js b/lib/ContextModule.js
index e517edc08..7ba242c82 100644
--- a/lib/ContextModule.js
+++ b/lib/ContextModule.js
@@ -462,13 +462,12 @@ class ContextModule extends Module {
return 9;
}
const moduleGraph = chunkGraph.moduleGraph;
+ // bitfield
+ let hasType = 0;
+ const comparator = compareModulesById(chunkGraph);
// if we filter first we get a new array
// therefor we dont need to create a clone of dependencies explicitly
// therefore the order of this is !important!
- let hasNonHarmony = false;
- let hasNamespace = false;
- let hasNamed = false;
- const comparator = compareModulesById(chunkGraph);
const fakeMap = dependencies
.map(dependency => ({
module: moduleGraph.getModule(dependency),
@@ -477,30 +476,46 @@ class ContextModule extends Module {
.filter(item => item.module)
.sort((a, b) => comparator(a.module, b.module))
.reduce((map, { dependency: dep, module }) => {
- const exportsType = module.buildMeta && module.buildMeta.exportsType;
+ const exportsType = module.getExportsType(
+ this.options.namespaceObject === "strict"
+ );
const id = chunkGraph.getModuleId(module);
- if (!exportsType) {
- map[id] = this.options.namespaceObject === "strict" ? 1 : 7;
- hasNonHarmony = true;
- } else if (exportsType === "namespace") {
- map[id] = 9;
- hasNamespace = true;
- } else if (exportsType === "default") {
- map[id] = this.options.namespaceObject === "strict" ? 1 : 3;
- hasNamed = true;
+ switch (exportsType) {
+ case "namespace":
+ map[id] = 9;
+ hasType |= 1;
+ break;
+ case "dynamic":
+ map[id] = 7;
+ hasType |= 2;
+ break;
+ case "dynamic-default":
+ case "default-only":
+ map[id] = 1;
+ hasType |= 4;
+ break;
+ case "default-with-named":
+ map[id] = 3;
+ hasType |= 8;
+ break;
+ default:
+ throw new Error(`Unexpected exports type ${exportsType}`);
}
return map;
}, Object.create(null));
- if (!hasNamespace && hasNonHarmony && !hasNamed) {
- return this.options.namespaceObject === "strict" ? 1 : 7;
- }
- if (hasNamespace && !hasNonHarmony && !hasNamed) {
+ if (hasType === 1) {
return 9;
}
- if (!hasNamespace && !hasNonHarmony && hasNamed) {
- return this.options.namespaceObject === "strict" ? 1 : 3;
+ if (hasType === 2) {
+ return 7;
}
- if (!hasNamespace && !hasNonHarmony && !hasNamed) {
+ if (hasType === 4) {
+ return 1;
+ }
+ if (hasType === 8) {
+ return 3;
+ }
+ if (hasType === 0) {
return 9;
}
return fakeMap;
diff --git a/lib/Module.js b/lib/Module.js
index f7e5947c6..cd7a15bae 100644
--- a/lib/Module.js
+++ b/lib/Module.js
@@ -65,7 +65,8 @@ const makeSerializable = require("./util/makeSerializable");
* @property {string=} exportsArgument
* @property {boolean=} strict
* @property {string=} moduleConcatenationBailout
- * @property {("default" | "namespace")=} exportsType
+ * @property {("default" | "namespace" | "flagged")=} exportsType
+ * @property {(boolean | "redirect" | "redirect-warn")=} defaultObject
* @property {boolean=} strictHarmonyModule
* @property {boolean=} async
*/
@@ -364,6 +365,29 @@ class Module extends DependenciesBlock {
return (this.buildInfo && this.buildInfo.moduleArgument) || "module";
}
+ /**
+ * @param {boolean} strict the importing module is strict
+ * @returns {"dynamic" | "dynamic-default" | "namespace" | "default-only" | "default-with-named"} export type
+ */
+ getExportsType(strict) {
+ switch (this.buildMeta && this.buildMeta.exportsType) {
+ case "flagged":
+ return strict ? "dynamic-default" : "namespace";
+ case "namespace":
+ return "namespace";
+ case "default":
+ switch (this.buildMeta.defaultObject) {
+ case "redirect":
+ case "redirect-warn":
+ return strict ? "default-only" : "default-with-named";
+ default:
+ return "default-only";
+ }
+ default:
+ return strict ? "dynamic-default" : "dynamic";
+ }
+ }
+
/**
* @param {Dependency} presentationalDependency dependency being tied to module.
* This is a Dependency without edge in the module graph. It's only for presentation.
@@ -602,7 +626,11 @@ class Module extends DependenciesBlock {
for (const exportInfo of exportsInfo.orderedExports) {
hash.update(exportInfo.name);
hash.update(exportInfo.used + "");
- hash.update(exportInfo.usedName + "");
+ hash.update(
+ exportInfo.usedName === ModuleGraph.SKIP_OVER_NAME
+ ? ""
+ : exportInfo.usedName + ""
+ );
}
if (this.presentationalDependencies !== undefined) {
for (const dep of this.presentationalDependencies) {
diff --git a/lib/ModuleGraph.js b/lib/ModuleGraph.js
index 2ca028d47..0495dfb1f 100644
--- a/lib/ModuleGraph.js
+++ b/lib/ModuleGraph.js
@@ -24,6 +24,8 @@ const makeSerializable = require("./util/makeSerializable");
const EMPTY_ARRAY = [];
+const SKIP_OVER_NAME = Symbol("skip over name");
+
/** @typedef {0|1|2|3|4} UsageStateType */
const UsageState = Object.freeze({
@@ -130,12 +132,8 @@ class ExportsInfo {
this._exportsAreOrdered = true;
}
- setRedirectToDefaultObject() {
- const defaultInfo = this.getExportInfo("default");
- defaultInfo.canMangleProvide = false;
- defaultInfo.usedName = "";
- const inner = defaultInfo.createNestedExportsInfo();
- this._redirectTo = inner;
+ setRedirectNamedTo(exportsInfo) {
+ this._redirectTo = exportsInfo;
}
setHasProvideInfo() {
@@ -190,8 +188,6 @@ class ExportsInfo {
const info = this._exports.get(name);
if (info !== undefined) return info;
if (this._redirectTo) return this._redirectTo.getExportInfo(name);
- if (!name)
- throw new Error("ModuleGraph.getExportInfo name must be a valid string");
const newInfo = new ExportInfo(name, this._otherExportsInfo);
this._exports.set(name, newInfo);
this._exportsAreOrdered = false;
@@ -456,11 +452,16 @@ class ExportsInfo {
let info = this.getReadOnlyExportInfo(name[0]);
const x = info.getUsedName(name[0]);
if (x === false) return false;
- const arr = x === name[0] && name.length === 1 ? name : x ? [x] : [];
+ const arr =
+ x === name[0] && name.length === 1
+ ? name
+ : x !== SKIP_OVER_NAME
+ ? [x]
+ : EMPTY_ARRAY;
if (name.length === 1) {
return arr;
}
- if (info.exportsInfo) {
+ if (info.exportsInfo && info.used === UsageState.OnlyPropertiesUsed) {
const nested = info.exportsInfo.getUsedName(name.slice(1));
if (!nested) return false;
return arr.concat(nested);
@@ -527,7 +528,7 @@ class ExportInfo {
constructor(name, initFrom) {
/** @type {string} */
this.name = name;
- /** @type {string | null} */
+ /** @type {string | null | SKIP_OVER_NAME} */
this.usedName = initFrom ? initFrom.usedName : null;
/** @type {UsageStateType} */
this.used = initFrom ? initFrom.used : UsageState.NoInfo;
@@ -628,7 +629,9 @@ class ExportInfo {
getRenameInfo() {
if (this.usedName !== null && this.usedName !== this.name) {
- return this.usedName ? `renamed to ${this.usedName}` : "no name, virtual";
+ return this.usedName !== SKIP_OVER_NAME
+ ? `renamed to ${JSON.stringify(this.usedName).slice(1, -1)}`
+ : "no name, virtual";
}
switch (this.canMangleProvide) {
case undefined:
@@ -958,7 +961,20 @@ class ModuleGraph {
*/
finishModule(module) {
if (module.buildMeta.exportsType === "default") {
- this.getExportsInfo(module).setRedirectToDefaultObject();
+ const exportsInfo = this.getExportsInfo(module);
+ const defaultInfo = exportsInfo.getExportInfo("default");
+ defaultInfo.canMangleProvide = false;
+ defaultInfo.provided = true;
+ defaultInfo.usedName = SKIP_OVER_NAME;
+ if (module.buildMeta.defaultObject) {
+ const innerObject = defaultInfo.createNestedExportsInfo();
+ if (
+ module.buildMeta.defaultObject === "redirect" ||
+ module.buildMeta.defaultObject === "redirect-warn"
+ ) {
+ exportsInfo.setRedirectNamedTo(innerObject);
+ }
+ }
}
}
@@ -1322,4 +1338,5 @@ module.exports = ModuleGraph;
module.exports.ModuleGraphConnection = ModuleGraphConnection;
module.exports.ExportsInfo = ExportsInfo;
module.exports.ExportInfo = ExportInfo;
+module.exports.SKIP_OVER_NAME = SKIP_OVER_NAME;
module.exports.UsageState = UsageState;
diff --git a/lib/ModuleInfoHeaderPlugin.js b/lib/ModuleInfoHeaderPlugin.js
index d9974518e..1cef3d88a 100644
--- a/lib/ModuleInfoHeaderPlugin.js
+++ b/lib/ModuleInfoHeaderPlugin.js
@@ -33,9 +33,10 @@ const printExportsInfoToSource = (source, indent, exportsInfo) => {
for (const exportInfo of exportsInfo.orderedExports) {
source.add(
Template.toComment(
- `${indent}export ${
- exportInfo.name
- } [${exportInfo.getProvidedInfo()}] [${exportInfo.getUsedInfo()}] [${exportInfo.getRenameInfo()}]`
+ `${indent}export ${JSON.stringify(exportInfo.name).slice(
+ 1,
+ -1
+ )} [${exportInfo.getProvidedInfo()}] [${exportInfo.getUsedInfo()}] [${exportInfo.getRenameInfo()}]`
) + "\n"
);
if (exportInfo.exportsInfo) {
@@ -79,6 +80,14 @@ class ModuleInfoHeaderPlugin {
source.add("/*!****" + reqStrStar + "****!*\\\n");
source.add(" !*** " + reqStr + " ***!\n");
source.add(" \\****" + reqStrStar + "****/\n");
+ const exportsType = module.buildMeta.exportsType;
+ source.add(
+ Template.toComment(
+ exportsType
+ ? `${exportsType} exports`
+ : "unknown exports (runtime-defined)"
+ ) + "\n"
+ );
const exportsInfo = moduleGraph.getExportsInfo(module);
printExportsInfoToSource(source, "", exportsInfo);
source.add(
diff --git a/lib/Parser.js b/lib/Parser.js
index fe59f70e2..5ec26adcc 100644
--- a/lib/Parser.js
+++ b/lib/Parser.js
@@ -13,13 +13,15 @@ const AbstractMethodError = require("./AbstractMethodError");
/** @typedef {Record} PreparsedAst */
/**
- * @typedef {Object} ParserState
+ * @typedef {Object} ParserStateBase
* @property {NormalModule} current
* @property {NormalModule} module
* @property {Compilation} compilation
* @property {TODO} options
*/
+/** @typedef {Record & ParserStateBase} ParserState */
+
class Parser {
/**
* @param {string | Buffer | PreparsedAst} source the source to parse
diff --git a/lib/RuntimeGlobals.js b/lib/RuntimeGlobals.js
index d5783ca6a..3efdb8009 100644
--- a/lib/RuntimeGlobals.js
+++ b/lib/RuntimeGlobals.js
@@ -35,6 +35,16 @@ exports.returnExportsFromRuntime = "return-exports-from-runtime";
*/
exports.module = "module";
+/**
+ * the internal module object
+ */
+exports.moduleId = "module.id";
+
+/**
+ * the internal module object
+ */
+exports.moduleLoaded = "module.loaded";
+
/**
* the bundle public path
*/
diff --git a/lib/RuntimePlugin.js b/lib/RuntimePlugin.js
index ce9243d31..5417b3a2b 100644
--- a/lib/RuntimePlugin.js
+++ b/lib/RuntimePlugin.js
@@ -45,6 +45,11 @@ const GLOBALS_ON_REQUIRE = [
RuntimeGlobals.instantiateWasm
];
+const MODULE_DEPENDENCIES = {
+ [RuntimeGlobals.moduleLoaded]: [RuntimeGlobals.module],
+ [RuntimeGlobals.moduleId]: [RuntimeGlobals.module]
+};
+
const TREE_DEPENDENCIES = {
[RuntimeGlobals.definePropertyGetters]: [RuntimeGlobals.hasOwnProperty],
[RuntimeGlobals.compatGetDefaultExport]: [
@@ -88,6 +93,14 @@ class RuntimePlugin {
for (const dep of deps) set.add(dep);
});
}
+ for (const req of Object.keys(MODULE_DEPENDENCIES)) {
+ const deps = MODULE_DEPENDENCIES[req];
+ compilation.hooks.runtimeRequirementInModule
+ .for(req)
+ .tap("RuntimePlugin", (chunk, set) => {
+ for (const dep of deps) set.add(dep);
+ });
+ }
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.definePropertyGetters)
.tap("RuntimePlugin", chunk => {
diff --git a/lib/RuntimeTemplate.js b/lib/RuntimeTemplate.js
index 69a735280..6f9cd32e5 100644
--- a/lib/RuntimeTemplate.js
+++ b/lib/RuntimeTemplate.js
@@ -326,25 +326,26 @@ class RuntimeTemplate {
request,
weak
});
- const exportsType = module.buildMeta && module.buildMeta.exportsType;
- if (exportsType === "namespace") {
- const rawModule = this.moduleRaw({
- module,
- chunkGraph,
- request,
- weak,
- runtimeRequirements
- });
- return rawModule;
- } else if (strict) {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 1)`;
- } else if (exportsType === "default") {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
- } else {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 7)`;
+ const exportsType = module.getExportsType(strict);
+ switch (exportsType) {
+ case "namespace":
+ return this.moduleRaw({
+ module,
+ chunkGraph,
+ request,
+ weak,
+ runtimeRequirements
+ });
+ case "default-with-named":
+ runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
+ return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
+ case "default-only":
+ case "dynamic-default":
+ runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
+ return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 1)`;
+ case "dynamic":
+ runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
+ return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 7)`;
}
}
@@ -427,54 +428,46 @@ class RuntimeTemplate {
request,
weak
});
- const exportsType = module.buildMeta && module.buildMeta.exportsType;
- if (exportsType === "namespace") {
- if (header) {
- const rawModule = this.moduleRaw({
- module,
- chunkGraph,
- request,
- weak,
- runtimeRequirements
- });
- getModuleFunction = this.basicFunction(
- "",
- `${header}return ${rawModule};`
- );
- } else {
- runtimeRequirements.add(RuntimeGlobals.require);
- getModuleFunction = `__webpack_require__.bind(null, ${comment}${idExpr})`;
- }
- } else if (strict) {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- if (header) {
- const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, 1)`;
- getModuleFunction = header
- ? this.basicFunction("", `${header}return ${returnExpression};`)
- : this.returningFunction(returnExpression);
- } else {
- getModuleFunction = `${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, 1)`;
- }
- } else if (exportsType === "default") {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- if (header) {
- const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, 3)`;
- getModuleFunction = header
- ? this.basicFunction("", `${header}return ${returnExpression};`)
- : this.returningFunction(returnExpression);
- } else {
- getModuleFunction = `${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, 3)`;
- }
- } else {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- if (header) {
- const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, 7)`;
- getModuleFunction = header
- ? this.basicFunction("", `${header}return ${returnExpression};`)
- : this.returningFunction(returnExpression);
- } else {
- getModuleFunction = `${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, 7)`;
- }
+ const exportsType = module.getExportsType(strict);
+ let fakeType = 0;
+ switch (exportsType) {
+ case "namespace":
+ if (header) {
+ const rawModule = this.moduleRaw({
+ module,
+ chunkGraph,
+ request,
+ weak,
+ runtimeRequirements
+ });
+ getModuleFunction = this.basicFunction(
+ "",
+ `${header}return ${rawModule};`
+ );
+ } else {
+ runtimeRequirements.add(RuntimeGlobals.require);
+ getModuleFunction = `__webpack_require__.bind(__webpack_require__, ${comment}${idExpr})`;
+ }
+ break;
+ case "dynamic":
+ fakeType |= 7;
+ /* fall through */
+ case "default-with-named":
+ fakeType |= 3;
+ /* fall through */
+ case "default-only":
+ case "dynamic-default":
+ fakeType |= 1;
+ runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
+ if (header) {
+ const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, ${fakeType})`;
+ getModuleFunction = header
+ ? this.basicFunction("", `${header}return ${returnExpression};`)
+ : this.returningFunction(returnExpression);
+ } else {
+ getModuleFunction = `${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, ${fakeType})`;
+ }
+ break;
}
return `${promise || "Promise.resolve()"}.then(${getModuleFunction})`;
@@ -552,6 +545,7 @@ class RuntimeTemplate {
* @param {boolean} options.asiSafe true, if location is safe for ASI, a bracket can be emitted
* @param {boolean} options.isCall true, if expression will be called
* @param {boolean} options.callContext when false, call context will not be preserved
+ * @param {boolean} options.defaultInterop when true and accessing the default exports, interop code will be generated
* @param {string} options.importVar the identifier name of the import variable
* @param {InitFragment[]} options.initFragments init fragments will be added here
* @param {Set} options.runtimeRequirements if set, will be filled with runtime requirements
@@ -566,6 +560,7 @@ class RuntimeTemplate {
asiSafe,
isCall,
callContext,
+ defaultInterop,
importVar,
initFragments,
runtimeRequirements
@@ -580,26 +575,43 @@ class RuntimeTemplate {
}
const exportsType = module.buildMeta && module.buildMeta.exportsType;
- if (!exportsType) {
- if (exportName.length > 0 && exportName[0] === "default") {
- if (!originModule.buildMeta.strictHarmonyModule) {
- if (isCall) {
- return `${importVar}_default()${propertyAccess(exportName, 1)}`;
- } else if (asiSafe) {
- return `(${importVar}_default()${propertyAccess(exportName, 1)})`;
+ if (defaultInterop) {
+ if (!exportsType) {
+ if (exportName.length > 0 && exportName[0] === "default") {
+ if (!originModule.buildMeta.strictHarmonyModule) {
+ if (isCall) {
+ return `${importVar}_default()${propertyAccess(exportName, 1)}`;
+ } else if (asiSafe) {
+ return `(${importVar}_default()${propertyAccess(exportName, 1)})`;
+ } else {
+ return `${importVar}_default.a${propertyAccess(exportName, 1)}`;
+ }
} else {
- return `${importVar}_default.a${propertyAccess(exportName, 1)}`;
+ return `${importVar}${propertyAccess(exportName, 1)}`;
+ }
+ } else if (originModule.buildMeta.strictHarmonyModule) {
+ if (exportName.length > 0) {
+ return (
+ "/* non-default import from non-esm module */undefined" +
+ propertyAccess(exportName, 1)
+ );
+ } else {
+ runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
+ initFragments.push(
+ new InitFragment(
+ `var ${importVar}_namespace_cache;\n`,
+ InitFragment.STAGE_CONSTANTS,
+ -1,
+ `${importVar}_namespace_cache`
+ )
+ );
+ return `/*#__PURE__*/ (${importVar}_namespace_cache || (${importVar}_namespace_cache = ${RuntimeGlobals.createFakeNamespaceObject}(${importVar})))`;
}
- } else {
- return `${importVar}${propertyAccess(exportName, 1)}`;
}
- } else if (originModule.buildMeta.strictHarmonyModule) {
- if (exportName.length > 0) {
- return (
- "/* non-default import from non-esm module */undefined" +
- propertyAccess(exportName, 1)
- );
- } else {
+ }
+
+ if (exportsType === "default") {
+ if (exportName.length === 0) {
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
initFragments.push(
new InitFragment(
@@ -609,30 +621,20 @@ class RuntimeTemplate {
`${importVar}_namespace_cache`
)
);
- return `/*#__PURE__*/ (${importVar}_namespace_cache || (${importVar}_namespace_cache = ${RuntimeGlobals.createFakeNamespaceObject}(${importVar})))`;
+ const content = `${importVar}_namespace_cache || (${importVar}_namespace_cache = ${
+ RuntimeGlobals.createFakeNamespaceObject
+ }(${importVar}, ${
+ originModule.buildMeta.strictHarmonyModule ? 0 : 2
+ }))`;
+ if (asiSafe) {
+ return `/*#__PURE__*/ (${content})`;
+ } else {
+ return `/*#__PURE__*/ Object(${content})`;
+ }
}
}
}
- if (exportsType === "default") {
- if (exportName.length === 0) {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- initFragments.push(
- new InitFragment(
- `var ${importVar}_namespace_cache;\n`,
- InitFragment.STAGE_CONSTANTS,
- -1,
- `${importVar}_namespace_cache`
- )
- );
- return `/*#__PURE__*/ (${importVar}_namespace_cache || (${importVar}_namespace_cache = ${
- RuntimeGlobals.createFakeNamespaceObject
- }(${importVar}, ${
- originModule.buildMeta.strictHarmonyModule ? 0 : 2
- })))`;
- }
- }
-
if (exportName.length > 0) {
const exportsInfo = moduleGraph.getExportsInfo(module);
const used = exportsInfo.getUsedName(exportName);
diff --git a/lib/SelfModuleFactory.js b/lib/SelfModuleFactory.js
new file mode 100644
index 000000000..b2430a440
--- /dev/null
+++ b/lib/SelfModuleFactory.js
@@ -0,0 +1,21 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+class SelfModuleFactory {
+ constructor(moduleGraph) {
+ this.moduleGraph = moduleGraph;
+ }
+
+ create(data, callback) {
+ const module = this.moduleGraph.getParentModule(data.dependencies[0]);
+ callback(null, {
+ module
+ });
+ }
+}
+
+module.exports = SelfModuleFactory;
diff --git a/lib/Template.js b/lib/Template.js
index 44f274dba..a3ea7a28d 100644
--- a/lib/Template.js
+++ b/lib/Template.js
@@ -27,6 +27,9 @@ const { compareIds } = require("./util/comparators");
const START_LOWERCASE_ALPHABET_CODE = "a".charCodeAt(0);
const START_UPPERCASE_ALPHABET_CODE = "A".charCodeAt(0);
const DELTA_A_TO_Z = "z".charCodeAt(0) - START_LOWERCASE_ALPHABET_CODE + 1;
+const NUMBER_OF_IDENTIFIER_START_CHARS = DELTA_A_TO_Z * 2 + 2; // a-z A-Z _ $
+const NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS =
+ NUMBER_OF_IDENTIFIER_START_CHARS + 10; // a-z A-Z _ $ 0-9
const FUNCTION_CONTENT_REGEX = /^function\s?\(\)\s?\{\r?\n?|\r?\n?\}$/g;
const INDENT_MULTILINE_REGEX = /^\t/gm;
const LINE_SEPARATOR_REGEX = /\r?\n/g;
@@ -124,30 +127,73 @@ class Template {
.replace(MATCH_PADDED_HYPHENS_REPLACE_REGEX, "");
}
- // map number to a single character a-z, A-Z or <_ + number> if number is too big
+ // map number to a single character a-z, A-Z or mulitple characters if number is too big
/**
- *
* @param {number} n number to convert to ident
* @returns {string} returns single character ident
*/
static numberToIdentifier(n) {
+ if (n >= NUMBER_OF_IDENTIFIER_START_CHARS) {
+ // use multiple letters
+ return (
+ Template.numberToIdentifier(n % NUMBER_OF_IDENTIFIER_START_CHARS) +
+ Template.numberToIdentifierContinuation(
+ Math.floor(n / NUMBER_OF_IDENTIFIER_START_CHARS)
+ )
+ );
+ }
+
// lower case
if (n < DELTA_A_TO_Z) {
return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n);
}
+ n -= DELTA_A_TO_Z;
// upper case
- if (n < DELTA_A_TO_Z * 2) {
- return String.fromCharCode(
- START_UPPERCASE_ALPHABET_CODE + n - DELTA_A_TO_Z
+ if (n < DELTA_A_TO_Z) {
+ return String.fromCharCode(START_UPPERCASE_ALPHABET_CODE + n);
+ }
+
+ if (n === DELTA_A_TO_Z) return "_";
+ return "$";
+ }
+
+ /**
+ * @param {number} n number to convert to ident
+ * @returns {string} returns single character ident
+ */
+ static numberToIdentifierContinuation(n) {
+ if (n >= NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS) {
+ // use multiple letters
+ return (
+ Template.numberToIdentifierContinuation(
+ n % NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS
+ ) +
+ Template.numberToIdentifierContinuation(
+ Math.floor(n / NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS)
+ )
);
}
- // use multiple letters
- return (
- Template.numberToIdentifier(n % (2 * DELTA_A_TO_Z)) +
- Template.numberToIdentifier(Math.floor(n / (2 * DELTA_A_TO_Z)))
- );
+ // lower case
+ if (n < DELTA_A_TO_Z) {
+ return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n);
+ }
+ n -= DELTA_A_TO_Z;
+
+ // upper case
+ if (n < DELTA_A_TO_Z) {
+ return String.fromCharCode(START_UPPERCASE_ALPHABET_CODE + n);
+ }
+ n -= DELTA_A_TO_Z;
+
+ // numbers
+ if (n < 10) {
+ return `${n}`;
+ }
+
+ if (n === 10) return "_";
+ return "$";
}
/**
@@ -358,3 +404,5 @@ class Template {
}
module.exports = Template;
+module.exports.NUMBER_OF_IDENTIFIER_START_CHARS = NUMBER_OF_IDENTIFIER_START_CHARS;
+module.exports.NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS = NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS;
diff --git a/lib/WebpackOptionsApply.js b/lib/WebpackOptionsApply.js
index f21ed0d94..2eb27c0e5 100644
--- a/lib/WebpackOptionsApply.js
+++ b/lib/WebpackOptionsApply.js
@@ -18,7 +18,6 @@ const RecordIdsPlugin = require("./RecordIdsPlugin");
const RuntimePlugin = require("./RuntimePlugin");
const APIPlugin = require("./APIPlugin");
-const CommonJsStuffPlugin = require("./CommonJsStuffPlugin");
const CompatibilityPlugin = require("./CompatibilityPlugin");
const ConstPlugin = require("./ConstPlugin");
const ExportsInfoApiPlugin = require("./ExportsInfoApiPlugin");
@@ -341,7 +340,6 @@ class WebpackOptionsApply extends OptionsApply {
const NodeStuffPlugin = require("./NodeStuffPlugin");
new NodeStuffPlugin(options.node).apply(compiler);
}
- new CommonJsStuffPlugin().apply(compiler);
new APIPlugin().apply(compiler);
new ExportsInfoApiPlugin().apply(compiler);
new ConstPlugin().apply(compiler);
diff --git a/lib/dependencies/AMDDefineDependencyParserPlugin.js b/lib/dependencies/AMDDefineDependencyParserPlugin.js
index a5bdb4655..817ab225b 100644
--- a/lib/dependencies/AMDDefineDependencyParserPlugin.js
+++ b/lib/dependencies/AMDDefineDependencyParserPlugin.js
@@ -12,6 +12,7 @@ const AMDRequireContextDependency = require("./AMDRequireContextDependency");
const AMDRequireItemDependency = require("./AMDRequireItemDependency");
const ConstDependency = require("./ConstDependency");
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
+const DynamicExports = require("./DynamicExports");
const LocalModuleDependency = require("./LocalModuleDependency");
const { addLocalModule, getLocalModule } = require("./LocalModulesHelpers");
@@ -217,6 +218,7 @@ class AMDDefineDependencyParserPlugin {
default:
return;
}
+ DynamicExports.bailout(parser.state);
let fnParams = null;
let fnParamsOffset = 0;
if (fn) {
diff --git a/lib/dependencies/CommonJsExportsDependency.js b/lib/dependencies/CommonJsExportsDependency.js
new file mode 100644
index 000000000..29a3f3ec0
--- /dev/null
+++ b/lib/dependencies/CommonJsExportsDependency.js
@@ -0,0 +1,182 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const InitFragment = require("../InitFragment");
+const { UsageState } = require("../ModuleGraph");
+const RuntimeGlobals = require("../RuntimeGlobals");
+const makeSerializable = require("../util/makeSerializable");
+const propertyAccess = require("../util/propertyAccess");
+const NullDependency = require("./NullDependency");
+
+/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
+/** @typedef {import("../Dependency")} Dependency */
+/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
+/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
+/** @typedef {import("../ModuleGraph")} ModuleGraph */
+
+class CommonJsExportsDependency extends NullDependency {
+ constructor(range, base, names) {
+ super();
+ this.range = range;
+ this.base = base;
+ this.names = names;
+ }
+
+ get type() {
+ return "cjs exports";
+ }
+
+ /**
+ * Returns the exported names
+ * @param {ModuleGraph} moduleGraph module graph
+ * @returns {ExportsSpec | undefined} export names
+ */
+ getExports(moduleGraph) {
+ return {
+ exports: [this.names[0]],
+ dependencies: undefined
+ };
+ }
+
+ serialize(context) {
+ const { write } = context;
+ write(this.range);
+ write(this.base);
+ write(this.names);
+ super.serialize(context);
+ }
+
+ deserialize(context) {
+ const { read } = context;
+ this.range = read();
+ this.base = read();
+ this.names = read();
+ super.deserialize(context);
+ }
+}
+
+makeSerializable(
+ CommonJsExportsDependency,
+ "webpack/lib/dependencies/CommonJsExportsDependency"
+);
+
+CommonJsExportsDependency.Template = class CommonJsExportsDependencyTemplate extends NullDependency.Template {
+ /**
+ * @param {Dependency} dependency the dependency for which the template should be applied
+ * @param {ReplaceSource} source the current replace source which can be modified
+ * @param {DependencyTemplateContext} templateContext the context object
+ * @returns {void}
+ */
+ apply(
+ dependency,
+ source,
+ { module, moduleGraph, initFragments, runtimeRequirements }
+ ) {
+ const dep = /** @type {CommonJsExportsDependency} */ (dependency);
+ let used;
+ if (module.buildMeta.exportsType === "default") {
+ const defaultInfo = moduleGraph.getExportInfo(module, "default");
+ if (defaultInfo.used === UsageState.Used) {
+ used = dep.names;
+ } else {
+ used = defaultInfo.exportsInfo.getUsedName(dep.names);
+ }
+ } else {
+ used = moduleGraph.getExportsInfo(module).getUsedName(dep.names);
+ }
+
+ let base = undefined;
+ let type;
+ switch (dep.base) {
+ case "exports":
+ runtimeRequirements.add(RuntimeGlobals.exports);
+ base = module.exportsArgument;
+ type = "expression";
+ break;
+ case "module.exports":
+ runtimeRequirements.add(RuntimeGlobals.module);
+ base = `${module.moduleArgument}.exports`;
+ type = "expression";
+ break;
+ case "this":
+ runtimeRequirements.add(RuntimeGlobals.thisAsExports);
+ base = "this";
+ type = "expression";
+ break;
+ case "Object.defineProperty(exports)":
+ runtimeRequirements.add(RuntimeGlobals.exports);
+ base = module.exportsArgument;
+ type = "Object.defineProperty";
+ break;
+ case "Object.defineProperty(module.exports)":
+ runtimeRequirements.add(RuntimeGlobals.module);
+ base = `${module.moduleArgument}.exports`;
+ type = "Object.defineProperty";
+ break;
+ case "Object.defineProperty(this)":
+ runtimeRequirements.add(RuntimeGlobals.thisAsExports);
+ base = "this";
+ type = "Object.defineProperty";
+ break;
+ default:
+ throw new Error(`Unsupported base ${dep.base}`);
+ }
+
+ switch (type) {
+ case "expression":
+ if (!used) {
+ initFragments.push(
+ new InitFragment(
+ "var __webpack_unused_export__;\n",
+ InitFragment.STAGE_CONSTANTS,
+ 0,
+ "__webpack_unused_export__"
+ )
+ );
+ source.replace(
+ dep.range[0],
+ dep.range[1] - 1,
+ "__webpack_unused_export__"
+ );
+ return;
+ }
+ source.replace(
+ dep.range[0],
+ dep.range[1] - 1,
+ `${base}${propertyAccess(used)}`
+ );
+ return;
+ case "Object.defineProperty":
+ if (!used) {
+ initFragments.push(
+ new InitFragment(
+ "var __webpack_unused_export__;\n",
+ InitFragment.STAGE_CONSTANTS,
+ 0,
+ "__webpack_unused_export__"
+ )
+ );
+ source.replace(
+ dep.range[0],
+ dep.range[1] - 1,
+ "__webpack_unused_export__ = ("
+ );
+ return;
+ }
+ source.replace(
+ dep.range[0],
+ dep.range[1] - 1,
+ `Object.defineProperty(${base}${propertyAccess(
+ used.slice(0, -1)
+ )}, ${JSON.stringify(used[used.length - 1])}, `
+ );
+ return;
+ }
+ }
+};
+
+module.exports = CommonJsExportsDependency;
diff --git a/lib/dependencies/CommonJsExportsParserPlugin.js b/lib/dependencies/CommonJsExportsParserPlugin.js
new file mode 100644
index 000000000..a33cfd279
--- /dev/null
+++ b/lib/dependencies/CommonJsExportsParserPlugin.js
@@ -0,0 +1,231 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const RuntimeGlobals = require("../RuntimeGlobals");
+const { evaluateToString } = require("../javascript/JavascriptParserHelpers");
+const CommonJsExportsDependency = require("./CommonJsExportsDependency");
+const CommonJsSelfReferenceDependency = require("./CommonJsSelfReferenceDependency");
+const DynamicExports = require("./DynamicExports");
+const HarmonyExports = require("./HarmonyExports");
+const ModuleDecoratorDependency = require("./ModuleDecoratorDependency");
+
+/** @typedef {import("../NormalModule")} NormalModule */
+/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
+
+/** @type {WeakMap} */
+const moduleExportsState = new WeakMap();
+
+const getValueOfPropertyDescription = expr => {
+ if (expr.type !== "ObjectExpression") return;
+ for (const property of expr.properties) {
+ if (property.computed) continue;
+ const key = property.key;
+ if (key.type !== "Identifier" || key.name !== "value") continue;
+ return property.value;
+ }
+};
+
+const isTruthyLiteral = expr => {
+ switch (expr.type) {
+ case "Literal":
+ return !!expr.value;
+ case "UnaryExpression":
+ if (expr.operator === "!") return isFalsyLiteral(expr.argument);
+ }
+ return false;
+};
+
+const isFalsyLiteral = expr => {
+ switch (expr.type) {
+ case "Literal":
+ return !expr.value;
+ case "UnaryExpression":
+ if (expr.operator === "!") return isTruthyLiteral(expr.argument);
+ }
+ return false;
+};
+
+class CommonJsExportsParserPlugin {
+ static bailout(module) {
+ const value = moduleExportsState.get(module);
+ moduleExportsState.set(module, false);
+ if (value === true) {
+ module.buildMeta.exportsType = undefined;
+ module.buildMeta.defaultObject = false;
+ }
+ }
+
+ /**
+ * @param {JavascriptParser} parser the parser
+ */
+ apply(parser) {
+ const enableStructuredExports = () => {
+ DynamicExports.enable(parser.state);
+ };
+ const checkNamespace = (members, valueExpr) => {
+ if (!DynamicExports.isEnabled(parser.state)) return;
+ if (members.length > 0 && members[0] === "__esModule") {
+ if (isTruthyLiteral(valueExpr)) {
+ DynamicExports.setFlagged(parser.state);
+ } else {
+ DynamicExports.bailout(parser.state);
+ }
+ }
+ };
+ const bailout = () => {
+ DynamicExports.bailout(parser.state);
+ };
+
+ // metadata //
+ parser.hooks.evaluateTypeof
+ .for("module")
+ .tap("CommonJsExportsParserPlugin", evaluateToString("object"));
+ parser.hooks.evaluateTypeof
+ .for("exports")
+ .tap("CommonJsPlugin", evaluateToString("object"));
+
+ // exporting //
+ parser.hooks.assignMemberChain
+ .for("exports")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ if (HarmonyExports.isEnabled(parser.state)) return;
+ enableStructuredExports();
+ checkNamespace(members, expr.right);
+ const dep = new CommonJsExportsDependency(
+ expr.left.range,
+ "exports",
+ members
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ });
+ parser.hooks.assignMemberChain
+ .for("this")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ if (HarmonyExports.isEnabled(parser.state)) return;
+ if (!parser.scope.topLevelScope) return;
+ enableStructuredExports();
+ checkNamespace(members, expr.right);
+ const dep = new CommonJsExportsDependency(
+ expr.left.range,
+ "this",
+ members
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ });
+ parser.hooks.assignMemberChain
+ .for("module")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ if (HarmonyExports.isEnabled(parser.state)) return;
+ if (members[0] !== "exports" || members.length <= 1) return;
+ enableStructuredExports();
+ checkNamespace(members, expr.right);
+ const dep = new CommonJsExportsDependency(
+ expr.left.range,
+ "module.exports",
+ members.slice(1)
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ });
+ parser.hooks.call
+ .for("Object.defineProperty")
+ .tap("CommonJsExportsParserPlugin", expression => {
+ const expr = /** @type {import("estree").CallExpression} */ (expression);
+ if (expr.arguments.length !== 3) return;
+ if (expr.arguments[0].type === "SpreadElement") return;
+ if (expr.arguments[1].type === "SpreadElement") return;
+ if (expr.arguments[2].type === "SpreadElement") return;
+ const exportsArg = parser.evaluateExpression(expr.arguments[0]);
+ if (!exportsArg || !exportsArg.isIdentifier()) return;
+ if (
+ exportsArg.identifier !== "exports" &&
+ exportsArg.identifier !== "module.exports" &&
+ exportsArg.identifier !== "this"
+ ) {
+ return;
+ }
+ const propertyArg = parser.evaluateExpression(expr.arguments[1]);
+ if (!propertyArg) return;
+ const property = propertyArg.asString();
+ if (typeof property !== "string") return;
+ enableStructuredExports();
+ const descArg = expr.arguments[2];
+ checkNamespace([property], getValueOfPropertyDescription(descArg));
+ const dep = new CommonJsExportsDependency(
+ [expr.callee.range[0], expr.arguments[2].range[0]],
+ `Object.defineProperty(${exportsArg.identifier})`,
+ [property]
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+
+ parser.walkExpression(expr.arguments[2]);
+ return true;
+ });
+
+ // Self reference //
+ parser.hooks.expression
+ .for("exports")
+ .tap("CommonJsExportsParserPlugin", expr => {
+ if (HarmonyExports.isEnabled(parser.state)) return;
+ bailout();
+ const dep = new CommonJsSelfReferenceDependency(
+ expr.range,
+ "exports",
+ []
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ });
+ parser.hooks.expression
+ .for("module.exports")
+ .tap("CommonJsExportsParserPlugin", expr => {
+ if (HarmonyExports.isEnabled(parser.state)) return;
+ bailout();
+ const dep = new CommonJsSelfReferenceDependency(
+ expr.range,
+ "module.exports",
+ []
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ });
+ parser.hooks.expression
+ .for("this")
+ .tap("CommonJsExportsParserPlugin", expr => {
+ if (HarmonyExports.isEnabled(parser.state)) return;
+ if (!parser.scope.topLevelScope) return;
+ bailout();
+ const dep = new CommonJsSelfReferenceDependency(expr.range, "this", []);
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ });
+
+ // Bailouts //
+ parser.hooks.expression.for("module").tap("CommonJsPlugin", expr => {
+ bailout();
+ const isHarmony = HarmonyExports.isEnabled(parser.state);
+ const dep = new ModuleDecoratorDependency(
+ isHarmony
+ ? RuntimeGlobals.harmonyModuleDecorator
+ : RuntimeGlobals.nodeModuleDecorator
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ });
+ }
+}
+module.exports = CommonJsExportsParserPlugin;
diff --git a/lib/dependencies/CommonJsFullRequireDependency.js b/lib/dependencies/CommonJsFullRequireDependency.js
new file mode 100644
index 000000000..ef57bd072
--- /dev/null
+++ b/lib/dependencies/CommonJsFullRequireDependency.js
@@ -0,0 +1,121 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const makeSerializable = require("../util/makeSerializable");
+const ModuleDependency = require("./ModuleDependency");
+
+/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
+/** @typedef {import("../Dependency")} Dependency */
+/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
+/** @typedef {import("../ModuleGraph")} ModuleGraph */
+
+class CommonJsFullRequireDependency extends ModuleDependency {
+ /**
+ * @param {string} request the request string
+ * @param {[number, number]} range location in source code
+ * @param {string[]} names accessed properties on module
+ */
+ constructor(request, range, names) {
+ super(request);
+ this.range = range;
+ this.names = names;
+ this.call = false;
+ this.asiSafe = false;
+ }
+
+ /**
+ * Returns list of exports referenced by this dependency
+ * @param {ModuleGraph} moduleGraph module graph
+ * @returns {string[][]} referenced exports
+ */
+ getReferencedExports(moduleGraph) {
+ if (this.call) {
+ const importedModule = moduleGraph.getModule(this);
+ if (
+ !importedModule ||
+ importedModule.getExportsType(false) !== "namespace"
+ ) {
+ return [this.names.slice(0, -1)];
+ }
+ }
+ return [this.names];
+ }
+
+ serialize(context) {
+ const { write } = context;
+ write(this.names);
+ write(this.call);
+ write(this.asiSafe);
+ super.serialize(context);
+ }
+
+ deserialize(context) {
+ const { read } = context;
+ this.names = read();
+ this.call = read();
+ this.asiSafe = read();
+ super.deserialize(context);
+ }
+
+ get type() {
+ return "cjs full require";
+ }
+}
+
+CommonJsFullRequireDependency.Template = class CommonJsFullRequireDependencyTemplate extends ModuleDependency.Template {
+ /**
+ * @param {Dependency} dependency the dependency for which the template should be applied
+ * @param {ReplaceSource} source the current replace source which can be modified
+ * @param {DependencyTemplateContext} templateContext the context object
+ * @returns {void}
+ */
+ apply(
+ dependency,
+ source,
+ {
+ module,
+ runtimeTemplate,
+ moduleGraph,
+ chunkGraph,
+ runtimeRequirements,
+ initFragments
+ }
+ ) {
+ const dep = /** @type {CommonJsFullRequireDependency} */ (dependency);
+ if (!dep.range) return;
+ const importedModule = moduleGraph.getModule(dep);
+ const exports = runtimeTemplate.moduleExports({
+ module: importedModule,
+ chunkGraph,
+ request: dep.request,
+ weak: dep.weak,
+ runtimeRequirements
+ });
+ const exportExpr = runtimeTemplate.exportFromImport({
+ moduleGraph,
+ module: importedModule,
+ request: dep.request,
+ exportName: dep.names,
+ originModule: module,
+ asiSafe: dep.asiSafe,
+ isCall: dep.call,
+ callContext: undefined,
+ defaultInterop: false,
+ importVar: exports,
+ initFragments,
+ runtimeRequirements
+ });
+ source.replace(dep.range[0], dep.range[1] - 1, exportExpr);
+ }
+};
+
+makeSerializable(
+ CommonJsFullRequireDependency,
+ "webpack/lib/dependencies/CommonJsFullRequireDependency"
+);
+
+module.exports = CommonJsFullRequireDependency;
diff --git a/lib/dependencies/CommonJsImportsParserPlugin.js b/lib/dependencies/CommonJsImportsParserPlugin.js
new file mode 100644
index 000000000..d321bd928
--- /dev/null
+++ b/lib/dependencies/CommonJsImportsParserPlugin.js
@@ -0,0 +1,340 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const RuntimeGlobals = require("../RuntimeGlobals");
+const {
+ evaluateToIdentifier,
+ evaluateToString,
+ expressionIsUnsupported,
+ toConstantDependency
+} = require("../javascript/JavascriptParserHelpers");
+const CommonJsFullRequireDependency = require("./CommonJsFullRequireDependency");
+const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
+const CommonJsRequireDependency = require("./CommonJsRequireDependency");
+const ConstDependency = require("./ConstDependency");
+const ContextDependencyHelpers = require("./ContextDependencyHelpers");
+const LocalModuleDependency = require("./LocalModuleDependency");
+const { getLocalModule } = require("./LocalModulesHelpers");
+const RequireHeaderDependency = require("./RequireHeaderDependency");
+const RequireResolveContextDependency = require("./RequireResolveContextDependency");
+const RequireResolveDependency = require("./RequireResolveDependency");
+const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
+
+class CommonJsImportsParserPlugin {
+ constructor(options) {
+ this.options = options;
+ }
+
+ apply(parser) {
+ const options = this.options;
+
+ // metadata //
+ const tapRequireExpression = (expression, getMembers) => {
+ parser.hooks.typeof
+ .for(expression)
+ .tap(
+ "CommonJsPlugin",
+ toConstantDependency(parser, JSON.stringify("function"))
+ );
+ parser.hooks.evaluateTypeof
+ .for(expression)
+ .tap("CommonJsPlugin", evaluateToString("function"));
+ parser.hooks.evaluateIdentifier
+ .for(expression)
+ .tap(
+ "CommonJsPlugin",
+ evaluateToIdentifier(expression, "require", getMembers, true)
+ );
+ };
+ tapRequireExpression("require", () => []);
+ tapRequireExpression("require.resolve", () => ["resolve"]);
+ tapRequireExpression("require.resolveWeak", () => ["resolveWeak"]);
+
+ // Weird stuff //
+ parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => {
+ // to not leak to global "require", we need to define a local require here.
+ const dep = new ConstDependency("var require;", 0);
+ dep.loc = expr.loc;
+ parser.state.module.addPresentationalDependency(dep);
+ return true;
+ });
+
+ // Unsupported //
+ parser.hooks.expression
+ .for("require.main.require")
+ .tap(
+ "CommonJsPlugin",
+ expressionIsUnsupported(
+ parser,
+ "require.main.require is not supported by webpack."
+ )
+ );
+ parser.hooks.call
+ .for("require.main.require")
+ .tap(
+ "CommonJsPlugin",
+ expressionIsUnsupported(
+ parser,
+ "require.main.require is not supported by webpack."
+ )
+ );
+ parser.hooks.expression
+ .for("module.parent.require")
+ .tap(
+ "CommonJsPlugin",
+ expressionIsUnsupported(
+ parser,
+ "module.parent.require is not supported by webpack."
+ )
+ );
+ parser.hooks.call
+ .for("module.parent.require")
+ .tap(
+ "CommonJsPlugin",
+ expressionIsUnsupported(
+ parser,
+ "module.parent.require is not supported by webpack."
+ )
+ );
+
+ // renaming //
+ parser.hooks.canRename.for("require").tap("CommonJsPlugin", () => true);
+ parser.hooks.rename.for("require").tap("CommonJsPlugin", expr => {
+ // To avoid "not defined" error, replace the value with undefined
+ const dep = new ConstDependency("undefined", expr.range);
+ dep.loc = expr.loc;
+ parser.state.module.addPresentationalDependency(dep);
+ return false;
+ });
+
+ // inspection //
+ parser.hooks.expression
+ .for("require.cache")
+ .tap(
+ "CommonJsImportsParserPlugin",
+ toConstantDependency(parser, RuntimeGlobals.moduleCache, [
+ RuntimeGlobals.moduleCache,
+ RuntimeGlobals.moduleId,
+ RuntimeGlobals.moduleLoaded
+ ])
+ );
+
+ // require as expression //
+ parser.hooks.expression
+ .for("require")
+ .tap("CommonJsImportsParserPlugin", expr => {
+ const dep = new CommonJsRequireContextDependency(
+ {
+ request: options.unknownContextRequest,
+ recursive: options.unknownContextRecursive,
+ regExp: options.unknownContextRegExp,
+ mode: "sync"
+ },
+ expr.range
+ );
+ dep.critical =
+ options.unknownContextCritical &&
+ "require function is used in a way in which dependencies cannot be statically extracted";
+ dep.loc = expr.loc;
+ dep.optional = !!parser.scope.inTry;
+ parser.state.current.addDependency(dep);
+ return true;
+ });
+
+ // require //
+ const processRequireItem = (expr, param) => {
+ if (param.isString()) {
+ const dep = new CommonJsRequireDependency(param.string, param.range);
+ dep.loc = expr.loc;
+ dep.optional = !!parser.scope.inTry;
+ parser.state.current.addDependency(dep);
+ return true;
+ }
+ };
+ const processRequireContext = (expr, param) => {
+ const dep = ContextDependencyHelpers.create(
+ CommonJsRequireContextDependency,
+ expr.range,
+ param,
+ expr,
+ options,
+ {},
+ parser
+ );
+ if (!dep) return;
+ dep.loc = expr.loc;
+ dep.optional = !!parser.scope.inTry;
+ parser.state.current.addDependency(dep);
+ return true;
+ };
+
+ const createRequireHandler = callNew => expr => {
+ if (expr.arguments.length !== 1) return;
+ let localModule;
+ const param = parser.evaluateExpression(expr.arguments[0]);
+ if (param.isConditional()) {
+ let isExpression = false;
+ for (const p of param.options) {
+ const result = processRequireItem(expr, p);
+ if (result === undefined) {
+ isExpression = true;
+ }
+ }
+ if (!isExpression) {
+ const dep = new RequireHeaderDependency(expr.callee.range);
+ dep.loc = expr.loc;
+ parser.state.module.addPresentationalDependency(dep);
+ return true;
+ }
+ }
+ if (
+ param.isString() &&
+ (localModule = getLocalModule(parser.state, param.string))
+ ) {
+ localModule.flagUsed();
+ const dep = new LocalModuleDependency(localModule, expr.range, callNew);
+ dep.loc = expr.loc;
+ parser.state.module.addPresentationalDependency(dep);
+ return true;
+ } else {
+ const result = processRequireItem(expr, param);
+ if (result === undefined) {
+ processRequireContext(expr, param);
+ } else {
+ const dep = new RequireHeaderDependency(expr.callee.range);
+ dep.loc = expr.loc;
+ parser.state.module.addPresentationalDependency(dep);
+ }
+ return true;
+ }
+ };
+ parser.hooks.call
+ .for("require")
+ .tap("CommonJsImportsParserPlugin", createRequireHandler(false));
+ parser.hooks.new
+ .for("require")
+ .tap("CommonJsImportsParserPlugin", createRequireHandler(true));
+ parser.hooks.call
+ .for("module.require")
+ .tap("CommonJsImportsParserPlugin", createRequireHandler(false));
+ parser.hooks.new
+ .for("module.require")
+ .tap("CommonJsImportsParserPlugin", createRequireHandler(true));
+
+ // require with property access //
+ const chainHandler = (expr, calleeMembers, callExpr, members) => {
+ if (callExpr.arguments.length !== 1) return;
+ const param = parser.evaluateExpression(callExpr.arguments[0]);
+ if (param.isString() && !getLocalModule(parser.state, param.string)) {
+ const dep = new CommonJsFullRequireDependency(
+ param.string,
+ expr.range,
+ members
+ );
+ dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ }
+ };
+ const callChainHandler = (expr, calleeMembers, callExpr, members) => {
+ if (callExpr.arguments.length !== 1) return;
+ const param = parser.evaluateExpression(callExpr.arguments[0]);
+ if (param.isString() && !getLocalModule(parser.state, param.string)) {
+ const dep = new CommonJsFullRequireDependency(
+ param.string,
+ expr.callee.range,
+ members
+ );
+ dep.call = true;
+ dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
+ dep.loc = expr.callee.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ }
+ };
+ parser.hooks.memberChainOfCallMemberChain
+ .for("require")
+ .tap("CommonJsImportsParserPlugin", chainHandler);
+ parser.hooks.memberChainOfCallMemberChain
+ .for("module.require")
+ .tap("CommonJsImportsParserPlugin", chainHandler);
+ parser.hooks.callMemberChainOfCallMemberChain
+ .for("require")
+ .tap("CommonJsImportsParserPlugin", callChainHandler);
+ parser.hooks.callMemberChainOfCallMemberChain
+ .for("module.require")
+ .tap("CommonJsImportsParserPlugin", callChainHandler);
+
+ // require.resolve //
+ const processResolve = (expr, weak) => {
+ if (expr.arguments.length !== 1) return;
+ const param = parser.evaluateExpression(expr.arguments[0]);
+ if (param.isConditional()) {
+ for (const option of param.options) {
+ const result = processResolveItem(expr, option, weak);
+ if (result === undefined) {
+ processResolveContext(expr, option, weak);
+ }
+ }
+ const dep = new RequireResolveHeaderDependency(expr.callee.range);
+ dep.loc = expr.loc;
+ parser.state.module.addPresentationalDependency(dep);
+ return true;
+ } else {
+ const result = processResolveItem(expr, param, weak);
+ if (result === undefined) {
+ processResolveContext(expr, param, weak);
+ }
+ const dep = new RequireResolveHeaderDependency(expr.callee.range);
+ dep.loc = expr.loc;
+ parser.state.module.addPresentationalDependency(dep);
+ return true;
+ }
+ };
+ const processResolveItem = (expr, param, weak) => {
+ if (param.isString()) {
+ const dep = new RequireResolveDependency(param.string, param.range);
+ dep.loc = expr.loc;
+ dep.optional = !!parser.scope.inTry;
+ dep.weak = weak;
+ parser.state.current.addDependency(dep);
+ return true;
+ }
+ };
+ const processResolveContext = (expr, param, weak) => {
+ const dep = ContextDependencyHelpers.create(
+ RequireResolveContextDependency,
+ param.range,
+ param,
+ expr,
+ options,
+ {
+ mode: weak ? "weak" : "sync"
+ },
+ parser
+ );
+ if (!dep) return;
+ dep.loc = expr.loc;
+ dep.optional = !!parser.scope.inTry;
+ parser.state.current.addDependency(dep);
+ return true;
+ };
+
+ parser.hooks.call
+ .for("require.resolve")
+ .tap("RequireResolveDependencyParserPlugin", expr => {
+ return processResolve(expr, false);
+ });
+ parser.hooks.call
+ .for("require.resolveWeak")
+ .tap("RequireResolveDependencyParserPlugin", expr => {
+ return processResolve(expr, true);
+ });
+ }
+}
+module.exports = CommonJsImportsParserPlugin;
diff --git a/lib/dependencies/CommonJsPlugin.js b/lib/dependencies/CommonJsPlugin.js
index 543165d29..753a8a5f4 100644
--- a/lib/dependencies/CommonJsPlugin.js
+++ b/lib/dependencies/CommonJsPlugin.js
@@ -5,22 +5,27 @@
"use strict";
+const RuntimeGlobals = require("../RuntimeGlobals");
+const RuntimeModule = require("../RuntimeModule");
+const SelfModuleFactory = require("../SelfModuleFactory");
+const Template = require("../Template");
+const CommonJsExportsDependency = require("./CommonJsExportsDependency");
+const CommonJsFullRequireDependency = require("./CommonJsFullRequireDependency");
const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
const CommonJsRequireDependency = require("./CommonJsRequireDependency");
-const ConstDependency = require("./ConstDependency");
+const CommonJsSelfReferenceDependency = require("./CommonJsSelfReferenceDependency");
+const ModuleDecoratorDependency = require("./ModuleDecoratorDependency");
const RequireHeaderDependency = require("./RequireHeaderDependency");
const RequireResolveContextDependency = require("./RequireResolveContextDependency");
const RequireResolveDependency = require("./RequireResolveDependency");
const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
+const RuntimeRequirementsDependency = require("./RuntimeRequirementsDependency");
-const CommonJsRequireDependencyParserPlugin = require("./CommonJsRequireDependencyParserPlugin");
-const RequireResolveDependencyParserPlugin = require("./RequireResolveDependencyParserPlugin");
-
-const RuntimeGlobals = require("../RuntimeGlobals");
+const CommonJsExportsParserPlugin = require("./CommonJsExportsParserPlugin");
+const CommonJsImportsParserPlugin = require("./CommonJsImportsParserPlugin");
const {
evaluateToIdentifier,
- evaluateToString,
toConstantDependency
} = require("../javascript/JavascriptParserHelpers");
@@ -43,6 +48,15 @@ class CommonJsPlugin {
new CommonJsRequireDependency.Template()
);
+ compilation.dependencyFactories.set(
+ CommonJsFullRequireDependency,
+ normalModuleFactory
+ );
+ compilation.dependencyTemplates.set(
+ CommonJsFullRequireDependency,
+ new CommonJsFullRequireDependency.Template()
+ );
+
compilation.dependencyFactories.set(
CommonJsRequireContextDependency,
contextModuleFactory
@@ -80,72 +94,116 @@ class CommonJsPlugin {
new RequireHeaderDependency.Template()
);
+ compilation.dependencyTemplates.set(
+ CommonJsExportsDependency,
+ new CommonJsExportsDependency.Template()
+ );
+
+ const selfFactory = new SelfModuleFactory(compilation.moduleGraph);
+
+ compilation.dependencyFactories.set(
+ CommonJsSelfReferenceDependency,
+ selfFactory
+ );
+ compilation.dependencyTemplates.set(
+ CommonJsSelfReferenceDependency,
+ new CommonJsSelfReferenceDependency.Template()
+ );
+
+ compilation.dependencyFactories.set(
+ ModuleDecoratorDependency,
+ selfFactory
+ );
+ compilation.dependencyTemplates.set(
+ ModuleDecoratorDependency,
+ new ModuleDecoratorDependency.Template()
+ );
+
+ compilation.hooks.runtimeRequirementInModule
+ .for(RuntimeGlobals.harmonyModuleDecorator)
+ .tap("CommonJsPlugin", (module, set) => {
+ set.add(RuntimeGlobals.module);
+ set.add(RuntimeGlobals.requireScope);
+ });
+
+ compilation.hooks.runtimeRequirementInModule
+ .for(RuntimeGlobals.nodeModuleDecorator)
+ .tap("CommonJsPlugin", (module, set) => {
+ set.add(RuntimeGlobals.module);
+ set.add(RuntimeGlobals.requireScope);
+ });
+
+ compilation.hooks.runtimeRequirementInTree
+ .for(RuntimeGlobals.harmonyModuleDecorator)
+ .tap("CommonJsPlugin", (chunk, set) => {
+ compilation.addRuntimeModule(
+ chunk,
+ new HarmonyModuleDecoratorRuntimeModule()
+ );
+ });
+
+ compilation.hooks.runtimeRequirementInTree
+ .for(RuntimeGlobals.nodeModuleDecorator)
+ .tap("CommonJsPlugin", (chunk, set) => {
+ compilation.addRuntimeModule(
+ chunk,
+ new NodeModuleDecoratorRuntimeModule()
+ );
+ });
+
const handler = (parser, parserOptions) => {
if (parserOptions.commonjs !== undefined && !parserOptions.commonjs)
return;
-
- const tapRequireExpression = (expression, getMembers) => {
- parser.hooks.typeof
- .for(expression)
- .tap(
- "CommonJsPlugin",
- toConstantDependency(parser, JSON.stringify("function"))
- );
- parser.hooks.evaluateTypeof
- .for(expression)
- .tap("CommonJsPlugin", evaluateToString("function"));
- parser.hooks.evaluateIdentifier
- .for(expression)
- .tap(
- "CommonJsPlugin",
- evaluateToIdentifier(expression, "require", getMembers, true)
- );
- };
- tapRequireExpression("require", () => []);
- tapRequireExpression("require.resolve", () => ["resolve"]);
- tapRequireExpression("require.resolveWeak", () => ["resolveWeak"]);
-
- parser.hooks.evaluateTypeof
- .for("module")
- .tap("CommonJsPlugin", evaluateToString("object"));
- parser.hooks.expression.for("exports").tap("CommonJsPlugin", expr => {
- const module = parser.state.module;
- const isHarmony = module.buildMeta && module.buildMeta.exportsType;
- if (!isHarmony) {
- return toConstantDependency(parser, module.exportsArgument, [
- RuntimeGlobals.exports
- ])(expr);
- }
- });
- parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => {
- // to not leak to global "require", we need to define a local require here.
- const dep = new ConstDependency("var require;", 0);
- dep.loc = expr.loc;
- parser.state.module.addPresentationalDependency(dep);
- return true;
- });
- parser.hooks.canRename
- .for("require")
- .tap("CommonJsPlugin", () => true);
- parser.hooks.rename.for("require").tap("CommonJsPlugin", expr => {
- // To avoid "not defined" error, replace the value with undefined
- const dep = new ConstDependency("undefined", expr.range);
- dep.loc = expr.loc;
- parser.state.module.addPresentationalDependency(dep);
- return false;
- });
parser.hooks.typeof
.for("module")
.tap(
"CommonJsPlugin",
toConstantDependency(parser, JSON.stringify("object"))
);
- parser.hooks.evaluateTypeof
- .for("exports")
- .tap("CommonJsPlugin", evaluateToString("object"));
- new CommonJsRequireDependencyParserPlugin(options).apply(parser);
- new RequireResolveDependencyParserPlugin(options).apply(parser);
+ parser.hooks.expression
+ .for("require.main")
+ .tap(
+ "CommonJsPlugin",
+ toConstantDependency(
+ parser,
+ `${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}]`,
+ [RuntimeGlobals.moduleCache, RuntimeGlobals.entryModuleId]
+ )
+ );
+ parser.hooks.expression
+ .for("module.loaded")
+ .tap("CommonJsPlugin", expr => {
+ parser.state.module.buildMeta.moduleConcatenationBailout =
+ "module.loaded";
+ const dep = new RuntimeRequirementsDependency([
+ RuntimeGlobals.moduleLoaded
+ ]);
+ dep.loc = expr.loc;
+ parser.state.module.addPresentationalDependency(dep);
+ return true;
+ });
+
+ parser.hooks.expression
+ .for("module.id")
+ .tap("CommonJsPlugin", expr => {
+ parser.state.module.buildMeta.moduleConcatenationBailout =
+ "module.id";
+ const dep = new RuntimeRequirementsDependency([
+ RuntimeGlobals.moduleId
+ ]);
+ dep.loc = expr.loc;
+ parser.state.module.addPresentationalDependency(dep);
+ return true;
+ });
+
+ parser.hooks.evaluateIdentifier.for("module.hot").tap(
+ "CommonJsPlugin",
+ evaluateToIdentifier("module.hot", "module", () => ["hot"], false)
+ );
+
+ new CommonJsImportsParserPlugin(options).apply(parser);
+ new CommonJsExportsParserPlugin().apply(parser);
};
normalModuleFactory.hooks.parser
@@ -158,4 +216,57 @@ class CommonJsPlugin {
);
}
}
+
+class HarmonyModuleDecoratorRuntimeModule extends RuntimeModule {
+ constructor() {
+ super("harmony module decorator");
+ }
+
+ /**
+ * @returns {string} runtime code
+ */
+ generate() {
+ const { runtimeTemplate } = this.compilation;
+ return Template.asString([
+ `${
+ RuntimeGlobals.harmonyModuleDecorator
+ } = ${runtimeTemplate.basicFunction("module", [
+ "module = Object.create(module);",
+ "if (!module.children) module.children = [];",
+ "Object.defineProperty(module, 'exports', {",
+ Template.indent([
+ "enumerable: true,",
+ `set: ${runtimeTemplate.basicFunction("", [
+ "throw new Error('ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id);"
+ ])}`
+ ]),
+ "});",
+ "return module;"
+ ])};`
+ ]);
+ }
+}
+
+class NodeModuleDecoratorRuntimeModule extends RuntimeModule {
+ constructor() {
+ super("node module decorator");
+ }
+
+ /**
+ * @returns {string} runtime code
+ */
+ generate() {
+ const { runtimeTemplate } = this.compilation;
+ return Template.asString([
+ `${
+ RuntimeGlobals.nodeModuleDecorator
+ } = ${runtimeTemplate.basicFunction("module", [
+ "module.paths = [];",
+ "if (!module.children) module.children = [];",
+ "return module;"
+ ])};`
+ ]);
+ }
+}
+
module.exports = CommonJsPlugin;
diff --git a/lib/dependencies/CommonJsRequireDependencyParserPlugin.js b/lib/dependencies/CommonJsRequireDependencyParserPlugin.js
deleted file mode 100644
index cb94089b5..000000000
--- a/lib/dependencies/CommonJsRequireDependencyParserPlugin.js
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
-*/
-
-"use strict";
-
-const RuntimeGlobals = require("../RuntimeGlobals");
-const {
- toConstantDependency
-} = require("../javascript/JavascriptParserHelpers");
-const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
-const CommonJsRequireDependency = require("./CommonJsRequireDependency");
-const ContextDependencyHelpers = require("./ContextDependencyHelpers");
-const LocalModuleDependency = require("./LocalModuleDependency");
-const { getLocalModule } = require("./LocalModulesHelpers");
-const RequireHeaderDependency = require("./RequireHeaderDependency");
-
-class CommonJsRequireDependencyParserPlugin {
- constructor(options) {
- this.options = options;
- }
-
- apply(parser) {
- const options = this.options;
-
- const processItem = (expr, param) => {
- if (param.isString()) {
- const dep = new CommonJsRequireDependency(param.string, param.range);
- dep.loc = expr.loc;
- dep.optional = !!parser.scope.inTry;
- parser.state.current.addDependency(dep);
- return true;
- }
- };
- const processContext = (expr, param) => {
- const dep = ContextDependencyHelpers.create(
- CommonJsRequireContextDependency,
- expr.range,
- param,
- expr,
- options,
- {},
- parser
- );
- if (!dep) return;
- dep.loc = expr.loc;
- dep.optional = !!parser.scope.inTry;
- parser.state.current.addDependency(dep);
- return true;
- };
-
- parser.hooks.expression
- .for("require.cache")
- .tap(
- "CommonJsRequireDependencyParserPlugin",
- toConstantDependency(parser, RuntimeGlobals.moduleCache, [
- RuntimeGlobals.moduleCache
- ])
- );
- parser.hooks.expression
- .for("require")
- .tap("CommonJsRequireDependencyParserPlugin", expr => {
- const dep = new CommonJsRequireContextDependency(
- {
- request: options.unknownContextRequest,
- recursive: options.unknownContextRecursive,
- regExp: options.unknownContextRegExp,
- mode: "sync"
- },
- expr.range
- );
- dep.critical =
- options.unknownContextCritical &&
- "require function is used in a way in which dependencies cannot be statically extracted";
- dep.loc = expr.loc;
- dep.optional = !!parser.scope.inTry;
- parser.state.current.addDependency(dep);
- return true;
- });
-
- const createHandler = callNew => expr => {
- if (expr.arguments.length !== 1) return;
- let localModule;
- const param = parser.evaluateExpression(expr.arguments[0]);
- if (param.isConditional()) {
- let isExpression = false;
- for (const p of param.options) {
- const result = processItem(expr, p);
- if (result === undefined) {
- isExpression = true;
- }
- }
- if (!isExpression) {
- const dep = new RequireHeaderDependency(expr.callee.range);
- dep.loc = expr.loc;
- parser.state.module.addPresentationalDependency(dep);
- return true;
- }
- }
- if (
- param.isString() &&
- (localModule = getLocalModule(parser.state, param.string))
- ) {
- localModule.flagUsed();
- const dep = new LocalModuleDependency(localModule, expr.range, callNew);
- dep.loc = expr.loc;
- parser.state.module.addPresentationalDependency(dep);
- return true;
- } else {
- const result = processItem(expr, param);
- if (result === undefined) {
- processContext(expr, param);
- } else {
- const dep = new RequireHeaderDependency(expr.callee.range);
- dep.loc = expr.loc;
- parser.state.module.addPresentationalDependency(dep);
- }
- return true;
- }
- };
- parser.hooks.call
- .for("require")
- .tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
- parser.hooks.new
- .for("require")
- .tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
- parser.hooks.call
- .for("module.require")
- .tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
- parser.hooks.new
- .for("module.require")
- .tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
- }
-}
-module.exports = CommonJsRequireDependencyParserPlugin;
diff --git a/lib/dependencies/CommonJsSelfReferenceDependency.js b/lib/dependencies/CommonJsSelfReferenceDependency.js
new file mode 100644
index 000000000..9fec7c9a4
--- /dev/null
+++ b/lib/dependencies/CommonJsSelfReferenceDependency.js
@@ -0,0 +1,136 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const { UsageState } = require("../ModuleGraph");
+const RuntimeGlobals = require("../RuntimeGlobals");
+const makeSerializable = require("../util/makeSerializable");
+const propertyAccess = require("../util/propertyAccess");
+const NullDependency = require("./NullDependency");
+
+/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
+/** @typedef {import("../Dependency")} Dependency */
+/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
+/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
+/** @typedef {import("../ModuleGraph")} ModuleGraph */
+
+class CommonJsSelfReferenceDependency extends NullDependency {
+ constructor(range, base, names) {
+ super();
+ this.range = range;
+ this.base = base;
+ this.names = names;
+ }
+
+ get type() {
+ return "cjs self exports reference";
+ }
+
+ /**
+ * @returns {string | null} an identifier to merge equal requests
+ */
+ getResourceIdentifier() {
+ return `self`;
+ }
+
+ /**
+ * Returns list of exports referenced by this dependency
+ * @param {ModuleGraph} moduleGraph module graph
+ * @returns {string[][]} referenced exports
+ */
+ getReferencedExports(moduleGraph) {
+ return [this.names];
+ }
+
+ serialize(context) {
+ const { write } = context;
+ write(this.range);
+ write(this.base);
+ write(this.names);
+ super.serialize(context);
+ }
+
+ deserialize(context) {
+ const { read } = context;
+ this.range = read();
+ this.base = read();
+ this.names = read();
+ super.deserialize(context);
+ }
+}
+
+makeSerializable(
+ CommonJsSelfReferenceDependency,
+ "webpack/lib/dependencies/CommonJsSelfReferenceDependency"
+);
+
+CommonJsSelfReferenceDependency.Template = class CommonJsSelfReferenceDependencyTemplate extends NullDependency.Template {
+ /**
+ * @param {Dependency} dependency the dependency for which the template should be applied
+ * @param {ReplaceSource} source the current replace source which can be modified
+ * @param {DependencyTemplateContext} templateContext the context object
+ * @returns {void}
+ */
+ apply(
+ dependency,
+ source,
+ { module, moduleGraph, initFragments, runtimeRequirements }
+ ) {
+ const dep = /** @type {CommonJsSelfReferenceDependency} */ (dependency);
+ let used;
+ if (dep.names.length === 0) {
+ used = dep.names;
+ } else if (module.buildMeta && module.buildMeta.exportsType === "default") {
+ const defaultInfo = moduleGraph.getExportInfo(module, "default");
+ if (defaultInfo.used === UsageState.Used) {
+ used = dep.names;
+ } else {
+ used = defaultInfo.exportsInfo.getUsedName(dep.names);
+ }
+ } else {
+ used = moduleGraph.getExportsInfo(module).getUsedName(dep.names);
+ }
+ if (!used) {
+ throw new Error(
+ "Self-reference dependency has unused export name: This should not happen"
+ );
+ }
+
+ let base = undefined;
+ switch (dep.base) {
+ case "exports":
+ runtimeRequirements.add(RuntimeGlobals.exports);
+ base = module.exportsArgument;
+ break;
+ case "module.exports":
+ runtimeRequirements.add(RuntimeGlobals.module);
+ base = `${module.moduleArgument}.exports`;
+ break;
+ case "this":
+ runtimeRequirements.add(RuntimeGlobals.thisAsExports);
+ base = "this";
+ break;
+ default:
+ throw new Error(`Unsupported base ${dep.base}`);
+ }
+
+ if (base === dep.base && used.join() === dep.names.join()) {
+ // Nothing has to be changed
+ // We don't use a replacement for compat reasons
+ // for plugins that update `module._source` which they
+ // shouldn't do!
+ return;
+ }
+
+ source.replace(
+ dep.range[0],
+ dep.range[1] - 1,
+ `/* self exports access */ ${base}${propertyAccess(used)}`
+ );
+ }
+};
+
+module.exports = CommonJsSelfReferenceDependency;
diff --git a/lib/dependencies/DynamicExports.js b/lib/dependencies/DynamicExports.js
new file mode 100644
index 000000000..1ac1007f1
--- /dev/null
+++ b/lib/dependencies/DynamicExports.js
@@ -0,0 +1,57 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+/** @typedef {import("../Parser").ParserState} ParserState */
+
+/** @type {WeakMap} */
+const parserStateExportsState = new WeakMap();
+
+/**
+ * @param {ParserState} parserState parser state
+ * @returns {void}
+ */
+exports.bailout = parserState => {
+ const value = parserStateExportsState.get(parserState);
+ parserStateExportsState.set(parserState, false);
+ if (value === true) {
+ parserState.module.buildMeta.exportsType = undefined;
+ parserState.module.buildMeta.defaultObject = false;
+ }
+};
+
+/**
+ * @param {ParserState} parserState parser state
+ * @returns {void}
+ */
+exports.enable = parserState => {
+ const value = parserStateExportsState.get(parserState);
+ if (value === false) return;
+ parserStateExportsState.set(parserState, true);
+ if (value !== true) {
+ parserState.module.buildMeta.exportsType = "default";
+ parserState.module.buildMeta.defaultObject = "redirect";
+ }
+};
+
+/**
+ * @param {ParserState} parserState parser state
+ * @returns {void}
+ */
+exports.setFlagged = parserState => {
+ const value = parserStateExportsState.get(parserState);
+ if (value !== true) return;
+ parserState.module.buildMeta.exportsType = "flagged";
+};
+
+/**
+ * @param {ParserState} parserState parser state
+ * @returns {boolean} true, when enabled
+ */
+exports.isEnabled = parserState => {
+ const value = parserStateExportsState.get(parserState);
+ return value === true;
+};
diff --git a/lib/dependencies/HarmonyDetectionParserPlugin.js b/lib/dependencies/HarmonyDetectionParserPlugin.js
index 941b66420..d7d631262 100644
--- a/lib/dependencies/HarmonyDetectionParserPlugin.js
+++ b/lib/dependencies/HarmonyDetectionParserPlugin.js
@@ -5,7 +5,9 @@
"use strict";
+const DynamicExports = require("./DynamicExports");
const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
+const HarmonyExports = require("./HarmonyExports");
module.exports = class HarmonyDetectionParserPlugin {
constructor(options) {
@@ -48,16 +50,10 @@ module.exports = class HarmonyDetectionParserPlugin {
index: -3
};
module.addPresentationalDependency(compatDep);
- parser.state.harmonyModule = true;
+ DynamicExports.bailout(parser.state);
+ HarmonyExports.enable(parser.state, isStrictHarmony);
parser.scope.isStrict = true;
- module.buildMeta.exportsType = "namespace";
module.buildMeta.async = isAsync;
- module.buildInfo.strict = true;
- module.buildInfo.exportsArgument = "__webpack_exports__";
- if (isStrictHarmony) {
- module.buildMeta.strictHarmonyModule = true;
- module.buildInfo.moduleArgument = "__webpack_module__";
- }
}
});
@@ -68,7 +64,7 @@ module.exports = class HarmonyDetectionParserPlugin {
"The top-level-await experiment is not enabled (set experiments.topLevelAwait: true to enabled it)"
);
}
- if (!parser.state.harmonyModule) {
+ if (!HarmonyExports.isEnabled(parser.state)) {
throw new Error(
"Top-level-await is only supported in EcmaScript Modules"
);
@@ -77,15 +73,13 @@ module.exports = class HarmonyDetectionParserPlugin {
});
const skipInHarmony = () => {
- const module = parser.state.module;
- if (module && module.buildMeta && module.buildMeta.exportsType) {
+ if (HarmonyExports.isEnabled(parser.state)) {
return true;
}
};
const nullInHarmony = () => {
- const module = parser.state.module;
- if (module && module.buildMeta && module.buildMeta.exportsType) {
+ if (HarmonyExports.isEnabled(parser.state)) {
return null;
}
};
diff --git a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js
index 897cbe009..7b2fcf2a3 100644
--- a/lib/dependencies/HarmonyExportImportedSpecifierDependency.js
+++ b/lib/dependencies/HarmonyExportImportedSpecifierDependency.js
@@ -29,7 +29,7 @@ const HarmonyImportDependency = require("./HarmonyImportDependency");
/** @typedef {import("../WebpackError")} WebpackError */
/** @typedef {import("../util/Hash")} Hash */
-/** @typedef {"missing"|"unused"|"empty-star"|"reexport-non-harmony-default"|"reexport-named-default"|"reexport-namespace-object"|"reexport-fake-named-namespace-object"|"reexport-fake-namespace-object"|"reexport-non-harmony-undefined"|"normal-reexport"|"dynamic-reexport"} ExportModeType */
+/** @typedef {"missing"|"unused"|"empty-star"|"reexport-dynamic-default"|"reexport-dynamic-default-default"|"reexport-named-default"|"reexport-namespace-object"|"reexport-fake-namespace-object"|"reexport-undefined"|"normal-reexport"|"dynamic-reexport"} ExportModeType */
const idsSymbol = Symbol("HarmonyExportImportedSpecifierDependency.ids");
@@ -190,30 +190,35 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
return mode;
}
- const strictHarmonyModule = parentModule.buildMeta.strictHarmonyModule;
+ const importedExportsType = importedModule.getExportsType(
+ parentModule.buildMeta.strictHarmonyModule
+ );
- const isNotAHarmonyModule =
- importedModule.buildMeta && !importedModule.buildMeta.exportsType;
- const isNamedModule =
- importedModule.buildMeta &&
- importedModule.buildMeta.exportsType === "default";
+ const isDynamic = importedExportsType === "dynamic";
+ const isDynamicDefault = importedExportsType === "dynamic-default";
+ const isDefaultOnly = importedExportsType === "default-only";
+ const isDefaultWithNamed = importedExportsType === "default-with-named";
// Special handling for reexporting the default export
- // from non-harmony modules
+ // from non-namespace modules
if (name && ids.length > 0 && ids[0] === "default") {
- if (isNotAHarmonyModule) {
- const mode = new ExportMode("reexport-non-harmony-default");
+ if (isDynamic) {
+ const mode = new ExportMode("reexport-dynamic-default");
mode.name = name;
return mode;
- } else if (isNamedModule) {
+ } else if (isDefaultOnly || isDefaultWithNamed) {
const exportInfo = exportsInfo.getReadOnlyExportInfo(name);
const mode = new ExportMode("reexport-named-default");
mode.name = name;
mode.partialNamespaceExportInfo = exportInfo;
+ return mode;
+ } else if (isDynamicDefault) {
+ const mode = new ExportMode("reexport-dynamic-default-default");
+ mode.name = name;
return mode;
}
}
@@ -225,8 +230,8 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
if (ids.length > 0) {
// export { name as name }
- if ((isNotAHarmonyModule || isNamedModule) && strictHarmonyModule) {
- mode = new ExportMode("reexport-non-harmony-undefined");
+ if (isDefaultOnly || isDynamicDefault) {
+ mode = new ExportMode("reexport-undefined");
mode.name = name;
} else {
mode = new ExportMode("normal-reexport");
@@ -235,14 +240,16 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
}
} else {
// export { * as name }
- if (isNotAHarmonyModule && strictHarmonyModule) {
+ if (isDefaultOnly || isDynamicDefault) {
mode = new ExportMode("reexport-fake-namespace-object");
mode.name = name;
- } else if (isNamedModule) {
- mode = new ExportMode("reexport-fake-named-namespace-object");
+ mode.partialNamespaceExportInfo = exportInfo;
+ mode.fakeType = 0;
+ } else if (isDefaultWithNamed) {
+ mode = new ExportMode("reexport-fake-namespace-object");
mode.name = name;
mode.partialNamespaceExportInfo = exportInfo;
- mode.fakeType = strictHarmonyModule ? 0 : 2;
+ mode.fakeType = 2;
} else {
mode = new ExportMode("reexport-namespace-object");
mode.name = name;
@@ -363,10 +370,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
case "missing":
case "unused":
case "empty-star":
- case "reexport-non-harmony-undefined":
+ case "reexport-undefined":
return Dependency.NO_EXPORTS_REFERENCED;
- case "reexport-non-harmony-default":
+ case "reexport-dynamic-default":
return Dependency.DEFAULT_EXPORT_REFERENCED;
case "reexport-named-default": {
@@ -383,7 +390,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
}
case "reexport-namespace-object":
- case "reexport-fake-named-namespace-object": {
+ case "reexport-fake-namespace-object": {
if (!mode.partialNamespaceExportInfo)
return Dependency.NS_OBJECT_REFERENCED;
/** @type {string[][]} */
@@ -396,8 +403,8 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
return referencedExports;
}
- case "reexport-fake-namespace-object":
case "dynamic-reexport":
+ case "reexport-dynamic-default-default":
return Dependency.NS_OBJECT_REFERENCED;
case "normal-reexport":
@@ -468,14 +475,14 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
})),
dependencies: [moduleGraph.getModule(this)]
};
- case "reexport-fake-namespace-object":
- case "reexport-non-harmony-default":
- case "reexport-non-harmony-undefined":
+ case "reexport-dynamic-default":
+ case "reexport-dynamic-default-default":
+ case "reexport-undefined":
return {
exports: [mode.name],
dependencies: [moduleGraph.getModule(this)]
};
- case "reexport-fake-named-namespace-object":
+ case "reexport-fake-namespace-object":
case "reexport-namespace-object":
return {
exports: [
@@ -678,23 +685,33 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
);
break;
- case "reexport-non-harmony-default":
+ case "reexport-dynamic-default":
initFragments.push(
this.getReexportFragment(
module,
- "reexport default from non-harmony",
+ "reexport default from dynamic",
module.getUsedName(moduleGraph, mode.name),
importVar,
- module.buildMeta && module.buildMeta.strictHarmonyModule
- ? ""
- : null,
+ null,
+ runtimeRequirements
+ )
+ );
+ break;
+
+ case "reexport-dynamic-default-default":
+ initFragments.push(
+ this.getReexportFragment(
+ module,
+ "reexport dynamic as default",
+ module.getUsedName(moduleGraph, mode.name),
+ importVar,
+ "",
runtimeRequirements
)
);
break;
case "reexport-fake-namespace-object":
- case "reexport-fake-named-namespace-object":
initFragments.push(
...this.getReexportFakeNamespaceObjectFragments(
module,
@@ -706,7 +723,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
);
break;
- case "reexport-non-harmony-undefined":
+ case "reexport-undefined":
initFragments.push(
this.getReexportFragment(
module,
diff --git a/lib/dependencies/HarmonyExports.js b/lib/dependencies/HarmonyExports.js
new file mode 100644
index 000000000..452865923
--- /dev/null
+++ b/lib/dependencies/HarmonyExports.js
@@ -0,0 +1,40 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+/** @typedef {import("../Parser").ParserState} ParserState */
+
+/** @type {WeakMap} */
+const parserStateExportsState = new WeakMap();
+
+/**
+ * @param {ParserState} parserState parser state
+ * @param {boolean} isStrictHarmony strict harmony mode should be enabled
+ * @returns {void}
+ */
+exports.enable = (parserState, isStrictHarmony) => {
+ const value = parserStateExportsState.get(parserState);
+ if (value === false) return;
+ parserStateExportsState.set(parserState, true);
+ if (value !== true) {
+ parserState.module.buildMeta.exportsType = "namespace";
+ parserState.module.buildInfo.strict = true;
+ parserState.module.buildInfo.exportsArgument = "__webpack_exports__";
+ if (isStrictHarmony) {
+ parserState.module.buildMeta.strictHarmonyModule = true;
+ parserState.module.buildInfo.moduleArgument = "__webpack_module__";
+ }
+ }
+};
+
+/**
+ * @param {ParserState} parserState parser state
+ * @returns {boolean} true, when enabled
+ */
+exports.isEnabled = parserState => {
+ const value = parserStateExportsState.get(parserState);
+ return value === true;
+};
diff --git a/lib/dependencies/HarmonyImportDependency.js b/lib/dependencies/HarmonyImportDependency.js
index 83320bfa6..63048e853 100644
--- a/lib/dependencies/HarmonyImportDependency.js
+++ b/lib/dependencies/HarmonyImportDependency.js
@@ -94,62 +94,68 @@ class HarmonyImportDependency extends ModuleDependency {
return;
}
- const exportsType =
- importedModule.buildMeta && importedModule.buildMeta.exportsType;
- if (!exportsType) {
- // It's not an harmony module
- if (
- moduleGraph.getParentModule(this).buildMeta.strictHarmonyModule &&
- ids.length > 0 &&
- ids[0] !== "default"
- ) {
- // In strict harmony modules we only support the default export
+ const parentModule = moduleGraph.getParentModule(this);
+ const exportsType = importedModule.getExportsType(
+ parentModule.buildMeta.strictHarmonyModule
+ );
+ switch (exportsType) {
+ case "default-only":
+ case "dynamic-default":
+ // It's has only a default export
+ if (ids.length > 0 && ids[0] !== "default") {
+ // In strict harmony modules we only support the default export
+ return [
+ new HarmonyLinkingError(
+ `Can't import the named export ${ids
+ .map(id => `'${id}'`)
+ .join(
+ "."
+ )} ${additionalMessage} from default-exporting module (only default export is available)`
+ )
+ ];
+ }
+ return;
+ case "default-with-named":
+ // It has a default export and named properties redirect
+ // In some cases we still want to warn here
+ if (
+ ids.length > 0 &&
+ ids[0] !== "default" &&
+ importedModule.buildMeta.defaultObject === "redirect-warn"
+ ) {
+ // For these modules only the default export is supported
+ return [
+ new HarmonyLinkingError(
+ `Should not import the named export ${ids
+ .map(id => `'${id}'`)
+ .join(
+ "."
+ )} ${additionalMessage} from default-exporting module (only default export is available soon)`
+ )
+ ];
+ }
+ return;
+ case "namespace":
+ if (ids.length === 0) {
+ return;
+ }
+
+ if (moduleGraph.isExportProvided(importedModule, ids) !== false) {
+ // It's provided or we are not sure
+ return;
+ }
+
+ // We are sure that it's not provided
return [
new HarmonyLinkingError(
- `Can't import the named export ${ids
+ `export ${ids
.map(id => `'${id}'`)
- .join(
- "."
- )} ${additionalMessage} from non EcmaScript module (only default export is available)`
+ .join(".")} ${additionalMessage} was not found in '${
+ this.userRequest
+ }'`
)
];
- }
- return;
- } else if (exportsType === "default") {
- if (ids.length > 0 && ids[0] !== "default") {
- // For these modules only the default export is supported
- return [
- new HarmonyLinkingError(
- `Can't import the named export ${ids
- .map(id => `'${id}'`)
- .join(
- "."
- )} ${additionalMessage} from JSON module (only default export is available)`
- )
- ];
- }
- return;
}
-
- if (ids.length === 0) {
- return;
- }
-
- if (moduleGraph.isExportProvided(importedModule, ids) !== false) {
- // It's provided or we are not sure
- return;
- }
-
- // We are sure that it's not provided
- return [
- new HarmonyLinkingError(
- `export ${ids
- .map(id => `'${id}'`)
- .join(".")} ${additionalMessage} was not found in '${
- this.userRequest
- }'`
- )
- ];
}
/**
@@ -161,12 +167,15 @@ class HarmonyImportDependency extends ModuleDependency {
updateHash(hash, chunkGraph) {
super.updateHash(hash, chunkGraph);
const importedModule = chunkGraph.moduleGraph.getModule(this);
- hash.update(
- (importedModule &&
- (!importedModule.buildMeta || importedModule.buildMeta.exportsType)) +
- ""
- );
- if (chunkGraph.moduleGraph.isAsync(importedModule)) hash.update("async");
+ if (importedModule) {
+ const parentModule = chunkGraph.moduleGraph.getParentModule(this);
+ hash.update(
+ importedModule.getExportsType(
+ parentModule.buildMeta && parentModule.buildMeta.strictHarmonyModule
+ )
+ );
+ if (chunkGraph.moduleGraph.isAsync(importedModule)) hash.update("async");
+ }
hash.update(`${this.sourceOrder}`);
if (this.await) hash.update("await");
}
diff --git a/lib/dependencies/HarmonyImportDependencyParserPlugin.js b/lib/dependencies/HarmonyImportDependencyParserPlugin.js
index 532ffbf03..2d73b6994 100644
--- a/lib/dependencies/HarmonyImportDependencyParserPlugin.js
+++ b/lib/dependencies/HarmonyImportDependencyParserPlugin.js
@@ -9,6 +9,7 @@ const HotModuleReplacementPlugin = require("../HotModuleReplacementPlugin");
const ConstDependency = require("./ConstDependency");
const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
+const HarmonyExports = require("./HarmonyExports");
const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
@@ -168,7 +169,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
hotAcceptCallback.tap(
"HarmonyImportDependencyParserPlugin",
(expr, requests) => {
- if (!parser.state.harmonyModule) {
+ if (!HarmonyExports.isEnabled(parser.state)) {
// This is not a harmony module, skip it
return;
}
@@ -192,7 +193,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
hotAcceptWithoutCallback.tap(
"HarmonyImportDependencyParserPlugin",
(expr, requests) => {
- if (!parser.state.harmonyModule) {
+ if (!HarmonyExports.isEnabled(parser.state)) {
// This is not a harmony module, skip it
return;
}
diff --git a/lib/dependencies/HarmonyImportSpecifierDependency.js b/lib/dependencies/HarmonyImportSpecifierDependency.js
index 1cae0fedf..9a03ecb1d 100644
--- a/lib/dependencies/HarmonyImportSpecifierDependency.js
+++ b/lib/dependencies/HarmonyImportSpecifierDependency.js
@@ -171,9 +171,6 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
if (importedModule) {
const exportsInfo = moduleGraph.getExportsInfo(importedModule);
hash.update(`${exportsInfo.getUsedName(ids)}`);
- hash.update(
- (!importedModule.buildMeta || importedModule.buildMeta.exportsType) + ""
- );
}
}
@@ -246,6 +243,7 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
asiSafe: dep.asiSafe || dep.shorthand,
isCall: dep.call,
callContext: !dep.directImport,
+ defaultInterop: true,
importVar: dep.getImportVar(moduleGraph),
initFragments,
runtimeRequirements
diff --git a/lib/dependencies/HarmonyTopLevelThisParserPlugin.js b/lib/dependencies/HarmonyTopLevelThisParserPlugin.js
index 1ecc3f7ce..9981c10fd 100644
--- a/lib/dependencies/HarmonyTopLevelThisParserPlugin.js
+++ b/lib/dependencies/HarmonyTopLevelThisParserPlugin.js
@@ -6,6 +6,7 @@
"use strict";
const ConstDependency = require("./ConstDependency");
+const HarmonyExports = require("./HarmonyExports");
class HarmonyTopLevelThisParserPlugin {
apply(parser) {
@@ -13,12 +14,11 @@ class HarmonyTopLevelThisParserPlugin {
.for("this")
.tap("HarmonyTopLevelThisParserPlugin", node => {
if (!parser.scope.topLevelScope) return;
- const module = parser.state.module;
- const isHarmony = !!(module.buildMeta && module.buildMeta.exportsType);
- if (isHarmony) {
+ if (HarmonyExports.isEnabled(parser.state)) {
const dep = new ConstDependency("undefined", node.range, null);
dep.loc = node.loc;
parser.state.module.addPresentationalDependency(dep);
+ return this;
}
});
}
diff --git a/lib/dependencies/ModuleDecoratorDependency.js b/lib/dependencies/ModuleDecoratorDependency.js
index 66733ee8e..353dd4f86 100644
--- a/lib/dependencies/ModuleDecoratorDependency.js
+++ b/lib/dependencies/ModuleDecoratorDependency.js
@@ -34,6 +34,22 @@ class ModuleDecoratorDependency extends NullDependency {
return "module decorator";
}
+ /**
+ * @returns {string | null} an identifier to merge equal requests
+ */
+ getResourceIdentifier() {
+ return `self`;
+ }
+
+ /**
+ * Returns list of exports referenced by this dependency
+ * @param {ModuleGraph} moduleGraph module graph
+ * @returns {string[][]} referenced exports
+ */
+ getReferencedExports(moduleGraph) {
+ return [[]];
+ }
+
/**
* Update the hash
* @param {Hash} hash hash to be updated
@@ -76,6 +92,8 @@ ModuleDecoratorDependency.Template = class ModuleDecoratorDependencyTemplate ext
{ module, chunkGraph, initFragments, runtimeRequirements }
) {
const dep = /** @type {ModuleDecoratorDependency} */ (dependency);
+ runtimeRequirements.add(RuntimeGlobals.moduleLoaded);
+ runtimeRequirements.add(RuntimeGlobals.moduleId);
runtimeRequirements.add(RuntimeGlobals.module);
runtimeRequirements.add(dep.decorator);
initFragments.push(
diff --git a/lib/dependencies/RequireResolveDependency.js b/lib/dependencies/RequireResolveDependency.js
index c58a988e2..4960578d0 100644
--- a/lib/dependencies/RequireResolveDependency.js
+++ b/lib/dependencies/RequireResolveDependency.js
@@ -5,10 +5,13 @@
"use strict";
+const Dependency = require("../Dependency");
const makeSerializable = require("../util/makeSerializable");
const ModuleDependency = require("./ModuleDependency");
const ModuleDependencyAsId = require("./ModuleDependencyTemplateAsId");
+/** @typedef {import("../ModuleGraph")} ModuleGraph */
+
class RequireResolveDependency extends ModuleDependency {
constructor(request, range) {
super(request);
@@ -20,6 +23,16 @@ class RequireResolveDependency extends ModuleDependency {
return "require.resolve";
}
+ /**
+ * Returns list of exports referenced by this dependency
+ * @param {ModuleGraph} moduleGraph module graph
+ * @returns {string[][]} referenced exports
+ */
+ getReferencedExports(moduleGraph) {
+ // This doesn't use any export
+ return Dependency.NO_EXPORTS_REFERENCED;
+ }
+
serialize(context) {
const { write } = context;
diff --git a/lib/dependencies/RequireResolveDependencyParserPlugin.js b/lib/dependencies/RequireResolveDependencyParserPlugin.js
deleted file mode 100644
index 5fce979ac..000000000
--- a/lib/dependencies/RequireResolveDependencyParserPlugin.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
-*/
-
-"use strict";
-
-const ContextDependencyHelpers = require("./ContextDependencyHelpers");
-const RequireResolveContextDependency = require("./RequireResolveContextDependency");
-const RequireResolveDependency = require("./RequireResolveDependency");
-const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
-
-class RequireResolveDependencyParserPlugin {
- constructor(options) {
- this.options = options;
- }
-
- apply(parser) {
- const options = this.options;
-
- const process = (expr, weak) => {
- if (expr.arguments.length !== 1) return;
- const param = parser.evaluateExpression(expr.arguments[0]);
- if (param.isConditional()) {
- for (const option of param.options) {
- const result = processItem(expr, option, weak);
- if (result === undefined) {
- processContext(expr, option, weak);
- }
- }
- const dep = new RequireResolveHeaderDependency(expr.callee.range);
- dep.loc = expr.loc;
- parser.state.module.addPresentationalDependency(dep);
- return true;
- } else {
- const result = processItem(expr, param, weak);
- if (result === undefined) {
- processContext(expr, param, weak);
- }
- const dep = new RequireResolveHeaderDependency(expr.callee.range);
- dep.loc = expr.loc;
- parser.state.module.addPresentationalDependency(dep);
- return true;
- }
- };
- const processItem = (expr, param, weak) => {
- if (param.isString()) {
- const dep = new RequireResolveDependency(param.string, param.range);
- dep.loc = expr.loc;
- dep.optional = !!parser.scope.inTry;
- dep.weak = weak;
- parser.state.current.addDependency(dep);
- return true;
- }
- };
- const processContext = (expr, param, weak) => {
- const dep = ContextDependencyHelpers.create(
- RequireResolveContextDependency,
- param.range,
- param,
- expr,
- options,
- {
- mode: weak ? "weak" : "sync"
- },
- parser
- );
- if (!dep) return;
- dep.loc = expr.loc;
- dep.optional = !!parser.scope.inTry;
- parser.state.current.addDependency(dep);
- return true;
- };
-
- parser.hooks.call
- .for("require.resolve")
- .tap("RequireResolveDependencyParserPlugin", expr => {
- return process(expr, false);
- });
- parser.hooks.call
- .for("require.resolveWeak")
- .tap("RequireResolveDependencyParserPlugin", expr => {
- return process(expr, true);
- });
- }
-}
-module.exports = RequireResolveDependencyParserPlugin;
diff --git a/lib/javascript/JavascriptModulesPlugin.js b/lib/javascript/JavascriptModulesPlugin.js
index a1896ace8..d7a2b2559 100644
--- a/lib/javascript/JavascriptModulesPlugin.js
+++ b/lib/javascript/JavascriptModulesPlugin.js
@@ -867,6 +867,10 @@ class JavascriptModulesPlugin {
: Template.asString([
"__webpack_modules__[moduleId](module, module.exports, __webpack_require__);"
]);
+ const needModuleId = runtimeRequirements.has(RuntimeGlobals.moduleId);
+ const needModuleLoaded = runtimeRequirements.has(
+ RuntimeGlobals.moduleLoaded
+ );
const content = Template.asString([
"// Check if module is in cache",
"if(__webpack_module_cache__[moduleId]) {",
@@ -874,7 +878,11 @@ class JavascriptModulesPlugin {
"}",
"// Create a new module (and put it into the cache)",
"var module = __webpack_module_cache__[moduleId] = {",
- Template.indent(["i: moduleId,", "l: false,", "exports: {}"]),
+ Template.indent([
+ needModuleId ? "id: moduleId," : "// no module.id needed",
+ needModuleLoaded ? "loaded: false," : "// no module.loaded needed",
+ "exports: {}"
+ ]),
"};",
"",
outputOptions.strictModuleExceptionHandling
@@ -893,10 +901,14 @@ class JavascriptModulesPlugin {
"// Execute the module function",
moduleExecution
]),
- "",
- "// Flag the module as loaded",
- "module.l = true;",
- "",
+ needModuleLoaded
+ ? Template.asString([
+ "",
+ "// Flag the module as loaded",
+ "module.loaded = true;",
+ ""
+ ])
+ : "",
"// Return the exports of the module",
"return module.exports;"
]);
diff --git a/lib/javascript/JavascriptParser.js b/lib/javascript/JavascriptParser.js
index 307e00d17..a9e3a0bd8 100644
--- a/lib/javascript/JavascriptParser.js
+++ b/lib/javascript/JavascriptParser.js
@@ -10,6 +10,7 @@ const { SyncBailHook, HookMap } = require("tapable");
const vm = require("vm");
const Parser = require("../Parser");
const StackedMap = require("../util/StackedMap");
+const memorize = require("../util/memorize");
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
/** @typedef {import("acorn").Options} AcornOptions */
@@ -41,6 +42,8 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
/** @typedef {import("../Parser").ParserState} ParserState */
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
+const EMPTY_ARRAY = [];
+
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
const parser = AcornParser.extend(require("../parsing/importAwaitAcornPlugin"));
@@ -84,6 +87,25 @@ const joinRanges = (startRange, endRange) => {
return [startRange[0], endRange[1]];
};
+const objectAndMembersToName = (object, membersReversed) => {
+ let name = object;
+ for (let i = membersReversed.length - 1; i >= 0; i--) {
+ name = name + "." + membersReversed[i];
+ }
+ return name;
+};
+
+const getRootName = expression => {
+ switch (expression.type) {
+ case "Identifier":
+ return expression.name;
+ case "ThisExpression":
+ return "this";
+ default:
+ return undefined;
+ }
+};
+
/** @type {AcornOptions} */
const defaultParserOptions = {
ranges: true,
@@ -186,6 +208,10 @@ class JavascriptParser extends Parser {
rename: new HookMap(() => new SyncBailHook(["initExpression"])),
/** @type {HookMap>} */
assign: new HookMap(() => new SyncBailHook(["expression"])),
+ /** @type {HookMap>} */
+ assignMemberChain: new HookMap(
+ () => new SyncBailHook(["expression", "members"])
+ ),
/** @type {HookMap>} */
typeof: new HookMap(() => new SyncBailHook(["expression"])),
/** @type {SyncBailHook<[ExpressionNode], boolean | void>} */
@@ -194,15 +220,38 @@ class JavascriptParser extends Parser {
topLevelAwait: new SyncBailHook(["expression"]),
/** @type {HookMap>} */
call: new HookMap(() => new SyncBailHook(["expression"])),
- /** @type {HookMap>} */
+ /** Something like "a.b()" */
+ /** @type {HookMap>} */
callMemberChain: new HookMap(
() => new SyncBailHook(["expression", "members"])
),
+ /** Something like "a.b().c.d" */
+ /** @type {HookMap>} */
+ memberChainOfCallMemberChain: new HookMap(
+ () =>
+ new SyncBailHook([
+ "expression",
+ "calleeMembers",
+ "callExpression",
+ "members"
+ ])
+ ),
+ /** Something like "a.b().c.d()"" */
+ /** @type {HookMap>} */
+ callMemberChainOfCallMemberChain: new HookMap(
+ () =>
+ new SyncBailHook([
+ "expression",
+ "calleeMembers",
+ "innerCallExpression",
+ "members"
+ ])
+ ),
/** @type {HookMap>} */
new: new HookMap(() => new SyncBailHook(["expression"])),
/** @type {HookMap>} */
expression: new HookMap(() => new SyncBailHook(["expression"])),
- /** @type {HookMap>} */
+ /** @type {HookMap>} */
expressionMemberChain: new HookMap(
() => new SyncBailHook(["expression", "members"])
),
@@ -219,6 +268,7 @@ class JavascriptParser extends Parser {
this.sourceType = sourceType;
/** @type {ScopeInfo} */
this.scope = undefined;
+ /** @type {ParserState} */
this.state = undefined;
this.comments = undefined;
this.semicolons = undefined;
@@ -1996,6 +2046,23 @@ class JavascriptParser extends Parser {
}
});
this.walkPattern(expression.left);
+ } else if (expression.left.type === "MemberExpression") {
+ const exprName = this.getMemberExpressionInfo(expression.left, [
+ "expression"
+ ]);
+ if (exprName) {
+ if (
+ this.callHooksForInfo(
+ this.hooks.assignMemberChain,
+ exprName.rootInfo,
+ expression,
+ exprName.getMembers()
+ )
+ ) {
+ return;
+ }
+ }
+ this.walkExpression(expression.left);
} else {
this.walkExpression(expression.left);
}
@@ -2140,6 +2207,22 @@ class JavascriptParser extends Parser {
// (function(…) { }(…))
this._walkIIFE(expression.callee, expression.arguments, null);
} else {
+ if (expression.callee.type === "MemberExpression") {
+ const exprInfo = this.getMemberExpressionInfo(expression.callee, [
+ "call"
+ ]);
+ if (exprInfo && exprInfo.type === "call") {
+ const result = this.callHooksForInfo(
+ this.hooks.callMemberChainOfCallMemberChain,
+ exprInfo.rootInfo,
+ expression,
+ exprInfo.getCalleeMembers(),
+ exprInfo.call,
+ exprInfo.getMembers()
+ );
+ if (result === true) return;
+ }
+ }
const callee = this.evaluateExpression(expression.callee);
if (callee.isIdentifier()) {
const result1 = this.callHooksForInfo(
@@ -2157,40 +2240,72 @@ class JavascriptParser extends Parser {
if (result2 === true) return;
}
- if (expression.callee) this.walkExpression(expression.callee);
+ if (expression.callee) {
+ if (expression.callee.type === "MemberExpression") {
+ // because of call context we need to walk the call context as expression
+ this.walkExpression(expression.callee.object);
+ if (expression.callee.computed === true)
+ this.walkExpression(expression.callee.property);
+ } else {
+ this.walkExpression(expression.callee);
+ }
+ }
if (expression.arguments) this.walkExpressions(expression.arguments);
}
}
walkMemberExpression(expression) {
- const exprName = this.getNameForExpression(expression);
- if (exprName) {
- this.walkMemberExpressionWithExpressionName(
- expression,
- exprName.name,
- exprName.rootInfo,
- exprName.getMembers()
- );
- return;
+ const exprInfo = this.getMemberExpressionInfo(expression, [
+ "call",
+ "expression"
+ ]);
+ if (exprInfo) {
+ switch (exprInfo.type) {
+ case "expression": {
+ const members = exprInfo.getMembers();
+ const result = this.callHooksForInfo(
+ this.hooks.expressionMemberChain,
+ exprInfo.rootInfo,
+ expression,
+ members
+ );
+ if (result === true) return;
+ this.walkMemberExpressionWithExpressionName(
+ expression,
+ exprInfo.name,
+ exprInfo.rootInfo,
+ members
+ );
+ return;
+ }
+ case "call": {
+ const result = this.callHooksForInfo(
+ this.hooks.memberChainOfCallMemberChain,
+ exprInfo.rootInfo,
+ expression,
+ exprInfo.getCalleeMembers(),
+ exprInfo.call,
+ exprInfo.getMembers()
+ );
+ if (result === true) return;
+ // Fast skip over the member chain as we already called memberChainOfCallMemberChain
+ // and call computed property are literals anyway
+ this.walkExpression(exprInfo.call);
+ return;
+ }
+ }
}
this.walkExpression(expression.object);
if (expression.computed === true) this.walkExpression(expression.property);
}
walkMemberExpressionWithExpressionName(expression, name, rootInfo, members) {
- const result1 = this.callHooksForInfo(
- this.hooks.expressionMemberChain,
- rootInfo,
- expression,
- members
- );
- if (result1 === true) return;
- const result2 = this.callHooksForInfo(
+ const result = this.callHooksForInfo(
this.hooks.expression,
name,
expression
);
- if (result2 === true) return;
+ if (result === true) return;
if (expression.object.type === "MemberExpression") {
// optimize case where expression.object is a MemberExpression too.
// we can keep info here when calling walkMemberExpression directly
@@ -2219,7 +2334,7 @@ class JavascriptParser extends Parser {
}
callHooksForExpression(hookMap, expr, ...args) {
- const exprName = this.getNameForExpression(expr);
+ const exprName = this.getMemberExpressionInfo(expr, ["expression"]);
if (exprName !== undefined) {
return this.callHooksForInfoWithFallback(
hookMap,
@@ -2235,7 +2350,7 @@ class JavascriptParser extends Parser {
* @template T
* @template R
* @param {HookMap>} hookMap hooks the should be called
- * @param {ExpressionNode} expr expression info
+ * @param {MemberExpressionNode} expr expression info
* @param {function(string, string | ScopeInfo | VariableInfo, function(): string[]): any} fallback callback when variable in not handled by hooks
* @param {function(string): any} defined callback when variable is defined
* @param {AsArray} args args for the hook
@@ -2248,7 +2363,7 @@ class JavascriptParser extends Parser {
defined,
...args
) {
- const exprName = this.getNameForExpression(expr);
+ const exprName = this.getMemberExpressionInfo(expr, ["expression"]);
if (exprName !== undefined) {
return this.callHooksForInfoWithFallback(
hookMap,
@@ -2677,6 +2792,7 @@ class JavascriptParser extends Parser {
isStrict: false,
definitions: new StackedMap()
};
+ /** @type {ParserState} */
this.state = state;
this.comments = comments;
this.semicolons = semicolons;
@@ -2691,6 +2807,7 @@ class JavascriptParser extends Parser {
}
this.hooks.finish.call(ast, comments);
this.scope = oldScope;
+ /** @type {ParserState} */
this.state = oldState;
this.comments = oldComments;
this.semicolons = oldSemicolons;
@@ -2843,60 +2960,112 @@ class JavascriptParser extends Parser {
}
/**
- * @param {ExpressionNode} expression an expression
- * @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => string[]}} name info
+ * @param {MemberExpressionNode} expression an member expression
+ * @returns {{ members: string[], object: ExpressionNode | SuperNode }} member names (reverse order) and remaining object
*/
- getNameForExpression(expression) {
+ extractMemberExpressionChain(expression) {
+ /** @type {AnyNode} */
let expr = expression;
- const exprName = [];
+ const members = [];
while (expr.type === "MemberExpression") {
- if (expr.object.type === "Super") return undefined;
if (expr.computed) {
if (expr.property.type !== "Literal") break;
- exprName.push(`${expr.property.value}`);
+ members.push(`${expr.property.value}`);
} else {
if (expr.property.type !== "Identifier") break;
- exprName.push(expr.property.name);
+ members.push(expr.property.name);
}
expr = expr.object;
}
- let rootName;
- if (expr.type === "Identifier") {
- rootName = expr.name;
- } else if (expr.type === "ThisExpression") {
- rootName = "this";
- } else {
- return undefined;
- }
- const rootInfo = this.getVariableInfo(rootName);
- /** @type {string | ScopeInfo | true} */
- let resolvedRoot;
- if (rootInfo instanceof VariableInfo) {
- resolvedRoot = rootInfo.freeName;
- } else {
- resolvedRoot = rootInfo;
- }
- if (typeof resolvedRoot !== "string") {
- return undefined;
- }
- let name = resolvedRoot;
- for (let i = exprName.length - 1; i >= 0; i--) {
- name = name + "." + exprName[i];
- }
- let reversed = false;
return {
- name,
- rootInfo,
- getMembers: () => {
- if (!reversed) {
- exprName.reverse();
- reversed = true;
- }
- return exprName;
- }
+ members,
+ object: expr
};
}
+ /**
+ * @param {string} varName variable name
+ * @returns {{name: string, info: VariableInfo | string}} name of the free variable and variable info for that
+ */
+ getFreeInfoFromVariable(varName) {
+ const info = this.getVariableInfo(varName);
+ let name;
+ if (info instanceof VariableInfo) {
+ name = info.freeName;
+ if (typeof name !== "string") return undefined;
+ } else if (typeof info !== "string") {
+ return undefined;
+ } else {
+ name = info;
+ }
+ return { info, name };
+ }
+
+ /** @typedef {{ type: "call", call: CallExpressionNode, calleeName: string, rootInfo: string | VariableInfo, getCalleeMembers: () => string[], name: string, getMembers: () => string[]}} CallExpressionInfo */
+ /** @typedef {{ type: "expression", rootInfo: string | VariableInfo, name: string, getMembers: () => string[]}} ExpressionExpressionInfo */
+
+ /**
+ * @param {MemberExpressionNode} expression an member expression
+ * @param {("call"|"expression")[]} allowedTypes which types should be returned
+ * @returns {CallExpressionInfo | ExpressionExpressionInfo | undefined} expression info
+ */
+ getMemberExpressionInfo(expression, allowedTypes) {
+ const possibleTypes = new Set(allowedTypes);
+ const { object, members } = this.extractMemberExpressionChain(expression);
+ switch (object.type) {
+ case "CallExpression": {
+ if (!possibleTypes.has("call")) return undefined;
+ let callee = object.callee;
+ let rootMembers = EMPTY_ARRAY;
+ if (callee.type === "MemberExpression") {
+ ({
+ object: callee,
+ members: rootMembers
+ } = this.extractMemberExpressionChain(callee));
+ }
+ const rootName = getRootName(callee);
+ if (!rootName) return undefined;
+ const result = this.getFreeInfoFromVariable(rootName);
+ if (!result) return undefined;
+ const { info: rootInfo, name: resolvedRoot } = result;
+ const calleeName = objectAndMembersToName(resolvedRoot, rootMembers);
+ return {
+ type: "call",
+ call: object,
+ calleeName,
+ rootInfo,
+ getCalleeMembers: memorize(() => rootMembers.reverse()),
+ name: objectAndMembersToName(`${calleeName}()`, members),
+ getMembers: memorize(() => members.reverse())
+ };
+ }
+ case "Identifier":
+ case "ThisExpression": {
+ if (!possibleTypes.has("expression")) return undefined;
+ const rootName = getRootName(object);
+ if (!rootName) return undefined;
+
+ const result = this.getFreeInfoFromVariable(rootName);
+ if (!result) return undefined;
+ const { info: rootInfo, name: resolvedRoot } = result;
+ return {
+ type: "expression",
+ name: objectAndMembersToName(resolvedRoot, members),
+ rootInfo,
+ getMembers: memorize(() => members.reverse())
+ };
+ }
+ }
+ }
+
+ /**
+ * @param {MemberExpressionNode} expression an expression
+ * @returns {{ name: string, rootInfo: ExportedVariableInfo, getMembers: () => string[]}} name info
+ */
+ getNameForExpression(expression) {
+ return this.getMemberExpressionInfo(expression, ["expression"]);
+ }
+
/**
* @param {string} code source code
* @param {ParseOptions} options parsing options
diff --git a/lib/json/JsonParser.js b/lib/json/JsonParser.js
index 1c0fcdabd..b7032b4a9 100644
--- a/lib/json/JsonParser.js
+++ b/lib/json/JsonParser.js
@@ -44,6 +44,8 @@ class JsonParser extends Parser {
state.module.buildInfo.jsonData = data;
state.module.buildInfo.strict = true;
state.module.buildMeta.exportsType = "default";
+ state.module.buildMeta.defaultObject =
+ typeof data === "object" ? "redirect-warn" : false;
state.module.addDependency(
new JsonExportsDependency(JsonExportsDependency.getExportsFromData(data))
);
diff --git a/lib/optimize/ConcatenatedModule.js b/lib/optimize/ConcatenatedModule.js
index 610e79429..ebd401444 100644
--- a/lib/optimize/ConcatenatedModule.js
+++ b/lib/optimize/ConcatenatedModule.js
@@ -232,48 +232,50 @@ const getExternalImport = (
? ""
: Template.toNormalComment(`${exportName.join(".")}`);
let exprStart;
+ const exportsType = importedModule.getExportsType(strictHarmonyModule);
if (exportName.length === 0) {
- switch (importedModule.buildMeta.exportsType) {
- case "default":
+ switch (exportsType) {
+ case "dynamic-default":
+ case "default-only":
+ case "default-with-named":
info.interopNamespaceObjectUsed = true;
exprStart = info.interopNamespaceObjectName;
break;
case "namespace":
exprStart = info.name;
break;
+ case "dynamic":
+ exprStart = info.name;
+ break;
default:
- if (strictHarmonyModule) {
- info.interopNamespaceObjectUsed = true;
- exprStart = info.interopNamespaceObjectName;
- break;
- } else {
- exprStart = info.name;
- break;
- }
+ throw new Error(`Unexpected exportsType ${exportsType}`);
}
} else {
- switch (importedModule.buildMeta.exportsType) {
- case "default":
+ switch (exportsType) {
+ case "default-with-named":
case "namespace":
break;
- default:
- if (strictHarmonyModule) {
- if (exportName[0] === "default") {
- exprStart = info.name;
- } else {
- exprStart = "/* non-default import from non-esm module */undefined";
- }
+ case "default-only":
+ case "dynamic-default":
+ if (exportName[0] === "default") {
+ exprStart = info.name;
} else {
- if (exportName[0] === "default") {
- info.interopDefaultAccessUsed = true;
- exprStart = asCall
- ? `${info.interopDefaultAccessName}()`
- : asiSafe
- ? `(${info.interopDefaultAccessName}())`
- : `${info.interopDefaultAccessName}.a`;
- }
+ exprStart =
+ "/* non-default import from default-exporting module */undefined";
}
break;
+ case "dynamic":
+ if (exportName[0] === "default") {
+ info.interopDefaultAccessUsed = true;
+ exprStart = asCall
+ ? `${info.interopDefaultAccessName}()`
+ : asiSafe
+ ? `(${info.interopDefaultAccessName}())`
+ : `${info.interopDefaultAccessName}.a`;
+ }
+ break;
+ default:
+ throw new Error(`Unexpected exportsType ${exportsType}`);
}
}
if (exprStart) {
@@ -978,6 +980,7 @@ class ConcatenatedModule extends Module {
info.name = externalName;
if (
info.module.buildMeta.exportsType === "default" ||
+ info.module.buildMeta.exportsType === "flagged" ||
!info.module.buildMeta.exportsType
) {
const externalNameInterop = this.findNewName(
@@ -1090,7 +1093,10 @@ class ConcatenatedModule extends Module {
result.add(
`var ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${info.name}, 2);\n`
);
- } else if (!info.module.buildMeta.exportsType) {
+ } else if (
+ info.module.buildMeta.exportsType === "flagged" ||
+ !info.module.buildMeta.exportsType
+ ) {
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
result.add(
`var ${info.interopNamespaceObjectName} = /*#__PURE__*/${RuntimeGlobals.createFakeNamespaceObject}(${info.name});\n`
diff --git a/lib/optimize/MangleExportsPlugin.js b/lib/optimize/MangleExportsPlugin.js
index d0669f60a..6f2e86468 100644
--- a/lib/optimize/MangleExportsPlugin.js
+++ b/lib/optimize/MangleExportsPlugin.js
@@ -6,7 +6,11 @@
"use strict";
const { UsageState } = require("../ModuleGraph");
-const { numberToIdentifier } = require("../Template");
+const {
+ numberToIdentifier,
+ NUMBER_OF_IDENTIFIER_START_CHARS,
+ NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS
+} = require("../Template");
const { assignDeterministicIds } = require("../ids/IdHelpers");
const {
concatComparators,
@@ -62,7 +66,7 @@ const mangleExportsInfo = (exportsInfo, canBeArray) => {
// Don't rename 1-2 char exports or exports that can't be mangled
for (const exportInfo of exportsInfo.ownedExports) {
const name = exportInfo.name;
- if (typeof exportInfo.usedName !== "string") {
+ if (exportInfo.usedName === null) {
if (
exportInfo.canMangle !== true ||
(name.length === 1 && /^[a-zA-Z0-9_$]/.test(name)) ||
@@ -76,7 +80,8 @@ const mangleExportsInfo = (exportsInfo, canBeArray) => {
}
if (
exportInfo.exportsInfoOwned &&
- exportInfo.used === UsageState.OnlyPropertiesUsed
+ (exportInfo.used === UsageState.OnlyPropertiesUsed ||
+ exportInfo.used === UsageState.Unused)
) {
mangleExportsInfo(exportInfo.exportsInfo, true);
}
@@ -93,8 +98,11 @@ const mangleExportsInfo = (exportsInfo, canBeArray) => {
e.usedName = name;
return true;
},
- [26, 52],
- 52,
+ [
+ NUMBER_OF_IDENTIFIER_START_CHARS,
+ NUMBER_OF_IDENTIFIER_START_CHARS * NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS
+ ],
+ NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS,
usedNames.size
);
};
diff --git a/lib/util/internalSerializables.js b/lib/util/internalSerializables.js
index f01e4fd5e..e0af6cf40 100644
--- a/lib/util/internalSerializables.js
+++ b/lib/util/internalSerializables.js
@@ -32,8 +32,14 @@ module.exports = {
require("../dependencies/CachedConstDependency"),
"dependencies/CommonJsRequireContextDependency": () =>
require("../dependencies/CommonJsRequireContextDependency"),
+ "dependencies/CommonJsExportsDependency": () =>
+ require("../dependencies/CommonJsExportsDependency"),
+ "dependencies/CommonJsFullRequireDependency": () =>
+ require("../dependencies/CommonJsFullRequireDependency"),
"dependencies/CommonJsRequireDependency": () =>
require("../dependencies/CommonJsRequireDependency"),
+ "dependencies/CommonJsSelfReferenceDependency": () =>
+ require("../dependencies/CommonJsSelfReferenceDependency"),
"dependencies/ConstDependency": () =>
require("../dependencies/ConstDependency"),
"dependencies/ContextDependency": () =>
diff --git a/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js b/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js
index f6f0bc98c..bc2a8a0f1 100644
--- a/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js
+++ b/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js
@@ -57,6 +57,7 @@ class AsyncWebAssemblyJavascriptGenerator extends Generator {
runtimeRequirements
} = generateContext;
runtimeRequirements.add(RuntimeGlobals.module);
+ runtimeRequirements.add(RuntimeGlobals.moduleId);
runtimeRequirements.add(RuntimeGlobals.exports);
runtimeRequirements.add(RuntimeGlobals.instantiateWasm);
/** @type {InitFragment[]} */
@@ -120,6 +121,7 @@ class AsyncWebAssemblyJavascriptGenerator extends Generator {
asiSafe: true,
isCall: false,
callContext: false,
+ defaultInterop: true,
importVar,
initFragments,
runtimeRequirements
@@ -143,7 +145,7 @@ class AsyncWebAssemblyJavascriptGenerator extends Generator {
: undefined;
const instantiateCall =
- `${RuntimeGlobals.instantiateWasm}(${module.exportsArgument}, ${module.moduleArgument}.i` +
+ `${RuntimeGlobals.instantiateWasm}(${module.exportsArgument}, ${module.moduleArgument}.id` +
(importsObj ? `, ${importsObj})` : `)`);
const source = new RawSource(
diff --git a/lib/wasm/WebAssemblyJavascriptGenerator.js b/lib/wasm/WebAssemblyJavascriptGenerator.js
index 697654ec4..a0912689c 100644
--- a/lib/wasm/WebAssemblyJavascriptGenerator.js
+++ b/lib/wasm/WebAssemblyJavascriptGenerator.js
@@ -100,6 +100,7 @@ class WebAssemblyJavascriptGenerator extends Generator {
asiSafe: true,
isCall: false,
callContext: null,
+ defaultInterop: true,
initFragments,
runtimeRequirements
})
@@ -127,6 +128,7 @@ class WebAssemblyJavascriptGenerator extends Generator {
asiSafe: true,
isCall: false,
callContext: null,
+ defaultInterop: true,
initFragments,
runtimeRequirements
})};`,
@@ -164,6 +166,7 @@ class WebAssemblyJavascriptGenerator extends Generator {
// need these globals
runtimeRequirements.add(RuntimeGlobals.module);
+ runtimeRequirements.add(RuntimeGlobals.moduleId);
runtimeRequirements.add(RuntimeGlobals.wasmInstances);
if (exportsInfo.otherExportsInfo.used !== UsageState.Unused) {
runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
@@ -178,7 +181,7 @@ class WebAssemblyJavascriptGenerator extends Generator {
[
'"use strict";',
"// Instantiate WebAssembly module",
- `var wasmExports = ${RuntimeGlobals.wasmInstances}[${module.moduleArgument}.i];`,
+ `var wasmExports = ${RuntimeGlobals.wasmInstances}[${module.moduleArgument}.id];`,
exportsInfo.otherExportsInfo.used !== UsageState.Unused
? `${RuntimeGlobals.makeNamespaceObject}(${module.exportsArgument});`
diff --git a/test/Errors.test.js b/test/Errors.test.js
index 7a3a1442a..c7ca783f6 100644
--- a/test/Errors.test.js
+++ b/test/Errors.test.js
@@ -188,7 +188,7 @@ it("should emit warning for require.main.require", async () => {
"errors": Array [],
"warnings": Array [
Object {
- "loc": "1:0-20",
+ "loc": "1:0-30",
"message": "require.main.require is not supported by webpack.",
"moduleId": 0,
"moduleIdentifier": "/test/fixtures/errors/require.main.require.js",
@@ -207,7 +207,7 @@ it("should emit warning for module.parent.require", async () => {
"errors": Array [],
"warnings": Array [
Object {
- "loc": "1:0-21",
+ "loc": "1:0-31",
"message": "module.parent.require is not supported by webpack.",
"moduleId": 0,
"moduleIdentifier": "/test/fixtures/errors/module.parent.require.js",
diff --git a/test/Stats.test.js b/test/Stats.test.js
index db5de492b..b8a23a627 100644
--- a/test/Stats.test.js
+++ b/test/Stats.test.js
@@ -202,10 +202,10 @@ describe("Stats", () => {
"comparedForEmit": false,
"emitted": true,
"info": Object {
- "size": 198,
+ "size": 182,
},
"name": "entryA.js",
- "size": 198,
+ "size": 182,
},
Object {
"auxiliaryChunkIdHints": Array [],
@@ -217,10 +217,10 @@ describe("Stats", () => {
"comparedForEmit": false,
"emitted": true,
"info": Object {
- "size": 1881,
+ "size": 1865,
},
"name": "entryB.js",
- "size": 1881,
+ "size": 1865,
},
],
"assetsByChunkName": Object {
diff --git a/test/__snapshots__/StatsTestCases.test.js.snap b/test/__snapshots__/StatsTestCases.test.js.snap
index 4adbec241..4fac74991 100644
--- a/test/__snapshots__/StatsTestCases.test.js.snap
+++ b/test/__snapshots__/StatsTestCases.test.js.snap
@@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`StatsTestCases should print correct stats for aggressive-splitting-entry 1`] = `
-"Hash: 3e9a5156d285240100f86c0a654fac4022388023
+"Hash: 31d55881a19b3d2759ff5cdd6b7270331317c7f6
Child fitting:
- Hash: 3e9a5156d285240100f8
+ Hash: 31d55881a19b3d2759ff
Time: Xms
Built at: 1970-04-20 12:42:42
PublicPath: (none)
@@ -11,9 +11,9 @@ Child fitting:
fitting-1e85d2c6a3bb53369456.js 1.91 KiB [emitted] [immutable]
fitting-32fa512a201604f3e8b7.js 1.08 KiB [emitted] [immutable]
fitting-64ea4fa3fe9d8c4817d8.js 1.91 KiB [emitted] [immutable]
- fitting-924d7c5cc437ae97bc00.js 13 KiB [emitted] [immutable]
- Entrypoint main = fitting-1e85d2c6a3bb53369456.js fitting-64ea4fa3fe9d8c4817d8.js fitting-924d7c5cc437ae97bc00.js
- chunk fitting-924d7c5cc437ae97bc00.js 1.87 KiB (javascript) 6.44 KiB (runtime) [entry] [rendered]
+ fitting-7b2cab993ce99b4797fe.js 13 KiB [emitted] [immutable]
+ Entrypoint main = fitting-1e85d2c6a3bb53369456.js fitting-64ea4fa3fe9d8c4817d8.js fitting-7b2cab993ce99b4797fe.js
+ chunk fitting-7b2cab993ce99b4797fe.js 1.87 KiB (javascript) 6.44 KiB (runtime) [entry] [rendered]
> ./index main
./e.js 899 bytes [built]
./f.js 900 bytes [built]
@@ -31,17 +31,17 @@ Child fitting:
> ./g ./index.js 7:0-13
./g.js 916 bytes [built]
Child content-change:
- Hash: 6c0a654fac4022388023
+ Hash: 5cdd6b7270331317c7f6
Time: Xms
Built at: 1970-04-20 12:42:42
PublicPath: (none)
Asset Size
content-change-1e85d2c6a3bb53369456.js 1.91 KiB [emitted] [immutable]
- content-change-21dae9f8fb83a384de5a.js 13 KiB [emitted] [immutable]
content-change-32fa512a201604f3e8b7.js 1.08 KiB [emitted] [immutable]
content-change-64ea4fa3fe9d8c4817d8.js 1.91 KiB [emitted] [immutable]
- Entrypoint main = content-change-1e85d2c6a3bb53369456.js content-change-64ea4fa3fe9d8c4817d8.js content-change-21dae9f8fb83a384de5a.js
- chunk content-change-21dae9f8fb83a384de5a.js 1.87 KiB (javascript) 6.45 KiB (runtime) [entry] [rendered]
+ content-change-7e58af86a6d19030ceaa.js 13 KiB [emitted] [immutable]
+ Entrypoint main = content-change-1e85d2c6a3bb53369456.js content-change-64ea4fa3fe9d8c4817d8.js content-change-7e58af86a6d19030ceaa.js
+ chunk content-change-7e58af86a6d19030ceaa.js 1.87 KiB (javascript) 6.45 KiB (runtime) [entry] [rendered]
> ./index main
./e.js 899 bytes [built]
./f.js 900 bytes [built]
@@ -61,7 +61,7 @@ Child content-change:
`;
exports[`StatsTestCases should print correct stats for aggressive-splitting-on-demand 1`] = `
-"Hash: 1f444a718517af4d97d0
+"Hash: 291229eefd3fe9850e83
Time: Xms
Built at: 1970-04-20 12:42:42
PublicPath: (none)
@@ -70,7 +70,7 @@ PublicPath: (none)
21fd8e73389271e24957.js 1.91 KiB [emitted] [immutable]
64ea4fa3fe9d8c4817d8.js 1.91 KiB [emitted] [immutable]
6a2a05a9feb43a535129.js 1.91 KiB [emitted] [immutable]
-adff9df7a105cc65b63f.js 9.39 KiB [emitted] [immutable] [name: main]
+7dc5d02991fa5ab5ee39.js 9.34 KiB [emitted] [immutable] [name: main]
ae7ced4135ed4f2282f6.js 1.91 KiB [emitted] [immutable]
b4a95c5544295741de67.js 1010 bytes [emitted] [immutable]
b63bab94d02c84e0f081.js 1.91 KiB [emitted] [immutable]
@@ -78,12 +78,12 @@ db9a189ff52c97050941.js 1.91 KiB [emitted] [immutable]
de61daf57f7861bbb2f6.js 1.91 KiB [emitted] [immutable]
f80243284f4ab491b78e.js 1.91 KiB [emitted] [immutable]
fb5a5560e641649a6ed8.js 1010 bytes [emitted] [immutable]
-Entrypoint main = adff9df7a105cc65b63f.js
+Entrypoint main = 7dc5d02991fa5ab5ee39.js
chunk 64ea4fa3fe9d8c4817d8.js 1.76 KiB [rendered] [recorded] aggressive splitted
> ./c ./d ./e ./index.js 3:0-30
./c.js 899 bytes [built]
./d.js 899 bytes [built]
-chunk adff9df7a105cc65b63f.js (main) 248 bytes (javascript) 4.55 KiB (runtime) [entry] [rendered]
+chunk 7dc5d02991fa5ab5ee39.js (main) 248 bytes (javascript) 4.55 KiB (runtime) [entry] [rendered]
> ./index main
./index.js 248 bytes [built]
+ 5 hidden chunk modules
@@ -131,13 +131,13 @@ chunk b4a95c5544295741de67.js 899 bytes [rendered]
`;
exports[`StatsTestCases should print correct stats for asset 1`] = `
-"Hash: f6c1cb50597248a12805
+"Hash: af0de91ff8df9396500e
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
-7095cdad7dbe7d0415ca.png 14.6 KiB [emitted] [immutable] [name: (main)]
- bundle.js 10.7 KiB [emitted] [name: main]
-Entrypoint main = bundle.js (7095cdad7dbe7d0415ca.png)
+6eef074bdaf47143a239.png 14.6 KiB [emitted] [immutable] [name: (main)]
+ bundle.js 10.6 KiB [emitted] [name: main]
+Entrypoint main = bundle.js (6eef074bdaf47143a239.png)
./index.js 111 bytes [built]
./images/file.png 42 bytes (javascript) 14.6 KiB (asset) [built]
./images/file.svg 915 bytes [built]
@@ -445,13 +445,13 @@ Child all:
`;
exports[`StatsTestCases should print correct stats for chunk-module-id-range 1`] = `
-"Hash: fb5c63d2e82f70b6a022
+"Hash: 024b7b1350be3708ba8e
Time: Xms
Built at: 1970-04-20 12:42:42
PublicPath: (none)
Asset Size
-main1.js 4.44 KiB [emitted] [name: main1]
-main2.js 4.43 KiB [emitted] [name: main2]
+main1.js 4.39 KiB [emitted] [name: main1]
+main2.js 4.38 KiB [emitted] [name: main2]
Entrypoint main1 = main1.js
Entrypoint main2 = main2.js
chunk main2.js (main2) 136 bytes (javascript) 668 bytes (runtime) [entry] [rendered]
@@ -473,7 +473,7 @@ chunk main1.js (main1) 136 bytes (javascript) 668 bytes (runtime) [entry] [rende
`;
exports[`StatsTestCases should print correct stats for chunks 1`] = `
-"Hash: f7bc9eacfcfa73a582b4
+"Hash: 8aa3985794dcb0a9189a
Time: Xms
Built at: 1970-04-20 12:42:42
PublicPath: (none)
@@ -481,11 +481,12 @@ PublicPath: (none)
460.bundle.js 324 bytes [emitted]
524.bundle.js 210 bytes [emitted]
996.bundle.js 142 bytes [emitted]
- bundle.js 7.91 KiB [emitted] [name: main]
+ bundle.js 7.86 KiB [emitted] [name: main]
Entrypoint main = bundle.js
chunk bundle.js (main) 73 bytes (javascript) 4.25 KiB (runtime) >{460}< >{996}< [entry] [rendered]
> ./index main
./a.js 22 bytes [built]
+ cjs self exports reference ./a.js 1:0-14
cjs require ./a ./index.js 1:0-14
Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
./index.js 51 bytes [built]
@@ -501,31 +502,35 @@ chunk 524.bundle.js 44 bytes <{460}> [rendered]
> ./c.js 1:0-52
./d.js 22 bytes [built]
require.ensure item ./d ./c.js 1:0-52
+ cjs self exports reference ./d.js 1:0-14
Xms -> Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
./e.js 22 bytes [built]
require.ensure item ./e ./c.js 1:0-52
+ cjs self exports reference ./e.js 1:0-14
Xms -> Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
chunk 996.bundle.js 22 bytes <{179}> [rendered]
> ./b ./index.js 2:0-16
./b.js 22 bytes [built]
+ cjs self exports reference ./b.js 1:0-14
amd require ./b ./index.js 2:0-16
Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)"
`;
exports[`StatsTestCases should print correct stats for chunks-development 1`] = `
-"Hash: bed3963e09b8f3d8b779
+"Hash: bb9c09a55e8e0ee99069
Time: Xms
Built at: 1970-04-20 12:42:42
PublicPath: (none)
Asset Size
- b_js.bundle.js 359 bytes [emitted]
- bundle.js 8.49 KiB [emitted] [name: main]
- c_js.bundle.js 588 bytes [emitted]
-d_js-e_js.bundle.js 759 bytes [emitted]
+ b_js.bundle.js 400 bytes [emitted]
+ bundle.js 8.52 KiB [emitted] [name: main]
+ c_js.bundle.js 629 bytes [emitted]
+d_js-e_js.bundle.js 841 bytes [emitted]
Entrypoint main = bundle.js
chunk b_js.bundle.js 22 bytes <{main}> [rendered]
> ./b ./index.js 2:0-16
./b.js 22 bytes [built]
+ cjs self exports reference ./b.js 1:0-14
amd require ./b ./index.js 2:0-16
Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
chunk c_js.bundle.js 54 bytes <{main}> >{d_js-e_js}< [rendered]
@@ -537,13 +542,16 @@ chunk d_js-e_js.bundle.js 60 bytes <{c_js}> [rendered]
> ./c.js 1:0-52
./d.js 22 bytes [built]
require.ensure item ./d ./c.js 1:0-52
+ cjs self exports reference ./d.js 1:0-14
Xms -> Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
./e.js 38 bytes [built]
require.ensure item ./e ./c.js 1:0-52
+ cjs self exports reference ./e.js 2:0-14
Xms -> Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
chunk bundle.js (main) 73 bytes (javascript) 4.25 KiB (runtime) >{b_js}< >{c_js}< [entry] [rendered]
> ./index main
./a.js 22 bytes [built]
+ cjs self exports reference ./a.js 1:0-14
cjs require ./a ./e.js 1:0-14
cjs require ./a ./index.js 1:0-14
Xms -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
@@ -597,12 +605,12 @@ Entrypoint main = main.js
`;
exports[`StatsTestCases should print correct stats for commons-chunk-min-size-0 1`] = `
-"Hash: c78165fa4b8e1f543b90
+"Hash: 52d6ddbdf7da6ee8696f
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
429.js 278 bytes [emitted] [id hint: vendor-1]
-entry-1.js 5.37 KiB [emitted] [name: entry-1]
+entry-1.js 5.32 KiB [emitted] [name: entry-1]
Entrypoint entry-1 = 429.js entry-1.js
./entry-1.js 145 bytes [built]
./modules/a.js 22 bytes [built]
@@ -615,11 +623,11 @@ Entrypoint entry-1 = 429.js entry-1.js
`;
exports[`StatsTestCases should print correct stats for commons-chunk-min-size-Infinity 1`] = `
-"Hash: e1811e7bd2b08fe91369
+"Hash: 1ac8d9f0a39f52c3c2a6
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- entry-1.js 5.37 KiB [emitted] [name: entry-1]
+ entry-1.js 5.32 KiB [emitted] [name: entry-1]
vendor-1.js 278 bytes [emitted] [name: vendor-1] [id hint: vendor-1]
Entrypoint entry-1 = vendor-1.js entry-1.js
./entry-1.js 145 bytes [built]
@@ -633,26 +641,26 @@ Entrypoint entry-1 = vendor-1.js entry-1.js
`;
exports[`StatsTestCases should print correct stats for commons-plugin-issue-4980 1`] = `
-"Hash: f574fa9691641230a92dbf35dda4a5870c2b90b4
+"Hash: cc1067a9ed68395a22d361ebf4f77d289ef5d090
Child
- Hash: f574fa9691641230a92d
+ Hash: cc1067a9ed68395a22d3
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- app.6a509d33476291bd4b84-1.js 5.91 KiB [emitted] [immutable] [name: app]
- vendor.6b4bbfa3863de7632c2b-1.js 615 bytes [emitted] [immutable] [name: vendor] [id hint: vendor]
- Entrypoint app = vendor.6b4bbfa3863de7632c2b-1.js app.6a509d33476291bd4b84-1.js
+ app.e7c3ca90761b75404b15-1.js 5.86 KiB [emitted] [immutable] [name: app]
+ vendor.611fd9bad8fe7de29fe7-1.js 615 bytes [emitted] [immutable] [name: vendor] [id hint: vendor]
+ Entrypoint app = vendor.611fd9bad8fe7de29fe7-1.js app.e7c3ca90761b75404b15-1.js
./entry-1.js + 2 modules 190 bytes [built]
./constants.js 87 bytes [built]
+ 3 hidden modules
Child
- Hash: bf35dda4a5870c2b90b4
+ Hash: 61ebf4f77d289ef5d090
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- app.3e294cabb068ca84e0dc-2.js 5.92 KiB [emitted] [immutable] [name: app]
- vendor.6b4bbfa3863de7632c2b-2.js 615 bytes [emitted] [immutable] [name: vendor] [id hint: vendor]
- Entrypoint app = vendor.6b4bbfa3863de7632c2b-2.js app.3e294cabb068ca84e0dc-2.js
+ app.3543b1c65e6a5b58cae6-2.js 5.87 KiB [emitted] [immutable] [name: app]
+ vendor.611fd9bad8fe7de29fe7-2.js 615 bytes [emitted] [immutable] [name: vendor] [id hint: vendor]
+ Entrypoint app = vendor.611fd9bad8fe7de29fe7-2.js app.3543b1c65e6a5b58cae6-2.js
./entry-2.js + 2 modules 197 bytes [built]
./constants.js 87 bytes [built]
+ 3 hidden modules"
@@ -676,81 +684,81 @@ exports[`StatsTestCases should print correct stats for concat-and-sideeffects 1`
`;
exports[`StatsTestCases should print correct stats for context-independence 1`] = `
-"Hash: 3c160984a980dac95b913c160984a980dac95b9111fdc8efed5dc9a0356111fdc8efed5dc9a03561
+"Hash: 6506665a35d2ca5d31ac6506665a35d2ca5d31accf181f0e0e06350b116acf181f0e0e06350b116a
Child
- Hash: 3c160984a980dac95b91
+ Hash: 6506665a35d2ca5d31ac
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- 703-31a50198ea37e1d30825.js 438 bytes [emitted] [immutable]
- 703-31a50198ea37e1d30825.js.map 343 bytes [emitted] [dev]
- main-4124fe68a732c1b5d1ad.js 8.18 KiB [emitted] [immutable] [name: main]
- main-4124fe68a732c1b5d1ad.js.map 7.23 KiB [emitted] [dev] [name: (main)]
- Entrypoint main = main-4124fe68a732c1b5d1ad.js (main-4124fe68a732c1b5d1ad.js.map)
+ 703-3e2afd6460ceb1cd6f5f.js 438 bytes [emitted] [immutable]
+ 703-3e2afd6460ceb1cd6f5f.js.map 343 bytes [emitted] [dev]
+ main-a1003986d61ab330d2c5.js 8.14 KiB [emitted] [immutable] [name: main]
+ main-a1003986d61ab330d2c5.js.map 7.2 KiB [emitted] [dev] [name: (main)]
+ Entrypoint main = main-a1003986d61ab330d2c5.js (main-a1003986d61ab330d2c5.js.map)
./a/index.js 40 bytes [built]
./a/chunk.js + 1 modules 66 bytes [built]
+ 6 hidden modules
Child
- Hash: 3c160984a980dac95b91
+ Hash: 6506665a35d2ca5d31ac
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- 703-31a50198ea37e1d30825.js 438 bytes [emitted] [immutable]
- 703-31a50198ea37e1d30825.js.map 343 bytes [emitted] [dev]
- main-4124fe68a732c1b5d1ad.js 8.18 KiB [emitted] [immutable] [name: main]
- main-4124fe68a732c1b5d1ad.js.map 7.23 KiB [emitted] [dev] [name: (main)]
- Entrypoint main = main-4124fe68a732c1b5d1ad.js (main-4124fe68a732c1b5d1ad.js.map)
+ 703-3e2afd6460ceb1cd6f5f.js 438 bytes [emitted] [immutable]
+ 703-3e2afd6460ceb1cd6f5f.js.map 343 bytes [emitted] [dev]
+ main-a1003986d61ab330d2c5.js 8.14 KiB [emitted] [immutable] [name: main]
+ main-a1003986d61ab330d2c5.js.map 7.2 KiB [emitted] [dev] [name: (main)]
+ Entrypoint main = main-a1003986d61ab330d2c5.js (main-a1003986d61ab330d2c5.js.map)
./b/index.js 40 bytes [built]
./b/chunk.js + 1 modules 66 bytes [built]
+ 6 hidden modules
Child
- Hash: 11fdc8efed5dc9a03561
+ Hash: cf181f0e0e06350b116a
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- 703-71c02d17a0d4fdf148ec.js 962 bytes [emitted] [immutable]
- main-105b1b44c9785e4fec51.js 8.52 KiB [emitted] [immutable] [name: main]
- Entrypoint main = main-105b1b44c9785e4fec51.js
+ 703-d51a9ad771055bba3447.js 962 bytes [emitted] [immutable]
+ main-f8577eeb56b10147974d.js 8.48 KiB [emitted] [immutable] [name: main]
+ Entrypoint main = main-f8577eeb56b10147974d.js
./a/index.js 40 bytes [built]
./a/chunk.js + 1 modules 66 bytes [built]
+ 6 hidden modules
Child
- Hash: 11fdc8efed5dc9a03561
+ Hash: cf181f0e0e06350b116a
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- 703-71c02d17a0d4fdf148ec.js 962 bytes [emitted] [immutable]
- main-105b1b44c9785e4fec51.js 8.52 KiB [emitted] [immutable] [name: main]
- Entrypoint main = main-105b1b44c9785e4fec51.js
+ 703-d51a9ad771055bba3447.js 962 bytes [emitted] [immutable]
+ main-f8577eeb56b10147974d.js 8.48 KiB [emitted] [immutable] [name: main]
+ Entrypoint main = main-f8577eeb56b10147974d.js
./b/index.js 40 bytes [built]
./b/chunk.js + 1 modules 66 bytes [built]
+ 6 hidden modules"
`;
exports[`StatsTestCases should print correct stats for define-plugin 1`] = `
-"Hash: d3bf22fe31b2dd574a379f4263d8fe2702bed0c5263ccfc8da5389b5549d
+"Hash: c4dfb63f41372476179f8a83bd0cdb16b7f71a200e0127ecbe2c521924dd
Child
- Hash: d3bf22fe31b2dd574a37
+ Hash: c4dfb63f41372476179f
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- 123.js 1.33 KiB [emitted] [name: main]
+ Asset Size
+ 123.js 1.3 KiB [emitted] [name: main]
Entrypoint main = 123.js
./index.js 24 bytes [built]
Child
- Hash: 9f4263d8fe2702bed0c5
+ Hash: 8a83bd0cdb16b7f71a20
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- 321.js 1.33 KiB [emitted] [name: main]
+ Asset Size
+ 321.js 1.3 KiB [emitted] [name: main]
Entrypoint main = 321.js
./index.js 24 bytes [built]
Child
- Hash: 263ccfc8da5389b5549d
+ Hash: 0e0127ecbe2c521924dd
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- both.js 1.33 KiB [emitted] [name: main]
+ Asset Size
+ both.js 1.3 KiB [emitted] [name: main]
Entrypoint main = both.js
./index.js 24 bytes [built]"
`;
@@ -779,11 +787,11 @@ Unexpected end of JSON input while parsing near ''
`;
exports[`StatsTestCases should print correct stats for exclude-with-loader 1`] = `
-"Hash: 44a857698e21eeb6ec4a
+"Hash: 574b1154129671ae12ac
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
-bundle.js 3.51 KiB [emitted] [name: main]
+bundle.js 3.46 KiB [emitted] [name: main]
+ 1 hidden asset
Entrypoint main = bundle.js (5bcd36918d225eeda398ea3f372b7f16.json)
./index.js 77 bytes [built]
@@ -792,24 +800,24 @@ Entrypoint main = bundle.js (5bcd36918d225eeda398ea3f372b7f16.json)
`;
exports[`StatsTestCases should print correct stats for external 1`] = `
-"Hash: 5607d9fc220b23d6ba41
+"Hash: e1259a13508c6d1d1e0c
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
-main.js 1.25 KiB [emitted] [name: main]
+ Asset Size
+main.js 1.2 KiB [emitted] [name: main]
Entrypoint main = main.js
./index.js 17 bytes [built]
external \\"test\\" 42 bytes [built]"
`;
exports[`StatsTestCases should print correct stats for filter-warnings 1`] = `
-"Hash: 2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff2e946c1b63d5a742a8ff
+"Hash: 9c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed33269c6e8f427e9f60ed3326
Child undefined:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle0.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle0.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle0.js
WARNING in Terser Plugin: Dropping unused function someRemoteUnUsedFunction1 [webpack://./a.js:3,0]
@@ -835,53 +843,53 @@ Child undefined:
WARNING in Terser Plugin: Dropping unused function someUnUsedFunction5 [webpack://./index.js:12,0]
Child Terser:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle1.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle1.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle1.js
Child /Terser/:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle2.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle2.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle2.js
Child warnings => true:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle3.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle3.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle3.js
Child [Terser]:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle4.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle4.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle4.js
Child [/Terser/]:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle5.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle5.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle5.js
Child [warnings => true]:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle6.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle6.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle6.js
Child should not filter:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle7.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle7.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle7.js
WARNING in Terser Plugin: Dropping unused function someRemoteUnUsedFunction1 [webpack://./a.js:3,0]
@@ -907,11 +915,11 @@ Child should not filter:
WARNING in Terser Plugin: Dropping unused function someUnUsedFunction5 [webpack://./index.js:12,0]
Child /should not filter/:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle8.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle8.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle8.js
WARNING in Terser Plugin: Dropping unused function someRemoteUnUsedFunction1 [webpack://./a.js:3,0]
@@ -937,11 +945,11 @@ Child /should not filter/:
WARNING in Terser Plugin: Dropping unused function someUnUsedFunction5 [webpack://./index.js:12,0]
Child warnings => false:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle9.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle9.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle9.js
WARNING in Terser Plugin: Dropping unused function someRemoteUnUsedFunction1 [webpack://./a.js:3,0]
@@ -967,11 +975,11 @@ Child warnings => false:
WARNING in Terser Plugin: Dropping unused function someUnUsedFunction5 [webpack://./index.js:12,0]
Child [should not filter]:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle10.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle10.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle10.js
WARNING in Terser Plugin: Dropping unused function someRemoteUnUsedFunction1 [webpack://./a.js:3,0]
@@ -997,11 +1005,11 @@ Child [should not filter]:
WARNING in Terser Plugin: Dropping unused function someUnUsedFunction5 [webpack://./index.js:12,0]
Child [/should not filter/]:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle11.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle11.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle11.js
WARNING in Terser Plugin: Dropping unused function someRemoteUnUsedFunction1 [webpack://./a.js:3,0]
@@ -1027,11 +1035,11 @@ Child [/should not filter/]:
WARNING in Terser Plugin: Dropping unused function someUnUsedFunction5 [webpack://./index.js:12,0]
Child [warnings => false]:
- Hash: 2e946c1b63d5a742a8ff
+ Hash: 9c6e8f427e9f60ed3326
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
- bundle12.js 1010 bytes [emitted] [name: main]
+ Asset Size
+ bundle12.js 556 bytes [emitted] [name: main]
Entrypoint main = bundle12.js
WARNING in Terser Plugin: Dropping unused function someRemoteUnUsedFunction1 [webpack://./a.js:3,0]
@@ -1153,19 +1161,19 @@ chunk trees.js (trees) 71 bytes [rendered]
exports[`StatsTestCases should print correct stats for immutable 1`] = `
" Asset Size
-1b847d037d2872a4c68b.js 346 bytes [emitted] [immutable]
-945fb1b905025df1339f.js 9.88 KiB [emitted] [immutable] [name: main]"
+1b847d037d2872a4c68b.js 387 bytes [emitted] [immutable]
+945fb1b905025df1339f.js 9.87 KiB [emitted] [immutable] [name: main]"
`;
exports[`StatsTestCases should print correct stats for import-context-filter 1`] = `
-"Hash: fde587e1bdf604f24e67
+"Hash: 60c4e631146a1ea0f372
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
398.js 484 bytes [emitted]
544.js 484 bytes [emitted]
718.js 484 bytes [emitted]
-entry.js 9.61 KiB [emitted] [name: entry]
+entry.js 9.56 KiB [emitted] [name: entry]
Entrypoint entry = entry.js
./entry.js 450 bytes [built]
./templates lazy ^\\\\.\\\\/.*$ include: \\\\.js$ exclude: \\\\.noimport\\\\.js$ namespace object 160 bytes [optional] [built]
@@ -1176,7 +1184,7 @@ Entrypoint entry = entry.js
`;
exports[`StatsTestCases should print correct stats for import-weak 1`] = `
-"Hash: 413c9966016a5c6b709a
+"Hash: 7160e41d3347e9709803
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1213,42 +1221,42 @@ Compilation error while processing magic comment(-s): /* webpackPrefetch: nope *
`;
exports[`StatsTestCases should print correct stats for issue-7577 1`] = `
-"Hash: db17495307f9577cdf0574f8b47a2c1a85c2641ba52e42c5fb5bcb0d0cc1
+"Hash: 94b82a2154c061cc7c6bb42f5fd308c78eb622dd3f7a76e8638213c06464
Child
- Hash: db17495307f9577cdf05
+ Hash: 94b82a2154c061cc7c6b
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
a-all-a_js-a0ca01d3da48ab4385f6.js 144 bytes [emitted] [immutable] [id hint: all]
a-main-fa06855251b873131c2c.js 115 bytes [emitted] [immutable] [name: main]
- a-runtime~main-58c0c5b1e0b10f369a33.js 4.93 KiB [emitted] [immutable] [name: runtime~main]
- Entrypoint main = a-runtime~main-58c0c5b1e0b10f369a33.js a-all-a_js-a0ca01d3da48ab4385f6.js a-main-fa06855251b873131c2c.js
+ a-runtime~main-286640ef21ec9cc6b07a.js 4.88 KiB [emitted] [immutable] [name: runtime~main]
+ Entrypoint main = a-runtime~main-286640ef21ec9cc6b07a.js a-all-a_js-a0ca01d3da48ab4385f6.js a-main-fa06855251b873131c2c.js
./a.js 18 bytes [built]
+ 2 hidden modules
Child
- Hash: 74f8b47a2c1a85c2641b
+ Hash: b42f5fd308c78eb622dd
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- b-all-b_js-3219344d13cc334d7831.js 479 bytes [emitted] [immutable] [id hint: all]
- b-main-6da637b8d22f213c8475.js 148 bytes [emitted] [immutable] [name: main]
- b-runtime~main-79835f2c8b4a4d8e8e21.js 5.86 KiB [emitted] [immutable] [name: runtime~main]
+ b-all-b_js-50bf184dfe57dc2022a6.js 479 bytes [emitted] [immutable] [id hint: all]
+ b-main-ffc8dbdfb8f2c2b16817.js 148 bytes [emitted] [immutable] [name: main]
+ b-runtime~main-a6e42222a1a01acc0438.js 5.81 KiB [emitted] [immutable] [name: runtime~main]
b-vendors-node_modules_vendor_js-a51f8ed2c8dc9ce97afd.js 189 bytes [emitted] [immutable] [id hint: vendors]
- Entrypoint main = b-runtime~main-79835f2c8b4a4d8e8e21.js b-vendors-node_modules_vendor_js-a51f8ed2c8dc9ce97afd.js b-all-b_js-3219344d13cc334d7831.js b-main-6da637b8d22f213c8475.js
+ Entrypoint main = b-runtime~main-a6e42222a1a01acc0438.js b-vendors-node_modules_vendor_js-a51f8ed2c8dc9ce97afd.js b-all-b_js-50bf184dfe57dc2022a6.js b-main-ffc8dbdfb8f2c2b16817.js
./b.js 17 bytes [built]
./node_modules/vendor.js 23 bytes [built]
+ 4 hidden modules
Child
- Hash: a52e42c5fb5bcb0d0cc1
+ Hash: 3f7a76e8638213c06464
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- c-all-b_js-3219344d13cc334d7831.js 506 bytes [emitted] [immutable] [id hint: all]
- c-all-c_js-6756694a5d280748f5a3.js 382 bytes [emitted] [immutable] [id hint: all]
+ c-all-b_js-50bf184dfe57dc2022a6.js 506 bytes [emitted] [immutable] [id hint: all]
+ c-all-c_js-6756694a5d280748f5a3.js 397 bytes [emitted] [immutable] [id hint: all]
c-main-476756bfcb471445cf2c.js 164 bytes [emitted] [immutable] [name: main]
- c-runtime~main-346ca173662bb43e22ef.js 11.4 KiB [emitted] [immutable] [name: runtime~main]
+ c-runtime~main-912fc4f81a625e30b5f0.js 11.3 KiB [emitted] [immutable] [name: runtime~main]
c-vendors-node_modules_vendor_js-a51f8ed2c8dc9ce97afd.js 189 bytes [emitted] [immutable] [id hint: vendors]
- Entrypoint main = c-runtime~main-346ca173662bb43e22ef.js c-all-c_js-6756694a5d280748f5a3.js c-main-476756bfcb471445cf2c.js (prefetch: c-vendors-node_modules_vendor_js-a51f8ed2c8dc9ce97afd.js c-all-b_js-3219344d13cc334d7831.js)
+ Entrypoint main = c-runtime~main-912fc4f81a625e30b5f0.js c-all-c_js-6756694a5d280748f5a3.js c-main-476756bfcb471445cf2c.js (prefetch: c-vendors-node_modules_vendor_js-a51f8ed2c8dc9ce97afd.js c-all-b_js-50bf184dfe57dc2022a6.js)
./c.js 61 bytes [built]
./b.js 17 bytes [built]
./node_modules/vendor.js 23 bytes [built]
@@ -1256,13 +1264,13 @@ Child
`;
exports[`StatsTestCases should print correct stats for limit-chunk-count-plugin 1`] = `
-"Hash: a0800a69d4b65916acc0edef925c59c09542572206d0ef7ed1356dcf7ae27c24a1e7619f90a97b8a
+"Hash: 15b4b06d5bdcf1dbb317c2ee020bd44fb8139f6b23dbaedcbaa797e2000666278eec152159ba577e
Child 1 chunks:
- Hash: a0800a69d4b65916acc0
+ Hash: 15b4b06d5bdcf1dbb317
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- bundle1.js 4.19 KiB [emitted] [name: main]
+ bundle1.js 4.14 KiB [emitted] [name: main]
Entrypoint main = bundle1.js
chunk bundle1.js (main) 219 bytes (javascript) 1.32 KiB (runtime) <{179}> >{179}< [entry] [rendered]
./a.js 22 bytes [built]
@@ -1273,12 +1281,12 @@ Child 1 chunks:
./index.js 101 bytes [built]
+ 4 hidden chunk modules
Child 2 chunks:
- Hash: edef925c59c095425722
+ Hash: c2ee020bd44fb8139f6b
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
459.bundle2.js 666 bytes [emitted] [name: c]
- bundle2.js 9.82 KiB [emitted] [name: main]
+ bundle2.js 9.77 KiB [emitted] [name: main]
Entrypoint main = bundle2.js
chunk bundle2.js (main) 101 bytes (javascript) 5.48 KiB (runtime) >{459}< [entry] [rendered]
./index.js 101 bytes [built]
@@ -1290,13 +1298,13 @@ Child 2 chunks:
./d.js 22 bytes [built]
./e.js 22 bytes [built]
Child 3 chunks:
- Hash: 06d0ef7ed1356dcf7ae2
+ Hash: 23dbaedcbaa797e20006
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
459.bundle3.js 530 bytes [emitted] [name: c]
524.bundle3.js 210 bytes [emitted]
- bundle3.js 9.82 KiB [emitted] [name: main]
+ bundle3.js 9.77 KiB [emitted] [name: main]
Entrypoint main = bundle3.js
chunk bundle3.js (main) 101 bytes (javascript) 5.48 KiB (runtime) >{459}< [entry] [rendered]
./index.js 101 bytes [built]
@@ -1309,14 +1317,14 @@ Child 3 chunks:
./d.js 22 bytes [built]
./e.js 22 bytes [built]
Child 4 chunks:
- Hash: 7c24a1e7619f90a97b8a
+ Hash: 66278eec152159ba577e
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
394.bundle4.js 210 bytes [emitted]
459.bundle4.js 394 bytes [emitted] [name: c]
524.bundle4.js 210 bytes [emitted]
- bundle4.js 9.82 KiB [emitted] [name: main]
+ bundle4.js 9.77 KiB [emitted] [name: main]
Entrypoint main = bundle4.js
chunk bundle4.js (main) 101 bytes (javascript) 5.48 KiB (runtime) >{394}< >{459}< [entry] [rendered]
./index.js 101 bytes [built]
@@ -1374,11 +1382,11 @@ Entrypoint main = main.js
`;
exports[`StatsTestCases should print correct stats for max-modules 1`] = `
-"Hash: 41d1bca9d8ea1cc53215
+"Hash: 896d8a1d7b73a2ef9139
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
-main.js 5.34 KiB [emitted] [name: main]
+main.js 5.29 KiB [emitted] [name: main]
Entrypoint main = main.js
./index.js 181 bytes [built]
./a.js?1 33 bytes [built]
@@ -1404,11 +1412,11 @@ Entrypoint main = main.js
`;
exports[`StatsTestCases should print correct stats for max-modules-default 1`] = `
-"Hash: 41d1bca9d8ea1cc53215
+"Hash: 896d8a1d7b73a2ef9139
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
-main.js 5.34 KiB [emitted] [name: main]
+main.js 5.29 KiB [emitted] [name: main]
Entrypoint main = main.js
./index.js 181 bytes [built]
./a.js?1 33 bytes [built]
@@ -1429,7 +1437,7 @@ Entrypoint main = main.js
`;
exports[`StatsTestCases should print correct stats for module-assets 1`] = `
-"Hash: 6c0e387dd087e95c56bb
+"Hash: 7ab754f97dbdb21a19b7
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1437,7 +1445,7 @@ Built at: 1970-04-20 12:42:42
2.png 21 KiB [emitted] [name: (a, b)]
a.js 988 bytes [emitted] [name: a]
b.js 616 bytes [emitted] [name: b]
-main.js 9.12 KiB [emitted] [name: main]
+main.js 9.1 KiB [emitted] [name: main]
Entrypoint main = main.js
Chunk Group a = a.js (1.png 2.png)
Chunk Group b = b.js (2.png)
@@ -1513,12 +1521,12 @@ chunk 923.js 37 bytes [rendered]
exports[`StatsTestCases should print correct stats for module-deduplication-named 1`] = `
" Asset Size
-async1.js 824 bytes [emitted] [name: async1]
-async2.js 824 bytes [emitted] [name: async2]
-async3.js 824 bytes [emitted] [name: async3]
- e1.js 10.2 KiB [emitted] [name: e1]
- e2.js 10.2 KiB [emitted] [name: e2]
- e3.js 10.2 KiB [emitted] [name: e3]
+async1.js 839 bytes [emitted] [name: async1]
+async2.js 839 bytes [emitted] [name: async2]
+async3.js 839 bytes [emitted] [name: async3]
+ e1.js 10.1 KiB [emitted] [name: e1]
+ e2.js 10.1 KiB [emitted] [name: e2]
+ e3.js 10.1 KiB [emitted] [name: e3]
Entrypoint e1 = e1.js
Entrypoint e2 = e2.js
Entrypoint e3 = e3.js
@@ -1580,11 +1588,11 @@ If you don't want to include a polyfill, you can use an empty module like this:
`;
exports[`StatsTestCases should print correct stats for module-reasons 1`] = `
-"Hash: c7a7f12c42b568c704da
+"Hash: a74cbe7b899ea89c631e
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
-main.js 1.46 KiB [emitted] [name: main]
+ Asset Size
+main.js 1.4 KiB [emitted] [name: main]
Entrypoint main = main.js
./index.js + 2 modules 102 bytes [built]
entry ./index main
@@ -1701,11 +1709,11 @@ Child
`;
exports[`StatsTestCases should print correct stats for named-chunks-plugin 1`] = `
-"Hash: c2a9265bba5ea48f8d32
+"Hash: 477a050407dcda362944
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- entry.js 5.24 KiB [emitted] [name: entry]
+ entry.js 5.19 KiB [emitted] [name: entry]
vendor.js 241 bytes [emitted] [name: vendor] [id hint: vendor]
Entrypoint entry = vendor.js entry.js
./entry.js 72 bytes [built]
@@ -1716,11 +1724,11 @@ Entrypoint entry = vendor.js entry.js
`;
exports[`StatsTestCases should print correct stats for named-chunks-plugin-async 1`] = `
-"Hash: 5b2d8bf6cb7123270228
+"Hash: b805309f74f84a36f101
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
- entry.js 9.68 KiB [emitted] [name: entry]
+ entry.js 9.63 KiB [emitted] [name: entry]
modules_a_js.js 316 bytes [emitted]
modules_b_js.js 153 bytes [emitted]
Entrypoint entry = entry.js
@@ -1745,7 +1753,7 @@ You can also set it to 'none' to disable any default behavior. Learn more: https
`;
exports[`StatsTestCases should print correct stats for optimize-chunks 1`] = `
-"Hash: 7311a4db759e711d1ef5
+"Hash: eb848647a72300169555
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1756,7 +1764,7 @@ Built at: 1970-04-20 12:42:42
cir1.js 334 bytes [emitted] [name: cir1]
cir2 from cir1.js 378 bytes [emitted] [name: cir2 from cir1]
cir2.js 334 bytes [emitted] [name: cir2]
- main.js 8.71 KiB [emitted] [name: main]
+ main.js 8.66 KiB [emitted] [name: main]
Entrypoint main = main.js
chunk ab.js (ab) 2 bytes <{179}> >{753}< [rendered]
> ./index.js 1:0-6:8
@@ -1813,9 +1821,9 @@ You may need an appropriate loader to handle this file type, currently no loader
`;
exports[`StatsTestCases should print correct stats for performance-different-mode-and-target 1`] = `
-"Hash: 085386bf0cb4accbb1eb085386bf0cb4accbb1eb085386bf0cb4accbb1eb1499b9952c8259430fac1499b9952c8259430fac1499b9952c8259430fac085386bf0cb4accbb1eb
+"Hash: 604851a4140d08550dd4604851a4140d08550dd4604851a4140d08550dd45cbd53d350a417320d6a5cbd53d350a417320d6a5cbd53d350a417320d6a604851a4140d08550dd4
Child
- Hash: 085386bf0cb4accbb1eb
+ Hash: 604851a4140d08550dd4
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1838,7 +1846,7 @@ Child
For more info visit https://webpack.js.org/guides/code-splitting/
Child
- Hash: 085386bf0cb4accbb1eb
+ Hash: 604851a4140d08550dd4
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1861,7 +1869,7 @@ Child
For more info visit https://webpack.js.org/guides/code-splitting/
Child
- Hash: 085386bf0cb4accbb1eb
+ Hash: 604851a4140d08550dd4
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1869,7 +1877,7 @@ Child
Entrypoint main = no-warning.pro-node.js
./index.js 293 KiB [built]
Child
- Hash: 1499b9952c8259430fac
+ Hash: 5cbd53d350a417320d6a
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1877,7 +1885,7 @@ Child
Entrypoint main = no-warning.dev-web.js
./index.js 293 KiB [built]
Child
- Hash: 1499b9952c8259430fac
+ Hash: 5cbd53d350a417320d6a
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1885,7 +1893,7 @@ Child
Entrypoint main = no-warning.dev-node.js
./index.js 293 KiB [built]
Child
- Hash: 1499b9952c8259430fac
+ Hash: 5cbd53d350a417320d6a
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1893,7 +1901,7 @@ Child
Entrypoint main [big] = no-warning.dev-web-with-limit-set.js
./index.js 293 KiB [built]
Child
- Hash: 085386bf0cb4accbb1eb
+ Hash: 604851a4140d08550dd4
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -1970,7 +1978,7 @@ exports[`StatsTestCases should print correct stats for performance-no-async-chun
Built at: 1970-04-20 12:42:42
Asset Size
main.js 294 KiB [emitted] [big] [name: main]
- sec.js 1.41 KiB [emitted] [name: sec]
+ sec.js 1.36 KiB [emitted] [name: sec]
Entrypoint main [big] = main.js
Entrypoint sec = sec.js
./index.js 32 bytes [built]
@@ -2084,7 +2092,7 @@ exports[`StatsTestCases should print correct stats for preload 1`] = `
" Asset Size
inner.js 114 bytes [emitted] [name: inner]
inner2.js 154 bytes [emitted] [name: inner2]
- main.js 11.9 KiB [emitted] [name: main]
+ main.js 11.8 KiB [emitted] [name: main]
normal.js 113 bytes [emitted] [name: normal]
preloaded.js 557 bytes [emitted] [name: preloaded]
preloaded2.js 113 bytes [emitted] [name: preloaded2]
@@ -2108,7 +2116,7 @@ exports[`StatsTestCases should print correct stats for preset-detailed 1`] = `
<+> [LogTestPlugin] Collaped group
[LogTestPlugin] Log
[LogTestPlugin] End
-Hash: cc6b3725f6c0e8507ded
+Hash: 75c2283ae108b4adfd48
Time: Xms
Built at: 1970-04-20 12:42:42
PublicPath: (none)
@@ -2116,7 +2124,7 @@ PublicPath: (none)
460.js 324 bytes {460} [emitted]
524.js 210 bytes {524} [emitted]
996.js 142 bytes {996} [emitted]
-main.js 7.91 KiB {179} [emitted] [name: main]
+main.js 7.86 KiB {179} [emitted] [name: main]
Entrypoint main = main.js
chunk {179} main.js (main) 73 bytes (javascript) 4.24 KiB (runtime) >{460}< >{996}< [entry] [rendered]
> ./index main
@@ -2228,14 +2236,14 @@ exports[`StatsTestCases should print correct stats for preset-normal 1`] = `
" [LogTestPlugin] Error
[LogTestPlugin] Warning
[LogTestPlugin] Info
-Hash: cc6b3725f6c0e8507ded
+Hash: 75c2283ae108b4adfd48
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
460.js 324 bytes [emitted]
524.js 210 bytes [emitted]
996.js 142 bytes [emitted]
-main.js 7.91 KiB [emitted] [name: main]
+main.js 7.86 KiB [emitted] [name: main]
Entrypoint main = main.js
./index.js 51 bytes [built]
./a.js 22 bytes [built]
@@ -2329,7 +2337,7 @@ exports[`StatsTestCases should print correct stats for preset-verbose 1`] = `
[LogTestPlugin] Inner inner message
[LogTestPlugin] Log
[LogTestPlugin] End
-Hash: cc6b3725f6c0e8507ded
+Hash: 75c2283ae108b4adfd48
Time: Xms
Built at: 1970-04-20 12:42:42
PublicPath: (none)
@@ -2337,12 +2345,13 @@ PublicPath: (none)
460.js 324 bytes {460} [emitted]
524.js 210 bytes {524} [emitted]
996.js 142 bytes {996} [emitted]
-main.js 7.91 KiB {179} [emitted] [name: main]
+main.js 7.86 KiB {179} [emitted] [name: main]
Entrypoint main = main.js
chunk {179} main.js (main) 73 bytes (javascript) 4.24 KiB (runtime) >{460}< >{996}< [entry] [rendered]
> ./index main
[847] ./a.js 22 bytes {179} [depth 1] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
+ cjs self exports reference [847] ./a.js 1:0-14
cjs require ./a [10] ./index.js 1:0-14
Xms [10] -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
[10] ./index.js 51 bytes {179} [depth 0] [built]
@@ -2376,15 +2385,18 @@ chunk {524} 524.js 44 bytes <{460}> [rendered]
[767] ./d.js 22 bytes {524} [depth 2] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
require.ensure item ./d [460] ./c.js 1:0-52
+ cjs self exports reference [767] ./d.js 1:0-14
Xms [10] -> Xms [460] -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
[390] ./e.js 22 bytes {524} [depth 2] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
require.ensure item ./e [460] ./c.js 1:0-52
+ cjs self exports reference [390] ./e.js 1:0-14
Xms [10] -> Xms [460] -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
chunk {996} 996.js 22 bytes <{179}> [rendered]
> ./b [10] ./index.js 2:0-16
[996] ./b.js 22 bytes {996} [depth 1] [built]
ModuleConcatenation bailout: Module is not an ECMAScript module
+ cjs self exports reference [996] ./b.js 1:0-14
amd require ./b [10] ./index.js 2:0-16
Xms [10] -> Xms (resolving: Xms, restoring: Xms, integration: Xms, building: Xms, storing: Xms)
@@ -2433,11 +2445,11 @@ LOG from webpack.SplitChunksPlugin
`;
exports[`StatsTestCases should print correct stats for resolve-plugin-context 1`] = `
-"Hash: b424ab63ddfccbe2edb4
+"Hash: 2b3ef749cda92d3cfac9
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
-bundle.js 1.55 KiB [emitted] [name: main]
+ Asset Size
+bundle.js 1.5 KiB [emitted] [name: main]
Entrypoint main = bundle.js
./index.js 48 bytes [built]
./node_modules/abc/index.js 16 bytes [built]
@@ -2447,11 +2459,11 @@ Entrypoint main = bundle.js
`;
exports[`StatsTestCases should print correct stats for reverse-sort-modules 1`] = `
-"Hash: 41d1bca9d8ea1cc53215
+"Hash: 896d8a1d7b73a2ef9139
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
-main.js 5.34 KiB [emitted] [name: main]
+main.js 5.29 KiB [emitted] [name: main]
Entrypoint main = main.js
./index.js 181 bytes [built]
./a.js?1 33 bytes [built]
@@ -2485,8 +2497,8 @@ exports[`StatsTestCases should print correct stats for runtime-chunk-integration
"Child base:
Asset Size
without-505.js 1.22 KiB [emitted]
- without-main1.js 556 bytes [emitted] [name: main1]
- without-runtime.js 9.83 KiB [emitted] [name: runtime]
+ without-main1.js 601 bytes [emitted] [name: main1]
+ without-runtime.js 9.78 KiB [emitted] [name: runtime]
Entrypoint main1 = without-runtime.js without-main1.js
./main1.js 66 bytes [built]
./b.js 20 bytes [built]
@@ -2496,8 +2508,8 @@ exports[`StatsTestCases should print correct stats for runtime-chunk-integration
Child manifest is named entry:
Asset Size
with-505.js 1.22 KiB [emitted]
- with-main1.js 556 bytes [emitted] [name: main1]
- with-manifest.js 9.96 KiB [emitted] [name: manifest]
+ with-main1.js 601 bytes [emitted] [name: main1]
+ with-manifest.js 9.91 KiB [emitted] [name: manifest]
Entrypoint main1 = with-manifest.js with-main1.js
Entrypoint manifest = with-manifest.js
./main1.js 66 bytes [built]
@@ -2519,7 +2531,7 @@ Entrypoint e2 = runtime.js e2.js"
`;
exports[`StatsTestCases should print correct stats for scope-hoisting-bailouts 1`] = `
-"Hash: 6c0e3ff2d7cd6333531e
+"Hash: ea361a8a1e8207bed262
Time: Xms
Built at: 1970-04-20 12:42:42
Entrypoint index = index.js
@@ -2549,9 +2561,9 @@ external \\"external\\" 42 bytes [built]
`;
exports[`StatsTestCases should print correct stats for scope-hoisting-multi 1`] = `
-"Hash: c32b7b7b3c075bb1b7ee58dad7f1031821535004
+"Hash: e2c7355c011145721c930f50cdfccf67cfa8eb2a
Child
- Hash: c32b7b7b3c075bb1b7ee
+ Hash: e2c7355c011145721c93
Time: Xms
Built at: 1970-04-20 12:42:42
Entrypoint first = a-vendor.js a-first.js
@@ -2569,7 +2581,7 @@ Child
./common_lazy_shared.js 25 bytes [built]
+ 12 hidden modules
Child
- Hash: 58dad7f1031821535004
+ Hash: 0f50cdfccf67cfa8eb2a
Time: Xms
Built at: 1970-04-20 12:42:42
Entrypoint first = b-vendor.js b-first.js
@@ -2596,12 +2608,12 @@ Child
`;
exports[`StatsTestCases should print correct stats for side-effects-issue-7428 1`] = `
-"Hash: 058fc77aba938f0dc820
+"Hash: dd7339ec873427ae72f9
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
1.js 642 bytes [emitted]
-main.js 9.94 KiB [emitted] [name: main]
+main.js 9.9 KiB [emitted] [name: main]
Entrypoint main = main.js
./main.js + 1 modules 231 bytes [built]
[no exports used]
@@ -2647,7 +2659,7 @@ Entrypoint main = main.js
`;
exports[`StatsTestCases should print correct stats for side-effects-simple-unused 1`] = `
-"Hash: 016a135c0421bd2fc947
+"Hash: 5e65a865b852c4d57af6
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
@@ -2684,7 +2696,7 @@ exports[`StatsTestCases should print correct stats for simple 1`] = `
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
-bundle.js 270 bytes [emitted] [name: main]
+bundle.js 311 bytes [emitted] [name: main]
Entrypoint main = bundle.js
./index.js 1 bytes [built]"
`;
@@ -3698,11 +3710,11 @@ chunk default/async-a.js (async-a) 134 bytes <{179}> [rendered]
`;
exports[`StatsTestCases should print correct stats for tree-shaking 1`] = `
-"Hash: 7682a53187338c456c65
+"Hash: 06b3690c160b35374c1d
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
-bundle.js 7.23 KiB [emitted] [name: main]
+bundle.js 7.17 KiB [emitted] [name: main]
Entrypoint main = bundle.js
./index.js 316 bytes [built] [1 warning]
[no exports]
@@ -3741,11 +3753,11 @@ require.include() is deprecated and will be removed soon.
`;
exports[`StatsTestCases should print correct stats for warnings-terser 1`] = `
-"Hash: fd5c5b8a9bb97e3968a4
+"Hash: dcfa5b734e4c3a1e9e77
Time: Xms
Built at: 1970-04-20 12:42:42
- Asset Size
-bundle.js 1010 bytes [emitted] [name: main]
+ Asset Size
+bundle.js 823 bytes [emitted] [name: main]
Entrypoint main = bundle.js
./index.js 299 bytes [built]
[no exports used]
@@ -3765,20 +3777,20 @@ WARNING in Terser Plugin: Dropping unused function someUnRemoteUsedFunction5 [we
`;
exports[`StatsTestCases should print correct stats for wasm-explorer-examples-sync 1`] = `
-"Hash: c2f1d1cb06dadb29613f
+"Hash: ebe9b2a585519304a1c8
Time: Xms
Built at: 1970-04-20 12:42:42
Asset Size
1d55f77c08cd19684f13.module.wasm 154 bytes [emitted] [immutable]
200c03abdc3f4ae1e15c.module.wasm 290 bytes [emitted] [immutable]
- 230.bundle.js 221 bytes [emitted]
+ 230.bundle.js 222 bytes [emitted]
256e72dd8b9a83a6e45b.module.wasm 120 bytes [emitted] [immutable]
325.bundle.js 3.74 KiB [emitted]
526.bundle.js 368 bytes [emitted] [id hint: vendors]
- 780.bundle.js 524 bytes [emitted]
- 99.bundle.js 219 bytes [emitted]
+ 780.bundle.js 526 bytes [emitted]
+ 99.bundle.js 220 bytes [emitted]
a0e9dd97d7ced35a5b2c.module.wasm 154 bytes [emitted] [immutable]
- bundle.js 11.1 KiB [emitted] [name: main-1df31ce3]
+ bundle.js 11.2 KiB [emitted] [name: main-1df31ce3]
d37b3336426771c2a6e2.module.wasm 531 bytes [emitted] [immutable]
ebd3f263522776d85971.module.wasm 156 bytes [emitted] [immutable]
Entrypoint main = bundle.js
diff --git a/test/cases/cjs-tree-shaking/bailouts/accessing-call-context.js b/test/cases/cjs-tree-shaking/bailouts/accessing-call-context.js
new file mode 100644
index 000000000..1e925b722
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/accessing-call-context.js
@@ -0,0 +1,5 @@
+module.exports.func = function f() {
+ "use strict";
+ return this;
+};
+module.exports.abc = "abc";
diff --git a/test/cases/cjs-tree-shaking/bailouts/accessing-module.js b/test/cases/cjs-tree-shaking/bailouts/accessing-module.js
new file mode 100644
index 000000000..1ae2ff1eb
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/accessing-module.js
@@ -0,0 +1,7 @@
+exports.abc = "abc";
+
+function f(m) {
+ m.exports = { abc: "abc", def: "def" };
+}
+
+f(module);
diff --git a/test/cases/cjs-tree-shaking/bailouts/assign-exports-assign.js b/test/cases/cjs-tree-shaking/bailouts/assign-exports-assign.js
new file mode 100644
index 000000000..5382b0246
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/assign-exports-assign.js
@@ -0,0 +1,6 @@
+exports.abc = "abc";
+
+var newObj = {};
+exports = newObj;
+
+exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/bailouts/assign-exports-define.js b/test/cases/cjs-tree-shaking/bailouts/assign-exports-define.js
new file mode 100644
index 000000000..416b24a58
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/assign-exports-define.js
@@ -0,0 +1,6 @@
+Object.defineProperty(exports, "abc", { value: "abc" });
+
+var newObj = {};
+exports = newObj;
+
+Object.defineProperty(exports, "def", { value: "def" });
diff --git a/test/cases/cjs-tree-shaking/bailouts/define-module-properties.js b/test/cases/cjs-tree-shaking/bailouts/define-module-properties.js
new file mode 100644
index 000000000..3e2c0dfb1
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/define-module-properties.js
@@ -0,0 +1,10 @@
+exports.abc = "abc";
+
+Object.defineProperties(module, {
+ exports: {
+ value: {
+ abc: "abc",
+ def: "def"
+ }
+ }
+});
diff --git a/test/cases/cjs-tree-shaking/bailouts/define-module-property.js b/test/cases/cjs-tree-shaking/bailouts/define-module-property.js
new file mode 100644
index 000000000..2ec922101
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/define-module-property.js
@@ -0,0 +1,8 @@
+exports.abc = "abc";
+
+Object.defineProperty(module, "exports", {
+ value: {
+ abc: "abc",
+ def: "def"
+ }
+});
diff --git a/test/cases/cjs-tree-shaking/bailouts/index.js b/test/cases/cjs-tree-shaking/bailouts/index.js
new file mode 100644
index 000000000..665c352dc
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/index.js
@@ -0,0 +1,56 @@
+it("should bailout when reading whole exports object from this", () => {
+ var test = require("./reading-this").test;
+ expect(test().abc).toBe("abc");
+});
+
+it("should bailout when reading whole exports object from exports", () => {
+ var test = require("./reading-exports").test;
+ expect(test().abc).toBe("abc");
+});
+
+it("should bailout when reading whole exports object from module.exports", () => {
+ var test = require("./reading-module-exports").test;
+ expect(test().abc).toBe("abc");
+});
+
+it("should reassigning exports (assign values)", () => {
+ expect(require("./assign-exports-assign?1").abc).toBe("abc");
+ expect(require("./assign-exports-assign?2").def).toBe(undefined);
+});
+
+it("should reassigning exports (define values)", () => {
+ expect(require("./assign-exports-define").abc).toBe("abc");
+ expect(require("./assign-exports-define").def).toBe(undefined);
+});
+
+it("should not mangle or remove nested properties", () => {
+ expect(require("./nested-property").abc).toBe("abc");
+});
+
+it("should be able to access the exports via call context", () => {
+ expect(require("./accessing-call-context?1").func().abc).toBe("abc");
+ var cc = require("./accessing-call-context?2");
+ expect(cc.func().abc).toBe("abc");
+ var func = require("./accessing-call-context?3").func;
+ expect(func()).toBe(undefined);
+});
+
+it("should be able to define an exports property on module (property)", () => {
+ expect(require("./define-module-property?2").abc).toBe("abc");
+ expect(require("./define-module-property?1").def).toBe("def");
+});
+
+it("should be able to define an exports property on module (properties)", () => {
+ expect(require("./define-module-properties?2").abc).toBe("abc");
+ expect(require("./define-module-properties?1").def).toBe("def");
+});
+
+it("should be able to do stuff with the module object", () => {
+ expect(require("./accessing-module?2").abc).toBe("abc");
+ expect(require("./accessing-module?1").def).toBe("def");
+});
+
+it("should be able to use AMD to define exports", () => {
+ expect(require("./using-amd?2").abc).toBe("abc");
+ expect(require("./using-amd?1").def).toBe("def");
+});
diff --git a/test/cases/cjs-tree-shaking/bailouts/nested-property.js b/test/cases/cjs-tree-shaking/bailouts/nested-property.js
new file mode 100644
index 000000000..4777d1581
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/nested-property.js
@@ -0,0 +1,8 @@
+var abc = {};
+
+module.exports = abc;
+
+module.exports.abc = "abc";
+module.exports.def = "def";
+
+expect(abc).toEqual({ abc: "abc", def: "def" });
diff --git a/test/cases/cjs-tree-shaking/bailouts/reading-exports.js b/test/cases/cjs-tree-shaking/bailouts/reading-exports.js
new file mode 100644
index 000000000..7c994d85b
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/reading-exports.js
@@ -0,0 +1,5 @@
+exports.abc = "abc";
+
+exports.test = function() {
+ return exports;
+};
diff --git a/test/cases/cjs-tree-shaking/bailouts/reading-module-exports.js b/test/cases/cjs-tree-shaking/bailouts/reading-module-exports.js
new file mode 100644
index 000000000..53c6437c5
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/reading-module-exports.js
@@ -0,0 +1,5 @@
+exports.abc = "abc";
+
+exports.test = function() {
+ return module.exports;
+};
diff --git a/test/cases/cjs-tree-shaking/bailouts/reading-this.js b/test/cases/cjs-tree-shaking/bailouts/reading-this.js
new file mode 100644
index 000000000..dace36f75
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/reading-this.js
@@ -0,0 +1,5 @@
+exports.abc = "abc";
+
+exports.test = () => {
+ return this;
+};
diff --git a/test/cases/cjs-tree-shaking/bailouts/using-amd.js b/test/cases/cjs-tree-shaking/bailouts/using-amd.js
new file mode 100644
index 000000000..28366950f
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/bailouts/using-amd.js
@@ -0,0 +1,5 @@
+exports.abc = "not-abc";
+define({
+ abc: "abc",
+ def: "def"
+});
diff --git a/test/cases/cjs-tree-shaking/cjs-to-esm/index.js b/test/cases/cjs-tree-shaking/cjs-to-esm/index.js
new file mode 100644
index 000000000..1c5838ace
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/cjs-to-esm/index.js
@@ -0,0 +1,10 @@
+it("should allow to require esm", () => {
+ expect(require("./module?1").abc).toBe("abc");
+ expect(typeof require("./module?2").func).toBe("function");
+ // check if a function called with a namespace object as context
+ // still yield the same optimization, compared to only accessing
+ // the export
+ expect(Object.keys(require("./module?3").func())).toEqual(
+ Object.keys(require.cache[require.resolve("./module?2")].exports)
+ );
+});
diff --git a/test/cases/cjs-tree-shaking/cjs-to-esm/module.js b/test/cases/cjs-tree-shaking/cjs-to-esm/module.js
new file mode 100644
index 000000000..6532d0868
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/cjs-to-esm/module.js
@@ -0,0 +1,6 @@
+export const abc = "abc";
+export const def = "def";
+export const func = function() {
+ "use strict";
+ return this;
+};
diff --git a/test/cases/cjs-tree-shaking/esm-to-cjs/index.js b/test/cases/cjs-tree-shaking/esm-to-cjs/index.js
new file mode 100644
index 000000000..71e5362a4
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/esm-to-cjs/index.js
@@ -0,0 +1,9 @@
+import m1 from "./module?1";
+import m2 from "./module?2";
+import { abc } from "./module?3";
+
+it("should allow to import cjs with esm", () => {
+ expect(m1.abc).toBe("abc");
+ expect(m2).toEqual({ abc: "abc", def: "def" });
+ expect(abc).toBe("abc");
+});
diff --git a/test/cases/cjs-tree-shaking/esm-to-cjs/module.js b/test/cases/cjs-tree-shaking/esm-to-cjs/module.js
new file mode 100644
index 000000000..0d3ae4379
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/esm-to-cjs/module.js
@@ -0,0 +1,2 @@
+exports.abc = "abc";
+exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/exports/assign-exports-property.js b/test/cases/cjs-tree-shaking/exports/assign-exports-property.js
new file mode 100644
index 000000000..0d3ae4379
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/assign-exports-property.js
@@ -0,0 +1,2 @@
+exports.abc = "abc";
+exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/exports/assign-module-exports-property.js b/test/cases/cjs-tree-shaking/exports/assign-module-exports-property.js
new file mode 100644
index 000000000..2136b98d7
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/assign-module-exports-property.js
@@ -0,0 +1,2 @@
+module.exports.abc = "abc";
+module.exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/exports/assign-this-property.js b/test/cases/cjs-tree-shaking/exports/assign-this-property.js
new file mode 100644
index 000000000..37d1ecb94
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/assign-this-property.js
@@ -0,0 +1,2 @@
+this.abc = "abc";
+this.def = "def";
diff --git a/test/cases/cjs-tree-shaking/exports/attach-to-arrow-function.js b/test/cases/cjs-tree-shaking/exports/attach-to-arrow-function.js
new file mode 100644
index 000000000..abc9576d2
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/attach-to-arrow-function.js
@@ -0,0 +1,3 @@
+module.exports = () => "abc";
+
+module.exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/exports/attach-to-function.js b/test/cases/cjs-tree-shaking/exports/attach-to-function.js
new file mode 100644
index 000000000..9341f94fd
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/attach-to-function.js
@@ -0,0 +1,5 @@
+module.exports = function() {
+ return "abc";
+};
+
+module.exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/exports/attach-to-object.js b/test/cases/cjs-tree-shaking/exports/attach-to-object.js
new file mode 100644
index 000000000..43abfd882
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/attach-to-object.js
@@ -0,0 +1,5 @@
+module.exports = {
+ abc: "abc"
+};
+
+module.exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/exports/define-exports-property.js b/test/cases/cjs-tree-shaking/exports/define-exports-property.js
new file mode 100644
index 000000000..8fdaf76e9
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/define-exports-property.js
@@ -0,0 +1,2 @@
+Object.defineProperty(exports, "abc", { enumerable: true, value: "abc" });
+Object.defineProperty(exports, "def", { enumerable: true, value: "def" });
diff --git a/test/cases/cjs-tree-shaking/exports/define-module-exports-property.js b/test/cases/cjs-tree-shaking/exports/define-module-exports-property.js
new file mode 100644
index 000000000..4ac21240a
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/define-module-exports-property.js
@@ -0,0 +1,8 @@
+Object.defineProperty(module.exports, "abc", {
+ enumerable: true,
+ value: "abc"
+});
+Object.defineProperty(module.exports, "def", {
+ enumerable: true,
+ value: "def"
+});
diff --git a/test/cases/cjs-tree-shaking/exports/define-this-property.js b/test/cases/cjs-tree-shaking/exports/define-this-property.js
new file mode 100644
index 000000000..2cfbf578d
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/define-this-property.js
@@ -0,0 +1,2 @@
+Object.defineProperty(this, "abc", { enumerable: true, value: "abc" });
+Object.defineProperty(this, "def", { enumerable: true, value: "def" });
diff --git a/test/cases/cjs-tree-shaking/exports/index.js b/test/cases/cjs-tree-shaking/exports/index.js
new file mode 100644
index 000000000..2524d9c11
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/index.js
@@ -0,0 +1,83 @@
+it("should allow to export via exports", () => {
+ expect(require("./assign-exports-property?1").abc).toBe("abc");
+ expect(require("./assign-exports-property?2")).toEqual({
+ abc: "abc",
+ def: "def"
+ });
+});
+
+it("should allow to export via module.exports", () => {
+ expect(require("./assign-module-exports-property?1").abc).toBe("abc");
+ expect(require("./assign-module-exports-property?2")).toEqual({
+ abc: "abc",
+ def: "def"
+ });
+});
+
+it("should allow to export via this", () => {
+ expect(require("./assign-this-property?1").abc).toBe("abc");
+ expect(require("./assign-this-property?2")).toEqual({
+ abc: "abc",
+ def: "def"
+ });
+});
+
+it("should allow to export via define property on exports", () => {
+ expect(require("./define-exports-property?1").abc).toBe("abc");
+ expect(require("./define-exports-property?2")).toEqual({
+ abc: "abc",
+ def: "def"
+ });
+});
+
+it("should allow to export via define property on module.exports", () => {
+ expect(require("./define-module-exports-property?1").abc).toBe("abc");
+ expect(require("./define-module-exports-property?2")).toEqual({
+ abc: "abc",
+ def: "def"
+ });
+});
+
+it("should allow to export via define property on this", () => {
+ expect(require("./define-this-property?1").abc).toBe("abc");
+ expect(require("./define-this-property?2")).toEqual({
+ abc: "abc",
+ def: "def"
+ });
+});
+
+it("should allow to read own exports via exports", () => {
+ var test = require("./reading-self-from-exports").test;
+ expect(test()).toBe("abc");
+});
+
+it("should allow to read own exports via module.exports", () => {
+ var test = require("./reading-self-from-module-exports").test;
+ expect(test()).toBe("abc");
+});
+
+it("should allow to read own exports via this", () => {
+ var test = require("./reading-self-from-this").test;
+ expect(test()).toBe("abc");
+});
+
+it("should allow to attach exports to object", () => {
+ expect(require("./attach-to-object?1").abc).toBe("abc");
+ expect(require("./attach-to-object?2").def).toBe("def");
+ expect(require("./attach-to-object?3").abc).toBe("abc");
+ expect(require("./attach-to-object?3").def).toBe("def");
+});
+
+it("should allow to attach exports to function", () => {
+ expect(require("./attach-to-function?1")()).toBe("abc");
+ expect(require("./attach-to-function?2").def).toBe("def");
+ expect(require("./attach-to-function?3")()).toBe("abc");
+ expect(require("./attach-to-function?3").def).toBe("def");
+});
+
+it("should allow to attach exports to arrow function", () => {
+ expect(require("./attach-to-arrow-function?1")()).toBe("abc");
+ expect(require("./attach-to-arrow-function?2").def).toBe("def");
+ expect(require("./attach-to-arrow-function?3")()).toBe("abc");
+ expect(require("./attach-to-arrow-function?3").def).toBe("def");
+});
diff --git a/test/cases/cjs-tree-shaking/exports/reading-self-from-exports.js b/test/cases/cjs-tree-shaking/exports/reading-self-from-exports.js
new file mode 100644
index 000000000..bee3ff361
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/reading-self-from-exports.js
@@ -0,0 +1,5 @@
+exports.abc = "abc";
+
+exports.test = function() {
+ return exports.abc;
+};
diff --git a/test/cases/cjs-tree-shaking/exports/reading-self-from-module-exports.js b/test/cases/cjs-tree-shaking/exports/reading-self-from-module-exports.js
new file mode 100644
index 000000000..9b197bfb8
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/reading-self-from-module-exports.js
@@ -0,0 +1,5 @@
+exports.abc = "abc";
+
+exports.test = function() {
+ return module.exports.abc;
+};
diff --git a/test/cases/cjs-tree-shaking/exports/reading-self-from-this.js b/test/cases/cjs-tree-shaking/exports/reading-self-from-this.js
new file mode 100644
index 000000000..ee4452148
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/exports/reading-self-from-this.js
@@ -0,0 +1,5 @@
+exports.abc = "abc";
+
+exports.test = () => {
+ return this.abc;
+};
diff --git a/test/cases/cjs-tree-shaking/importing/index.js b/test/cases/cjs-tree-shaking/importing/index.js
new file mode 100644
index 000000000..fb044fcad
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/importing/index.js
@@ -0,0 +1,15 @@
+it("should be able to import a module via require and property", () => {
+ expect(require("./module").abc).toBe("abc");
+});
+
+it("should be able to import a module via require and destruct", () => {
+ var { abc } = require("./module");
+ expect(abc).toBe("abc");
+});
+
+it("should be able to import a module via require and exports object", () => {
+ var module1 = require("./module?1");
+ expect(module1.abc).toBe("abc");
+ var module2 = require("./module?2");
+ expect(module2).toEqual({ abc: "abc", def: "def" });
+});
diff --git a/test/cases/cjs-tree-shaking/importing/module.js b/test/cases/cjs-tree-shaking/importing/module.js
new file mode 100644
index 000000000..0d3ae4379
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/importing/module.js
@@ -0,0 +1,2 @@
+exports.abc = "abc";
+exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/mutate/index.js b/test/cases/cjs-tree-shaking/mutate/index.js
new file mode 100644
index 000000000..cd913b48f
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/mutate/index.js
@@ -0,0 +1,33 @@
+import module1 from "./module?1";
+import module2, { a } from "./module?2";
+
+it("should allow mutating imported modules (changing existing exports)", () => {
+ expect(module1.abc).toBe("abc");
+ expect(module1.def).toBe("def");
+ module1.abc = "new-abc";
+ expect(module1.abc).toBe("new-abc");
+ expect(module1.def).toBe("def");
+});
+
+it("should allow mutating imported modules (adding new properties)", () => {
+ expect(module2.abc).toBe("abc");
+ expect(module2.def).toBe("def");
+ expect(module2.ghi).toBe(undefined);
+ expect(module2.Oi).toBe(undefined);
+ expect(module2.a).toBe(undefined);
+ expect(a).toBe(undefined);
+ expect(module2[""]).toBe(undefined);
+ module2.ghi = "ghi";
+ module2.Oi = "Oi";
+ module2.a = "a";
+ module2[""] = {};
+ module2[""].abc = "abc";
+ expect(module2.abc).toBe("abc");
+ expect(module2.def).toBe("def");
+ expect(module2.ghi).toBe("ghi");
+ expect(module2.Oi).toBe("Oi");
+ expect(module2.a).toBe("a");
+ expect(a).toBe("a");
+ expect(module2[""]).toEqual({ abc: "abc" });
+ expect(module2[""].abc).toBe("abc");
+});
diff --git a/test/cases/cjs-tree-shaking/mutate/module.js b/test/cases/cjs-tree-shaking/mutate/module.js
new file mode 100644
index 000000000..0d3ae4379
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/mutate/module.js
@@ -0,0 +1,2 @@
+exports.abc = "abc";
+exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/namespace/index.js b/test/cases/cjs-tree-shaking/namespace/index.js
new file mode 100644
index 000000000..e4407ae46
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/namespace/index.js
@@ -0,0 +1,25 @@
+it("should allow to create namespace exports via __esModule on exports", async () => {
+ expect(await import("./namespace-via-exports")).toBe(
+ require("./namespace-via-exports")
+ );
+});
+it("should allow to create namespace exports via __esModule on literal", async () => {
+ expect(await import("./namespace-via-literal")).toBe(
+ require("./namespace-via-literal")
+ );
+});
+it("should allow to create namespace exports via __esModule with Object.defineProperty", async () => {
+ expect(await import("./namespace-via-define-property")).toBe(
+ require("./namespace-via-define-property")
+ );
+});
+it("should allow to create namespace exports via __esModule with Object.defineProperty minimized true", async () => {
+ expect(await import("./namespace-via-define-property-minimized")).toBe(
+ require("./namespace-via-define-property-minimized")
+ );
+});
+it("should allow to create namespace exports via __esModule with Object.defineProperties", async () => {
+ expect(await import("./namespace-via-define-properties")).toBe(
+ require("./namespace-via-define-properties")
+ );
+});
diff --git a/test/cases/cjs-tree-shaking/namespace/namespace-via-define-properties.js b/test/cases/cjs-tree-shaking/namespace/namespace-via-define-properties.js
new file mode 100644
index 000000000..fcf031e86
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/namespace/namespace-via-define-properties.js
@@ -0,0 +1,5 @@
+Object.defineProperties(exports, {
+ __esModule: { value: true },
+ abc: { enumerable: true, value: "abc" },
+ default: { enumerable: true, value: "default" }
+});
diff --git a/test/cases/cjs-tree-shaking/namespace/namespace-via-define-property-minimized.js b/test/cases/cjs-tree-shaking/namespace/namespace-via-define-property-minimized.js
new file mode 100644
index 000000000..cd10e84bf
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/namespace/namespace-via-define-property-minimized.js
@@ -0,0 +1,3 @@
+Object.defineProperty(exports, "__esModule", { value: !0 });
+exports.abc = "abc";
+exports.default = "default";
diff --git a/test/cases/cjs-tree-shaking/namespace/namespace-via-define-property.js b/test/cases/cjs-tree-shaking/namespace/namespace-via-define-property.js
new file mode 100644
index 000000000..50c67588d
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/namespace/namespace-via-define-property.js
@@ -0,0 +1,3 @@
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.abc = "abc";
+exports.default = "default";
diff --git a/test/cases/cjs-tree-shaking/namespace/namespace-via-exports.js b/test/cases/cjs-tree-shaking/namespace/namespace-via-exports.js
new file mode 100644
index 000000000..92cc687c7
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/namespace/namespace-via-exports.js
@@ -0,0 +1,3 @@
+exports.__esModule = true;
+exports.abc = "abc";
+exports.default = "default";
\ No newline at end of file
diff --git a/test/cases/cjs-tree-shaking/namespace/namespace-via-literal.js b/test/cases/cjs-tree-shaking/namespace/namespace-via-literal.js
new file mode 100644
index 000000000..21867372a
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/namespace/namespace-via-literal.js
@@ -0,0 +1,5 @@
+module.exports = {
+ __esModule: true,
+ abc: "abc",
+ default: "default"
+};
diff --git a/test/cases/cjs-tree-shaking/objects/direct-object.js b/test/cases/cjs-tree-shaking/objects/direct-object.js
new file mode 100644
index 000000000..f32a5fb07
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/objects/direct-object.js
@@ -0,0 +1,4 @@
+module.exports = {
+ abc: "abc",
+ def: "def"
+};
diff --git a/test/cases/cjs-tree-shaking/objects/index.js b/test/cases/cjs-tree-shaking/objects/index.js
new file mode 100644
index 000000000..cf9fa76da
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/objects/index.js
@@ -0,0 +1,9 @@
+it("should be able to export an object literal", () => {
+ expect(require("./direct-object?1").abc).toBe("abc");
+ expect(require("./direct-object?2")).toEqual({ abc: "abc", def: "def" });
+});
+
+it("should be able to export an object literal indirect", () => {
+ expect(require("./indirect-object?1").abc).toBe("abc");
+ expect(require("./indirect-object?2")).toEqual({ abc: "abc", def: "def" });
+});
diff --git a/test/cases/cjs-tree-shaking/objects/indirect-object.js b/test/cases/cjs-tree-shaking/objects/indirect-object.js
new file mode 100644
index 000000000..9df708c91
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/objects/indirect-object.js
@@ -0,0 +1,6 @@
+var value = {
+ abc: "abc",
+ def: "def"
+};
+
+module.exports = value;
diff --git a/test/cases/cjs-tree-shaking/reexports/index.js b/test/cases/cjs-tree-shaking/reexports/index.js
new file mode 100644
index 000000000..2fb27e1d3
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/reexports/index.js
@@ -0,0 +1,41 @@
+it("should allow to reexport a exports object (this, exports)", () => {
+ expect(require("./reexport-whole-exports?1").m1.abc).toBe("abc");
+ expect(require("./reexport-whole-exports?2").m2.abc).toBe("abc");
+ expect(require("./reexport-whole-exports?3").m3.abc).toBe("abc");
+ expect(require("./reexport-whole-exports?4").m4.abc).toBe("abc");
+});
+
+it("should allow to reexport a exports object (module.exports, object literal)", () => {
+ expect(require("./reexport-whole-module-exports?1").m1.abc).toBe("abc");
+ expect(require("./reexport-whole-module-exports?2").m2.abc).toBe("abc");
+ expect(require("./reexport-whole-module-exports?3").m3.abc).toBe("abc");
+ expect(require("./reexport-whole-module-exports?4").m4.abc).toBe("abc");
+});
+
+it("should allow to reexport a imported property (this, exports)", () => {
+ expect(require("./reexport-property-exports?1").p1).toBe("abc");
+ expect(require("./reexport-property-exports?2").p2).toBe("abc");
+ expect(require("./reexport-property-exports?3").p3).toBe("abc");
+ expect(require("./reexport-property-exports?4").p4).toBe("abc");
+});
+
+it("should allow to reexport a imported property (module.exports, object literal)", () => {
+ expect(require("./reexport-property-module-exports?1").p1).toBe("abc");
+ expect(require("./reexport-property-module-exports?2").p2).toBe("abc");
+ expect(require("./reexport-property-module-exports?3").p3).toBe("abc");
+ expect(require("./reexport-property-module-exports?4").p4).toBe("abc");
+});
+
+it("should allow to reexport a reexported exports object (this, exports)", () => {
+ expect(require("./reexport-reexport-exports?1").x1.abc).toBe("abc");
+ expect(require("./reexport-reexport-exports?2").x2.abc).toBe("abc");
+ expect(require("./reexport-reexport-exports?3").x3.abc).toBe("abc");
+ expect(require("./reexport-reexport-exports?4").x4.abc).toBe("abc");
+});
+
+it("should allow to reexport a reexported exports object (module.exports, object literal)", () => {
+ expect(require("./reexport-reexport-module-exports?1").x1.abc).toBe("abc");
+ expect(require("./reexport-reexport-module-exports?2").x2.abc).toBe("abc");
+ expect(require("./reexport-reexport-module-exports?3").x3.abc).toBe("abc");
+ expect(require("./reexport-reexport-module-exports?4").x4.abc).toBe("abc");
+});
diff --git a/test/cases/cjs-tree-shaking/reexports/module.js b/test/cases/cjs-tree-shaking/reexports/module.js
new file mode 100644
index 000000000..0d3ae4379
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/reexports/module.js
@@ -0,0 +1,2 @@
+exports.abc = "abc";
+exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/reexports/reexport-property-exports.js b/test/cases/cjs-tree-shaking/reexports/reexport-property-exports.js
new file mode 100644
index 000000000..011358abf
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/reexports/reexport-property-exports.js
@@ -0,0 +1,6 @@
+exports.p1 = require("./module?pe1").abc;
+var m2 = require("./module?pe2");
+exports.p2 = m2.abc;
+this.p3 = require("./module?pe3").abc;
+var m4 = require("./module?pe4");
+this.p4 = m4.abc;
diff --git a/test/cases/cjs-tree-shaking/reexports/reexport-property-module-exports.js b/test/cases/cjs-tree-shaking/reexports/reexport-property-module-exports.js
new file mode 100644
index 000000000..d08197d67
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/reexports/reexport-property-module-exports.js
@@ -0,0 +1,8 @@
+var m2 = require("./module?pme2");
+module.exports = {
+ p1: require("./module?pme1").abc,
+ p2: m2.abc
+};
+module.exports.p3 = require("./module?pme3").abc;
+var m4 = require("./module?pme4");
+module.exports.p4 = m4.abc;
diff --git a/test/cases/cjs-tree-shaking/reexports/reexport-reexport-exports.js b/test/cases/cjs-tree-shaking/reexports/reexport-reexport-exports.js
new file mode 100644
index 000000000..6bfd379d6
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/reexports/reexport-reexport-exports.js
@@ -0,0 +1,6 @@
+exports.x1 = require("./reexport-whole-exports?x1").m1;
+var m2 = require("./reexport-whole-exports?x2");
+exports.x2 = m2.m2;
+this.x3 = require("./reexport-whole-exports?x3").m3;
+var m4 = require("./reexport-whole-exports?x4");
+this.x4 = m4.m4;
diff --git a/test/cases/cjs-tree-shaking/reexports/reexport-reexport-module-exports.js b/test/cases/cjs-tree-shaking/reexports/reexport-reexport-module-exports.js
new file mode 100644
index 000000000..41c61110b
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/reexports/reexport-reexport-module-exports.js
@@ -0,0 +1,8 @@
+var m2 = require("./reexport-whole-module-exports?x2");
+module.exports = {
+ x1: require("./reexport-whole-module-exports?x1").m1,
+ x2: m2.m2
+};
+module.exports.x3 = require("./reexport-whole-module-exports?x3").m3;
+var m4 = require("./reexport-whole-module-exports?x4");
+module.exports.x4 = m4.m4;
diff --git a/test/cases/cjs-tree-shaking/reexports/reexport-whole-exports.js b/test/cases/cjs-tree-shaking/reexports/reexport-whole-exports.js
new file mode 100644
index 000000000..8fb1a720e
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/reexports/reexport-whole-exports.js
@@ -0,0 +1,6 @@
+exports.m1 = require("./module?we1");
+var m2 = require("./module?we2");
+exports.m2 = m2;
+this.m3 = require("./module?we3");
+var m4 = require("./module?we4");
+this.m4 = m4;
diff --git a/test/cases/cjs-tree-shaking/reexports/reexport-whole-module-exports.js b/test/cases/cjs-tree-shaking/reexports/reexport-whole-module-exports.js
new file mode 100644
index 000000000..e17157394
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/reexports/reexport-whole-module-exports.js
@@ -0,0 +1,8 @@
+var m2 = require("./module?wme2");
+module.exports = {
+ m1: require("./module?wme1"),
+ m2
+};
+module.exports.m3 = require("./module?wme3");
+var m4 = require("./module?wme4");
+module.exports.m4 = m4;
diff --git a/test/cases/cjs-tree-shaking/transpiled/babel-default-interop.js b/test/cases/cjs-tree-shaking/transpiled/babel-default-interop.js
new file mode 100644
index 000000000..8accb6fef
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/transpiled/babel-default-interop.js
@@ -0,0 +1,5 @@
+var xxx = _interopRequireDefault(require("./module?2"));
+function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : { default: obj };
+}
+module.exports = xxx.default.abc;
diff --git a/test/cases/cjs-tree-shaking/transpiled/index.js b/test/cases/cjs-tree-shaking/transpiled/index.js
new file mode 100644
index 000000000..d7a8a7e2e
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/transpiled/index.js
@@ -0,0 +1,14 @@
+it("should support typescript export *", () => {
+ expect(require("./typescript-reexport").abc).toBe("abc");
+});
+
+it("should support babel default interop", () => {
+ var xxx2 = _interopRequireDefault(require("./module?2"));
+ var xxx3 = _interopRequireDefault(require("./module?3"));
+ expect(xxx2.default.abc).toBe("abc");
+ expect(xxx3.default).toEqual({ abc: "abc", def: "def" });
+});
+
+function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : { default: obj };
+}
diff --git a/test/cases/cjs-tree-shaking/transpiled/module.js b/test/cases/cjs-tree-shaking/transpiled/module.js
new file mode 100644
index 000000000..0d3ae4379
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/transpiled/module.js
@@ -0,0 +1,2 @@
+exports.abc = "abc";
+exports.def = "def";
diff --git a/test/cases/cjs-tree-shaking/transpiled/typescript-reexport.js b/test/cases/cjs-tree-shaking/transpiled/typescript-reexport.js
new file mode 100644
index 000000000..1d623783a
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/transpiled/typescript-reexport.js
@@ -0,0 +1,4 @@
+function __export(m) {
+ for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+__export(require("./module?1"));
diff --git a/test/cases/cjs-tree-shaking/weird-names/index.js b/test/cases/cjs-tree-shaking/weird-names/index.js
new file mode 100644
index 000000000..453a0120c
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/weird-names/index.js
@@ -0,0 +1,16 @@
+import m from "./module";
+
+it("should allow any name as exports in CommonJs", () => {
+ expect(m.abc).toBe("abc");
+ expect(m[""]).toBe("");
+ expect(m["default"]).toBe("default");
+ expect(m["0"]).toBe("0");
+ expect(m[1]).toBe(1);
+ expect(m.length).toBe("length");
+ expect(m["0_0"]).toBe("0_0");
+ expect(m.if).toBe("if");
+ expect(m["\0"]).toBe("\0");
+ expect(m["\n"]).toBe("\n");
+ expect(m["*/"]).toBe("*/");
+ expect(m["a.b.c"]).toBe("a.b.c");
+});
diff --git a/test/cases/cjs-tree-shaking/weird-names/module.js b/test/cases/cjs-tree-shaking/weird-names/module.js
new file mode 100644
index 000000000..af166b755
--- /dev/null
+++ b/test/cases/cjs-tree-shaking/weird-names/module.js
@@ -0,0 +1,12 @@
+exports.abc = "abc";
+exports[""] = "";
+exports["default"] = "default";
+exports["0"] = "0";
+exports[1] = 1;
+exports.length = "length";
+exports["0_0"] = "0_0";
+exports.if = "if";
+exports["\0"] = "\0";
+exports["\n"] = "\n";
+exports["*/"] = "*/";
+exports["a.b.c"] = "a.b.c";
diff --git a/test/cases/json/import-by-name-with-concatenation/warnings.js b/test/cases/json/import-by-name-with-concatenation/warnings.js
index d124326de..82fc687d9 100644
--- a/test/cases/json/import-by-name-with-concatenation/warnings.js
+++ b/test/cases/json/import-by-name-with-concatenation/warnings.js
@@ -1,17 +1,17 @@
module.exports = [
[
- /Can't import the named export '2' \(imported as 'c'\) from JSON module \(only default export is available\)/
+ /Should not import the named export '2' \(imported as 'c'\) from default-exporting module \(only default export is available soon\)/
],
[
- /Can't import the named export 'aa' \(imported as 'aa'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'aa' \(imported as 'aa'\) from default-exporting module \(only default export is available soon\)/
],
[
- /Can't import the named export 'bb' \(imported as 'bb'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'bb' \(imported as 'bb'\) from default-exporting module \(only default export is available soon\)/
],
[
- /Can't import the named export 'named' \(imported as 'named'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'named' \(imported as 'named'\) from default-exporting module \(only default export is available soon\)/
],
[
- /Can't import the named export 'named' \(imported as 'gnamed'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'named' \(imported as 'gnamed'\) from default-exporting module \(only default export is available soon\)/
]
];
diff --git a/test/cases/json/import-by-name/warnings.js b/test/cases/json/import-by-name/warnings.js
index d124326de..82fc687d9 100644
--- a/test/cases/json/import-by-name/warnings.js
+++ b/test/cases/json/import-by-name/warnings.js
@@ -1,17 +1,17 @@
module.exports = [
[
- /Can't import the named export '2' \(imported as 'c'\) from JSON module \(only default export is available\)/
+ /Should not import the named export '2' \(imported as 'c'\) from default-exporting module \(only default export is available soon\)/
],
[
- /Can't import the named export 'aa' \(imported as 'aa'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'aa' \(imported as 'aa'\) from default-exporting module \(only default export is available soon\)/
],
[
- /Can't import the named export 'bb' \(imported as 'bb'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'bb' \(imported as 'bb'\) from default-exporting module \(only default export is available soon\)/
],
[
- /Can't import the named export 'named' \(imported as 'named'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'named' \(imported as 'named'\) from default-exporting module \(only default export is available soon\)/
],
[
- /Can't import the named export 'named' \(imported as 'gnamed'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'named' \(imported as 'gnamed'\) from default-exporting module \(only default export is available soon\)/
]
];
diff --git a/test/cases/json/reexport/warnings.js b/test/cases/json/reexport/warnings.js
index 50af7f5ec..c9990f3c9 100644
--- a/test/cases/json/reexport/warnings.js
+++ b/test/cases/json/reexport/warnings.js
@@ -1,5 +1,5 @@
module.exports = [
[
- /Can't import the named export 'named' \(reexported as 'fNamed'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'named' \(reexported as 'fNamed'\) from default-exporting module \(only default export is available soon\)/
]
];
diff --git a/test/cases/mjs/cjs-import-default/errors.js b/test/cases/mjs/cjs-import-default/errors.js
index b5a4af50a..d0ecea7f3 100644
--- a/test/cases/mjs/cjs-import-default/errors.js
+++ b/test/cases/mjs/cjs-import-default/errors.js
@@ -1,11 +1,11 @@
module.exports = [
[
- /Can't import the named export 'data' \(imported as 'data'\) from non EcmaScript module \(only default export is available\)/
+ /Can't import the named export 'data' \(imported as 'data'\) from default-exporting module \(only default export is available\)/
],
[
- /Can't import the named export 'data' \(imported as 'data'\) from non EcmaScript module \(only default export is available\)/
+ /Can't import the named export 'data' \(imported as 'data'\) from default-exporting module \(only default export is available\)/
],
[
- /Can't import the named export 'data' \(reexported as 'data'\) from non EcmaScript module \(only default export is available\)/
+ /Can't import the named export 'data' \(reexported as 'data'\) from default-exporting module \(only default export is available\)/
]
];
diff --git a/test/cases/mjs/namespace-object-lazy/index.mjs b/test/cases/mjs/namespace-object-lazy/index.mjs
index 5192ed9c2..f6601db55 100644
--- a/test/cases/mjs/namespace-object-lazy/index.mjs
+++ b/test/cases/mjs/namespace-object-lazy/index.mjs
@@ -53,8 +53,7 @@ function contextMixed(name) {
function promiseTest(promise, equalsTo) {
return promise.then(function(results) {
- for(const result of results)
- expect(result).toEqual(equalsTo);
+ expect(results).toEqual(results.map(() => equalsTo));
});
}
diff --git a/test/cases/parsing/harmony-duplicate-export/index.js b/test/cases/parsing/harmony-duplicate-export/index.js
index 83ed81cb0..23b7c2d18 100644
--- a/test/cases/parsing/harmony-duplicate-export/index.js
+++ b/test/cases/parsing/harmony-duplicate-export/index.js
@@ -21,7 +21,7 @@ it("should not overwrite when using star export (known exports)", function() {
expect(x4).toBe("b");
expect(x5).toBe("c");
expect(x6).toBe("a");
- expect(x7).toBe("b"); // Looks wrong, but is irrelevant as this should be an error anyway
+ expect(x7).toBe("d"); // Looks wrong, but is irrelevant as this should be an error anyway
});
it("should not overwrite when using star export (unknown exports)", function() {
@@ -31,5 +31,5 @@ it("should not overwrite when using star export (unknown exports)", function() {
expect(y4).toBe("b");
expect(y5).toBe("c");
expect(y6).toBe("a");
- expect(y7).toBe("b"); // Looks wrong, but is irrelevant as this should be an error anyway
+ expect(y7).toBe("d"); // Looks wrong, but is irrelevant as this should be an error anyway
});
diff --git a/test/cases/scope-hoisting/json-reexport-6700/warnings.js b/test/cases/scope-hoisting/json-reexport-6700/warnings.js
index 5d963765d..1bce6f573 100644
--- a/test/cases/scope-hoisting/json-reexport-6700/warnings.js
+++ b/test/cases/scope-hoisting/json-reexport-6700/warnings.js
@@ -1,8 +1,8 @@
module.exports = [
[
- /Can't import the named export 'a' \(reexported as 'a'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'a' \(reexported as 'a'\) from default-exporting module \(only default export is available soon\)/
],
[
- /Can't import the named export 'b' \(reexported as 'b'\) from JSON module \(only default export is available\)/
+ /Should not import the named export 'b' \(reexported as 'b'\) from default-exporting module \(only default export is available soon\)/
]
];
diff --git a/test/configCases/json/tree-shaking-default/warnings.js b/test/configCases/json/tree-shaking-default/warnings.js
index d99eafdf1..6857cae53 100644
--- a/test/configCases/json/tree-shaking-default/warnings.js
+++ b/test/configCases/json/tree-shaking-default/warnings.js
@@ -1 +1 @@
-module.exports = [[/Can't import the named export/]];
+module.exports = [[/Should not import the named export/]];
diff --git a/test/hotCases/errors/decline/index.js b/test/hotCases/errors/decline/index.js
index e7b844a0a..01e094ed4 100644
--- a/test/hotCases/errors/decline/index.js
+++ b/test/hotCases/errors/decline/index.js
@@ -4,8 +4,8 @@ it("should abort when module is declined by parent", (done) => {
expect(a).toBe(1);
NEXT(require("../../update")((err) => {
try {
- expect(/Aborted because of declined dependency: \.\/b\.js in \.\/a\.js/.test(err.message)).toBe(true);
- expect(/Update propagation: \.\/c\.js -> \.\/b\.js -> \.\/a\.js/.test(err.message)).toBe(true);
+ expect(err.message).toMatch(/Aborted because of declined dependency: \.\/b\.js in \.\/a\.js/);
+ expect(err.message).toMatch(/Update propagation: \.\/c\.js -> \.\/b\.js -> \.\/a\.js/);
done();
} catch(e) {
done(e);
diff --git a/test/hotCases/errors/self-decline/index.js b/test/hotCases/errors/self-decline/index.js
index b5814ee08..ff7f37749 100644
--- a/test/hotCases/errors/self-decline/index.js
+++ b/test/hotCases/errors/self-decline/index.js
@@ -4,8 +4,8 @@ it("should abort when module is declined by itself", (done) => {
expect(a).toBe(1);
NEXT(require("../../update")((err) => {
try {
- expect(/Aborted because of self decline: \.\/a\.js/.test(err.message)).toBe(true);
- expect(/Update propagation: \.\/c\.js -> \.\/b\.js -> \.\/a\.js/.test(err.message)).toBe(true);
+ expect(err.message).toMatch(/Aborted because of self decline: \.\/a\.js/);
+ expect(err.message).toMatch(/Update propagation: \.\/c\.js -> \.\/b\.js -> \.\/a\.js/);
done();
} catch(e) {
done(e);
diff --git a/test/hotCases/errors/unaccepted/index.js b/test/hotCases/errors/unaccepted/index.js
index 5409a58f7..864a55380 100644
--- a/test/hotCases/errors/unaccepted/index.js
+++ b/test/hotCases/errors/unaccepted/index.js
@@ -6,8 +6,8 @@ it("should abort when module is not accepted", (done) => {
expect(b).toBe(1);
NEXT(require("../../update")((err) => {
try {
- expect(/Aborted because \.\/c\.js is not accepted/.test(err.message)).toBe(true);
- expect(/Update propagation: \.\/c\.js -> \.\/b\.js -> \.\/index\.js/.test(err.message)).toBe(true);
+ expect(err.message).toMatch(/Aborted because \.\/c\.js is not accepted/);
+ expect(err.message).toMatch(/Update propagation: \.\/c\.js -> \.\/b\.js -> \.\/index\.js/);
done();
} catch(e) { done(e); }
}));
diff --git a/test/statsCases/filter-warnings/a.js b/test/statsCases/filter-warnings/a.js
index c5264c9c2..259e3bd7a 100644
--- a/test/statsCases/filter-warnings/a.js
+++ b/test/statsCases/filter-warnings/a.js
@@ -1,4 +1,4 @@
-module.export = function someUsedFunction() {};
+module.exports = function someUsedFunction() {};
function someRemoteUnUsedFunction1() {}
function someRemoteUnUsedFunction2() {}
diff --git a/test/watchCases/plugins/module-concatenation-plugin/0/index.js b/test/watchCases/plugins/module-concatenation-plugin/0/index.js
index 91b447495..e99887547 100644
--- a/test/watchCases/plugins/module-concatenation-plugin/0/index.js
+++ b/test/watchCases/plugins/module-concatenation-plugin/0/index.js
@@ -9,5 +9,5 @@ it("should watch for changes", function() {
expect(require("./foo/" + WATCH_STEP)).toBe('This should be working.' + WATCH_STEP);
}
- expect(STATS_JSON.modules.length).toBe(7 + Number(WATCH_STEP));
+ expect(STATS_JSON.modules.filter(m => !m.runtime).length).toBe(4 + Number(WATCH_STEP));
});