webpack 5.70.0 → 5.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

Files changed (42) hide show
  1. package/hot/poll.js +1 -1
  2. package/hot/signal.js +1 -1
  3. package/lib/Chunk.js +1 -1
  4. package/lib/ChunkGroup.js +1 -1
  5. package/lib/Compilation.js +10 -8
  6. package/lib/Compiler.js +16 -3
  7. package/lib/ConstPlugin.js +2 -2
  8. package/lib/ContextModule.js +31 -8
  9. package/lib/ContextModuleFactory.js +7 -11
  10. package/lib/DelegatedModuleFactoryPlugin.js +1 -1
  11. package/lib/Dependency.js +7 -0
  12. package/lib/ErrorHelpers.js +2 -2
  13. package/lib/ExternalModuleFactoryPlugin.js +4 -4
  14. package/lib/FileSystemInfo.js +8 -0
  15. package/lib/LoaderOptionsPlugin.js +1 -1
  16. package/lib/Module.js +2 -0
  17. package/lib/ModuleFilenameHelpers.js +3 -3
  18. package/lib/NormalModule.js +2 -2
  19. package/lib/NormalModuleFactory.js +2 -2
  20. package/lib/RuntimePlugin.js +18 -0
  21. package/lib/config/defaults.js +9 -1
  22. package/lib/dependencies/CommonJsExportsParserPlugin.js +1 -2
  23. package/lib/dependencies/ContextDependencyHelpers.js +2 -2
  24. package/lib/dependencies/ContextElementDependency.js +33 -1
  25. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +95 -0
  26. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +127 -43
  27. package/lib/dependencies/HarmonyImportSpecifierDependency.js +22 -8
  28. package/lib/dependencies/HarmonyModulesPlugin.js +10 -0
  29. package/lib/esm/ModuleChunkLoadingPlugin.js +3 -1
  30. package/lib/hmr/HotModuleReplacement.runtime.js +29 -14
  31. package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +4 -3
  32. package/lib/ids/HashedModuleIdsPlugin.js +2 -2
  33. package/lib/ids/IdHelpers.js +1 -1
  34. package/lib/javascript/BasicEvaluatedExpression.js +5 -2
  35. package/lib/javascript/JavascriptParser.js +66 -40
  36. package/lib/library/UmdLibraryPlugin.js +5 -3
  37. package/lib/runtime/BaseUriRuntimeModule.js +31 -0
  38. package/lib/stats/DefaultStatsFactoryPlugin.js +1 -1
  39. package/lib/util/internalSerializables.js +2 -0
  40. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -1
  41. package/package.json +1 -1
  42. package/types.d.ts +21 -11
@@ -0,0 +1,95 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Ivan Kopeykin @vankop
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const makeSerializable = require("../util/makeSerializable");
9
+ const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
10
+
11
+ /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
12
+ /** @typedef {import("../ChunkGraph")} ChunkGraph */
13
+ /** @typedef {import("../Dependency")} Dependency */
14
+ /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
15
+
16
+ /**
17
+ * Dependency for static evaluating import specifier. e.g.
18
+ * @example
19
+ * import a from "a";
20
+ * "x" in a;
21
+ * a.x !== undefined; // if x value statically analyzable
22
+ */
23
+ class HarmonyEvaluatedImportSpecifierDependency extends HarmonyImportSpecifierDependency {
24
+ constructor(request, sourceOrder, ids, name, range, assertions, operator) {
25
+ super(request, sourceOrder, ids, name, range, false, assertions);
26
+ this.operator = operator;
27
+ }
28
+
29
+ get type() {
30
+ return `evaluated X ${this.operator} harmony import specifier`;
31
+ }
32
+
33
+ serialize(context) {
34
+ super.serialize(context);
35
+ const { write } = context;
36
+ write(this.operator);
37
+ }
38
+
39
+ deserialize(context) {
40
+ super.deserialize(context);
41
+ const { read } = context;
42
+ this.operator = read();
43
+ }
44
+ }
45
+
46
+ makeSerializable(
47
+ HarmonyEvaluatedImportSpecifierDependency,
48
+ "webpack/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency"
49
+ );
50
+
51
+ HarmonyEvaluatedImportSpecifierDependency.Template = class HarmonyEvaluatedImportSpecifierDependencyTemplate extends (
52
+ HarmonyImportSpecifierDependency.Template
53
+ ) {
54
+ /**
55
+ * @param {Dependency} dependency the dependency for which the template should be applied
56
+ * @param {ReplaceSource} source the current replace source which can be modified
57
+ * @param {DependencyTemplateContext} templateContext the context object
58
+ * @returns {void}
59
+ */
60
+ apply(dependency, source, templateContext) {
61
+ const dep = /** @type {HarmonyEvaluatedImportSpecifierDependency} */ (
62
+ dependency
63
+ );
64
+ const { moduleGraph, runtime } = templateContext;
65
+ const connection = moduleGraph.getConnection(dep);
66
+ // Skip rendering depending when dependency is conditional
67
+ if (connection && !connection.isTargetActive(runtime)) return;
68
+
69
+ const exportsInfo = moduleGraph.getExportsInfo(connection.module);
70
+ const ids = dep.getIds(moduleGraph);
71
+ const value = exportsInfo.isExportProvided(ids);
72
+
73
+ if (typeof value === "boolean") {
74
+ source.replace(dep.range[0], dep.range[1] - 1, `${value}`);
75
+ } else {
76
+ const usedName = exportsInfo.getUsedName(ids, runtime);
77
+
78
+ const code = this._getCodeForIds(
79
+ dep,
80
+ source,
81
+ templateContext,
82
+ ids.slice(0, -1)
83
+ );
84
+ source.replace(
85
+ dep.range[0],
86
+ dep.range[1] - 1,
87
+ `${
88
+ usedName ? JSON.stringify(usedName[usedName.length - 1]) : '""'
89
+ } in ${code}`
90
+ );
91
+ }
92
+ }
93
+ };
94
+
95
+ module.exports = HarmonyEvaluatedImportSpecifierDependency;
@@ -10,6 +10,7 @@ const InnerGraph = require("../optimize/InnerGraph");
10
10
  const ConstDependency = require("./ConstDependency");
11
11
  const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
12
12
  const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
13
+ const HarmonyEvaluatedImportSpecifierDependency = require("./HarmonyEvaluatedImportSpecifierDependency");
13
14
  const HarmonyExports = require("./HarmonyExports");
14
15
  const { ExportPresenceModes } = require("./HarmonyImportDependency");
15
16
  const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
@@ -83,6 +84,18 @@ module.exports = class HarmonyImportDependencyParserPlugin {
83
84
  */
84
85
  apply(parser) {
85
86
  const { exportPresenceMode } = this;
87
+
88
+ function getNonOptionalPart(members, membersOptionals) {
89
+ let i = 0;
90
+ while (i < members.length && membersOptionals[i] === false) i++;
91
+ return i !== members.length ? members.slice(0, i) : members;
92
+ }
93
+
94
+ function getNonOptionalMemberChain(node, count) {
95
+ while (count--) node = node.object;
96
+ return node;
97
+ }
98
+
86
99
  parser.hooks.isPure
87
100
  .for("Identifier")
88
101
  .tap("HarmonyImportDependencyParserPlugin", expression => {
@@ -131,74 +144,145 @@ module.exports = class HarmonyImportDependencyParserPlugin {
131
144
  return true;
132
145
  }
133
146
  );
134
- parser.hooks.expression
135
- .for(harmonySpecifierTag)
136
- .tap("HarmonyImportDependencyParserPlugin", expr => {
137
- const settings = /** @type {HarmonySettings} */ (parser.currentTagData);
138
- const dep = new HarmonyImportSpecifierDependency(
147
+ parser.hooks.binaryExpression.tap(
148
+ "HarmonyImportDependencyParserPlugin",
149
+ expression => {
150
+ if (expression.operator !== "in") return;
151
+
152
+ const leftPartEvaluated = parser.evaluateExpression(expression.left);
153
+ if (leftPartEvaluated.couldHaveSideEffects()) return;
154
+ const leftPart = leftPartEvaluated.asString();
155
+ if (!leftPart) return;
156
+
157
+ const rightPart = parser.evaluateExpression(expression.right);
158
+ if (!rightPart.isIdentifier()) return;
159
+
160
+ const rootInfo = rightPart.rootInfo;
161
+ if (
162
+ !rootInfo ||
163
+ !rootInfo.tagInfo ||
164
+ rootInfo.tagInfo.tag !== harmonySpecifierTag
165
+ )
166
+ return;
167
+ const settings = rootInfo.tagInfo.data;
168
+ const members = rightPart.getMembers();
169
+ const dep = new HarmonyEvaluatedImportSpecifierDependency(
139
170
  settings.source,
140
171
  settings.sourceOrder,
141
- settings.ids,
172
+ settings.ids.concat(members).concat([leftPart]),
142
173
  settings.name,
143
- expr.range,
144
- exportPresenceMode,
145
- settings.assertions
174
+ expression.range,
175
+ settings.assertions,
176
+ "in"
146
177
  );
147
- dep.shorthand = parser.scope.inShorthand;
148
- dep.directImport = true;
149
- dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
150
- dep.loc = expr.loc;
178
+ dep.directImport = members.length === 0;
179
+ dep.asiSafe = !parser.isAsiPosition(expression.range[0]);
180
+ dep.loc = expression.loc;
151
181
  parser.state.module.addDependency(dep);
152
182
  InnerGraph.onUsage(parser.state, e => (dep.usedByExports = e));
153
183
  return true;
154
- });
155
- parser.hooks.expressionMemberChain
184
+ }
185
+ );
186
+ parser.hooks.expression
156
187
  .for(harmonySpecifierTag)
157
- .tap("HarmonyImportDependencyParserPlugin", (expr, members) => {
188
+ .tap("HarmonyImportDependencyParserPlugin", expr => {
158
189
  const settings = /** @type {HarmonySettings} */ (parser.currentTagData);
159
- const ids = settings.ids.concat(members);
160
190
  const dep = new HarmonyImportSpecifierDependency(
161
191
  settings.source,
162
192
  settings.sourceOrder,
163
- ids,
193
+ settings.ids,
164
194
  settings.name,
165
195
  expr.range,
166
196
  exportPresenceMode,
167
197
  settings.assertions
168
198
  );
199
+ dep.shorthand = parser.scope.inShorthand;
200
+ dep.directImport = true;
169
201
  dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
170
202
  dep.loc = expr.loc;
171
203
  parser.state.module.addDependency(dep);
172
204
  InnerGraph.onUsage(parser.state, e => (dep.usedByExports = e));
173
205
  return true;
174
206
  });
207
+ parser.hooks.expressionMemberChain
208
+ .for(harmonySpecifierTag)
209
+ .tap(
210
+ "HarmonyImportDependencyParserPlugin",
211
+ (expression, members, membersOptionals) => {
212
+ const settings = /** @type {HarmonySettings} */ (
213
+ parser.currentTagData
214
+ );
215
+ const nonOptionalMembers = getNonOptionalPart(
216
+ members,
217
+ membersOptionals
218
+ );
219
+ const expr =
220
+ nonOptionalMembers !== members
221
+ ? getNonOptionalMemberChain(
222
+ expression,
223
+ members.length - nonOptionalMembers.length
224
+ )
225
+ : expression;
226
+ const ids = settings.ids.concat(nonOptionalMembers);
227
+ const dep = new HarmonyImportSpecifierDependency(
228
+ settings.source,
229
+ settings.sourceOrder,
230
+ ids,
231
+ settings.name,
232
+ expr.range,
233
+ exportPresenceMode,
234
+ settings.assertions
235
+ );
236
+ dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
237
+ dep.loc = expr.loc;
238
+ parser.state.module.addDependency(dep);
239
+ InnerGraph.onUsage(parser.state, e => (dep.usedByExports = e));
240
+ return true;
241
+ }
242
+ );
175
243
  parser.hooks.callMemberChain
176
244
  .for(harmonySpecifierTag)
177
- .tap("HarmonyImportDependencyParserPlugin", (expr, members) => {
178
- const { arguments: args, callee } = expr;
179
- const settings = /** @type {HarmonySettings} */ (parser.currentTagData);
180
- const ids = settings.ids.concat(members);
181
- const dep = new HarmonyImportSpecifierDependency(
182
- settings.source,
183
- settings.sourceOrder,
184
- ids,
185
- settings.name,
186
- callee.range,
187
- exportPresenceMode,
188
- settings.assertions
189
- );
190
- dep.directImport = members.length === 0;
191
- dep.call = true;
192
- dep.asiSafe = !parser.isAsiPosition(callee.range[0]);
193
- // only in case when we strictly follow the spec we need a special case here
194
- dep.namespaceObjectAsContext =
195
- members.length > 0 && this.strictThisContextOnImports;
196
- dep.loc = callee.loc;
197
- parser.state.module.addDependency(dep);
198
- if (args) parser.walkExpressions(args);
199
- InnerGraph.onUsage(parser.state, e => (dep.usedByExports = e));
200
- return true;
201
- });
245
+ .tap(
246
+ "HarmonyImportDependencyParserPlugin",
247
+ (expression, members, membersOptionals) => {
248
+ const { arguments: args, callee } = expression;
249
+ const settings = /** @type {HarmonySettings} */ (
250
+ parser.currentTagData
251
+ );
252
+ const nonOptionalMembers = getNonOptionalPart(
253
+ members,
254
+ membersOptionals
255
+ );
256
+ const expr =
257
+ nonOptionalMembers !== members
258
+ ? getNonOptionalMemberChain(
259
+ callee,
260
+ members.length - nonOptionalMembers.length
261
+ )
262
+ : callee;
263
+ const ids = settings.ids.concat(nonOptionalMembers);
264
+ const dep = new HarmonyImportSpecifierDependency(
265
+ settings.source,
266
+ settings.sourceOrder,
267
+ ids,
268
+ settings.name,
269
+ expr.range,
270
+ exportPresenceMode,
271
+ settings.assertions
272
+ );
273
+ dep.directImport = members.length === 0;
274
+ dep.call = true;
275
+ dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
276
+ // only in case when we strictly follow the spec we need a special case here
277
+ dep.namespaceObjectAsContext =
278
+ members.length > 0 && this.strictThisContextOnImports;
279
+ dep.loc = expr.loc;
280
+ parser.state.module.addDependency(dep);
281
+ if (args) parser.walkExpressions(args);
282
+ InnerGraph.onUsage(parser.state, e => (dep.usedByExports = e));
283
+ return true;
284
+ }
285
+ );
202
286
  const { hotAcceptCallback, hotAcceptWithoutCallback } =
203
287
  HotModuleReplacementPlugin.getParserHooks(parser);
204
288
  hotAcceptCallback.tap(
@@ -261,14 +261,32 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
261
261
  */
262
262
  apply(dependency, source, templateContext) {
263
263
  const dep = /** @type {HarmonyImportSpecifierDependency} */ (dependency);
264
- const { moduleGraph, module, runtime, concatenationScope } =
265
- templateContext;
264
+ const { moduleGraph, runtime } = templateContext;
266
265
  const connection = moduleGraph.getConnection(dep);
267
266
  // Skip rendering depending when dependency is conditional
268
267
  if (connection && !connection.isTargetActive(runtime)) return;
269
268
 
270
269
  const ids = dep.getIds(moduleGraph);
270
+ const exportExpr = this._getCodeForIds(dep, source, templateContext, ids);
271
+ const range = dep.range;
272
+ if (dep.shorthand) {
273
+ source.insert(range[1], `: ${exportExpr}`);
274
+ } else {
275
+ source.replace(range[0], range[1] - 1, exportExpr);
276
+ }
277
+ }
271
278
 
279
+ /**
280
+ * @param {HarmonyImportSpecifierDependency} dep dependency
281
+ * @param {ReplaceSource} source source
282
+ * @param {DependencyTemplateContext} templateContext context
283
+ * @param {string[]} ids ids
284
+ * @returns {string} generated code
285
+ */
286
+ _getCodeForIds(dep, source, templateContext, ids) {
287
+ const { moduleGraph, module, runtime, concatenationScope } =
288
+ templateContext;
289
+ const connection = moduleGraph.getConnection(dep);
272
290
  let exportExpr;
273
291
  if (
274
292
  connection &&
@@ -299,7 +317,7 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
299
317
  );
300
318
  }
301
319
  } else {
302
- super.apply(dependency, source, templateContext);
320
+ super.apply(dep, source, templateContext);
303
321
 
304
322
  const { runtimeTemplate, initFragments, runtimeRequirements } =
305
323
  templateContext;
@@ -320,11 +338,7 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen
320
338
  runtimeRequirements
321
339
  });
322
340
  }
323
- if (dep.shorthand) {
324
- source.insert(dep.range[1], `: ${exportExpr}`);
325
- } else {
326
- source.replace(dep.range[0], dep.range[1] - 1, exportExpr);
327
- }
341
+ return exportExpr;
328
342
  }
329
343
  };
330
344
 
@@ -8,6 +8,7 @@
8
8
  const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
9
9
  const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
10
10
  const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
11
+ const HarmonyEvaluatedImportSpecifierDependency = require("./HarmonyEvaluatedImportSpecifierDependency");
11
12
  const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency");
12
13
  const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
13
14
  const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
@@ -59,6 +60,15 @@ class HarmonyModulesPlugin {
59
60
  new HarmonyImportSpecifierDependency.Template()
60
61
  );
61
62
 
63
+ compilation.dependencyFactories.set(
64
+ HarmonyEvaluatedImportSpecifierDependency,
65
+ normalModuleFactory
66
+ );
67
+ compilation.dependencyTemplates.set(
68
+ HarmonyEvaluatedImportSpecifierDependency,
69
+ new HarmonyEvaluatedImportSpecifierDependency.Template()
70
+ );
71
+
62
72
  compilation.dependencyTemplates.set(
63
73
  HarmonyExportHeaderDependency,
64
74
  new HarmonyExportHeaderDependency.Template()
@@ -25,7 +25,9 @@ class ModuleChunkLoadingPlugin {
25
25
  const isEnabledForChunk = chunk => {
26
26
  const options = chunk.getEntryOptions();
27
27
  const chunkLoading =
28
- (options && options.chunkLoading) || globalChunkLoading;
28
+ options && options.chunkLoading !== undefined
29
+ ? options.chunkLoading
30
+ : globalChunkLoading;
29
31
  return chunkLoading === "import";
30
32
  };
31
33
  const onceForChunkSet = new WeakSet();
@@ -28,7 +28,8 @@ module.exports = function () {
28
28
  var currentStatus = "idle";
29
29
 
30
30
  // while downloading
31
- var blockingPromises;
31
+ var blockingPromises = 0;
32
+ var blockingPromisesWaiting = [];
32
33
 
33
34
  // The update info
34
35
  var currentUpdateApplyHandlers;
@@ -218,17 +219,28 @@ module.exports = function () {
218
219
  return Promise.all(results);
219
220
  }
220
221
 
222
+ function unblock() {
223
+ if (--blockingPromises === 0) {
224
+ setStatus("ready").then(function () {
225
+ if (blockingPromises === 0) {
226
+ var list = blockingPromisesWaiting;
227
+ blockingPromisesWaiting = [];
228
+ for (var i = 0; i < list.length; i++) {
229
+ list[i]();
230
+ }
231
+ }
232
+ });
233
+ }
234
+ }
235
+
221
236
  function trackBlockingPromise(promise) {
222
237
  switch (currentStatus) {
223
238
  case "ready":
224
239
  setStatus("prepare");
225
- blockingPromises.push(promise);
226
- waitForBlockingPromises(function () {
227
- return setStatus("ready");
228
- });
229
- return promise;
240
+ /* fallthrough */
230
241
  case "prepare":
231
- blockingPromises.push(promise);
242
+ blockingPromises++;
243
+ promise.then(unblock, unblock);
232
244
  return promise;
233
245
  default:
234
246
  return promise;
@@ -236,11 +248,11 @@ module.exports = function () {
236
248
  }
237
249
 
238
250
  function waitForBlockingPromises(fn) {
239
- if (blockingPromises.length === 0) return fn();
240
- var blocker = blockingPromises;
241
- blockingPromises = [];
242
- return Promise.all(blocker).then(function () {
243
- return waitForBlockingPromises(fn);
251
+ if (blockingPromises === 0) return fn();
252
+ return new Promise(function (resolve) {
253
+ blockingPromisesWaiting.push(function () {
254
+ resolve(fn());
255
+ });
244
256
  });
245
257
  }
246
258
 
@@ -261,7 +273,6 @@ module.exports = function () {
261
273
 
262
274
  return setStatus("prepare").then(function () {
263
275
  var updatedModules = [];
264
- blockingPromises = [];
265
276
  currentUpdateApplyHandlers = [];
266
277
 
267
278
  return Promise.all(
@@ -298,7 +309,11 @@ module.exports = function () {
298
309
  function hotApply(options) {
299
310
  if (currentStatus !== "ready") {
300
311
  return Promise.resolve().then(function () {
301
- throw new Error("apply() is only allowed in ready status");
312
+ throw new Error(
313
+ "apply() is only allowed in ready status (state: " +
314
+ currentStatus +
315
+ ")"
316
+ );
302
317
  });
303
318
  }
304
319
  return internalApply(options);
@@ -443,15 +443,16 @@ module.exports = function () {
443
443
  ) {
444
444
  promises.push($loadUpdateChunk$(chunkId, updatedModulesList));
445
445
  currentUpdateChunks[chunkId] = true;
446
+ } else {
447
+ currentUpdateChunks[chunkId] = false;
446
448
  }
447
449
  });
448
450
  if ($ensureChunkHandlers$) {
449
451
  $ensureChunkHandlers$.$key$Hmr = function (chunkId, promises) {
450
452
  if (
451
453
  currentUpdateChunks &&
452
- !$hasOwnProperty$(currentUpdateChunks, chunkId) &&
453
- $hasOwnProperty$($installedChunks$, chunkId) &&
454
- $installedChunks$[chunkId] !== undefined
454
+ $hasOwnProperty$(currentUpdateChunks, chunkId) &&
455
+ !currentUpdateChunks[chunkId]
455
456
  ) {
456
457
  promises.push($loadUpdateChunk$(chunkId));
457
458
  currentUpdateChunks[chunkId] = true;
@@ -64,8 +64,8 @@ class HashedModuleIdsPlugin {
64
64
  hash.digest(options.hashDigest)
65
65
  );
66
66
  let len = options.hashDigestLength;
67
- while (usedIds.has(hashId.substr(0, len))) len++;
68
- const moduleId = hashId.substr(0, len);
67
+ while (usedIds.has(hashId.slice(0, len))) len++;
68
+ const moduleId = hashId.slice(0, len);
69
69
  chunkGraph.setModuleId(module, moduleId);
70
70
  usedIds.add(moduleId);
71
71
  }
@@ -25,7 +25,7 @@ const getHash = (str, len, hashFunction) => {
25
25
  const hash = createHash(hashFunction);
26
26
  hash.update(str);
27
27
  const digest = /** @type {string} */ (hash.digest("hex"));
28
- return digest.substr(0, len);
28
+ return digest.slice(0, len);
29
29
  };
30
30
 
31
31
  /**
@@ -61,12 +61,14 @@ class BasicEvaluatedExpression {
61
61
  /** @type {BasicEvaluatedExpression | undefined} */
62
62
  this.postfix = undefined;
63
63
  this.wrappedInnerExpressions = undefined;
64
- /** @type {string | undefined} */
64
+ /** @type {string | VariableInfoInterface | undefined} */
65
65
  this.identifier = undefined;
66
66
  /** @type {VariableInfoInterface} */
67
67
  this.rootInfo = undefined;
68
68
  /** @type {() => string[]} */
69
69
  this.getMembers = undefined;
70
+ /** @type {() => boolean[]} */
71
+ this.getMembersOptionals = undefined;
70
72
  /** @type {EsTreeNode} */
71
73
  this.expression = undefined;
72
74
  }
@@ -342,11 +344,12 @@ class BasicEvaluatedExpression {
342
344
  return this;
343
345
  }
344
346
 
345
- setIdentifier(identifier, rootInfo, getMembers) {
347
+ setIdentifier(identifier, rootInfo, getMembers, getMembersOptionals) {
346
348
  this.type = TypeIdentifier;
347
349
  this.identifier = identifier;
348
350
  this.rootInfo = rootInfo;
349
351
  this.getMembers = getMembers;
352
+ this.getMembersOptionals = getMembersOptionals;
350
353
  this.sideEffects = true;
351
354
  return this;
352
355
  }