webpack 3.3.0 → 3.5.1

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.
Files changed (40) hide show
  1. package/README.md +34 -11
  2. package/bin/config-optimist.js +1 -0
  3. package/bin/config-yargs.js +12 -4
  4. package/bin/convert-argv.js +28 -8
  5. package/bin/webpack.js +198 -182
  6. package/lib/ContextModule.js +87 -13
  7. package/lib/DelegatedModule.js +10 -4
  8. package/lib/DelegatedModuleFactoryPlugin.js +5 -4
  9. package/lib/DelegatedPlugin.js +3 -0
  10. package/lib/DllReferencePlugin.js +3 -0
  11. package/lib/ExternalModule.js +6 -1
  12. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  13. package/lib/HotModuleReplacement.runtime.js +13 -5
  14. package/lib/MultiCompiler.js +2 -2
  15. package/lib/NormalModule.js +32 -9
  16. package/lib/NormalModuleFactory.js +133 -145
  17. package/lib/Parser.js +52 -58
  18. package/lib/RecordIdsPlugin.js +3 -3
  19. package/lib/SourceMapDevToolPlugin.js +57 -41
  20. package/lib/Stats.js +58 -24
  21. package/lib/Template.js +1 -1
  22. package/lib/dependencies/DelegatedExportsDependency.js +33 -0
  23. package/lib/dependencies/HarmonyCompatibilityDependency.js +1 -1
  24. package/lib/dependencies/ImportParserPlugin.js +11 -4
  25. package/lib/dependencies/ImportPlugin.js +8 -0
  26. package/lib/dependencies/ImportWeakContextDependency.js +22 -0
  27. package/lib/dependencies/ImportWeakDependency.js +47 -0
  28. package/lib/dependencies/RequireContextDependency.js +5 -1
  29. package/lib/dependencies/RequireContextDependencyParserPlugin.js +9 -1
  30. package/lib/dependencies/RequireResolveDependencyParserPlugin.js +1 -1
  31. package/lib/optimize/AggressiveMergingPlugin.js +27 -33
  32. package/lib/optimize/AggressiveSplittingPlugin.js +46 -33
  33. package/lib/optimize/ChunkModuleIdRangePlugin.js +1 -3
  34. package/lib/optimize/CommonsChunkPlugin.js +11 -4
  35. package/lib/optimize/ConcatenatedModule.js +403 -229
  36. package/lib/optimize/ModuleConcatenationPlugin.js +30 -35
  37. package/lib/util/identifier.js +23 -1
  38. package/lib/webpack.js +52 -55
  39. package/package.json +10 -10
  40. package/schemas/webpackOptionsSchema.json +27 -12
@@ -7,6 +7,8 @@
7
7
 
8
8
  const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin");
9
9
  const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
10
+ const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency");
11
+ const NullFactory = require("./NullFactory");
10
12
 
11
13
  class DelegatedPlugin {
12
14
  constructor(options) {
@@ -16,6 +18,7 @@ class DelegatedPlugin {
16
18
  apply(compiler) {
17
19
  compiler.plugin("compilation", (compilation, params) => {
18
20
  compilation.dependencyFactories.set(DelegatedSourceDependency, params.normalModuleFactory);
21
+ compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory());
19
22
  });
20
23
 
21
24
  compiler.plugin("compile", (params) => {
@@ -7,6 +7,8 @@
7
7
  const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
8
8
  const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin");
9
9
  const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin");
10
+ const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency");
11
+ const NullFactory = require("./NullFactory");
10
12
 
11
13
  class DllReferencePlugin {
12
14
  constructor(options) {
@@ -17,6 +19,7 @@ class DllReferencePlugin {
17
19
  compiler.plugin("compilation", (compilation, params) => {
18
20
  const normalModuleFactory = params.normalModuleFactory;
19
21
  compilation.dependencyFactories.set(DelegatedSourceDependency, normalModuleFactory);
22
+ compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory());
20
23
  });
21
24
 
22
25
  compiler.plugin("before-compile", (params, callback) => {
@@ -10,14 +10,19 @@ const WebpackMissingModule = require("./dependencies/WebpackMissingModule");
10
10
  const Template = require("./Template");
11
11
 
12
12
  class ExternalModule extends Module {
13
- constructor(request, type) {
13
+ constructor(request, type, userRequest) {
14
14
  super();
15
15
  this.request = request;
16
+ this.userRequest = userRequest;
16
17
  this.type = type;
17
18
  this.built = false;
18
19
  this.external = true;
19
20
  }
20
21
 
22
+ libIdent() {
23
+ return this.userRequest;
24
+ }
25
+
21
26
  chunkCondition(chunk) {
22
27
  return chunk.hasEntryModule();
23
28
  }
@@ -30,7 +30,7 @@ class ExternalModuleFactoryPlugin {
30
30
  type = value.substr(0, idx);
31
31
  value = value.substr(idx + 1);
32
32
  }
33
- callback(null, new ExternalModule(value, type || globalType));
33
+ callback(null, new ExternalModule(value, type || globalType, dependency.request));
34
34
  return true;
35
35
  }
36
36
  (function handleExternals(externals, callback) {
@@ -228,11 +228,19 @@ module.exports = function() {
228
228
  hotDeferred = null;
229
229
  if(!deferred) return;
230
230
  if(hotApplyOnUpdate) {
231
- hotApply(hotApplyOnUpdate).then(function(result) {
232
- deferred.resolve(result);
233
- }, function(err) {
234
- deferred.reject(err);
235
- });
231
+ // Wrap deferred object in Promise to mark it as a well-handled Promise to
232
+ // avoid triggering uncaught exception warning in Chrome.
233
+ // See https://bugs.chromium.org/p/chromium/issues/detail?id=465666
234
+ Promise.resolve().then(function() {
235
+ return hotApply(hotApplyOnUpdate);
236
+ }).then(
237
+ function(result) {
238
+ deferred.resolve(result);
239
+ },
240
+ function(err) {
241
+ deferred.reject(err);
242
+ }
243
+ );
236
244
  } else {
237
245
  var outdatedModules = [];
238
246
  for(var id in hotUpdate) {
@@ -46,8 +46,8 @@ module.exports = class MultiCompiler extends Tapable {
46
46
  get outputPath() {
47
47
  let commonPath = this.compilers[0].outputPath;
48
48
  for(const compiler of this.compilers) {
49
- while(compiler.outputPath.indexOf(commonPath) !== 0 && /[\/\\]/.test(commonPath)) {
50
- commonPath = commonPath.replace(/[\/\\][^\/\\]*$/, "");
49
+ while(compiler.outputPath.indexOf(commonPath) !== 0 && /[/\\]/.test(commonPath)) {
50
+ commonPath = commonPath.replace(/[/\\][^/\\]*$/, "");
51
51
  }
52
52
  }
53
53
 
@@ -392,9 +392,16 @@ class NormalModule extends Module {
392
392
  * These will contain the variable name and its expression.
393
393
  * The name will be added as a paramter in a IIFE the expression as its value.
394
394
  */
395
- const vars = block.variables.map((variable) => this.sourceVariables(
396
- variable, availableVars, dependencyTemplates, outputOptions, requestShortener))
397
- .filter(Boolean);
395
+ const vars = block.variables.reduce((result, value) => {
396
+ const variable = this.sourceVariables(
397
+ value, availableVars, dependencyTemplates, outputOptions, requestShortener);
398
+
399
+ if(variable) {
400
+ result.push(variable);
401
+ }
402
+
403
+ return result;
404
+ }, []);
398
405
 
399
406
  /**
400
407
  * if we actually have variables
@@ -420,15 +427,22 @@ class NormalModule extends Module {
420
427
  const injectionVariableChunks = this.splitVariablesInUniqueNamedChunks(vars);
421
428
 
422
429
  // create all the beginnings of IIFEs
423
- const functionWrapperStarts = injectionVariableChunks.map((variableChunk) => variableChunk.map(variable => variable.name))
424
- .map(names => this.variableInjectionFunctionWrapperStartCode(names));
430
+ const functionWrapperStarts = injectionVariableChunks.map((variableChunk) => {
431
+ return this.variableInjectionFunctionWrapperStartCode(
432
+ variableChunk.map(variable => variable.name)
433
+ );
434
+ });
425
435
 
426
436
  // and all the ends
427
- const functionWrapperEnds = injectionVariableChunks.map((variableChunk) => variableChunk.map(variable => variable.expression))
428
- .map(expressions => this.variableInjectionFunctionWrapperEndCode(expressions, block));
437
+ const functionWrapperEnds = injectionVariableChunks.map((variableChunk) => {
438
+ return this.variableInjectionFunctionWrapperEndCode(
439
+ variableChunk.map(variable => variable.expression), block
440
+ );
441
+ });
429
442
 
430
443
  // join them to one big string
431
444
  const varStartCode = functionWrapperStarts.join("");
445
+
432
446
  // reverse the ends first before joining them, as the last added must be the inner most
433
447
  const varEndCode = functionWrapperEnds.reverse().join("");
434
448
 
@@ -440,8 +454,17 @@ class NormalModule extends Module {
440
454
  source.insert(end + 0.5, "\n/* WEBPACK VAR INJECTION */" + varEndCode);
441
455
  }
442
456
  }
443
- block.blocks.forEach((block) => this.sourceBlock(
444
- block, availableVars.concat(vars), dependencyTemplates, source, outputOptions, requestShortener));
457
+
458
+ block.blocks.forEach((block) =>
459
+ this.sourceBlock(
460
+ block,
461
+ availableVars.concat(vars),
462
+ dependencyTemplates,
463
+ source,
464
+ outputOptions,
465
+ requestShortener
466
+ )
467
+ );
445
468
  }
446
469
 
447
470
  source(dependencyTemplates, outputOptions, requestShortener) {
@@ -50,173 +50,161 @@ class NormalModuleFactory extends Tapable {
50
50
  this.cachePredicate = typeof options.unsafeCache === "function" ? options.unsafeCache : Boolean.bind(null, options.unsafeCache);
51
51
  this.context = context || "";
52
52
  this.parserCache = {};
53
- this.plugin("factory", function() {
54
- /* beautify preserve:start */
55
- // js-beautify consider to concat "return" and "("
56
- // but it сontradicts eslint rule (keyword-spacing)
57
- return (result, callback) => {
58
- /* beautify preserve:end */
59
- let resolver = this.applyPluginsWaterfall0("resolver", null);
53
+ this.plugin("factory", () => (result, callback) => {
54
+ let resolver = this.applyPluginsWaterfall0("resolver", null);
60
55
 
61
- // Ignored
62
- if(!resolver) return callback();
63
-
64
- resolver(result, (err, data) => {
65
- if(err) return callback(err);
56
+ // Ignored
57
+ if(!resolver) return callback();
66
58
 
67
- // Ignored
68
- if(!data) return callback();
59
+ resolver(result, (err, data) => {
60
+ if(err) return callback(err);
69
61
 
70
- // direct module
71
- if(typeof data.source === "function")
72
- return callback(null, data);
62
+ // Ignored
63
+ if(!data) return callback();
73
64
 
74
- this.applyPluginsAsyncWaterfall("after-resolve", data, (err, result) => {
75
- if(err) return callback(err);
65
+ // direct module
66
+ if(typeof data.source === "function")
67
+ return callback(null, data);
76
68
 
77
- // Ignored
78
- if(!result) return callback();
69
+ this.applyPluginsAsyncWaterfall("after-resolve", data, (err, result) => {
70
+ if(err) return callback(err);
79
71
 
80
- let createdModule = this.applyPluginsBailResult("create-module", result);
81
- if(!createdModule) {
72
+ // Ignored
73
+ if(!result) return callback();
82
74
 
83
- if(!result.request) {
84
- return callback(new Error("Empty dependency (no request)"));
85
- }
75
+ let createdModule = this.applyPluginsBailResult("create-module", result);
76
+ if(!createdModule) {
86
77
 
87
- createdModule = new NormalModule(
88
- result.request,
89
- result.userRequest,
90
- result.rawRequest,
91
- result.loaders,
92
- result.resource,
93
- result.parser
94
- );
78
+ if(!result.request) {
79
+ return callback(new Error("Empty dependency (no request)"));
95
80
  }
96
81
 
97
- createdModule = this.applyPluginsWaterfall0("module", createdModule);
82
+ createdModule = new NormalModule(
83
+ result.request,
84
+ result.userRequest,
85
+ result.rawRequest,
86
+ result.loaders,
87
+ result.resource,
88
+ result.parser
89
+ );
90
+ }
98
91
 
99
- return callback(null, createdModule);
100
- });
92
+ createdModule = this.applyPluginsWaterfall0("module", createdModule);
93
+
94
+ return callback(null, createdModule);
101
95
  });
102
- };
96
+ });
103
97
  });
104
- this.plugin("resolver", function() {
105
- /* beautify preserve:start */
106
- // js-beautify consider to concat "return" and "("
107
- // but it сontradicts eslint rule (keyword-spacing)
108
- return (data, callback) => {
109
- /* beautify preserve:end */
110
- const contextInfo = data.contextInfo;
111
- const context = data.context;
112
- const request = data.request;
113
-
114
- const noAutoLoaders = /^-?!/.test(request);
115
- const noPrePostAutoLoaders = /^!!/.test(request);
116
- const noPostAutoLoaders = /^-!/.test(request);
117
- let elements = request.replace(/^-?!+/, "").replace(/!!+/g, "!").split("!");
118
- let resource = elements.pop();
119
- elements = elements.map(identToLoaderRequest);
120
-
121
- asyncLib.parallel([
122
- callback => this.resolveRequestArray(contextInfo, context, elements, this.resolvers.loader, callback),
123
- callback => {
124
- if(resource === "" || resource[0] === "?")
125
- return callback(null, {
126
- resource
127
- });
128
-
129
- this.resolvers.normal.resolve(contextInfo, context, resource, (err, resource, resourceResolveData) => {
130
- if(err) return callback(err);
131
- callback(null, {
132
- resourceResolveData,
133
- resource
134
- });
98
+ this.plugin("resolver", () => (data, callback) => {
99
+ const contextInfo = data.contextInfo;
100
+ const context = data.context;
101
+ const request = data.request;
102
+
103
+ const noAutoLoaders = /^-?!/.test(request);
104
+ const noPrePostAutoLoaders = /^!!/.test(request);
105
+ const noPostAutoLoaders = /^-!/.test(request);
106
+ let elements = request.replace(/^-?!+/, "").replace(/!!+/g, "!").split("!");
107
+ let resource = elements.pop();
108
+ elements = elements.map(identToLoaderRequest);
109
+
110
+ asyncLib.parallel([
111
+ callback => this.resolveRequestArray(contextInfo, context, elements, this.resolvers.loader, callback),
112
+ callback => {
113
+ if(resource === "" || resource[0] === "?")
114
+ return callback(null, {
115
+ resource
135
116
  });
136
- }
137
- ], (err, results) => {
138
- if(err) return callback(err);
139
- let loaders = results[0];
140
- const resourceResolveData = results[1].resourceResolveData;
141
- resource = results[1].resource;
142
-
143
- // translate option idents
144
- try {
145
- loaders.forEach(item => {
146
- if(typeof item.options === "string" && /^\?/.test(item.options)) {
147
- item.options = this.ruleSet.findOptionsByIdent(item.options.substr(1));
148
- }
117
+
118
+ this.resolvers.normal.resolve(contextInfo, context, resource, (err, resource, resourceResolveData) => {
119
+ if(err) return callback(err);
120
+ callback(null, {
121
+ resourceResolveData,
122
+ resource
149
123
  });
150
- } catch(e) {
151
- return callback(e);
152
- }
124
+ });
125
+ }
126
+ ], (err, results) => {
127
+ if(err) return callback(err);
128
+ let loaders = results[0];
129
+ const resourceResolveData = results[1].resourceResolveData;
130
+ resource = results[1].resource;
131
+
132
+ // translate option idents
133
+ try {
134
+ loaders.forEach(item => {
135
+ if(typeof item.options === "string" && /^\?/.test(item.options)) {
136
+ item.options = this.ruleSet.findOptionsByIdent(item.options.substr(1));
137
+ }
138
+ });
139
+ } catch(e) {
140
+ return callback(e);
141
+ }
153
142
 
154
- if(resource === false) {
155
- // ignored
156
- return callback(null,
157
- new RawModule(
158
- "/* (ignored) */",
159
- `ignored ${context} ${request}`,
160
- `${request} (ignored)`
161
- )
162
- );
163
- }
143
+ if(resource === false) {
144
+ // ignored
145
+ return callback(null,
146
+ new RawModule(
147
+ "/* (ignored) */",
148
+ `ignored ${context} ${request}`,
149
+ `${request} (ignored)`
150
+ )
151
+ );
152
+ }
164
153
 
165
- const userRequest = loaders.map(loaderToIdent).concat([resource]).join("!");
154
+ const userRequest = loaders.map(loaderToIdent).concat([resource]).join("!");
166
155
 
167
- let resourcePath = resource;
168
- let resourceQuery = "";
169
- const queryIndex = resourcePath.indexOf("?");
170
- if(queryIndex >= 0) {
171
- resourceQuery = resourcePath.substr(queryIndex);
172
- resourcePath = resourcePath.substr(0, queryIndex);
173
- }
156
+ let resourcePath = resource;
157
+ let resourceQuery = "";
158
+ const queryIndex = resourcePath.indexOf("?");
159
+ if(queryIndex >= 0) {
160
+ resourceQuery = resourcePath.substr(queryIndex);
161
+ resourcePath = resourcePath.substr(0, queryIndex);
162
+ }
174
163
 
175
- const result = this.ruleSet.exec({
176
- resource: resourcePath,
177
- resourceQuery,
178
- issuer: contextInfo.issuer,
179
- compiler: contextInfo.compiler
180
- });
181
- const settings = {};
182
- const useLoadersPost = [];
183
- const useLoaders = [];
184
- const useLoadersPre = [];
185
- result.forEach(r => {
186
- if(r.type === "use") {
187
- if(r.enforce === "post" && !noPostAutoLoaders && !noPrePostAutoLoaders)
188
- useLoadersPost.push(r.value);
189
- else if(r.enforce === "pre" && !noPrePostAutoLoaders)
190
- useLoadersPre.push(r.value);
191
- else if(!r.enforce && !noAutoLoaders && !noPrePostAutoLoaders)
192
- useLoaders.push(r.value);
193
- } else {
194
- settings[r.type] = r.value;
195
- }
196
- });
197
- asyncLib.parallel([
198
- this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPost, this.resolvers.loader),
199
- this.resolveRequestArray.bind(this, contextInfo, this.context, useLoaders, this.resolvers.loader),
200
- this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPre, this.resolvers.loader)
201
- ], (err, results) => {
202
- if(err) return callback(err);
203
- loaders = results[0].concat(loaders, results[1], results[2]);
204
- process.nextTick(() => {
205
- callback(null, {
206
- context: context,
207
- request: loaders.map(loaderToIdent).concat([resource]).join("!"),
208
- dependencies: data.dependencies,
209
- userRequest,
210
- rawRequest: request,
211
- loaders,
212
- resource,
213
- resourceResolveData,
214
- parser: this.getParser(settings.parser)
215
- });
164
+ const result = this.ruleSet.exec({
165
+ resource: resourcePath,
166
+ resourceQuery,
167
+ issuer: contextInfo.issuer,
168
+ compiler: contextInfo.compiler
169
+ });
170
+ const settings = {};
171
+ const useLoadersPost = [];
172
+ const useLoaders = [];
173
+ const useLoadersPre = [];
174
+ result.forEach(r => {
175
+ if(r.type === "use") {
176
+ if(r.enforce === "post" && !noPostAutoLoaders && !noPrePostAutoLoaders)
177
+ useLoadersPost.push(r.value);
178
+ else if(r.enforce === "pre" && !noPrePostAutoLoaders)
179
+ useLoadersPre.push(r.value);
180
+ else if(!r.enforce && !noAutoLoaders && !noPrePostAutoLoaders)
181
+ useLoaders.push(r.value);
182
+ } else {
183
+ settings[r.type] = r.value;
184
+ }
185
+ });
186
+ asyncLib.parallel([
187
+ this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPost, this.resolvers.loader),
188
+ this.resolveRequestArray.bind(this, contextInfo, this.context, useLoaders, this.resolvers.loader),
189
+ this.resolveRequestArray.bind(this, contextInfo, this.context, useLoadersPre, this.resolvers.loader)
190
+ ], (err, results) => {
191
+ if(err) return callback(err);
192
+ loaders = results[0].concat(loaders, results[1], results[2]);
193
+ process.nextTick(() => {
194
+ callback(null, {
195
+ context: context,
196
+ request: loaders.map(loaderToIdent).concat([resource]).join("!"),
197
+ dependencies: data.dependencies,
198
+ userRequest,
199
+ rawRequest: request,
200
+ loaders,
201
+ resource,
202
+ resourceResolveData,
203
+ parser: this.getParser(settings.parser)
216
204
  });
217
205
  });
218
206
  });
219
- };
207
+ });
220
208
  });
221
209
  }
222
210
 
package/lib/Parser.js CHANGED
@@ -214,19 +214,10 @@ class Parser extends Tapable {
214
214
  }
215
215
  }
216
216
  if(expr.argument.type === "MemberExpression") {
217
- let expression = expr.argument;
218
- let exprName = [];
219
- while(expression.type === "MemberExpression" && !expression.computed) {
220
- exprName.unshift(this.scope.renames["$" + expression.property.name] || expression.property.name);
221
- expression = expression.object;
222
- }
223
- if(expression.type === "Identifier") {
224
- exprName.unshift(this.scope.renames["$" + expression.name] || expression.name);
225
- if(this.scope.definitions.indexOf(name) === -1) {
226
- exprName = exprName.join(".");
227
- res = this.applyPluginsBailResult1("evaluate typeof " + exprName, expr);
228
- if(res !== undefined) return res;
229
- }
217
+ const exprName = this.getNameForExpression(expr.argument);
218
+ if(exprName && exprName.free) {
219
+ res = this.applyPluginsBailResult1("evaluate typeof " + exprName.name, expr);
220
+ if(res !== undefined) return res;
230
221
  }
231
222
  }
232
223
  if(expr.argument.type === "FunctionExpression") {
@@ -275,24 +266,14 @@ class Parser extends Tapable {
275
266
  }
276
267
  });
277
268
  this.plugin("evaluate MemberExpression", function(expression) {
278
- let expr = expression;
279
- let exprName = [];
280
- while(expr.type === "MemberExpression" && expr.property.type === (expr.computed ? "Literal" : "Identifier")) {
281
- exprName.unshift(expr.property.name || expr.property.value);
282
- expr = expr.object;
283
- }
284
- if(expr.type === "Identifier") {
285
- const name = this.scope.renames["$" + expr.name] || expr.name;
286
- if(this.scope.definitions.indexOf(name) === -1) {
287
- exprName.unshift(name);
288
- exprName = exprName.join(".");
289
- if(this.scope.definitions.indexOf(expr.name) === -1) {
290
- const result = this.applyPluginsBailResult1("evaluate Identifier " + exprName, expression);
291
- if(result) return result;
292
- return new BasicEvaluatedExpression().setIdentifier(exprName).setRange(expression.range);
293
- } else {
294
- return this.applyPluginsBailResult1("evaluate defined Identifier " + exprName, expression);
295
- }
269
+ let exprName = this.getNameForExpression(expression);
270
+ if(exprName) {
271
+ if(exprName.free) {
272
+ const result = this.applyPluginsBailResult1("evaluate Identifier " + exprName.name, expression);
273
+ if(result) return result;
274
+ return new BasicEvaluatedExpression().setIdentifier(exprName.name).setRange(expression.range);
275
+ } else {
276
+ return this.applyPluginsBailResult1("evaluate defined Identifier " + exprName.name, expression);
296
277
  }
297
278
  }
298
279
  });
@@ -970,16 +951,9 @@ class Parser extends Tapable {
970
951
 
971
952
  walkUnaryExpression(expression) {
972
953
  if(expression.operator === "typeof") {
973
- let expr = expression.argument;
974
- let exprName = [];
975
- while(expr.type === "MemberExpression" && expr.property.type === (expr.computed ? "Literal" : "Identifier")) {
976
- exprName.unshift(expr.property.name || expr.property.value);
977
- expr = expr.object;
978
- }
979
- if(expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) {
980
- exprName.unshift(this.scope.renames["$" + expr.name] || expr.name);
981
- exprName = exprName.join(".");
982
- const result = this.applyPluginsBailResult1("typeof " + exprName, expression);
954
+ const exprName = this.getNameForExpression(expression.argument);
955
+ if(exprName && exprName.free) {
956
+ const result = this.applyPluginsBailResult1("typeof " + exprName.name, expression);
983
957
  if(result === true)
984
958
  return;
985
959
  }
@@ -1128,7 +1102,7 @@ class Parser extends Tapable {
1128
1102
  result = this.applyPluginsBailResult1("call " + callee.identifier, expression);
1129
1103
  if(result === true)
1130
1104
  return;
1131
- let identifier = callee.identifier.replace(/\.[^\.]+$/, ".*");
1105
+ let identifier = callee.identifier.replace(/\.[^.]+$/, ".*");
1132
1106
  if(identifier !== callee.identifier) {
1133
1107
  result = this.applyPluginsBailResult1("call " + identifier, expression);
1134
1108
  if(result === true)
@@ -1144,24 +1118,12 @@ class Parser extends Tapable {
1144
1118
  }
1145
1119
 
1146
1120
  walkMemberExpression(expression) {
1147
- let expr = expression;
1148
- let exprName = [];
1149
- while(expr.type === "MemberExpression" && expr.property.type === (expr.computed ? "Literal" : "Identifier")) {
1150
- exprName.unshift(expr.property.name || expr.property.value);
1151
- expr = expr.object;
1152
- }
1153
- if((expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) ||
1154
- (expr.type === "ThisExpression" && this.scope.renames.$this)) {
1155
- if(expr.type === "ThisExpression") {
1156
- exprName.unshift(this.scope.renames.$this);
1157
- } else {
1158
- exprName.unshift(this.scope.renames["$" + expr.name] || expr.name);
1159
- }
1160
- let result = this.applyPluginsBailResult1("expression " + exprName.join("."), expression);
1121
+ const exprName = this.getNameForExpression(expression);
1122
+ if(exprName && exprName.free) {
1123
+ let result = this.applyPluginsBailResult1("expression " + exprName.name, expression);
1161
1124
  if(result === true)
1162
1125
  return;
1163
- exprName[exprName.length - 1] = "*";
1164
- result = this.applyPluginsBailResult1("expression " + exprName.join("."), expression);
1126
+ result = this.applyPluginsBailResult1("expression " + exprName.nameGeneral, expression);
1165
1127
  if(result === true)
1166
1128
  return;
1167
1129
  }
@@ -1430,6 +1392,38 @@ class Parser extends Tapable {
1430
1392
  return options.reduce((o, i) => Object.assign(o, i), {});
1431
1393
  }
1432
1394
 
1395
+ getNameForExpression(expression) {
1396
+ let expr = expression;
1397
+ const exprName = [];
1398
+ while(expr.type === "MemberExpression" && expr.property.type === (expr.computed ? "Literal" : "Identifier")) {
1399
+ exprName.push(expr.computed ? expr.property.value : expr.property.name);
1400
+ expr = expr.object;
1401
+ }
1402
+ let free;
1403
+ if(expr.type === "Identifier") {
1404
+ free = this.scope.definitions.indexOf(expr.name) === -1;
1405
+ exprName.push(this.scope.renames["$" + expr.name] || expr.name);
1406
+ } else if(expr.type === "ThisExpression" && this.scope.renames.$this) {
1407
+ free = true;
1408
+ exprName.push(this.scope.renames.$this);
1409
+ } else if(expr.type === "ThisExpression") {
1410
+ free = false;
1411
+ exprName.push("this");
1412
+ } else {
1413
+ return null;
1414
+ }
1415
+ let prefix = "";
1416
+ for(let i = exprName.length - 1; i >= 1; i--)
1417
+ prefix += exprName[i] + ".";
1418
+ const name = prefix + exprName[0];
1419
+ const nameGeneral = prefix + "*";
1420
+ return {
1421
+ name,
1422
+ nameGeneral,
1423
+ free
1424
+ };
1425
+ }
1426
+
1433
1427
  }
1434
1428
 
1435
1429
  Parser.ECMA_VERSION = ECMA_VERSION;
@@ -47,12 +47,12 @@ class RecordIdsPlugin {
47
47
  const p = block.parent;
48
48
  const idx = p.blocks.indexOf(block);
49
49
  const l = p.blocks.length - 1;
50
- ident.unshift(`${idx}/${l}`);
50
+ ident.push(`${idx}/${l}`);
51
51
  block = block.parent;
52
52
  }
53
53
  if(!block.identifier) return null;
54
- ident.unshift(identifierUtils.makePathsRelative(compiler.context, block.identifier()));
55
- return ident.join(":");
54
+ ident.push(identifierUtils.makePathsRelative(compiler.context, block.identifier()));
55
+ return ident.reverse().join(":");
56
56
  }
57
57
  compilation.plugin("record-chunks", (chunks, records) => {
58
58
  records.nextFreeChunkId = compilation.nextFreeChunkId;