webpack 4.24.0 → 4.26.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.
package/LICENSE CHANGED
@@ -1,20 +1,20 @@
1
- Copyright JS Foundation and other contributors
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- 'Software'), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright JS Foundation and other contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/SECURITY.md CHANGED
@@ -1,9 +1,9 @@
1
- # Reporting Security Issues
2
-
3
- If you discover a security issue in webpack, please report it by sending an
4
- email to [webpack@opencollective.com](mailto:webpack@opencollective.com).
5
-
6
- This will allow us to assess the risk, and make a fix available before we add a
7
- bug report to the GitHub repository.
8
-
9
- Thanks for helping make webpack safe for everyone.
1
+ # Reporting Security Issues
2
+
3
+ If you discover a security issue in webpack, please report it by sending an
4
+ email to [webpack@opencollective.com](mailto:webpack@opencollective.com).
5
+
6
+ This will allow us to assess the risk, and make a fix available before we add a
7
+ bug report to the GitHub repository.
8
+
9
+ Thanks for helping make webpack safe for everyone.
@@ -1,3 +1,3 @@
1
- module.exports = function() {
2
- throw new Error("define cannot be used indirect");
3
- };
1
+ module.exports = function() {
2
+ throw new Error("define cannot be used indirect");
3
+ };
@@ -1,2 +1,2 @@
1
- /* globals __webpack_amd_options__ */
2
- module.exports = __webpack_amd_options__;
1
+ /* globals __webpack_amd_options__ */
2
+ module.exports = __webpack_amd_options__;
package/buildin/global.js CHANGED
@@ -7,7 +7,7 @@ g = (function() {
7
7
 
8
8
  try {
9
9
  // This works if eval is allowed (see CSP)
10
- g = g || Function("return this")() || (1, eval)("this");
10
+ g = g || new Function("return this")();
11
11
  } catch (e) {
12
12
  // This works if the window reference is available
13
13
  if (typeof window === "object") g = window;
package/buildin/module.js CHANGED
@@ -1,22 +1,22 @@
1
- module.exports = function(module) {
2
- if (!module.webpackPolyfill) {
3
- module.deprecate = function() {};
4
- module.paths = [];
5
- // module.parent = undefined by default
6
- if (!module.children) module.children = [];
7
- Object.defineProperty(module, "loaded", {
8
- enumerable: true,
9
- get: function() {
10
- return module.l;
11
- }
12
- });
13
- Object.defineProperty(module, "id", {
14
- enumerable: true,
15
- get: function() {
16
- return module.i;
17
- }
18
- });
19
- module.webpackPolyfill = 1;
20
- }
21
- return module;
22
- };
1
+ module.exports = function(module) {
2
+ if (!module.webpackPolyfill) {
3
+ module.deprecate = function() {};
4
+ module.paths = [];
5
+ // module.parent = undefined by default
6
+ if (!module.children) module.children = [];
7
+ Object.defineProperty(module, "loaded", {
8
+ enumerable: true,
9
+ get: function() {
10
+ return module.l;
11
+ }
12
+ });
13
+ Object.defineProperty(module, "id", {
14
+ enumerable: true,
15
+ get: function() {
16
+ return module.i;
17
+ }
18
+ });
19
+ module.webpackPolyfill = 1;
20
+ }
21
+ return module;
22
+ };
package/buildin/system.js CHANGED
@@ -1,7 +1,7 @@
1
- // Provide a "System" global.
2
- module.exports = {
3
- // Make sure import is only used as "System.import"
4
- import: function() {
5
- throw new Error("System.import cannot be used indirectly");
6
- }
7
- };
1
+ // Provide a "System" global.
2
+ module.exports = {
3
+ // Make sure import is only used as "System.import"
4
+ import: function() {
5
+ throw new Error("System.import cannot be used indirectly");
6
+ }
7
+ };
@@ -13,6 +13,10 @@ export interface DllPluginOptions {
13
13
  * If true, only entry points will be exposed
14
14
  */
15
15
  entryOnly?: boolean;
16
+ /**
17
+ * If true, manifest json file (output) will be formatted
18
+ */
19
+ format?: boolean;
16
20
  /**
17
21
  * Name of the exposed dll function (external name, use value of 'output.library')
18
22
  */
@@ -0,0 +1,42 @@
1
+ /**
2
+ * This file was automatically generated.
3
+ * DO NOT MODIFY BY HAND.
4
+ * Run `yarn special-lint-fix` to update
5
+ */
6
+
7
+ export type ProgressPluginArgument = ProgressPluginOptions | HandlerFunction;
8
+ /**
9
+ * Function that executes for every progress step
10
+ */
11
+ export type HandlerFunction = ((
12
+ percentage: number,
13
+ msg: string,
14
+ ...args: string[]
15
+ ) => void);
16
+
17
+ export interface ProgressPluginOptions {
18
+ /**
19
+ * Show active modules count and one active module in progress message
20
+ */
21
+ activeModules?: boolean;
22
+ /**
23
+ * Show entries count in progress message
24
+ */
25
+ entries?: boolean;
26
+ /**
27
+ * Function that executes for every progress step
28
+ */
29
+ handler?: HandlerFunction;
30
+ /**
31
+ * Show modules count in progress message
32
+ */
33
+ modules?: boolean;
34
+ /**
35
+ * Minimum modules count to start with. Only for mode=modules. Default: 500
36
+ */
37
+ modulesCount?: number;
38
+ /**
39
+ * Collect profile data for progress steps. Default: false
40
+ */
41
+ profile?: true | false | null;
42
+ }
package/hot/emitter.js CHANGED
@@ -1,2 +1,2 @@
1
- var EventEmitter = require("events");
2
- module.exports = new EventEmitter();
1
+ var EventEmitter = require("events");
2
+ module.exports = new EventEmitter();
@@ -29,11 +29,14 @@ class BasicEvaluatedExpression {
29
29
  this.regExp = null;
30
30
  this.string = null;
31
31
  this.quasis = null;
32
+ this.parts = null;
32
33
  this.array = null;
33
34
  this.items = null;
34
35
  this.options = null;
35
36
  this.prefix = null;
36
37
  this.postfix = null;
38
+ this.wrappedInnerExpressions = null;
39
+ this.expression = null;
37
40
  }
38
41
 
39
42
  isNull() {
@@ -105,10 +108,36 @@ class BasicEvaluatedExpression {
105
108
  : undefined;
106
109
  }
107
110
  if (this.isTemplateString()) {
108
- for (const quasi of this.quasis) {
109
- if (quasi.asBool()) return true;
111
+ const str = this.asString();
112
+ if (typeof str === "string") return str !== "";
113
+ }
114
+ return undefined;
115
+ }
116
+
117
+ asString() {
118
+ if (this.isBoolean()) return `${this.bool}`;
119
+ if (this.isNull()) return "null";
120
+ if (this.isString()) return this.string;
121
+ if (this.isNumber()) return `${this.number}`;
122
+ if (this.isRegExp()) return `${this.regExp}`;
123
+ if (this.isArray()) {
124
+ let array = [];
125
+ for (const item of this.items) {
126
+ const itemStr = item.asString();
127
+ if (itemStr === undefined) return undefined;
128
+ array.push(itemStr);
129
+ }
130
+ return `${array}`;
131
+ }
132
+ if (this.isConstArray()) return `${this.array}`;
133
+ if (this.isTemplateString()) {
134
+ let str = "";
135
+ for (const part of this.parts) {
136
+ const partStr = part.asString();
137
+ if (partStr === undefined) return undefined;
138
+ str += partStr;
110
139
  }
111
- // can't tell if string will be empty without executing
140
+ return str;
112
141
  }
113
142
  return undefined;
114
143
  }
@@ -148,10 +177,11 @@ class BasicEvaluatedExpression {
148
177
  return this;
149
178
  }
150
179
 
151
- setWrapped(prefix, postfix) {
180
+ setWrapped(prefix, postfix, innerExpressions) {
152
181
  this.type = TypeWrapped;
153
182
  this.prefix = prefix;
154
183
  this.postfix = postfix;
184
+ this.wrappedInnerExpressions = innerExpressions;
155
185
  return this;
156
186
  }
157
187
 
@@ -184,9 +214,11 @@ class BasicEvaluatedExpression {
184
214
  return this;
185
215
  }
186
216
 
187
- setTemplateString(quasis) {
217
+ setTemplateString(quasis, parts, kind) {
188
218
  this.type = TypeTemplateString;
189
219
  this.quasis = quasis;
220
+ this.parts = parts;
221
+ this.templateStringKind = kind;
190
222
  return this;
191
223
  }
192
224
 
@@ -206,6 +238,11 @@ class BasicEvaluatedExpression {
206
238
  this.range = range;
207
239
  return this;
208
240
  }
241
+
242
+ setExpression(expression) {
243
+ this.expression = expression;
244
+ return this;
245
+ }
209
246
  }
210
247
 
211
248
  module.exports = BasicEvaluatedExpression;
package/lib/Chunk.js CHANGED
@@ -430,7 +430,7 @@ class Chunk {
430
430
  }
431
431
 
432
432
  /**
433
- * @param {Chunk} newChunk the new chunk that will be split out of, and then chunk raphi twil=
433
+ * @param {Chunk} newChunk the new chunk that will be split out of the current chunk
434
434
  * @returns {void}
435
435
  */
436
436
  split(newChunk) {
@@ -224,6 +224,13 @@ class Compilation extends Tapable {
224
224
  /** @type {SyncHook<Module>} */
225
225
  succeedModule: new SyncHook(["module"]),
226
226
 
227
+ /** @type {SyncHook<Dependency, string>} */
228
+ addEntry: new SyncHook(["entry", "name"]),
229
+ /** @type {SyncHook<Dependency, string, Error>} */
230
+ failedEntry: new SyncHook(["entry", "name", "error"]),
231
+ /** @type {SyncHook<Dependency, string, Module>} */
232
+ succeedEntry: new SyncHook(["entry", "name", "module"]),
233
+
227
234
  /** @type {SyncWaterfallHook<DependencyReference, Dependency, Module>} */
228
235
  dependencyReference: new SyncWaterfallHook([
229
236
  "dependencyReference",
@@ -1041,6 +1048,8 @@ class Compilation extends Tapable {
1041
1048
  * @returns {void} returns
1042
1049
  */
1043
1050
  addEntry(context, entry, name, callback) {
1051
+ this.hooks.addEntry.call(entry, name);
1052
+
1044
1053
  const slot = {
1045
1054
  name: name,
1046
1055
  // TODO webpack 5 remove `request`
@@ -1068,6 +1077,7 @@ class Compilation extends Tapable {
1068
1077
  },
1069
1078
  (err, module) => {
1070
1079
  if (err) {
1080
+ this.hooks.failedEntry.call(entry, name, err);
1071
1081
  return callback(err);
1072
1082
  }
1073
1083
 
@@ -1079,6 +1089,7 @@ class Compilation extends Tapable {
1079
1089
  this._preparedEntrypoints.splice(idx, 1);
1080
1090
  }
1081
1091
  }
1092
+ this.hooks.succeedEntry.call(entry, name, module);
1082
1093
  return callback(null, module);
1083
1094
  }
1084
1095
  );
@@ -67,7 +67,11 @@ class LibManifestPlugin {
67
67
  return obj;
68
68
  }, Object.create(null))
69
69
  };
70
- const content = Buffer.from(JSON.stringify(manifest), "utf8");
70
+ // Apply formatting to content if format flag is true;
71
+ const manifestContent = this.options.format
72
+ ? JSON.stringify(manifest, null, 2)
73
+ : JSON.stringify(manifest);
74
+ const content = Buffer.from(manifestContent, "utf8");
71
75
  compiler.outputFileSystem.mkdirp(path.dirname(targetPath), err => {
72
76
  if (err) return callback(err);
73
77
  compiler.outputFileSystem.writeFile(
package/lib/Parser.js CHANGED
@@ -216,62 +216,114 @@ class Parser extends Tapable {
216
216
  right.prefix &&
217
217
  right.prefix.isString()
218
218
  ) {
219
+ // "left" + ("prefix" + inner + "postfix")
220
+ // => ("leftprefix" + inner + "postfix")
219
221
  res.setWrapped(
220
222
  new BasicEvaluatedExpression()
221
223
  .setString(left.string + right.prefix.string)
222
224
  .setRange(joinRanges(left.range, right.prefix.range)),
223
- right.postfix
225
+ right.postfix,
226
+ right.wrappedInnerExpressions
224
227
  );
225
228
  } else if (right.isWrapped()) {
226
- res.setWrapped(
227
- new BasicEvaluatedExpression()
228
- .setString(left.string)
229
- .setRange(left.range),
230
- right.postfix
231
- );
229
+ // "left" + ([null] + inner + "postfix")
230
+ // => ("left" + inner + "postfix")
231
+ res.setWrapped(left, right.postfix, right.wrappedInnerExpressions);
232
232
  } else {
233
- res.setWrapped(left, null);
233
+ // "left" + expr
234
+ // => ("left" + expr + "")
235
+ res.setWrapped(left, null, [right]);
234
236
  }
235
237
  } else if (left.isNumber()) {
236
238
  if (right.isString()) {
237
239
  res.setString(left.number + right.string);
238
240
  } else if (right.isNumber()) {
239
241
  res.setNumber(left.number + right.number);
242
+ } else {
243
+ return;
240
244
  }
241
245
  } else if (left.isWrapped()) {
242
246
  if (left.postfix && left.postfix.isString() && right.isString()) {
247
+ // ("prefix" + inner + "postfix") + "right"
248
+ // => ("prefix" + inner + "postfixright")
243
249
  res.setWrapped(
244
250
  left.prefix,
245
251
  new BasicEvaluatedExpression()
246
252
  .setString(left.postfix.string + right.string)
247
- .setRange(joinRanges(left.postfix.range, right.range))
253
+ .setRange(joinRanges(left.postfix.range, right.range)),
254
+ left.wrappedInnerExpressions
248
255
  );
249
256
  } else if (
250
257
  left.postfix &&
251
258
  left.postfix.isString() &&
252
259
  right.isNumber()
253
260
  ) {
261
+ // ("prefix" + inner + "postfix") + 123
262
+ // => ("prefix" + inner + "postfix123")
254
263
  res.setWrapped(
255
264
  left.prefix,
256
265
  new BasicEvaluatedExpression()
257
266
  .setString(left.postfix.string + right.number)
258
- .setRange(joinRanges(left.postfix.range, right.range))
267
+ .setRange(joinRanges(left.postfix.range, right.range)),
268
+ left.wrappedInnerExpressions
259
269
  );
260
270
  } else if (right.isString()) {
261
- res.setWrapped(left.prefix, right);
271
+ // ("prefix" + inner + [null]) + "right"
272
+ // => ("prefix" + inner + "right")
273
+ res.setWrapped(left.prefix, right, left.wrappedInnerExpressions);
262
274
  } else if (right.isNumber()) {
275
+ // ("prefix" + inner + [null]) + 123
276
+ // => ("prefix" + inner + "123")
263
277
  res.setWrapped(
264
278
  left.prefix,
265
279
  new BasicEvaluatedExpression()
266
280
  .setString(right.number + "")
267
- .setRange(right.range)
281
+ .setRange(right.range),
282
+ left.wrappedInnerExpressions
283
+ );
284
+ } else if (right.isWrapped()) {
285
+ // ("prefix1" + inner1 + "postfix1") + ("prefix2" + inner2 + "postfix2")
286
+ // ("prefix1" + inner1 + "postfix1" + "prefix2" + inner2 + "postfix2")
287
+ res.setWrapped(
288
+ left.prefix,
289
+ right.postfix,
290
+ left.wrappedInnerExpressions &&
291
+ right.wrappedInnerExpressions &&
292
+ left.wrappedInnerExpressions
293
+ .concat(left.postfix ? [left.postfix] : [])
294
+ .concat(right.prefix ? [right.prefix] : [])
295
+ .concat(right.wrappedInnerExpressions)
268
296
  );
269
297
  } else {
270
- res.setWrapped(left.prefix, new BasicEvaluatedExpression());
298
+ // ("prefix" + inner + postfix) + expr
299
+ // => ("prefix" + inner + postfix + expr + [null])
300
+ res.setWrapped(
301
+ left.prefix,
302
+ null,
303
+ left.wrappedInnerExpressions &&
304
+ left.wrappedInnerExpressions.concat(
305
+ left.postfix ? [left.postfix, right] : [right]
306
+ )
307
+ );
271
308
  }
272
309
  } else {
273
310
  if (right.isString()) {
274
- res.setWrapped(null, right);
311
+ // left + "right"
312
+ // => ([null] + left + "right")
313
+ res.setWrapped(null, right, [left]);
314
+ } else if (right.isWrapped()) {
315
+ // left + (prefix + inner + "postfix")
316
+ // => ([null] + left + prefix + inner + "postfix")
317
+ res.setWrapped(
318
+ null,
319
+ right.postfix,
320
+ right.wrappedInnerExpressions &&
321
+ (right.prefix ? [left, right.prefix] : [left]).concat(
322
+ right.wrappedInnerExpressions
323
+ )
324
+ );
325
+ } else {
326
+ return;
275
327
  }
276
328
  }
277
329
  res.setRange(expr.range);
@@ -602,62 +654,66 @@ class Parser extends Tapable {
602
654
 
603
655
  /**
604
656
  * @param {string} kind "cooked" | "raw"
605
- * @param {TODO[]} quasis quasis
606
- * @param {TODO[]} expressions expressions
607
- * @returns {BasicEvaluatedExpression[]} Simplified template
657
+ * @param {TODO} templateLiteralExpr TemplateLiteral expr
658
+ * @returns {{quasis: BasicEvaluatedExpression[], parts: BasicEvaluatedExpression[]}} Simplified template
608
659
  */
609
- const getSimplifiedTemplateResult = (kind, quasis, expressions) => {
660
+ const getSimplifiedTemplateResult = (kind, templateLiteralExpr) => {
661
+ const quasis = [];
610
662
  const parts = [];
611
663
 
612
- for (let i = 0; i < quasis.length; i++) {
613
- parts.push(
614
- new BasicEvaluatedExpression()
615
- .setString(quasis[i].value[kind])
616
- .setRange(quasis[i].range)
617
- );
664
+ for (let i = 0; i < templateLiteralExpr.quasis.length; i++) {
665
+ const quasiExpr = templateLiteralExpr.quasis[i];
666
+ const quasi = quasiExpr.value[kind];
618
667
 
619
668
  if (i > 0) {
620
- const prevExpr = parts[parts.length - 2],
621
- lastExpr = parts[parts.length - 1];
622
- const expr = this.evaluateExpression(expressions[i - 1]);
623
- if (!(expr.isString() || expr.isNumber())) continue;
624
-
625
- prevExpr.setString(
626
- prevExpr.string +
627
- (expr.isString() ? expr.string : expr.number) +
628
- lastExpr.string
669
+ const prevExpr = parts[parts.length - 1];
670
+ const expr = this.evaluateExpression(
671
+ templateLiteralExpr.expressions[i - 1]
629
672
  );
630
- prevExpr.setRange([prevExpr.range[0], lastExpr.range[1]]);
631
- parts.pop();
673
+ const exprAsString = expr.asString();
674
+ if (typeof exprAsString === "string") {
675
+ // We can merge quasi + expr + quasi when expr
676
+ // is a const string
677
+
678
+ prevExpr.setString(prevExpr.string + exprAsString + quasi);
679
+ prevExpr.setRange([prevExpr.range[0], quasiExpr.range[1]]);
680
+ // We unset the expression as it doesn't match to a single expression
681
+ prevExpr.setExpression(undefined);
682
+ continue;
683
+ }
684
+ parts.push(expr);
632
685
  }
686
+
687
+ const part = new BasicEvaluatedExpression()
688
+ .setString(quasi)
689
+ .setRange(quasiExpr.range)
690
+ .setExpression(quasiExpr);
691
+ quasis.push(part);
692
+ parts.push(part);
633
693
  }
634
- return parts;
694
+ return {
695
+ quasis,
696
+ parts
697
+ };
635
698
  };
636
699
 
637
700
  this.hooks.evaluate.for("TemplateLiteral").tap("Parser", node => {
638
- const parts = getSimplifiedTemplateResult.call(
639
- this,
640
- "cooked",
641
- node.quasis,
642
- node.expressions
643
- );
701
+ const { quasis, parts } = getSimplifiedTemplateResult("cooked", node);
644
702
  if (parts.length === 1) {
645
703
  return parts[0].setRange(node.range);
646
704
  }
647
705
  return new BasicEvaluatedExpression()
648
- .setTemplateString(parts)
706
+ .setTemplateString(quasis, parts, "cooked")
649
707
  .setRange(node.range);
650
708
  });
651
709
  this.hooks.evaluate.for("TaggedTemplateExpression").tap("Parser", node => {
652
710
  if (this.evaluateExpression(node.tag).identifier !== "String.raw") return;
653
- const parts = getSimplifiedTemplateResult.call(
654
- this,
655
- "raw",
656
- node.quasi.quasis,
657
- node.quasi.expressions
658
- );
711
+ const { quasis, parts } = getSimplifiedTemplateResult("raw", node.quasi);
712
+ if (parts.length === 1) {
713
+ return parts[0].setRange(node.range);
714
+ }
659
715
  return new BasicEvaluatedExpression()
660
- .setTemplateString(parts)
716
+ .setTemplateString(quasis, parts, "raw")
661
717
  .setRange(node.range);
662
718
  });
663
719
 
@@ -1926,13 +1982,20 @@ class Parser extends Tapable {
1926
1982
  const hook = this.hooks.evaluate.get(expression.type);
1927
1983
  if (hook !== undefined) {
1928
1984
  const result = hook.call(expression);
1929
- if (result !== undefined) return result;
1985
+ if (result !== undefined) {
1986
+ if (result) {
1987
+ result.setExpression(expression);
1988
+ }
1989
+ return result;
1990
+ }
1930
1991
  }
1931
1992
  } catch (e) {
1932
1993
  console.warn(e);
1933
1994
  // ignore error
1934
1995
  }
1935
- return new BasicEvaluatedExpression().setRange(expression.range);
1996
+ return new BasicEvaluatedExpression()
1997
+ .setRange(expression.range)
1998
+ .setExpression(expression);
1936
1999
  }
1937
2000
 
1938
2001
  parseString(expression) {