webpack 2.3.3 → 2.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 (81) hide show
  1. package/README.md +148 -133
  2. package/lib/APIPlugin.js +0 -6
  3. package/lib/AsyncDependenciesBlock.js +1 -1
  4. package/lib/AutomaticPrefetchPlugin.js +2 -2
  5. package/lib/BannerPlugin.js +30 -8
  6. package/lib/CachePlugin.js +2 -2
  7. package/lib/CaseSensitiveModulesWarning.js +6 -3
  8. package/lib/ChunkRenderError.js +3 -1
  9. package/lib/ChunkTemplate.js +2 -2
  10. package/lib/Compilation.js +17 -17
  11. package/lib/Compiler.js +30 -25
  12. package/lib/ContextModule.js +4 -3
  13. package/lib/ContextModuleFactory.js +5 -5
  14. package/lib/DelegatedModule.js +69 -63
  15. package/lib/DependenciesBlock.js +65 -59
  16. package/lib/Dependency.js +1 -0
  17. package/lib/EntryModuleNotFoundError.js +16 -10
  18. package/lib/ExtendedAPIPlugin.js +7 -2
  19. package/lib/ExternalModule.js +1 -1
  20. package/lib/ExternalModuleFactoryPlugin.js +26 -23
  21. package/lib/FlagDependencyUsagePlugin.js +63 -75
  22. package/lib/HotModuleReplacement.runtime.js +25 -27
  23. package/lib/HotModuleReplacementPlugin.js +3 -5
  24. package/lib/IgnorePlugin.js +48 -17
  25. package/lib/JsonpChunkTemplatePlugin.js +24 -24
  26. package/lib/JsonpMainTemplatePlugin.js +182 -182
  27. package/lib/LibManifestPlugin.js +51 -46
  28. package/lib/MainTemplate.js +17 -18
  29. package/lib/Module.js +158 -160
  30. package/lib/ModuleBuildError.js +4 -2
  31. package/lib/ModuleDependencyError.js +2 -1
  32. package/lib/ModuleDependencyWarning.js +2 -1
  33. package/lib/ModuleError.js +2 -2
  34. package/lib/ModuleFilenameHelpers.js +27 -27
  35. package/lib/ModuleNotFoundError.js +3 -1
  36. package/lib/ModuleParseError.js +6 -4
  37. package/lib/ModuleWarning.js +2 -2
  38. package/lib/MultiCompiler.js +3 -4
  39. package/lib/MultiStats.js +3 -3
  40. package/lib/MultiWatching.js +2 -2
  41. package/lib/NamedChunksPlugin.js +30 -0
  42. package/lib/NodeStuffPlugin.js +80 -79
  43. package/lib/NormalModule.js +7 -3
  44. package/lib/NormalModuleFactory.js +244 -240
  45. package/lib/Parser.js +1256 -1079
  46. package/lib/ProgressPlugin.js +2 -2
  47. package/lib/RawModule.js +1 -1
  48. package/lib/RecordIdsPlugin.js +5 -9
  49. package/lib/SetVarMainTemplatePlugin.js +1 -1
  50. package/lib/SourceMapDevToolPlugin.js +153 -157
  51. package/lib/Stats.js +34 -6
  52. package/lib/TemplatedPathPlugin.js +1 -0
  53. package/lib/UnsupportedFeatureWarning.js +2 -1
  54. package/lib/WebpackError.js +11 -0
  55. package/lib/WebpackOptionsApply.js +4 -4
  56. package/lib/WebpackOptionsValidationError.js +2 -3
  57. package/lib/dependencies/AMDDefineDependency.js +10 -6
  58. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +8 -1
  59. package/lib/dependencies/AMDPlugin.js +3 -3
  60. package/lib/dependencies/ContextDependencyHelpers.js +19 -16
  61. package/lib/dependencies/CriticalDependencyWarning.js +4 -1
  62. package/lib/dependencies/DepBlockHelpers.js +3 -3
  63. package/lib/dependencies/HarmonyCompatibilityDependency.js +1 -1
  64. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +3 -3
  65. package/lib/dependencies/ImportContextDependency.js +2 -1
  66. package/lib/dependencies/ImportDependenciesBlock.js +2 -2
  67. package/lib/dependencies/ImportParserPlugin.js +16 -2
  68. package/lib/dependencies/RequireEnsureDependenciesBlock.js +11 -3
  69. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +42 -13
  70. package/lib/dependencies/RequireEnsureDependency.js +9 -2
  71. package/lib/formatLocation.js +44 -27
  72. package/lib/optimize/AggressiveSplittingPlugin.js +10 -17
  73. package/lib/optimize/CommonsChunkPlugin.js +2 -2
  74. package/lib/performance/AssetsOverSizeLimitWarning.js +4 -1
  75. package/lib/performance/EntrypointsOverSizeLimitWarning.js +5 -1
  76. package/lib/performance/NoAsyncChunksWarning.js +5 -1
  77. package/lib/removeAndDo.js +6 -4
  78. package/lib/util/identifier.js +16 -0
  79. package/lib/webpack.js +2 -1
  80. package/package.json +7 -4
  81. package/schemas/webpackOptionsSchema.json +35 -0
package/lib/Parser.js CHANGED
@@ -2,1213 +2,1390 @@
2
2
  MIT License http://www.opensource.org/licenses/mit-license.php
3
3
  Author Tobias Koppers @sokra
4
4
  */
5
- var acorn = require("acorn-dynamic-import").default;
6
- var Tapable = require("tapable");
7
- var BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
8
-
9
- function Parser(options) {
10
- Tapable.call(this);
11
- this.options = options;
12
- this.initializeEvaluating();
13
- }
14
- module.exports = Parser;
5
+ "use strict";
15
6
 
16
7
  // Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
17
8
 
18
- Parser.prototype = Object.create(Tapable.prototype);
19
- Parser.prototype.constructor = Parser;
20
-
21
- Parser.prototype.initializeEvaluating = function() {
22
- function joinRanges(startRange, endRange) {
23
- if(!endRange) return startRange;
24
- if(!startRange) return endRange;
25
- return [startRange[0], endRange[1]];
26
- }
27
- this.plugin("evaluate Literal", function(expr) {
28
- switch(typeof expr.value) {
29
- case "number":
30
- return new BasicEvaluatedExpression().setNumber(expr.value).setRange(expr.range);
31
- case "string":
32
- return new BasicEvaluatedExpression().setString(expr.value).setRange(expr.range);
33
- case "boolean":
34
- return new BasicEvaluatedExpression().setBoolean(expr.value).setRange(expr.range);
35
- }
36
- if(expr.value === null)
37
- return new BasicEvaluatedExpression().setNull().setRange(expr.range);
38
- if(expr.value instanceof RegExp)
39
- return new BasicEvaluatedExpression().setRegExp(expr.value).setRange(expr.range);
40
- });
41
- this.plugin("evaluate LogicalExpression", function(expr) {
42
- var left;
43
- var leftAsBool;
44
- var right;
45
- if(expr.operator === "&&") {
46
- left = this.evaluateExpression(expr.left);
47
- leftAsBool = left && left.asBool();
48
- if(leftAsBool === false) return left.setRange(expr.range);
49
- if(leftAsBool !== true) return;
50
- right = this.evaluateExpression(expr.right);
51
- return right.setRange(expr.range);
52
- } else if(expr.operator === "||") {
53
- left = this.evaluateExpression(expr.left);
54
- leftAsBool = left && left.asBool();
55
- if(leftAsBool === true) return left.setRange(expr.range);
56
- if(leftAsBool !== false) return;
57
- right = this.evaluateExpression(expr.right);
58
- return right.setRange(expr.range);
59
- }
60
- });
61
- this.plugin("evaluate BinaryExpression", function(expr) {
62
- var left;
63
- var right;
64
- var res;
65
- if(expr.operator === "+") {
66
- left = this.evaluateExpression(expr.left);
67
- right = this.evaluateExpression(expr.right);
68
- if(!left || !right) return;
69
- res = new BasicEvaluatedExpression();
70
- if(left.isString()) {
71
- if(right.isString()) {
72
- res.setString(left.string + right.string);
73
- } else if(right.isNumber()) {
74
- res.setString(left.string + right.number);
75
- } else if(right.isWrapped() && right.prefix && right.prefix.isString()) {
76
- res.setWrapped(
77
- new BasicEvaluatedExpression()
78
- .setString(left.string + right.prefix.string)
79
- .setRange(joinRanges(left.range, right.prefix.range)),
80
- right.postfix);
81
- } else {
82
- res.setWrapped(left, null);
83
- }
84
- } else if(left.isNumber()) {
85
- if(right.isString()) {
86
- res.setString(left.number + right.string);
87
- } else if(right.isNumber()) {
88
- res.setNumber(left.number + right.number);
89
- }
90
- } else if(left.isWrapped()) {
91
- if(left.postfix && left.postfix.isString() && right.isString()) {
92
- res.setWrapped(left.prefix,
93
- new BasicEvaluatedExpression()
94
- .setString(left.postfix.string + right.string)
95
- .setRange(joinRanges(left.postfix.range, right.range))
96
- );
97
- } else if(left.postfix && left.postfix.isString() && right.isNumber()) {
98
- res.setWrapped(left.prefix,
99
- new BasicEvaluatedExpression()
100
- .setString(left.postfix.string + right.number)
101
- .setRange(joinRanges(left.postfix.range, right.range))
102
- );
103
- } else if(right.isString()) {
104
- res.setWrapped(left.prefix, right);
105
- } else if(right.isNumber()) {
106
- res.setWrapped(left.prefix,
107
- new BasicEvaluatedExpression()
108
- .setString(right.number + "")
109
- .setRange(right.range));
9
+ const acorn = require("acorn-dynamic-import").default;
10
+ const Tapable = require("tapable");
11
+ const json5 = require("json5");
12
+ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
13
+
14
+ function joinRanges(startRange, endRange) {
15
+ if(!endRange) return startRange;
16
+ if(!startRange) return endRange;
17
+ return [startRange[0], endRange[1]];
18
+ }
19
+
20
+ const POSSIBLE_AST_OPTIONS = [{
21
+ ranges: true,
22
+ locations: true,
23
+ ecmaVersion: 2017,
24
+ sourceType: "module",
25
+ plugins: {
26
+ dynamicImport: true
27
+ }
28
+ }, {
29
+ ranges: true,
30
+ locations: true,
31
+ ecmaVersion: 2017,
32
+ sourceType: "script",
33
+ plugins: {
34
+ dynamicImport: true
35
+ }
36
+ }];
37
+
38
+ class Parser extends Tapable {
39
+ constructor(options) {
40
+ super();
41
+ this.options = options;
42
+ this.scope = undefined;
43
+ this.state = undefined;
44
+ this.comments = undefined;
45
+ this.initializeEvaluating();
46
+ }
47
+
48
+ initializeEvaluating() {
49
+ this.plugin("evaluate Literal", expr => {
50
+ switch(typeof expr.value) {
51
+ case "number":
52
+ return new BasicEvaluatedExpression().setNumber(expr.value).setRange(expr.range);
53
+ case "string":
54
+ return new BasicEvaluatedExpression().setString(expr.value).setRange(expr.range);
55
+ case "boolean":
56
+ return new BasicEvaluatedExpression().setBoolean(expr.value).setRange(expr.range);
57
+ }
58
+ if(expr.value === null)
59
+ return new BasicEvaluatedExpression().setNull().setRange(expr.range);
60
+ if(expr.value instanceof RegExp)
61
+ return new BasicEvaluatedExpression().setRegExp(expr.value).setRange(expr.range);
62
+ });
63
+ this.plugin("evaluate LogicalExpression", function(expr) {
64
+ let left;
65
+ let leftAsBool;
66
+ let right;
67
+ if(expr.operator === "&&") {
68
+ left = this.evaluateExpression(expr.left);
69
+ leftAsBool = left && left.asBool();
70
+ if(leftAsBool === false) return left.setRange(expr.range);
71
+ if(leftAsBool !== true) return;
72
+ right = this.evaluateExpression(expr.right);
73
+ return right.setRange(expr.range);
74
+ } else if(expr.operator === "||") {
75
+ left = this.evaluateExpression(expr.left);
76
+ leftAsBool = left && left.asBool();
77
+ if(leftAsBool === true) return left.setRange(expr.range);
78
+ if(leftAsBool !== false) return;
79
+ right = this.evaluateExpression(expr.right);
80
+ return right.setRange(expr.range);
81
+ }
82
+ });
83
+ this.plugin("evaluate BinaryExpression", function(expr) {
84
+ let left;
85
+ let right;
86
+ let res;
87
+ if(expr.operator === "+") {
88
+ left = this.evaluateExpression(expr.left);
89
+ right = this.evaluateExpression(expr.right);
90
+ if(!left || !right) return;
91
+ res = new BasicEvaluatedExpression();
92
+ if(left.isString()) {
93
+ if(right.isString()) {
94
+ res.setString(left.string + right.string);
95
+ } else if(right.isNumber()) {
96
+ res.setString(left.string + right.number);
97
+ } else if(right.isWrapped() && right.prefix && right.prefix.isString()) {
98
+ res.setWrapped(
99
+ new BasicEvaluatedExpression()
100
+ .setString(left.string + right.prefix.string)
101
+ .setRange(joinRanges(left.range, right.prefix.range)),
102
+ right.postfix);
103
+ } else if(right.isWrapped()) {
104
+ res.setWrapped(
105
+ new BasicEvaluatedExpression()
106
+ .setString(left.string)
107
+ .setRange(left.range),
108
+ right.postfix);
109
+ } else {
110
+ res.setWrapped(left, null);
111
+ }
112
+ } else if(left.isNumber()) {
113
+ if(right.isString()) {
114
+ res.setString(left.number + right.string);
115
+ } else if(right.isNumber()) {
116
+ res.setNumber(left.number + right.number);
117
+ }
118
+ } else if(left.isWrapped()) {
119
+ if(left.postfix && left.postfix.isString() && right.isString()) {
120
+ res.setWrapped(left.prefix,
121
+ new BasicEvaluatedExpression()
122
+ .setString(left.postfix.string + right.string)
123
+ .setRange(joinRanges(left.postfix.range, right.range))
124
+ );
125
+ } else if(left.postfix && left.postfix.isString() && right.isNumber()) {
126
+ res.setWrapped(left.prefix,
127
+ new BasicEvaluatedExpression()
128
+ .setString(left.postfix.string + right.number)
129
+ .setRange(joinRanges(left.postfix.range, right.range))
130
+ );
131
+ } else if(right.isString()) {
132
+ res.setWrapped(left.prefix, right);
133
+ } else if(right.isNumber()) {
134
+ res.setWrapped(left.prefix,
135
+ new BasicEvaluatedExpression()
136
+ .setString(right.number + "")
137
+ .setRange(right.range));
138
+ } else {
139
+ res.setWrapped(left.prefix, new BasicEvaluatedExpression());
140
+ }
110
141
  } else {
111
- res.setWrapped(left.prefix, new BasicEvaluatedExpression());
142
+ if(right.isString()) {
143
+ res.setWrapped(null, right);
144
+ }
112
145
  }
113
- } else {
114
- if(right.isString()) {
115
- res.setWrapped(null, right);
146
+ res.setRange(expr.range);
147
+ return res;
148
+ } else if(expr.operator === "-") {
149
+ left = this.evaluateExpression(expr.left);
150
+ right = this.evaluateExpression(expr.right);
151
+ if(!left || !right) return;
152
+ if(!left.isNumber() || !right.isNumber()) return;
153
+ res = new BasicEvaluatedExpression();
154
+ res.setNumber(left.number - right.number);
155
+ res.setRange(expr.range);
156
+ return res;
157
+ } else if(expr.operator === "*") {
158
+ left = this.evaluateExpression(expr.left);
159
+ right = this.evaluateExpression(expr.right);
160
+ if(!left || !right) return;
161
+ if(!left.isNumber() || !right.isNumber()) return;
162
+ res = new BasicEvaluatedExpression();
163
+ res.setNumber(left.number * right.number);
164
+ res.setRange(expr.range);
165
+ return res;
166
+ } else if(expr.operator === "/") {
167
+ left = this.evaluateExpression(expr.left);
168
+ right = this.evaluateExpression(expr.right);
169
+ if(!left || !right) return;
170
+ if(!left.isNumber() || !right.isNumber()) return;
171
+ res = new BasicEvaluatedExpression();
172
+ res.setNumber(left.number / right.number);
173
+ res.setRange(expr.range);
174
+ return res;
175
+ } else if(expr.operator === "==" || expr.operator === "===") {
176
+ left = this.evaluateExpression(expr.left);
177
+ right = this.evaluateExpression(expr.right);
178
+ if(!left || !right) return;
179
+ res = new BasicEvaluatedExpression();
180
+ res.setRange(expr.range);
181
+ if(left.isString() && right.isString()) {
182
+ return res.setBoolean(left.string === right.string);
183
+ } else if(left.isNumber() && right.isNumber()) {
184
+ return res.setBoolean(left.number === right.number);
185
+ } else if(left.isBoolean() && right.isBoolean()) {
186
+ return res.setBoolean(left.bool === right.bool);
116
187
  }
117
- }
118
- res.setRange(expr.range);
119
- return res;
120
- } else if(expr.operator === "-") {
121
- left = this.evaluateExpression(expr.left);
122
- right = this.evaluateExpression(expr.right);
123
- if(!left || !right) return;
124
- if(!left.isNumber() || !right.isNumber()) return;
125
- res = new BasicEvaluatedExpression();
126
- res.setNumber(left.number - right.number);
127
- res.setRange(expr.range);
128
- return res;
129
- } else if(expr.operator === "*") {
130
- left = this.evaluateExpression(expr.left);
131
- right = this.evaluateExpression(expr.right);
132
- if(!left || !right) return;
133
- if(!left.isNumber() || !right.isNumber()) return;
134
- res = new BasicEvaluatedExpression();
135
- res.setNumber(left.number * right.number);
136
- res.setRange(expr.range);
137
- return res;
138
- } else if(expr.operator === "/") {
139
- left = this.evaluateExpression(expr.left);
140
- right = this.evaluateExpression(expr.right);
141
- if(!left || !right) return;
142
- if(!left.isNumber() || !right.isNumber()) return;
143
- res = new BasicEvaluatedExpression();
144
- res.setNumber(left.number / right.number);
145
- res.setRange(expr.range);
146
- return res;
147
- } else if(expr.operator === "==" || expr.operator === "===") {
148
- left = this.evaluateExpression(expr.left);
149
- right = this.evaluateExpression(expr.right);
150
- if(!left || !right) return;
151
- res = new BasicEvaluatedExpression();
152
- res.setRange(expr.range);
153
- if(left.isString() && right.isString()) {
154
- return res.setBoolean(left.string === right.string);
155
- } else if(left.isNumber() && right.isNumber()) {
156
- return res.setBoolean(left.number === right.number);
157
- } else if(left.isBoolean() && right.isBoolean()) {
158
- return res.setBoolean(left.bool === right.bool);
159
- }
160
- } else if(expr.operator === "!=" || expr.operator === "!==") {
161
- left = this.evaluateExpression(expr.left);
162
- right = this.evaluateExpression(expr.right);
163
- if(!left || !right) return;
164
- res = new BasicEvaluatedExpression();
165
- res.setRange(expr.range);
166
- if(left.isString() && right.isString()) {
167
- return res.setBoolean(left.string !== right.string);
168
- } else if(left.isNumber() && right.isNumber()) {
169
- return res.setBoolean(left.number !== right.number);
170
- } else if(left.isBoolean() && right.isBoolean()) {
171
- return res.setBoolean(left.bool !== right.bool);
172
- }
173
- }
174
- });
175
- this.plugin("evaluate UnaryExpression", function(expr) {
176
- if(expr.operator === "typeof") {
177
- var res;
178
- if(expr.argument.type === "Identifier") {
179
- var name = this.scope.renames["$" + expr.argument.name] || expr.argument.name;
180
- if(this.scope.definitions.indexOf(name) === -1) {
181
- res = this.applyPluginsBailResult1("evaluate typeof " + name, expr);
182
- if(res !== undefined) return res;
188
+ } else if(expr.operator === "!=" || expr.operator === "!==") {
189
+ left = this.evaluateExpression(expr.left);
190
+ right = this.evaluateExpression(expr.right);
191
+ if(!left || !right) return;
192
+ res = new BasicEvaluatedExpression();
193
+ res.setRange(expr.range);
194
+ if(left.isString() && right.isString()) {
195
+ return res.setBoolean(left.string !== right.string);
196
+ } else if(left.isNumber() && right.isNumber()) {
197
+ return res.setBoolean(left.number !== right.number);
198
+ } else if(left.isBoolean() && right.isBoolean()) {
199
+ return res.setBoolean(left.bool !== right.bool);
183
200
  }
184
201
  }
185
- if(expr.argument.type === "MemberExpression") {
186
- var expression = expr.argument;
187
- var exprName = [];
188
- while(expression.type === "MemberExpression" && !expression.computed) {
189
- exprName.unshift(this.scope.renames["$" + expression.property.name] || expression.property.name);
190
- expression = expression.object;
191
- }
192
- if(expression.type === "Identifier") {
193
- exprName.unshift(this.scope.renames["$" + expression.name] || expression.name);
202
+ });
203
+ this.plugin("evaluate UnaryExpression", function(expr) {
204
+ if(expr.operator === "typeof") {
205
+ let res;
206
+ let name;
207
+ if(expr.argument.type === "Identifier") {
208
+ name = this.scope.renames["$" + expr.argument.name] || expr.argument.name;
194
209
  if(this.scope.definitions.indexOf(name) === -1) {
195
- exprName = exprName.join(".");
196
- res = this.applyPluginsBailResult1("evaluate typeof " + exprName, expr);
210
+ res = this.applyPluginsBailResult1("evaluate typeof " + name, expr);
197
211
  if(res !== undefined) return res;
198
212
  }
199
213
  }
214
+ if(expr.argument.type === "MemberExpression") {
215
+ let expression = expr.argument;
216
+ let exprName = [];
217
+ while(expression.type === "MemberExpression" && !expression.computed) {
218
+ exprName.unshift(this.scope.renames["$" + expression.property.name] || expression.property.name);
219
+ expression = expression.object;
220
+ }
221
+ if(expression.type === "Identifier") {
222
+ exprName.unshift(this.scope.renames["$" + expression.name] || expression.name);
223
+ if(this.scope.definitions.indexOf(name) === -1) {
224
+ exprName = exprName.join(".");
225
+ res = this.applyPluginsBailResult1("evaluate typeof " + exprName, expr);
226
+ if(res !== undefined) return res;
227
+ }
228
+ }
229
+ }
230
+ if(expr.argument.type === "FunctionExpression") {
231
+ return new BasicEvaluatedExpression().setString("function").setRange(expr.range);
232
+ }
233
+ const arg = this.evaluateExpression(expr.argument);
234
+ if(arg.isString() || arg.isWrapped()) return new BasicEvaluatedExpression().setString("string").setRange(expr.range);
235
+ else if(arg.isNumber()) return new BasicEvaluatedExpression().setString("number").setRange(expr.range);
236
+ else if(arg.isBoolean()) return new BasicEvaluatedExpression().setString("boolean").setRange(expr.range);
237
+ else if(arg.isArray() || arg.isConstArray() || arg.isRegExp()) return new BasicEvaluatedExpression().setString("object").setRange(expr.range);
238
+ } else if(expr.operator === "!") {
239
+ const argument = this.evaluateExpression(expr.argument);
240
+ if(!argument) return;
241
+ if(argument.isBoolean()) {
242
+ return new BasicEvaluatedExpression().setBoolean(!argument.bool).setRange(expr.range);
243
+ } else if(argument.isString()) {
244
+ return new BasicEvaluatedExpression().setBoolean(!argument.string).setRange(expr.range);
245
+ } else if(argument.isNumber()) {
246
+ return new BasicEvaluatedExpression().setBoolean(!argument.number).setRange(expr.range);
247
+ }
200
248
  }
201
- if(expr.argument.type === "FunctionExpression") {
202
- return new BasicEvaluatedExpression().setString("function").setRange(expr.range);
249
+ });
250
+ this.plugin("evaluate typeof undefined", function(expr) {
251
+ return new BasicEvaluatedExpression().setString("undefined").setRange(expr.range);
252
+ });
253
+ this.plugin("evaluate Identifier", function(expr) {
254
+ const name = this.scope.renames["$" + expr.name] || expr.name;
255
+ if(this.scope.definitions.indexOf(expr.name) === -1) {
256
+ const result = this.applyPluginsBailResult1("evaluate Identifier " + name, expr);
257
+ if(result) return result;
258
+ return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range);
259
+ } else {
260
+ return this.applyPluginsBailResult1("evaluate defined Identifier " + name, expr);
203
261
  }
204
- var arg = this.evaluateExpression(expr.argument);
205
- if(arg.isString() || arg.isWrapped()) return new BasicEvaluatedExpression().setString("string").setRange(expr.range);
206
- else if(arg.isNumber()) return new BasicEvaluatedExpression().setString("number").setRange(expr.range);
207
- else if(arg.isBoolean()) return new BasicEvaluatedExpression().setString("boolean").setRange(expr.range);
208
- else if(arg.isArray() || arg.isConstArray() || arg.isRegExp()) return new BasicEvaluatedExpression().setString("object").setRange(expr.range);
209
- } else if(expr.operator === "!") {
210
- var argument = this.evaluateExpression(expr.argument);
211
- if(!argument) return;
212
- if(argument.isBoolean()) {
213
- return new BasicEvaluatedExpression().setBoolean(!argument.bool).setRange(expr.range);
214
- } else if(argument.isString()) {
215
- return new BasicEvaluatedExpression().setBoolean(!argument.string).setRange(expr.range);
216
- } else if(argument.isNumber()) {
217
- return new BasicEvaluatedExpression().setBoolean(!argument.number).setRange(expr.range);
262
+ });
263
+ this.plugin("evaluate MemberExpression", function(expression) {
264
+ let expr = expression;
265
+ let exprName = [];
266
+ while(expr.type === "MemberExpression" && expr.property.type === (expr.computed ? "Literal" : "Identifier")) {
267
+ exprName.unshift(expr.property.name || expr.property.value);
268
+ expr = expr.object;
218
269
  }
219
- }
220
- });
221
- this.plugin("evaluate typeof undefined", function(expr) {
222
- return new BasicEvaluatedExpression().setString("undefined").setRange(expr.range);
223
- });
224
- this.plugin("evaluate Identifier", function(expr) {
225
- var name = this.scope.renames["$" + expr.name] || expr.name;
226
- if(this.scope.definitions.indexOf(expr.name) === -1) {
227
- var result = this.applyPluginsBailResult1("evaluate Identifier " + name, expr);
228
- if(result) return result;
229
- return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range);
230
- } else {
231
- return this.applyPluginsBailResult1("evaluate defined Identifier " + name, expr);
232
- }
233
- });
234
- this.plugin("evaluate MemberExpression", function(expression) {
235
- var expr = expression;
236
- var exprName = [];
237
- while(expr.type === "MemberExpression" &&
238
- expr.property.type === (expr.computed ? "Literal" : "Identifier")
239
- ) {
240
- exprName.unshift(expr.property.name || expr.property.value);
241
- expr = expr.object;
242
- }
243
- if(expr.type === "Identifier") {
244
- var name = this.scope.renames["$" + expr.name] || expr.name;
245
- if(this.scope.definitions.indexOf(name) === -1) {
246
- exprName.unshift(name);
247
- exprName = exprName.join(".");
248
- if(this.scope.definitions.indexOf(expr.name) === -1) {
249
- var result = this.applyPluginsBailResult1("evaluate Identifier " + exprName, expression);
250
- if(result) return result;
251
- return new BasicEvaluatedExpression().setIdentifier(exprName).setRange(expression.range);
252
- } else {
253
- return this.applyPluginsBailResult1("evaluate defined Identifier " + exprName, expression);
270
+ if(expr.type === "Identifier") {
271
+ const name = this.scope.renames["$" + expr.name] || expr.name;
272
+ if(this.scope.definitions.indexOf(name) === -1) {
273
+ exprName.unshift(name);
274
+ exprName = exprName.join(".");
275
+ if(this.scope.definitions.indexOf(expr.name) === -1) {
276
+ const result = this.applyPluginsBailResult1("evaluate Identifier " + exprName, expression);
277
+ if(result) return result;
278
+ return new BasicEvaluatedExpression().setIdentifier(exprName).setRange(expression.range);
279
+ } else {
280
+ return this.applyPluginsBailResult1("evaluate defined Identifier " + exprName, expression);
281
+ }
254
282
  }
255
283
  }
256
- }
257
- });
258
- this.plugin("evaluate CallExpression", function(expr) {
259
- if(expr.callee.type !== "MemberExpression") return;
260
- if(expr.callee.property.type !== (expr.callee.computed ? "Literal" : "Identifier")) return;
261
- var param = this.evaluateExpression(expr.callee.object);
262
- if(!param) return;
263
- var property = expr.callee.property.name || expr.callee.property.value;
264
- return this.applyPluginsBailResult("evaluate CallExpression ." + property, expr, param);
265
- });
266
- this.plugin("evaluate CallExpression .replace", function(expr, param) {
267
- if(!param.isString()) return;
268
- if(expr.arguments.length !== 2) return;
269
- var arg1 = this.evaluateExpression(expr.arguments[0]);
270
- var arg2 = this.evaluateExpression(expr.arguments[1]);
271
- if(!arg1.isString() && !arg1.isRegExp()) return;
272
- arg1 = arg1.regExp || arg1.string;
273
- if(!arg2.isString()) return;
274
- arg2 = arg2.string;
275
- return new BasicEvaluatedExpression().setString(param.string.replace(arg1, arg2)).setRange(expr.range);
276
- });
277
- ["substr", "substring"].forEach(function(fn) {
278
- this.plugin("evaluate CallExpression ." + fn, function(expr, param) {
284
+ });
285
+ this.plugin("evaluate CallExpression", function(expr) {
286
+ if(expr.callee.type !== "MemberExpression") return;
287
+ if(expr.callee.property.type !== (expr.callee.computed ? "Literal" : "Identifier")) return;
288
+ const param = this.evaluateExpression(expr.callee.object);
289
+ if(!param) return;
290
+ const property = expr.callee.property.name || expr.callee.property.value;
291
+ return this.applyPluginsBailResult("evaluate CallExpression ." + property, expr, param);
292
+ });
293
+ this.plugin("evaluate CallExpression .replace", function(expr, param) {
279
294
  if(!param.isString()) return;
280
- var arg1;
281
- var result, str = param.string;
282
- switch(expr.arguments.length) {
283
- case 1:
284
- arg1 = this.evaluateExpression(expr.arguments[0]);
285
- if(!arg1.isNumber()) return;
286
- result = str[fn](arg1.number);
287
- break;
288
- case 2:
289
- arg1 = this.evaluateExpression(expr.arguments[0]);
290
- var arg2 = this.evaluateExpression(expr.arguments[1]);
291
- if(!arg1.isNumber()) return;
292
- if(!arg2.isNumber()) return;
293
- result = str[fn](arg1.number, arg2.number);
294
- break;
295
- default:
296
- return;
297
- }
298
- return new BasicEvaluatedExpression().setString(result).setRange(expr.range);
295
+ if(expr.arguments.length !== 2) return;
296
+ let arg1 = this.evaluateExpression(expr.arguments[0]);
297
+ let arg2 = this.evaluateExpression(expr.arguments[1]);
298
+ if(!arg1.isString() && !arg1.isRegExp()) return;
299
+ arg1 = arg1.regExp || arg1.string;
300
+ if(!arg2.isString()) return;
301
+ arg2 = arg2.string;
302
+ return new BasicEvaluatedExpression().setString(param.string.replace(arg1, arg2)).setRange(expr.range);
299
303
  });
304
+ ["substr", "substring"].forEach(fn => {
305
+ this.plugin("evaluate CallExpression ." + fn, function(expr, param) {
306
+ if(!param.isString()) return;
307
+ let arg1;
308
+ let result, str = param.string;
309
+ switch(expr.arguments.length) {
310
+ case 1:
311
+ arg1 = this.evaluateExpression(expr.arguments[0]);
312
+ if(!arg1.isNumber()) return;
313
+ result = str[fn](arg1.number);
314
+ break;
315
+ case 2:
316
+ {
317
+ arg1 = this.evaluateExpression(expr.arguments[0]);
318
+ const arg2 = this.evaluateExpression(expr.arguments[1]);
319
+ if(!arg1.isNumber()) return;
320
+ if(!arg2.isNumber()) return;
321
+ result = str[fn](arg1.number, arg2.number);
322
+ break;
323
+ }
324
+ default:
325
+ return;
326
+ }
327
+ return new BasicEvaluatedExpression().setString(result).setRange(expr.range);
328
+ });
300
329
 
301
- /**
302
- * @param {string} kind "cooked" | "raw"
303
- * @param {any[]} quasis quasis
304
- * @param {any[]} expressions expressions
305
- * @return {BasicEvaluatedExpression[]} Simplified template
306
- */
307
- function getSimplifiedTemplateResult(kind, quasis, expressions) {
308
- var i = 0;
309
- var parts = [];
310
-
311
- for(i = 0; i < quasis.length; i++) {
312
- parts.push(new BasicEvaluatedExpression().setString(quasis[i].value[kind]).setRange(quasis[i].range));
313
-
314
- if(i > 0) {
315
- var prevExpr = parts[parts.length - 2],
316
- lastExpr = parts[parts.length - 1];
317
- var expr = this.evaluateExpression(expressions[i - 1]);
318
- if(!(expr.isString() || expr.isNumber())) continue;
319
-
320
- prevExpr.setString(prevExpr.string + (expr.isString() ? expr.string : expr.number) + lastExpr.string);
321
- prevExpr.setRange([prevExpr.range[0], lastExpr.range[1]]);
322
- parts.pop();
330
+ /**
331
+ * @param {string} kind "cooked" | "raw"
332
+ * @param {any[]} quasis quasis
333
+ * @param {any[]} expressions expressions
334
+ * @return {BasicEvaluatedExpression[]} Simplified template
335
+ */
336
+ function getSimplifiedTemplateResult(kind, quasis, expressions) {
337
+ const parts = [];
338
+
339
+ for(let i = 0; i < quasis.length; i++) {
340
+ parts.push(new BasicEvaluatedExpression().setString(quasis[i].value[kind]).setRange(quasis[i].range));
341
+
342
+ if(i > 0) {
343
+ const prevExpr = parts[parts.length - 2],
344
+ lastExpr = parts[parts.length - 1];
345
+ const expr = this.evaluateExpression(expressions[i - 1]);
346
+ if(!(expr.isString() || expr.isNumber())) continue;
347
+
348
+ prevExpr.setString(prevExpr.string + (expr.isString() ? expr.string : expr.number) + lastExpr.string);
349
+ prevExpr.setRange([prevExpr.range[0], lastExpr.range[1]]);
350
+ parts.pop();
351
+ }
323
352
  }
353
+ return parts;
324
354
  }
325
- return parts;
326
- }
327
355
 
328
- this.plugin("evaluate TemplateLiteral", function(node) {
329
- var parts = getSimplifiedTemplateResult.call(this, "cooked", node.quasis, node.expressions);
330
- if(parts.length === 1) {
331
- return parts[0].setRange(node.range);
356
+ this.plugin("evaluate TemplateLiteral", function(node) {
357
+ const parts = getSimplifiedTemplateResult.call(this, "cooked", node.quasis, node.expressions);
358
+ if(parts.length === 1) {
359
+ return parts[0].setRange(node.range);
360
+ }
361
+ return new BasicEvaluatedExpression().setTemplateString(parts).setRange(node.range);
362
+ });
363
+ this.plugin("evaluate TaggedTemplateExpression", function(node) {
364
+ if(this.evaluateExpression(node.tag).identifier !== "String.raw") return;
365
+ const parts = getSimplifiedTemplateResult.call(this, "raw", node.quasi.quasis, node.quasi.expressions);
366
+ return new BasicEvaluatedExpression().setTemplateString(parts).setRange(node.range);
367
+ });
368
+ });
369
+ this.plugin("evaluate CallExpression .split", function(expr, param) {
370
+ if(!param.isString()) return;
371
+ if(expr.arguments.length !== 1) return;
372
+ let result;
373
+ const arg = this.evaluateExpression(expr.arguments[0]);
374
+ if(arg.isString()) {
375
+ result = param.string.split(arg.string);
376
+ } else if(arg.isRegExp()) {
377
+ result = param.string.split(arg.regExp);
378
+ } else return;
379
+ return new BasicEvaluatedExpression().setArray(result).setRange(expr.range);
380
+ });
381
+ this.plugin("evaluate ConditionalExpression", function(expr) {
382
+ const condition = this.evaluateExpression(expr.test);
383
+ const conditionValue = condition.asBool();
384
+ let res;
385
+ if(conditionValue === undefined) {
386
+ const consequent = this.evaluateExpression(expr.consequent);
387
+ const alternate = this.evaluateExpression(expr.alternate);
388
+ if(!consequent || !alternate) return;
389
+ res = new BasicEvaluatedExpression();
390
+ if(consequent.isConditional())
391
+ res.setOptions(consequent.options);
392
+ else
393
+ res.setOptions([consequent]);
394
+ if(alternate.isConditional())
395
+ res.addOptions(alternate.options);
396
+ else
397
+ res.addOptions([alternate]);
398
+ } else {
399
+ res = this.evaluateExpression(conditionValue ? expr.consequent : expr.alternate);
332
400
  }
333
- return new BasicEvaluatedExpression().setTemplateString(parts).setRange(node.range);
401
+ res.setRange(expr.range);
402
+ return res;
334
403
  });
335
- this.plugin("evaluate TaggedTemplateExpression", function(node) {
336
- if(this.evaluateExpression(node.tag).identifier !== "String.raw") return;
337
- var parts = getSimplifiedTemplateResult.call(this, "raw", node.quasi.quasis, node.quasi.expressions);
338
- return new BasicEvaluatedExpression().setTemplateString(parts).setRange(node.range);
404
+ this.plugin("evaluate ArrayExpression", function(expr) {
405
+ const items = expr.elements.map(function(element) {
406
+ return element !== null && this.evaluateExpression(element);
407
+ }, this);
408
+ if(!items.every(Boolean)) return;
409
+ return new BasicEvaluatedExpression().setItems(items).setRange(expr.range);
339
410
  });
340
- }, this);
341
- this.plugin("evaluate CallExpression .split", function(expr, param) {
342
- if(!param.isString()) return;
343
- if(expr.arguments.length !== 1) return;
344
- var result;
345
- var arg = this.evaluateExpression(expr.arguments[0]);
346
- if(arg.isString()) {
347
- result = param.string.split(arg.string);
348
- } else if(arg.isRegExp()) {
349
- result = param.string.split(arg.regExp);
350
- } else return;
351
- return new BasicEvaluatedExpression().setArray(result).setRange(expr.range);
352
- });
353
- this.plugin("evaluate ConditionalExpression", function(expr) {
354
- var condition = this.evaluateExpression(expr.test);
355
- var conditionValue = condition.asBool();
356
- var res;
357
- if(conditionValue === undefined) {
358
- var consequent = this.evaluateExpression(expr.consequent);
359
- var alternate = this.evaluateExpression(expr.alternate);
360
- if(!consequent || !alternate) return;
361
- res = new BasicEvaluatedExpression();
362
- if(consequent.isConditional())
363
- res.setOptions(consequent.options);
364
- else
365
- res.setOptions([consequent]);
366
- if(alternate.isConditional())
367
- res.addOptions(alternate.options);
368
- else
369
- res.addOptions([alternate]);
370
- } else {
371
- res = this.evaluateExpression(conditionValue ? expr.consequent : expr.alternate);
411
+ }
412
+
413
+ getRenameIdentifier(expr) {
414
+ const result = this.evaluateExpression(expr);
415
+ if(!result) return;
416
+ if(result.isIdentifier()) return result.identifier;
417
+ return;
418
+ }
419
+
420
+ walkClass(classy) {
421
+ if(classy.superClass)
422
+ this.walkExpression(classy.superClass);
423
+ if(classy.body && classy.body.type === "ClassBody") {
424
+ classy.body.body.forEach(methodDefinition => {
425
+ if(methodDefinition.type === "MethodDefinition")
426
+ this.walkMethodDefinition(methodDefinition);
427
+ });
372
428
  }
373
- res.setRange(expr.range);
374
- return res;
375
- });
376
- this.plugin("evaluate ArrayExpression", function(expr) {
377
- var items = expr.elements.map(function(element) {
378
- return element !== null && this.evaluateExpression(element);
379
- }, this);
380
- if(!items.every(Boolean)) return;
381
- return new BasicEvaluatedExpression().setItems(items).setRange(expr.range);
382
- });
383
- };
384
-
385
- Parser.prototype.getRenameIdentifier = function getRenameIdentifier(expr) {
386
- var result = this.evaluateExpression(expr);
387
- if(!result) return;
388
- if(result.isIdentifier()) return result.identifier;
389
- return;
390
- };
391
-
392
- Parser.prototype.walkClass = function walkClass(classy) {
393
- if(classy.superClass)
394
- this.walkExpression(classy.superClass);
395
- if(classy.body && classy.body.type === "ClassBody") {
396
- classy.body.body.forEach(function(methodDefinition) {
397
- if(methodDefinition.type === "MethodDefinition")
398
- this.walkMethodDefinition(methodDefinition);
399
- }, this);
400
429
  }
401
- };
402
-
403
- Parser.prototype.walkMethodDefinition = function walkMethodDefinition(methodDefinition) {
404
- if(methodDefinition.computed && methodDefinition.key)
405
- this.walkExpression(methodDefinition.key);
406
- if(methodDefinition.value)
407
- this.walkExpression(methodDefinition.value);
408
- };
409
-
410
- Parser.prototype.walkStatements = function walkStatements(statements) {
411
- for(var indexA = 0, lenA = statements.length; indexA < lenA; indexA++) {
412
- var statementA = statements[indexA];
413
- if(this.isHoistedStatement(statementA))
414
- this.walkStatement(statementA);
415
- }
416
- for(var indexB = 0, lenB = statements.length; indexB < lenB; indexB++) {
417
- var statementB = statements[indexB];
418
- if(!this.isHoistedStatement(statementB))
419
- this.walkStatement(statementB);
420
- }
421
- };
422
-
423
- Parser.prototype.isHoistedStatement = function isHoistedStatement(statement) {
424
- switch(statement.type) {
425
- case "ImportDeclaration":
426
- case "ExportAllDeclaration":
427
- case "ExportNamedDeclaration":
428
- return true;
429
- }
430
- return false;
431
- };
432
-
433
- Parser.prototype.walkStatement = function walkStatement(statement) {
434
- if(this.applyPluginsBailResult1("statement", statement) !== undefined) return;
435
- if(this["walk" + statement.type])
436
- this["walk" + statement.type](statement);
437
- };
438
-
439
- // Real Statements
440
- Parser.prototype.walkBlockStatement = function walkBlockStatement(statement) {
441
- this.walkStatements(statement.body);
442
- };
443
-
444
- Parser.prototype.walkExpressionStatement = function walkExpressionStatement(statement) {
445
- this.walkExpression(statement.expression);
446
- };
447
-
448
- Parser.prototype.walkIfStatement = function walkIfStatement(statement) {
449
- var result = this.applyPluginsBailResult1("statement if", statement);
450
- if(result === undefined) {
451
- this.walkExpression(statement.test);
452
- this.walkStatement(statement.consequent);
430
+
431
+ walkMethodDefinition(methodDefinition) {
432
+ if(methodDefinition.computed && methodDefinition.key)
433
+ this.walkExpression(methodDefinition.key);
434
+ if(methodDefinition.value)
435
+ this.walkExpression(methodDefinition.value);
436
+ }
437
+
438
+ // Prewalking iterates the scope for variable declarations
439
+ prewalkStatements(statements) {
440
+ for(let index = 0, len = statements.length; index < len; index++) {
441
+ const statement = statements[index];
442
+ this.prewalkStatement(statement);
443
+ }
444
+ }
445
+
446
+ // Walking iterates the statements and expressions and processes them
447
+ walkStatements(statements) {
448
+ for(let index = 0, len = statements.length; index < len; index++) {
449
+ const statement = statements[index];
450
+ this.walkStatement(statement);
451
+ }
452
+ }
453
+
454
+ prewalkStatement(statement) {
455
+ const handler = this["prewalk" + statement.type];
456
+ if(handler)
457
+ handler.call(this, statement);
458
+ }
459
+
460
+ walkStatement(statement) {
461
+ if(this.applyPluginsBailResult1("statement", statement) !== undefined) return;
462
+ const handler = this["walk" + statement.type];
463
+ if(handler)
464
+ handler.call(this, statement);
465
+ }
466
+
467
+ // Real Statements
468
+ prewalkBlockStatement(statement) {
469
+ this.prewalkStatements(statement.body);
470
+ }
471
+
472
+ walkBlockStatement(statement) {
473
+ this.walkStatements(statement.body);
474
+ }
475
+
476
+ walkExpressionStatement(statement) {
477
+ this.walkExpression(statement.expression);
478
+ }
479
+
480
+ prewalkIfStatement(statement) {
481
+ this.prewalkStatement(statement.consequent);
453
482
  if(statement.alternate)
454
- this.walkStatement(statement.alternate);
455
- } else {
456
- if(result)
483
+ this.prewalkStatement(statement.alternate);
484
+ }
485
+
486
+ walkIfStatement(statement) {
487
+ const result = this.applyPluginsBailResult1("statement if", statement);
488
+ if(result === undefined) {
489
+ this.walkExpression(statement.test);
457
490
  this.walkStatement(statement.consequent);
458
- else if(statement.alternate)
459
- this.walkStatement(statement.alternate);
491
+ if(statement.alternate)
492
+ this.walkStatement(statement.alternate);
493
+ } else {
494
+ if(result)
495
+ this.walkStatement(statement.consequent);
496
+ else if(statement.alternate)
497
+ this.walkStatement(statement.alternate);
498
+ }
499
+ }
500
+
501
+ prewalkLabeledStatement(statement) {
502
+ this.prewalkStatement(statement.body);
460
503
  }
461
- };
462
504
 
463
- Parser.prototype.walkLabeledStatement = function walkLabeledStatement(statement) {
464
- var result = this.applyPluginsBailResult1("label " + statement.label.name, statement);
465
- if(result !== true)
505
+ walkLabeledStatement(statement) {
506
+ const result = this.applyPluginsBailResult1("label " + statement.label.name, statement);
507
+ if(result !== true)
508
+ this.walkStatement(statement.body);
509
+ }
510
+
511
+ prewalkWithStatement(statement) {
512
+ this.prewalkStatement(statement.body);
513
+ }
514
+
515
+ walkWithStatement(statement) {
516
+ this.walkExpression(statement.object);
466
517
  this.walkStatement(statement.body);
467
- };
518
+ }
468
519
 
469
- Parser.prototype.walkWithStatement = function walkWithStatement(statement) {
470
- this.walkExpression(statement.object);
471
- this.walkStatement(statement.body);
472
- };
520
+ prewalkSwitchStatement(statement) {
521
+ this.prewalkSwitchCases(statement.cases);
522
+ }
473
523
 
474
- Parser.prototype.walkSwitchStatement = function walkSwitchStatement(statement) {
475
- this.walkExpression(statement.discriminant);
476
- this.walkSwitchCases(statement.cases);
477
- };
524
+ walkSwitchStatement(statement) {
525
+ this.walkExpression(statement.discriminant);
526
+ this.walkSwitchCases(statement.cases);
527
+ }
478
528
 
479
- Parser.prototype.walkReturnStatement =
480
- Parser.prototype.walkThrowStatement = function walkArgumentStatement(statement) {
529
+ walkTerminatingStatement(statement) {
481
530
  if(statement.argument)
482
531
  this.walkExpression(statement.argument);
483
- };
484
-
485
- Parser.prototype.walkTryStatement = function walkTryStatement(statement) {
486
- if(this.scope.inTry) {
487
- this.walkStatement(statement.block);
488
- } else {
489
- this.scope.inTry = true;
490
- this.walkStatement(statement.block);
491
- this.scope.inTry = false;
492
- }
493
- if(statement.handler)
494
- this.walkCatchClause(statement.handler);
495
- if(statement.finalizer)
496
- this.walkStatement(statement.finalizer);
497
- };
498
-
499
- Parser.prototype.walkWhileStatement =
500
- Parser.prototype.walkDoWhileStatement = function walkLoopStatement(statement) {
532
+ }
533
+
534
+ walkReturnStatement(statement) {
535
+ this.walkTerminatingStatement(statement);
536
+ }
537
+
538
+ walkThrowStatement(statement) {
539
+ this.walkTerminatingStatement(statement);
540
+ }
541
+
542
+ prewalkTryStatement(statement) {
543
+ this.prewalkStatement(statement.block);
544
+ }
545
+
546
+ walkTryStatement(statement) {
547
+ if(this.scope.inTry) {
548
+ this.walkStatement(statement.block);
549
+ } else {
550
+ this.scope.inTry = true;
551
+ this.walkStatement(statement.block);
552
+ this.scope.inTry = false;
553
+ }
554
+ if(statement.handler)
555
+ this.walkCatchClause(statement.handler);
556
+ if(statement.finalizer)
557
+ this.walkStatement(statement.finalizer);
558
+ }
559
+
560
+ prewalkWhileStatement(statement) {
561
+ this.prewalkStatement(statement.body);
562
+ }
563
+
564
+ walkWhileStatement(statement) {
501
565
  this.walkExpression(statement.test);
502
566
  this.walkStatement(statement.body);
503
- };
567
+ }
504
568
 
505
- Parser.prototype.walkForStatement = function walkForStatement(statement) {
506
- if(statement.init) {
507
- if(statement.init.type === "VariableDeclaration")
508
- this.walkStatement(statement.init);
509
- else
510
- this.walkExpression(statement.init);
569
+ prewalkDoWhileStatement(statement) {
570
+ this.prewalkStatement(statement.body);
511
571
  }
512
- if(statement.test)
572
+
573
+ walkDoWhileStatement(statement) {
574
+ this.walkStatement(statement.body);
513
575
  this.walkExpression(statement.test);
514
- if(statement.update)
515
- this.walkExpression(statement.update);
516
- this.walkStatement(statement.body);
517
- };
518
-
519
- Parser.prototype.walkForInStatement = function walkForInStatement(statement) {
520
- if(statement.left.type === "VariableDeclaration")
521
- this.walkStatement(statement.left);
522
- else
523
- this.walkExpression(statement.left);
524
- this.walkExpression(statement.right);
525
- this.walkStatement(statement.body);
526
- };
527
-
528
- Parser.prototype.walkForOfStatement = function walkForOfStatement(statement) {
529
- if(statement.left.type === "VariableDeclaration")
530
- this.walkStatement(statement.left);
531
- else
532
- this.walkExpression(statement.left);
533
- this.walkExpression(statement.right);
534
- this.walkStatement(statement.body);
535
- };
536
-
537
- // Declarations
538
- Parser.prototype.walkFunctionDeclaration = function walkFunctionDeclaration(statement) {
539
- this.scope.renames["$" + statement.id.name] = undefined;
540
- this.scope.definitions.push(statement.id.name);
541
- this.inScope(statement.params, function() {
542
- if(statement.body.type === "BlockStatement")
543
- this.walkStatement(statement.body);
576
+ }
577
+
578
+ prewalkForStatement(statement) {
579
+ if(statement.init) {
580
+ if(statement.init.type === "VariableDeclaration")
581
+ this.prewalkStatement(statement.init);
582
+ }
583
+ this.prewalkStatement(statement.body);
584
+ }
585
+
586
+ walkForStatement(statement) {
587
+ if(statement.init) {
588
+ if(statement.init.type === "VariableDeclaration")
589
+ this.walkStatement(statement.init);
590
+ else
591
+ this.walkExpression(statement.init);
592
+ }
593
+ if(statement.test)
594
+ this.walkExpression(statement.test);
595
+ if(statement.update)
596
+ this.walkExpression(statement.update);
597
+ this.walkStatement(statement.body);
598
+ }
599
+
600
+ prewalkForInStatement(statement) {
601
+ if(statement.left.type === "VariableDeclaration")
602
+ this.prewalkStatement(statement.left);
603
+ this.prewalkStatement(statement.body);
604
+ }
605
+
606
+ walkForInStatement(statement) {
607
+ if(statement.left.type === "VariableDeclaration")
608
+ this.walkStatement(statement.left);
544
609
  else
545
- this.walkExpression(statement.body);
546
- }.bind(this));
547
- };
548
-
549
- Parser.prototype.walkImportDeclaration = function walkImportDeclaration(statement) {
550
- var source = statement.source.value;
551
- this.applyPluginsBailResult("import", statement, source);
552
- statement.specifiers.forEach(function(specifier) {
553
- var name = specifier.local.name;
554
- this.scope.renames["$" + name] = undefined;
555
- this.scope.definitions.push(name);
556
- switch(specifier.type) {
557
- case "ImportDefaultSpecifier":
558
- this.applyPluginsBailResult("import specifier", statement, source, "default", name);
559
- break;
560
- case "ImportSpecifier":
561
- this.applyPluginsBailResult("import specifier", statement, source, specifier.imported.name, name);
562
- break;
563
- case "ImportNamespaceSpecifier":
564
- this.applyPluginsBailResult("import specifier", statement, source, null, name);
565
- break;
610
+ this.walkExpression(statement.left);
611
+ this.walkExpression(statement.right);
612
+ this.walkStatement(statement.body);
613
+ }
614
+
615
+ prewalkForOfStatement(statement) {
616
+ if(statement.left.type === "VariableDeclaration")
617
+ this.prewalkStatement(statement.left);
618
+ this.prewalkStatement(statement.body);
619
+ }
620
+
621
+ walkForOfStatement(statement) {
622
+ if(statement.left.type === "VariableDeclaration")
623
+ this.walkStatement(statement.left);
624
+ else
625
+ this.walkExpression(statement.left);
626
+ this.walkExpression(statement.right);
627
+ this.walkStatement(statement.body);
628
+ }
629
+
630
+ // Declarations
631
+ prewalkFunctionDeclaration(statement) {
632
+ if(statement.id) {
633
+ this.scope.renames["$" + statement.id.name] = undefined;
634
+ this.scope.definitions.push(statement.id.name);
566
635
  }
567
- }, this);
568
- };
636
+ }
569
637
 
570
- Parser.prototype.walkExportNamedDeclaration = function walkExportNamedDeclaration(statement) {
571
- if(statement.source) {
572
- var source = statement.source.value;
573
- this.applyPluginsBailResult("export import", statement, source);
574
- } else {
575
- this.applyPluginsBailResult1("export", statement);
638
+ walkFunctionDeclaration(statement) {
639
+ this.inScope(statement.params, function() {
640
+ if(statement.body.type === "BlockStatement") {
641
+ this.prewalkStatement(statement.body);
642
+ this.walkStatement(statement.body);
643
+ } else {
644
+ this.walkExpression(statement.body);
645
+ }
646
+ }.bind(this));
576
647
  }
577
- if(statement.declaration) {
578
- if(/Expression$/.test(statement.declaration.type)) {
579
- throw new Error("Doesn't occur?");
648
+
649
+ prewalkImportDeclaration(statement) {
650
+ const source = statement.source.value;
651
+ this.applyPluginsBailResult("import", statement, source);
652
+ statement.specifiers.forEach(function(specifier) {
653
+ const name = specifier.local.name;
654
+ this.scope.renames["$" + name] = undefined;
655
+ this.scope.definitions.push(name);
656
+ switch(specifier.type) {
657
+ case "ImportDefaultSpecifier":
658
+ this.applyPluginsBailResult("import specifier", statement, source, "default", name);
659
+ break;
660
+ case "ImportSpecifier":
661
+ this.applyPluginsBailResult("import specifier", statement, source, specifier.imported.name, name);
662
+ break;
663
+ case "ImportNamespaceSpecifier":
664
+ this.applyPluginsBailResult("import specifier", statement, source, null, name);
665
+ break;
666
+ }
667
+ }, this);
668
+ }
669
+
670
+ prewalkExportNamedDeclaration(statement) {
671
+ let source;
672
+ if(statement.source) {
673
+ source = statement.source.value;
674
+ this.applyPluginsBailResult("export import", statement, source);
580
675
  } else {
581
- if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) {
582
- var pos = this.scope.definitions.length;
583
- this.walkStatement(statement.declaration);
584
- var newDefs = this.scope.definitions.slice(pos);
585
- for(var index = newDefs.length - 1; index >= 0; index--) {
586
- var def = newDefs[index];
587
- this.applyPluginsBailResult("export specifier", statement, def, def, index);
676
+ this.applyPluginsBailResult1("export", statement);
677
+ }
678
+ if(statement.declaration) {
679
+ if(/Expression$/.test(statement.declaration.type)) {
680
+ throw new Error("Doesn't occur?");
681
+ } else {
682
+ if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) {
683
+ const pos = this.scope.definitions.length;
684
+ this.prewalkStatement(statement.declaration);
685
+ const newDefs = this.scope.definitions.slice(pos);
686
+ for(let index = newDefs.length - 1; index >= 0; index--) {
687
+ const def = newDefs[index];
688
+ this.applyPluginsBailResult("export specifier", statement, def, def, index);
689
+ }
588
690
  }
589
691
  }
590
692
  }
591
- }
592
- if(statement.specifiers) {
593
- for(var specifierIndex = 0; specifierIndex < statement.specifiers.length; specifierIndex++) {
594
- var specifier = statement.specifiers[specifierIndex];
595
- switch(specifier.type) {
596
- case "ExportSpecifier":
597
- var name = specifier.exported.name;
598
- if(source)
599
- this.applyPluginsBailResult("export import specifier", statement, source, specifier.local.name, name, specifierIndex);
600
- else
601
- this.applyPluginsBailResult("export specifier", statement, specifier.local.name, name, specifierIndex);
602
- break;
693
+ if(statement.specifiers) {
694
+ for(let specifierIndex = 0; specifierIndex < statement.specifiers.length; specifierIndex++) {
695
+ const specifier = statement.specifiers[specifierIndex];
696
+ switch(specifier.type) {
697
+ case "ExportSpecifier":
698
+ {
699
+ const name = specifier.exported.name;
700
+ if(source)
701
+ this.applyPluginsBailResult("export import specifier", statement, source, specifier.local.name, name, specifierIndex);
702
+ else
703
+ this.applyPluginsBailResult("export specifier", statement, specifier.local.name, name, specifierIndex);
704
+ break;
705
+ }
706
+ }
603
707
  }
604
708
  }
605
709
  }
606
- };
607
710
 
608
- Parser.prototype.walkExportDefaultDeclaration = function walkExportDefaultDeclaration(statement) {
609
- this.applyPluginsBailResult1("export", statement);
610
- if(/Declaration$/.test(statement.declaration.type)) {
611
- if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) {
612
- var pos = this.scope.definitions.length;
711
+ walkExportNamedDeclaration(statement) {
712
+ if(statement.declaration) {
613
713
  this.walkStatement(statement.declaration);
614
- var newDefs = this.scope.definitions.slice(pos);
615
- for(var index = 0, len = newDefs.length; index < len; index++) {
616
- var def = newDefs[index];
714
+ }
715
+ }
716
+
717
+ prewalkExportDefaultDeclaration(statement) {
718
+ if(/Declaration$/.test(statement.declaration.type)) {
719
+ const pos = this.scope.definitions.length;
720
+ this.prewalkStatement(statement.declaration);
721
+ const newDefs = this.scope.definitions.slice(pos);
722
+ for(let index = 0, len = newDefs.length; index < len; index++) {
723
+ const def = newDefs[index];
617
724
  this.applyPluginsBailResult("export specifier", statement, def, "default");
618
725
  }
619
726
  }
620
- } else {
621
- this.walkExpression(statement.declaration);
622
- if(!this.applyPluginsBailResult("export expression", statement, statement.declaration)) {
623
- this.applyPluginsBailResult("export specifier", statement, statement.declaration, "default");
727
+ }
728
+
729
+ walkExportDefaultDeclaration(statement) {
730
+ this.applyPluginsBailResult1("export", statement);
731
+ if(/Declaration$/.test(statement.declaration.type)) {
732
+ if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) {
733
+ this.walkStatement(statement.declaration);
734
+ }
735
+ } else {
736
+ this.walkExpression(statement.declaration);
737
+ if(!this.applyPluginsBailResult("export expression", statement, statement.declaration)) {
738
+ this.applyPluginsBailResult("export specifier", statement, statement.declaration, "default");
739
+ }
624
740
  }
625
741
  }
626
- };
627
742
 
628
- Parser.prototype.walkExportAllDeclaration = function walkExportAllDeclaration(statement) {
629
- var source = statement.source.value;
630
- this.applyPluginsBailResult("export import", statement, source);
631
- this.applyPluginsBailResult("export import specifier", statement, source, null, null, 0);
632
- };
743
+ prewalkExportAllDeclaration(statement) {
744
+ const source = statement.source.value;
745
+ this.applyPluginsBailResult("export import", statement, source);
746
+ this.applyPluginsBailResult("export import specifier", statement, source, null, null, 0);
747
+ }
748
+
749
+ prewalkVariableDeclaration(statement) {
750
+ if(statement.declarations)
751
+ this.prewalkVariableDeclarators(statement.declarations);
752
+ }
753
+
754
+ walkVariableDeclaration(statement) {
755
+ if(statement.declarations)
756
+ this.walkVariableDeclarators(statement.declarations);
757
+ }
758
+
759
+ prewalkClassDeclaration(statement) {
760
+ if(statement.id) {
761
+ this.scope.renames["$" + statement.id.name] = undefined;
762
+ this.scope.definitions.push(statement.id.name);
763
+ }
764
+ }
633
765
 
634
- Parser.prototype.walkVariableDeclaration = function walkVariableDeclaration(statement) {
635
- if(statement.declarations)
636
- this.walkVariableDeclarators(statement.declarations);
637
- };
766
+ walkClassDeclaration(statement) {
767
+ this.walkClass(statement);
768
+ }
638
769
 
639
- Parser.prototype.walkClassDeclaration = function walkClassDeclaration(statement) {
640
- this.scope.renames["$" + statement.id.name] = undefined;
641
- this.scope.definitions.push(statement.id.name);
642
- this.walkClass(statement);
643
- };
770
+ prewalkSwitchCases(switchCases) {
771
+ for(let index = 0, len = switchCases.length; index < len; index++) {
772
+ const switchCase = switchCases[index];
773
+ this.prewalkStatements(switchCase.consequent);
774
+ }
775
+ }
644
776
 
645
- Parser.prototype.walkSwitchCases = function walkSwitchCases(switchCases) {
646
- for(var index = 0, len = switchCases.length; index < len; index++) {
647
- var switchCase = switchCases[index];
777
+ walkSwitchCases(switchCases) {
778
+ for(let index = 0, len = switchCases.length; index < len; index++) {
779
+ const switchCase = switchCases[index];
648
780
 
649
- if(switchCase.test) {
650
- this.walkExpression(switchCase.test);
781
+ if(switchCase.test) {
782
+ this.walkExpression(switchCase.test);
783
+ }
784
+ this.walkStatements(switchCase.consequent);
651
785
  }
652
- this.walkStatements(switchCase.consequent);
653
- }
654
- };
655
-
656
- Parser.prototype.walkCatchClause = function walkCatchClause(catchClause) {
657
- if(catchClause.guard)
658
- this.walkExpression(catchClause.guard);
659
- this.inScope([catchClause.param], function() {
660
- this.walkStatement(catchClause.body);
661
- }.bind(this));
662
- };
663
-
664
- Parser.prototype.walkVariableDeclarators = function walkVariableDeclarators(declarators) {
665
- var _this = this;
666
- declarators.forEach(function(declarator) {
667
- switch(declarator.type) {
668
- case "VariableDeclarator":
669
- var renameIdentifier = declarator.init && _this.getRenameIdentifier(declarator.init);
670
- if(renameIdentifier && declarator.id.type === "Identifier" && _this.applyPluginsBailResult1("can-rename " + renameIdentifier, declarator.init)) {
671
- // renaming with "var a = b;"
672
- if(!_this.applyPluginsBailResult1("rename " + renameIdentifier, declarator.init)) {
673
- _this.scope.renames["$" + declarator.id.name] = _this.scope.renames["$" + renameIdentifier] || renameIdentifier;
674
- var idx = _this.scope.definitions.indexOf(declarator.id.name);
675
- if(idx >= 0) _this.scope.definitions.splice(idx, 1);
786
+ }
787
+
788
+ walkCatchClause(catchClause) {
789
+ this.inScope([catchClause.param], function() {
790
+ this.prewalkStatement(catchClause.body);
791
+ this.walkStatement(catchClause.body);
792
+ }.bind(this));
793
+ }
794
+
795
+ prewalkVariableDeclarators(declarators) {
796
+ declarators.forEach(declarator => {
797
+ switch(declarator.type) {
798
+ case "VariableDeclarator":
799
+ {
800
+ const renameIdentifier = declarator.init && this.getRenameIdentifier(declarator.init);
801
+ if(renameIdentifier && declarator.id.type === "Identifier" && this.applyPluginsBailResult1("can-rename " + renameIdentifier, declarator.init)) {
802
+ // renaming with "var a = b;"
803
+ if(!this.applyPluginsBailResult1("rename " + renameIdentifier, declarator.init)) {
804
+ this.scope.renames["$" + declarator.id.name] = this.scope.renames["$" + renameIdentifier] || renameIdentifier;
805
+ const idx = this.scope.definitions.indexOf(declarator.id.name);
806
+ if(idx >= 0) this.scope.definitions.splice(idx, 1);
807
+ }
808
+ } else {
809
+ this.enterPattern(declarator.id, (name, decl) => {
810
+ if(!this.applyPluginsBailResult1("var-" + declarator.kind + " " + name, decl)) {
811
+ if(!this.applyPluginsBailResult1("var " + name, decl)) {
812
+ this.scope.renames["$" + name] = undefined;
813
+ this.scope.definitions.push(name);
814
+ }
815
+ }
816
+ });
817
+ }
818
+ break;
676
819
  }
677
- } else {
678
- _this.walkPattern(declarator.id);
679
- _this.enterPattern(declarator.id, function(name, decl) {
680
- if(!_this.applyPluginsBailResult1("var " + name, decl)) {
681
- _this.scope.renames["$" + name] = undefined;
682
- _this.scope.definitions.push(name);
820
+ }
821
+ });
822
+ }
823
+
824
+ walkVariableDeclarators(declarators) {
825
+ declarators.forEach(declarator => {
826
+ switch(declarator.type) {
827
+ case "VariableDeclarator":
828
+ {
829
+ const renameIdentifier = declarator.init && this.getRenameIdentifier(declarator.init);
830
+ if(!renameIdentifier || declarator.id.type !== "Identifier" || !this.applyPluginsBailResult1("can-rename " + renameIdentifier, declarator.init)) {
831
+ this.walkPattern(declarator.id);
832
+ if(declarator.init)
833
+ this.walkExpression(declarator.init);
683
834
  }
684
- });
685
- if(declarator.init)
686
- _this.walkExpression(declarator.init);
687
- }
688
- break;
835
+ break;
836
+ }
837
+ }
838
+ });
839
+ }
840
+
841
+ walkPattern(pattern) {
842
+ if(pattern.type === "Identifier")
843
+ return;
844
+ if(this["walk" + pattern.type])
845
+ this["walk" + pattern.type](pattern);
846
+ }
847
+
848
+ walkObjectPattern(pattern) {
849
+ for(let i = 0, len = pattern.properties.length; i < len; i++) {
850
+ const prop = pattern.properties[i];
851
+ if(prop) {
852
+ if(prop.computed)
853
+ this.walkExpression(prop.key);
854
+ if(prop.value)
855
+ this.walkPattern(prop.value);
856
+ }
689
857
  }
690
- });
691
- };
858
+ }
692
859
 
693
- Parser.prototype.walkPattern = function walkPattern(pattern) {
694
- if(pattern.type === "Identifier")
695
- return;
696
- if(this["walk" + pattern.type])
697
- this["walk" + pattern.type](pattern);
698
- };
699
-
700
- Parser.prototype.walkObjectPattern = function walkObjectPattern(pattern) {
701
- for(var i = 0, len = pattern.properties.length; i < len; i++) {
702
- var prop = pattern.properties[i];
703
- if(prop) {
860
+ walkArrayPattern(pattern) {
861
+ for(let i = 0, len = pattern.elements.length; i < len; i++) {
862
+ const element = pattern.elements[i];
863
+ if(element)
864
+ this.walkPattern(element);
865
+ }
866
+ }
867
+
868
+ walkRestElement(pattern) {
869
+ this.walkPattern(pattern.argument);
870
+ }
871
+
872
+ walkExpressions(expressions) {
873
+ for(let expressionsIndex = 0, len = expressions.length; expressionsIndex < len; expressionsIndex++) {
874
+ const expression = expressions[expressionsIndex];
875
+ if(expression)
876
+ this.walkExpression(expression);
877
+ }
878
+ }
879
+
880
+ walkExpression(expression) {
881
+ if(this["walk" + expression.type])
882
+ return this["walk" + expression.type](expression);
883
+ }
884
+
885
+ walkAwaitExpression(expression) {
886
+ const argument = expression.argument;
887
+ if(this["walk" + argument.type])
888
+ return this["walk" + argument.type](argument);
889
+ }
890
+
891
+ walkArrayExpression(expression) {
892
+ if(expression.elements)
893
+ this.walkExpressions(expression.elements);
894
+ }
895
+
896
+ walkSpreadElement(expression) {
897
+ if(expression.argument)
898
+ this.walkExpression(expression.argument);
899
+ }
900
+
901
+ walkObjectExpression(expression) {
902
+ for(let propIndex = 0, len = expression.properties.length; propIndex < len; propIndex++) {
903
+ const prop = expression.properties[propIndex];
704
904
  if(prop.computed)
705
905
  this.walkExpression(prop.key);
706
- if(prop.value)
707
- this.walkPattern(prop.value);
906
+ if(prop.shorthand)
907
+ this.scope.inShorthand = true;
908
+ this.walkExpression(prop.value);
909
+ if(prop.shorthand)
910
+ this.scope.inShorthand = false;
911
+ }
912
+ }
913
+
914
+ walkFunctionExpression(expression) {
915
+ this.inScope(expression.params, function() {
916
+ if(expression.body.type === "BlockStatement") {
917
+ this.prewalkStatement(expression.body);
918
+ this.walkStatement(expression.body);
919
+ } else {
920
+ this.walkExpression(expression.body);
921
+ }
922
+ }.bind(this));
923
+ }
924
+
925
+ walkArrowFunctionExpression(expression) {
926
+ this.inScope(expression.params, function() {
927
+ if(expression.body.type === "BlockStatement") {
928
+ this.prewalkStatement(expression.body);
929
+ this.walkStatement(expression.body);
930
+ } else {
931
+ this.walkExpression(expression.body);
932
+ }
933
+ }.bind(this));
934
+ }
935
+
936
+ walkSequenceExpression(expression) {
937
+ if(expression.expressions)
938
+ this.walkExpressions(expression.expressions);
939
+ }
940
+
941
+ walkUpdateExpression(expression) {
942
+ this.walkExpression(expression.argument);
943
+ }
944
+
945
+ walkUnaryExpression(expression) {
946
+ if(expression.operator === "typeof") {
947
+ let expr = expression.argument;
948
+ let exprName = [];
949
+ while(expr.type === "MemberExpression" && expr.property.type === (expr.computed ? "Literal" : "Identifier")) {
950
+ exprName.unshift(expr.property.name || expr.property.value);
951
+ expr = expr.object;
952
+ }
953
+ if(expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) {
954
+ exprName.unshift(this.scope.renames["$" + expr.name] || expr.name);
955
+ exprName = exprName.join(".");
956
+ const result = this.applyPluginsBailResult1("typeof " + exprName, expression);
957
+ if(result === true)
958
+ return;
959
+ }
708
960
  }
961
+ this.walkExpression(expression.argument);
709
962
  }
710
- };
711
963
 
712
- Parser.prototype.walkArrayPattern = function walkArrayPattern(pattern) {
713
- for(var i = 0, len = pattern.elements.length; i < len; i++) {
714
- var element = pattern.elements[i];
715
- if(element)
716
- this.walkPattern(element);
964
+ walkLeftRightExpression(expression) {
965
+ this.walkExpression(expression.left);
966
+ this.walkExpression(expression.right);
717
967
  }
718
- };
719
968
 
720
- Parser.prototype.walkRestElement = function walkRestElement(pattern) {
721
- this.walkPattern(pattern.argument);
722
- };
969
+ walkBinaryExpression(expression) {
970
+ this.walkLeftRightExpression(expression);
971
+ }
723
972
 
724
- Parser.prototype.walkExpressions = function walkExpressions(expressions) {
725
- for(var expressionsIndex = 0, len = expressions.length; expressionsIndex < len; expressionsIndex++) {
726
- var expression = expressions[expressionsIndex];
727
- if(expression)
728
- this.walkExpression(expression);
973
+ walkLogicalExpression(expression) {
974
+ this.walkLeftRightExpression(expression);
729
975
  }
730
- };
731
976
 
732
- Parser.prototype.walkExpression = function walkExpression(expression) {
733
- if(this["walk" + expression.type])
734
- return this["walk" + expression.type](expression);
735
- };
977
+ walkAssignmentExpression(expression) {
978
+ const renameIdentifier = this.getRenameIdentifier(expression.right);
979
+ if(expression.left.type === "Identifier" && renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, expression.right)) {
980
+ // renaming "a = b;"
981
+ if(!this.applyPluginsBailResult1("rename " + renameIdentifier, expression.right)) {
982
+ this.scope.renames["$" + expression.left.name] = renameIdentifier;
983
+ const idx = this.scope.definitions.indexOf(expression.left.name);
984
+ if(idx >= 0) this.scope.definitions.splice(idx, 1);
985
+ }
986
+ } else if(expression.left.type === "Identifier") {
987
+ if(!this.applyPluginsBailResult1("assigned " + expression.left.name, expression)) {
988
+ this.walkExpression(expression.right);
989
+ }
990
+ this.scope.renames["$" + expression.left.name] = undefined;
991
+ if(!this.applyPluginsBailResult1("assign " + expression.left.name, expression)) {
992
+ this.walkExpression(expression.left);
993
+ }
994
+ } else {
995
+ this.walkExpression(expression.right);
996
+ this.scope.renames["$" + expression.left.name] = undefined;
997
+ this.walkExpression(expression.left);
998
+ }
999
+ }
736
1000
 
737
- Parser.prototype.walkAwaitExpression = function walkAwaitExpression(expression) {
738
- var argument = expression.argument;
739
- if(this["walk" + argument.type])
740
- return this["walk" + argument.type](argument);
741
- };
1001
+ walkConditionalExpression(expression) {
1002
+ const result = this.applyPluginsBailResult1("expression ?:", expression);
1003
+ if(result === undefined) {
1004
+ this.walkExpression(expression.test);
1005
+ this.walkExpression(expression.consequent);
1006
+ if(expression.alternate)
1007
+ this.walkExpression(expression.alternate);
1008
+ } else {
1009
+ if(result)
1010
+ this.walkExpression(expression.consequent);
1011
+ else if(expression.alternate)
1012
+ this.walkExpression(expression.alternate);
1013
+ }
1014
+ }
742
1015
 
743
- Parser.prototype.walkArrayExpression = function walkArrayExpression(expression) {
744
- if(expression.elements)
745
- this.walkExpressions(expression.elements);
746
- };
1016
+ walkNewExpression(expression) {
1017
+ this.walkExpression(expression.callee);
1018
+ if(expression.arguments)
1019
+ this.walkExpressions(expression.arguments);
1020
+ }
747
1021
 
748
- Parser.prototype.walkSpreadElement = function walkSpreadElement(expression) {
749
- if(expression.argument)
750
- this.walkExpression(expression.argument);
751
- };
752
-
753
- Parser.prototype.walkObjectExpression = function walkObjectExpression(expression) {
754
- for(var propIndex = 0, len = expression.properties.length; propIndex < len; propIndex++) {
755
- var prop = expression.properties[propIndex];
756
- if(prop.computed)
757
- this.walkExpression(prop.key);
758
- if(prop.shorthand)
759
- this.scope.inShorthand = true;
760
- this.walkExpression(prop.value);
761
- if(prop.shorthand)
762
- this.scope.inShorthand = false;
763
- }
764
- };
765
-
766
- Parser.prototype.walkFunctionExpression = function walkFunctionExpression(expression) {
767
- this.inScope(expression.params, function() {
768
- if(expression.body.type === "BlockStatement")
769
- this.walkStatement(expression.body);
770
- else
771
- this.walkExpression(expression.body);
772
- }.bind(this));
773
- };
774
-
775
- Parser.prototype.walkArrowFunctionExpression = function walkArrowFunctionExpression(expression) {
776
- this.inScope(expression.params, function() {
777
- if(expression.body.type === "BlockStatement")
778
- this.walkStatement(expression.body);
779
- else
780
- this.walkExpression(expression.body);
781
- }.bind(this));
782
- };
783
-
784
- Parser.prototype.walkSequenceExpression = function walkSequenceExpression(expression) {
785
- if(expression.expressions)
786
- this.walkExpressions(expression.expressions);
787
- };
788
-
789
- Parser.prototype.walkUpdateExpression = function walkUpdateExpression(expression) {
790
- this.walkExpression(expression.argument);
791
- };
792
-
793
- Parser.prototype.walkUnaryExpression = function walkUnaryExpression(expression) {
794
- if(expression.operator === "typeof") {
795
- var expr = expression.argument;
796
- var exprName = [];
797
- while(expr.type === "MemberExpression" &&
798
- expr.property.type === (expr.computed ? "Literal" : "Identifier")
1022
+ walkYieldExpression(expression) {
1023
+ if(expression.argument)
1024
+ this.walkExpression(expression.argument);
1025
+ }
1026
+
1027
+ walkTemplateLiteral(expression) {
1028
+ if(expression.expressions)
1029
+ this.walkExpressions(expression.expressions);
1030
+ }
1031
+
1032
+ walkTaggedTemplateExpression(expression) {
1033
+ if(expression.tag)
1034
+ this.walkExpression(expression.tag);
1035
+ if(expression.quasi && expression.quasi.expressions)
1036
+ this.walkExpressions(expression.quasi.expressions);
1037
+ }
1038
+
1039
+ walkClassExpression(expression) {
1040
+ this.walkClass(expression);
1041
+ }
1042
+
1043
+ walkCallExpression(expression) {
1044
+ let result;
1045
+
1046
+ function walkIIFE(functionExpression, options) {
1047
+ const params = functionExpression.params;
1048
+ const args = options.map(function(arg) {
1049
+ const renameIdentifier = this.getRenameIdentifier(arg);
1050
+ if(renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, arg)) {
1051
+ if(!this.applyPluginsBailResult1("rename " + renameIdentifier, arg))
1052
+ return renameIdentifier;
1053
+ }
1054
+ this.walkExpression(arg);
1055
+ }, this);
1056
+ this.inScope(params.filter(function(identifier, idx) {
1057
+ return !args[idx];
1058
+ }), function() {
1059
+ for(let i = 0; i < args.length; i++) {
1060
+ const param = args[i];
1061
+ if(!param) continue;
1062
+ if(!params[i] || params[i].type !== "Identifier") continue;
1063
+ this.scope.renames["$" + params[i].name] = param;
1064
+ }
1065
+ if(functionExpression.body.type === "BlockStatement") {
1066
+ this.prewalkStatement(functionExpression.body);
1067
+ this.walkStatement(functionExpression.body);
1068
+ } else
1069
+ this.walkExpression(functionExpression.body);
1070
+ }.bind(this));
1071
+ }
1072
+ if(expression.callee.type === "MemberExpression" &&
1073
+ expression.callee.object.type === "FunctionExpression" &&
1074
+ !expression.callee.computed &&
1075
+ (["call", "bind"]).indexOf(expression.callee.property.name) >= 0 &&
1076
+ expression.arguments &&
1077
+ expression.arguments.length > 1
799
1078
  ) {
1079
+ // (function(...) { }.call/bind(?, ...))
1080
+ walkIIFE.call(this, expression.callee.object, expression.arguments.slice(1));
1081
+ this.walkExpression(expression.arguments[0]);
1082
+ } else if(expression.callee.type === "FunctionExpression" && expression.arguments) {
1083
+ // (function(...) { }(...))
1084
+ walkIIFE.call(this, expression.callee, expression.arguments);
1085
+ } else if(expression.callee.type === "Import") {
1086
+ result = this.applyPluginsBailResult1("import-call", expression);
1087
+ if(result === true)
1088
+ return;
1089
+
1090
+ if(expression.arguments)
1091
+ this.walkExpressions(expression.arguments);
1092
+ } else {
1093
+
1094
+ const callee = this.evaluateExpression(expression.callee);
1095
+ if(callee.isIdentifier()) {
1096
+ result = this.applyPluginsBailResult1("call " + callee.identifier, expression);
1097
+ if(result === true)
1098
+ return;
1099
+ }
1100
+
1101
+ if(expression.callee)
1102
+ this.walkExpression(expression.callee);
1103
+ if(expression.arguments)
1104
+ this.walkExpressions(expression.arguments);
1105
+ }
1106
+ }
1107
+
1108
+ walkMemberExpression(expression) {
1109
+ let expr = expression;
1110
+ let exprName = [];
1111
+ while(expr.type === "MemberExpression" && expr.property.type === (expr.computed ? "Literal" : "Identifier")) {
800
1112
  exprName.unshift(expr.property.name || expr.property.value);
801
1113
  expr = expr.object;
802
1114
  }
803
1115
  if(expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) {
804
1116
  exprName.unshift(this.scope.renames["$" + expr.name] || expr.name);
805
- exprName = exprName.join(".");
806
- var result = this.applyPluginsBailResult1("typeof " + exprName, expression);
1117
+ let result = this.applyPluginsBailResult1("expression " + exprName.join("."), expression);
1118
+ if(result === true)
1119
+ return;
1120
+ exprName[exprName.length - 1] = "*";
1121
+ result = this.applyPluginsBailResult1("expression " + exprName.join("."), expression);
807
1122
  if(result === true)
808
1123
  return;
809
1124
  }
1125
+ this.walkExpression(expression.object);
1126
+ if(expression.computed === true)
1127
+ this.walkExpression(expression.property);
810
1128
  }
811
- this.walkExpression(expression.argument);
812
- };
813
1129
 
814
- Parser.prototype.walkBinaryExpression =
815
- Parser.prototype.walkLogicalExpression = function walkLeftRightExpression(expression) {
816
- this.walkExpression(expression.left);
817
- this.walkExpression(expression.right);
818
- };
819
-
820
- Parser.prototype.walkAssignmentExpression = function walkAssignmentExpression(expression) {
821
- var renameIdentifier = this.getRenameIdentifier(expression.right);
822
- if(expression.left.type === "Identifier" && renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, expression.right)) {
823
- // renaming "a = b;"
824
- if(!this.applyPluginsBailResult1("rename " + renameIdentifier, expression.right)) {
825
- this.scope.renames["$" + expression.left.name] = renameIdentifier;
826
- var idx = this.scope.definitions.indexOf(expression.left.name);
827
- if(idx >= 0) this.scope.definitions.splice(idx, 1);
828
- }
829
- } else if(expression.left.type === "Identifier") {
830
- if(!this.applyPluginsBailResult1("assigned " + expression.left.name, expression)) {
831
- this.walkExpression(expression.right);
832
- }
833
- this.scope.renames["$" + expression.left.name] = undefined;
834
- if(!this.applyPluginsBailResult1("assign " + expression.left.name, expression)) {
835
- this.walkExpression(expression.left);
1130
+ walkIdentifier(expression) {
1131
+ if(this.scope.definitions.indexOf(expression.name) === -1) {
1132
+ const result = this.applyPluginsBailResult1("expression " + (this.scope.renames["$" + expression.name] || expression.name), expression);
1133
+ if(result === true)
1134
+ return;
836
1135
  }
837
- } else {
838
- this.walkExpression(expression.right);
839
- this.scope.renames["$" + expression.left.name] = undefined;
840
- this.walkExpression(expression.left);
841
1136
  }
842
- };
843
-
844
- Parser.prototype.walkConditionalExpression = function walkConditionalExpression(expression) {
845
- var result = this.applyPluginsBailResult1("expression ?:", expression);
846
- if(result === undefined) {
847
- this.walkExpression(expression.test);
848
- this.walkExpression(expression.consequent);
849
- if(expression.alternate)
850
- this.walkExpression(expression.alternate);
851
- } else {
852
- if(result)
853
- this.walkExpression(expression.consequent);
854
- else if(expression.alternate)
855
- this.walkExpression(expression.alternate);
1137
+
1138
+ inScope(params, fn) {
1139
+ const oldScope = this.scope;
1140
+ this.scope = {
1141
+ inTry: false,
1142
+ inShorthand: false,
1143
+ definitions: oldScope.definitions.slice(),
1144
+ renames: Object.create(oldScope.renames)
1145
+ };
1146
+
1147
+ for(let paramIndex = 0, len = params.length; paramIndex < len; paramIndex++) {
1148
+ const param = params[paramIndex];
1149
+
1150
+ if(typeof param !== "string") {
1151
+ this.enterPattern(param, param => {
1152
+ this.scope.renames["$" + param] = undefined;
1153
+ this.scope.definitions.push(param);
1154
+ });
1155
+ } else {
1156
+ this.scope.renames["$" + param] = undefined;
1157
+ this.scope.definitions.push(param);
1158
+ }
1159
+ }
1160
+
1161
+ fn();
1162
+ this.scope = oldScope;
856
1163
  }
857
- };
858
1164
 
859
- Parser.prototype.walkNewExpression = function walkNewExpression(expression) {
860
- this.walkExpression(expression.callee);
861
- if(expression.arguments)
862
- this.walkExpressions(expression.arguments);
863
- };
1165
+ enterPattern(pattern, onIdent) {
1166
+ if(pattern && this["enter" + pattern.type])
1167
+ this["enter" + pattern.type](pattern, onIdent);
1168
+ }
864
1169
 
865
- Parser.prototype.walkYieldExpression = function walkYieldExpression(expression) {
866
- if(expression.argument)
867
- this.walkExpression(expression.argument);
868
- };
869
-
870
- Parser.prototype.walkTemplateLiteral = function walkTemplateLiteral(expression) {
871
- if(expression.expressions)
872
- this.walkExpressions(expression.expressions);
873
- };
874
-
875
- Parser.prototype.walkTaggedTemplateExpression = function walkTaggedTemplateExpression(expression) {
876
- if(expression.tag)
877
- this.walkExpression(expression.tag);
878
- if(expression.quasi && expression.quasi.expressions)
879
- this.walkExpressions(expression.quasi.expressions);
880
- };
881
-
882
- Parser.prototype.walkClassExpression = function walkClassExpression(expression) {
883
- this.walkClass(expression);
884
- };
885
-
886
- Parser.prototype.walkCallExpression = function walkCallExpression(expression) {
887
- var result;
888
-
889
- function walkIIFE(functionExpression, options) {
890
- var params = functionExpression.params;
891
- var args = options.map(function(arg) {
892
- var renameIdentifier = this.getRenameIdentifier(arg);
893
- if(renameIdentifier && this.applyPluginsBailResult1("can-rename " + renameIdentifier, arg)) {
894
- if(!this.applyPluginsBailResult1("rename " + renameIdentifier, arg))
895
- return renameIdentifier;
896
- }
897
- this.walkExpression(arg);
898
- }, this);
899
- this.inScope(params.filter(function(identifier, idx) {
900
- return !args[idx];
901
- }), function() {
902
- for(var i = 0; i < args.length; i++) {
903
- var param = args[i];
904
- if(!param) continue;
905
- if(!params[i] || params[i].type !== "Identifier") continue;
906
- this.scope.renames["$" + params[i].name] = param;
907
- }
908
- if(functionExpression.body.type === "BlockStatement")
909
- this.walkStatement(functionExpression.body);
910
- else
911
- this.walkExpression(functionExpression.body);
912
- }.bind(this));
1170
+ enterIdentifier(pattern, onIdent) {
1171
+ onIdent(pattern.name, pattern);
913
1172
  }
914
- if(expression.callee.type === "MemberExpression" &&
915
- expression.callee.object.type === "FunctionExpression" &&
916
- !expression.callee.computed &&
917
- (["call", "bind"]).indexOf(expression.callee.property.name) >= 0 &&
918
- expression.arguments &&
919
- expression.arguments.length > 1
920
- ) {
921
- // (function(...) { }.call/bind(?, ...))
922
- walkIIFE.call(this, expression.callee.object, expression.arguments.slice(1));
923
- this.walkExpression(expression.arguments[0]);
924
- } else if(expression.callee.type === "FunctionExpression" && expression.arguments) {
925
- // (function(...) { }(...))
926
- walkIIFE.call(this, expression.callee, expression.arguments);
927
- } else if(expression.callee.type === "Import") {
928
- result = this.applyPluginsBailResult1("import-call", expression);
929
- if(result === true)
930
- return;
931
1173
 
932
- if(expression.arguments)
933
- this.walkExpressions(expression.arguments);
934
- } else {
1174
+ enterObjectPattern(pattern, onIdent) {
1175
+ for(let propIndex = 0, len = pattern.properties.length; propIndex < len; propIndex++) {
1176
+ const prop = pattern.properties[propIndex];
1177
+ this.enterPattern(prop.value, onIdent);
1178
+ }
1179
+ }
935
1180
 
936
- var callee = this.evaluateExpression(expression.callee);
937
- if(callee.isIdentifier()) {
938
- result = this.applyPluginsBailResult1("call " + callee.identifier, expression);
939
- if(result === true)
940
- return;
1181
+ enterArrayPattern(pattern, onIdent) {
1182
+ for(let elementIndex = 0, len = pattern.elements.length; elementIndex < len; elementIndex++) {
1183
+ const element = pattern.elements[elementIndex];
1184
+ this.enterPattern(element, onIdent);
941
1185
  }
1186
+ }
942
1187
 
943
- if(expression.callee)
944
- this.walkExpression(expression.callee);
945
- if(expression.arguments)
946
- this.walkExpressions(expression.arguments);
1188
+ enterRestElement(pattern, onIdent) {
1189
+ this.enterPattern(pattern.argument, onIdent);
947
1190
  }
948
- };
949
-
950
- Parser.prototype.walkMemberExpression = function walkMemberExpression(expression) {
951
- var expr = expression;
952
- var exprName = [];
953
- while(expr.type === "MemberExpression" &&
954
- expr.property.type === (expr.computed ? "Literal" : "Identifier")
955
- ) {
956
- exprName.unshift(expr.property.name || expr.property.value);
957
- expr = expr.object;
958
- }
959
- if(expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) {
960
- exprName.unshift(this.scope.renames["$" + expr.name] || expr.name);
961
- var result = this.applyPluginsBailResult1("expression " + exprName.join("."), expression);
962
- if(result === true)
963
- return;
964
- exprName[exprName.length - 1] = "*";
965
- result = this.applyPluginsBailResult1("expression " + exprName.join("."), expression);
966
- if(result === true)
967
- return;
1191
+
1192
+ enterAssignmentPattern(pattern, onIdent) {
1193
+ this.enterPattern(pattern.left, onIdent);
1194
+ this.walkExpression(pattern.right);
968
1195
  }
969
- this.walkExpression(expression.object);
970
- if(expression.computed === true)
971
- this.walkExpression(expression.property);
972
- };
973
1196
 
974
- Parser.prototype.walkIdentifier = function walkIdentifier(expression) {
975
- if(this.scope.definitions.indexOf(expression.name) === -1) {
976
- var result = this.applyPluginsBailResult1("expression " + (this.scope.renames["$" + expression.name] || expression.name), expression);
977
- if(result === true)
978
- return;
1197
+ evaluateExpression(expression) {
1198
+ try {
1199
+ const result = this.applyPluginsBailResult1("evaluate " + expression.type, expression);
1200
+ if(result !== undefined)
1201
+ return result;
1202
+ } catch(e) {
1203
+ console.warn(e);
1204
+ // ignore error
1205
+ }
1206
+ return new BasicEvaluatedExpression().setRange(expression.range);
979
1207
  }
980
- };
981
-
982
- Parser.prototype.inScope = function inScope(params, fn) {
983
- var oldScope = this.scope;
984
- var _this = this;
985
- this.scope = {
986
- inTry: false,
987
- inShorthand: false,
988
- definitions: oldScope.definitions.slice(),
989
- renames: Object.create(oldScope.renames)
990
- };
991
-
992
- for(var paramIndex = 0, len = params.length; paramIndex < len; paramIndex++) {
993
- var param = params[paramIndex];
994
-
995
- if(typeof param !== "string") {
996
- _this.enterPattern(param, function(param) {
997
- _this.scope.renames["$" + param] = undefined;
998
- _this.scope.definitions.push(param);
999
- });
1000
- } else {
1001
- _this.scope.renames["$" + param] = undefined;
1002
- _this.scope.definitions.push(param);
1208
+
1209
+ parseString(expression) {
1210
+ switch(expression.type) {
1211
+ case "BinaryExpression":
1212
+ if(expression.operator === "+")
1213
+ return this.parseString(expression.left) + this.parseString(expression.right);
1214
+ break;
1215
+ case "Literal":
1216
+ return expression.value + "";
1003
1217
  }
1218
+ throw new Error(expression.type + " is not supported as parameter for require");
1004
1219
  }
1005
1220
 
1006
- fn();
1007
- _this.scope = oldScope;
1008
- };
1009
-
1010
- Parser.prototype.enterPattern = function enterPattern(pattern, onIdent) {
1011
- if(pattern && this["enter" + pattern.type])
1012
- this["enter" + pattern.type](pattern, onIdent);
1013
- };
1014
-
1015
- Parser.prototype.enterIdentifier = function enterIdentifier(pattern, onIdent) {
1016
- onIdent(pattern.name, pattern);
1017
- };
1018
-
1019
- Parser.prototype.enterObjectPattern = function enterObjectPattern(pattern, onIdent) {
1020
- for(var propIndex = 0, len = pattern.properties.length; propIndex < len; propIndex++) {
1021
- var prop = pattern.properties[propIndex];
1022
- this.enterPattern(prop.value, onIdent);
1023
- }
1024
- };
1025
-
1026
- Parser.prototype.enterArrayPattern = function enterArrayPattern(pattern, onIdent) {
1027
- for(var elementIndex = 0, len = pattern.elements.length; elementIndex < len; elementIndex++) {
1028
- var element = pattern.elements[elementIndex];
1029
- this.enterPattern(element, onIdent);
1030
- }
1031
- };
1032
-
1033
- Parser.prototype.enterRestElement = function enterRestElement(pattern, onIdent) {
1034
- this.enterPattern(pattern.argument, onIdent);
1035
- };
1036
-
1037
- Parser.prototype.enterAssignmentPattern = function enterAssignmentPattern(pattern, onIdent) {
1038
- this.enterPattern(pattern.left, onIdent);
1039
- this.walkExpression(pattern.right);
1040
- };
1041
-
1042
- Parser.prototype.evaluateExpression = function evaluateExpression(expression) {
1043
- try {
1044
- var result = this.applyPluginsBailResult1("evaluate " + expression.type, expression);
1045
- if(result !== undefined)
1046
- return result;
1047
- } catch(e) {
1048
- console.warn(e);
1049
- // ignore error
1050
- }
1051
- return new BasicEvaluatedExpression().setRange(expression.range);
1052
- };
1053
-
1054
- Parser.prototype.parseString = function parseString(expression) {
1055
- switch(expression.type) {
1056
- case "BinaryExpression":
1057
- if(expression.operator === "+")
1058
- return this.parseString(expression.left) + this.parseString(expression.right);
1059
- break;
1060
- case "Literal":
1061
- return expression.value + "";
1062
- }
1063
- throw new Error(expression.type + " is not supported as parameter for require");
1064
- };
1065
-
1066
- Parser.prototype.parseCalculatedString = function parseCalculatedString(expression) {
1067
- switch(expression.type) {
1068
- case "BinaryExpression":
1069
- if(expression.operator === "+") {
1070
- var left = this.parseCalculatedString(expression.left);
1071
- var right = this.parseCalculatedString(expression.right);
1072
- if(left.code) {
1073
- return {
1074
- range: left.range,
1075
- value: left.value,
1076
- code: true
1077
- };
1078
- } else if(right.code) {
1079
- return {
1080
- range: [left.range[0], right.range ? right.range[1] : left.range[1]],
1081
- value: left.value + right.value,
1082
- code: true
1083
- };
1084
- } else {
1221
+ parseCalculatedString(expression) {
1222
+ switch(expression.type) {
1223
+ case "BinaryExpression":
1224
+ if(expression.operator === "+") {
1225
+ const left = this.parseCalculatedString(expression.left);
1226
+ const right = this.parseCalculatedString(expression.right);
1227
+ if(left.code) {
1228
+ return {
1229
+ range: left.range,
1230
+ value: left.value,
1231
+ code: true
1232
+ };
1233
+ } else if(right.code) {
1234
+ return {
1235
+ range: [left.range[0], right.range ? right.range[1] : left.range[1]],
1236
+ value: left.value + right.value,
1237
+ code: true
1238
+ };
1239
+ } else {
1240
+ return {
1241
+ range: [left.range[0], right.range[1]],
1242
+ value: left.value + right.value
1243
+ };
1244
+ }
1245
+ }
1246
+ break;
1247
+ case "ConditionalExpression":
1248
+ {
1249
+ const consequent = this.parseCalculatedString(expression.consequent);
1250
+ const alternate = this.parseCalculatedString(expression.alternate);
1251
+ const items = [];
1252
+ if(consequent.conditional)
1253
+ Array.prototype.push.apply(items, consequent.conditional);
1254
+ else if(!consequent.code)
1255
+ items.push(consequent);
1256
+ else break;
1257
+ if(alternate.conditional)
1258
+ Array.prototype.push.apply(items, alternate.conditional);
1259
+ else if(!alternate.code)
1260
+ items.push(alternate);
1261
+ else break;
1085
1262
  return {
1086
- range: [left.range[0], right.range[1]],
1087
- value: left.value + right.value
1263
+ value: "",
1264
+ code: true,
1265
+ conditional: items
1088
1266
  };
1089
1267
  }
1090
- }
1091
- break;
1092
- case "ConditionalExpression":
1093
- var consequent = this.parseCalculatedString(expression.consequent);
1094
- var alternate = this.parseCalculatedString(expression.alternate);
1095
- var items = [];
1096
- if(consequent.conditional)
1097
- Array.prototype.push.apply(items, consequent.conditional);
1098
- else if(!consequent.code)
1099
- items.push(consequent);
1100
- else break;
1101
- if(alternate.conditional)
1102
- Array.prototype.push.apply(items, alternate.conditional);
1103
- else if(!alternate.code)
1104
- items.push(alternate);
1105
- else break;
1106
- return {
1107
- value: "",
1108
- code: true,
1109
- conditional: items
1110
- };
1111
- case "Literal":
1112
- return {
1113
- range: expression.range,
1114
- value: expression.value + ""
1115
- };
1116
- }
1117
- return {
1118
- value: "",
1119
- code: true
1120
- };
1121
- };
1122
-
1123
- ["parseString", "parseCalculatedString"].forEach(function(fn) {
1124
- Parser.prototype[fn + "Array"] = function parseXXXArray(expression) {
1125
- switch(expression.type) {
1126
- case "ArrayExpression":
1127
- var arr = [];
1128
- if(expression.elements)
1129
- expression.elements.forEach(function(expr) {
1130
- arr.push(this[fn](expr));
1131
- }, this);
1132
- return arr;
1268
+ case "Literal":
1269
+ return {
1270
+ range: expression.range,
1271
+ value: expression.value + ""
1272
+ };
1133
1273
  }
1134
- return [this[fn](expression)];
1135
- };
1136
- });
1274
+ return {
1275
+ value: "",
1276
+ code: true
1277
+ };
1278
+ }
1137
1279
 
1138
- var POSSIBLE_AST_OPTIONS = [{
1139
- ranges: true,
1140
- locations: true,
1141
- ecmaVersion: 2017,
1142
- sourceType: "module",
1143
- plugins: {
1144
- dynamicImport: true
1280
+ parseStringArray(expression) {
1281
+ if(expression.type !== "ArrayExpression") {
1282
+ return [this.parseString(expression)];
1283
+ }
1284
+
1285
+ const arr = [];
1286
+ if(expression.elements)
1287
+ expression.elements.forEach(function(expr) {
1288
+ arr.push(this.parseString(expr));
1289
+ }, this);
1290
+ return arr;
1145
1291
  }
1146
- }, {
1147
- ranges: true,
1148
- locations: true,
1149
- ecmaVersion: 2017,
1150
- sourceType: "script",
1151
- plugins: {
1152
- dynamicImport: true
1292
+
1293
+ parseCalculatedStringArray(expression) {
1294
+ if(expression.type !== "ArrayExpression") {
1295
+ return [this.parseCalculatedString(expression)];
1296
+ }
1297
+
1298
+ const arr = [];
1299
+ if(expression.elements)
1300
+ expression.elements.forEach(function(expr) {
1301
+ arr.push(this.parseCalculatedString(expr));
1302
+ }, this);
1303
+ return arr;
1153
1304
  }
1154
- }];
1155
1305
 
1156
- Parser.prototype.parse = function parse(source, initialState) {
1157
- var ast, comments = [];
1158
- for(var i = 0, len = POSSIBLE_AST_OPTIONS.length; i < len; i++) {
1159
- if(!ast) {
1160
- try {
1161
- comments.length = 0;
1162
- POSSIBLE_AST_OPTIONS[i].onComment = comments;
1163
- ast = acorn.parse(source, POSSIBLE_AST_OPTIONS[i]);
1164
- } catch(e) {
1165
- // ignore the error
1306
+ parse(source, initialState) {
1307
+ let ast;
1308
+ const comments = [];
1309
+ for(let i = 0, len = POSSIBLE_AST_OPTIONS.length; i < len; i++) {
1310
+ if(!ast) {
1311
+ try {
1312
+ comments.length = 0;
1313
+ POSSIBLE_AST_OPTIONS[i].onComment = comments;
1314
+ ast = acorn.parse(source, POSSIBLE_AST_OPTIONS[i]);
1315
+ } catch(e) {
1316
+ // ignore the error
1317
+ }
1166
1318
  }
1167
1319
  }
1320
+ if(!ast) {
1321
+ // for the error
1322
+ ast = acorn.parse(source, {
1323
+ ranges: true,
1324
+ locations: true,
1325
+ ecmaVersion: 2017,
1326
+ sourceType: "module",
1327
+ plugins: {
1328
+ dynamicImport: true
1329
+ },
1330
+ onComment: comments
1331
+ });
1332
+ }
1333
+ if(!ast || typeof ast !== "object")
1334
+ throw new Error("Source couldn't be parsed");
1335
+ const oldScope = this.scope;
1336
+ const oldState = this.state;
1337
+ const oldComments = this.comments;
1338
+ this.scope = {
1339
+ inTry: false,
1340
+ definitions: [],
1341
+ renames: {}
1342
+ };
1343
+ const state = this.state = initialState || {};
1344
+ this.comments = comments;
1345
+ if(this.applyPluginsBailResult("program", ast, comments) === undefined) {
1346
+ this.prewalkStatements(ast.body);
1347
+ this.walkStatements(ast.body);
1348
+ }
1349
+ this.scope = oldScope;
1350
+ this.state = oldState;
1351
+ this.comments = oldComments;
1352
+ return state;
1168
1353
  }
1169
- if(!ast) {
1170
- // for the error
1171
- ast = acorn.parse(source, {
1354
+
1355
+ evaluate(source) {
1356
+ const ast = acorn.parse("(" + source + ")", {
1172
1357
  ranges: true,
1173
1358
  locations: true,
1174
1359
  ecmaVersion: 2017,
1175
1360
  sourceType: "module",
1176
1361
  plugins: {
1177
1362
  dynamicImport: true
1178
- },
1179
- onComment: comments
1363
+ }
1180
1364
  });
1365
+ if(!ast || typeof ast !== "object" || ast.type !== "Program")
1366
+ throw new Error("evaluate: Source couldn't be parsed");
1367
+ if(ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement")
1368
+ throw new Error("evaluate: Source is not a expression");
1369
+ return this.evaluateExpression(ast.body[0].expression);
1181
1370
  }
1182
- if(!ast || typeof ast !== "object")
1183
- throw new Error("Source couldn't be parsed");
1184
- var oldScope = this.scope;
1185
- var oldState = this.state;
1186
- this.scope = {
1187
- inTry: false,
1188
- definitions: [],
1189
- renames: {}
1190
- };
1191
- var state = this.state = initialState || {};
1192
- if(this.applyPluginsBailResult("program", ast, comments) === undefined)
1193
- this.walkStatements(ast.body);
1194
- this.scope = oldScope;
1195
- this.state = oldState;
1196
- return state;
1197
- };
1198
-
1199
- Parser.prototype.evaluate = function evaluate(source) {
1200
- var ast = acorn.parse("(" + source + ")", {
1201
- ranges: true,
1202
- locations: true,
1203
- ecmaVersion: 2017,
1204
- sourceType: "module",
1205
- plugins: {
1206
- dynamicImport: true
1207
- }
1208
- });
1209
- if(!ast || typeof ast !== "object" || ast.type !== "Program")
1210
- throw new Error("evaluate: Source couldn't be parsed");
1211
- if(ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement")
1212
- throw new Error("evaluate: Source is not a expression");
1213
- return this.evaluateExpression(ast.body[0].expression);
1214
- };
1371
+
1372
+ getComments(range) {
1373
+ return this.comments.filter(comment => comment.range[0] >= range[0] && comment.range[1] <= range[1]);
1374
+ }
1375
+
1376
+ getCommentOptions(range) {
1377
+ const comments = this.getComments(range);
1378
+ if(comments.length === 0) return null;
1379
+ const options = comments.map(comment => {
1380
+ try {
1381
+ return json5.parse(`{${comment.value}}`);
1382
+ } catch(e) {
1383
+ return {};
1384
+ }
1385
+ });
1386
+ return options.reduce((o, i) => Object.assign(o, i), {});
1387
+ }
1388
+
1389
+ }
1390
+
1391
+ module.exports = Parser;