webpack 4.31.0 → 4.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -90,7 +90,7 @@ or packaging just about any resource or asset.
90
90
 
91
91
  ### Get Started
92
92
 
93
- Check out webpack's quick [**Get Started**](https://webpack.js.org/get-started/) guide and the [other guides](https://webpack.js.org/guides/).
93
+ Check out webpack's quick [**Get Started**](https://webpack.js.org/guides/getting-started) guide and the [other guides](https://webpack.js.org/guides/).
94
94
 
95
95
  ### Browser Compatibility
96
96
 
package/bin/webpack.js CHANGED
@@ -109,7 +109,7 @@ if (installedClis.length === 0) {
109
109
  )}".`
110
110
  );
111
111
 
112
- let question = `Do you want to install 'webpack-cli' (yes/no): `;
112
+ const question = `Do you want to install 'webpack-cli' (yes/no): `;
113
113
 
114
114
  const questionInterface = readLine.createInterface({
115
115
  input: process.stdin,
@@ -22,6 +22,8 @@ export type EntryDynamic = () => EntryStatic | Promise<EntryStatic>;
22
22
  */
23
23
  export type EntryStatic = EntryObject | EntryItem;
24
24
  /**
25
+ * A non-empty array of non-empty strings
26
+ *
25
27
  * This interface was referenced by `WebpackOptions`'s JSON-Schema
26
28
  * via the `definition` "NonEmptyArrayOfUniqueStringValues".
27
29
  */
@@ -388,7 +390,8 @@ export interface WebpackOptions {
388
390
  | "async-node"
389
391
  | "node-webkit"
390
392
  | "electron-main"
391
- | "electron-renderer")
393
+ | "electron-renderer"
394
+ | "electron-preload")
392
395
  | ((compiler: import("../lib/Compiler")) => void);
393
396
  /**
394
397
  * Enter watch mode, which rebuilds on file change.
@@ -1061,7 +1064,7 @@ export interface OutputOptions {
1061
1064
  */
1062
1065
  filename?: string | Function;
1063
1066
  /**
1064
- * Use the future version of asset emitting logic, which is allows freeing memory of assets after emitting. It could break plugins which assume that assets are still readable after emitting. Will be the new default in the next major version.
1067
+ * Use the future version of asset emitting logic, which allows freeing memory of assets after emitting. It could break plugins which assume that assets are still readable after emitting. Will be the new default in the next major version.
1065
1068
  */
1066
1069
  futureEmitAssets?: boolean;
1067
1070
  /**
package/lib/Chunk.js CHANGED
@@ -688,7 +688,15 @@ class Chunk {
688
688
  };
689
689
 
690
690
  if (includeDirectChildren) {
691
- addChildIdsByOrdersToMap(this);
691
+ const chunks = new Set();
692
+ for (const chunkGroup of this.groupsIterable) {
693
+ for (const chunk of chunkGroup.chunks) {
694
+ chunks.add(chunk);
695
+ }
696
+ }
697
+ for (const chunk of chunks) {
698
+ addChildIdsByOrdersToMap(chunk);
699
+ }
692
700
  }
693
701
 
694
702
  for (const chunk of this.getAllAsyncChunks()) {
@@ -0,0 +1,114 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+ "use strict";
6
+
7
+ const path = require("path");
8
+ const ParserHelpers = require("./ParserHelpers");
9
+
10
+ class CommonJsStuffPlugin {
11
+ apply(compiler) {
12
+ compiler.hooks.compilation.tap(
13
+ "CommonJsStuffPlugin",
14
+ (compilation, { normalModuleFactory }) => {
15
+ const handler = (parser, parserOptions) => {
16
+ parser.hooks.expression
17
+ .for("require.main.require")
18
+ .tap(
19
+ "CommonJsStuffPlugin",
20
+ ParserHelpers.expressionIsUnsupported(
21
+ parser,
22
+ "require.main.require is not supported by webpack."
23
+ )
24
+ );
25
+ parser.hooks.expression
26
+ .for("module.parent.require")
27
+ .tap(
28
+ "CommonJsStuffPlugin",
29
+ ParserHelpers.expressionIsUnsupported(
30
+ parser,
31
+ "module.parent.require is not supported by webpack."
32
+ )
33
+ );
34
+ parser.hooks.expression
35
+ .for("require.main")
36
+ .tap(
37
+ "CommonJsStuffPlugin",
38
+ ParserHelpers.toConstantDependencyWithWebpackRequire(
39
+ parser,
40
+ "__webpack_require__.c[__webpack_require__.s]"
41
+ )
42
+ );
43
+ parser.hooks.expression
44
+ .for("module.loaded")
45
+ .tap("CommonJsStuffPlugin", expr => {
46
+ parser.state.module.buildMeta.moduleConcatenationBailout =
47
+ "module.loaded";
48
+ return ParserHelpers.toConstantDependency(parser, "module.l")(
49
+ expr
50
+ );
51
+ });
52
+ parser.hooks.expression
53
+ .for("module.id")
54
+ .tap("CommonJsStuffPlugin", expr => {
55
+ parser.state.module.buildMeta.moduleConcatenationBailout =
56
+ "module.id";
57
+ return ParserHelpers.toConstantDependency(parser, "module.i")(
58
+ expr
59
+ );
60
+ });
61
+ parser.hooks.expression
62
+ .for("module.exports")
63
+ .tap("CommonJsStuffPlugin", () => {
64
+ const module = parser.state.module;
65
+ const isHarmony =
66
+ module.buildMeta && module.buildMeta.exportsType;
67
+ if (!isHarmony) return true;
68
+ });
69
+ parser.hooks.evaluateIdentifier
70
+ .for("module.hot")
71
+ .tap(
72
+ "CommonJsStuffPlugin",
73
+ ParserHelpers.evaluateToIdentifier("module.hot", false)
74
+ );
75
+ parser.hooks.expression
76
+ .for("module")
77
+ .tap("CommonJsStuffPlugin", () => {
78
+ const module = parser.state.module;
79
+ const isHarmony =
80
+ module.buildMeta && module.buildMeta.exportsType;
81
+ let moduleJsPath = path.join(
82
+ __dirname,
83
+ "..",
84
+ "buildin",
85
+ isHarmony ? "harmony-module.js" : "module.js"
86
+ );
87
+ if (module.context) {
88
+ moduleJsPath = path.relative(
89
+ parser.state.module.context,
90
+ moduleJsPath
91
+ );
92
+ if (!/^[A-Z]:/i.test(moduleJsPath)) {
93
+ moduleJsPath = `./${moduleJsPath.replace(/\\/g, "/")}`;
94
+ }
95
+ }
96
+ return ParserHelpers.addParsedVariableToModule(
97
+ parser,
98
+ "module",
99
+ `require(${JSON.stringify(moduleJsPath)})(module)`
100
+ );
101
+ });
102
+ };
103
+
104
+ normalModuleFactory.hooks.parser
105
+ .for("javascript/auto")
106
+ .tap("CommonJsStuffPlugin", handler);
107
+ normalModuleFactory.hooks.parser
108
+ .for("javascript/dynamic")
109
+ .tap("CommonJsStuffPlugin", handler);
110
+ }
111
+ );
112
+ }
113
+ }
114
+ module.exports = CommonJsStuffPlugin;
@@ -290,7 +290,7 @@ module.exports = function() {
290
290
  var outdatedModules = [updateModuleId];
291
291
  var outdatedDependencies = {};
292
292
 
293
- var queue = outdatedModules.slice().map(function(id) {
293
+ var queue = outdatedModules.map(function(id) {
294
294
  return {
295
295
  chain: [id],
296
296
  id: id
@@ -467,12 +467,15 @@ module.exports = function() {
467
467
  moduleId = outdatedModules[i];
468
468
  if (
469
469
  installedModules[moduleId] &&
470
- installedModules[moduleId].hot._selfAccepted
471
- )
470
+ installedModules[moduleId].hot._selfAccepted &&
471
+ // removed self-accepted modules should not be required
472
+ appliedUpdate[moduleId] !== warnUnexpectedRequire
473
+ ) {
472
474
  outdatedSelfAcceptedModules.push({
473
475
  module: moduleId,
474
476
  errorHandler: installedModules[moduleId].hot._selfAccepted
475
477
  });
478
+ }
476
479
  }
477
480
 
478
481
  // Now in "dispose" phase
@@ -539,7 +542,7 @@ module.exports = function() {
539
542
  }
540
543
  }
541
544
 
542
- // Not in "apply" phase
545
+ // Now in "apply" phase
543
546
  hotSetStatus("apply");
544
547
 
545
548
  hotCurrentHash = hotUpdateNewHash;
@@ -98,6 +98,8 @@ module.exports = class MainTemplate extends Tapable {
98
98
  beforeStartup: new SyncWaterfallHook(["source", "chunk", "hash"]),
99
99
  /** @type {SyncWaterfallHook<string, Chunk, string>} */
100
100
  startup: new SyncWaterfallHook(["source", "chunk", "hash"]),
101
+ /** @type {SyncWaterfallHook<string, Chunk, string>} */
102
+ afterStartup: new SyncWaterfallHook(["source", "chunk", "hash"]),
101
103
  render: new SyncWaterfallHook([
102
104
  "source",
103
105
  "chunk",
@@ -404,7 +406,20 @@ module.exports = class MainTemplate extends Tapable {
404
406
  );
405
407
  buf.push("");
406
408
  buf.push(Template.asString(this.hooks.beforeStartup.call("", chunk, hash)));
409
+ const afterStartupCode = Template.asString(
410
+ this.hooks.afterStartup.call("", chunk, hash)
411
+ );
412
+ if (afterStartupCode) {
413
+ // TODO webpack 5: this is a bit hacky to avoid a breaking change
414
+ // change it to a better way
415
+ buf.push("var startupResult = (function() {");
416
+ }
407
417
  buf.push(Template.asString(this.hooks.startup.call("", chunk, hash)));
418
+ if (afterStartupCode) {
419
+ buf.push("})();");
420
+ buf.push(afterStartupCode);
421
+ buf.push("return startupResult;");
422
+ }
408
423
  return buf;
409
424
  }
410
425
 
@@ -58,47 +58,42 @@ class NodeStuffPlugin {
58
58
  });
59
59
  };
60
60
  const context = compiler.context;
61
- if (localOptions.__filename === "mock") {
62
- setConstant("__filename", "/index.js");
63
- } else if (localOptions.__filename) {
64
- setModuleConstant("__filename", module =>
65
- path.relative(context, module.resource)
66
- );
61
+ if (localOptions.__filename) {
62
+ if (localOptions.__filename === "mock") {
63
+ setConstant("__filename", "/index.js");
64
+ } else {
65
+ setModuleConstant("__filename", module =>
66
+ path.relative(context, module.resource)
67
+ );
68
+ }
69
+ parser.hooks.evaluateIdentifier
70
+ .for("__filename")
71
+ .tap("NodeStuffPlugin", expr => {
72
+ if (!parser.state.module) return;
73
+ const resource = parser.state.module.resource;
74
+ const i = resource.indexOf("?");
75
+ return ParserHelpers.evaluateToString(
76
+ i < 0 ? resource : resource.substr(0, i)
77
+ )(expr);
78
+ });
67
79
  }
68
- parser.hooks.evaluateIdentifier
69
- .for("__filename")
70
- .tap("NodeStuffPlugin", expr => {
71
- if (!parser.state.module) return;
72
- const resource = parser.state.module.resource;
73
- const i = resource.indexOf("?");
74
- return ParserHelpers.evaluateToString(
75
- i < 0 ? resource : resource.substr(0, i)
76
- )(expr);
77
- });
78
- if (localOptions.__dirname === "mock") {
79
- setConstant("__dirname", "/");
80
- } else if (localOptions.__dirname) {
81
- setModuleConstant("__dirname", module =>
82
- path.relative(context, module.context)
83
- );
80
+ if (localOptions.__dirname) {
81
+ if (localOptions.__dirname === "mock") {
82
+ setConstant("__dirname", "/");
83
+ } else {
84
+ setModuleConstant("__dirname", module =>
85
+ path.relative(context, module.context)
86
+ );
87
+ }
88
+ parser.hooks.evaluateIdentifier
89
+ .for("__dirname")
90
+ .tap("NodeStuffPlugin", expr => {
91
+ if (!parser.state.module) return;
92
+ return ParserHelpers.evaluateToString(
93
+ parser.state.module.context
94
+ )(expr);
95
+ });
84
96
  }
85
- parser.hooks.evaluateIdentifier
86
- .for("__dirname")
87
- .tap("NodeStuffPlugin", expr => {
88
- if (!parser.state.module) return;
89
- return ParserHelpers.evaluateToString(
90
- parser.state.module.context
91
- )(expr);
92
- });
93
- parser.hooks.expression
94
- .for("require.main")
95
- .tap(
96
- "NodeStuffPlugin",
97
- ParserHelpers.toConstantDependencyWithWebpackRequire(
98
- parser,
99
- "__webpack_require__.c[__webpack_require__.s]"
100
- )
101
- );
102
97
  parser.hooks.expression
103
98
  .for("require.extensions")
104
99
  .tap(
@@ -108,80 +103,6 @@ class NodeStuffPlugin {
108
103
  "require.extensions is not supported by webpack. Use a loader instead."
109
104
  )
110
105
  );
111
- parser.hooks.expression
112
- .for("require.main.require")
113
- .tap(
114
- "NodeStuffPlugin",
115
- ParserHelpers.expressionIsUnsupported(
116
- parser,
117
- "require.main.require is not supported by webpack."
118
- )
119
- );
120
- parser.hooks.expression
121
- .for("module.parent.require")
122
- .tap(
123
- "NodeStuffPlugin",
124
- ParserHelpers.expressionIsUnsupported(
125
- parser,
126
- "module.parent.require is not supported by webpack."
127
- )
128
- );
129
- parser.hooks.expression
130
- .for("module.loaded")
131
- .tap("NodeStuffPlugin", expr => {
132
- parser.state.module.buildMeta.moduleConcatenationBailout =
133
- "module.loaded";
134
- return ParserHelpers.toConstantDependency(parser, "module.l")(
135
- expr
136
- );
137
- });
138
- parser.hooks.expression
139
- .for("module.id")
140
- .tap("NodeStuffPlugin", expr => {
141
- parser.state.module.buildMeta.moduleConcatenationBailout =
142
- "module.id";
143
- return ParserHelpers.toConstantDependency(parser, "module.i")(
144
- expr
145
- );
146
- });
147
- parser.hooks.expression
148
- .for("module.exports")
149
- .tap("NodeStuffPlugin", () => {
150
- const module = parser.state.module;
151
- const isHarmony =
152
- module.buildMeta && module.buildMeta.exportsType;
153
- if (!isHarmony) return true;
154
- });
155
- parser.hooks.evaluateIdentifier
156
- .for("module.hot")
157
- .tap(
158
- "NodeStuffPlugin",
159
- ParserHelpers.evaluateToIdentifier("module.hot", false)
160
- );
161
- parser.hooks.expression.for("module").tap("NodeStuffPlugin", () => {
162
- const module = parser.state.module;
163
- const isHarmony = module.buildMeta && module.buildMeta.exportsType;
164
- let moduleJsPath = path.join(
165
- __dirname,
166
- "..",
167
- "buildin",
168
- isHarmony ? "harmony-module.js" : "module.js"
169
- );
170
- if (module.context) {
171
- moduleJsPath = path.relative(
172
- parser.state.module.context,
173
- moduleJsPath
174
- );
175
- if (!/^[A-Z]:/i.test(moduleJsPath)) {
176
- moduleJsPath = `./${moduleJsPath.replace(/\\/g, "/")}`;
177
- }
178
- }
179
- return ParserHelpers.addParsedVariableToModule(
180
- parser,
181
- "module",
182
- `require(${JSON.stringify(moduleJsPath)})(module)`
183
- );
184
- });
185
106
  };
186
107
 
187
108
  normalModuleFactory.hooks.parser
@@ -212,6 +212,7 @@ class NormalModule extends Module {
212
212
  rootContext: options.context,
213
213
  webpack: true,
214
214
  sourceMap: !!this.useSourceMap,
215
+ mode: options.mode || "production",
215
216
  _module: this,
216
217
  _compilation: compilation,
217
218
  _compiler: compilation.compiler,
package/lib/Parser.js CHANGED
@@ -1954,6 +1954,9 @@ class Parser extends Tapable {
1954
1954
  case "RestElement":
1955
1955
  this.enterRestElement(pattern, onIdent);
1956
1956
  break;
1957
+ case "Property":
1958
+ this.enterPattern(pattern.value, onIdent);
1959
+ break;
1957
1960
  }
1958
1961
  }
1959
1962
 
@@ -1968,7 +1971,7 @@ class Parser extends Tapable {
1968
1971
  propIndex++
1969
1972
  ) {
1970
1973
  const prop = pattern.properties[propIndex];
1971
- this.enterPattern(prop.value, onIdent);
1974
+ this.enterPattern(prop, onIdent);
1972
1975
  }
1973
1976
  }
1974
1977
 
@@ -21,7 +21,7 @@ const RecordIdsPlugin = require("./RecordIdsPlugin");
21
21
 
22
22
  const APIPlugin = require("./APIPlugin");
23
23
  const ConstPlugin = require("./ConstPlugin");
24
- const NodeStuffPlugin = require("./NodeStuffPlugin");
24
+ const CommonJsStuffPlugin = require("./CommonJsStuffPlugin");
25
25
  const CompatibilityPlugin = require("./CompatibilityPlugin");
26
26
 
27
27
  const TemplatedPathPlugin = require("./TemplatedPathPlugin");
@@ -156,11 +156,19 @@ class WebpackOptionsApply extends OptionsApply {
156
156
  new LoaderTargetPlugin(options.target).apply(compiler);
157
157
  break;
158
158
  case "electron-renderer":
159
- JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin");
159
+ case "electron-preload":
160
160
  FetchCompileWasmTemplatePlugin = require("./web/FetchCompileWasmTemplatePlugin");
161
161
  NodeTargetPlugin = require("./node/NodeTargetPlugin");
162
162
  ExternalsPlugin = require("./ExternalsPlugin");
163
- new JsonpTemplatePlugin().apply(compiler);
163
+ if (options.target === "electron-renderer") {
164
+ JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin");
165
+ new JsonpTemplatePlugin().apply(compiler);
166
+ } else if (options.target === "electron-preload") {
167
+ NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
168
+ new NodeTemplatePlugin({
169
+ asyncChunkLoading: true
170
+ }).apply(compiler);
171
+ }
164
172
  new FetchCompileWasmTemplatePlugin({
165
173
  mangleImports: options.optimization.mangleWasmImports
166
174
  }).apply(compiler);
@@ -290,7 +298,11 @@ class WebpackOptionsApply extends OptionsApply {
290
298
  }
291
299
  new CommonJsPlugin(options.module).apply(compiler);
292
300
  new LoaderPlugin().apply(compiler);
293
- new NodeStuffPlugin(options.node).apply(compiler);
301
+ if (options.node !== false) {
302
+ const NodeStuffPlugin = require("./NodeStuffPlugin");
303
+ new NodeStuffPlugin(options.node).apply(compiler);
304
+ }
305
+ new CommonJsStuffPlugin().apply(compiler);
294
306
  new APIPlugin().apply(compiler);
295
307
  new ConstPlugin().apply(compiler);
296
308
  new UseStrictPlugin().apply(compiler);
@@ -50,13 +50,34 @@ const getSchemaPartDescription = schemaPart => {
50
50
  return "";
51
51
  };
52
52
 
53
+ const SPECIFICITY = {
54
+ type: 1,
55
+ oneOf: 1,
56
+ anyOf: 1,
57
+ allOf: 1,
58
+ additionalProperties: 2,
59
+ enum: 1,
60
+ instanceof: 1,
61
+ required: 2,
62
+ minimum: 2,
63
+ uniqueItems: 2,
64
+ minLength: 2,
65
+ minItems: 2,
66
+ minProperties: 2,
67
+ absolutePath: 2
68
+ };
69
+
70
+ const filterMax = (array, fn) => {
71
+ const max = array.reduce((max, item) => Math.max(max, fn(item)), 0);
72
+ return array.filter(item => fn(item) === max);
73
+ };
74
+
53
75
  const filterChildren = children => {
54
- return children.filter(
55
- err =>
56
- err.keyword !== "anyOf" &&
57
- err.keyword !== "allOf" &&
58
- err.keyword !== "oneOf"
76
+ children = filterMax(children, err =>
77
+ err.dataPath ? err.dataPath.length : 0
59
78
  );
79
+ children = filterMax(children, err => SPECIFICITY[err.keyword] || 2);
80
+ return children;
60
81
  };
61
82
 
62
83
  const indent = (str, prefix, firstLine) => {
@@ -154,6 +175,10 @@ class WebpackOptionsValidationError extends WebpackError {
154
175
  return "RegExp";
155
176
  }
156
177
 
178
+ if (schema.enum) {
179
+ return schema.enum.map(item => JSON.stringify(item)).join(" | ");
180
+ }
181
+
157
182
  if (schema.$ref) {
158
183
  return formatInnerSchema(getSchemaPart(schema.$ref), true);
159
184
  }
@@ -166,9 +191,6 @@ class WebpackOptionsValidationError extends WebpackError {
166
191
  if (schema.anyOf) {
167
192
  return schema.anyOf.map(formatInnerSchema).join(" | ");
168
193
  }
169
- if (schema.enum) {
170
- return schema.enum.map(item => JSON.stringify(item)).join(" | ");
171
- }
172
194
  return JSON.stringify(schema, null, 2);
173
195
  }
174
196
 
@@ -229,11 +251,17 @@ class WebpackOptionsValidationError extends WebpackError {
229
251
  })
230
252
  );
231
253
  }
254
+ const children = filterChildren(err.children);
255
+ if (children.length === 1) {
256
+ return WebpackOptionsValidationError.formatValidationError(
257
+ children[0]
258
+ );
259
+ }
232
260
  return (
233
261
  `${dataPath} should be one of these:\n${getSchemaPartText(
234
262
  err.parentSchema
235
263
  )}\n` +
236
- `Details:\n${filterChildren(err.children)
264
+ `Details:\n${children
237
265
  .map(
238
266
  err =>
239
267
  " * " +
@@ -312,7 +340,21 @@ class WebpackOptionsValidationError extends WebpackError {
312
340
  err.keyword === "minProperties"
313
341
  ) {
314
342
  if (err.params.limit === 1) {
315
- return `${dataPath} should not be empty.${getSchemaPartDescription(
343
+ switch (err.keyword) {
344
+ case "minLength":
345
+ return `${dataPath} should be an non-empty string.${getSchemaPartDescription(
346
+ err.parentSchema
347
+ )}`;
348
+ case "minItems":
349
+ return `${dataPath} should be an non-empty array.${getSchemaPartDescription(
350
+ err.parentSchema
351
+ )}`;
352
+ case "minProperties":
353
+ return `${dataPath} should be an non-empty object.${getSchemaPartDescription(
354
+ err.parentSchema
355
+ )}`;
356
+ }
357
+ return `${dataPath} should be not empty.${getSchemaPartDescription(
316
358
  err.parentSchema
317
359
  )}`;
318
360
  } else {
@@ -50,6 +50,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
50
50
  ) {
51
51
  super(request, originModule, sourceOrder, parserScope);
52
52
  this.id = id;
53
+ this.redirectedId = undefined;
53
54
  this.name = name;
54
55
  this.activeExports = activeExports;
55
56
  this.otherStarExports = otherStarExports;
@@ -60,9 +61,13 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
60
61
  return "harmony export imported specifier";
61
62
  }
62
63
 
64
+ get _id() {
65
+ return this.redirectedId || this.id;
66
+ }
67
+
63
68
  getMode(ignoreUnused) {
64
69
  const name = this.name;
65
- const id = this.id;
70
+ const id = this._id;
66
71
  const used = this.originModule.isUsed(name);
67
72
  const importedModule = this._module;
68
73
 
@@ -288,7 +293,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
288
293
  };
289
294
  }
290
295
 
291
- const importedModule = this.module;
296
+ const importedModule = this._module;
292
297
 
293
298
  if (!importedModule) {
294
299
  // no imported module available
@@ -350,11 +355,11 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
350
355
  // It's not an harmony module
351
356
  if (
352
357
  this.originModule.buildMeta.strictHarmonyModule &&
353
- this.id !== "default"
358
+ this._id !== "default"
354
359
  ) {
355
360
  // In strict harmony modules we only support the default export
356
- const exportName = this.id
357
- ? `the named export '${this.id}'`
361
+ const exportName = this._id
362
+ ? `the named export '${this._id}'`
358
363
  : "the namespace object";
359
364
  return [
360
365
  new HarmonyLinkingError(
@@ -365,20 +370,20 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
365
370
  return;
366
371
  }
367
372
 
368
- if (!this.id) {
373
+ if (!this._id) {
369
374
  return;
370
375
  }
371
376
 
372
- if (importedModule.isProvided(this.id) !== false) {
377
+ if (importedModule.isProvided(this._id) !== false) {
373
378
  // It's provided or we are not sure
374
379
  return;
375
380
  }
376
381
 
377
382
  // We are sure that it's not provided
378
383
  const idIsNotNameMessage =
379
- this.id !== this.name ? ` (reexported as '${this.name}')` : "";
384
+ this._id !== this.name ? ` (reexported as '${this.name}')` : "";
380
385
  const errorMessage = `"export '${
381
- this.id
386
+ this._id
382
387
  }'${idIsNotNameMessage} was not found in '${this.userRequest}'`;
383
388
  return [new HarmonyLinkingError(errorMessage)];
384
389
  }
@@ -402,6 +407,11 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
402
407
  importedModule.used + stringifiedUsedExport + stringifiedProvidedExport
403
408
  );
404
409
  }
410
+
411
+ disconnect() {
412
+ super.disconnect();
413
+ this.redirectedId = undefined;
414
+ }
405
415
  }
406
416
 
407
417
  module.exports = HarmonyExportImportedSpecifierDependency;
@@ -521,7 +521,7 @@ class ConcatenatedModule extends Module {
521
521
  dep instanceof HarmonyExportImportedSpecifierDependency
522
522
  ) {
523
523
  const exportName = dep.name;
524
- const importName = dep.id;
524
+ const importName = dep._id;
525
525
  const importedModule = dep._module;
526
526
  if (exportName && importName) {
527
527
  if (!reexportMap.has(exportName)) {
@@ -1390,12 +1390,12 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate {
1390
1390
 
1391
1391
  getExports(dep) {
1392
1392
  const importModule = dep._module;
1393
- if (dep.id) {
1393
+ if (dep._id) {
1394
1394
  // export { named } from "module"
1395
1395
  return [
1396
1396
  {
1397
1397
  name: dep.name,
1398
- id: dep.id,
1398
+ id: dep._id,
1399
1399
  module: importModule
1400
1400
  }
1401
1401
  ];
@@ -111,8 +111,9 @@ class SideEffectsFlagPlugin {
111
111
  const reason = module.reasons[i];
112
112
  const dep = reason.dependency;
113
113
  if (
114
- dep instanceof HarmonyImportSpecifierDependency &&
115
- !dep.namespaceObjectAsContext
114
+ dep instanceof HarmonyExportImportedSpecifierDependency ||
115
+ (dep instanceof HarmonyImportSpecifierDependency &&
116
+ !dep.namespaceObjectAsContext)
116
117
  ) {
117
118
  const mapping = map.get(dep.id);
118
119
  if (mapping) {
@@ -115,7 +115,11 @@ class JsonpMainTemplatePlugin {
115
115
  ),
116
116
  "};",
117
117
  "",
118
- needEntryDeferringCode(chunk) ? "var deferredModules = [];" : ""
118
+ needEntryDeferringCode(chunk)
119
+ ? needPrefetchingCode(chunk)
120
+ ? "var deferredModules = [], deferredPrefetch = [];"
121
+ : "var deferredModules = [];"
122
+ : ""
119
123
  );
120
124
  }
121
125
  if (needChunkOnDemandLoadingCode(chunk)) {
@@ -169,6 +173,8 @@ class JsonpMainTemplatePlugin {
169
173
  "}"
170
174
  ])
171
175
  : "",
176
+ "// create error before stack unwound to get useful stacktrace later",
177
+ "var error = new Error();",
172
178
  "onScriptComplete = function (event) {",
173
179
  Template.indent([
174
180
  "// avoid mem leaks in IE.",
@@ -181,7 +187,7 @@ class JsonpMainTemplatePlugin {
181
187
  Template.indent([
182
188
  "var errorType = event && (event.type === 'load' ? 'missing' : event.type);",
183
189
  "var realSrc = event && event.target && event.target.src;",
184
- "var error = new Error('Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')');",
190
+ "error.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';",
185
191
  "error.type = errorType;",
186
192
  "error.request = realSrc;",
187
193
  "chunk[1](error);"
@@ -384,20 +390,22 @@ class JsonpMainTemplatePlugin {
384
390
  "}",
385
391
  "if(parentJsonpFunction) parentJsonpFunction(data);",
386
392
  withPrefetch
387
- ? Template.asString([
388
- "// chunk prefetching for javascript",
389
- "prefetchChunks.forEach(function(chunkId) {",
390
- Template.indent([
391
- "if(installedChunks[chunkId] === undefined) {",
393
+ ? withDefer
394
+ ? "deferredPrefetch.push.apply(deferredPrefetch, prefetchChunks);"
395
+ : Template.asString([
396
+ "// chunk prefetching for javascript",
397
+ "prefetchChunks.forEach(function(chunkId) {",
392
398
  Template.indent([
393
- "installedChunks[chunkId] = null;",
394
- mainTemplate.hooks.linkPrefetch.call("", chunk, hash),
395
- "document.head.appendChild(link);"
399
+ "if(installedChunks[chunkId] === undefined) {",
400
+ Template.indent([
401
+ "installedChunks[chunkId] = null;",
402
+ mainTemplate.hooks.linkPrefetch.call("", chunk, hash),
403
+ "document.head.appendChild(link);"
404
+ ]),
405
+ "}"
396
406
  ]),
397
- "}"
398
- ]),
399
- "});"
400
- ])
407
+ "});"
408
+ ])
401
409
  : "",
402
410
  "while(resolves.length) {",
403
411
  Template.indent("resolves.shift()();"),
@@ -441,6 +449,31 @@ class JsonpMainTemplatePlugin {
441
449
  "}"
442
450
  ]),
443
451
  "}",
452
+ withPrefetch
453
+ ? Template.asString([
454
+ "if(deferredModules.length === 0) {",
455
+ Template.indent([
456
+ "// chunk prefetching for javascript",
457
+ "deferredPrefetch.forEach(function(chunkId) {",
458
+ Template.indent([
459
+ "if(installedChunks[chunkId] === undefined) {",
460
+ Template.indent([
461
+ "installedChunks[chunkId] = null;",
462
+ mainTemplate.hooks.linkPrefetch.call(
463
+ "",
464
+ chunk,
465
+ hash
466
+ ),
467
+ "document.head.appendChild(link);"
468
+ ]),
469
+ "}"
470
+ ]),
471
+ "});",
472
+ "deferredPrefetch.length = 0;"
473
+ ]),
474
+ "}"
475
+ ])
476
+ : "",
444
477
  "return result;"
445
478
  ]),
446
479
  "}"
@@ -473,7 +506,7 @@ class JsonpMainTemplatePlugin {
473
506
  return source;
474
507
  }
475
508
  );
476
- mainTemplate.hooks.beforeStartup.tap(
509
+ mainTemplate.hooks.afterStartup.tap(
477
510
  "JsonpMainTemplatePlugin",
478
511
  (source, chunk, hash) => {
479
512
  const prefetchChunks = chunk.getChildIdsByOrders().prefetch;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpack",
3
- "version": "4.31.0",
3
+ "version": "4.33.0",
4
4
  "author": "Tobias Koppers @sokra",
5
5
  "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
6
6
  "license": "MIT",
@@ -110,12 +110,12 @@
110
110
  "test:integration": "node --max-old-space-size=4096 --trace-deprecation node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.test.js\"",
111
111
  "test:basic": "node --max-old-space-size=4096 --trace-deprecation node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/te{st/TestCasesNormal,st/StatsTestCases,st/ConfigTestCases}.test.js\"",
112
112
  "test:unit": "node --max-old-space-size=4096 --trace-deprecation node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.unittest.js\"",
113
- "travis:integration": "yarn cover:init && yarn cover:integration --ci $JEST",
114
- "travis:basic": "yarn test:basic --ci $JEST",
115
- "travis:lint-unit": "yarn lint && yarn cover:init && yarn cover:unit --ci $JEST",
113
+ "travis:integration": "yarn cover:integration --ci $JEST",
114
+ "travis:basic": "yarn cover:basic --ci $JEST",
115
+ "travis:lintunit": "yarn lint && yarn cover:unit --ci $JEST",
116
116
  "travis:benchmark": "yarn benchmark --ci",
117
- "appveyor:integration": "yarn cover:init && yarn cover:integration --ci %JEST%",
118
- "appveyor:unit": "yarn cover:init && yarn cover:unit --ci %JEST%",
117
+ "appveyor:integration": "yarn cover:integration --ci %JEST%",
118
+ "appveyor:unit": "yarn cover:unit --ci %JEST%",
119
119
  "appveyor:benchmark": "yarn benchmark --ci",
120
120
  "build:examples": "cd examples && node buildAll.js",
121
121
  "pretest": "yarn lint",
@@ -129,9 +129,9 @@
129
129
  "pretty": "prettier --loglevel warn --write \"*.{ts,js,json,yml,yaml}\" \"{setup,lib,bin,hot,buildin,benchmark,tooling,schemas}/**/*.{js,json}\" \"test/*.js\" \"test/{configCases,watchCases,statsCases,hotCases}/**/webpack.config.js\" \"examples/**/webpack.config.js\"",
130
130
  "jest-lint": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.lint.js\" --no-verbose",
131
131
  "benchmark": "node --max-old-space-size=4096 --trace-deprecation node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.benchmark.js\" --runInBand",
132
- "cover": "yarn cover:init && yarn cover:all && yarn cover:report",
133
- "cover:init": "rimraf coverage",
132
+ "cover": "yarn cover:all && yarn cover:report",
134
133
  "cover:all": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --coverage",
134
+ "cover:basic": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/te{st/TestCasesNormal,st/StatsTestCases,st/ConfigTestCases}.test.js\" --coverage",
135
135
  "cover:integration": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.test.js\" --coverage",
136
136
  "cover:unit": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.unittest.js\" --coverage",
137
137
  "cover:report": "istanbul report"
@@ -385,6 +385,7 @@
385
385
  }
386
386
  },
387
387
  "NonEmptyArrayOfUniqueStringValues": {
388
+ "description": "A non-empty array of non-empty strings",
388
389
  "type": "array",
389
390
  "items": {
390
391
  "description": "A non-empty string",
@@ -868,7 +869,7 @@
868
869
  ]
869
870
  },
870
871
  "futureEmitAssets": {
871
- "description": "Use the future version of asset emitting logic, which is allows freeing memory of assets after emitting. It could break plugins which assume that assets are still readable after emitting. Will be the new default in the next major version.",
872
+ "description": "Use the future version of asset emitting logic, which allows freeing memory of assets after emitting. It could break plugins which assume that assets are still readable after emitting. Will be the new default in the next major version.",
872
873
  "type": "boolean"
873
874
  },
874
875
  "globalObject": {
@@ -2127,7 +2128,8 @@
2127
2128
  "async-node",
2128
2129
  "node-webkit",
2129
2130
  "electron-main",
2130
- "electron-renderer"
2131
+ "electron-renderer",
2132
+ "electron-preload"
2131
2133
  ]
2132
2134
  },
2133
2135
  {