mirror of https://github.com/webpack/webpack.git
Merge branch 'next' into import-context-filter
This commit is contained in:
commit
6a6cd57b26
|
@ -283,6 +283,11 @@ module.exports = function(yargs, argv, convertOptions) {
|
|||
}
|
||||
}
|
||||
|
||||
function addPlugin(options, plugin) {
|
||||
ensureArray(options, "plugins");
|
||||
options.plugins.unshift(plugin);
|
||||
}
|
||||
|
||||
ifArgPair("entry", function(name, entry) {
|
||||
if(typeof options.entry[name] !== "undefined" && options.entry[name] !== null) {
|
||||
options.entry[name] = [].concat(options.entry[name]).concat(entry);
|
||||
|
@ -328,9 +333,8 @@ module.exports = function(yargs, argv, convertOptions) {
|
|||
}, function() {
|
||||
defineObject = {};
|
||||
}, function() {
|
||||
ensureArray(options, "plugins");
|
||||
var DefinePlugin = require("../lib/DefinePlugin");
|
||||
options.plugins.push(new DefinePlugin(defineObject));
|
||||
addPlugin(options, new DefinePlugin(defineObject));
|
||||
});
|
||||
|
||||
ifArg("output-path", function(value) {
|
||||
|
@ -398,15 +402,13 @@ module.exports = function(yargs, argv, convertOptions) {
|
|||
mapArgToBoolean("cache");
|
||||
|
||||
ifBooleanArg("hot", function() {
|
||||
ensureArray(options, "plugins");
|
||||
var HotModuleReplacementPlugin = require("../lib/HotModuleReplacementPlugin");
|
||||
options.plugins.push(new HotModuleReplacementPlugin());
|
||||
addPlugin(options, new HotModuleReplacementPlugin());
|
||||
});
|
||||
|
||||
ifBooleanArg("debug", function() {
|
||||
ensureArray(options, "plugins");
|
||||
var LoaderOptionsPlugin = require("../lib/LoaderOptionsPlugin");
|
||||
options.plugins.push(new LoaderOptionsPlugin({
|
||||
addPlugin(options, new LoaderOptionsPlugin({
|
||||
debug: true
|
||||
}));
|
||||
});
|
||||
|
@ -438,41 +440,36 @@ module.exports = function(yargs, argv, convertOptions) {
|
|||
});
|
||||
|
||||
ifArg("optimize-max-chunks", function(value) {
|
||||
ensureArray(options, "plugins");
|
||||
var LimitChunkCountPlugin = require("../lib/optimize/LimitChunkCountPlugin");
|
||||
options.plugins.push(new LimitChunkCountPlugin({
|
||||
addPlugin(options, new LimitChunkCountPlugin({
|
||||
maxChunks: parseInt(value, 10)
|
||||
}));
|
||||
});
|
||||
|
||||
ifArg("optimize-min-chunk-size", function(value) {
|
||||
ensureArray(options, "plugins");
|
||||
var MinChunkSizePlugin = require("../lib/optimize/MinChunkSizePlugin");
|
||||
options.plugins.push(new MinChunkSizePlugin({
|
||||
addPlugin(options, new MinChunkSizePlugin({
|
||||
minChunkSize: parseInt(value, 10)
|
||||
}));
|
||||
});
|
||||
|
||||
ifBooleanArg("optimize-minimize", function() {
|
||||
ensureArray(options, "plugins");
|
||||
var UglifyJsPlugin = require("../lib/optimize/UglifyJsPlugin");
|
||||
var LoaderOptionsPlugin = require("../lib/LoaderOptionsPlugin");
|
||||
options.plugins.push(new UglifyJsPlugin({
|
||||
addPlugin(options, new UglifyJsPlugin({
|
||||
sourceMap: options.devtool && (options.devtool.indexOf("sourcemap") >= 0 || options.devtool.indexOf("source-map") >= 0)
|
||||
}));
|
||||
options.plugins.push(new LoaderOptionsPlugin({
|
||||
addPlugin(options, new LoaderOptionsPlugin({
|
||||
minimize: true
|
||||
}));
|
||||
});
|
||||
|
||||
ifArg("prefetch", function(request) {
|
||||
ensureArray(options, "plugins");
|
||||
var PrefetchPlugin = require("../lib/PrefetchPlugin");
|
||||
options.plugins.push(new PrefetchPlugin(request));
|
||||
addPlugin(options, new PrefetchPlugin(request));
|
||||
});
|
||||
|
||||
ifArg("provide", function(value) {
|
||||
ensureArray(options, "plugins");
|
||||
var idx = value.indexOf("=");
|
||||
var name;
|
||||
if(idx >= 0) {
|
||||
|
@ -482,12 +479,11 @@ module.exports = function(yargs, argv, convertOptions) {
|
|||
name = value;
|
||||
}
|
||||
var ProvidePlugin = require("../lib/ProvidePlugin");
|
||||
options.plugins.push(new ProvidePlugin(name, value));
|
||||
addPlugin(options, new ProvidePlugin(name, value));
|
||||
});
|
||||
|
||||
ifArg("plugin", function(value) {
|
||||
ensureArray(options, "plugins");
|
||||
options.plugins.push(loadPlugin(value));
|
||||
addPlugin(options, loadPlugin(value));
|
||||
});
|
||||
|
||||
mapArgToBoolean("bail");
|
||||
|
|
|
@ -106,6 +106,9 @@
|
|||
## Scope Hoisting
|
||||
[scope-hoisting](scope-hoisting)
|
||||
|
||||
## Pure Module
|
||||
[pure-module](pure-module)
|
||||
|
||||
## Source Map
|
||||
[source-map](source-map)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
var ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
module.exports = {
|
||||
module: {
|
||||
loaders: [
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module.exports = {
|
||||
module: {
|
||||
loaders: [
|
||||
rules: [
|
||||
{ test: /\.coffee$/, loader: "coffee-loader" }
|
||||
]
|
||||
},
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
var ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
module.exports = {
|
||||
module: {
|
||||
loaders: [
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module.exports = {
|
||||
module: {
|
||||
loaders: [
|
||||
rules: [
|
||||
{ test: /\.css$/, loader: "css-loader" }
|
||||
]
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ module.exports = {
|
|||
filename: "[name].js"
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
|
|
|
@ -0,0 +1,280 @@
|
|||
This example shows how the `sideEffects` flag for library authors works.
|
||||
|
||||
The example contains a large library, `big-module`. `big-module` contains multiple child modules: `a`, `b` and `c`. The exports from the child modules are re-exported in the entry module (`index.js`) of the library. A consumer uses **some** of the exports, importing them from the library via `import { a, b } from "big-module"`. According to the EcmaScript spec, all child modules _must_ be evaluated because they could contain side effects.
|
||||
|
||||
The `"sideEffects": false` flag in `big-module`'s `package.json` indicates that the package's modules have no side effects (on evaluation) and only expose exports. This allows tools like webpack to optimize re-exports. In the case `import { a, b } from "big-module-with-flag"` is rewritten to `import { a } from "big-module-with-flag/a"; import { b } from "big-module-with-flag/b"`.
|
||||
|
||||
The example contains two variants of `big-module`. `big-module` has no `sideEffects` flag and `big-module-with-flag` has the `sideEffects` flag. The example client imports `a` and `b` from each of the variants.
|
||||
|
||||
After being built by webpack, the output bundle contains `index.js` `a.js` `b.js` `c.js` from `big-module`, but only `a.js` and `b.js` from `big-module-with-flag`.
|
||||
|
||||
Advantages:
|
||||
|
||||
* Smaller bundles
|
||||
* Faster bootup
|
||||
|
||||
# example.js
|
||||
|
||||
``` javascript
|
||||
import { a as a1, b as b1 } from "big-module";
|
||||
import { a as a2, b as b2 } from "big-module-with-flag";
|
||||
|
||||
console.log(
|
||||
a1,
|
||||
b1,
|
||||
a2,
|
||||
b2
|
||||
);
|
||||
```
|
||||
|
||||
# node_modules/big-module/package.json
|
||||
|
||||
``` javascript
|
||||
{
|
||||
"name": "big-module"
|
||||
}
|
||||
```
|
||||
|
||||
# node_modules/big-module-with-flag/package.json
|
||||
|
||||
``` javascript
|
||||
{
|
||||
"name": "big-module-with-flag",
|
||||
"sideEffects": false
|
||||
}
|
||||
```
|
||||
|
||||
# node_modules/big-module(-with-flag)/index.js
|
||||
|
||||
``` javascript
|
||||
export { a } from "./a";
|
||||
export { b } from "./b";
|
||||
export { c } from "./c";
|
||||
```
|
||||
|
||||
# js/output.js
|
||||
|
||||
<details><summary><code>/******/ (function(modules) { /* webpackBootstrap */ })</code></summary>
|
||||
|
||||
``` javascript
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "js/";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 4);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
``` javascript
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/*!******************************************!*\
|
||||
!*** ./node_modules/big-module/index.js ***!
|
||||
\******************************************/
|
||||
/*! exports provided: a, b, c */
|
||||
/*! exports used: a, b */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* harmony import */ var _a__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./a */1);
|
||||
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _a__WEBPACK_IMPORTED_MODULE_0__["a"]; });
|
||||
|
||||
/* harmony import */ var _b__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./b */2);
|
||||
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "b", function() { return _b__WEBPACK_IMPORTED_MODULE_1__["a"]; });
|
||||
|
||||
/* harmony import */ var _c__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./c */3);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 1 */
|
||||
/*!**************************************!*\
|
||||
!*** ./node_modules/big-module/a.js ***!
|
||||
\**************************************/
|
||||
/*! exports provided: a */
|
||||
/*! exports used: a */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return a; });
|
||||
const a = "a";
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 2 */
|
||||
/*!**************************************!*\
|
||||
!*** ./node_modules/big-module/b.js ***!
|
||||
\**************************************/
|
||||
/*! exports provided: b */
|
||||
/*! exports used: b */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return b; });
|
||||
const b = "b";
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 3 */
|
||||
/*!**************************************!*\
|
||||
!*** ./node_modules/big-module/c.js ***!
|
||||
\**************************************/
|
||||
/*! exports provided: c */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* unused harmony export c */
|
||||
const c = "c";
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 4 */
|
||||
/*!********************!*\
|
||||
!*** ./example.js ***!
|
||||
\********************/
|
||||
/*! exports provided: */
|
||||
/*! all exports used */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
|
||||
/* harmony import */ var big_module__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! big-module */0);
|
||||
/* harmony import */ var big_module_with_flag__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! big-module-with-flag */5);
|
||||
/* harmony import */ var big_module_with_flag__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! big-module-with-flag */6);
|
||||
|
||||
|
||||
|
||||
console.log(
|
||||
big_module__WEBPACK_IMPORTED_MODULE_0__["a"],
|
||||
big_module__WEBPACK_IMPORTED_MODULE_0__["b"],
|
||||
big_module_with_flag__WEBPACK_IMPORTED_MODULE_1__["a"],
|
||||
big_module_with_flag__WEBPACK_IMPORTED_MODULE_2__["a" /* b */]
|
||||
);
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 5 */
|
||||
/*!************************************************!*\
|
||||
!*** ./node_modules/big-module-with-flag/a.js ***!
|
||||
\************************************************/
|
||||
/*! exports provided: a */
|
||||
/*! exports used: a */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return a; });
|
||||
const a = "a";
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 6 */
|
||||
/*!************************************************!*\
|
||||
!*** ./node_modules/big-module-with-flag/b.js ***!
|
||||
\************************************************/
|
||||
/*! exports provided: b */
|
||||
/*! exports used: b */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return b; });
|
||||
const b = "b";
|
||||
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
```
|
||||
|
||||
# Info
|
||||
|
||||
## Uncompressed
|
||||
|
||||
```
|
||||
Hash: 0f036598352d4d3caffa
|
||||
Version: webpack 3.5.6
|
||||
Asset Size Chunks Chunk Names
|
||||
output.js 6.2 kB 0 [emitted] main
|
||||
Entrypoint main = output.js
|
||||
chunk {0} output.js (main) 342 bytes [entry] [rendered]
|
||||
> main [4] ./example.js
|
||||
[4] ./example.js 149 bytes {0} [built]
|
||||
[no exports]
|
||||
+ 6 hidden modules
|
||||
```
|
||||
|
||||
## Minimized (uglify-js, no zip)
|
||||
|
||||
```
|
||||
Hash: 0f036598352d4d3caffa
|
||||
Version: webpack 3.5.6
|
||||
Asset Size Chunks Chunk Names
|
||||
output.js 1.05 kB 0 [emitted] main
|
||||
Entrypoint main = output.js
|
||||
chunk {0} output.js (main) 342 bytes [entry] [rendered]
|
||||
> main [4] ./example.js
|
||||
[4] ./example.js 149 bytes {0} [built]
|
||||
[no exports]
|
||||
+ 6 hidden modules
|
||||
```
|
|
@ -0,0 +1 @@
|
|||
require("../build-common");
|
|
@ -0,0 +1,9 @@
|
|||
import { a as a1, b as b1 } from "big-module";
|
||||
import { a as a2, b as b2 } from "big-module-with-flag";
|
||||
|
||||
console.log(
|
||||
a1,
|
||||
b1,
|
||||
a2,
|
||||
b2
|
||||
);
|
|
@ -0,0 +1 @@
|
|||
export const a = "a";
|
|
@ -0,0 +1 @@
|
|||
export const b = "b";
|
|
@ -0,0 +1 @@
|
|||
export const c = "c";
|
|
@ -0,0 +1,3 @@
|
|||
export { a } from "./a";
|
||||
export { b } from "./b";
|
||||
export { c } from "./c";
|
4
examples/side-effects/node_modules/big-module-with-flag/package.json
generated
vendored
Normal file
4
examples/side-effects/node_modules/big-module-with-flag/package.json
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "big-module-with-flag",
|
||||
"side-effects": false
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export const a = "a";
|
|
@ -0,0 +1 @@
|
|||
export const b = "b";
|
|
@ -0,0 +1 @@
|
|||
export const c = "c";
|
|
@ -0,0 +1,3 @@
|
|||
export { a } from "./a";
|
||||
export { b } from "./b";
|
||||
export { c } from "./c";
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"name": "big-module"
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
This example shows how the `sideEffects` flag for library authors works.
|
||||
|
||||
The example contains a large library, `big-module`. `big-module` contains multiple child modules: `a`, `b` and `c`. The exports from the child modules are re-exported in the entry module (`index.js`) of the library. A consumer uses **some** of the exports, importing them from the library via `import { a, b } from "big-module"`. According to the EcmaScript spec, all child modules _must_ be evaluated because they could contain side effects.
|
||||
|
||||
The `"sideEffects": false` flag in `big-module`'s `package.json` indicates that the package's modules have no side effects (on evaluation) and only expose exports. This allows tools like webpack to optimize re-exports. In the case `import { a, b } from "big-module-with-flag"` is rewritten to `import { a } from "big-module-with-flag/a"; import { b } from "big-module-with-flag/b"`.
|
||||
|
||||
The example contains two variants of `big-module`. `big-module` has no `sideEffects` flag and `big-module-with-flag` has the `sideEffects` flag. The example client imports `a` and `b` from each of the variants.
|
||||
|
||||
After being built by webpack, the output bundle contains `index.js` `a.js` `b.js` `c.js` from `big-module`, but only `a.js` and `b.js` from `big-module-with-flag`.
|
||||
|
||||
Advantages:
|
||||
|
||||
* Smaller bundles
|
||||
* Faster bootup
|
||||
|
||||
# example.js
|
||||
|
||||
``` javascript
|
||||
{{example.js}}
|
||||
```
|
||||
|
||||
# node_modules/big-module/package.json
|
||||
|
||||
``` javascript
|
||||
{{node_modules/big-module/package.json}}
|
||||
```
|
||||
|
||||
# node_modules/big-module-with-flag/package.json
|
||||
|
||||
``` javascript
|
||||
{{node_modules/big-module-with-flag/package.json}}
|
||||
```
|
||||
|
||||
# node_modules/big-module(-with-flag)/index.js
|
||||
|
||||
``` javascript
|
||||
{{node_modules/big-module-with-flag/index.js}}
|
||||
```
|
||||
|
||||
# js/output.js
|
||||
|
||||
``` javascript
|
||||
{{js/output.js}}
|
||||
```
|
||||
|
||||
# Info
|
||||
|
||||
## Uncompressed
|
||||
|
||||
```
|
||||
{{stdout}}
|
||||
```
|
||||
|
||||
## Minimized (uglify-js, no zip)
|
||||
|
||||
```
|
||||
{{min:stdout}}
|
||||
```
|
|
@ -22,7 +22,7 @@ class AmdMainTemplatePlugin {
|
|||
typeof m.request === "object" ? m.request.amd : m.request
|
||||
));
|
||||
const externalsArguments = externals.map((m) =>
|
||||
Template.toIdentifier(`__WEBPACK_EXTERNAL_MODULE_${m.id}__`)
|
||||
`__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__`
|
||||
).join(", ");
|
||||
|
||||
if(this.name) {
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
|
||||
const ConcatSource = require("webpack-sources").ConcatSource;
|
||||
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
||||
const Template = require("./Template");
|
||||
|
||||
const wrapComment = (str) => {
|
||||
if(!str.includes("\n")) return `/*! ${str} */`;
|
||||
return `/*!\n * ${str.split("\n").join("\n * ")}\n */`;
|
||||
if(!str.includes("\n")) return Template.toComment(str);
|
||||
return `/*!\n * ${str.replace(/\*\//g, "* /").split("\n").join("\n * ")}\n */`;
|
||||
};
|
||||
|
||||
class BannerPlugin {
|
||||
|
|
|
@ -20,8 +20,6 @@ class CachePlugin {
|
|||
} else {
|
||||
const registerCacheToCompiler = (compiler, cache) => {
|
||||
compiler.plugin("this-compilation", compilation => {
|
||||
// TODO remove notCacheable for webpack 4
|
||||
if(!compilation.notCacheable) {
|
||||
compilation.cache = cache;
|
||||
compilation.plugin("child-compiler", (childCompiler, compilerName, compilerIndex) => {
|
||||
if(cache) {
|
||||
|
@ -35,11 +33,6 @@ class CachePlugin {
|
|||
registerCacheToCompiler(childCompiler, childCache);
|
||||
}
|
||||
});
|
||||
} else if(this.watching) {
|
||||
compilation.warnings.push(
|
||||
new Error(`CachePlugin - Cache cannot be used because of: ${compilation.notCacheable}`)
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
registerCacheToCompiler(compiler, this.cache);
|
||||
|
|
278
lib/Chunk.js
278
lib/Chunk.js
|
@ -30,9 +30,9 @@ class Chunk {
|
|||
this.name = name;
|
||||
this._modules = new SortableSet(undefined, sortByIdentifier);
|
||||
this.entrypoints = [];
|
||||
this.chunks = [];
|
||||
this.parents = [];
|
||||
this.blocks = [];
|
||||
this._chunks = new SortableSet(undefined, sortById);
|
||||
this._parents = new SortableSet(undefined, sortById);
|
||||
this._blocks = new SortableSet();
|
||||
this.origins = [];
|
||||
this.files = [];
|
||||
this.rendered = false;
|
||||
|
@ -61,9 +61,82 @@ class Chunk {
|
|||
throw new Error("Chunk.initial was removed. Use isInitial()");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array} - an array containing the chunks
|
||||
*/
|
||||
getChunks() {
|
||||
return Array.from(this._chunks);
|
||||
}
|
||||
|
||||
getNumberOfChunks() {
|
||||
return this._chunks.size;
|
||||
}
|
||||
|
||||
get chunksIterable() {
|
||||
return this._chunks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array} - an array containing the parents
|
||||
*/
|
||||
getParents() {
|
||||
return Array.from(this._parents);
|
||||
}
|
||||
|
||||
setParents(newParents) {
|
||||
this._parents.clear();
|
||||
for(const p of newParents)
|
||||
this._parents.add(p);
|
||||
}
|
||||
|
||||
mapParents(fn) {
|
||||
return Array.from(this._parents, fn);
|
||||
}
|
||||
|
||||
getNumberOfParents() {
|
||||
return this._parents.size;
|
||||
}
|
||||
|
||||
hasParent(parent) {
|
||||
return this._parents.has(parent);
|
||||
}
|
||||
|
||||
get parentsIterable() {
|
||||
return this._parents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array} - an array containing the blocks
|
||||
*/
|
||||
getBlocks() {
|
||||
return Array.from(this._blocks);
|
||||
}
|
||||
|
||||
setBlocks(newBlocks) {
|
||||
this._blocks.clear();
|
||||
for(const p of newBlocks)
|
||||
this._blocks.add(p);
|
||||
}
|
||||
|
||||
mapBlocks(fn) {
|
||||
return Array.from(this._blocks, fn);
|
||||
}
|
||||
|
||||
getNumberOfBlocks() {
|
||||
return this._blocks.size;
|
||||
}
|
||||
|
||||
hasBlock(block) {
|
||||
return this._blocks.has(block);
|
||||
}
|
||||
|
||||
get blocksIterable() {
|
||||
return this._blocks;
|
||||
}
|
||||
|
||||
hasRuntime() {
|
||||
if(this.entrypoints.length === 0) return false;
|
||||
return this.entrypoints[0].chunks[0] === this;
|
||||
return this.entrypoints[0].getRuntimeChunk() === this;
|
||||
}
|
||||
|
||||
isInitial() {
|
||||
|
@ -88,11 +161,19 @@ class Chunk {
|
|||
}
|
||||
|
||||
addChunk(chunk) {
|
||||
return this.addToCollection(this.chunks, chunk);
|
||||
if(this._chunks.has(chunk)) {
|
||||
return false;
|
||||
}
|
||||
this._chunks.add(chunk);
|
||||
return true;
|
||||
}
|
||||
|
||||
addParent(parentChunk) {
|
||||
return this.addToCollection(this.parents, parentChunk);
|
||||
if(!this._parents.has(parentChunk)) {
|
||||
this._parents.add(parentChunk);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
addModule(module) {
|
||||
|
@ -104,7 +185,11 @@ class Chunk {
|
|||
}
|
||||
|
||||
addBlock(block) {
|
||||
return this.addToCollection(this.blocks, block);
|
||||
if(!this._blocks.has(block)) {
|
||||
this._blocks.add(block);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
removeModule(module) {
|
||||
|
@ -116,19 +201,17 @@ class Chunk {
|
|||
}
|
||||
|
||||
removeChunk(chunk) {
|
||||
const idx = this.chunks.indexOf(chunk);
|
||||
if(idx >= 0) {
|
||||
this.chunks.splice(idx, 1);
|
||||
chunk.removeParent(this);
|
||||
return true;
|
||||
}
|
||||
if(!this._chunks.has(chunk)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._chunks.delete(chunk);
|
||||
chunk.removeParent(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
removeParent(chunk) {
|
||||
const idx = this.parents.indexOf(chunk);
|
||||
if(idx >= 0) {
|
||||
this.parents.splice(idx, 1);
|
||||
if(this._parents.delete(chunk)) {
|
||||
chunk.removeChunk(this);
|
||||
return true;
|
||||
}
|
||||
|
@ -201,20 +284,17 @@ class Chunk {
|
|||
remove(reason) {
|
||||
// cleanup modules
|
||||
// Array.from is used here to create a clone, because removeChunk modifies this._modules
|
||||
Array.from(this._modules).forEach(module => {
|
||||
for(const module of Array.from(this._modules)) {
|
||||
module.removeChunk(this);
|
||||
});
|
||||
|
||||
// cleanup parents
|
||||
this.parents.forEach(parentChunk => {
|
||||
// remove this chunk from its parents
|
||||
const idx = parentChunk.chunks.indexOf(this);
|
||||
if(idx >= 0) {
|
||||
parentChunk.chunks.splice(idx, 1);
|
||||
}
|
||||
|
||||
// cleanup parents
|
||||
for(const parentChunk of this._parents) {
|
||||
// remove this chunk from its parents
|
||||
parentChunk._chunks.delete(this);
|
||||
|
||||
// cleanup "sub chunks"
|
||||
this.chunks.forEach(chunk => {
|
||||
this._chunks.forEach(chunk => {
|
||||
/**
|
||||
* remove this chunk as "intermediary" and connect
|
||||
* it "sub chunks" and parents directly
|
||||
|
@ -224,24 +304,21 @@ class Chunk {
|
|||
// add "sub chunk" to parent
|
||||
parentChunk.addChunk(chunk);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* we need to iterate again over the chunks
|
||||
* to remove this from the chunks parents.
|
||||
* This can not be done in the above loop
|
||||
* as it is not garuanteed that `this.parents` contains anything.
|
||||
* as it is not garuanteed that `this._parents` contains anything.
|
||||
*/
|
||||
this.chunks.forEach(chunk => {
|
||||
for(const chunk of this._chunks) {
|
||||
// remove this as parent of every "sub chunk"
|
||||
const idx = chunk.parents.indexOf(this);
|
||||
if(idx >= 0) {
|
||||
chunk.parents.splice(idx, 1);
|
||||
chunk._parents.delete(this);
|
||||
}
|
||||
});
|
||||
|
||||
// cleanup blocks
|
||||
this.blocks.forEach(block => {
|
||||
for(const block of this._blocks) {
|
||||
const idx = block.chunks.indexOf(this);
|
||||
if(idx >= 0) {
|
||||
block.chunks.splice(idx, 1);
|
||||
|
@ -250,7 +327,7 @@ class Chunk {
|
|||
block.chunkReason = reason;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
moveModule(module, otherChunk) {
|
||||
|
@ -261,20 +338,14 @@ class Chunk {
|
|||
}
|
||||
|
||||
replaceChunk(oldChunk, newChunk) {
|
||||
const idx = this.chunks.indexOf(oldChunk);
|
||||
if(idx >= 0) {
|
||||
this.chunks.splice(idx, 1);
|
||||
}
|
||||
this._chunks.delete(oldChunk);
|
||||
if(this !== newChunk && newChunk.addParent(this)) {
|
||||
this.addChunk(newChunk);
|
||||
}
|
||||
}
|
||||
|
||||
replaceParentChunk(oldParentChunk, newParentChunk) {
|
||||
const idx = this.parents.indexOf(oldParentChunk);
|
||||
if(idx >= 0) {
|
||||
this.parents.splice(idx, 1);
|
||||
}
|
||||
this._parents.delete(oldParentChunk);
|
||||
if(this !== newParentChunk && newParentChunk.addChunk(this)) {
|
||||
this.addParent(newParentChunk);
|
||||
}
|
||||
|
@ -286,24 +357,29 @@ class Chunk {
|
|||
}
|
||||
|
||||
// Array.from is used here to create a clone, because moveModule modifies otherChunk._modules
|
||||
const otherChunkModules = Array.from(otherChunk._modules);
|
||||
otherChunkModules.forEach(module => otherChunk.moveModule(module, this));
|
||||
for(const module of Array.from(otherChunk._modules)) {
|
||||
otherChunk.moveModule(module, this);
|
||||
}
|
||||
otherChunk._modules.clear();
|
||||
|
||||
otherChunk.parents.forEach(parentChunk => parentChunk.replaceChunk(otherChunk, this));
|
||||
otherChunk.parents.length = 0;
|
||||
for(const parentChunk of otherChunk._parents) {
|
||||
parentChunk.replaceChunk(otherChunk, this);
|
||||
}
|
||||
otherChunk._parents.clear();
|
||||
|
||||
otherChunk.chunks.forEach(chunk => chunk.replaceParentChunk(otherChunk, this));
|
||||
otherChunk.chunks.length = 0;
|
||||
for(const chunk of otherChunk._chunks) {
|
||||
chunk.replaceParentChunk(otherChunk, this);
|
||||
}
|
||||
otherChunk._chunks.clear();
|
||||
|
||||
otherChunk.blocks.forEach(b => {
|
||||
for(const b of otherChunk._blocks) {
|
||||
b.chunks = b.chunks ? b.chunks.map(c => {
|
||||
return c === otherChunk ? this : c;
|
||||
}) : [this];
|
||||
b.chunkReason = reason;
|
||||
this.addBlock(b);
|
||||
});
|
||||
otherChunk.blocks.length = 0;
|
||||
}
|
||||
otherChunk._blocks.clear();
|
||||
|
||||
otherChunk.origins.forEach(origin => {
|
||||
this.origins.push(origin);
|
||||
|
@ -318,31 +394,31 @@ class Chunk {
|
|||
origin.reasons.unshift(reason);
|
||||
}
|
||||
});
|
||||
this.chunks = this.chunks.filter(chunk => {
|
||||
return chunk !== otherChunk && chunk !== this;
|
||||
});
|
||||
this.parents = this.parents.filter(parentChunk => {
|
||||
return parentChunk !== otherChunk && parentChunk !== this;
|
||||
});
|
||||
this._chunks.delete(otherChunk);
|
||||
this._chunks.delete(this);
|
||||
for(const parentChunk of this._parents) {
|
||||
if(parentChunk === otherChunk || parentChunk === this)
|
||||
this._parents.delete(parentChunk);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
split(newChunk) {
|
||||
this.blocks.forEach(block => {
|
||||
newChunk.blocks.push(block);
|
||||
for(const block of this._blocks) {
|
||||
newChunk._blocks.add(block);
|
||||
block.chunks.push(newChunk);
|
||||
});
|
||||
this.chunks.forEach(chunk => {
|
||||
newChunk.chunks.push(chunk);
|
||||
chunk.parents.push(newChunk);
|
||||
});
|
||||
this.parents.forEach(parentChunk => {
|
||||
parentChunk.chunks.push(newChunk);
|
||||
newChunk.parents.push(parentChunk);
|
||||
});
|
||||
this.entrypoints.forEach(entrypoint => {
|
||||
}
|
||||
for(const chunk of this._chunks) {
|
||||
newChunk.addChunk(chunk);
|
||||
chunk._parents.add(newChunk);
|
||||
}
|
||||
for(const parentChunk of this._parents) {
|
||||
parentChunk.addChunk(newChunk);
|
||||
newChunk._parents.add(parentChunk);
|
||||
}
|
||||
for(const entrypoint of this.entrypoints) {
|
||||
entrypoint.insertChunk(newChunk, this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
|
@ -361,7 +437,7 @@ class Chunk {
|
|||
return false;
|
||||
}
|
||||
if(this.isInitial()) {
|
||||
if(otherChunk.parents.length !== 1 || otherChunk.parents[0] !== this) {
|
||||
if(otherChunk.getNumberOfParents() !== 1 || otherChunk.getParents()[0] !== this) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -416,7 +492,7 @@ class Chunk {
|
|||
if(chunk.name)
|
||||
chunkNameMap[chunk.id] = chunk.name;
|
||||
}
|
||||
chunk.chunks.forEach(addChunk);
|
||||
chunk._chunks.forEach(addChunk);
|
||||
}(this));
|
||||
return {
|
||||
hash: chunkHashMap,
|
||||
|
@ -428,7 +504,7 @@ class Chunk {
|
|||
this._modules.sortWith(sortByFn || sortById);
|
||||
}
|
||||
|
||||
sortItems() {
|
||||
sortItems(sortChunks) {
|
||||
this.sortModules();
|
||||
this.origins.sort((a, b) => {
|
||||
const aIdent = a.module.identifier();
|
||||
|
@ -441,8 +517,10 @@ class Chunk {
|
|||
if(origin.reasons)
|
||||
origin.reasons.sort();
|
||||
});
|
||||
this.parents.sort(sortById);
|
||||
this.chunks.sort(sortById);
|
||||
if(sortChunks) {
|
||||
this._parents.sort();
|
||||
this._chunks.sort();
|
||||
}
|
||||
}
|
||||
|
||||
toString() {
|
||||
|
@ -451,29 +529,55 @@ class Chunk {
|
|||
|
||||
checkConstraints() {
|
||||
const chunk = this;
|
||||
chunk.chunks.forEach((child, idx) => {
|
||||
if(chunk.chunks.indexOf(child) !== idx)
|
||||
throw new Error(`checkConstraints: duplicate child in chunk ${chunk.debugId} ${child.debugId}`);
|
||||
if(child.parents.indexOf(chunk) < 0)
|
||||
for(const child of chunk._chunks) {
|
||||
if(!child._parents.has(chunk))
|
||||
throw new Error(`checkConstraints: child missing parent ${chunk.debugId} -> ${child.debugId}`);
|
||||
});
|
||||
chunk.parents.forEach((parentChunk, idx) => {
|
||||
if(chunk.parents.indexOf(parentChunk) !== idx)
|
||||
throw new Error(`checkConstraints: duplicate parent in chunk ${chunk.debugId} ${parentChunk.debugId}`);
|
||||
if(parentChunk.chunks.indexOf(chunk) < 0)
|
||||
}
|
||||
for(const parentChunk of chunk._parents) {
|
||||
if(!parentChunk._chunks.has(chunk))
|
||||
throw new Error(`checkConstraints: parent missing child ${parentChunk.debugId} <- ${chunk.debugId}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(Chunk.prototype, "modules", {
|
||||
configurable: false,
|
||||
get: util.deprecate(function() {
|
||||
return Array.from(this._modules);
|
||||
return this._modules.getFrozenArray();
|
||||
}, "Chunk.modules is deprecated. Use Chunk.getNumberOfModules/mapModules/forEachModule/containsModule instead."),
|
||||
set: util.deprecate(function(value) {
|
||||
this.setModules(value);
|
||||
}, "Chunk.modules is deprecated. Use Chunk.addModule/removeModule instead.")
|
||||
});
|
||||
|
||||
Object.defineProperty(Chunk.prototype, "chunks", {
|
||||
configurable: false,
|
||||
get: util.deprecate(function() {
|
||||
return this._chunks.getFrozenArray();
|
||||
}, "Chunk.chunks: Use Chunk.getChunks() instead"),
|
||||
set() {
|
||||
throw new Error("Readonly. Use Chunk.addChunk/removeChunk/getChunks to access/modify chunks.");
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(Chunk.prototype, "parents", {
|
||||
configurable: false,
|
||||
get: util.deprecate(function() {
|
||||
return this._parents.getFrozenArray();
|
||||
}, "Chunk.parents: Use Chunk.getParents() instead"),
|
||||
set: util.deprecate(function(value) {
|
||||
this.setParents(value);
|
||||
}, "Chunk.parents: Use Chunk.addParent/removeParent/setParents to modify parents.")
|
||||
});
|
||||
|
||||
Object.defineProperty(Chunk.prototype, "blocks", {
|
||||
configurable: false,
|
||||
get: util.deprecate(function() {
|
||||
return this._blocks.getFrozenArray();
|
||||
}, "Chunk.blocks: Use Chunk.getBlocks() instead"),
|
||||
set: util.deprecate(function(value) {
|
||||
this.setBlocks(value);
|
||||
}, "Chunk.blocks: Use Chunk.addBlock/removeBlock/setBlocks to modify blocks.")
|
||||
});
|
||||
|
||||
module.exports = Chunk;
|
||||
|
|
|
@ -573,6 +573,12 @@ class Compilation extends Tapable {
|
|||
seal(callback) {
|
||||
const self = this;
|
||||
self.applyPlugins0("seal");
|
||||
|
||||
while(self.applyPluginsBailResult1("optimize-dependencies-basic", self.modules) ||
|
||||
self.applyPluginsBailResult1("optimize-dependencies", self.modules) ||
|
||||
self.applyPluginsBailResult1("optimize-dependencies-advanced", self.modules)) { /* empty */ }
|
||||
self.applyPlugins1("after-optimize-dependencies", self.modules);
|
||||
|
||||
self.nextFreeModuleIndex = 0;
|
||||
self.nextFreeModuleIndex2 = 0;
|
||||
self.preparedChunks.forEach(preparedChunk => {
|
||||
|
@ -910,8 +916,14 @@ class Compilation extends Tapable {
|
|||
|
||||
// For each Dependency in the graph
|
||||
const iteratorDependency = d => {
|
||||
// We skip Dependencies without Reference
|
||||
const ref = d.getReference();
|
||||
if(!ref) {
|
||||
return;
|
||||
}
|
||||
// We skip Dependencies without Module pointer
|
||||
if(!d.module) {
|
||||
const refModule = ref.module;
|
||||
if(!refModule) {
|
||||
return;
|
||||
}
|
||||
// We skip weak Dependencies
|
||||
|
@ -919,12 +931,13 @@ class Compilation extends Tapable {
|
|||
return;
|
||||
}
|
||||
// We connect Module and Chunk when not already done
|
||||
if(chunk.addModule(d.module)) {
|
||||
d.module.addChunk(chunk);
|
||||
if(chunk.addModule(refModule)) {
|
||||
refModule.addChunk(chunk);
|
||||
|
||||
// And enqueue the Module for traversal
|
||||
queue.push({
|
||||
block: d.module,
|
||||
block: refModule,
|
||||
module: refModule,
|
||||
chunk
|
||||
});
|
||||
}
|
||||
|
@ -1051,7 +1064,7 @@ class Compilation extends Tapable {
|
|||
|
||||
// Remove all unconnected chunks
|
||||
for(const chunk of allCreatedChunks) {
|
||||
if(chunk.parents.length === 0)
|
||||
if(chunk.getNumberOfParents() === 0)
|
||||
chunk.remove("unconnected");
|
||||
}
|
||||
}
|
||||
|
@ -1203,7 +1216,7 @@ class Compilation extends Tapable {
|
|||
|
||||
const chunks = this.chunks;
|
||||
for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
|
||||
chunks[indexChunk].sortItems();
|
||||
chunks[indexChunk].sortItems(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1217,7 +1230,7 @@ class Compilation extends Tapable {
|
|||
|
||||
const chunks = this.chunks;
|
||||
for(let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
|
||||
chunks[indexChunk].sortItems();
|
||||
chunks[indexChunk].sortItems(true);
|
||||
}
|
||||
|
||||
const byMessage = (a, b) => {
|
||||
|
|
|
@ -39,6 +39,12 @@ class DependenciesBlock {
|
|||
this.dependencies.push(dependency);
|
||||
}
|
||||
|
||||
removeDependency(dependency) {
|
||||
const idx = this.dependencies.indexOf(dependency);
|
||||
if(idx >= 0)
|
||||
this.dependencies.splice(idx, 1);
|
||||
}
|
||||
|
||||
updateHash(hash) {
|
||||
function updateHash(i) {
|
||||
i.updateHash(hash);
|
||||
|
|
|
@ -8,6 +8,7 @@ const compareLocations = require("./compareLocations");
|
|||
class Dependency {
|
||||
constructor() {
|
||||
this.module = null;
|
||||
this.weak = false;
|
||||
}
|
||||
|
||||
isEqualResource() {
|
||||
|
@ -19,6 +20,7 @@ class Dependency {
|
|||
if(!this.module) return null;
|
||||
return {
|
||||
module: this.module,
|
||||
weak: this.weak,
|
||||
importedNames: true, // true: full object, false: only sideeffects/no export, array of strings: the exports with this names
|
||||
};
|
||||
}
|
||||
|
@ -43,11 +45,6 @@ class Dependency {
|
|||
disconnect() {
|
||||
this.module = null;
|
||||
}
|
||||
|
||||
// TODO: remove in webpack 3
|
||||
compare(a, b) {
|
||||
return compareLocations(a.loc, b.loc);
|
||||
}
|
||||
}
|
||||
Dependency.compare = (a, b) => compareLocations(a.loc, b.loc);
|
||||
|
||||
|
|
|
@ -16,14 +16,19 @@ class Entrypoint {
|
|||
}
|
||||
|
||||
insertChunk(chunk, before) {
|
||||
const oldIdx = this.chunks.indexOf(chunk);
|
||||
const idx = this.chunks.indexOf(before);
|
||||
if(idx >= 0) {
|
||||
this.chunks.splice(idx, 0, chunk);
|
||||
} else {
|
||||
if(idx < 0) {
|
||||
throw new Error("before chunk not found");
|
||||
}
|
||||
if(oldIdx >= 0 && oldIdx > idx) {
|
||||
this.chunks.splice(oldIdx, 1);
|
||||
this.chunks.splice(idx, 0, chunk);
|
||||
} else if(oldIdx < 0) {
|
||||
this.chunks.splice(idx, 0, chunk);
|
||||
chunk.entrypoints.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
getFiles() {
|
||||
const files = [];
|
||||
|
@ -38,6 +43,10 @@ class Entrypoint {
|
|||
|
||||
return files;
|
||||
}
|
||||
|
||||
getRuntimeChunk() {
|
||||
return this.chunks[0];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Entrypoint;
|
||||
|
|
|
@ -70,7 +70,7 @@ class ExternalModule extends Module {
|
|||
}
|
||||
|
||||
getSourceForAmdOrUmdExternal(id, optional, request) {
|
||||
const externalVariable = Template.toIdentifier(`__WEBPACK_EXTERNAL_MODULE_${id}__`);
|
||||
const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${id}`)}__`;
|
||||
const missingModuleError = optional ? this.checkExternalVariable(externalVariable, request) : "";
|
||||
return `${missingModuleError}module.exports = ${externalVariable};`;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,13 @@ class FlagDependencyUsagePlugin {
|
|||
else
|
||||
module.usedExports = false;
|
||||
|
||||
// for a module without side effects we stop tracking usage here when no export is used
|
||||
// This module won't be evaluated in this case
|
||||
if(module.sideEffectFree) {
|
||||
if(module.usedExports === false) return;
|
||||
if(Array.isArray(module.usedExports) && module.usedExports.length === 0) return;
|
||||
}
|
||||
|
||||
queue.push([module, module.usedExports]);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ class FlagInitialModulesAsUsedPlugin {
|
|||
return;
|
||||
}
|
||||
chunk.forEachModule((module) => {
|
||||
module.used = true;
|
||||
module.usedExports = true;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const ConcatSource = require("webpack-sources").ConcatSource;
|
||||
const Template = require("./Template");
|
||||
|
||||
class FunctionModuleTemplatePlugin {
|
||||
apply(moduleTemplate) {
|
||||
|
@ -29,21 +30,21 @@ class FunctionModuleTemplatePlugin {
|
|||
source.add(" !*** " + req.replace(/\*\//g, "*_/") + " ***!\n");
|
||||
source.add(" \\****" + req.replace(/./g, "*") + "****/\n");
|
||||
if(Array.isArray(module.providedExports) && module.providedExports.length === 0)
|
||||
source.add("/*! no exports provided */\n");
|
||||
source.add(Template.toComment("no exports provided") + "\n");
|
||||
else if(Array.isArray(module.providedExports))
|
||||
source.add("/*! exports provided: " + module.providedExports.join(", ") + " */\n");
|
||||
source.add(Template.toComment("exports provided: " + module.providedExports.join(", ")) + "\n");
|
||||
else if(module.providedExports)
|
||||
source.add("/*! dynamic exports provided */\n");
|
||||
source.add(Template.toComment("no static exports found") + "\n");
|
||||
if(Array.isArray(module.usedExports) && module.usedExports.length === 0)
|
||||
source.add("/*! no exports used */\n");
|
||||
source.add(Template.toComment("no exports used") + "\n");
|
||||
else if(Array.isArray(module.usedExports))
|
||||
source.add("/*! exports used: " + module.usedExports.join(", ") + " */\n");
|
||||
source.add(Template.toComment("exports used: " + module.usedExports.join(", ")) + "\n");
|
||||
else if(module.usedExports)
|
||||
source.add("/*! all exports used */\n");
|
||||
source.add(Template.toComment("all exports used") + "\n");
|
||||
if(module.optimizationBailout) {
|
||||
module.optimizationBailout.forEach(text => {
|
||||
if(typeof text === "function") text = text(this.requestShortener);
|
||||
source.add(`/*! ${text} */\n`);
|
||||
source.add(Template.toComment(`${text}`) + "\n");
|
||||
});
|
||||
}
|
||||
source.add(moduleSource);
|
||||
|
|
|
@ -561,7 +561,6 @@ module.exports = function() {
|
|||
type: "self-accept-error-handler-errored",
|
||||
moduleId: moduleId,
|
||||
error: err2,
|
||||
orginalError: err, // TODO remove in webpack 4
|
||||
originalError: err
|
||||
});
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ module.exports = class HotModuleReplacementPlugin {
|
|||
.replace(/\$require\$/g, this.requireFn)
|
||||
.replace(/\$hash\$/g, JSON.stringify(hash))
|
||||
.replace(/\$requestTimeout\$/g, requestTimeout)
|
||||
.replace(/\/\*foreachInstalledChunks\*\//g, chunk.chunks.length > 0 ? "for(var chunkId in installedChunks)" : `var chunkId = ${JSON.stringify(chunk.id)};`)
|
||||
.replace(/\/\*foreachInstalledChunks\*\//g, chunk.getNumberOfChunks() > 0 ? "for(var chunkId in installedChunks)" : `var chunkId = ${JSON.stringify(chunk.id)};`)
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
@ -11,18 +11,20 @@ class JsonpChunkTemplatePlugin {
|
|||
chunkTemplate.plugin("render", function(modules, chunk) {
|
||||
const jsonpFunction = this.outputOptions.jsonpFunction;
|
||||
const source = new ConcatSource();
|
||||
source.add(`${jsonpFunction}(${JSON.stringify(chunk.ids)},`);
|
||||
source.add(`(window[${JSON.stringify(jsonpFunction)}] = window[${JSON.stringify(jsonpFunction)}] || []).push([${JSON.stringify(chunk.ids)},`);
|
||||
source.add(modules);
|
||||
const entries = [chunk.entryModule].filter(Boolean).map(m => m.id);
|
||||
const entries = [chunk.entryModule]
|
||||
.filter(Boolean)
|
||||
.map(m => [m.id].concat(chunk.entrypoints[0].chunks.map(c => c.id)));
|
||||
if(entries.length > 0) {
|
||||
source.add(`,${JSON.stringify(entries)}`);
|
||||
}
|
||||
source.add(")");
|
||||
source.add("])");
|
||||
return source;
|
||||
});
|
||||
chunkTemplate.plugin("hash", function(hash) {
|
||||
hash.update("JsonpChunkTemplatePlugin");
|
||||
hash.update("3");
|
||||
hash.update("4");
|
||||
hash.update(`${this.outputOptions.jsonpFunction}`);
|
||||
hash.update(`${this.outputOptions.library}`);
|
||||
});
|
||||
|
|
|
@ -12,7 +12,6 @@ module.exports = function() {
|
|||
function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars
|
||||
var head = document.getElementsByTagName("head")[0];
|
||||
var script = document.createElement("script");
|
||||
script.type = "text/javascript";
|
||||
script.charset = "utf-8";
|
||||
script.src = $require$.p + $hotChunkFilename$;
|
||||
$crossOriginLoading$;
|
||||
|
|
|
@ -9,8 +9,15 @@ const Template = require("./Template");
|
|||
class JsonpMainTemplatePlugin {
|
||||
|
||||
apply(mainTemplate) {
|
||||
function needChunkLoadingCode(chunk) {
|
||||
var otherChunksInEntry = chunk.entrypoints.some(function(entrypoint) {
|
||||
return entrypoint.chunks.length > 1;
|
||||
});
|
||||
var onDemandChunks = chunk.getNumberOfChunks() > 0;
|
||||
return otherChunksInEntry || onDemandChunks;
|
||||
}
|
||||
mainTemplate.plugin("local-vars", function(source, chunk) {
|
||||
if(chunk.chunks.length > 0) {
|
||||
if(needChunkLoadingCode(chunk)) {
|
||||
return this.asString([
|
||||
source,
|
||||
"",
|
||||
|
@ -19,7 +26,9 @@ class JsonpMainTemplatePlugin {
|
|||
this.indent(
|
||||
chunk.ids.map(id => `${JSON.stringify(id)}: 0`).join(",\n")
|
||||
),
|
||||
"};"
|
||||
"};",
|
||||
"",
|
||||
"var scheduledModules = [];"
|
||||
]);
|
||||
}
|
||||
return source;
|
||||
|
@ -48,18 +57,20 @@ class JsonpMainTemplatePlugin {
|
|||
});
|
||||
return this.asString([
|
||||
"var script = document.createElement('script');",
|
||||
"script.type = 'text/javascript';",
|
||||
"script.charset = 'utf-8';",
|
||||
"script.async = true;",
|
||||
`script.timeout = ${chunkLoadTimeout};`,
|
||||
crossOriginLoading ? `script.crossOrigin = ${JSON.stringify(crossOriginLoading)};` : "",
|
||||
`if (${this.requireFn}.nc) {`,
|
||||
this.indent(`script.setAttribute("nonce", ${this.requireFn}.nc);`),
|
||||
"}",
|
||||
`script.src = ${this.requireFn}.p + ${scriptSrcPath};`,
|
||||
`var timeout = setTimeout(onScriptComplete, ${chunkLoadTimeout});`,
|
||||
"var timeout = setTimeout(function(){",
|
||||
this.indent([
|
||||
"onScriptComplete({ type: 'timeout', target: script });",
|
||||
]),
|
||||
`}, ${chunkLoadTimeout});`,
|
||||
"script.onerror = script.onload = onScriptComplete;",
|
||||
"function onScriptComplete() {",
|
||||
"function onScriptComplete(event) {",
|
||||
this.indent([
|
||||
"// avoid mem leaks in IE.",
|
||||
"script.onerror = script.onload = null;",
|
||||
|
@ -68,7 +79,14 @@ class JsonpMainTemplatePlugin {
|
|||
"if(chunk !== 0) {",
|
||||
this.indent([
|
||||
"if(chunk) {",
|
||||
this.indent("chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));"),
|
||||
this.indent([
|
||||
"var errorType = event && (event.type === 'load' ? 'missing' : event.type);",
|
||||
"var realSrc = event && event.target && event.target.src;",
|
||||
"var error = new Error('Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')');",
|
||||
"error.type = errorType;",
|
||||
"error.request = realSrc;",
|
||||
"chunk[1](error);"
|
||||
]),
|
||||
"}",
|
||||
"installedChunks[chunkId] = undefined;"
|
||||
]),
|
||||
|
@ -110,7 +128,7 @@ class JsonpMainTemplatePlugin {
|
|||
]);
|
||||
});
|
||||
mainTemplate.plugin("require-extensions", function(source, chunk) {
|
||||
if(chunk.chunks.length === 0) return source;
|
||||
if(chunk.getNumberOfChunks() === 0) return source;
|
||||
|
||||
return this.asString([
|
||||
source,
|
||||
|
@ -120,15 +138,14 @@ class JsonpMainTemplatePlugin {
|
|||
]);
|
||||
});
|
||||
mainTemplate.plugin("bootstrap", function(source, chunk, hash) {
|
||||
if(chunk.chunks.length > 0) {
|
||||
var jsonpFunction = this.outputOptions.jsonpFunction;
|
||||
if(needChunkLoadingCode(chunk)) {
|
||||
return this.asString([
|
||||
source,
|
||||
"",
|
||||
"// install a JSONP callback for chunk loading",
|
||||
`var parentJsonpFunction = window[${JSON.stringify(jsonpFunction)}];`,
|
||||
`window[${JSON.stringify(jsonpFunction)}] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {`,
|
||||
"function webpackJsonpCallback(data) {",
|
||||
this.indent([
|
||||
"var chunkIds = data[0], moreModules = data[1], executeModules = data[2];",
|
||||
"// add \"moreModules\" to the modules object,",
|
||||
"// then flag all \"chunkIds\" as loaded and fire callback",
|
||||
"var moduleId, chunkId, i = 0, resolves = [], result;",
|
||||
|
@ -148,15 +165,28 @@ class JsonpMainTemplatePlugin {
|
|||
"}"
|
||||
]),
|
||||
"}",
|
||||
"if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);",
|
||||
"if(parentJsonpFunction) parentJsonpFunction(data);",
|
||||
"while(resolves.length) {",
|
||||
this.indent("resolves.shift()();"),
|
||||
"}",
|
||||
this.entryPointInChildren(chunk) ? [
|
||||
"if(executeModules) {",
|
||||
"scheduledModules.push.apply(scheduledModules, executeModules || []);",
|
||||
"",
|
||||
"for(i = 0; i < scheduledModules.length; i++) {",
|
||||
this.indent([
|
||||
"for(i=0; i < executeModules.length; i++) {",
|
||||
this.indent(`result = ${this.requireFn}(${this.requireFn}.s = executeModules[i]);`),
|
||||
"var scheduledModule = scheduledModules[i];",
|
||||
"var fullfilled = true;",
|
||||
"for(var j = 1; j < scheduledModule.length; j++) {",
|
||||
this.indent([
|
||||
"var depId = scheduledModule[j];",
|
||||
"if(installedChunks[depId] !== 0) fullfilled = false;"
|
||||
]),
|
||||
"}",
|
||||
"if(fullfilled) {",
|
||||
this.indent([
|
||||
"scheduledModules.splice(i--, 1);",
|
||||
"result = " + this.requireFn + "(" + this.requireFn + ".s = scheduledModule[0]);",
|
||||
]),
|
||||
"}"
|
||||
]),
|
||||
"}",
|
||||
|
@ -168,6 +198,21 @@ class JsonpMainTemplatePlugin {
|
|||
}
|
||||
return source;
|
||||
});
|
||||
mainTemplate.plugin("startup", function(source, chunk, hash) {
|
||||
if(needChunkLoadingCode(chunk)) {
|
||||
var jsonpFunction = this.outputOptions.jsonpFunction;
|
||||
return this.asString([
|
||||
`var jsonpArray = window[${JSON.stringify(jsonpFunction)}] = window[${JSON.stringify(jsonpFunction)}] || [];`,
|
||||
"var parentJsonpFunction = jsonpArray.push.bind(jsonpArray);",
|
||||
"jsonpArray.push = webpackJsonpCallback;",
|
||||
"jsonpArray = jsonpArray.slice();",
|
||||
"for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);",
|
||||
"",
|
||||
source
|
||||
]);
|
||||
}
|
||||
return source;
|
||||
});
|
||||
mainTemplate.plugin("hot-bootstrap", function(source, chunk, hash) {
|
||||
const hotUpdateChunkFilename = this.outputOptions.hotUpdateChunkFilename;
|
||||
const hotUpdateMainFilename = this.outputOptions.hotUpdateMainFilename;
|
||||
|
@ -200,7 +245,7 @@ this[${JSON.stringify(hotUpdateFunction)}] = ${runtimeSource}`;
|
|||
});
|
||||
mainTemplate.plugin("hash", function(hash) {
|
||||
hash.update("jsonp");
|
||||
hash.update("4");
|
||||
hash.update("5");
|
||||
hash.update(`${this.outputOptions.filename}`);
|
||||
hash.update(`${this.outputOptions.chunkFilename}`);
|
||||
hash.update(`${this.outputOptions.jsonpFunction}`);
|
||||
|
|
|
@ -99,7 +99,7 @@ module.exports = class MainTemplate extends Template {
|
|||
});
|
||||
this.plugin("require-extensions", (source, chunk, hash) => {
|
||||
const buf = [];
|
||||
if(chunk.chunks.length > 0) {
|
||||
if(chunk.getNumberOfChunks() > 0) {
|
||||
buf.push("// This file contains only the entry chunk.");
|
||||
buf.push("// The chunk loading function for additional chunks");
|
||||
buf.push(`${this.requireFn}.e = function requireEnsure(chunkId) {`);
|
||||
|
@ -199,13 +199,16 @@ module.exports = class MainTemplate extends Template {
|
|||
|
||||
entryPointInChildren(chunk) {
|
||||
const checkChildren = (chunk, alreadyCheckedChunks) => {
|
||||
return chunk.chunks.some((child) => {
|
||||
if(alreadyCheckedChunks.indexOf(child) >= 0) return;
|
||||
alreadyCheckedChunks.push(child);
|
||||
return child.hasEntryModule() || checkChildren(child, alreadyCheckedChunks);
|
||||
});
|
||||
for(const child of chunk.chunksIterable) {
|
||||
if(!alreadyCheckedChunks.has(child)) {
|
||||
alreadyCheckedChunks.add(child);
|
||||
if(child.hasEntryModule() || checkChildren(child, alreadyCheckedChunks)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return checkChildren(chunk, []);
|
||||
return checkChildren(chunk, new Set()) === true;
|
||||
}
|
||||
|
||||
getPublicPath(options) {
|
||||
|
|
|
@ -129,6 +129,10 @@ class Module extends DependenciesBlock {
|
|||
return this._chunks.size;
|
||||
}
|
||||
|
||||
get chunksIterable() {
|
||||
return this._chunks;
|
||||
}
|
||||
|
||||
hasEqualsChunks(otherModule) {
|
||||
if(this._chunks.size !== otherModule._chunks.size) return false;
|
||||
this._chunks.sortWith(sortByDebugId);
|
||||
|
@ -233,7 +237,7 @@ Object.defineProperty(Module.prototype, "entry", {
|
|||
Object.defineProperty(Module.prototype, "chunks", {
|
||||
configurable: false,
|
||||
get: util.deprecate(function() {
|
||||
return Array.from(this._chunks);
|
||||
return this._chunks.getFrozenArray();
|
||||
}, "Module.chunks: Use Module.forEachChunk/mapChunks/getNumberOfChunks/isInChunk/addChunk/removeChunk instead"),
|
||||
set() {
|
||||
throw new Error("Readonly. Use Module.addChunk/removeChunk to modify chunks.");
|
||||
|
|
|
@ -75,6 +75,63 @@ module.exports = class MultiCompiler extends Tapable {
|
|||
});
|
||||
}
|
||||
|
||||
validateDependencies(callback) {
|
||||
const edges = new Set();
|
||||
const missing = [];
|
||||
const targetFound = (compiler) => {
|
||||
for(const edge of edges) {
|
||||
if(edge.target === compiler) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const sortEdges = (e1, e2) => {
|
||||
return e1.source.name.localeCompare(e2.source.name) ||
|
||||
e1.target.name.localeCompare(e2.target.name);
|
||||
};
|
||||
for(const source of this.compilers) {
|
||||
if(source.dependencies) {
|
||||
for(const dep of source.dependencies) {
|
||||
const target = this.compilers.find((c) => c.name === dep);
|
||||
if(!target) {
|
||||
missing.push(dep);
|
||||
} else {
|
||||
edges.add({
|
||||
source,
|
||||
target
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const errors = missing.map((m) => `Compiler dependency \`${m}\` not found.`);
|
||||
const stack = this.compilers.filter((c) => !targetFound(c));
|
||||
while(stack.length > 0) {
|
||||
const current = stack.pop();
|
||||
for(const edge of edges) {
|
||||
if(edge.source === current) {
|
||||
edges.delete(edge);
|
||||
const target = edge.target;
|
||||
if(!targetFound(target)) {
|
||||
stack.push(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(edges.size > 0) {
|
||||
const lines = Array.from(edges).sort(sortEdges).map(edge => `${edge.source.name} -> ${edge.target.name}`);
|
||||
lines.unshift("Circular dependency found in compiler dependencies.");
|
||||
errors.unshift(lines.join("\n"));
|
||||
}
|
||||
if(errors.length > 0) {
|
||||
const message = errors.join("\n");
|
||||
callback(new Error(message));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
runWithDependencies(compilers, fn, callback) {
|
||||
let fulfilledNames = {};
|
||||
let remainingCompilers = compilers;
|
||||
|
@ -109,6 +166,7 @@ module.exports = class MultiCompiler extends Tapable {
|
|||
let watchings = [];
|
||||
let allStats = this.compilers.map(() => null);
|
||||
let compilerStatus = this.compilers.map(() => false);
|
||||
if(this.validateDependencies(handler)) {
|
||||
this.runWithDependencies(this.compilers, (compiler, callback) => {
|
||||
const compilerIdx = this.compilers.indexOf(compiler);
|
||||
let firstRun = true;
|
||||
|
@ -136,12 +194,14 @@ module.exports = class MultiCompiler extends Tapable {
|
|||
}, () => {
|
||||
// ignore
|
||||
});
|
||||
}
|
||||
|
||||
return new MultiWatching(watchings, this);
|
||||
}
|
||||
|
||||
run(callback) {
|
||||
const allStats = this.compilers.map(() => null);
|
||||
if(this.validateDependencies(callback)) {
|
||||
this.runWithDependencies(this.compilers, ((compiler, callback) => {
|
||||
const compilerIdx = this.compilers.indexOf(compiler);
|
||||
compiler.run((err, stats) => {
|
||||
|
@ -154,6 +214,7 @@ module.exports = class MultiCompiler extends Tapable {
|
|||
callback(null, new MultiStats(allStats));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
purgeInputFileSystem() {
|
||||
this.compilers.forEach((compiler) => {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const Module = require("./Module");
|
||||
const Template = require("./Template");
|
||||
const RawSource = require("webpack-sources").RawSource;
|
||||
|
||||
class MultiModule extends Module {
|
||||
|
@ -58,7 +59,7 @@ class MultiModule extends Module {
|
|||
str.push("module.exports = ");
|
||||
str.push("__webpack_require__(");
|
||||
if(outputOptions.pathinfo)
|
||||
str.push(`/*! ${dep.request} */`);
|
||||
str.push(Template.toComment(dep.request));
|
||||
str.push(`${JSON.stringify(dep.module.id)}`);
|
||||
str.push(")");
|
||||
} else {
|
||||
|
|
|
@ -132,13 +132,10 @@ class NormalModule extends Module {
|
|||
resolve(context, request, callback) {
|
||||
resolver.resolve({}, context, request, callback);
|
||||
},
|
||||
resolveSync(context, request) {
|
||||
return resolver.resolveSync({}, context, request);
|
||||
},
|
||||
emitFile: (name, content, sourceMap) => {
|
||||
this.assets[name] = this.createSourceForAsset(name, content, sourceMap);
|
||||
},
|
||||
options: options,
|
||||
rootContext: options.context,
|
||||
webpack: true,
|
||||
sourceMap: !!this.useSourceMap,
|
||||
_module: this,
|
||||
|
|
|
@ -46,7 +46,7 @@ class NormalModuleFactory extends Tapable {
|
|||
constructor(context, resolvers, options) {
|
||||
super();
|
||||
this.resolvers = resolvers;
|
||||
this.ruleSet = new RuleSet(options.rules || options.loaders);
|
||||
this.ruleSet = new RuleSet(options.rules);
|
||||
this.cachePredicate = typeof options.unsafeCache === "function" ? options.unsafeCache : Boolean.bind(null, options.unsafeCache);
|
||||
this.context = context || "";
|
||||
this.parserCache = {};
|
||||
|
@ -72,7 +72,7 @@ class NormalModuleFactory extends Tapable {
|
|||
// Ignored
|
||||
if(!result) return callback();
|
||||
|
||||
let createdModule = this.applyPluginsBailResult("create-module", result);
|
||||
let createdModule = this.applyPluginsBailResult1("create-module", result);
|
||||
if(!createdModule) {
|
||||
|
||||
if(!result.request) {
|
||||
|
@ -89,7 +89,7 @@ class NormalModuleFactory extends Tapable {
|
|||
);
|
||||
}
|
||||
|
||||
createdModule = this.applyPluginsWaterfall0("module", createdModule);
|
||||
createdModule = this.applyPluginsWaterfall1("module", createdModule, result);
|
||||
|
||||
return callback(null, createdModule);
|
||||
});
|
||||
|
|
|
@ -30,7 +30,7 @@ class OptionsDefaulter {
|
|||
}
|
||||
|
||||
process(options) {
|
||||
// TODO: change this for webpack 4: options = Object.assign({}, options);
|
||||
options = Object.assign({}, options);
|
||||
for(let name in this.defaults) {
|
||||
switch(this.config[name]) {
|
||||
case undefined:
|
||||
|
@ -56,7 +56,7 @@ class OptionsDefaulter {
|
|||
throw new Error("OptionsDefaulter cannot process " + this.config[name]);
|
||||
}
|
||||
}
|
||||
// TODO: change this for webpack 4: return options;
|
||||
return options;
|
||||
}
|
||||
|
||||
set(name, config, def) {
|
||||
|
|
157
lib/Parser.js
157
lib/Parser.js
|
@ -10,6 +10,7 @@ const acorn = require("acorn-dynamic-import").default;
|
|||
const Tapable = require("tapable");
|
||||
const vm = require("vm");
|
||||
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
||||
const StackedSetMap = require("./util/StackedSetMap");
|
||||
|
||||
function joinRanges(startRange, endRange) {
|
||||
if(!endRange) return startRange;
|
||||
|
@ -37,6 +38,36 @@ const POSSIBLE_AST_OPTIONS = [{
|
|||
}
|
||||
}];
|
||||
|
||||
class TrackingSet {
|
||||
constructor(set) {
|
||||
this.set = set;
|
||||
this.set2 = new Set();
|
||||
this.stack = set.stack;
|
||||
}
|
||||
|
||||
add(item) {
|
||||
this.set2.add(item);
|
||||
return this.set.add(item);
|
||||
}
|
||||
|
||||
delete(item) {
|
||||
this.set2.delete(item);
|
||||
return this.set.delete(item);
|
||||
}
|
||||
|
||||
has(item) {
|
||||
return this.set.has(item);
|
||||
}
|
||||
|
||||
createChild() {
|
||||
return this.set.createChild();
|
||||
}
|
||||
|
||||
getAddedItems() {
|
||||
return this.set2;
|
||||
}
|
||||
}
|
||||
|
||||
class Parser extends Tapable {
|
||||
constructor(options) {
|
||||
super();
|
||||
|
@ -207,8 +238,8 @@ class Parser extends Tapable {
|
|||
let res;
|
||||
let name;
|
||||
if(expr.argument.type === "Identifier") {
|
||||
name = this.scope.renames["$" + expr.argument.name] || expr.argument.name;
|
||||
if(this.scope.definitions.indexOf(name) === -1) {
|
||||
name = this.scope.renames.get(expr.argument.name) || expr.argument.name;
|
||||
if(!this.scope.definitions.has(name)) {
|
||||
res = this.applyPluginsBailResult1("evaluate typeof " + name, expr);
|
||||
if(res !== undefined) return res;
|
||||
}
|
||||
|
@ -248,8 +279,8 @@ class Parser extends Tapable {
|
|||
return new BasicEvaluatedExpression().setString("undefined").setRange(expr.range);
|
||||
});
|
||||
this.plugin("evaluate Identifier", function(expr) {
|
||||
const name = this.scope.renames["$" + expr.name] || expr.name;
|
||||
if(this.scope.definitions.indexOf(expr.name) === -1) {
|
||||
const name = this.scope.renames.get(expr.name) || expr.name;
|
||||
if(!this.scope.definitions.has(expr.name)) {
|
||||
const result = this.applyPluginsBailResult1("evaluate Identifier " + name, expr);
|
||||
if(result) return result;
|
||||
return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range);
|
||||
|
@ -258,7 +289,7 @@ class Parser extends Tapable {
|
|||
}
|
||||
});
|
||||
this.plugin("evaluate ThisExpression", function(expr) {
|
||||
const name = this.scope.renames.$this;
|
||||
const name = this.scope.renames.get("this");
|
||||
if(name) {
|
||||
const result = this.applyPluginsBailResult1("evaluate Identifier " + name, expr);
|
||||
if(result) return result;
|
||||
|
@ -283,7 +314,7 @@ class Parser extends Tapable {
|
|||
const param = this.evaluateExpression(expr.callee.object);
|
||||
if(!param) return;
|
||||
const property = expr.callee.property.name || expr.callee.property.value;
|
||||
return this.applyPluginsBailResult("evaluate CallExpression ." + property, expr, param);
|
||||
return this.applyPluginsBailResult2("evaluate CallExpression ." + property, expr, param);
|
||||
});
|
||||
this.plugin("evaluate CallExpression .replace", function(expr, param) {
|
||||
if(!param.isString()) return;
|
||||
|
@ -656,8 +687,8 @@ class Parser extends Tapable {
|
|||
// Declarations
|
||||
prewalkFunctionDeclaration(statement) {
|
||||
if(statement.id) {
|
||||
this.scope.renames["$" + statement.id.name] = undefined;
|
||||
this.scope.definitions.push(statement.id.name);
|
||||
this.scope.renames.set(statement.id.name, null);
|
||||
this.scope.definitions.add(statement.id.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -677,20 +708,20 @@ class Parser extends Tapable {
|
|||
|
||||
prewalkImportDeclaration(statement) {
|
||||
const source = statement.source.value;
|
||||
this.applyPluginsBailResult("import", statement, source);
|
||||
this.applyPluginsBailResult2("import", statement, source);
|
||||
statement.specifiers.forEach(function(specifier) {
|
||||
const name = specifier.local.name;
|
||||
this.scope.renames["$" + name] = undefined;
|
||||
this.scope.definitions.push(name);
|
||||
this.scope.renames.set(name, null);
|
||||
this.scope.definitions.add(name);
|
||||
switch(specifier.type) {
|
||||
case "ImportDefaultSpecifier":
|
||||
this.applyPluginsBailResult("import specifier", statement, source, "default", name);
|
||||
this.applyPluginsBailResult4("import specifier", statement, source, "default", name);
|
||||
break;
|
||||
case "ImportSpecifier":
|
||||
this.applyPluginsBailResult("import specifier", statement, source, specifier.imported.name, name);
|
||||
this.applyPluginsBailResult4("import specifier", statement, source, specifier.imported.name, name);
|
||||
break;
|
||||
case "ImportNamespaceSpecifier":
|
||||
this.applyPluginsBailResult("import specifier", statement, source, null, name);
|
||||
this.applyPluginsBailResult4("import specifier", statement, source, null, name);
|
||||
break;
|
||||
}
|
||||
}, this);
|
||||
|
@ -700,7 +731,7 @@ class Parser extends Tapable {
|
|||
let source;
|
||||
if(statement.source) {
|
||||
source = statement.source.value;
|
||||
this.applyPluginsBailResult("export import", statement, source);
|
||||
this.applyPluginsBailResult2("export import", statement, source);
|
||||
} else {
|
||||
this.applyPluginsBailResult1("export", statement);
|
||||
}
|
||||
|
@ -708,13 +739,16 @@ class Parser extends Tapable {
|
|||
if(/Expression$/.test(statement.declaration.type)) {
|
||||
throw new Error("Doesn't occur?");
|
||||
} else {
|
||||
if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) {
|
||||
const pos = this.scope.definitions.length;
|
||||
if(!this.applyPluginsBailResult2("export declaration", statement, statement.declaration)) {
|
||||
const originalDefinitions = this.scope.definitions;
|
||||
const tracker = new TrackingSet(this.scope.definitions);
|
||||
this.scope.definitions = tracker;
|
||||
this.prewalkStatement(statement.declaration);
|
||||
const newDefs = this.scope.definitions.slice(pos);
|
||||
const newDefs = Array.from(tracker.getAddedItems());
|
||||
this.scope.definitions = originalDefinitions;
|
||||
for(let index = newDefs.length - 1; index >= 0; index--) {
|
||||
const def = newDefs[index];
|
||||
this.applyPluginsBailResult("export specifier", statement, def, def, index);
|
||||
this.applyPluginsBailResult4("export specifier", statement, def, def, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -727,9 +761,9 @@ class Parser extends Tapable {
|
|||
{
|
||||
const name = specifier.exported.name;
|
||||
if(source)
|
||||
this.applyPluginsBailResult("export import specifier", statement, source, specifier.local.name, name, specifierIndex);
|
||||
this.applyPluginsBailResult5("export import specifier", statement, source, specifier.local.name, name, specifierIndex);
|
||||
else
|
||||
this.applyPluginsBailResult("export specifier", statement, specifier.local.name, name, specifierIndex);
|
||||
this.applyPluginsBailResult4("export specifier", statement, specifier.local.name, name, specifierIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -745,12 +779,15 @@ class Parser extends Tapable {
|
|||
|
||||
prewalkExportDefaultDeclaration(statement) {
|
||||
if(/Declaration$/.test(statement.declaration.type)) {
|
||||
const pos = this.scope.definitions.length;
|
||||
const originalDefinitions = this.scope.definitions;
|
||||
const tracker = new TrackingSet(this.scope.definitions);
|
||||
this.scope.definitions = tracker;
|
||||
this.prewalkStatement(statement.declaration);
|
||||
const newDefs = this.scope.definitions.slice(pos);
|
||||
const newDefs = Array.from(tracker.getAddedItems());
|
||||
this.scope.definitions = originalDefinitions;
|
||||
for(let index = 0, len = newDefs.length; index < len; index++) {
|
||||
const def = newDefs[index];
|
||||
this.applyPluginsBailResult("export specifier", statement, def, "default");
|
||||
this.applyPluginsBailResult3("export specifier", statement, def, "default");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -758,21 +795,21 @@ class Parser extends Tapable {
|
|||
walkExportDefaultDeclaration(statement) {
|
||||
this.applyPluginsBailResult1("export", statement);
|
||||
if(/Declaration$/.test(statement.declaration.type)) {
|
||||
if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) {
|
||||
if(!this.applyPluginsBailResult2("export declaration", statement, statement.declaration)) {
|
||||
this.walkStatement(statement.declaration);
|
||||
}
|
||||
} else {
|
||||
this.walkExpression(statement.declaration);
|
||||
if(!this.applyPluginsBailResult("export expression", statement, statement.declaration)) {
|
||||
this.applyPluginsBailResult("export specifier", statement, statement.declaration, "default");
|
||||
if(!this.applyPluginsBailResult2("export expression", statement, statement.declaration)) {
|
||||
this.applyPluginsBailResult3("export specifier", statement, statement.declaration, "default");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prewalkExportAllDeclaration(statement) {
|
||||
const source = statement.source.value;
|
||||
this.applyPluginsBailResult("export import", statement, source);
|
||||
this.applyPluginsBailResult("export import specifier", statement, source, null, null, 0);
|
||||
this.applyPluginsBailResult2("export import", statement, source);
|
||||
this.applyPluginsBailResult5("export import specifier", statement, source, null, null, 0);
|
||||
}
|
||||
|
||||
prewalkVariableDeclaration(statement) {
|
||||
|
@ -787,8 +824,8 @@ class Parser extends Tapable {
|
|||
|
||||
prewalkClassDeclaration(statement) {
|
||||
if(statement.id) {
|
||||
this.scope.renames["$" + statement.id.name] = undefined;
|
||||
this.scope.definitions.push(statement.id.name);
|
||||
this.scope.renames.set(statement.id.name, null);
|
||||
this.scope.definitions.add(statement.id.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -829,9 +866,8 @@ class Parser extends Tapable {
|
|||
this.enterPattern(declarator.id, (name, decl) => {
|
||||
if(!this.applyPluginsBailResult1("var-" + declarator.kind + " " + name, decl)) {
|
||||
if(!this.applyPluginsBailResult1("var " + name, decl)) {
|
||||
this.scope.renames["$" + name] = undefined;
|
||||
if(this.scope.definitions.indexOf(name) < 0)
|
||||
this.scope.definitions.push(name);
|
||||
this.scope.renames.set(name, null);
|
||||
this.scope.definitions.add(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -850,9 +886,8 @@ class Parser extends Tapable {
|
|||
if(renameIdentifier && declarator.id.type === "Identifier" && this.applyPluginsBailResult1("can-rename " + renameIdentifier, declarator.init)) {
|
||||
// renaming with "var a = b;"
|
||||
if(!this.applyPluginsBailResult1("rename " + renameIdentifier, declarator.init)) {
|
||||
this.scope.renames["$" + declarator.id.name] = this.scope.renames["$" + renameIdentifier] || renameIdentifier;
|
||||
const idx = this.scope.definitions.indexOf(declarator.id.name);
|
||||
if(idx >= 0) this.scope.definitions.splice(idx, 1);
|
||||
this.scope.renames.set(declarator.id.name, this.scope.renames.get(renameIdentifier) || renameIdentifier);
|
||||
this.scope.definitions.delete(declarator.id.name);
|
||||
}
|
||||
} else {
|
||||
this.walkPattern(declarator.id);
|
||||
|
@ -1010,15 +1045,14 @@ class Parser extends Tapable {
|
|||
if(expression.left.type === "Identifier" && renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, expression.right)) {
|
||||
// renaming "a = b;"
|
||||
if(!this.applyPluginsBailResult1("rename " + renameIdentifier, expression.right)) {
|
||||
this.scope.renames["$" + expression.left.name] = renameIdentifier;
|
||||
const idx = this.scope.definitions.indexOf(expression.left.name);
|
||||
if(idx >= 0) this.scope.definitions.splice(idx, 1);
|
||||
this.scope.renames.set(expression.left.name, renameIdentifier);
|
||||
this.scope.definitions.delete(expression.left.name);
|
||||
}
|
||||
} else if(expression.left.type === "Identifier") {
|
||||
if(!this.applyPluginsBailResult1("assigned " + expression.left.name, expression)) {
|
||||
this.walkExpression(expression.right);
|
||||
}
|
||||
this.scope.renames["$" + expression.left.name] = undefined;
|
||||
this.scope.renames.set(expression.left.name, null);
|
||||
if(!this.applyPluginsBailResult1("assign " + expression.left.name, expression)) {
|
||||
this.walkExpression(expression.left);
|
||||
}
|
||||
|
@ -1026,7 +1060,7 @@ class Parser extends Tapable {
|
|||
this.walkExpression(expression.right);
|
||||
this.walkPattern(expression.left);
|
||||
this.enterPattern(expression.left, (name, decl) => {
|
||||
this.scope.renames["$" + name] = undefined;
|
||||
this.scope.renames.set(name, null);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1092,13 +1126,13 @@ class Parser extends Tapable {
|
|||
return !args[idx];
|
||||
}), () => {
|
||||
if(renameThis) {
|
||||
this.scope.renames.$this = renameThis;
|
||||
this.scope.renames.set("this", renameThis);
|
||||
}
|
||||
for(let i = 0; i < args.length; i++) {
|
||||
const param = args[i];
|
||||
if(!param) continue;
|
||||
if(!params[i] || params[i].type !== "Identifier") continue;
|
||||
this.scope.renames["$" + params[i].name] = param;
|
||||
this.scope.renames.set(params[i].name, param);
|
||||
}
|
||||
if(functionExpression.body.type === "BlockStatement") {
|
||||
this.prewalkStatement(functionExpression.body);
|
||||
|
@ -1110,7 +1144,7 @@ class Parser extends Tapable {
|
|||
if(expression.callee.type === "MemberExpression" &&
|
||||
expression.callee.object.type === "FunctionExpression" &&
|
||||
!expression.callee.computed &&
|
||||
(["call", "bind"]).indexOf(expression.callee.property.name) >= 0 &&
|
||||
(expression.callee.property.name === "call" || expression.callee.property.name === "bind") &&
|
||||
expression.arguments &&
|
||||
expression.arguments.length > 0
|
||||
) {
|
||||
|
@ -1164,8 +1198,8 @@ class Parser extends Tapable {
|
|||
}
|
||||
|
||||
walkIdentifier(expression) {
|
||||
if(this.scope.definitions.indexOf(expression.name) === -1) {
|
||||
const result = this.applyPluginsBailResult1("expression " + (this.scope.renames["$" + expression.name] || expression.name), expression);
|
||||
if(!this.scope.definitions.has(expression.name)) {
|
||||
const result = this.applyPluginsBailResult1("expression " + (this.scope.renames.get(expression.name) || expression.name), expression);
|
||||
if(result === true)
|
||||
return;
|
||||
}
|
||||
|
@ -1176,23 +1210,23 @@ class Parser extends Tapable {
|
|||
this.scope = {
|
||||
inTry: false,
|
||||
inShorthand: false,
|
||||
definitions: oldScope.definitions.slice(),
|
||||
renames: Object.create(oldScope.renames)
|
||||
definitions: oldScope.definitions.createChild(),
|
||||
renames: oldScope.renames.createChild()
|
||||
};
|
||||
|
||||
this.scope.renames.$this = undefined;
|
||||
this.scope.renames.set("this", null);
|
||||
|
||||
for(let paramIndex = 0, len = params.length; paramIndex < len; paramIndex++) {
|
||||
const param = params[paramIndex];
|
||||
|
||||
if(typeof param !== "string") {
|
||||
this.enterPattern(param, param => {
|
||||
this.scope.renames["$" + param] = undefined;
|
||||
this.scope.definitions.push(param);
|
||||
this.scope.renames.set(param, null);
|
||||
this.scope.definitions.add(param);
|
||||
});
|
||||
} else {
|
||||
this.scope.renames["$" + param] = undefined;
|
||||
this.scope.definitions.push(param);
|
||||
this.scope.renames.set(param, null);
|
||||
this.scope.definitions.add(param);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1374,12 +1408,12 @@ class Parser extends Tapable {
|
|||
const oldComments = this.comments;
|
||||
this.scope = {
|
||||
inTry: false,
|
||||
definitions: [],
|
||||
renames: {}
|
||||
definitions: new StackedSetMap(),
|
||||
renames: new StackedSetMap()
|
||||
};
|
||||
const state = this.state = initialState || {};
|
||||
this.comments = comments;
|
||||
if(this.applyPluginsBailResult("program", ast, comments) === undefined) {
|
||||
if(this.applyPluginsBailResult2("program", ast, comments) === undefined) {
|
||||
this.prewalkStatements(ast.body);
|
||||
this.walkStatements(ast.body);
|
||||
}
|
||||
|
@ -1433,11 +1467,11 @@ class Parser extends Tapable {
|
|||
}
|
||||
let free;
|
||||
if(expr.type === "Identifier") {
|
||||
free = this.scope.definitions.indexOf(expr.name) === -1;
|
||||
exprName.push(this.scope.renames["$" + expr.name] || expr.name);
|
||||
} else if(expr.type === "ThisExpression" && this.scope.renames.$this) {
|
||||
free = !this.scope.definitions.has(expr.name);
|
||||
exprName.push(this.scope.renames.get(expr.name) || expr.name);
|
||||
} else if(expr.type === "ThisExpression" && this.scope.renames.get("this")) {
|
||||
free = true;
|
||||
exprName.push(this.scope.renames.$this);
|
||||
exprName.push(this.scope.renames.get("this"));
|
||||
} else if(expr.type === "ThisExpression") {
|
||||
free = false;
|
||||
exprName.push("this");
|
||||
|
@ -1461,3 +1495,4 @@ class Parser extends Tapable {
|
|||
Parser.ECMA_VERSION = ECMA_VERSION;
|
||||
|
||||
module.exports = Parser;
|
||||
Parser.StackedSetMap = StackedSetMap;
|
||||
|
|
|
@ -62,7 +62,7 @@ class RecordIdsPlugin {
|
|||
records.chunks.usedIds = {};
|
||||
chunks.forEach(chunk => {
|
||||
const name = chunk.name;
|
||||
const blockIdents = chunk.blocks.map(getDepBlockIdent.bind(null, chunk)).filter(Boolean);
|
||||
const blockIdents = chunk.mapBlocks(getDepBlockIdent.bind(null, chunk)).filter(Boolean);
|
||||
if(name) records.chunks.byName[name] = chunk.id;
|
||||
blockIdents.forEach((blockIdent) => {
|
||||
records.chunks.byBlocks[blockIdent] = chunk.id;
|
||||
|
@ -87,7 +87,7 @@ class RecordIdsPlugin {
|
|||
if(records.chunks.byBlocks) {
|
||||
const argumentedChunks = chunks.filter(chunk => chunk.id === null).map(chunk => ({
|
||||
chunk,
|
||||
blockIdents: chunk.blocks.map(getDepBlockIdent.bind(null, chunk)).filter(Boolean)
|
||||
blockIdents: chunk.mapBlocks(getDepBlockIdent.bind(null, chunk)).filter(Boolean)
|
||||
})).filter(arg => arg.blockIdents.length > 0);
|
||||
let blockIdentsCount = {};
|
||||
argumentedChunks.forEach((arg, idx) => {
|
||||
|
|
|
@ -53,12 +53,8 @@ class SourceMapDevToolPlugin {
|
|||
constructor(options) {
|
||||
if(arguments.length > 1)
|
||||
throw new Error("SourceMapDevToolPlugin only takes one argument (pass an options object)");
|
||||
// TODO: remove in webpack 3
|
||||
if(typeof options === "string") {
|
||||
options = {
|
||||
sourceMapFilename: options
|
||||
};
|
||||
}
|
||||
if(!options || typeof options !== "object")
|
||||
throw new Error("SourceMapDevToolPlugin takes an options argument");
|
||||
if(!options) options = {};
|
||||
this.sourceMapFilename = options.filename;
|
||||
this.sourceMappingURLComment = options.append === false ? false : options.append || "\n//# sourceMappingURL=[url]";
|
||||
|
|
|
@ -379,7 +379,7 @@ class Stats {
|
|||
names: chunk.name ? [chunk.name] : [],
|
||||
files: chunk.files.slice(),
|
||||
hash: chunk.renderedHash,
|
||||
parents: chunk.parents.map(c => c.id)
|
||||
parents: chunk.mapParents(c => c.id)
|
||||
};
|
||||
if(showChunkModules) {
|
||||
obj.modules = chunk
|
||||
|
|
|
@ -10,10 +10,12 @@ const ConcatSource = require("webpack-sources").ConcatSource;
|
|||
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 FUNCTION_CONTENT_REGEX = /^function\s?\(\)\s?\{\n?|\n?\}$/g;
|
||||
const FUNCTION_CONTENT_REGEX = /^function\s?\(\)\s?\{\r?\n?|\r?\n?\}$/g;
|
||||
const INDENT_MULTILINE_REGEX = /^\t/mg;
|
||||
const IDENTIFIER_NAME_REPLACE_REGEX = /^[^a-zA-Z$_]/;
|
||||
const IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX = /[^a-zA-Z0-9$_]/g;
|
||||
const LINE_SEPARATOR_REGEX = /\r?\n/g;
|
||||
const IDENTIFIER_NAME_REPLACE_REGEX = /^([^a-zA-Z$_])/;
|
||||
const IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX = /[^a-zA-Z0-9$]+/g;
|
||||
const COMMENT_END_REGEX = /\*\//g;
|
||||
const PATH_NAME_NORMALIZE_REPLACE_REGEX = /[^a-zA-Z0-9_!§$()=\-^°]+/g;
|
||||
const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g;
|
||||
|
||||
|
@ -24,12 +26,22 @@ module.exports = class Template extends Tapable {
|
|||
}
|
||||
|
||||
static getFunctionContent(fn) {
|
||||
return fn.toString().replace(FUNCTION_CONTENT_REGEX, "").replace(INDENT_MULTILINE_REGEX, "");
|
||||
return fn.toString().replace(FUNCTION_CONTENT_REGEX, "").replace(INDENT_MULTILINE_REGEX, "").replace(LINE_SEPARATOR_REGEX, "\n");
|
||||
}
|
||||
|
||||
static toIdentifier(str) {
|
||||
if(typeof str !== "string") return "";
|
||||
return str.replace(IDENTIFIER_NAME_REPLACE_REGEX, "_").replace(IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX, "_");
|
||||
return str.replace(IDENTIFIER_NAME_REPLACE_REGEX, "_$1").replace(IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX, "_");
|
||||
}
|
||||
|
||||
static toComment(str) {
|
||||
if(!str) return "";
|
||||
return `/*! ${str.replace(COMMENT_END_REGEX, "* /")} */`;
|
||||
}
|
||||
|
||||
static toNormalComment(str) {
|
||||
if(!str) return "";
|
||||
return `/* ${str.replace(COMMENT_END_REGEX, "* /")} */`;
|
||||
}
|
||||
|
||||
static toPath(str) {
|
||||
|
|
|
@ -18,17 +18,6 @@ const REGEXP_HASH_FOR_TEST = new RegExp(REGEXP_HASH.source, "i"),
|
|||
REGEXP_CHUNKHASH_FOR_TEST = new RegExp(REGEXP_CHUNKHASH.source, "i"),
|
||||
REGEXP_NAME_FOR_TEST = new RegExp(REGEXP_NAME.source, "i");
|
||||
|
||||
// TODO: remove in webpack 3
|
||||
// Backwards compatibility; expose regexes on Template object
|
||||
const Template = require("./Template");
|
||||
Template.REGEXP_HASH = REGEXP_HASH;
|
||||
Template.REGEXP_CHUNKHASH = REGEXP_CHUNKHASH;
|
||||
Template.REGEXP_NAME = REGEXP_NAME;
|
||||
Template.REGEXP_ID = REGEXP_ID;
|
||||
Template.REGEXP_FILE = REGEXP_FILE;
|
||||
Template.REGEXP_QUERY = REGEXP_QUERY;
|
||||
Template.REGEXP_FILEBASE = REGEXP_FILEBASE;
|
||||
|
||||
const withHashLength = (replacer, handlerFn) => {
|
||||
return function(_, hashLength) {
|
||||
const length = hashLength && parseInt(hashLength, 10);
|
||||
|
|
|
@ -95,7 +95,7 @@ class UmdMainTemplatePlugin {
|
|||
}
|
||||
|
||||
function externalsArguments(modules) {
|
||||
return modules.map(m => Template.toIdentifier(`__WEBPACK_EXTERNAL_MODULE_${m.id}__`)).join(", ");
|
||||
return modules.map(m => `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__`).join(", ");
|
||||
}
|
||||
|
||||
function libraryName(library) {
|
||||
|
|
|
@ -41,6 +41,7 @@ const RemoveEmptyChunksPlugin = require("./optimize/RemoveEmptyChunksPlugin");
|
|||
const MergeDuplicateChunksPlugin = require("./optimize/MergeDuplicateChunksPlugin");
|
||||
const FlagIncludedChunksPlugin = require("./optimize/FlagIncludedChunksPlugin");
|
||||
const OccurrenceOrderPlugin = require("./optimize/OccurrenceOrderPlugin");
|
||||
const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin");
|
||||
const FlagDependencyUsagePlugin = require("./FlagDependencyUsagePlugin");
|
||||
const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");
|
||||
const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin");
|
||||
|
@ -259,6 +260,7 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
new MergeDuplicateChunksPlugin(),
|
||||
new FlagIncludedChunksPlugin(),
|
||||
new OccurrenceOrderPlugin(true),
|
||||
new SideEffectsFlagPlugin(),
|
||||
new FlagDependencyExportsPlugin(),
|
||||
new FlagDependencyUsagePlugin()
|
||||
);
|
||||
|
|
|
@ -109,7 +109,7 @@ class AMDDefineDependencyParserPlugin {
|
|||
if(fnParamsOffset < 0) fnParamsOffset = 0;
|
||||
}
|
||||
}
|
||||
let fnRenames = Object.create(parser.scope.renames);
|
||||
let fnRenames = parser.scope.renames.createChild();
|
||||
let identifiers;
|
||||
if(array) {
|
||||
identifiers = {};
|
||||
|
@ -118,7 +118,7 @@ class AMDDefineDependencyParserPlugin {
|
|||
if(!result) return;
|
||||
if(fnParams) fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => {
|
||||
if(identifiers[idx]) {
|
||||
fnRenames["$" + param.name] = identifiers[idx];
|
||||
fnRenames.set(param.name, identifiers[idx]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -127,7 +127,7 @@ class AMDDefineDependencyParserPlugin {
|
|||
identifiers = ["require", "exports", "module"];
|
||||
if(fnParams) fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => {
|
||||
if(identifiers[idx]) {
|
||||
fnRenames["$" + param.name] = identifiers[idx];
|
||||
fnRenames.set(param.name, identifiers[idx]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
"use strict";
|
||||
const Dependency = require("../Dependency");
|
||||
const Template = require("../Template");
|
||||
const webpackMissingModuleModule = require("./WebpackMissingModule").module;
|
||||
|
||||
class AMDRequireArrayDependency extends Dependency {
|
||||
|
@ -26,19 +27,12 @@ AMDRequireArrayDependency.Template = class AMDRequireArrayDependencyTemplate {
|
|||
|
||||
getContent(dep, outputOptions, requestShortener) {
|
||||
const requires = dep.depsArray.map((dependency) => {
|
||||
const optionalComment = this.optionalComment(outputOptions.pathinfo, requestShortener.shorten(dependency.request));
|
||||
const optionalComment = outputOptions.pathinfo ? Template.toComment(requestShortener.shorten(dependency.request)) : "";
|
||||
return this.contentForDependency(dependency, optionalComment);
|
||||
});
|
||||
return `[${requires.join(", ")}]`;
|
||||
}
|
||||
|
||||
optionalComment(pathInfo, shortenedRequest) {
|
||||
if(!pathInfo) {
|
||||
return "";
|
||||
}
|
||||
return `/*! ${shortenedRequest} */ `;
|
||||
}
|
||||
|
||||
contentForDependency(dep, comment) {
|
||||
if(typeof dep === "string") {
|
||||
return dep;
|
||||
|
|
|
@ -65,7 +65,7 @@ class CommonJsPlugin {
|
|||
const dep = new ConstDependency("var require;", 0);
|
||||
dep.loc = expr.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.scope.definitions.push("require");
|
||||
parser.scope.definitions.add("require");
|
||||
return true;
|
||||
});
|
||||
parser.plugin("can-rename require", () => true);
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const Template = require("../Template");
|
||||
|
||||
class ContextDependencyTemplateAsId {
|
||||
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
const comment = outputOptions.pathinfo ?
|
||||
"/*! " + requestShortener.shorten(dep.request) + " */ " : "";
|
||||
const comment = outputOptions.pathinfo ? Template.toComment(requestShortener.shorten(dep.request)) + " " : "";
|
||||
|
||||
if(dep.module && dep.module.dependencies && dep.module.dependencies.length > 0) {
|
||||
if(dep.valueRange) {
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const Template = require("../Template");
|
||||
|
||||
class ContextDependencyTemplateAsRequireCall {
|
||||
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
const comment = outputOptions.pathinfo ?
|
||||
"/*! " + requestShortener.shorten(dep.request) + " */ " : "";
|
||||
const comment = outputOptions.pathinfo ? Template.toComment(requestShortener.shorten(dep.request)) + " " : "";
|
||||
|
||||
const containsDeps = dep.module && dep.module.dependencies && dep.module.dependencies.length > 0;
|
||||
const isAsync = dep.module && dep.module.options.async;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const Template = require("../Template");
|
||||
|
||||
const DepBlockHelpers = exports;
|
||||
|
||||
DepBlockHelpers.getLoadDepBlockWrapper = (depBlock, outputOptions, requestShortener, name) => {
|
||||
|
@ -25,9 +27,9 @@ DepBlockHelpers.getDepBlockPromise = (depBlock, outputOptions, requestShortener,
|
|||
name = asComment(name);
|
||||
if(chunks.length === 1) {
|
||||
const chunkId = JSON.stringify(chunks[0].id);
|
||||
return `__webpack_require__.e${name}(${chunkId}${pathChunkCheck ? "/*! " + shortChunkName + " */" : ""}${chunkReason})`;
|
||||
return `__webpack_require__.e${name}(${chunkId}${pathChunkCheck ? Template.toComment(shortChunkName) : ""}${chunkReason})`;
|
||||
} else if(chunks.length > 0) {
|
||||
return `Promise.all${name}(${pathChunkCheck ? "/*! " + shortChunkName + " */" : ""}[${chunks.map(requireChunkId).join(", ")}])`;
|
||||
return `Promise.all${name}(${pathChunkCheck ? Template.toComment(shortChunkName) : ""}[${chunks.map(requireChunkId).join(", ")}])`;
|
||||
}
|
||||
}
|
||||
return "new Promise(function(resolve) { resolve(); })";
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const NullDependency = require("./NullDependency");
|
||||
const makeHarmonyImportStatement = require("./HarmonyImportDependency").makeImportStatement;
|
||||
const HarmonyImportDependency = require("./HarmonyImportDependency");
|
||||
|
||||
class HarmonyAcceptDependency extends NullDependency {
|
||||
constructor(range, dependencies, hasCallback) {
|
||||
|
@ -22,12 +23,9 @@ class HarmonyAcceptDependency extends NullDependency {
|
|||
HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate {
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
const content = dep.dependencies
|
||||
.map(dependency => makeHarmonyImportStatement(
|
||||
false,
|
||||
dependency,
|
||||
outputOptions,
|
||||
requestShortener
|
||||
)).join("");
|
||||
.filter(dependency => HarmonyImportDependency.Template.isImportEmitted(dependency, source))
|
||||
.map(dependency => dependency.getImportStatement(false, outputOptions, requestShortener))
|
||||
.join("");
|
||||
|
||||
if(dep.hasCallback) {
|
||||
source.insert(dep.range[0], `function(__WEBPACK_OUTDATED_DEPENDENCIES__) { ${content}(`);
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
const HarmonyImportDependency = require("./HarmonyImportDependency");
|
||||
|
||||
class HarmonyAcceptImportDependency extends HarmonyImportDependency {
|
||||
constructor(request, importedVar, range) {
|
||||
super(request, importedVar, range);
|
||||
constructor(request, originModule, parserScope) {
|
||||
super(request, originModule, NaN, parserScope);
|
||||
}
|
||||
|
||||
get type() {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
|
||||
const HarmonyInitDependency = require("./HarmonyInitDependency");
|
||||
|
||||
module.exports = class HarmonyDetectionParserPlugin {
|
||||
apply(parser) {
|
||||
|
@ -14,8 +15,21 @@ module.exports = class HarmonyDetectionParserPlugin {
|
|||
});
|
||||
if(isHarmony) {
|
||||
const module = parser.state.module;
|
||||
const dep = new HarmonyCompatibilityDependency(module);
|
||||
dep.loc = {
|
||||
const compatDep = new HarmonyCompatibilityDependency(module);
|
||||
compatDep.loc = {
|
||||
start: {
|
||||
line: -1,
|
||||
column: 0
|
||||
},
|
||||
end: {
|
||||
line: -1,
|
||||
column: 0
|
||||
},
|
||||
index: -3
|
||||
};
|
||||
module.addDependency(compatDep);
|
||||
const initDep = new HarmonyInitDependency(module);
|
||||
initDep.loc = {
|
||||
start: {
|
||||
line: -1,
|
||||
column: 0
|
||||
|
@ -26,7 +40,8 @@ module.exports = class HarmonyDetectionParserPlugin {
|
|||
},
|
||||
index: -2
|
||||
};
|
||||
module.addDependency(dep);
|
||||
module.addDependency(initDep);
|
||||
parser.state.harmonyParserScope = parser.state.harmonyParserScope || {};
|
||||
module.meta.harmonyModule = true;
|
||||
module.strict = true;
|
||||
module.exportsArgument = "__webpack_exports__";
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
"use strict";
|
||||
|
||||
const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency");
|
||||
const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
|
||||
const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
|
||||
const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
|
||||
const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
|
||||
const HarmonyImportDependency = require("./HarmonyImportDependency");
|
||||
const HarmonyModulesHelpers = require("./HarmonyModulesHelpers");
|
||||
const ConstDependency = require("./ConstDependency");
|
||||
|
||||
module.exports = class HarmonyExportDependencyParserPlugin {
|
||||
apply(parser) {
|
||||
|
@ -21,11 +21,15 @@ module.exports = class HarmonyExportDependencyParserPlugin {
|
|||
return true;
|
||||
});
|
||||
parser.plugin("export import", (statement, source) => {
|
||||
const dep = new HarmonyImportDependency(source, HarmonyModulesHelpers.getNewModuleVar(parser.state, source), statement.range);
|
||||
dep.loc = Object.create(statement.loc);
|
||||
dep.loc.index = -1;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.lastHarmonyImport = dep;
|
||||
parser.state.lastHarmonyImportOrder = (parser.state.lastHarmonyImportOrder || 0) + 1;
|
||||
const clearDep = new ConstDependency("", statement.range);
|
||||
clearDep.loc = Object.create(statement.loc);
|
||||
clearDep.loc.index = -1;
|
||||
parser.state.current.addDependency(clearDep);
|
||||
const sideEffectDep = new HarmonyImportSideEffectDependency(source, parser.state.module, parser.state.lastHarmonyImportOrder, parser.state.harmonyParserScope);
|
||||
sideEffectDep.loc = Object.create(statement.loc);
|
||||
sideEffectDep.loc.index = -1;
|
||||
parser.state.current.addDependency(sideEffectDep);
|
||||
return true;
|
||||
});
|
||||
parser.plugin("export expression", (statement, expr) => {
|
||||
|
@ -37,17 +41,15 @@ module.exports = class HarmonyExportDependencyParserPlugin {
|
|||
});
|
||||
parser.plugin("export declaration", statement => {});
|
||||
parser.plugin("export specifier", (statement, id, name, idx) => {
|
||||
const rename = parser.scope.renames[`$${id}`];
|
||||
const rename = parser.scope.renames.get(id);
|
||||
let dep;
|
||||
const harmonyNamedExports = parser.state.harmonyNamedExports = parser.state.harmonyNamedExports || new Set();
|
||||
harmonyNamedExports.add(name);
|
||||
if(rename === "imported var") {
|
||||
const settings = parser.state.harmonySpecifier[`$${id}`];
|
||||
dep = new HarmonyExportImportedSpecifierDependency(parser.state.module, settings[0], settings[1], settings[2], name, harmonyNamedExports, null);
|
||||
const settings = parser.state.harmonySpecifier.get(id);
|
||||
dep = new HarmonyExportImportedSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, settings.id, name, harmonyNamedExports, null);
|
||||
} else {
|
||||
const immutable = statement.declaration && isImmutableStatement(statement.declaration);
|
||||
const hoisted = statement.declaration && isHoistedStatement(statement.declaration);
|
||||
dep = new HarmonyExportSpecifierDependency(parser.state.module, id, name, !immutable || hoisted ? -2 : (statement.range[1] + 0.5), immutable);
|
||||
dep = new HarmonyExportSpecifierDependency(parser.state.module, id, name);
|
||||
}
|
||||
dep.loc = Object.create(statement.loc);
|
||||
dep.loc.index = idx;
|
||||
|
@ -62,7 +64,7 @@ module.exports = class HarmonyExportDependencyParserPlugin {
|
|||
} else {
|
||||
harmonyStarExports = parser.state.harmonyStarExports = parser.state.harmonyStarExports || [];
|
||||
}
|
||||
const dep = new HarmonyExportImportedSpecifierDependency(parser.state.module, parser.state.lastHarmonyImport, HarmonyModulesHelpers.getModuleVar(parser.state, source), id, name, harmonyNamedExports, harmonyStarExports && harmonyStarExports.slice());
|
||||
const dep = new HarmonyExportImportedSpecifierDependency(source, parser.state.module, parser.state.lastHarmonyImportOrder, parser.state.harmonyParserScope, id, name, harmonyNamedExports, harmonyStarExports && harmonyStarExports.slice());
|
||||
if(harmonyStarExports) {
|
||||
harmonyStarExports.push(dep);
|
||||
}
|
||||
|
@ -73,15 +75,3 @@ module.exports = class HarmonyExportDependencyParserPlugin {
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
function isImmutableStatement(statement) {
|
||||
if(statement.type === "FunctionDeclaration") return true;
|
||||
if(statement.type === "ClassDeclaration") return true;
|
||||
if(statement.type === "VariableDeclaration" && statement.kind === "const") return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function isHoistedStatement(statement) {
|
||||
if(statement.type === "FunctionDeclaration") return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3,14 +3,12 @@
|
|||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
const NullDependency = require("./NullDependency");
|
||||
const HarmonyImportDependency = require("./HarmonyImportDependency");
|
||||
const Template = require("../Template");
|
||||
|
||||
class HarmonyExportImportedSpecifierDependency extends NullDependency {
|
||||
constructor(originModule, importDependency, importedVar, id, name, activeExports, otherStarExports) {
|
||||
super();
|
||||
this.originModule = originModule;
|
||||
this.importDependency = importDependency;
|
||||
this.importedVar = importedVar;
|
||||
class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
||||
constructor(request, originModule, sourceOrder, parserScope, id, name, activeExports, otherStarExports) {
|
||||
super(request, originModule, sourceOrder, parserScope);
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.activeExports = activeExports;
|
||||
|
@ -21,81 +19,183 @@ class HarmonyExportImportedSpecifierDependency extends NullDependency {
|
|||
return "harmony export imported specifier";
|
||||
}
|
||||
|
||||
getReference() {
|
||||
getMode(ignoreUnused) {
|
||||
const name = this.name;
|
||||
const id = this.id;
|
||||
const used = this.originModule.isUsed(name);
|
||||
const importedModule = this.importDependency.module;
|
||||
const importedModule = this.module;
|
||||
|
||||
if(!importedModule || !used || !this.originModule.usedExports) return null;
|
||||
if(!importedModule) {
|
||||
return {
|
||||
type: "missing",
|
||||
userRequest: this.userRequest
|
||||
};
|
||||
}
|
||||
|
||||
const hasUsedExports = Array.isArray(this.originModule.usedExports);
|
||||
if(!ignoreUnused && (name ? !used : this.originModule.usedExports === false)) {
|
||||
return {
|
||||
type: "unused",
|
||||
name: name || "*"
|
||||
};
|
||||
}
|
||||
|
||||
const isNotAHarmonyModule = importedModule.meta && !importedModule.meta.harmonyModule;
|
||||
if(name && id === "default" && isNotAHarmonyModule) {
|
||||
return {
|
||||
type: "reexport-non-harmony-default",
|
||||
module: importedModule,
|
||||
name
|
||||
};
|
||||
}
|
||||
|
||||
if(name) {
|
||||
const nameIsNotInUsedExports = hasUsedExports && this.originModule.usedExports.indexOf(name) < 0;
|
||||
if(nameIsNotInUsedExports) return null;
|
||||
|
||||
// export { name as name }
|
||||
if(this.id) {
|
||||
if(id) {
|
||||
return {
|
||||
type: "safe-reexport",
|
||||
module: importedModule,
|
||||
importedNames: [this.id]
|
||||
map: new Map([
|
||||
[name, id]
|
||||
])
|
||||
};
|
||||
}
|
||||
|
||||
// export { * as name }
|
||||
return {
|
||||
type: "reexport-namespace-object",
|
||||
module: importedModule,
|
||||
importedNames: true
|
||||
name
|
||||
};
|
||||
}
|
||||
|
||||
const hasUsedExports = Array.isArray(this.originModule.usedExports);
|
||||
const hasProvidedExports = Array.isArray(importedModule.providedExports);
|
||||
const activeFromOtherStarExports = this._discoverActiveExportsFromOtherStartExports();
|
||||
|
||||
// export *
|
||||
if(hasUsedExports) {
|
||||
// reexport * with known used exports
|
||||
const importedNames = this.originModule.usedExports.filter(id => {
|
||||
if(hasProvidedExports) {
|
||||
const map = new Map(this.originModule.usedExports.filter((id) => {
|
||||
if(id === "default") return false;
|
||||
if(this.activeExports.has(id)) return false;
|
||||
if(activeFromOtherStarExports.has(id)) return false;
|
||||
if(hasProvidedExports && importedModule.providedExports.indexOf(id) < 0) return false;
|
||||
if(importedModule.providedExports.indexOf(id) < 0) return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
}).map(item => [item, item]));
|
||||
|
||||
if(map.size === 0) {
|
||||
return {
|
||||
type: "empty-star"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: "safe-reexport",
|
||||
module: importedModule,
|
||||
importedNames
|
||||
map
|
||||
};
|
||||
}
|
||||
|
||||
const map = new Map(this.originModule.usedExports.filter(id => {
|
||||
if(id === "default") return false;
|
||||
if(this.activeExports.has(id)) return false;
|
||||
if(activeFromOtherStarExports.has(id)) return false;
|
||||
|
||||
return true;
|
||||
}).map(item => [item, item]));
|
||||
|
||||
if(map.size === 0) {
|
||||
return {
|
||||
type: "empty-star"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: "checked-reexport",
|
||||
module: importedModule,
|
||||
map
|
||||
};
|
||||
}
|
||||
|
||||
if(hasProvidedExports) {
|
||||
return {
|
||||
module: importedModule,
|
||||
importedNames: importedModule.providedExports.filter(id => {
|
||||
const map = new Map(importedModule.providedExports
|
||||
.filter(id => {
|
||||
if(id === "default") return false;
|
||||
if(this.activeExports.has(id)) return false;
|
||||
if(activeFromOtherStarExports.has(id)) return false;
|
||||
|
||||
return true;
|
||||
})
|
||||
.map(item => [item, item])
|
||||
);
|
||||
|
||||
if(map.size === 0) {
|
||||
return {
|
||||
type: "empty-star"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: "safe-reexport",
|
||||
module: importedModule,
|
||||
importedNames: true,
|
||||
map
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: "dynamic-reexport",
|
||||
module: importedModule
|
||||
};
|
||||
}
|
||||
|
||||
getReference() {
|
||||
const mode = this.getMode();
|
||||
|
||||
switch(mode.type) {
|
||||
case "missing":
|
||||
case "unused":
|
||||
case "empty-star":
|
||||
return null;
|
||||
|
||||
case "reexport-non-harmony-default":
|
||||
return {
|
||||
module: mode.module,
|
||||
importedNames: ["default"]
|
||||
};
|
||||
|
||||
case "reexport-namespace-object":
|
||||
return {
|
||||
module: mode.module,
|
||||
importedNames: true
|
||||
};
|
||||
|
||||
case "safe-reexport":
|
||||
case "checked-reexport":
|
||||
return {
|
||||
module: mode.module,
|
||||
importedNames: Array.from(mode.map.values())
|
||||
};
|
||||
|
||||
case "dynamic-reexport":
|
||||
return {
|
||||
module: mode.module,
|
||||
importedNames: true
|
||||
};
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown mode ${mode.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
_discoverActiveExportsFromOtherStartExports() {
|
||||
if(!this.otherStarExports)
|
||||
return new Set();
|
||||
const result = new Set();
|
||||
// try to learn impossible exports from other star exports with provided exports
|
||||
for(const otherStarExport of this.otherStarExports) {
|
||||
const otherImportedModule = otherStarExport.importDependency.module;
|
||||
const otherImportedModule = otherStarExport.module;
|
||||
if(otherImportedModule && Array.isArray(otherImportedModule.providedExports)) {
|
||||
for(const exportName of otherImportedModule.providedExports)
|
||||
result.add(exportName);
|
||||
|
@ -111,7 +211,7 @@ class HarmonyExportImportedSpecifierDependency extends NullDependency {
|
|||
};
|
||||
}
|
||||
|
||||
const importedModule = this.importDependency.module;
|
||||
const importedModule = this.module;
|
||||
|
||||
if(!importedModule) {
|
||||
// no imported module available
|
||||
|
@ -141,7 +241,7 @@ class HarmonyExportImportedSpecifierDependency extends NullDependency {
|
|||
|
||||
updateHash(hash) {
|
||||
super.updateHash(hash);
|
||||
const hashValue = this.getHashValue(this.importDependency.module);
|
||||
const hashValue = this.getHashValue(this.module);
|
||||
hash.update(hashValue);
|
||||
}
|
||||
|
||||
|
@ -158,91 +258,85 @@ class HarmonyExportImportedSpecifierDependency extends NullDependency {
|
|||
|
||||
module.exports = HarmonyExportImportedSpecifierDependency;
|
||||
|
||||
HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedSpecifierDependencyTemplate {
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
const content = this.getContent(dep);
|
||||
HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedSpecifierDependencyTemplate extends HarmonyImportDependency.Template {
|
||||
harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
super.harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates);
|
||||
const importVar = dep.getImportVar(requestShortener);
|
||||
const content = this.getContent(dep, importVar);
|
||||
source.insert(-1, content);
|
||||
}
|
||||
|
||||
getContent(dep) {
|
||||
const name = dep.importedVar;
|
||||
getHarmonyInitOrder(dep) {
|
||||
const used = dep.originModule.isUsed(dep.name);
|
||||
const importedModule = dep.importDependency.module;
|
||||
const importsExportsUnknown = !importedModule || !Array.isArray(importedModule.providedExports);
|
||||
|
||||
const getReexportStatement = this.reexportStatementCreator(dep.originModule, importsExportsUnknown, name);
|
||||
|
||||
// we want to rexport something, but the export isn't used
|
||||
if(!used) {
|
||||
return "/* unused harmony reexport " + dep.name + " */\n";
|
||||
}
|
||||
|
||||
// we want to reexport the default export from a non-hamory module
|
||||
const isNotAHarmonyModule = !(importedModule && (!importedModule.meta || importedModule.meta.harmonyModule));
|
||||
if(dep.name && dep.id === "default" && isNotAHarmonyModule) {
|
||||
return "/* harmony reexport (default from non-hamory) */ " + getReexportStatement(JSON.stringify(used), null);
|
||||
}
|
||||
|
||||
// we want to reexport a key as new key
|
||||
if(dep.name && dep.id) {
|
||||
var idUsed = importedModule && importedModule.isUsed(dep.id);
|
||||
return "/* harmony reexport (binding) */ " + getReexportStatement(JSON.stringify(used), JSON.stringify(idUsed));
|
||||
}
|
||||
|
||||
// we want to reexport the module object as named export
|
||||
if(dep.name) {
|
||||
return "/* harmony reexport (module object) */ " + getReexportStatement(JSON.stringify(used), "");
|
||||
}
|
||||
|
||||
const hasProvidedExports = importedModule && Array.isArray(importedModule.providedExports);
|
||||
if(!used) return NaN;
|
||||
if(!dep.name) {
|
||||
const importedModule = dep.module;
|
||||
|
||||
const activeFromOtherStarExports = dep._discoverActiveExportsFromOtherStartExports();
|
||||
|
||||
// we know which exports are used
|
||||
if(Array.isArray(dep.originModule.usedExports)) {
|
||||
const items = dep.originModule.usedExports.map(id => {
|
||||
if(id === "default") return;
|
||||
if(dep.activeExports.has(id)) return;
|
||||
if(importedModule.isProvided(id) === false) return;
|
||||
if(activeFromOtherStarExports.has(id)) return;
|
||||
var exportUsed = dep.originModule.isUsed(id);
|
||||
var idUsed = importedModule && importedModule.isUsed(id);
|
||||
return [exportUsed, idUsed];
|
||||
}).filter(Boolean);
|
||||
// we know which exports are used
|
||||
|
||||
if(items.length === 0) {
|
||||
return "/* unused harmony namespace reexport */\n";
|
||||
}
|
||||
|
||||
return items.map(function(item) {
|
||||
return "/* harmony namespace reexport (by used) */ " + getReexportStatement(JSON.stringify(item[0]), JSON.stringify(item[1]));
|
||||
}).join("");
|
||||
}
|
||||
const unused = dep.originModule.usedExports.every(function(id) {
|
||||
if(id === "default") return true;
|
||||
if(dep.activeExports.has(id)) return true;
|
||||
if(importedModule.isProvided(id) === false) return true;
|
||||
if(activeFromOtherStarExports.has(id)) return true;
|
||||
return false;
|
||||
});
|
||||
if(unused) return NaN;
|
||||
|
||||
} else if(dep.originModule.usedExports && importedModule && Array.isArray(importedModule.providedExports)) {
|
||||
// not sure which exports are used, but we know which are provided
|
||||
if(dep.originModule.usedExports && importedModule && hasProvidedExports) {
|
||||
const items = importedModule.providedExports.map(id => {
|
||||
if(id === "default") return;
|
||||
if(dep.activeExports.has(id)) return;
|
||||
if(activeFromOtherStarExports.has(id)) return;
|
||||
var exportUsed = dep.originModule.isUsed(id);
|
||||
var idUsed = importedModule && importedModule.isUsed(id);
|
||||
return [exportUsed, idUsed];
|
||||
}).filter(Boolean);
|
||||
|
||||
if(items.length === 0) {
|
||||
return "/* empty harmony namespace reexport */\n";
|
||||
const unused = importedModule.providedExports.every(function(id) {
|
||||
if(id === "default") return true;
|
||||
if(dep.activeExports.has(id)) return true;
|
||||
if(activeFromOtherStarExports.has(id)) return true;
|
||||
return false;
|
||||
});
|
||||
if(unused) return NaN;
|
||||
}
|
||||
}
|
||||
return super.getHarmonyInitOrder(dep);
|
||||
}
|
||||
|
||||
return items.map(function(item) {
|
||||
return "/* harmony namespace reexport (by provided) */ " + getReexportStatement(JSON.stringify(item[0]), JSON.stringify(item[1]));
|
||||
getContent(dep, name) {
|
||||
const mode = dep.getMode();
|
||||
const module = dep.originModule;
|
||||
const importedModule = dep.module;
|
||||
const importVar = dep.getImportVar();
|
||||
|
||||
switch(mode.type) {
|
||||
case "missing":
|
||||
return `throw new Error(${JSON.stringify(`Cannot find module '${mode.userRequest}'`)});\n`;
|
||||
|
||||
case "unused":
|
||||
return `${Template.toNormalComment(`unused harmony reexport ${mode.name}`)}\n`;
|
||||
|
||||
case "reexport-non-harmony-default":
|
||||
return "/* harmony reexport (default from non-hamory) */ " + this.getReexportStatement(module, module.isUsed(mode.name), importVar, null);
|
||||
|
||||
case "reexport-namespace-object":
|
||||
return "/* harmony reexport (module object) */ " + this.getReexportStatement(module, module.isUsed(mode.name), importVar, "");
|
||||
|
||||
case "empty-star":
|
||||
return "/* empty/unused harmony star reexport */";
|
||||
|
||||
case "safe-reexport":
|
||||
return Array.from(mode.map.entries()).map(item => {
|
||||
return "/* harmony reexport (safe) */ " + this.getReexportStatement(module, module.isUsed(item[0]), importVar, importedModule.isUsed(item[1])) + "\n";
|
||||
}).join("");
|
||||
}
|
||||
|
||||
// not sure which exports are used and provided
|
||||
if(dep.originModule.usedExports) {
|
||||
const activeExports = Array.from(dep.activeExports).concat(Array.from(activeFromOtherStarExports));
|
||||
let content = "/* harmony namespace reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in " + name + ") ";
|
||||
case "checked-reexport":
|
||||
return Array.from(mode.map.entries()).map(item => {
|
||||
return "/* harmony reexport (checked) */ " + this.getConditionalReexportStatement(module, item[0], importVar, item[1]) + "\n";
|
||||
}).join("");
|
||||
|
||||
case "dynamic-reexport":
|
||||
{
|
||||
const activeExports = Array.from(dep.activeExports).concat(dep._discoverActiveExportsFromOtherStartExports());
|
||||
let content = "/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in " + importVar + ") ";
|
||||
|
||||
// Filter out exports which are defined by other exports
|
||||
// and filter out default export because it cannot be reexported with *
|
||||
|
@ -254,25 +348,21 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
|
|||
return content + `(function(key) { __webpack_require__.d(${exportsName}, key, function() { return ${name}[key]; }) }(__WEBPACK_IMPORT_KEY__));\n`;
|
||||
}
|
||||
|
||||
return "/* unused harmony reexport namespace */\n";
|
||||
default:
|
||||
throw new Error(`Unknown mode ${mode.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
reexportStatementCreator(module, importsExportsUnknown, name) {
|
||||
getReexportStatement(module, key, name, valueKey) {
|
||||
const exportsName = module.exportsArgument || "exports";
|
||||
const getReexportStatement = (key, valueKey) => {
|
||||
const conditional = this.getConditional(importsExportsUnknown, valueKey, name);
|
||||
const returnValue = this.getReturnValue(valueKey);
|
||||
return `${conditional}__webpack_require__.d(${exportsName}, ${key}, function() { return ${name}${returnValue}; });\n`;
|
||||
};
|
||||
return getReexportStatement;
|
||||
return `__webpack_require__.d(${exportsName}, ${JSON.stringify(key)}, function() { return ${name}${returnValue}; });\n`;
|
||||
}
|
||||
|
||||
getConditional(importsExportsUnknown, valueKey, name) {
|
||||
if(!importsExportsUnknown || !valueKey) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return `if(__webpack_require__.o(${name}, ${valueKey})) `;
|
||||
getConditionalReexportStatement(module, key, name, valueKey) {
|
||||
const exportsName = module.exportsArgument || "exports";
|
||||
const returnValue = this.getReturnValue(valueKey);
|
||||
return `if(__webpack_require__.o(${name}, ${JSON.stringify(valueKey)})) __webpack_require__.d(${exportsName}, ${JSON.stringify(key)}, function() { return ${name}${returnValue}; });\n`;
|
||||
}
|
||||
|
||||
getReturnValue(valueKey) {
|
||||
|
@ -280,6 +370,6 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
|
|||
return "_default.a";
|
||||
}
|
||||
|
||||
return valueKey && "[" + valueKey + "]";
|
||||
return valueKey && "[" + JSON.stringify(valueKey) + "]";
|
||||
}
|
||||
};
|
||||
|
|
|
@ -6,13 +6,11 @@
|
|||
const NullDependency = require("./NullDependency");
|
||||
|
||||
class HarmonyExportSpecifierDependency extends NullDependency {
|
||||
constructor(originModule, id, name, position, immutable) {
|
||||
constructor(originModule, id, name) {
|
||||
super();
|
||||
this.originModule = originModule;
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.position = position;
|
||||
this.immutable = immutable;
|
||||
}
|
||||
|
||||
get type() {
|
||||
|
@ -27,13 +25,15 @@ class HarmonyExportSpecifierDependency extends NullDependency {
|
|||
}
|
||||
|
||||
HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependencyTemplate {
|
||||
apply(dep, source) {
|
||||
const content = this.getPrefix(dep) + this.getContent(dep);
|
||||
source.insert(dep.position, content);
|
||||
apply(dep, source) {}
|
||||
|
||||
getHarmonyInitOrder(dep) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
getPrefix(dep) {
|
||||
return dep.position > 0 ? "\n" : "";
|
||||
harmonyInit(dep, source, outputOptions, requestShortener) {
|
||||
const content = this.getContent(dep);
|
||||
source.insert(-1, content);
|
||||
}
|
||||
|
||||
getContent(dep) {
|
||||
|
@ -43,9 +43,6 @@ HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependen
|
|||
}
|
||||
|
||||
const exportsName = dep.originModule.exportsArgument || "exports";
|
||||
if(dep.immutable) {
|
||||
return `/* harmony export (immutable) */ ${exportsName}[${JSON.stringify(used)}] = ${dep.id};\n`;
|
||||
}
|
||||
|
||||
return `/* harmony export (binding) */ __webpack_require__.d(${exportsName}, ${JSON.stringify(used)}, function() { return ${dep.id}; });\n`;
|
||||
}
|
||||
|
|
|
@ -3,17 +3,15 @@
|
|||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
var ModuleDependency = require("./ModuleDependency");
|
||||
const ModuleDependency = require("./ModuleDependency");
|
||||
const Template = require("../Template");
|
||||
|
||||
class HarmonyImportDependency extends ModuleDependency {
|
||||
constructor(request, importedVar, range) {
|
||||
constructor(request, originModule, sourceOrder, parserScope) {
|
||||
super(request);
|
||||
this.range = range;
|
||||
this.importedVar = importedVar;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return "harmony import";
|
||||
this.originModule = originModule;
|
||||
this.sourceOrder = sourceOrder;
|
||||
this.parserScope = parserScope;
|
||||
}
|
||||
|
||||
getReference() {
|
||||
|
@ -25,48 +23,78 @@ class HarmonyImportDependency extends ModuleDependency {
|
|||
};
|
||||
}
|
||||
|
||||
updateHash(hash) {
|
||||
super.updateHash(hash);
|
||||
hash.update((this.module && (!this.module.meta || this.module.meta.harmonyModule)) + "");
|
||||
}
|
||||
getImportVar() {
|
||||
let importVarMap = this.parserScope.importVarMap;
|
||||
if(!importVarMap) this.parserScope.importVarMap = importVarMap = new Map();
|
||||
let importVar = importVarMap.get(this.module);
|
||||
if(importVar) return importVar;
|
||||
importVar = `${Template.toIdentifier(`${this.userRequest}`)}__WEBPACK_IMPORTED_MODULE_${importVarMap.size}__`;
|
||||
importVarMap.set(this.module, importVar);
|
||||
return importVar;
|
||||
}
|
||||
|
||||
HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate {
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
const content = makeImportStatement(true, dep, outputOptions, requestShortener);
|
||||
source.replace(dep.range[0], dep.range[1] - 1, "");
|
||||
source.insert(-1, content);
|
||||
}
|
||||
};
|
||||
getImportStatement(declare, outputOptions, requestShortener) {
|
||||
const module = this.module;
|
||||
const comment = outputOptions.pathinfo ? Template.toComment(requestShortener.shorten(this.request)) : "";
|
||||
const optDeclaration = declare ? "var " : "";
|
||||
const optNewline = declare ? "\n" : " ";
|
||||
|
||||
function getOptionalComment(pathinfo, shortenedRequest) {
|
||||
if(!pathinfo) {
|
||||
return "";
|
||||
}
|
||||
return `/*! ${shortenedRequest} */ `;
|
||||
if(!module) {
|
||||
const stringifiedError = JSON.stringify(`Cannot find module "${this.request}"`);
|
||||
return `throw new Error(${stringifiedError});${optNewline}`;
|
||||
}
|
||||
|
||||
function makeImportStatement(declare, dep, outputOptions, requestShortener) {
|
||||
const comment = getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request));
|
||||
const declaration = declare ? "var " : "";
|
||||
const newline = declare ? "\n" : " ";
|
||||
const importVar = this.getImportVar();
|
||||
|
||||
if(!dep.module) {
|
||||
const stringifiedError = JSON.stringify(`Cannot find module "${dep.request}"`);
|
||||
return `throw new Error(${stringifiedError});${newline}`;
|
||||
}
|
||||
|
||||
if(dep.importedVar) {
|
||||
const isHarmonyModule = dep.module.meta && dep.module.meta.harmonyModule;
|
||||
const content = `/* harmony import */ ${declaration}${dep.importedVar} = __webpack_require__(${comment}${JSON.stringify(dep.module.id)});${newline}`;
|
||||
if(importVar) {
|
||||
const isHarmonyModule = module.meta && module.meta.harmonyModule;
|
||||
const content = `/* harmony import */ ${optDeclaration}${importVar} = __webpack_require__(${comment}${JSON.stringify(module.id)});${optNewline}`;
|
||||
if(isHarmonyModule) {
|
||||
return content;
|
||||
}
|
||||
return `${content}/* harmony import */ ${declaration}${dep.importedVar}_default = __webpack_require__.n(${dep.importedVar});${newline}`;
|
||||
return `${content}/* harmony import */ ${optDeclaration}${importVar}_default = /*#__PURE__*/__webpack_require__.n(${importVar});${optNewline}`;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
HarmonyImportDependency.makeImportStatement = makeImportStatement;
|
||||
|
||||
updateHash(hash) {
|
||||
super.updateHash(hash);
|
||||
const importedModule = this.module;
|
||||
hash.update((importedModule && (!importedModule.meta || importedModule.meta.harmonyModule)) + "");
|
||||
hash.update((importedModule && importedModule.id) + "");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HarmonyImportDependency;
|
||||
|
||||
const importEmittedMap = new WeakMap();
|
||||
|
||||
HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate {
|
||||
apply() {}
|
||||
|
||||
getHarmonyInitOrder(dep) {
|
||||
return dep.sourceOrder;
|
||||
}
|
||||
|
||||
static isImportEmitted(dep, source) {
|
||||
let sourceInfo = importEmittedMap.get(source);
|
||||
if(!sourceInfo) return false;
|
||||
const key = dep.module || dep.request;
|
||||
return key && sourceInfo.emittedImports.get(key);
|
||||
}
|
||||
|
||||
harmonyInit(dep, source, outputOptions, requestShortener) {
|
||||
let sourceInfo = importEmittedMap.get(source);
|
||||
if(!sourceInfo) {
|
||||
importEmittedMap.set(source, sourceInfo = {
|
||||
emittedImports: new Map()
|
||||
});
|
||||
}
|
||||
const key = dep.module || dep.request;
|
||||
if(key && sourceInfo.emittedImports.get(key)) return;
|
||||
sourceInfo.emittedImports.set(key, true);
|
||||
const content = dep.getImportStatement(true, outputOptions, requestShortener);
|
||||
source.insert(-1, content);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const HarmonyImportDependency = require("./HarmonyImportDependency");
|
||||
const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
|
||||
const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
|
||||
const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
|
||||
const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
|
||||
const HarmonyModulesHelpers = require("./HarmonyModulesHelpers");
|
||||
const ConstDependency = require("./ConstDependency");
|
||||
|
||||
module.exports = class HarmonyImportDependencyParserPlugin {
|
||||
constructor(moduleOptions) {
|
||||
|
@ -18,39 +18,46 @@ module.exports = class HarmonyImportDependencyParserPlugin {
|
|||
|
||||
apply(parser) {
|
||||
parser.plugin("import", (statement, source) => {
|
||||
const dep = new HarmonyImportDependency(source, HarmonyModulesHelpers.getNewModuleVar(parser.state, source), statement.range);
|
||||
dep.loc = statement.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.lastHarmonyImport = dep;
|
||||
parser.state.lastHarmonyImportOrder = (parser.state.lastHarmonyImportOrder || 0) + 1;
|
||||
const clearDep = new ConstDependency("", statement.range);
|
||||
clearDep.loc = statement.loc;
|
||||
parser.state.module.addDependency(clearDep);
|
||||
const sideEffectDep = new HarmonyImportSideEffectDependency(source, parser.state.module, parser.state.lastHarmonyImportOrder, parser.state.harmonyParserScope);
|
||||
sideEffectDep.loc = statement.loc;
|
||||
parser.state.module.addDependency(sideEffectDep);
|
||||
return true;
|
||||
});
|
||||
parser.plugin("import specifier", (statement, source, id, name) => {
|
||||
parser.scope.definitions.length--;
|
||||
parser.scope.renames[`$${name}`] = "imported var";
|
||||
if(!parser.state.harmonySpecifier) parser.state.harmonySpecifier = {};
|
||||
parser.state.harmonySpecifier[`$${name}`] = [parser.state.lastHarmonyImport, HarmonyModulesHelpers.getModuleVar(parser.state, source), id];
|
||||
parser.scope.definitions.delete(name);
|
||||
parser.scope.renames.set(name, "imported var");
|
||||
if(!parser.state.harmonySpecifier) parser.state.harmonySpecifier = new Map();
|
||||
parser.state.harmonySpecifier.set(name, {
|
||||
source,
|
||||
id,
|
||||
sourceOrder: parser.state.lastHarmonyImportOrder
|
||||
});
|
||||
return true;
|
||||
});
|
||||
parser.plugin("expression imported var", (expr) => {
|
||||
const name = expr.name;
|
||||
const settings = parser.state.harmonySpecifier[`$${name}`];
|
||||
const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], settings[2], name, expr.range, this.strictExportPresence);
|
||||
const settings = parser.state.harmonySpecifier.get(name);
|
||||
const dep = new HarmonyImportSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, settings.id, name, expr.range, this.strictExportPresence);
|
||||
dep.shorthand = parser.scope.inShorthand;
|
||||
dep.directImport = true;
|
||||
dep.loc = expr.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.module.addDependency(dep);
|
||||
return true;
|
||||
});
|
||||
parser.plugin("expression imported var.*", (expr) => {
|
||||
const name = expr.object.name;
|
||||
const settings = parser.state.harmonySpecifier[`$${name}`];
|
||||
if(settings[2] !== null)
|
||||
const settings = parser.state.harmonySpecifier.get(name);
|
||||
if(settings.id !== null)
|
||||
return false;
|
||||
const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], expr.property.name || expr.property.value, name, expr.range, this.strictExportPresence);
|
||||
const dep = new HarmonyImportSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, expr.property.name || expr.property.value, name, expr.range, this.strictExportPresence);
|
||||
dep.shorthand = parser.scope.inShorthand;
|
||||
dep.directImport = false;
|
||||
dep.loc = expr.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.module.addDependency(dep);
|
||||
return true;
|
||||
});
|
||||
if(this.strictThisContextOnImports) {
|
||||
|
@ -59,15 +66,15 @@ module.exports = class HarmonyImportDependencyParserPlugin {
|
|||
if(expr.callee.type !== "MemberExpression") return;
|
||||
if(expr.callee.object.type !== "Identifier") return;
|
||||
const name = expr.callee.object.name;
|
||||
const settings = parser.state.harmonySpecifier[`$${name}`];
|
||||
if(settings[2] !== null)
|
||||
const settings = parser.state.harmonySpecifier.get(name);
|
||||
if(settings.id !== null)
|
||||
return false;
|
||||
const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], expr.callee.property.name || expr.callee.property.value, name, expr.callee.range, this.strictExportPresence);
|
||||
const dep = new HarmonyImportSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, expr.callee.property.name || expr.callee.property.value, name, expr.callee.range, this.strictExportPresence);
|
||||
dep.shorthand = parser.scope.inShorthand;
|
||||
dep.directImport = false;
|
||||
dep.namespaceObjectAsContext = true;
|
||||
dep.loc = expr.callee.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.module.addDependency(dep);
|
||||
if(expr.arguments)
|
||||
parser.walkExpressions(expr.arguments);
|
||||
return true;
|
||||
|
@ -79,45 +86,43 @@ module.exports = class HarmonyImportDependencyParserPlugin {
|
|||
expr = expr.callee;
|
||||
if(expr.type !== "Identifier") return;
|
||||
const name = expr.name;
|
||||
const settings = parser.state.harmonySpecifier[`$${name}`];
|
||||
const dep = new HarmonyImportSpecifierDependency(settings[0], settings[1], settings[2], name, expr.range, this.strictExportPresence);
|
||||
const settings = parser.state.harmonySpecifier.get(name);
|
||||
const dep = new HarmonyImportSpecifierDependency(settings.source, parser.state.module, settings.sourceOrder, parser.state.harmonyParserScope, settings.id, name, expr.range, this.strictExportPresence);
|
||||
dep.directImport = true;
|
||||
dep.callArgs = args;
|
||||
dep.call = fullExpr;
|
||||
dep.loc = expr.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.module.addDependency(dep);
|
||||
if(args)
|
||||
parser.walkExpressions(args);
|
||||
return true;
|
||||
});
|
||||
parser.plugin("hot accept callback", (expr, requests) => {
|
||||
const dependencies = requests
|
||||
.filter(request => HarmonyModulesHelpers.checkModuleVar(parser.state, request))
|
||||
.map(request => {
|
||||
const dep = new HarmonyAcceptImportDependency(request, HarmonyModulesHelpers.getModuleVar(parser.state, request), expr.range);
|
||||
const dep = new HarmonyAcceptImportDependency(request, parser.state.module, parser.state.harmonyParserScope);
|
||||
dep.loc = expr.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.module.addDependency(dep);
|
||||
return dep;
|
||||
});
|
||||
if(dependencies.length > 0) {
|
||||
const dep = new HarmonyAcceptDependency(expr.range, dependencies, true);
|
||||
dep.loc = expr.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.module.addDependency(dep);
|
||||
}
|
||||
});
|
||||
parser.plugin("hot accept without callback", (expr, requests) => {
|
||||
const dependencies = requests
|
||||
.filter(request => HarmonyModulesHelpers.checkModuleVar(parser.state, request))
|
||||
.map(request => {
|
||||
const dep = new HarmonyAcceptImportDependency(request, HarmonyModulesHelpers.getModuleVar(parser.state, request), expr.range);
|
||||
const dep = new HarmonyAcceptImportDependency(request, parser.state.module, parser.state.harmonyParserScope);
|
||||
dep.loc = expr.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.module.addDependency(dep);
|
||||
return dep;
|
||||
});
|
||||
if(dependencies.length > 0) {
|
||||
const dep = new HarmonyAcceptDependency(expr.range, dependencies, false);
|
||||
dep.loc = expr.loc;
|
||||
parser.state.current.addDependency(dep);
|
||||
parser.state.module.addDependency(dep);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
const HarmonyImportDependency = require("./HarmonyImportDependency");
|
||||
|
||||
class HarmonyImportSideEffectDependency extends HarmonyImportDependency {
|
||||
constructor(request, originModule, sourceOrder, parserScope) {
|
||||
super(request, originModule, sourceOrder, parserScope);
|
||||
}
|
||||
|
||||
getReference() {
|
||||
if(this.module && this.module.sideEffectFree) return null;
|
||||
|
||||
return super.getReference();
|
||||
}
|
||||
|
||||
get type() {
|
||||
return "harmony side effect evaluation";
|
||||
}
|
||||
}
|
||||
|
||||
HarmonyImportSideEffectDependency.Template = class HarmonyImportSideEffectDependencyTemplate extends HarmonyImportDependency.Template {
|
||||
getHarmonyInitOrder(dep) {
|
||||
if(dep.module && dep.module.sideEffectFree) return NaN;
|
||||
return super.getHarmonyInitOrder(dep);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = HarmonyImportSideEffectDependency;
|
|
@ -3,13 +3,11 @@
|
|||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
const NullDependency = require("./NullDependency");
|
||||
const HarmonyImportDependency = require("./HarmonyImportDependency");
|
||||
|
||||
class HarmonyImportSpecifierDependency extends NullDependency {
|
||||
constructor(importDependency, importedVar, id, name, range, strictExportPresence) {
|
||||
super();
|
||||
this.importDependency = importDependency;
|
||||
this.importedVar = importedVar;
|
||||
class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
|
||||
constructor(request, originModule, sourceOrder, parserScope, id, name, range, strictExportPresence) {
|
||||
super(request, originModule, sourceOrder, parserScope);
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.range = range;
|
||||
|
@ -25,9 +23,9 @@ class HarmonyImportSpecifierDependency extends NullDependency {
|
|||
}
|
||||
|
||||
getReference() {
|
||||
if(!this.importDependency.module) return null;
|
||||
if(!this.module) return null;
|
||||
return {
|
||||
module: this.importDependency.module,
|
||||
module: this.module,
|
||||
importedNames: this.id && !this.namespaceObjectAsContext ? [this.id] : true
|
||||
};
|
||||
}
|
||||
|
@ -47,7 +45,7 @@ class HarmonyImportSpecifierDependency extends NullDependency {
|
|||
}
|
||||
|
||||
_getErrors() {
|
||||
const importedModule = this.importDependency.module;
|
||||
const importedModule = this.module;
|
||||
if(!importedModule || !importedModule.meta || !importedModule.meta.harmonyModule) {
|
||||
return;
|
||||
}
|
||||
|
@ -61,38 +59,42 @@ class HarmonyImportSpecifierDependency extends NullDependency {
|
|||
}
|
||||
|
||||
const idIsNotNameMessage = this.id !== this.name ? ` (imported as '${this.name}')` : "";
|
||||
const errorMessage = `"export '${this.id}'${idIsNotNameMessage} was not found in '${this.importDependency.userRequest}'`;
|
||||
const errorMessage = `"export '${this.id}'${idIsNotNameMessage} was not found in '${this.userRequest}'`;
|
||||
const err = new Error(errorMessage);
|
||||
err.hideStack = true;
|
||||
return [err];
|
||||
}
|
||||
|
||||
// implement this method to allow the occurence order plugin to count correctly
|
||||
getNumberOfIdOccurrences() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
updateHash(hash) {
|
||||
super.updateHash(hash);
|
||||
const importedModule = this.importDependency.module;
|
||||
hash.update((importedModule && importedModule.id) + "");
|
||||
const importedModule = this.module;
|
||||
hash.update((importedModule && this.id) + "");
|
||||
hash.update((importedModule && this.importedVar) + "");
|
||||
hash.update((importedModule && this.id && importedModule.isUsed(this.id)) + "");
|
||||
hash.update((importedModule && (!importedModule.meta || importedModule.meta.harmonyModule)) + "");
|
||||
hash.update((importedModule && (importedModule.used + JSON.stringify(importedModule.usedExports))) + "");
|
||||
}
|
||||
}
|
||||
|
||||
HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependencyTemplate {
|
||||
apply(dep, source) {
|
||||
const content = this.getContent(dep);
|
||||
HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependencyTemplate extends HarmonyImportDependency.Template {
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
super.apply(dep, source, outputOptions, requestShortener);
|
||||
const importedVar = dep.getImportVar(requestShortener);
|
||||
const content = this.getContent(dep, importedVar);
|
||||
source.replace(dep.range[0], dep.range[1] - 1, content);
|
||||
}
|
||||
|
||||
getContent(dep) {
|
||||
const importedModule = dep.importDependency.module;
|
||||
const defaultImport = dep.directImport && dep.id === "default" && !(importedModule && (!importedModule.meta || importedModule.meta.harmonyModule));
|
||||
const shortHandPrefix = this.getShortHandPrefix(dep);
|
||||
const importedVar = dep.importedVar;
|
||||
const importedVarSuffix = this.getImportVarSuffix(dep, defaultImport, importedModule);
|
||||
getContent(dep, importedVar) {
|
||||
const importedModule = dep.module;
|
||||
const nonHarmonyDefaultImport = dep.directImport && dep.id === "default" && !(importedModule && (!importedModule.meta || importedModule.meta.harmonyModule));
|
||||
const shortHandPrefix = dep.shorthand ? `${dep.name}: ` : "";
|
||||
const importedVarSuffix = this.getImportVarSuffix(dep.id, nonHarmonyDefaultImport, importedModule);
|
||||
|
||||
if(dep.call && defaultImport) {
|
||||
if(dep.call && nonHarmonyDefaultImport) {
|
||||
return `${shortHandPrefix}${importedVar}_default()`;
|
||||
}
|
||||
|
||||
|
@ -103,27 +105,19 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
|
|||
return `${shortHandPrefix}${importedVar}${importedVarSuffix}`;
|
||||
}
|
||||
|
||||
getImportVarSuffix(dep, defaultImport, importedModule) {
|
||||
if(defaultImport) {
|
||||
getImportVarSuffix(id, nonHarmonyDefaultImport, importedModule) {
|
||||
if(nonHarmonyDefaultImport) {
|
||||
return "_default.a";
|
||||
}
|
||||
|
||||
if(dep.id) {
|
||||
const used = importedModule ? importedModule.isUsed(dep.id) : dep.id;
|
||||
const optionalComment = dep.id !== used ? " /* " + dep.id + " */" : "";
|
||||
if(id) {
|
||||
const used = importedModule ? importedModule.isUsed(id) : id;
|
||||
const optionalComment = id !== used ? " /* " + id + " */" : "";
|
||||
return `[${JSON.stringify(used)}${optionalComment}]`;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
getShortHandPrefix(dep) {
|
||||
if(!dep.shorthand) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return dep.name + ": ";
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = HarmonyImportSpecifierDependency;
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const NullDependency = require("./NullDependency");
|
||||
|
||||
class HarmonyInitDependency extends NullDependency {
|
||||
constructor(originModule) {
|
||||
super();
|
||||
this.originModule = originModule;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return "harmony init";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HarmonyInitDependency;
|
||||
|
||||
HarmonyInitDependency.Template = class HarmonyInitDependencyTemplate {
|
||||
apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
const module = dep.originModule;
|
||||
const list = [];
|
||||
for(const dependency of module.dependencies) {
|
||||
const template = dependencyTemplates.get(dependency.constructor);
|
||||
if(template && typeof template.harmonyInit === "function" && typeof template.getHarmonyInitOrder === "function") {
|
||||
const order = template.getHarmonyInitOrder(dependency);
|
||||
if(!isNaN(order)) {
|
||||
list.push({
|
||||
order,
|
||||
listOrder: list.length,
|
||||
dependency,
|
||||
template,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list.sort((a, b) => {
|
||||
const x = a.order - b.order;
|
||||
if(x) return x;
|
||||
return a.listOrder - b.listOrder;
|
||||
});
|
||||
|
||||
for(const item of list) {
|
||||
item.template.harmonyInit(item.dependency, source, outputOptions, requestShortener, dependencyTemplates);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
class HarmonyModulesHelpers {
|
||||
|
||||
static getModuleVar(state, request) {
|
||||
if(!state.harmonyModules) state.harmonyModules = [];
|
||||
let idx = state.harmonyModules.indexOf(request);
|
||||
if(idx < 0) {
|
||||
idx = state.harmonyModules.length;
|
||||
state.harmonyModules.push(request);
|
||||
}
|
||||
return `__WEBPACK_IMPORTED_MODULE_${idx}_${request.replace(/[^A-Za-z0-9_]/g, "_").replace(/__+/g, "_")}__`;
|
||||
}
|
||||
|
||||
static getNewModuleVar(state, request) {
|
||||
if(state.harmonyModules && state.harmonyModules.indexOf(request) >= 0)
|
||||
return null;
|
||||
return this.getModuleVar(state, request);
|
||||
}
|
||||
|
||||
static checkModuleVar(state, request) {
|
||||
if(!state.harmonyModules || state.harmonyModules.indexOf(request) < 0)
|
||||
return null;
|
||||
return this.getModuleVar(state, request);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HarmonyModulesHelpers;
|
|
@ -3,9 +3,10 @@
|
|||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
const HarmonyImportDependency = require("./HarmonyImportDependency");
|
||||
const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
|
||||
const HarmonyInitDependency = require("./HarmonyInitDependency");
|
||||
const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
|
||||
const HarmonyCompatiblilityDependency = require("./HarmonyCompatibilityDependency");
|
||||
const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
|
||||
const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
|
||||
const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency");
|
||||
const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
|
||||
|
@ -28,15 +29,18 @@ class HarmonyModulesPlugin {
|
|||
compiler.plugin("compilation", (compilation, params) => {
|
||||
const normalModuleFactory = params.normalModuleFactory;
|
||||
|
||||
compilation.dependencyFactories.set(HarmonyImportDependency, normalModuleFactory);
|
||||
compilation.dependencyTemplates.set(HarmonyImportDependency, new HarmonyImportDependency.Template());
|
||||
compilation.dependencyFactories.set(HarmonyCompatibilityDependency, new NullFactory());
|
||||
compilation.dependencyTemplates.set(HarmonyCompatibilityDependency, new HarmonyCompatibilityDependency.Template());
|
||||
|
||||
compilation.dependencyFactories.set(HarmonyImportSpecifierDependency, new NullFactory());
|
||||
compilation.dependencyFactories.set(HarmonyInitDependency, new NullFactory());
|
||||
compilation.dependencyTemplates.set(HarmonyInitDependency, new HarmonyInitDependency.Template());
|
||||
|
||||
compilation.dependencyFactories.set(HarmonyImportSideEffectDependency, normalModuleFactory);
|
||||
compilation.dependencyTemplates.set(HarmonyImportSideEffectDependency, new HarmonyImportSideEffectDependency.Template());
|
||||
|
||||
compilation.dependencyFactories.set(HarmonyImportSpecifierDependency, normalModuleFactory);
|
||||
compilation.dependencyTemplates.set(HarmonyImportSpecifierDependency, new HarmonyImportSpecifierDependency.Template());
|
||||
|
||||
compilation.dependencyFactories.set(HarmonyCompatiblilityDependency, new NullFactory());
|
||||
compilation.dependencyTemplates.set(HarmonyCompatiblilityDependency, new HarmonyCompatiblilityDependency.Template());
|
||||
|
||||
compilation.dependencyFactories.set(HarmonyExportHeaderDependency, new NullFactory());
|
||||
compilation.dependencyTemplates.set(HarmonyExportHeaderDependency, new HarmonyExportHeaderDependency.Template());
|
||||
|
||||
|
@ -46,7 +50,7 @@ class HarmonyModulesPlugin {
|
|||
compilation.dependencyFactories.set(HarmonyExportSpecifierDependency, new NullFactory());
|
||||
compilation.dependencyTemplates.set(HarmonyExportSpecifierDependency, new HarmonyExportSpecifierDependency.Template());
|
||||
|
||||
compilation.dependencyFactories.set(HarmonyExportImportedSpecifierDependency, new NullFactory());
|
||||
compilation.dependencyFactories.set(HarmonyExportImportedSpecifierDependency, normalModuleFactory);
|
||||
compilation.dependencyTemplates.set(HarmonyExportImportedSpecifierDependency, new HarmonyExportImportedSpecifierDependency.Template());
|
||||
|
||||
compilation.dependencyFactories.set(HarmonyAcceptDependency, new NullFactory());
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
"use strict";
|
||||
const ModuleDependency = require("./ModuleDependency");
|
||||
const Template = require("../Template");
|
||||
const DepBlockHelpers = require("./DepBlockHelpers");
|
||||
const webpackMissingPromiseModule = require("./WebpackMissingModule").promise;
|
||||
|
||||
|
@ -22,20 +23,12 @@ ImportDependency.Template = class ImportDependencyTemplate {
|
|||
apply(dep, source, outputOptions, requestShortener) {
|
||||
const depBlock = dep.block;
|
||||
const promise = DepBlockHelpers.getDepBlockPromise(depBlock, outputOptions, requestShortener, "import()");
|
||||
const comment = this.getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request));
|
||||
const comment = outputOptions.pathinfo ? Template.toComment(requestShortener.shorten(dep.request)) : "";
|
||||
|
||||
const content = this.getContent(promise, dep, comment);
|
||||
source.replace(depBlock.range[0], depBlock.range[1] - 1, content);
|
||||
}
|
||||
|
||||
getOptionalComment(pathinfo, shortenedRequest) {
|
||||
if(!pathinfo) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return `/*! ${shortenedRequest} */ `;
|
||||
}
|
||||
|
||||
getContent(promise, dep, comment) {
|
||||
if(promise && dep.module) {
|
||||
const stringifiedId = JSON.stringify(dep.module.id);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
"use strict";
|
||||
const ModuleDependency = require("./ModuleDependency");
|
||||
const Template = require("../Template");
|
||||
const webpackMissingPromiseModule = require("./WebpackMissingModule").promise;
|
||||
|
||||
class ImportEagerDependency extends ModuleDependency {
|
||||
|
@ -19,20 +20,12 @@ class ImportEagerDependency extends ModuleDependency {
|
|||
|
||||
ImportEagerDependency.Template = class ImportEagerDependencyTemplate {
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
const comment = this.getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request));
|
||||
const comment = outputOptions.pathinfo ? Template.toComment(requestShortener.shorten(dep.request)) : "";
|
||||
|
||||
const content = this.getContent(dep, comment);
|
||||
source.replace(dep.range[0], dep.range[1] - 1, content);
|
||||
}
|
||||
|
||||
getOptionalComment(pathinfo, shortenedRequest) {
|
||||
if(!pathinfo) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return `/*! ${shortenedRequest} */ `;
|
||||
}
|
||||
|
||||
getContent(dep, comment) {
|
||||
if(dep.module) {
|
||||
const stringifiedId = JSON.stringify(dep.module.id);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
"use strict";
|
||||
const ModuleDependency = require("./ModuleDependency");
|
||||
const Template = require("../Template");
|
||||
const webpackMissingPromiseModule = require("./WebpackMissingModule").promise;
|
||||
|
||||
class ImportWeakDependency extends ModuleDependency {
|
||||
|
@ -20,20 +21,12 @@ class ImportWeakDependency extends ModuleDependency {
|
|||
|
||||
ImportWeakDependency.Template = class ImportDependencyTemplate {
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
const comment = this.getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request));
|
||||
const comment = outputOptions.pathinfo ? Template.toComment(requestShortener.shorten(dep.request)) : "";
|
||||
|
||||
const content = this.getContent(dep, comment);
|
||||
source.replace(dep.range[0], dep.range[1] - 1, content);
|
||||
}
|
||||
|
||||
getOptionalComment(pathinfo, shortenedRequest) {
|
||||
if(!pathinfo) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return `/*! ${shortenedRequest} */ `;
|
||||
}
|
||||
|
||||
getContent(dep, comment) {
|
||||
if(dep.module) {
|
||||
const stringifiedId = JSON.stringify(dep.module.id);
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const Template = require("../Template");
|
||||
|
||||
class ModuleDependencyTemplateAsId {
|
||||
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
if(!dep.range) return;
|
||||
const comment = outputOptions.pathinfo ?
|
||||
`/*! ${requestShortener.shorten(dep.request)} */ ` : "";
|
||||
Template.toComment(requestShortener.shorten(dep.request)) + " " : "";
|
||||
let content;
|
||||
if(dep.module)
|
||||
content = comment + JSON.stringify(dep.module.id);
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const Template = require("../Template");
|
||||
|
||||
class ModuleDependencyTemplateAsRequireId {
|
||||
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
if(!dep.range) return;
|
||||
const comment = outputOptions.pathinfo ?
|
||||
`/*! ${requestShortener.shorten(dep.request)} */ ` : "";
|
||||
Template.toComment(requestShortener.shorten(dep.request)) + " " : "";
|
||||
let content;
|
||||
if(dep.module)
|
||||
content = `__webpack_require__(${comment}${JSON.stringify(dep.module.id)})`;
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const ModuleDependency = require("./ModuleDependency");
|
||||
const Template = require("../Template");
|
||||
|
||||
class RequireIncludeDependency extends ModuleDependency {
|
||||
constructor(request, range) {
|
||||
|
@ -18,16 +20,9 @@ class RequireIncludeDependency extends ModuleDependency {
|
|||
|
||||
RequireIncludeDependency.Template = class RequireIncludeDependencyTemplate {
|
||||
apply(dep, source, outputOptions, requestShortener) {
|
||||
const comment = this.getOptionalComment(outputOptions.pathinfo && dep.module, requestShortener.shorten(dep.request));
|
||||
const comment = outputOptions.pathinfo ? Template.toComment(`require.include ${requestShortener.shorten(dep.request)}`) : "";
|
||||
source.replace(dep.range[0], dep.range[1] - 1, `undefined${comment}`);
|
||||
}
|
||||
|
||||
getOptionalComment(shouldHaveComment, shortenedRequest) {
|
||||
if(shouldHaveComment) {
|
||||
return "";
|
||||
}
|
||||
return `/*! require.include ${shortenedRequest} */`;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = RequireIncludeDependency;
|
||||
|
|
|
@ -14,7 +14,7 @@ module.exports = class NodeMainTemplatePlugin {
|
|||
apply(mainTemplate) {
|
||||
const asyncChunkLoading = this.asyncChunkLoading;
|
||||
mainTemplate.plugin("local-vars", function(source, chunk) {
|
||||
if(chunk.chunks.length > 0) {
|
||||
if(chunk.getNumberOfChunks() > 0) {
|
||||
return this.asString([
|
||||
source,
|
||||
"",
|
||||
|
@ -28,7 +28,7 @@ module.exports = class NodeMainTemplatePlugin {
|
|||
return source;
|
||||
});
|
||||
mainTemplate.plugin("require-extensions", function(source, chunk) {
|
||||
if(chunk.chunks.length > 0) {
|
||||
if(chunk.getNumberOfChunks() > 0) {
|
||||
return this.asString([
|
||||
source,
|
||||
"",
|
||||
|
|
|
@ -17,7 +17,7 @@ class AggressiveMergingPlugin {
|
|||
const minSizeReduce = options.minSizeReduce || 1.5;
|
||||
|
||||
function getParentsWeight(chunk) {
|
||||
return chunk.parents.map((p) => {
|
||||
return chunk.mapParents((p) => {
|
||||
return p.isInitial() ? options.entryChunkMultiplicator || 10 : 1;
|
||||
}).reduce((a, b) => {
|
||||
return a + b;
|
||||
|
@ -77,30 +77,30 @@ class AggressiveMergingPlugin {
|
|||
if(pair.improvement < minSizeReduce) return;
|
||||
|
||||
if(options.moveToParents) {
|
||||
const commonModules = pair.b.modules.filter((m) => {
|
||||
return pair.a.modules.indexOf(m) >= 0;
|
||||
const commonModules = new Set(pair.b.getModules().filter((m) => {
|
||||
return pair.a.containsModule(m);
|
||||
}));
|
||||
const aOnlyModules = pair.b.getModules().filter((m) => {
|
||||
return !commonModules.has(m);
|
||||
});
|
||||
const aOnlyModules = pair.b.modules.filter((m) => {
|
||||
return commonModules.indexOf(m) < 0;
|
||||
});
|
||||
const bOnlyModules = pair.a.modules.filter((m) => {
|
||||
return commonModules.indexOf(m) < 0;
|
||||
const bOnlyModules = pair.a.getModules().filter((m) => {
|
||||
return !commonModules.has(m);
|
||||
});
|
||||
aOnlyModules.forEach((m) => {
|
||||
pair.b.removeModule(m);
|
||||
m.removeChunk(pair.b);
|
||||
pair.b.parents.forEach((c) => {
|
||||
for(const c of pair.b.parentsIterable) {
|
||||
c.addModule(m);
|
||||
m.addChunk(c);
|
||||
});
|
||||
}
|
||||
});
|
||||
bOnlyModules.forEach((m) => {
|
||||
pair.a.removeModule(m);
|
||||
m.removeChunk(pair.a);
|
||||
pair.a.parents.forEach((c) => {
|
||||
for(const c of pair.a.parentsIterable) {
|
||||
c.addModule(m);
|
||||
m.addChunk(c);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if(pair.b.integrate(pair.a, "aggressive-merge")) {
|
||||
|
|
|
@ -153,6 +153,8 @@ class AggressiveSplittingPlugin {
|
|||
// 3. save to made splittings to records
|
||||
const minSize = this.options.minSize;
|
||||
if(!records.aggressiveSplits) records.aggressiveSplits = [];
|
||||
const newSplits = [];
|
||||
let splittingInvalid = false;
|
||||
compilation.chunks.forEach((chunk) => {
|
||||
if(chunk.hasEntryModule()) return;
|
||||
const size = chunk.size(this.options);
|
||||
|
@ -160,8 +162,9 @@ class AggressiveSplittingPlugin {
|
|||
const modules = chunk.mapModules(m => identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache));
|
||||
if(typeof chunk._fromAggressiveSplittingIndex === "undefined") {
|
||||
if(incorrectSize) return;
|
||||
// this is a new chunk splitting, we record it so we reuse it next time
|
||||
chunk.recorded = true;
|
||||
records.aggressiveSplits.push({
|
||||
newSplits.push({
|
||||
modules: modules,
|
||||
hash: chunk.hash,
|
||||
id: chunk.id
|
||||
|
@ -172,15 +175,20 @@ class AggressiveSplittingPlugin {
|
|||
if(chunk._fromAggressiveSplitting) {
|
||||
chunk._aggressiveSplittingInvalid = true;
|
||||
splitData.invalid = true;
|
||||
splittingInvalid = true;
|
||||
} else {
|
||||
splitData.hash = chunk.hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if(splittingInvalid) {
|
||||
records.aggressiveSplits = records.aggressiveSplits.filter((splitData) => {
|
||||
return !splitData.invalid;
|
||||
});
|
||||
} else {
|
||||
records.aggressiveSplits = records.aggressiveSplits.concat(newSplits);
|
||||
}
|
||||
});
|
||||
compilation.plugin("need-additional-seal", (callback) => {
|
||||
const invalid = compilation.chunks.some((chunk) => {
|
||||
|
|
|
@ -215,17 +215,16 @@ Take a look at the "name"/"names" or async/children option.`);
|
|||
}
|
||||
|
||||
getAffectedUnnamedChunks(affectedChunks, targetChunk, rootChunk, asyncOption, deepChildrenOption) {
|
||||
let chunks = targetChunk.chunks;
|
||||
chunks && chunks.forEach((chunk) => {
|
||||
for(const chunk of targetChunk.chunksIterable) {
|
||||
if(chunk.isInitial()) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
// If all the parents of a chunk are either
|
||||
// a) the target chunk we started with
|
||||
// b) themselves affected chunks
|
||||
// we can assume that this chunk is an affected chunk too, as there is no way a chunk that
|
||||
// isn't only depending on the target chunk is a parent of the chunk tested
|
||||
if(asyncOption || chunk.parents.every((parentChunk) => parentChunk === rootChunk || affectedChunks.has(parentChunk))) {
|
||||
if(asyncOption || chunk.getParents().every((parentChunk) => parentChunk === rootChunk || affectedChunks.has(parentChunk))) {
|
||||
// This check not only dedupes the affectedChunks but also guarantees we avoid endless loops
|
||||
if(!affectedChunks.has(chunk)) {
|
||||
// We mutate the affected chunks before going deeper, so the deeper levels and other branches
|
||||
|
@ -242,7 +241,7 @@ Take a look at the "name"/"names" or async/children option.`);
|
|||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getAffectedChunks(compilation, allChunks, targetChunk, targetChunks, currentIndex, selectedChunks, asyncOption, childrenOption, deepChildrenOption) {
|
||||
|
@ -265,7 +264,7 @@ Take a look at the "name"/"names" or async/children option.`);
|
|||
/**
|
||||
* past this point only entry chunks are allowed to become commonChunks
|
||||
*/
|
||||
if(targetChunk.parents.length > 0) {
|
||||
if(targetChunk.getNumberOfParents() > 0) {
|
||||
compilation.errors.push(new Error("CommonsChunkPlugin: While running in normal mode it's not allowed to use a non-entry chunk (" + targetChunk.name + ")"));
|
||||
return;
|
||||
}
|
||||
|
@ -283,7 +282,7 @@ Take a look at the "name"/"names" or async/children option.`);
|
|||
return allChunks.filter((chunk) => {
|
||||
const found = targetChunks.indexOf(chunk);
|
||||
if(found >= currentIndex) return false;
|
||||
return chunk.hasRuntime();
|
||||
return chunk.isInitial();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -366,11 +365,11 @@ Take a look at the "name"/"names" or async/children option.`);
|
|||
makeTargetChunkParentOfAffectedChunks(usedChunks, commonChunk) {
|
||||
for(const chunk of usedChunks) {
|
||||
// set commonChunk as new sole parent
|
||||
chunk.parents = [commonChunk];
|
||||
chunk.setParents([commonChunk]);
|
||||
// add chunk to commonChunk
|
||||
commonChunk.addChunk(chunk);
|
||||
|
||||
for(const entrypoint of chunk.entrypoints) {
|
||||
for(const entrypoint of chunk.entrypoints.slice()) {
|
||||
entrypoint.insertChunk(commonChunk, chunk);
|
||||
}
|
||||
}
|
||||
|
@ -379,7 +378,7 @@ Take a look at the "name"/"names" or async/children option.`);
|
|||
moveExtractedChunkBlocksToTargetChunk(chunks, targetChunk) {
|
||||
for(const chunk of chunks) {
|
||||
if(chunk === targetChunk) continue;
|
||||
for(const block of chunk.blocks) {
|
||||
for(const block of chunk.blocksIterable) {
|
||||
if(block.chunks.indexOf(targetChunk) === -1) {
|
||||
block.chunks.unshift(targetChunk);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ const escope = require("escope");
|
|||
const ReplaceSource = require("webpack-sources/lib/ReplaceSource");
|
||||
const ConcatSource = require("webpack-sources/lib/ConcatSource");
|
||||
const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
|
||||
const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency");
|
||||
const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
|
||||
const HarmonyExportSpecifierDependency = require("../dependencies/HarmonyExportSpecifierDependency");
|
||||
const HarmonyExportExpressionDependency = require("../dependencies/HarmonyExportExpressionDependency");
|
||||
|
@ -38,8 +39,7 @@ function getExternalImport(importedModule, info, exportName, asCall) {
|
|||
if(info.interop && exportName === "default") {
|
||||
return asCall ? `${info.interopName}()` : `${info.interopName}.a`;
|
||||
}
|
||||
// TODO use Template.toNormalComment when merging with pure-module
|
||||
const comment = used !== exportName ? ` /* ${exportName} */` : "";
|
||||
const comment = used !== exportName ? ` ${Template.toNormalComment(exportName)}` : "";
|
||||
const reference = `${info.name}[${JSON.stringify(used)}${comment}]`;
|
||||
if(asCall)
|
||||
return `Object(${reference})`;
|
||||
|
@ -70,8 +70,7 @@ function getFinalName(info, exportName, moduleToInfoMap, requestShortener, asCal
|
|||
const problem = `Cannot get final name for export "${exportName}" in "${info.module.readableIdentifier(requestShortener)}"` +
|
||||
` (known exports: ${Array.from(info.exportMap.keys()).filter(name => name !== true).join(" ")}, ` +
|
||||
`known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`;
|
||||
// TODO use Template.toNormalComment when merging with pure-module
|
||||
return `/* ${problem} */ undefined`;
|
||||
return `${Template.toNormalComment(problem)} undefined`;
|
||||
}
|
||||
case "external":
|
||||
{
|
||||
|
@ -261,15 +260,18 @@ class ConcatenatedModule extends Module {
|
|||
const set = new Set();
|
||||
|
||||
function getConcatenatedImports(module) {
|
||||
// TODO need changes when merging with the pure-module branch
|
||||
const allDeps = module.dependencies
|
||||
.filter(dep => dep instanceof HarmonyImportDependency && dep.module);
|
||||
|
||||
return allDeps.map(dep => () => dep.module);
|
||||
return module.dependencies
|
||||
.filter(dep => dep instanceof HarmonyImportDependency)
|
||||
.sort((a, b) => a.sourceOrder - b.sourceOrder)
|
||||
.map(dep => () => {
|
||||
const ref = dep.getReference();
|
||||
return ref && ref.module;
|
||||
});
|
||||
}
|
||||
|
||||
function enterModule(getModule) {
|
||||
const module = getModule();
|
||||
if(!module) return;
|
||||
if(set.has(module)) return;
|
||||
set.add(module);
|
||||
if(modulesSet.has(module)) {
|
||||
|
@ -315,7 +317,7 @@ class ConcatenatedModule extends Module {
|
|||
} else if(dep instanceof HarmonyExportImportedSpecifierDependency) {
|
||||
const exportName = dep.name;
|
||||
const importName = dep.id;
|
||||
const importedModule = dep.importDependency.module;
|
||||
const importedModule = dep.module;
|
||||
if(exportName && importName) {
|
||||
if(!reexportMap.has(exportName)) {
|
||||
reexportMap.set(exportName, {
|
||||
|
@ -352,6 +354,7 @@ class ConcatenatedModule extends Module {
|
|||
module: info.module,
|
||||
index: idx,
|
||||
ast: undefined,
|
||||
internalSource: undefined,
|
||||
source: undefined,
|
||||
globalScope: undefined,
|
||||
moduleScope: undefined,
|
||||
|
@ -387,8 +390,8 @@ class ConcatenatedModule extends Module {
|
|||
dependencyTemplates.get(HarmonyImportSpecifierDependency),
|
||||
moduleToInfoMap
|
||||
));
|
||||
innerDependencyTemplates.set(HarmonyImportDependency, new HarmonyImportDependencyConcatenatedTemplate(
|
||||
dependencyTemplates.get(HarmonyImportDependency),
|
||||
innerDependencyTemplates.set(HarmonyImportSideEffectDependency, new HarmonyImportSideEffectDependencyConcatenatedTemplate(
|
||||
dependencyTemplates.get(HarmonyImportSideEffectDependency),
|
||||
moduleToInfoMap
|
||||
));
|
||||
innerDependencyTemplates.set(HarmonyExportSpecifierDependency, new HarmonyExportSpecifierDependencyConcatenatedTemplate(
|
||||
|
@ -446,6 +449,7 @@ class ConcatenatedModule extends Module {
|
|||
const moduleScope = globalScope.childScopes[0];
|
||||
const resultSource = new ReplaceSource(source);
|
||||
info.ast = ast;
|
||||
info.internalSource = source;
|
||||
info.source = resultSource;
|
||||
info.globalScope = globalScope;
|
||||
info.moduleScope = moduleScope;
|
||||
|
@ -662,8 +666,26 @@ class HarmonyImportSpecifierDependencyConcatenatedTemplate {
|
|||
this.modulesMap = modulesMap;
|
||||
}
|
||||
|
||||
getHarmonyInitOrder(dep) {
|
||||
const module = dep.module;
|
||||
const info = this.modulesMap.get(module);
|
||||
if(!info) {
|
||||
return this.originalTemplate.getHarmonyInitOrder(dep);
|
||||
}
|
||||
return NaN;
|
||||
}
|
||||
|
||||
harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
const module = dep.module;
|
||||
const info = this.modulesMap.get(module);
|
||||
if(!info) {
|
||||
this.originalTemplate.harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
const module = dep.importDependency.module;
|
||||
const module = dep.module;
|
||||
const info = this.modulesMap.get(module);
|
||||
if(!info) {
|
||||
this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
|
||||
|
@ -685,12 +707,30 @@ class HarmonyImportSpecifierDependencyConcatenatedTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
class HarmonyImportDependencyConcatenatedTemplate {
|
||||
class HarmonyImportSideEffectDependencyConcatenatedTemplate {
|
||||
constructor(originalTemplate, modulesMap) {
|
||||
this.originalTemplate = originalTemplate;
|
||||
this.modulesMap = modulesMap;
|
||||
}
|
||||
|
||||
getHarmonyInitOrder(dep) {
|
||||
const module = dep.module;
|
||||
const info = this.modulesMap.get(module);
|
||||
if(!info) {
|
||||
return this.originalTemplate.getHarmonyInitOrder(dep);
|
||||
}
|
||||
return NaN;
|
||||
}
|
||||
|
||||
harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
const module = dep.module;
|
||||
const info = this.modulesMap.get(module);
|
||||
if(!info) {
|
||||
this.originalTemplate.harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
const module = dep.module;
|
||||
const info = this.modulesMap.get(module);
|
||||
|
@ -698,7 +738,6 @@ class HarmonyImportDependencyConcatenatedTemplate {
|
|||
this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
|
||||
return;
|
||||
}
|
||||
source.replace(dep.range[0], dep.range[1] - 1, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -708,6 +747,20 @@ class HarmonyExportSpecifierDependencyConcatenatedTemplate {
|
|||
this.rootModule = rootModule;
|
||||
}
|
||||
|
||||
getHarmonyInitOrder(dep) {
|
||||
if(dep.originModule === this.rootModule) {
|
||||
return this.originalTemplate.getHarmonyInitOrder(dep);
|
||||
}
|
||||
return NaN;
|
||||
}
|
||||
|
||||
harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
if(dep.originModule === this.rootModule) {
|
||||
this.originalTemplate.harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
if(dep.originModule === this.rootModule) {
|
||||
this.originalTemplate.apply(dep, source, outputOptions, requestShortener, dependencyTemplates);
|
||||
|
@ -747,7 +800,7 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate {
|
|||
}
|
||||
|
||||
getExports(dep) {
|
||||
const importModule = dep.importDependency.module;
|
||||
const importModule = dep.module;
|
||||
if(dep.id) {
|
||||
// export { named } from "module"
|
||||
return [{
|
||||
|
@ -774,9 +827,27 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate {
|
|||
});
|
||||
}
|
||||
|
||||
getHarmonyInitOrder(dep) {
|
||||
const module = dep.module;
|
||||
const info = this.modulesMap.get(module);
|
||||
if(!info) {
|
||||
return this.originalTemplate.getHarmonyInitOrder(dep);
|
||||
}
|
||||
return NaN;
|
||||
}
|
||||
|
||||
harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
const module = dep.module;
|
||||
const info = this.modulesMap.get(module);
|
||||
if(!info) {
|
||||
this.originalTemplate.harmonyInit(dep, source, outputOptions, requestShortener, dependencyTemplates);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
apply(dep, source, outputOptions, requestShortener, dependencyTemplates) {
|
||||
if(dep.originModule === this.rootModule) {
|
||||
if(this.modulesMap.get(dep.importDependency.module)) {
|
||||
if(this.modulesMap.get(dep.module)) {
|
||||
const exportDefs = this.getExports(dep);
|
||||
exportDefs.forEach(def => {
|
||||
const info = this.modulesMap.get(def.module);
|
||||
|
|
|
@ -19,13 +19,13 @@ class EnsureChunkConditionsPlugin {
|
|||
if(!usedChunks) triesMap.set(module, usedChunks = new Set());
|
||||
usedChunks.add(chunk);
|
||||
const newChunks = [];
|
||||
chunk.parents.forEach((parent) => {
|
||||
for(const parent of chunk.parentsIterable) {
|
||||
if(!usedChunks.has(parent)) {
|
||||
parent.addModule(module);
|
||||
module.addChunk(parent);
|
||||
newChunks.push(parent);
|
||||
}
|
||||
});
|
||||
}
|
||||
module.rewriteChunkInReasons(chunk, newChunks);
|
||||
chunk.removeModule(module);
|
||||
changed = true;
|
||||
|
|
|
@ -11,7 +11,7 @@ class MergeDuplicateChunksPlugin {
|
|||
compilation.plugin("optimize-chunks-basic", (chunks) => {
|
||||
const map = Object.create(null);
|
||||
chunks.slice().forEach((chunk) => {
|
||||
if(chunk.hasRuntime() || chunk.hasEntryModule()) return;
|
||||
if(chunk.hasEntryModule()) return;
|
||||
const ident = chunk.getModulesIdent();
|
||||
const otherChunk = map[ident];
|
||||
if(otherChunk) {
|
||||
|
|
|
@ -8,7 +8,6 @@ const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency
|
|||
const ModuleHotAcceptDependency = require("../dependencies/ModuleHotAcceptDependency");
|
||||
const ModuleHotDeclineDependency = require("../dependencies/ModuleHotDeclineDependency");
|
||||
const ConcatenatedModule = require("./ConcatenatedModule");
|
||||
const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
|
||||
const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency");
|
||||
|
||||
function formatBailoutReason(msg) {
|
||||
|
@ -189,18 +188,17 @@ class ModuleConcatenationPlugin {
|
|||
// Only harmony Dependencies
|
||||
.filter(dep => dep instanceof HarmonyImportDependency && dep.module)
|
||||
|
||||
// Get reference info for this dependency
|
||||
.map(dep => dep.getReference())
|
||||
|
||||
// Reference is valid and has a module
|
||||
.filter(ref => ref && ref.module)
|
||||
|
||||
// Dependencies are simple enough to concat them
|
||||
.filter(dep => {
|
||||
return !module.dependencies.some(d =>
|
||||
d instanceof HarmonyExportImportedSpecifierDependency &&
|
||||
d.importDependency === dep &&
|
||||
!d.id &&
|
||||
!Array.isArray(dep.module.providedExports)
|
||||
);
|
||||
})
|
||||
.filter(ref => Array.isArray(ref.importedNames) || Array.isArray(ref.module.providedExports))
|
||||
|
||||
// Take the imported module
|
||||
.map(dep => dep.module)
|
||||
.map(ref => ref.module)
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -235,6 +233,10 @@ class ModuleConcatenationPlugin {
|
|||
|
||||
// Every module which depends on the added module must be in the configuration too.
|
||||
for(const reason of module.reasons) {
|
||||
|
||||
// Modules that are not used can be ignored
|
||||
if(reason.module.sideEffectFree && reason.module.used === false) continue;
|
||||
|
||||
const problem = this.tryToAdd(testConfig, reason.module, possibleModules, failureCache);
|
||||
if(problem) {
|
||||
failureCache.set(module, problem); // cache failures for performance
|
||||
|
|
|
@ -37,7 +37,11 @@ class OccurrenceOrderPlugin {
|
|||
};
|
||||
const countOccurs = (sum, r) => {
|
||||
if(!r.module) return sum;
|
||||
return sum + r.module.getNumberOfChunks();
|
||||
let factor = 1;
|
||||
if(typeof r.dependency.getNumberOfIdOccurrences === "function")
|
||||
factor = r.dependency.getNumberOfIdOccurrences();
|
||||
if(factor === 0) return sum;
|
||||
return sum + factor * r.module.getNumberOfChunks();
|
||||
};
|
||||
|
||||
if(preferEntry) {
|
||||
|
@ -72,7 +76,7 @@ class OccurrenceOrderPlugin {
|
|||
const occursInInitialChunksMap = new Map();
|
||||
|
||||
chunks.forEach(c => {
|
||||
const result = c.parents.reduce((sum, p) => {
|
||||
const result = c.getParents().reduce((sum, p) => {
|
||||
if(p.isInitial()) return sum + 1;
|
||||
return sum;
|
||||
}, 0);
|
||||
|
@ -80,7 +84,7 @@ class OccurrenceOrderPlugin {
|
|||
});
|
||||
|
||||
function occurs(c) {
|
||||
return c.blocks.length;
|
||||
return c.getNumberOfBlocks();
|
||||
}
|
||||
|
||||
chunks.sort((a, b) => {
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
function hasModule(chunk, module, checkedChunks) {
|
||||
if(chunk.containsModule(module)) return [chunk];
|
||||
if(chunk.parents.length === 0) return false;
|
||||
return allHaveModule(chunk.parents.filter((c) => {
|
||||
if(chunk.getNumberOfParents() === 0) return false;
|
||||
return allHaveModule(chunk.getParents().filter((c) => {
|
||||
return !checkedChunks.has(c);
|
||||
}), module, checkedChunks);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class RemoveParentModulesPlugin {
|
|||
compilation.plugin(["optimize-chunks-basic", "optimize-extracted-chunks-basic"], (chunks) => {
|
||||
for(var index = 0; index < chunks.length; index++) {
|
||||
var chunk = chunks[index];
|
||||
if(chunk.parents.length === 0) continue;
|
||||
if(chunk.getNumberOfParents() === 0) continue;
|
||||
|
||||
// TODO consider Map when performance has improved https://gist.github.com/sokra/b36098368da7b8f6792fd7c85fca6311
|
||||
var cache = Object.create(null);
|
||||
|
@ -46,11 +46,11 @@ class RemoveParentModulesPlugin {
|
|||
var dId = module.getChunkIdsIdent();
|
||||
var parentChunksWithModule;
|
||||
if(dId === null) {
|
||||
parentChunksWithModule = allHaveModule(chunk.parents, module);
|
||||
parentChunksWithModule = allHaveModule(chunk.getParents(), module);
|
||||
} else if(dId in cache) {
|
||||
parentChunksWithModule = cache[dId];
|
||||
} else {
|
||||
parentChunksWithModule = cache[dId] = allHaveModule(chunk.parents, module);
|
||||
parentChunksWithModule = cache[dId] = allHaveModule(chunk.getParents(), module);
|
||||
}
|
||||
if(parentChunksWithModule) {
|
||||
module.rewriteChunkInReasons(chunk, Array.from(parentChunksWithModule));
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
|
||||
const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency");
|
||||
const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
|
||||
|
||||
class SideEffectsFlagPlugin {
|
||||
|
||||
apply(compiler) {
|
||||
compiler.plugin("normal-module-factory", nmf => {
|
||||
nmf.plugin("module", (module, data) => {
|
||||
const resolveData = data.resourceResolveData;
|
||||
if(resolveData && resolveData.descriptionFileData && resolveData.relativePath) {
|
||||
const sideEffects = resolveData.descriptionFileData.sideEffects;
|
||||
const isSideEffectFree = sideEffects === false; // TODO allow more complex expressions
|
||||
if(isSideEffectFree) {
|
||||
module.sideEffectFree = true;
|
||||
}
|
||||
}
|
||||
|
||||
return module;
|
||||
});
|
||||
});
|
||||
compiler.plugin("compilation", compilation => {
|
||||
compilation.plugin("optimize-dependencies", modules => {
|
||||
const reexportMaps = new Map();
|
||||
|
||||
// Capture reexports of sideEffectFree modules
|
||||
for(const module of modules) {
|
||||
const removeDependencies = [];
|
||||
for(const dep of module.dependencies) {
|
||||
if(dep instanceof HarmonyImportSideEffectDependency) {
|
||||
if(dep.module && dep.module.sideEffectFree) {
|
||||
removeDependencies.push(dep);
|
||||
}
|
||||
} else if(dep instanceof HarmonyExportImportedSpecifierDependency) {
|
||||
if(module.sideEffectFree) {
|
||||
const mode = dep.getMode(true);
|
||||
if(mode.type === "safe-reexport") {
|
||||
let map = reexportMaps.get(module);
|
||||
if(!map) {
|
||||
reexportMaps.set(module, map = new Map());
|
||||
}
|
||||
for(const pair of mode.map) {
|
||||
map.set(pair[0], {
|
||||
module: mode.module,
|
||||
exportName: pair[1]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(const dep of removeDependencies) {
|
||||
module.removeDependency(dep);
|
||||
dep.module.reasons = dep.module.reasons.filter(r => r.dependency !== dep);
|
||||
}
|
||||
}
|
||||
|
||||
// Flatten reexports
|
||||
for(const map of reexportMaps.values()) {
|
||||
for(const pair of map) {
|
||||
let mapping = pair[1];
|
||||
while(mapping) {
|
||||
const innerMap = reexportMaps.get(mapping.module);
|
||||
if(!innerMap) break;
|
||||
const newMapping = innerMap.get(mapping.exportName);
|
||||
if(newMapping) {
|
||||
map.set(pair[0], newMapping);
|
||||
}
|
||||
mapping = newMapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update imports along the reexports from sideEffectFree modules
|
||||
const updates = [];
|
||||
for(const pair of reexportMaps) {
|
||||
const module = pair[0];
|
||||
const map = pair[1];
|
||||
for(const reason of module.reasons) {
|
||||
const dep = reason.dependency;
|
||||
if(dep instanceof HarmonyImportSpecifierDependency) {
|
||||
const mapping = map.get(dep.id);
|
||||
if(mapping) {
|
||||
updates.push({
|
||||
dep,
|
||||
mapping,
|
||||
module,
|
||||
reason
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Execute updates
|
||||
for(const update of updates) {
|
||||
const dep = update.dep;
|
||||
const mapping = update.mapping;
|
||||
const module = update.module;
|
||||
const reason = update.reason;
|
||||
dep.module = mapping.module;
|
||||
dep.id = mapping.exportName;
|
||||
module.removeReason(reason.module, dep);
|
||||
mapping.module.addReason(reason.module, dep);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
module.exports = SideEffectsFlagPlugin;
|
|
@ -6,6 +6,7 @@ module.exports = class SortableSet extends Set {
|
|||
super(initialIterable);
|
||||
this._sortFn = defaultSort;
|
||||
this._lastActiveSortFn = null;
|
||||
this._frozenArray = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,10 +15,21 @@ module.exports = class SortableSet extends Set {
|
|||
*/
|
||||
add(value) {
|
||||
this._lastActiveSortFn = null;
|
||||
this._frozenArray = null;
|
||||
super.add(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
delete(value) {
|
||||
this._frozenArray = null;
|
||||
return super.delete(value);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._frozenArray = null;
|
||||
return super.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Function} sortFn - function to sort the set
|
||||
* @returns {void}
|
||||
|
@ -31,9 +43,10 @@ module.exports = class SortableSet extends Set {
|
|||
const sortedArray = Array.from(this).sort(sortFn);
|
||||
super.clear();
|
||||
for(let i = 0; i < sortedArray.length; i += 1) {
|
||||
this.add(sortedArray[i]);
|
||||
super.add(sortedArray[i]);
|
||||
}
|
||||
this._lastActiveSortFn = sortFn;
|
||||
this._frozenArray = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,4 +55,14 @@ module.exports = class SortableSet extends Set {
|
|||
sort() {
|
||||
this.sortWith(this._sortFn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {any[]} - returns content as frozen array
|
||||
*/
|
||||
getFrozenArray() {
|
||||
if(this._frozenArray === null) {
|
||||
this._frozenArray = Object.freeze(Array.from(this));
|
||||
}
|
||||
return this._frozenArray;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const util = require("util");
|
||||
|
||||
const TOMBSTONE = {};
|
||||
const UNDEFINED_MARKER = {};
|
||||
|
||||
class StackedSetMap {
|
||||
constructor(parentStack) {
|
||||
this.stack = parentStack === undefined ? [] : parentStack.slice();
|
||||
this.map = new Map();
|
||||
this.stack.push(this.map);
|
||||
}
|
||||
|
||||
add(item) {
|
||||
this.map.set(item, true);
|
||||
}
|
||||
|
||||
set(item, value) {
|
||||
this.map.set(item, value === undefined ? UNDEFINED_MARKER : value);
|
||||
}
|
||||
|
||||
delete(item) {
|
||||
if(this.stack.length > 1)
|
||||
this.map.set(item, TOMBSTONE);
|
||||
else
|
||||
this.map.delete(item);
|
||||
}
|
||||
|
||||
has(item) {
|
||||
const topValue = this.map.get(item);
|
||||
if(topValue !== undefined)
|
||||
return topValue !== TOMBSTONE;
|
||||
if(this.stack.length > 1) {
|
||||
for(var i = this.stack.length - 2; i >= 0; i--) {
|
||||
const value = this.stack[i].get(item);
|
||||
if(value !== undefined) {
|
||||
this.map.set(item, value);
|
||||
return value !== TOMBSTONE;
|
||||
}
|
||||
}
|
||||
this.map.set(item, TOMBSTONE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
get(item) {
|
||||
const topValue = this.map.get(item);
|
||||
if(topValue !== undefined)
|
||||
return topValue === TOMBSTONE || topValue === UNDEFINED_MARKER ? undefined : topValue;
|
||||
if(this.stack.length > 1) {
|
||||
for(var i = this.stack.length - 2; i >= 0; i--) {
|
||||
const value = this.stack[i].get(item);
|
||||
if(value !== undefined) {
|
||||
this.map.set(item, value);
|
||||
return value === TOMBSTONE || value === UNDEFINED_MARKER ? undefined : value;
|
||||
}
|
||||
}
|
||||
this.map.set(item, TOMBSTONE);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
_compress() {
|
||||
this.map = new Map();
|
||||
for(const data of this.stack) {
|
||||
for(const pair of data) {
|
||||
if(pair[1] === TOMBSTONE)
|
||||
this.map.delete(pair[0]);
|
||||
else
|
||||
this.map.set(pair[0], pair[1]);
|
||||
}
|
||||
}
|
||||
this.stack = [this.map];
|
||||
}
|
||||
|
||||
asSet() {
|
||||
this._compress();
|
||||
return new Set(Array.from(this.map.entries()).map(pair => pair[0]));
|
||||
}
|
||||
|
||||
asMap() {
|
||||
this._compress();
|
||||
return new Map(this.map.entries());
|
||||
}
|
||||
|
||||
createChild() {
|
||||
return new StackedSetMap(this.stack);
|
||||
}
|
||||
|
||||
get length() {
|
||||
throw new Error("This is no longer an Array");
|
||||
}
|
||||
|
||||
set length(value) {
|
||||
throw new Error("This is no longer an Array");
|
||||
}
|
||||
}
|
||||
|
||||
StackedSetMap.prototype.push = util.deprecate(function(item) {
|
||||
this.add(item);
|
||||
}, "This is no longer an Array: Use add instead.");
|
||||
|
||||
module.exports = StackedSetMap;
|
|
@ -22,8 +22,7 @@ function webpack(options, callback) {
|
|||
if(Array.isArray(options)) {
|
||||
compiler = new MultiCompiler(options.map(options => webpack(options)));
|
||||
} else if(typeof options === "object") {
|
||||
// TODO webpack 4: process returns options
|
||||
new WebpackOptionsDefaulter().process(options);
|
||||
options = new WebpackOptionsDefaulter().process(options);
|
||||
|
||||
compiler = new Compiler();
|
||||
compiler.context = options.context;
|
||||
|
@ -115,6 +114,7 @@ exportPlugins(exports.optimize = {}, {
|
|||
"LimitChunkCountPlugin": () => require("./optimize/LimitChunkCountPlugin"),
|
||||
"MinChunkSizePlugin": () => require("./optimize/MinChunkSizePlugin"),
|
||||
"ModuleConcatenationPlugin": () => require("./optimize/ModuleConcatenationPlugin"),
|
||||
"SideEffectsFlagPlugin": () => require("./optimize/SideEffectsFlagPlugin"),
|
||||
"OccurrenceOrderPlugin": () => require("./optimize/OccurrenceOrderPlugin"),
|
||||
"UglifyJsPlugin": () => require("./optimize/UglifyJsPlugin")
|
||||
});
|
||||
|
|
|
@ -13,7 +13,6 @@ function webpack(options, callback) {
|
|||
new WebpackOptionsDefaulter().process(options);
|
||||
|
||||
const compiler = new Compiler();
|
||||
compiler.options = options;
|
||||
compiler.options = new WebpackOptionsApply().process(options, compiler);
|
||||
new WebEnvironmentPlugin(options.inputFileSystem, options.outputFileSystem).apply(compiler);
|
||||
if(callback) {
|
||||
|
|
|
@ -9,7 +9,7 @@ const Template = require("../Template");
|
|||
class WebWorkerMainTemplatePlugin {
|
||||
apply(mainTemplate) {
|
||||
mainTemplate.plugin("local-vars", function(source, chunk) {
|
||||
if(chunk.chunks.length > 0) {
|
||||
if(chunk.getNumberOfChunks() > 0) {
|
||||
return this.asString([
|
||||
source,
|
||||
"",
|
||||
|
@ -48,7 +48,7 @@ class WebWorkerMainTemplatePlugin {
|
|||
]);
|
||||
});
|
||||
mainTemplate.plugin("bootstrap", function(source, chunk, hash) {
|
||||
if(chunk.chunks.length > 0) {
|
||||
if(chunk.getNumberOfChunks() > 0) {
|
||||
const chunkCallbackName = this.outputOptions.chunkCallbackName || Template.toIdentifier("webpackChunk" + (this.outputOptions.library || ""));
|
||||
return this.asString([
|
||||
source,
|
||||
|
|
14
package.json
14
package.json
|
@ -20,7 +20,7 @@
|
|||
"node-libs-browser": "^2.0.0",
|
||||
"source-map": "^0.5.3",
|
||||
"supports-color": "^4.2.1",
|
||||
"tapable": "^0.2.7",
|
||||
"tapable": "^0.2.8",
|
||||
"uglifyjs-webpack-plugin": "^0.4.6",
|
||||
"watchpack": "^1.4.0",
|
||||
"webpack-sources": "^1.0.1",
|
||||
|
@ -88,13 +88,13 @@
|
|||
"schemas/"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "mocha test/*.test.js --max-old-space-size=4096 --harmony --check-leaks",
|
||||
"test": "mocha test/*.test.js --max-old-space-size=4096 --harmony --trace-deprecation --check-leaks",
|
||||
"travis:test": "npm run cover:min",
|
||||
"travis:lint": "npm run lint-files && npm run nsp",
|
||||
"travis:benchmark": "npm run benchmark",
|
||||
"appveyor:test": "node node_modules\\mocha\\bin\\mocha --max-old-space-size=4096 --harmony test/*.test.js",
|
||||
"appveyor:test": "node node_modules\\mocha\\bin\\mocha --max-old-space-size=4096 --harmony --trace-deprecation test/*.test.js",
|
||||
"appveyor:benchmark": "npm run benchmark",
|
||||
"circleci:test": "node node_modules/mocha/bin/mocha --max-old-space-size=4096 --harmony test/*.test.js",
|
||||
"circleci:test": "node node_modules/mocha/bin/mocha --max-old-space-size=4096 --harmony --trace-deprecation test/*.test.js",
|
||||
"circleci:lint": "npm run lint-files && npm run nsp",
|
||||
"build:examples": "cd examples && node buildAll.js",
|
||||
"pretest": "npm run lint-files",
|
||||
|
@ -103,9 +103,9 @@
|
|||
"fix": "npm run lint -- --fix",
|
||||
"beautify-lint": "beautify-lint \"lib/**/*.js\" \"hot/**/*.js\" \"bin/**/*.js\" \"benchmark/*.js\" \"test/*.js\"",
|
||||
"nsp": "nsp check --output summary",
|
||||
"benchmark": "mocha --max-old-space-size=4096 --harmony test/*.benchmark.js -R spec",
|
||||
"cover": "node --max-old-space-size=4096 --harmony ./node_modules/istanbul/lib/cli.js cover -x '**/*.runtime.js' node_modules/mocha/bin/_mocha -- test/*.test.js",
|
||||
"cover:min": "node --max-old-space-size=4096 --harmony ./node_modules/istanbul/lib/cli.js cover -x '**/*.runtime.js' --report lcovonly node_modules/mocha/bin/_mocha -- test/*.test.js",
|
||||
"benchmark": "mocha --max-old-space-size=4096 --harmony --trace-deprecation test/*.benchmark.js -R spec",
|
||||
"cover": "node --max-old-space-size=4096 --harmony --trace-deprecation ./node_modules/istanbul/lib/cli.js cover -x '**/*.runtime.js' node_modules/mocha/bin/_mocha -- test/*.test.js",
|
||||
"cover:min": "node --max-old-space-size=4096 --harmony --trace-deprecation ./node_modules/istanbul/lib/cli.js cover -x '**/*.runtime.js' --report lcovonly node_modules/mocha/bin/_mocha -- test/*.test.js",
|
||||
"publish-patch": "npm run lint && npm run beautify-lint && mocha && npm version patch && git push && git push --tags && npm publish"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,14 +138,6 @@
|
|||
"exprContextRequest": {
|
||||
"type": "string"
|
||||
},
|
||||
"loaders": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ruleSet-rules"
|
||||
}
|
||||
],
|
||||
"description": "An array of automatically applied loaders."
|
||||
},
|
||||
"noParse": {
|
||||
"description": "Don't parse files matching. It's matched against the full resolved request.",
|
||||
"anyOf": [
|
||||
|
|
|
@ -128,7 +128,7 @@ describe("Chunk", () => {
|
|||
});
|
||||
describe("and the chunk does contain this module", function() {
|
||||
beforeEach(function() {
|
||||
ChunkInstance.chunks = [chunk];
|
||||
ChunkInstance._chunks = new Set([chunk]);
|
||||
});
|
||||
it("calls module.removeChunk with itself and returns true", function() {
|
||||
ChunkInstance.removeChunk(chunk).should.eql(true);
|
||||
|
|
|
@ -12,7 +12,7 @@ describe("Compiler (caching)", function() {
|
|||
this.timeout(15000);
|
||||
|
||||
function compile(entry, options, callback) {
|
||||
new WebpackOptionsDefaulter().process(options);
|
||||
options = new WebpackOptionsDefaulter().process(options);
|
||||
options.entry = entry;
|
||||
options.context = path.join(__dirname, "fixtures");
|
||||
options.output.path = "/";
|
||||
|
|
|
@ -12,7 +12,7 @@ const Compiler = require("../lib/Compiler");
|
|||
describe("Compiler", () => {
|
||||
function compile(entry, options, callback) {
|
||||
const noOutputPath = !options.output || !options.output.path;
|
||||
new WebpackOptionsDefaulter().process(options);
|
||||
options = new WebpackOptionsDefaulter().process(options);
|
||||
options.entry = entry;
|
||||
options.context = path.join(__dirname, "fixtures");
|
||||
if(noOutputPath) options.output.path = "/";
|
||||
|
@ -161,7 +161,7 @@ describe("Compiler", () => {
|
|||
bundle.should.not.containEql("fixtures");
|
||||
chunk.should.not.containEql("fixtures");
|
||||
bundle.should.containEql("webpackJsonp");
|
||||
chunk.should.containEql("webpackJsonp(");
|
||||
chunk.should.containEql("window[\"webpackJsonp\"] || []).push");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -33,6 +33,13 @@ describe("Examples", () => {
|
|||
options.output.filename = "output.js";
|
||||
if(!options.entry)
|
||||
options.entry = "./example.js";
|
||||
if(!options.plugins)
|
||||
options.plugins = [];
|
||||
// To support deprecated loaders
|
||||
// TODO remove in webpack 5
|
||||
options.plugins.push(new webpack.LoaderOptionsPlugin({
|
||||
options: {}
|
||||
}));
|
||||
}
|
||||
webpack(options, (err, stats) => {
|
||||
if(err) return done(err);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue