@rollup/wasm-node 4.16.3 → 4.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/rollup +2 -2
- package/dist/es/getLogFilter.js +2 -2
- package/dist/es/parseAst.js +2 -2
- package/dist/es/rollup.js +2 -2
- package/dist/es/shared/node-entry.js +1259 -1315
- package/dist/es/shared/parseAst.js +2 -2
- package/dist/es/shared/watch.js +2 -2
- package/dist/getLogFilter.js +2 -2
- package/dist/loadConfigFile.js +2 -2
- package/dist/parseAst.js +2 -2
- package/dist/rollup.js +2 -2
- package/dist/shared/fsevents-importer.js +2 -2
- package/dist/shared/index.js +2 -2
- package/dist/shared/loadConfigFile.js +2 -2
- package/dist/shared/parseAst.js +2 -2
- package/dist/shared/rollup.js +1244 -1300
- package/dist/shared/watch-cli.js +2 -2
- package/dist/shared/watch.js +2 -2
- package/dist/wasm-node/bindings_wasm_bg.wasm +0 -0
- package/package.json +14 -13
package/dist/shared/rollup.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
@license
|
|
3
|
-
Rollup.js v4.
|
|
4
|
-
|
|
3
|
+
Rollup.js v4.17.0
|
|
4
|
+
Sat, 27 Apr 2024 11:29:22 GMT - commit 91352494fc722bcd5e8e922cd1497b34aec57a67
|
|
5
5
|
|
|
6
6
|
https://github.com/rollup/rollup
|
|
7
7
|
|
|
@@ -31,7 +31,7 @@ function _interopNamespaceDefault(e) {
|
|
|
31
31
|
|
|
32
32
|
const tty__namespace = /*#__PURE__*/_interopNamespaceDefault(tty);
|
|
33
33
|
|
|
34
|
-
var version = "4.
|
|
34
|
+
var version = "4.17.0";
|
|
35
35
|
|
|
36
36
|
function ensureArray$1(items) {
|
|
37
37
|
if (Array.isArray(items)) {
|
|
@@ -3416,7 +3416,6 @@ class Variable extends ExpressionEntity {
|
|
|
3416
3416
|
addReference(_identifier) { }
|
|
3417
3417
|
/**
|
|
3418
3418
|
* Check if the identifier variable is only used as function call
|
|
3419
|
-
* Forward the check to the export default variable if it is only used once
|
|
3420
3419
|
* @returns true if the variable is only used as function call
|
|
3421
3420
|
*/
|
|
3422
3421
|
getOnlyFunctionCallUsed() {
|
|
@@ -7133,936 +7132,338 @@ class ArrayPattern extends NodeBase {
|
|
|
7133
7132
|
}
|
|
7134
7133
|
}
|
|
7135
7134
|
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
}
|
|
7194
|
-
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|
|
7195
|
-
if (this.isReassigned) {
|
|
7196
|
-
return UNKNOWN_RETURN_EXPRESSION;
|
|
7197
|
-
}
|
|
7198
|
-
return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
|
|
7199
|
-
this.expressionsToBeDeoptimized.push(origin);
|
|
7200
|
-
return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
|
|
7201
|
-
}, UNKNOWN_RETURN_EXPRESSION);
|
|
7202
|
-
}
|
|
7203
|
-
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
7204
|
-
switch (interaction.type) {
|
|
7205
|
-
case INTERACTION_ACCESSED: {
|
|
7206
|
-
if (this.isReassigned)
|
|
7207
|
-
return true;
|
|
7208
|
-
return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
|
|
7209
|
-
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
7210
|
-
}
|
|
7211
|
-
case INTERACTION_ASSIGNED: {
|
|
7212
|
-
if (this.included)
|
|
7213
|
-
return true;
|
|
7214
|
-
if (path.length === 0)
|
|
7215
|
-
return false;
|
|
7216
|
-
if (this.isReassigned)
|
|
7217
|
-
return true;
|
|
7218
|
-
return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
|
|
7219
|
-
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
7220
|
-
}
|
|
7221
|
-
case INTERACTION_CALLED: {
|
|
7222
|
-
if (this.isReassigned)
|
|
7223
|
-
return true;
|
|
7224
|
-
return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
|
|
7225
|
-
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
7226
|
-
}
|
|
7227
|
-
}
|
|
7228
|
-
}
|
|
7229
|
-
include() {
|
|
7230
|
-
if (!this.included) {
|
|
7231
|
-
super.include();
|
|
7232
|
-
for (const declaration of this.declarations) {
|
|
7233
|
-
// If node is a default export, it can save a tree-shaking run to include the full declaration now
|
|
7234
|
-
if (!declaration.included)
|
|
7235
|
-
declaration.include(createInclusionContext(), false);
|
|
7236
|
-
let node = declaration.parent;
|
|
7237
|
-
while (!node.included) {
|
|
7238
|
-
// We do not want to properly include parents in case they are part of a dead branch
|
|
7239
|
-
// in which case .include() might pull in more dead code
|
|
7240
|
-
node.included = true;
|
|
7241
|
-
if (node.type === parseAst_js.Program)
|
|
7242
|
-
break;
|
|
7243
|
-
node = node.parent;
|
|
7244
|
-
}
|
|
7245
|
-
}
|
|
7135
|
+
/** @typedef { import('estree').Node} Node */
|
|
7136
|
+
/** @typedef {Node | {
|
|
7137
|
+
* type: 'PropertyDefinition';
|
|
7138
|
+
* computed: boolean;
|
|
7139
|
+
* value: Node
|
|
7140
|
+
* }} NodeWithPropertyDefinition */
|
|
7141
|
+
|
|
7142
|
+
/**
|
|
7143
|
+
*
|
|
7144
|
+
* @param {NodeWithPropertyDefinition} node
|
|
7145
|
+
* @param {NodeWithPropertyDefinition} parent
|
|
7146
|
+
* @returns {boolean}
|
|
7147
|
+
*/
|
|
7148
|
+
function is_reference (node, parent) {
|
|
7149
|
+
if (node.type === 'MemberExpression') {
|
|
7150
|
+
return !node.computed && is_reference(node.object, node);
|
|
7151
|
+
}
|
|
7152
|
+
|
|
7153
|
+
if (node.type === 'Identifier') {
|
|
7154
|
+
if (!parent) return true;
|
|
7155
|
+
|
|
7156
|
+
switch (parent.type) {
|
|
7157
|
+
// disregard `bar` in `foo.bar`
|
|
7158
|
+
case 'MemberExpression': return parent.computed || node === parent.object;
|
|
7159
|
+
|
|
7160
|
+
// disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
|
|
7161
|
+
case 'MethodDefinition': return parent.computed;
|
|
7162
|
+
|
|
7163
|
+
// disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
|
|
7164
|
+
case 'PropertyDefinition': return parent.computed || node === parent.value;
|
|
7165
|
+
|
|
7166
|
+
// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
|
|
7167
|
+
case 'Property': return parent.computed || node === parent.value;
|
|
7168
|
+
|
|
7169
|
+
// disregard the `bar` in `export { foo as bar }` or
|
|
7170
|
+
// the foo in `import { foo as bar }`
|
|
7171
|
+
case 'ExportSpecifier':
|
|
7172
|
+
case 'ImportSpecifier': return node === parent.local;
|
|
7173
|
+
|
|
7174
|
+
// disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
|
|
7175
|
+
case 'LabeledStatement':
|
|
7176
|
+
case 'BreakStatement':
|
|
7177
|
+
case 'ContinueStatement': return false;
|
|
7178
|
+
default: return true;
|
|
7179
|
+
}
|
|
7180
|
+
}
|
|
7181
|
+
|
|
7182
|
+
return false;
|
|
7183
|
+
}
|
|
7184
|
+
|
|
7185
|
+
const PureFunctionKey = Symbol('PureFunction');
|
|
7186
|
+
const getPureFunctions = ({ treeshake }) => {
|
|
7187
|
+
const pureFunctions = Object.create(null);
|
|
7188
|
+
for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
|
|
7189
|
+
let currentFunctions = pureFunctions;
|
|
7190
|
+
for (const pathSegment of functionName.split('.')) {
|
|
7191
|
+
currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
|
|
7246
7192
|
}
|
|
7193
|
+
currentFunctions[PureFunctionKey] = true;
|
|
7247
7194
|
}
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7195
|
+
return pureFunctions;
|
|
7196
|
+
};
|
|
7197
|
+
|
|
7198
|
+
/* eslint sort-keys: "off" */
|
|
7199
|
+
const ValueProperties = Symbol('Value Properties');
|
|
7200
|
+
const getTruthyLiteralValue = () => UnknownTruthyValue;
|
|
7201
|
+
const returnFalse = () => false;
|
|
7202
|
+
const returnTrue = () => true;
|
|
7203
|
+
const PURE = {
|
|
7204
|
+
deoptimizeArgumentsOnCall: doNothing,
|
|
7205
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7206
|
+
hasEffectsWhenCalled: returnFalse
|
|
7207
|
+
};
|
|
7208
|
+
const IMPURE = {
|
|
7209
|
+
deoptimizeArgumentsOnCall: doNothing,
|
|
7210
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7211
|
+
hasEffectsWhenCalled: returnTrue
|
|
7212
|
+
};
|
|
7213
|
+
const PURE_WITH_ARRAY = {
|
|
7214
|
+
deoptimizeArgumentsOnCall: doNothing,
|
|
7215
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7216
|
+
hasEffectsWhenCalled({ args }) {
|
|
7217
|
+
return args.length > 1 && !(args[1] instanceof ArrayExpression);
|
|
7259
7218
|
}
|
|
7260
|
-
|
|
7261
|
-
|
|
7219
|
+
};
|
|
7220
|
+
const GETTER_ACCESS = {
|
|
7221
|
+
deoptimizeArgumentsOnCall: doNothing,
|
|
7222
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7223
|
+
hasEffectsWhenCalled({ args }, context) {
|
|
7224
|
+
const [_thisArgument, firstArgument] = args;
|
|
7225
|
+
return (!(firstArgument instanceof ExpressionEntity) ||
|
|
7226
|
+
firstArgument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
7262
7227
|
}
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7228
|
+
};
|
|
7229
|
+
// We use shortened variables to reduce file size here
|
|
7230
|
+
/* OBJECT */
|
|
7231
|
+
const O = {
|
|
7232
|
+
__proto__: null,
|
|
7233
|
+
[ValueProperties]: IMPURE
|
|
7234
|
+
};
|
|
7235
|
+
/* PURE FUNCTION */
|
|
7236
|
+
const PF = {
|
|
7237
|
+
__proto__: null,
|
|
7238
|
+
[ValueProperties]: PURE
|
|
7239
|
+
};
|
|
7240
|
+
/* PURE FUNCTION IF FIRST ARG DOES NOT CONTAIN A GETTER */
|
|
7241
|
+
const PF_NO_GETTER = {
|
|
7242
|
+
__proto__: null,
|
|
7243
|
+
[ValueProperties]: GETTER_ACCESS
|
|
7244
|
+
};
|
|
7245
|
+
/* FUNCTION THAT MUTATES FIRST ARG WITHOUT TRIGGERING ACCESSORS */
|
|
7246
|
+
const MUTATES_ARG_WITHOUT_ACCESSOR = {
|
|
7247
|
+
__proto__: null,
|
|
7248
|
+
[ValueProperties]: {
|
|
7249
|
+
deoptimizeArgumentsOnCall({ args: [, firstArgument] }) {
|
|
7250
|
+
firstArgument?.deoptimizePath(UNKNOWN_PATH);
|
|
7251
|
+
},
|
|
7252
|
+
getLiteralValue: getTruthyLiteralValue,
|
|
7253
|
+
hasEffectsWhenCalled({ args }, context) {
|
|
7254
|
+
return (args.length <= 1 ||
|
|
7255
|
+
args[1].hasEffectsOnInteractionAtPath(UNKNOWN_NON_ACCESSOR_PATH, NODE_INTERACTION_UNKNOWN_ASSIGNMENT, context));
|
|
7268
7256
|
}
|
|
7269
|
-
return this.additionalInitializers;
|
|
7270
7257
|
}
|
|
7271
|
-
}
|
|
7272
|
-
|
|
7273
|
-
const
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
parent.children.push(this);
|
|
7481
|
-
}
|
|
7482
|
-
addAccessedDynamicImport(importExpression) {
|
|
7483
|
-
(this.accessedDynamicImports || (this.accessedDynamicImports = new Set())).add(importExpression);
|
|
7484
|
-
if (this.parent instanceof ChildScope) {
|
|
7485
|
-
this.parent.addAccessedDynamicImport(importExpression);
|
|
7486
|
-
}
|
|
7487
|
-
}
|
|
7488
|
-
addAccessedGlobals(globals, accessedGlobalsByScope) {
|
|
7489
|
-
const accessedGlobals = accessedGlobalsByScope.get(this) || new Set();
|
|
7490
|
-
for (const name of globals) {
|
|
7491
|
-
accessedGlobals.add(name);
|
|
7492
|
-
}
|
|
7493
|
-
accessedGlobalsByScope.set(this, accessedGlobals);
|
|
7494
|
-
if (this.parent instanceof ChildScope) {
|
|
7495
|
-
this.parent.addAccessedGlobals(globals, accessedGlobalsByScope);
|
|
7496
|
-
}
|
|
7497
|
-
}
|
|
7498
|
-
addNamespaceMemberAccess(name, variable) {
|
|
7499
|
-
this.accessedOutsideVariables.set(name, variable);
|
|
7500
|
-
this.parent.addNamespaceMemberAccess(name, variable);
|
|
7501
|
-
}
|
|
7502
|
-
addReturnExpression(expression) {
|
|
7503
|
-
this.parent instanceof ChildScope && this.parent.addReturnExpression(expression);
|
|
7504
|
-
}
|
|
7505
|
-
addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
7506
|
-
for (const variable of this.accessedOutsideVariables.values()) {
|
|
7507
|
-
if (variable.included) {
|
|
7508
|
-
usedNames.add(variable.getBaseVariableName());
|
|
7509
|
-
if (format === 'system' && exportNamesByVariable.has(variable)) {
|
|
7510
|
-
usedNames.add('exports');
|
|
7511
|
-
}
|
|
7512
|
-
}
|
|
7513
|
-
}
|
|
7514
|
-
const accessedGlobals = accessedGlobalsByScope.get(this);
|
|
7515
|
-
if (accessedGlobals) {
|
|
7516
|
-
for (const name of accessedGlobals) {
|
|
7517
|
-
usedNames.add(name);
|
|
7518
|
-
}
|
|
7519
|
-
}
|
|
7520
|
-
}
|
|
7521
|
-
contains(name) {
|
|
7522
|
-
return this.variables.has(name) || this.parent.contains(name);
|
|
7523
|
-
}
|
|
7524
|
-
deconflict(format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
7525
|
-
const usedNames = new Set();
|
|
7526
|
-
this.addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope);
|
|
7527
|
-
if (this.accessedDynamicImports) {
|
|
7528
|
-
for (const importExpression of this.accessedDynamicImports) {
|
|
7529
|
-
if (importExpression.inlineNamespace) {
|
|
7530
|
-
usedNames.add(importExpression.inlineNamespace.getBaseVariableName());
|
|
7531
|
-
}
|
|
7532
|
-
}
|
|
7533
|
-
}
|
|
7534
|
-
for (const [name, variable] of this.variables) {
|
|
7535
|
-
if (variable.included || variable.alwaysRendered) {
|
|
7536
|
-
variable.setRenderNames(null, getSafeName(name, usedNames, variable.forbiddenNames));
|
|
7537
|
-
}
|
|
7538
|
-
}
|
|
7539
|
-
for (const scope of this.children) {
|
|
7540
|
-
scope.deconflict(format, exportNamesByVariable, accessedGlobalsByScope);
|
|
7541
|
-
}
|
|
7542
|
-
}
|
|
7543
|
-
findLexicalBoundary() {
|
|
7544
|
-
return this.parent.findLexicalBoundary();
|
|
7545
|
-
}
|
|
7546
|
-
findVariable(name) {
|
|
7547
|
-
const knownVariable = this.variables.get(name) || this.accessedOutsideVariables.get(name);
|
|
7548
|
-
if (knownVariable) {
|
|
7549
|
-
return knownVariable;
|
|
7550
|
-
}
|
|
7551
|
-
const variable = this.parent.findVariable(name);
|
|
7552
|
-
this.accessedOutsideVariables.set(name, variable);
|
|
7553
|
-
return variable;
|
|
7554
|
-
}
|
|
7555
|
-
}
|
|
7556
|
-
|
|
7557
|
-
class CatchBodyScope extends ChildScope {
|
|
7558
|
-
constructor(parent) {
|
|
7559
|
-
super(parent, parent.context);
|
|
7560
|
-
this.parent = parent;
|
|
7561
|
-
}
|
|
7562
|
-
addDeclaration(identifier, context, init, kind) {
|
|
7563
|
-
if (kind === 'var') {
|
|
7564
|
-
const name = identifier.name;
|
|
7565
|
-
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
7566
|
-
if (existingVariable) {
|
|
7567
|
-
const existingKind = existingVariable.kind;
|
|
7568
|
-
if (existingKind === 'parameter' &&
|
|
7569
|
-
// If this is a destructured parameter, it is forbidden to redeclare
|
|
7570
|
-
existingVariable.declarations[0].parent.type === parseAst_js.CatchClause) {
|
|
7571
|
-
// If this is a var with the same name as the catch scope parameter,
|
|
7572
|
-
// the assignment actually goes to the parameter and the var is
|
|
7573
|
-
// hoisted without assignment. Locally, it is shadowed by the
|
|
7574
|
-
// parameter
|
|
7575
|
-
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
|
|
7576
|
-
// To avoid the need to rewrite the declaration, we link the variable
|
|
7577
|
-
// names. If we ever implement a logic that splits initialization and
|
|
7578
|
-
// assignment for hoisted vars, the "renderLikeHoisted" logic can be
|
|
7579
|
-
// removed again.
|
|
7580
|
-
// We do not need to check whether there already is a linked
|
|
7581
|
-
// variable because then declaredVariable would be that linked
|
|
7582
|
-
// variable.
|
|
7583
|
-
existingVariable.renderLikeHoisted(declaredVariable);
|
|
7584
|
-
this.addHoistedVariable(name, declaredVariable);
|
|
7585
|
-
return declaredVariable;
|
|
7586
|
-
}
|
|
7587
|
-
if (existingKind === 'var') {
|
|
7588
|
-
existingVariable.addDeclaration(identifier, init);
|
|
7589
|
-
return existingVariable;
|
|
7590
|
-
}
|
|
7591
|
-
return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
7592
|
-
}
|
|
7593
|
-
// We only add parameters to parameter scopes
|
|
7594
|
-
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
|
|
7595
|
-
// Necessary to make sure the init is deoptimized for conditional declarations.
|
|
7596
|
-
// We cannot call deoptimizePath here.
|
|
7597
|
-
declaredVariable.markInitializersForDeoptimization();
|
|
7598
|
-
// We add the variable to this and all parent scopes to reliably detect conflicts
|
|
7599
|
-
this.addHoistedVariable(name, declaredVariable);
|
|
7600
|
-
return declaredVariable;
|
|
7601
|
-
}
|
|
7602
|
-
return super.addDeclaration(identifier, context, init, kind);
|
|
7603
|
-
}
|
|
7604
|
-
}
|
|
7605
|
-
|
|
7606
|
-
class FunctionBodyScope extends ChildScope {
|
|
7607
|
-
constructor(parent) {
|
|
7608
|
-
super(parent, parent.context);
|
|
7609
|
-
}
|
|
7610
|
-
// There is stuff that is only allowed in function scopes, i.e. functions can
|
|
7611
|
-
// be redeclared, functions and var can redeclare each other
|
|
7612
|
-
addDeclaration(identifier, context, init, kind) {
|
|
7613
|
-
const name = identifier.name;
|
|
7614
|
-
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
7615
|
-
if (existingVariable) {
|
|
7616
|
-
const existingKind = existingVariable.kind;
|
|
7617
|
-
if ((kind === 'var' || kind === 'function') &&
|
|
7618
|
-
(existingKind === 'var' || existingKind === 'function' || existingKind === 'parameter')) {
|
|
7619
|
-
existingVariable.addDeclaration(identifier, init);
|
|
7620
|
-
return existingVariable;
|
|
7621
|
-
}
|
|
7622
|
-
context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
7623
|
-
}
|
|
7624
|
-
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
7625
|
-
this.variables.set(name, newVariable);
|
|
7626
|
-
return newVariable;
|
|
7627
|
-
}
|
|
7628
|
-
}
|
|
7629
|
-
|
|
7630
|
-
class ParameterScope extends ChildScope {
|
|
7631
|
-
constructor(parent, isCatchScope) {
|
|
7632
|
-
super(parent, parent.context);
|
|
7633
|
-
this.parameters = [];
|
|
7634
|
-
this.hasRest = false;
|
|
7635
|
-
this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
|
|
7636
|
-
}
|
|
7637
|
-
/**
|
|
7638
|
-
* Adds a parameter to this scope. Parameters must be added in the correct
|
|
7639
|
-
* order, i.e. from left to right.
|
|
7640
|
-
*/
|
|
7641
|
-
addParameterDeclaration(identifier) {
|
|
7642
|
-
const { name, start } = identifier;
|
|
7643
|
-
const existingParameter = this.variables.get(name);
|
|
7644
|
-
if (existingParameter) {
|
|
7645
|
-
return this.context.error(parseAst_js.logDuplicateArgumentNameError(name), start);
|
|
7646
|
-
}
|
|
7647
|
-
const variable = new ParameterVariable(name, identifier, this.context);
|
|
7648
|
-
this.variables.set(name, variable);
|
|
7649
|
-
// We also add it to the body scope to detect name conflicts with local
|
|
7650
|
-
// variables. We still need the intermediate scope, though, as parameter
|
|
7651
|
-
// defaults are NOT taken from the body scope but from the parameters or
|
|
7652
|
-
// outside scope.
|
|
7653
|
-
this.bodyScope.addHoistedVariable(name, variable);
|
|
7654
|
-
return variable;
|
|
7655
|
-
}
|
|
7656
|
-
addParameterVariables(parameters, hasRest) {
|
|
7657
|
-
this.parameters = parameters;
|
|
7658
|
-
for (const parameterList of parameters) {
|
|
7659
|
-
for (const parameter of parameterList) {
|
|
7660
|
-
parameter.alwaysRendered = true;
|
|
7661
|
-
}
|
|
7662
|
-
}
|
|
7663
|
-
this.hasRest = hasRest;
|
|
7664
|
-
}
|
|
7665
|
-
includeCallArguments(context, parameters) {
|
|
7666
|
-
let calledFromTryStatement = false;
|
|
7667
|
-
let argumentIncluded = false;
|
|
7668
|
-
const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
|
|
7669
|
-
for (const checkedArgument of parameters) {
|
|
7670
|
-
if (checkedArgument instanceof SpreadElement) {
|
|
7671
|
-
for (const argument of parameters) {
|
|
7672
|
-
argument.include(context, false);
|
|
7673
|
-
}
|
|
7674
|
-
break;
|
|
7675
|
-
}
|
|
7676
|
-
}
|
|
7677
|
-
for (let index = parameters.length - 1; index >= 0; index--) {
|
|
7678
|
-
const parameterVariables = this.parameters[index] || restParameter;
|
|
7679
|
-
const argument = parameters[index];
|
|
7680
|
-
if (parameterVariables) {
|
|
7681
|
-
calledFromTryStatement = false;
|
|
7682
|
-
if (parameterVariables.length === 0) {
|
|
7683
|
-
// handle empty destructuring
|
|
7684
|
-
argumentIncluded = true;
|
|
7685
|
-
}
|
|
7686
|
-
else {
|
|
7687
|
-
for (const variable of parameterVariables) {
|
|
7688
|
-
if (variable.included) {
|
|
7689
|
-
argumentIncluded = true;
|
|
7690
|
-
}
|
|
7691
|
-
if (variable.calledFromTryStatement) {
|
|
7692
|
-
calledFromTryStatement = true;
|
|
7693
|
-
}
|
|
7694
|
-
}
|
|
7695
|
-
}
|
|
7696
|
-
}
|
|
7697
|
-
if (!argumentIncluded && argument.shouldBeIncluded(context)) {
|
|
7698
|
-
argumentIncluded = true;
|
|
7699
|
-
}
|
|
7700
|
-
if (argumentIncluded) {
|
|
7701
|
-
argument.include(context, calledFromTryStatement);
|
|
7702
|
-
}
|
|
7703
|
-
}
|
|
7704
|
-
}
|
|
7705
|
-
}
|
|
7706
|
-
|
|
7707
|
-
class ReturnValueScope extends ParameterScope {
|
|
7708
|
-
constructor() {
|
|
7709
|
-
super(...arguments);
|
|
7710
|
-
this.returnExpression = null;
|
|
7711
|
-
this.returnExpressions = [];
|
|
7712
|
-
}
|
|
7713
|
-
addReturnExpression(expression) {
|
|
7714
|
-
this.returnExpressions.push(expression);
|
|
7715
|
-
}
|
|
7716
|
-
getReturnExpression() {
|
|
7717
|
-
if (this.returnExpression === null)
|
|
7718
|
-
this.updateReturnExpression();
|
|
7719
|
-
return this.returnExpression;
|
|
7720
|
-
}
|
|
7721
|
-
updateReturnExpression() {
|
|
7722
|
-
if (this.returnExpressions.length === 1) {
|
|
7723
|
-
this.returnExpression = this.returnExpressions[0];
|
|
7724
|
-
}
|
|
7725
|
-
else {
|
|
7726
|
-
this.returnExpression = UNKNOWN_EXPRESSION;
|
|
7727
|
-
for (const expression of this.returnExpressions) {
|
|
7728
|
-
expression.deoptimizePath(UNKNOWN_PATH);
|
|
7729
|
-
}
|
|
7730
|
-
}
|
|
7731
|
-
}
|
|
7732
|
-
}
|
|
7733
|
-
|
|
7734
|
-
/** @typedef { import('estree').Node} Node */
|
|
7735
|
-
/** @typedef {Node | {
|
|
7736
|
-
* type: 'PropertyDefinition';
|
|
7737
|
-
* computed: boolean;
|
|
7738
|
-
* value: Node
|
|
7739
|
-
* }} NodeWithPropertyDefinition */
|
|
7740
|
-
|
|
7741
|
-
/**
|
|
7742
|
-
*
|
|
7743
|
-
* @param {NodeWithPropertyDefinition} node
|
|
7744
|
-
* @param {NodeWithPropertyDefinition} parent
|
|
7745
|
-
* @returns {boolean}
|
|
7746
|
-
*/
|
|
7747
|
-
function is_reference (node, parent) {
|
|
7748
|
-
if (node.type === 'MemberExpression') {
|
|
7749
|
-
return !node.computed && is_reference(node.object, node);
|
|
7750
|
-
}
|
|
7751
|
-
|
|
7752
|
-
if (node.type === 'Identifier') {
|
|
7753
|
-
if (!parent) return true;
|
|
7754
|
-
|
|
7755
|
-
switch (parent.type) {
|
|
7756
|
-
// disregard `bar` in `foo.bar`
|
|
7757
|
-
case 'MemberExpression': return parent.computed || node === parent.object;
|
|
7758
|
-
|
|
7759
|
-
// disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
|
|
7760
|
-
case 'MethodDefinition': return parent.computed;
|
|
7761
|
-
|
|
7762
|
-
// disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
|
|
7763
|
-
case 'PropertyDefinition': return parent.computed || node === parent.value;
|
|
7764
|
-
|
|
7765
|
-
// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
|
|
7766
|
-
case 'Property': return parent.computed || node === parent.value;
|
|
7767
|
-
|
|
7768
|
-
// disregard the `bar` in `export { foo as bar }` or
|
|
7769
|
-
// the foo in `import { foo as bar }`
|
|
7770
|
-
case 'ExportSpecifier':
|
|
7771
|
-
case 'ImportSpecifier': return node === parent.local;
|
|
7772
|
-
|
|
7773
|
-
// disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
|
|
7774
|
-
case 'LabeledStatement':
|
|
7775
|
-
case 'BreakStatement':
|
|
7776
|
-
case 'ContinueStatement': return false;
|
|
7777
|
-
default: return true;
|
|
7778
|
-
}
|
|
7779
|
-
}
|
|
7780
|
-
|
|
7781
|
-
return false;
|
|
7782
|
-
}
|
|
7783
|
-
|
|
7784
|
-
const PureFunctionKey = Symbol('PureFunction');
|
|
7785
|
-
const getPureFunctions = ({ treeshake }) => {
|
|
7786
|
-
const pureFunctions = Object.create(null);
|
|
7787
|
-
for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
|
|
7788
|
-
let currentFunctions = pureFunctions;
|
|
7789
|
-
for (const pathSegment of functionName.split('.')) {
|
|
7790
|
-
currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
|
|
7791
|
-
}
|
|
7792
|
-
currentFunctions[PureFunctionKey] = true;
|
|
7793
|
-
}
|
|
7794
|
-
return pureFunctions;
|
|
7795
|
-
};
|
|
7796
|
-
|
|
7797
|
-
/* eslint sort-keys: "off" */
|
|
7798
|
-
const ValueProperties = Symbol('Value Properties');
|
|
7799
|
-
const getTruthyLiteralValue = () => UnknownTruthyValue;
|
|
7800
|
-
const returnFalse = () => false;
|
|
7801
|
-
const returnTrue = () => true;
|
|
7802
|
-
const PURE = {
|
|
7803
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
7804
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7805
|
-
hasEffectsWhenCalled: returnFalse
|
|
7806
|
-
};
|
|
7807
|
-
const IMPURE = {
|
|
7808
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
7809
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7810
|
-
hasEffectsWhenCalled: returnTrue
|
|
7811
|
-
};
|
|
7812
|
-
const PURE_WITH_ARRAY = {
|
|
7813
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
7814
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7815
|
-
hasEffectsWhenCalled({ args }) {
|
|
7816
|
-
return args.length > 1 && !(args[1] instanceof ArrayExpression);
|
|
7817
|
-
}
|
|
7818
|
-
};
|
|
7819
|
-
const GETTER_ACCESS = {
|
|
7820
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
7821
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7822
|
-
hasEffectsWhenCalled({ args }, context) {
|
|
7823
|
-
const [_thisArgument, firstArgument] = args;
|
|
7824
|
-
return (!(firstArgument instanceof ExpressionEntity) ||
|
|
7825
|
-
firstArgument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
7826
|
-
}
|
|
7827
|
-
};
|
|
7828
|
-
// We use shortened variables to reduce file size here
|
|
7829
|
-
/* OBJECT */
|
|
7830
|
-
const O = {
|
|
7831
|
-
__proto__: null,
|
|
7832
|
-
[ValueProperties]: IMPURE
|
|
7833
|
-
};
|
|
7834
|
-
/* PURE FUNCTION */
|
|
7835
|
-
const PF = {
|
|
7836
|
-
__proto__: null,
|
|
7837
|
-
[ValueProperties]: PURE
|
|
7838
|
-
};
|
|
7839
|
-
/* PURE FUNCTION IF FIRST ARG DOES NOT CONTAIN A GETTER */
|
|
7840
|
-
const PF_NO_GETTER = {
|
|
7841
|
-
__proto__: null,
|
|
7842
|
-
[ValueProperties]: GETTER_ACCESS
|
|
7843
|
-
};
|
|
7844
|
-
/* FUNCTION THAT MUTATES FIRST ARG WITHOUT TRIGGERING ACCESSORS */
|
|
7845
|
-
const MUTATES_ARG_WITHOUT_ACCESSOR = {
|
|
7846
|
-
__proto__: null,
|
|
7847
|
-
[ValueProperties]: {
|
|
7848
|
-
deoptimizeArgumentsOnCall({ args: [, firstArgument] }) {
|
|
7849
|
-
firstArgument?.deoptimizePath(UNKNOWN_PATH);
|
|
7850
|
-
},
|
|
7851
|
-
getLiteralValue: getTruthyLiteralValue,
|
|
7852
|
-
hasEffectsWhenCalled({ args }, context) {
|
|
7853
|
-
return (args.length <= 1 ||
|
|
7854
|
-
args[1].hasEffectsOnInteractionAtPath(UNKNOWN_NON_ACCESSOR_PATH, NODE_INTERACTION_UNKNOWN_ASSIGNMENT, context));
|
|
7855
|
-
}
|
|
7856
|
-
}
|
|
7857
|
-
};
|
|
7858
|
-
/* CONSTRUCTOR */
|
|
7859
|
-
const C = {
|
|
7860
|
-
__proto__: null,
|
|
7861
|
-
[ValueProperties]: IMPURE,
|
|
7862
|
-
prototype: O
|
|
7863
|
-
};
|
|
7864
|
-
/* PURE CONSTRUCTOR */
|
|
7865
|
-
const PC = {
|
|
7866
|
-
__proto__: null,
|
|
7867
|
-
[ValueProperties]: PURE,
|
|
7868
|
-
prototype: O
|
|
7869
|
-
};
|
|
7870
|
-
const PC_WITH_ARRAY = {
|
|
7871
|
-
__proto__: null,
|
|
7872
|
-
[ValueProperties]: PURE_WITH_ARRAY,
|
|
7873
|
-
prototype: O
|
|
7874
|
-
};
|
|
7875
|
-
const ARRAY_TYPE = {
|
|
7876
|
-
__proto__: null,
|
|
7877
|
-
[ValueProperties]: PURE,
|
|
7878
|
-
from: O,
|
|
7879
|
-
of: PF,
|
|
7880
|
-
prototype: O
|
|
7881
|
-
};
|
|
7882
|
-
const INTL_MEMBER = {
|
|
7883
|
-
__proto__: null,
|
|
7884
|
-
[ValueProperties]: PURE,
|
|
7885
|
-
supportedLocalesOf: PC
|
|
7886
|
-
};
|
|
7887
|
-
const knownGlobals = {
|
|
7888
|
-
// Placeholders for global objects to avoid shape mutations
|
|
7889
|
-
global: O,
|
|
7890
|
-
globalThis: O,
|
|
7891
|
-
self: O,
|
|
7892
|
-
window: O,
|
|
7893
|
-
// Common globals
|
|
7894
|
-
__proto__: null,
|
|
7895
|
-
[ValueProperties]: IMPURE,
|
|
7896
|
-
Array: {
|
|
7897
|
-
__proto__: null,
|
|
7898
|
-
[ValueProperties]: IMPURE,
|
|
7899
|
-
from: O,
|
|
7900
|
-
isArray: PF,
|
|
7901
|
-
of: PF,
|
|
7902
|
-
prototype: O
|
|
7903
|
-
},
|
|
7904
|
-
ArrayBuffer: {
|
|
7905
|
-
__proto__: null,
|
|
7906
|
-
[ValueProperties]: PURE,
|
|
7907
|
-
isView: PF,
|
|
7908
|
-
prototype: O
|
|
7909
|
-
},
|
|
7910
|
-
Atomics: O,
|
|
7911
|
-
BigInt: C,
|
|
7912
|
-
BigInt64Array: C,
|
|
7913
|
-
BigUint64Array: C,
|
|
7914
|
-
Boolean: PC,
|
|
7915
|
-
constructor: C,
|
|
7916
|
-
DataView: PC,
|
|
7917
|
-
Date: {
|
|
7918
|
-
__proto__: null,
|
|
7919
|
-
[ValueProperties]: PURE,
|
|
7920
|
-
now: PF,
|
|
7921
|
-
parse: PF,
|
|
7922
|
-
prototype: O,
|
|
7923
|
-
UTC: PF
|
|
7924
|
-
},
|
|
7925
|
-
decodeURI: PF,
|
|
7926
|
-
decodeURIComponent: PF,
|
|
7927
|
-
encodeURI: PF,
|
|
7928
|
-
encodeURIComponent: PF,
|
|
7929
|
-
Error: PC,
|
|
7930
|
-
escape: PF,
|
|
7931
|
-
eval: O,
|
|
7932
|
-
EvalError: PC,
|
|
7933
|
-
Float32Array: ARRAY_TYPE,
|
|
7934
|
-
Float64Array: ARRAY_TYPE,
|
|
7935
|
-
Function: C,
|
|
7936
|
-
hasOwnProperty: O,
|
|
7937
|
-
Infinity: O,
|
|
7938
|
-
Int16Array: ARRAY_TYPE,
|
|
7939
|
-
Int32Array: ARRAY_TYPE,
|
|
7940
|
-
Int8Array: ARRAY_TYPE,
|
|
7941
|
-
isFinite: PF,
|
|
7942
|
-
isNaN: PF,
|
|
7943
|
-
isPrototypeOf: O,
|
|
7944
|
-
JSON: O,
|
|
7945
|
-
Map: PC_WITH_ARRAY,
|
|
7946
|
-
Math: {
|
|
7947
|
-
__proto__: null,
|
|
7948
|
-
[ValueProperties]: IMPURE,
|
|
7949
|
-
abs: PF,
|
|
7950
|
-
acos: PF,
|
|
7951
|
-
acosh: PF,
|
|
7952
|
-
asin: PF,
|
|
7953
|
-
asinh: PF,
|
|
7954
|
-
atan: PF,
|
|
7955
|
-
atan2: PF,
|
|
7956
|
-
atanh: PF,
|
|
7957
|
-
cbrt: PF,
|
|
7958
|
-
ceil: PF,
|
|
7959
|
-
clz32: PF,
|
|
7960
|
-
cos: PF,
|
|
7961
|
-
cosh: PF,
|
|
7962
|
-
exp: PF,
|
|
7963
|
-
expm1: PF,
|
|
7964
|
-
floor: PF,
|
|
7965
|
-
fround: PF,
|
|
7966
|
-
hypot: PF,
|
|
7967
|
-
imul: PF,
|
|
7968
|
-
log: PF,
|
|
7969
|
-
log10: PF,
|
|
7970
|
-
log1p: PF,
|
|
7971
|
-
log2: PF,
|
|
7972
|
-
max: PF,
|
|
7973
|
-
min: PF,
|
|
7974
|
-
pow: PF,
|
|
7975
|
-
random: PF,
|
|
7976
|
-
round: PF,
|
|
7977
|
-
sign: PF,
|
|
7978
|
-
sin: PF,
|
|
7979
|
-
sinh: PF,
|
|
7980
|
-
sqrt: PF,
|
|
7981
|
-
tan: PF,
|
|
7982
|
-
tanh: PF,
|
|
7983
|
-
trunc: PF
|
|
7984
|
-
},
|
|
7985
|
-
NaN: O,
|
|
7986
|
-
Number: {
|
|
7987
|
-
__proto__: null,
|
|
7988
|
-
[ValueProperties]: PURE,
|
|
7989
|
-
isFinite: PF,
|
|
7990
|
-
isInteger: PF,
|
|
7991
|
-
isNaN: PF,
|
|
7992
|
-
isSafeInteger: PF,
|
|
7993
|
-
parseFloat: PF,
|
|
7994
|
-
parseInt: PF,
|
|
7995
|
-
prototype: O
|
|
7996
|
-
},
|
|
7997
|
-
Object: {
|
|
7998
|
-
__proto__: null,
|
|
7999
|
-
[ValueProperties]: PURE,
|
|
8000
|
-
create: PF,
|
|
8001
|
-
// Technically those can throw in certain situations, but we ignore this as
|
|
8002
|
-
// code that relies on this will hopefully wrap this in a try-catch, which
|
|
8003
|
-
// deoptimizes everything anyway
|
|
8004
|
-
defineProperty: MUTATES_ARG_WITHOUT_ACCESSOR,
|
|
8005
|
-
defineProperties: MUTATES_ARG_WITHOUT_ACCESSOR,
|
|
8006
|
-
freeze: MUTATES_ARG_WITHOUT_ACCESSOR,
|
|
8007
|
-
getOwnPropertyDescriptor: PF,
|
|
8008
|
-
getOwnPropertyDescriptors: PF,
|
|
8009
|
-
getOwnPropertyNames: PF,
|
|
8010
|
-
getOwnPropertySymbols: PF,
|
|
8011
|
-
getPrototypeOf: PF,
|
|
8012
|
-
hasOwn: PF,
|
|
8013
|
-
is: PF,
|
|
8014
|
-
isExtensible: PF,
|
|
8015
|
-
isFrozen: PF,
|
|
8016
|
-
isSealed: PF,
|
|
8017
|
-
keys: PF,
|
|
8018
|
-
fromEntries: O,
|
|
8019
|
-
entries: PF_NO_GETTER,
|
|
8020
|
-
values: PF_NO_GETTER,
|
|
8021
|
-
prototype: O
|
|
8022
|
-
},
|
|
8023
|
-
parseFloat: PF,
|
|
8024
|
-
parseInt: PF,
|
|
8025
|
-
Promise: {
|
|
8026
|
-
__proto__: null,
|
|
8027
|
-
[ValueProperties]: IMPURE,
|
|
8028
|
-
all: O,
|
|
8029
|
-
allSettled: O,
|
|
8030
|
-
any: O,
|
|
8031
|
-
prototype: O,
|
|
8032
|
-
race: O,
|
|
8033
|
-
reject: O,
|
|
8034
|
-
resolve: O
|
|
8035
|
-
},
|
|
8036
|
-
propertyIsEnumerable: O,
|
|
8037
|
-
Proxy: O,
|
|
8038
|
-
RangeError: PC,
|
|
8039
|
-
ReferenceError: PC,
|
|
8040
|
-
Reflect: O,
|
|
8041
|
-
RegExp: PC,
|
|
8042
|
-
Set: PC_WITH_ARRAY,
|
|
8043
|
-
SharedArrayBuffer: C,
|
|
8044
|
-
String: {
|
|
8045
|
-
__proto__: null,
|
|
8046
|
-
[ValueProperties]: PURE,
|
|
8047
|
-
fromCharCode: PF,
|
|
8048
|
-
fromCodePoint: PF,
|
|
8049
|
-
prototype: O,
|
|
8050
|
-
raw: PF
|
|
8051
|
-
},
|
|
8052
|
-
Symbol: {
|
|
8053
|
-
__proto__: null,
|
|
8054
|
-
[ValueProperties]: PURE,
|
|
8055
|
-
for: PF,
|
|
8056
|
-
keyFor: PF,
|
|
8057
|
-
prototype: O,
|
|
8058
|
-
toStringTag: {
|
|
8059
|
-
__proto__: null,
|
|
8060
|
-
[ValueProperties]: {
|
|
8061
|
-
deoptimizeArgumentsOnCall: doNothing,
|
|
8062
|
-
getLiteralValue() {
|
|
8063
|
-
return SymbolToStringTag;
|
|
8064
|
-
},
|
|
8065
|
-
hasEffectsWhenCalled: returnTrue
|
|
7258
|
+
};
|
|
7259
|
+
/* CONSTRUCTOR */
|
|
7260
|
+
const C = {
|
|
7261
|
+
__proto__: null,
|
|
7262
|
+
[ValueProperties]: IMPURE,
|
|
7263
|
+
prototype: O
|
|
7264
|
+
};
|
|
7265
|
+
/* PURE CONSTRUCTOR */
|
|
7266
|
+
const PC = {
|
|
7267
|
+
__proto__: null,
|
|
7268
|
+
[ValueProperties]: PURE,
|
|
7269
|
+
prototype: O
|
|
7270
|
+
};
|
|
7271
|
+
const PC_WITH_ARRAY = {
|
|
7272
|
+
__proto__: null,
|
|
7273
|
+
[ValueProperties]: PURE_WITH_ARRAY,
|
|
7274
|
+
prototype: O
|
|
7275
|
+
};
|
|
7276
|
+
const ARRAY_TYPE = {
|
|
7277
|
+
__proto__: null,
|
|
7278
|
+
[ValueProperties]: PURE,
|
|
7279
|
+
from: O,
|
|
7280
|
+
of: PF,
|
|
7281
|
+
prototype: O
|
|
7282
|
+
};
|
|
7283
|
+
const INTL_MEMBER = {
|
|
7284
|
+
__proto__: null,
|
|
7285
|
+
[ValueProperties]: PURE,
|
|
7286
|
+
supportedLocalesOf: PC
|
|
7287
|
+
};
|
|
7288
|
+
const knownGlobals = {
|
|
7289
|
+
// Placeholders for global objects to avoid shape mutations
|
|
7290
|
+
global: O,
|
|
7291
|
+
globalThis: O,
|
|
7292
|
+
self: O,
|
|
7293
|
+
window: O,
|
|
7294
|
+
// Common globals
|
|
7295
|
+
__proto__: null,
|
|
7296
|
+
[ValueProperties]: IMPURE,
|
|
7297
|
+
Array: {
|
|
7298
|
+
__proto__: null,
|
|
7299
|
+
[ValueProperties]: IMPURE,
|
|
7300
|
+
from: O,
|
|
7301
|
+
isArray: PF,
|
|
7302
|
+
of: PF,
|
|
7303
|
+
prototype: O
|
|
7304
|
+
},
|
|
7305
|
+
ArrayBuffer: {
|
|
7306
|
+
__proto__: null,
|
|
7307
|
+
[ValueProperties]: PURE,
|
|
7308
|
+
isView: PF,
|
|
7309
|
+
prototype: O
|
|
7310
|
+
},
|
|
7311
|
+
Atomics: O,
|
|
7312
|
+
BigInt: C,
|
|
7313
|
+
BigInt64Array: C,
|
|
7314
|
+
BigUint64Array: C,
|
|
7315
|
+
Boolean: PC,
|
|
7316
|
+
constructor: C,
|
|
7317
|
+
DataView: PC,
|
|
7318
|
+
Date: {
|
|
7319
|
+
__proto__: null,
|
|
7320
|
+
[ValueProperties]: PURE,
|
|
7321
|
+
now: PF,
|
|
7322
|
+
parse: PF,
|
|
7323
|
+
prototype: O,
|
|
7324
|
+
UTC: PF
|
|
7325
|
+
},
|
|
7326
|
+
decodeURI: PF,
|
|
7327
|
+
decodeURIComponent: PF,
|
|
7328
|
+
encodeURI: PF,
|
|
7329
|
+
encodeURIComponent: PF,
|
|
7330
|
+
Error: PC,
|
|
7331
|
+
escape: PF,
|
|
7332
|
+
eval: O,
|
|
7333
|
+
EvalError: PC,
|
|
7334
|
+
Float32Array: ARRAY_TYPE,
|
|
7335
|
+
Float64Array: ARRAY_TYPE,
|
|
7336
|
+
Function: C,
|
|
7337
|
+
hasOwnProperty: O,
|
|
7338
|
+
Infinity: O,
|
|
7339
|
+
Int16Array: ARRAY_TYPE,
|
|
7340
|
+
Int32Array: ARRAY_TYPE,
|
|
7341
|
+
Int8Array: ARRAY_TYPE,
|
|
7342
|
+
isFinite: PF,
|
|
7343
|
+
isNaN: PF,
|
|
7344
|
+
isPrototypeOf: O,
|
|
7345
|
+
JSON: O,
|
|
7346
|
+
Map: PC_WITH_ARRAY,
|
|
7347
|
+
Math: {
|
|
7348
|
+
__proto__: null,
|
|
7349
|
+
[ValueProperties]: IMPURE,
|
|
7350
|
+
abs: PF,
|
|
7351
|
+
acos: PF,
|
|
7352
|
+
acosh: PF,
|
|
7353
|
+
asin: PF,
|
|
7354
|
+
asinh: PF,
|
|
7355
|
+
atan: PF,
|
|
7356
|
+
atan2: PF,
|
|
7357
|
+
atanh: PF,
|
|
7358
|
+
cbrt: PF,
|
|
7359
|
+
ceil: PF,
|
|
7360
|
+
clz32: PF,
|
|
7361
|
+
cos: PF,
|
|
7362
|
+
cosh: PF,
|
|
7363
|
+
exp: PF,
|
|
7364
|
+
expm1: PF,
|
|
7365
|
+
floor: PF,
|
|
7366
|
+
fround: PF,
|
|
7367
|
+
hypot: PF,
|
|
7368
|
+
imul: PF,
|
|
7369
|
+
log: PF,
|
|
7370
|
+
log10: PF,
|
|
7371
|
+
log1p: PF,
|
|
7372
|
+
log2: PF,
|
|
7373
|
+
max: PF,
|
|
7374
|
+
min: PF,
|
|
7375
|
+
pow: PF,
|
|
7376
|
+
random: PF,
|
|
7377
|
+
round: PF,
|
|
7378
|
+
sign: PF,
|
|
7379
|
+
sin: PF,
|
|
7380
|
+
sinh: PF,
|
|
7381
|
+
sqrt: PF,
|
|
7382
|
+
tan: PF,
|
|
7383
|
+
tanh: PF,
|
|
7384
|
+
trunc: PF
|
|
7385
|
+
},
|
|
7386
|
+
NaN: O,
|
|
7387
|
+
Number: {
|
|
7388
|
+
__proto__: null,
|
|
7389
|
+
[ValueProperties]: PURE,
|
|
7390
|
+
isFinite: PF,
|
|
7391
|
+
isInteger: PF,
|
|
7392
|
+
isNaN: PF,
|
|
7393
|
+
isSafeInteger: PF,
|
|
7394
|
+
parseFloat: PF,
|
|
7395
|
+
parseInt: PF,
|
|
7396
|
+
prototype: O
|
|
7397
|
+
},
|
|
7398
|
+
Object: {
|
|
7399
|
+
__proto__: null,
|
|
7400
|
+
[ValueProperties]: PURE,
|
|
7401
|
+
create: PF,
|
|
7402
|
+
// Technically those can throw in certain situations, but we ignore this as
|
|
7403
|
+
// code that relies on this will hopefully wrap this in a try-catch, which
|
|
7404
|
+
// deoptimizes everything anyway
|
|
7405
|
+
defineProperty: MUTATES_ARG_WITHOUT_ACCESSOR,
|
|
7406
|
+
defineProperties: MUTATES_ARG_WITHOUT_ACCESSOR,
|
|
7407
|
+
freeze: MUTATES_ARG_WITHOUT_ACCESSOR,
|
|
7408
|
+
getOwnPropertyDescriptor: PF,
|
|
7409
|
+
getOwnPropertyDescriptors: PF,
|
|
7410
|
+
getOwnPropertyNames: PF,
|
|
7411
|
+
getOwnPropertySymbols: PF,
|
|
7412
|
+
getPrototypeOf: PF,
|
|
7413
|
+
hasOwn: PF,
|
|
7414
|
+
is: PF,
|
|
7415
|
+
isExtensible: PF,
|
|
7416
|
+
isFrozen: PF,
|
|
7417
|
+
isSealed: PF,
|
|
7418
|
+
keys: PF,
|
|
7419
|
+
fromEntries: O,
|
|
7420
|
+
entries: PF_NO_GETTER,
|
|
7421
|
+
values: PF_NO_GETTER,
|
|
7422
|
+
prototype: O
|
|
7423
|
+
},
|
|
7424
|
+
parseFloat: PF,
|
|
7425
|
+
parseInt: PF,
|
|
7426
|
+
Promise: {
|
|
7427
|
+
__proto__: null,
|
|
7428
|
+
[ValueProperties]: IMPURE,
|
|
7429
|
+
all: O,
|
|
7430
|
+
allSettled: O,
|
|
7431
|
+
any: O,
|
|
7432
|
+
prototype: O,
|
|
7433
|
+
race: O,
|
|
7434
|
+
reject: O,
|
|
7435
|
+
resolve: O
|
|
7436
|
+
},
|
|
7437
|
+
propertyIsEnumerable: O,
|
|
7438
|
+
Proxy: O,
|
|
7439
|
+
RangeError: PC,
|
|
7440
|
+
ReferenceError: PC,
|
|
7441
|
+
Reflect: O,
|
|
7442
|
+
RegExp: PC,
|
|
7443
|
+
Set: PC_WITH_ARRAY,
|
|
7444
|
+
SharedArrayBuffer: C,
|
|
7445
|
+
String: {
|
|
7446
|
+
__proto__: null,
|
|
7447
|
+
[ValueProperties]: PURE,
|
|
7448
|
+
fromCharCode: PF,
|
|
7449
|
+
fromCodePoint: PF,
|
|
7450
|
+
prototype: O,
|
|
7451
|
+
raw: PF
|
|
7452
|
+
},
|
|
7453
|
+
Symbol: {
|
|
7454
|
+
__proto__: null,
|
|
7455
|
+
[ValueProperties]: PURE,
|
|
7456
|
+
for: PF,
|
|
7457
|
+
keyFor: PF,
|
|
7458
|
+
prototype: O,
|
|
7459
|
+
toStringTag: {
|
|
7460
|
+
__proto__: null,
|
|
7461
|
+
[ValueProperties]: {
|
|
7462
|
+
deoptimizeArgumentsOnCall: doNothing,
|
|
7463
|
+
getLiteralValue() {
|
|
7464
|
+
return SymbolToStringTag;
|
|
7465
|
+
},
|
|
7466
|
+
hasEffectsWhenCalled: returnTrue
|
|
8066
7467
|
}
|
|
8067
7468
|
}
|
|
8068
7469
|
},
|
|
@@ -8729,295 +8130,928 @@ const knownGlobals = {
|
|
|
8729
8130
|
for (const global of ['window', 'global', 'self', 'globalThis']) {
|
|
8730
8131
|
knownGlobals[global] = knownGlobals;
|
|
8731
8132
|
}
|
|
8732
|
-
function getGlobalAtPath(path) {
|
|
8733
|
-
let currentGlobal = knownGlobals;
|
|
8734
|
-
for (const pathSegment of path) {
|
|
8735
|
-
if (typeof pathSegment !== 'string') {
|
|
8736
|
-
return null;
|
|
8133
|
+
function getGlobalAtPath(path) {
|
|
8134
|
+
let currentGlobal = knownGlobals;
|
|
8135
|
+
for (const pathSegment of path) {
|
|
8136
|
+
if (typeof pathSegment !== 'string') {
|
|
8137
|
+
return null;
|
|
8138
|
+
}
|
|
8139
|
+
currentGlobal = currentGlobal[pathSegment];
|
|
8140
|
+
if (!currentGlobal) {
|
|
8141
|
+
return null;
|
|
8142
|
+
}
|
|
8143
|
+
}
|
|
8144
|
+
return currentGlobal[ValueProperties];
|
|
8145
|
+
}
|
|
8146
|
+
|
|
8147
|
+
class GlobalVariable extends Variable {
|
|
8148
|
+
constructor(name) {
|
|
8149
|
+
super(name);
|
|
8150
|
+
// Ensure we use live-bindings for globals as we do not know if they have
|
|
8151
|
+
// been reassigned
|
|
8152
|
+
this.markReassigned();
|
|
8153
|
+
}
|
|
8154
|
+
deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
|
|
8155
|
+
switch (interaction.type) {
|
|
8156
|
+
// While there is no point in testing these cases as at the moment, they
|
|
8157
|
+
// are also covered via other means, we keep them for completeness
|
|
8158
|
+
case INTERACTION_ACCESSED:
|
|
8159
|
+
case INTERACTION_ASSIGNED: {
|
|
8160
|
+
if (!getGlobalAtPath([this.name, ...path].slice(0, -1))) {
|
|
8161
|
+
super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
8162
|
+
}
|
|
8163
|
+
return;
|
|
8164
|
+
}
|
|
8165
|
+
case INTERACTION_CALLED: {
|
|
8166
|
+
const globalAtPath = getGlobalAtPath([this.name, ...path]);
|
|
8167
|
+
if (globalAtPath) {
|
|
8168
|
+
globalAtPath.deoptimizeArgumentsOnCall(interaction);
|
|
8169
|
+
}
|
|
8170
|
+
else {
|
|
8171
|
+
super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
8172
|
+
}
|
|
8173
|
+
return;
|
|
8174
|
+
}
|
|
8175
|
+
}
|
|
8176
|
+
}
|
|
8177
|
+
getLiteralValueAtPath(path, _recursionTracker, _origin) {
|
|
8178
|
+
const globalAtPath = getGlobalAtPath([this.name, ...path]);
|
|
8179
|
+
return globalAtPath ? globalAtPath.getLiteralValue() : UnknownValue;
|
|
8180
|
+
}
|
|
8181
|
+
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
8182
|
+
switch (interaction.type) {
|
|
8183
|
+
case INTERACTION_ACCESSED: {
|
|
8184
|
+
if (path.length === 0) {
|
|
8185
|
+
// Technically, "undefined" is a global variable of sorts
|
|
8186
|
+
return this.name !== 'undefined' && !getGlobalAtPath([this.name]);
|
|
8187
|
+
}
|
|
8188
|
+
return !getGlobalAtPath([this.name, ...path].slice(0, -1));
|
|
8189
|
+
}
|
|
8190
|
+
case INTERACTION_ASSIGNED: {
|
|
8191
|
+
return true;
|
|
8192
|
+
}
|
|
8193
|
+
case INTERACTION_CALLED: {
|
|
8194
|
+
const globalAtPath = getGlobalAtPath([this.name, ...path]);
|
|
8195
|
+
return !globalAtPath || globalAtPath.hasEffectsWhenCalled(interaction, context);
|
|
8196
|
+
}
|
|
8197
|
+
}
|
|
8198
|
+
}
|
|
8199
|
+
}
|
|
8200
|
+
|
|
8201
|
+
class LocalVariable extends Variable {
|
|
8202
|
+
constructor(name, declarator, init, context, kind) {
|
|
8203
|
+
super(name);
|
|
8204
|
+
this.init = init;
|
|
8205
|
+
this.calledFromTryStatement = false;
|
|
8206
|
+
this.additionalInitializers = null;
|
|
8207
|
+
this.expressionsToBeDeoptimized = [];
|
|
8208
|
+
this.declarations = declarator ? [declarator] : [];
|
|
8209
|
+
this.deoptimizationTracker = context.deoptimizationTracker;
|
|
8210
|
+
this.module = context.module;
|
|
8211
|
+
this.kind = kind;
|
|
8212
|
+
}
|
|
8213
|
+
addDeclaration(identifier, init) {
|
|
8214
|
+
this.declarations.push(identifier);
|
|
8215
|
+
this.markInitializersForDeoptimization().push(init);
|
|
8216
|
+
}
|
|
8217
|
+
consolidateInitializers() {
|
|
8218
|
+
if (this.additionalInitializers) {
|
|
8219
|
+
for (const initializer of this.additionalInitializers) {
|
|
8220
|
+
initializer.deoptimizePath(UNKNOWN_PATH);
|
|
8221
|
+
}
|
|
8222
|
+
this.additionalInitializers = null;
|
|
8223
|
+
}
|
|
8224
|
+
}
|
|
8225
|
+
deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
|
|
8226
|
+
if (this.isReassigned) {
|
|
8227
|
+
deoptimizeInteraction(interaction);
|
|
8228
|
+
return;
|
|
8229
|
+
}
|
|
8230
|
+
recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
|
|
8231
|
+
}
|
|
8232
|
+
deoptimizePath(path) {
|
|
8233
|
+
if (this.isReassigned ||
|
|
8234
|
+
this.deoptimizationTracker.trackEntityAtPathAndGetIfTracked(path, this)) {
|
|
8235
|
+
return;
|
|
8236
|
+
}
|
|
8237
|
+
if (path.length === 0) {
|
|
8238
|
+
this.markReassigned();
|
|
8239
|
+
const expressionsToBeDeoptimized = this.expressionsToBeDeoptimized;
|
|
8240
|
+
this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
|
|
8241
|
+
for (const expression of expressionsToBeDeoptimized) {
|
|
8242
|
+
expression.deoptimizeCache();
|
|
8243
|
+
}
|
|
8244
|
+
this.init.deoptimizePath(UNKNOWN_PATH);
|
|
8245
|
+
}
|
|
8246
|
+
else {
|
|
8247
|
+
this.init.deoptimizePath(path);
|
|
8248
|
+
}
|
|
8249
|
+
}
|
|
8250
|
+
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
8251
|
+
if (this.isReassigned) {
|
|
8252
|
+
return UnknownValue;
|
|
8253
|
+
}
|
|
8254
|
+
return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
|
|
8255
|
+
this.expressionsToBeDeoptimized.push(origin);
|
|
8256
|
+
return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
|
|
8257
|
+
}, UnknownValue);
|
|
8258
|
+
}
|
|
8259
|
+
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|
|
8260
|
+
if (this.isReassigned) {
|
|
8261
|
+
return UNKNOWN_RETURN_EXPRESSION;
|
|
8262
|
+
}
|
|
8263
|
+
return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
|
|
8264
|
+
this.expressionsToBeDeoptimized.push(origin);
|
|
8265
|
+
return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
|
|
8266
|
+
}, UNKNOWN_RETURN_EXPRESSION);
|
|
8267
|
+
}
|
|
8268
|
+
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
8269
|
+
switch (interaction.type) {
|
|
8270
|
+
case INTERACTION_ACCESSED: {
|
|
8271
|
+
if (this.isReassigned)
|
|
8272
|
+
return true;
|
|
8273
|
+
return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
|
|
8274
|
+
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8275
|
+
}
|
|
8276
|
+
case INTERACTION_ASSIGNED: {
|
|
8277
|
+
if (this.included)
|
|
8278
|
+
return true;
|
|
8279
|
+
if (path.length === 0)
|
|
8280
|
+
return false;
|
|
8281
|
+
if (this.isReassigned)
|
|
8282
|
+
return true;
|
|
8283
|
+
return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
|
|
8284
|
+
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8285
|
+
}
|
|
8286
|
+
case INTERACTION_CALLED: {
|
|
8287
|
+
if (this.isReassigned)
|
|
8288
|
+
return true;
|
|
8289
|
+
return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
|
|
8290
|
+
this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8291
|
+
}
|
|
8292
|
+
}
|
|
8293
|
+
}
|
|
8294
|
+
include() {
|
|
8295
|
+
if (!this.included) {
|
|
8296
|
+
super.include();
|
|
8297
|
+
for (const declaration of this.declarations) {
|
|
8298
|
+
// If node is a default export, it can save a tree-shaking run to include the full declaration now
|
|
8299
|
+
if (!declaration.included)
|
|
8300
|
+
declaration.include(createInclusionContext(), false);
|
|
8301
|
+
let node = declaration.parent;
|
|
8302
|
+
while (!node.included) {
|
|
8303
|
+
// We do not want to properly include parents in case they are part of a dead branch
|
|
8304
|
+
// in which case .include() might pull in more dead code
|
|
8305
|
+
node.included = true;
|
|
8306
|
+
if (node.type === parseAst_js.Program)
|
|
8307
|
+
break;
|
|
8308
|
+
node = node.parent;
|
|
8309
|
+
}
|
|
8310
|
+
}
|
|
8311
|
+
}
|
|
8312
|
+
}
|
|
8313
|
+
includeCallArguments(context, parameters) {
|
|
8314
|
+
if (this.isReassigned || context.includedCallArguments.has(this.init)) {
|
|
8315
|
+
for (const argument of parameters) {
|
|
8316
|
+
argument.include(context, false);
|
|
8317
|
+
}
|
|
8318
|
+
}
|
|
8319
|
+
else {
|
|
8320
|
+
context.includedCallArguments.add(this.init);
|
|
8321
|
+
this.init.includeCallArguments(context, parameters);
|
|
8322
|
+
context.includedCallArguments.delete(this.init);
|
|
8323
|
+
}
|
|
8324
|
+
}
|
|
8325
|
+
markCalledFromTryStatement() {
|
|
8326
|
+
this.calledFromTryStatement = true;
|
|
8327
|
+
}
|
|
8328
|
+
markInitializersForDeoptimization() {
|
|
8329
|
+
if (this.additionalInitializers === null) {
|
|
8330
|
+
this.additionalInitializers = [this.init];
|
|
8331
|
+
this.init = UNKNOWN_EXPRESSION;
|
|
8332
|
+
this.markReassigned();
|
|
8333
|
+
}
|
|
8334
|
+
return this.additionalInitializers;
|
|
8335
|
+
}
|
|
8336
|
+
}
|
|
8337
|
+
|
|
8338
|
+
const tdzVariableKinds = new Set(['class', 'const', 'let', 'var', 'using', 'await using']);
|
|
8339
|
+
class Identifier extends NodeBase {
|
|
8340
|
+
constructor() {
|
|
8341
|
+
super(...arguments);
|
|
8342
|
+
this.variable = null;
|
|
8343
|
+
this.isReferenceVariable = false;
|
|
8344
|
+
}
|
|
8345
|
+
get isTDZAccess() {
|
|
8346
|
+
if (!isFlagSet(this.flags, 4 /* Flag.tdzAccessDefined */)) {
|
|
8347
|
+
return null;
|
|
8348
|
+
}
|
|
8349
|
+
return isFlagSet(this.flags, 8 /* Flag.tdzAccess */);
|
|
8350
|
+
}
|
|
8351
|
+
set isTDZAccess(value) {
|
|
8352
|
+
this.flags = setFlag(this.flags, 4 /* Flag.tdzAccessDefined */, true);
|
|
8353
|
+
this.flags = setFlag(this.flags, 8 /* Flag.tdzAccess */, value);
|
|
8354
|
+
}
|
|
8355
|
+
addExportedVariables(variables, exportNamesByVariable) {
|
|
8356
|
+
if (exportNamesByVariable.has(this.variable)) {
|
|
8357
|
+
variables.push(this.variable);
|
|
8358
|
+
}
|
|
8359
|
+
}
|
|
8360
|
+
bind() {
|
|
8361
|
+
if (!this.variable && is_reference(this, this.parent)) {
|
|
8362
|
+
this.variable = this.scope.findVariable(this.name);
|
|
8363
|
+
this.variable.addReference(this);
|
|
8364
|
+
this.isReferenceVariable = true;
|
|
8365
|
+
}
|
|
8366
|
+
}
|
|
8367
|
+
declare(kind, init) {
|
|
8368
|
+
let variable;
|
|
8369
|
+
const { treeshake } = this.scope.context.options;
|
|
8370
|
+
switch (kind) {
|
|
8371
|
+
case 'var': {
|
|
8372
|
+
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
8373
|
+
if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
|
|
8374
|
+
// Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
|
|
8375
|
+
variable.markInitializersForDeoptimization();
|
|
8376
|
+
}
|
|
8377
|
+
break;
|
|
8378
|
+
}
|
|
8379
|
+
case 'function': {
|
|
8380
|
+
// in strict mode, functions are only hoisted within a scope but not across block scopes
|
|
8381
|
+
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
8382
|
+
break;
|
|
8383
|
+
}
|
|
8384
|
+
case 'let':
|
|
8385
|
+
case 'const':
|
|
8386
|
+
case 'using':
|
|
8387
|
+
case 'await using':
|
|
8388
|
+
case 'class': {
|
|
8389
|
+
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
8390
|
+
break;
|
|
8391
|
+
}
|
|
8392
|
+
case 'parameter': {
|
|
8393
|
+
variable = this.scope.addParameterDeclaration(this);
|
|
8394
|
+
break;
|
|
8395
|
+
}
|
|
8396
|
+
/* istanbul ignore next */
|
|
8397
|
+
default: {
|
|
8398
|
+
/* istanbul ignore next */
|
|
8399
|
+
throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
|
|
8400
|
+
}
|
|
8401
|
+
}
|
|
8402
|
+
return [(this.variable = variable)];
|
|
8403
|
+
}
|
|
8404
|
+
deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
|
|
8405
|
+
this.variable.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
8406
|
+
}
|
|
8407
|
+
deoptimizePath(path) {
|
|
8408
|
+
if (path.length === 0 && !this.scope.contains(this.name)) {
|
|
8409
|
+
this.disallowImportReassignment();
|
|
8410
|
+
}
|
|
8411
|
+
// We keep conditional chaining because an unknown Node could have an
|
|
8412
|
+
// Identifier as property that might be deoptimized by default
|
|
8413
|
+
this.variable?.deoptimizePath(path);
|
|
8414
|
+
}
|
|
8415
|
+
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
8416
|
+
return this.getVariableRespectingTDZ().getLiteralValueAtPath(path, recursionTracker, origin);
|
|
8417
|
+
}
|
|
8418
|
+
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|
|
8419
|
+
const [expression, isPure] = this.getVariableRespectingTDZ().getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
|
|
8420
|
+
return [expression, isPure || this.isPureFunction(path)];
|
|
8421
|
+
}
|
|
8422
|
+
hasEffects(context) {
|
|
8423
|
+
if (!this.deoptimized)
|
|
8424
|
+
this.applyDeoptimizations();
|
|
8425
|
+
if (this.isPossibleTDZ() && this.variable.kind !== 'var') {
|
|
8426
|
+
return true;
|
|
8427
|
+
}
|
|
8428
|
+
return (this.scope.context.options.treeshake
|
|
8429
|
+
.unknownGlobalSideEffects &&
|
|
8430
|
+
this.variable instanceof GlobalVariable &&
|
|
8431
|
+
!this.isPureFunction(EMPTY_PATH) &&
|
|
8432
|
+
this.variable.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
8433
|
+
}
|
|
8434
|
+
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
8435
|
+
switch (interaction.type) {
|
|
8436
|
+
case INTERACTION_ACCESSED: {
|
|
8437
|
+
return (this.variable !== null &&
|
|
8438
|
+
!this.isPureFunction(path) &&
|
|
8439
|
+
this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8440
|
+
}
|
|
8441
|
+
case INTERACTION_ASSIGNED: {
|
|
8442
|
+
return (path.length > 0 ? this.getVariableRespectingTDZ() : this.variable).hasEffectsOnInteractionAtPath(path, interaction, context);
|
|
8443
|
+
}
|
|
8444
|
+
case INTERACTION_CALLED: {
|
|
8445
|
+
return (!this.isPureFunction(path) &&
|
|
8446
|
+
this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8447
|
+
}
|
|
8448
|
+
}
|
|
8449
|
+
}
|
|
8450
|
+
include() {
|
|
8451
|
+
if (!this.deoptimized)
|
|
8452
|
+
this.applyDeoptimizations();
|
|
8453
|
+
if (!this.included) {
|
|
8454
|
+
this.included = true;
|
|
8455
|
+
if (this.variable !== null) {
|
|
8456
|
+
this.scope.context.includeVariableInModule(this.variable);
|
|
8457
|
+
}
|
|
8458
|
+
}
|
|
8459
|
+
}
|
|
8460
|
+
includeCallArguments(context, parameters) {
|
|
8461
|
+
this.variable.includeCallArguments(context, parameters);
|
|
8462
|
+
}
|
|
8463
|
+
isPossibleTDZ() {
|
|
8464
|
+
// return cached value to avoid issues with the next tree-shaking pass
|
|
8465
|
+
const cachedTdzAccess = this.isTDZAccess;
|
|
8466
|
+
if (cachedTdzAccess !== null)
|
|
8467
|
+
return cachedTdzAccess;
|
|
8468
|
+
if (!(this.variable instanceof LocalVariable &&
|
|
8469
|
+
this.variable.kind &&
|
|
8470
|
+
tdzVariableKinds.has(this.variable.kind) &&
|
|
8471
|
+
// we ignore possible TDZs due to circular module dependencies as
|
|
8472
|
+
// otherwise we get many false positives
|
|
8473
|
+
this.variable.module === this.scope.context.module)) {
|
|
8474
|
+
return (this.isTDZAccess = false);
|
|
8475
|
+
}
|
|
8476
|
+
let decl_id;
|
|
8477
|
+
if (this.variable.declarations &&
|
|
8478
|
+
this.variable.declarations.length === 1 &&
|
|
8479
|
+
(decl_id = this.variable.declarations[0]) &&
|
|
8480
|
+
this.start < decl_id.start &&
|
|
8481
|
+
closestParentFunctionOrProgram(this) === closestParentFunctionOrProgram(decl_id)) {
|
|
8482
|
+
// a variable accessed before its declaration
|
|
8483
|
+
// in the same function or at top level of module
|
|
8484
|
+
return (this.isTDZAccess = true);
|
|
8485
|
+
}
|
|
8486
|
+
// We ignore the case where the module is not yet executed because
|
|
8487
|
+
// moduleSideEffects are false.
|
|
8488
|
+
if (!this.variable.initReached && this.scope.context.module.isExecuted) {
|
|
8489
|
+
// Either a const/let TDZ violation or
|
|
8490
|
+
// var use before declaration was encountered.
|
|
8491
|
+
return (this.isTDZAccess = true);
|
|
8492
|
+
}
|
|
8493
|
+
return (this.isTDZAccess = false);
|
|
8494
|
+
}
|
|
8495
|
+
markDeclarationReached() {
|
|
8496
|
+
this.variable.initReached = true;
|
|
8497
|
+
}
|
|
8498
|
+
render(code, { snippets: { getPropertyAccess }, useOriginalName }, { renderedParentType, isCalleeOfRenderedParent, isShorthandProperty } = parseAst_js.BLANK) {
|
|
8499
|
+
if (this.variable) {
|
|
8500
|
+
const name = this.variable.getName(getPropertyAccess, useOriginalName);
|
|
8501
|
+
if (name !== this.name) {
|
|
8502
|
+
code.overwrite(this.start, this.end, name, {
|
|
8503
|
+
contentOnly: true,
|
|
8504
|
+
storeName: true
|
|
8505
|
+
});
|
|
8506
|
+
if (isShorthandProperty) {
|
|
8507
|
+
code.prependRight(this.start, `${this.name}: `);
|
|
8508
|
+
}
|
|
8509
|
+
}
|
|
8510
|
+
// In strict mode, any variable named "eval" must be the actual "eval" function
|
|
8511
|
+
if (name === 'eval' &&
|
|
8512
|
+
renderedParentType === parseAst_js.CallExpression &&
|
|
8513
|
+
isCalleeOfRenderedParent) {
|
|
8514
|
+
code.appendRight(this.start, '0, ');
|
|
8515
|
+
}
|
|
8516
|
+
}
|
|
8517
|
+
}
|
|
8518
|
+
disallowImportReassignment() {
|
|
8519
|
+
return this.scope.context.error(parseAst_js.logIllegalImportReassignment(this.name, this.scope.context.module.id), this.start);
|
|
8520
|
+
}
|
|
8521
|
+
applyDeoptimizations() {
|
|
8522
|
+
this.deoptimized = true;
|
|
8523
|
+
if (this.variable instanceof LocalVariable) {
|
|
8524
|
+
this.variable.consolidateInitializers();
|
|
8525
|
+
this.scope.context.requestTreeshakingPass();
|
|
8526
|
+
}
|
|
8527
|
+
if (this.isReferenceVariable) {
|
|
8528
|
+
this.variable.addUsedPlace(this);
|
|
8529
|
+
this.scope.context.requestTreeshakingPass();
|
|
8530
|
+
}
|
|
8531
|
+
}
|
|
8532
|
+
getVariableRespectingTDZ() {
|
|
8533
|
+
if (this.isPossibleTDZ()) {
|
|
8534
|
+
return UNKNOWN_EXPRESSION;
|
|
8535
|
+
}
|
|
8536
|
+
return this.variable;
|
|
8537
|
+
}
|
|
8538
|
+
isPureFunction(path) {
|
|
8539
|
+
let currentPureFunction = this.scope.context.manualPureFunctions[this.name];
|
|
8540
|
+
for (const segment of path) {
|
|
8541
|
+
if (currentPureFunction) {
|
|
8542
|
+
if (currentPureFunction[PureFunctionKey]) {
|
|
8543
|
+
return true;
|
|
8544
|
+
}
|
|
8545
|
+
currentPureFunction = currentPureFunction[segment];
|
|
8546
|
+
}
|
|
8547
|
+
else {
|
|
8548
|
+
return false;
|
|
8549
|
+
}
|
|
8550
|
+
}
|
|
8551
|
+
return currentPureFunction?.[PureFunctionKey];
|
|
8552
|
+
}
|
|
8553
|
+
}
|
|
8554
|
+
function closestParentFunctionOrProgram(node) {
|
|
8555
|
+
while (node && !/^Program|Function/.test(node.type)) {
|
|
8556
|
+
node = node.parent;
|
|
8557
|
+
}
|
|
8558
|
+
// one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
|
|
8559
|
+
return node;
|
|
8560
|
+
}
|
|
8561
|
+
|
|
8562
|
+
const MAX_TRACKED_INTERACTIONS = 20;
|
|
8563
|
+
const NO_INTERACTIONS = parseAst_js.EMPTY_ARRAY;
|
|
8564
|
+
const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
|
|
8565
|
+
const EMPTY_PATH_TRACKER = new PathTracker();
|
|
8566
|
+
const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
|
|
8567
|
+
class ParameterVariable extends LocalVariable {
|
|
8568
|
+
constructor(name, declarator, context) {
|
|
8569
|
+
super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
|
|
8570
|
+
this.deoptimizationInteractions = [];
|
|
8571
|
+
this.deoptimizations = new PathTracker();
|
|
8572
|
+
this.deoptimizedFields = new Set();
|
|
8573
|
+
this.entitiesToBeDeoptimized = new Set();
|
|
8574
|
+
this.expressionsUseTheKnownValue = [];
|
|
8575
|
+
this.knownValue = null;
|
|
8576
|
+
this.knownValueLiteral = UnknownValue;
|
|
8577
|
+
this.frozenValue = null;
|
|
8578
|
+
}
|
|
8579
|
+
addEntityToBeDeoptimized(entity) {
|
|
8580
|
+
if (entity === UNKNOWN_EXPRESSION) {
|
|
8581
|
+
// As unknown expressions fully deoptimize all interactions, we can clear
|
|
8582
|
+
// the interaction cache at this point provided we keep this optimization
|
|
8583
|
+
// in mind when adding new interactions
|
|
8584
|
+
if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
|
|
8585
|
+
this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
|
|
8586
|
+
for (const { interaction } of this.deoptimizationInteractions) {
|
|
8587
|
+
deoptimizeInteraction(interaction);
|
|
8588
|
+
}
|
|
8589
|
+
this.deoptimizationInteractions = NO_INTERACTIONS;
|
|
8590
|
+
}
|
|
8591
|
+
}
|
|
8592
|
+
else if (this.deoptimizedFields.has(UnknownKey)) {
|
|
8593
|
+
// This means that we already deoptimized all interactions and no longer
|
|
8594
|
+
// track them
|
|
8595
|
+
entity.deoptimizePath(UNKNOWN_PATH);
|
|
8596
|
+
}
|
|
8597
|
+
else if (!this.entitiesToBeDeoptimized.has(entity)) {
|
|
8598
|
+
this.entitiesToBeDeoptimized.add(entity);
|
|
8599
|
+
for (const field of this.deoptimizedFields) {
|
|
8600
|
+
entity.deoptimizePath([field]);
|
|
8601
|
+
}
|
|
8602
|
+
for (const { interaction, path } of this.deoptimizationInteractions) {
|
|
8603
|
+
entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
|
|
8604
|
+
}
|
|
8605
|
+
}
|
|
8606
|
+
}
|
|
8607
|
+
markReassigned() {
|
|
8608
|
+
if (this.isReassigned) {
|
|
8609
|
+
return;
|
|
8610
|
+
}
|
|
8611
|
+
super.markReassigned();
|
|
8612
|
+
for (const expression of this.expressionsUseTheKnownValue) {
|
|
8613
|
+
expression.deoptimizeCache();
|
|
8614
|
+
}
|
|
8615
|
+
this.expressionsUseTheKnownValue = parseAst_js.EMPTY_ARRAY;
|
|
8616
|
+
}
|
|
8617
|
+
deoptimizeCache() {
|
|
8618
|
+
this.markReassigned();
|
|
8619
|
+
}
|
|
8620
|
+
/**
|
|
8621
|
+
* Update the known value of the parameter variable.
|
|
8622
|
+
* Must be called for every function call, so it can track all the arguments,
|
|
8623
|
+
* and deoptimizeCache itself to mark reassigned if the argument is changed.
|
|
8624
|
+
* @param argument The argument of the function call
|
|
8625
|
+
*/
|
|
8626
|
+
updateKnownValue(argument) {
|
|
8627
|
+
if (this.isReassigned) {
|
|
8628
|
+
return;
|
|
8629
|
+
}
|
|
8630
|
+
if (this.knownValue === null) {
|
|
8631
|
+
this.knownValue = argument;
|
|
8632
|
+
this.knownValueLiteral = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
|
|
8633
|
+
return;
|
|
8634
|
+
}
|
|
8635
|
+
// the same literal or identifier, do nothing
|
|
8636
|
+
if (this.knownValue === argument ||
|
|
8637
|
+
(this.knownValue instanceof Identifier &&
|
|
8638
|
+
argument instanceof Identifier &&
|
|
8639
|
+
this.knownValue.variable === argument.variable)) {
|
|
8640
|
+
return;
|
|
8641
|
+
}
|
|
8642
|
+
const oldValue = this.knownValueLiteral;
|
|
8643
|
+
if (typeof oldValue === 'symbol') {
|
|
8644
|
+
this.markReassigned();
|
|
8645
|
+
return;
|
|
8646
|
+
}
|
|
8647
|
+
// add tracking for the new argument
|
|
8648
|
+
const newValue = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
|
|
8649
|
+
if (newValue !== oldValue) {
|
|
8650
|
+
this.markReassigned();
|
|
8651
|
+
}
|
|
8652
|
+
}
|
|
8653
|
+
/**
|
|
8654
|
+
* This function freezes the known value of the parameter variable,
|
|
8655
|
+
* so the optimization starts with a certain ExpressionEntity.
|
|
8656
|
+
* The optimization can be undone by calling `markReassigned`.
|
|
8657
|
+
* @returns the frozen value
|
|
8658
|
+
*/
|
|
8659
|
+
getKnownValue() {
|
|
8660
|
+
if (this.frozenValue === null) {
|
|
8661
|
+
this.frozenValue = this.knownValue || UNKNOWN_EXPRESSION;
|
|
8662
|
+
}
|
|
8663
|
+
return this.frozenValue;
|
|
8664
|
+
}
|
|
8665
|
+
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
8666
|
+
if (this.isReassigned) {
|
|
8667
|
+
return UnknownValue;
|
|
8668
|
+
}
|
|
8669
|
+
const knownValue = this.getKnownValue();
|
|
8670
|
+
this.expressionsUseTheKnownValue.push(origin);
|
|
8671
|
+
return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath(path, recursionTracker, origin), UnknownValue);
|
|
8672
|
+
}
|
|
8673
|
+
hasEffectsOnInteractionAtPath(path, interaction, context) {
|
|
8674
|
+
if (this.isReassigned || interaction.type === INTERACTION_ASSIGNED) {
|
|
8675
|
+
return super.hasEffectsOnInteractionAtPath(path, interaction, context);
|
|
8676
|
+
}
|
|
8677
|
+
const knownValue = this.getKnownValue();
|
|
8678
|
+
return knownValue.hasEffectsOnInteractionAtPath(path, interaction, context);
|
|
8679
|
+
}
|
|
8680
|
+
deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
|
|
8681
|
+
// For performance reasons, we fully deoptimize all deeper interactions
|
|
8682
|
+
if (path.length >= 2 ||
|
|
8683
|
+
this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
|
|
8684
|
+
this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
|
|
8685
|
+
(path.length === 1 &&
|
|
8686
|
+
(this.deoptimizedFields.has(UnknownKey) ||
|
|
8687
|
+
(interaction.type === INTERACTION_CALLED && this.deoptimizedFields.has(path[0]))))) {
|
|
8688
|
+
deoptimizeInteraction(interaction);
|
|
8689
|
+
return;
|
|
8690
|
+
}
|
|
8691
|
+
if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
|
|
8692
|
+
for (const entity of this.entitiesToBeDeoptimized) {
|
|
8693
|
+
entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
|
|
8694
|
+
}
|
|
8695
|
+
if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
|
|
8696
|
+
this.deoptimizationInteractions.push({
|
|
8697
|
+
interaction,
|
|
8698
|
+
path
|
|
8699
|
+
});
|
|
8700
|
+
}
|
|
8701
|
+
}
|
|
8702
|
+
}
|
|
8703
|
+
deoptimizePath(path) {
|
|
8704
|
+
if (path.length === 0) {
|
|
8705
|
+
this.markReassigned();
|
|
8706
|
+
return;
|
|
8707
|
+
}
|
|
8708
|
+
if (this.deoptimizedFields.has(UnknownKey)) {
|
|
8709
|
+
return;
|
|
8710
|
+
}
|
|
8711
|
+
const key = path[0];
|
|
8712
|
+
if (this.deoptimizedFields.has(key)) {
|
|
8713
|
+
return;
|
|
8714
|
+
}
|
|
8715
|
+
this.deoptimizedFields.add(key);
|
|
8716
|
+
for (const entity of this.entitiesToBeDeoptimized) {
|
|
8717
|
+
// We do not need a recursion tracker here as we already track whether
|
|
8718
|
+
// this field is deoptimized
|
|
8719
|
+
entity.deoptimizePath([key]);
|
|
8720
|
+
}
|
|
8721
|
+
if (key === UnknownKey) {
|
|
8722
|
+
// save some memory
|
|
8723
|
+
this.deoptimizationInteractions = NO_INTERACTIONS;
|
|
8724
|
+
this.deoptimizations = EMPTY_PATH_TRACKER;
|
|
8725
|
+
this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
|
|
8726
|
+
this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
|
|
8727
|
+
}
|
|
8728
|
+
}
|
|
8729
|
+
getReturnExpressionWhenCalledAtPath(path) {
|
|
8730
|
+
// We deoptimize everything that is called as that will trivially deoptimize
|
|
8731
|
+
// the corresponding return expressions as well and avoid badly performing
|
|
8732
|
+
// and complicated alternatives
|
|
8733
|
+
if (path.length === 0) {
|
|
8734
|
+
this.deoptimizePath(UNKNOWN_PATH);
|
|
8735
|
+
}
|
|
8736
|
+
else if (!this.deoptimizedFields.has(path[0])) {
|
|
8737
|
+
this.deoptimizePath([path[0]]);
|
|
8738
|
+
}
|
|
8739
|
+
return UNKNOWN_RETURN_EXPRESSION;
|
|
8740
|
+
}
|
|
8741
|
+
}
|
|
8742
|
+
|
|
8743
|
+
function getSafeName(baseName, usedNames, forbiddenNames) {
|
|
8744
|
+
let safeName = baseName;
|
|
8745
|
+
let count = 1;
|
|
8746
|
+
while (usedNames.has(safeName) || RESERVED_NAMES.has(safeName) || forbiddenNames?.has(safeName)) {
|
|
8747
|
+
safeName = `${baseName}$${toBase64(count++)}`;
|
|
8748
|
+
}
|
|
8749
|
+
usedNames.add(safeName);
|
|
8750
|
+
return safeName;
|
|
8751
|
+
}
|
|
8752
|
+
|
|
8753
|
+
class Scope {
|
|
8754
|
+
constructor() {
|
|
8755
|
+
this.children = [];
|
|
8756
|
+
this.variables = new Map();
|
|
8757
|
+
}
|
|
8758
|
+
/*
|
|
8759
|
+
Redeclaration rules:
|
|
8760
|
+
- var can redeclare var
|
|
8761
|
+
- in function scopes, function and var can redeclare function and var
|
|
8762
|
+
- var is hoisted across scopes, function remains in the scope it is declared
|
|
8763
|
+
- var and function can redeclare function parameters, but parameters cannot redeclare parameters
|
|
8764
|
+
- function cannot redeclare catch scope parameters
|
|
8765
|
+
- var can redeclare catch scope parameters in a way
|
|
8766
|
+
- if the parameter is an identifier and not a pattern
|
|
8767
|
+
- then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
|
|
8768
|
+
- const, let, class, and function except in the cases above cannot redeclare anything
|
|
8769
|
+
*/
|
|
8770
|
+
addDeclaration(identifier, context, init, kind) {
|
|
8771
|
+
const name = identifier.name;
|
|
8772
|
+
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
8773
|
+
if (existingVariable) {
|
|
8774
|
+
const existingKind = existingVariable.kind;
|
|
8775
|
+
if (kind === 'var' && existingKind === 'var') {
|
|
8776
|
+
existingVariable.addDeclaration(identifier, init);
|
|
8777
|
+
return existingVariable;
|
|
8778
|
+
}
|
|
8779
|
+
context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
8780
|
+
}
|
|
8781
|
+
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
8782
|
+
this.variables.set(name, newVariable);
|
|
8783
|
+
return newVariable;
|
|
8784
|
+
}
|
|
8785
|
+
addHoistedVariable(name, variable) {
|
|
8786
|
+
(this.hoistedVariables ||= new Map()).set(name, variable);
|
|
8787
|
+
}
|
|
8788
|
+
contains(name) {
|
|
8789
|
+
return this.variables.has(name);
|
|
8790
|
+
}
|
|
8791
|
+
findVariable(_name) {
|
|
8792
|
+
/* istanbul ignore next */
|
|
8793
|
+
throw new Error('Internal Error: findVariable needs to be implemented by a subclass');
|
|
8794
|
+
}
|
|
8795
|
+
}
|
|
8796
|
+
|
|
8797
|
+
class ChildScope extends Scope {
|
|
8798
|
+
constructor(parent, context) {
|
|
8799
|
+
super();
|
|
8800
|
+
this.parent = parent;
|
|
8801
|
+
this.context = context;
|
|
8802
|
+
this.accessedOutsideVariables = new Map();
|
|
8803
|
+
parent.children.push(this);
|
|
8804
|
+
}
|
|
8805
|
+
addAccessedDynamicImport(importExpression) {
|
|
8806
|
+
(this.accessedDynamicImports || (this.accessedDynamicImports = new Set())).add(importExpression);
|
|
8807
|
+
if (this.parent instanceof ChildScope) {
|
|
8808
|
+
this.parent.addAccessedDynamicImport(importExpression);
|
|
8737
8809
|
}
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
8810
|
+
}
|
|
8811
|
+
addAccessedGlobals(globals, accessedGlobalsByScope) {
|
|
8812
|
+
const accessedGlobals = accessedGlobalsByScope.get(this) || new Set();
|
|
8813
|
+
for (const name of globals) {
|
|
8814
|
+
accessedGlobals.add(name);
|
|
8815
|
+
}
|
|
8816
|
+
accessedGlobalsByScope.set(this, accessedGlobals);
|
|
8817
|
+
if (this.parent instanceof ChildScope) {
|
|
8818
|
+
this.parent.addAccessedGlobals(globals, accessedGlobalsByScope);
|
|
8741
8819
|
}
|
|
8742
8820
|
}
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
class GlobalVariable extends Variable {
|
|
8747
|
-
constructor(name) {
|
|
8748
|
-
super(name);
|
|
8749
|
-
// Ensure we use live-bindings for globals as we do not know if they have
|
|
8750
|
-
// been reassigned
|
|
8751
|
-
this.markReassigned();
|
|
8821
|
+
addNamespaceMemberAccess(name, variable) {
|
|
8822
|
+
this.accessedOutsideVariables.set(name, variable);
|
|
8823
|
+
this.parent.addNamespaceMemberAccess(name, variable);
|
|
8752
8824
|
}
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8825
|
+
addReturnExpression(expression) {
|
|
8826
|
+
this.parent instanceof ChildScope && this.parent.addReturnExpression(expression);
|
|
8827
|
+
}
|
|
8828
|
+
addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
8829
|
+
for (const variable of this.accessedOutsideVariables.values()) {
|
|
8830
|
+
if (variable.included) {
|
|
8831
|
+
usedNames.add(variable.getBaseVariableName());
|
|
8832
|
+
if (format === 'system' && exportNamesByVariable.has(variable)) {
|
|
8833
|
+
usedNames.add('exports');
|
|
8761
8834
|
}
|
|
8762
|
-
return;
|
|
8763
8835
|
}
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
else {
|
|
8770
|
-
super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
8771
|
-
}
|
|
8772
|
-
return;
|
|
8836
|
+
}
|
|
8837
|
+
const accessedGlobals = accessedGlobalsByScope.get(this);
|
|
8838
|
+
if (accessedGlobals) {
|
|
8839
|
+
for (const name of accessedGlobals) {
|
|
8840
|
+
usedNames.add(name);
|
|
8773
8841
|
}
|
|
8774
8842
|
}
|
|
8775
8843
|
}
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
return globalAtPath ? globalAtPath.getLiteralValue() : UnknownValue;
|
|
8844
|
+
contains(name) {
|
|
8845
|
+
return this.variables.has(name) || this.parent.contains(name);
|
|
8779
8846
|
}
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8847
|
+
deconflict(format, exportNamesByVariable, accessedGlobalsByScope) {
|
|
8848
|
+
const usedNames = new Set();
|
|
8849
|
+
this.addUsedOutsideNames(usedNames, format, exportNamesByVariable, accessedGlobalsByScope);
|
|
8850
|
+
if (this.accessedDynamicImports) {
|
|
8851
|
+
for (const importExpression of this.accessedDynamicImports) {
|
|
8852
|
+
if (importExpression.inlineNamespace) {
|
|
8853
|
+
usedNames.add(importExpression.inlineNamespace.getBaseVariableName());
|
|
8786
8854
|
}
|
|
8787
|
-
return !getGlobalAtPath([this.name, ...path].slice(0, -1));
|
|
8788
|
-
}
|
|
8789
|
-
case INTERACTION_ASSIGNED: {
|
|
8790
|
-
return true;
|
|
8791
8855
|
}
|
|
8792
|
-
|
|
8793
|
-
|
|
8794
|
-
|
|
8856
|
+
}
|
|
8857
|
+
for (const [name, variable] of this.variables) {
|
|
8858
|
+
if (variable.included || variable.alwaysRendered) {
|
|
8859
|
+
variable.setRenderNames(null, getSafeName(name, usedNames, variable.forbiddenNames));
|
|
8795
8860
|
}
|
|
8796
8861
|
}
|
|
8797
|
-
|
|
8798
|
-
|
|
8799
|
-
|
|
8800
|
-
const tdzVariableKinds = new Set(['class', 'const', 'let', 'var', 'using', 'await using']);
|
|
8801
|
-
class Identifier extends NodeBase {
|
|
8802
|
-
constructor() {
|
|
8803
|
-
super(...arguments);
|
|
8804
|
-
this.variable = null;
|
|
8805
|
-
this.isReferenceVariable = false;
|
|
8806
|
-
}
|
|
8807
|
-
get isTDZAccess() {
|
|
8808
|
-
if (!isFlagSet(this.flags, 4 /* Flag.tdzAccessDefined */)) {
|
|
8809
|
-
return null;
|
|
8862
|
+
for (const scope of this.children) {
|
|
8863
|
+
scope.deconflict(format, exportNamesByVariable, accessedGlobalsByScope);
|
|
8810
8864
|
}
|
|
8811
|
-
return isFlagSet(this.flags, 8 /* Flag.tdzAccess */);
|
|
8812
8865
|
}
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
this.flags = setFlag(this.flags, 8 /* Flag.tdzAccess */, value);
|
|
8866
|
+
findLexicalBoundary() {
|
|
8867
|
+
return this.parent.findLexicalBoundary();
|
|
8816
8868
|
}
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8869
|
+
findVariable(name) {
|
|
8870
|
+
const knownVariable = this.variables.get(name) || this.accessedOutsideVariables.get(name);
|
|
8871
|
+
if (knownVariable) {
|
|
8872
|
+
return knownVariable;
|
|
8820
8873
|
}
|
|
8874
|
+
const variable = this.parent.findVariable(name);
|
|
8875
|
+
this.accessedOutsideVariables.set(name, variable);
|
|
8876
|
+
return variable;
|
|
8821
8877
|
}
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8878
|
+
}
|
|
8879
|
+
|
|
8880
|
+
class CatchBodyScope extends ChildScope {
|
|
8881
|
+
constructor(parent) {
|
|
8882
|
+
super(parent, parent.context);
|
|
8883
|
+
this.parent = parent;
|
|
8828
8884
|
}
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
if (
|
|
8836
|
-
//
|
|
8837
|
-
|
|
8885
|
+
addDeclaration(identifier, context, init, kind) {
|
|
8886
|
+
if (kind === 'var') {
|
|
8887
|
+
const name = identifier.name;
|
|
8888
|
+
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
8889
|
+
if (existingVariable) {
|
|
8890
|
+
const existingKind = existingVariable.kind;
|
|
8891
|
+
if (existingKind === 'parameter' &&
|
|
8892
|
+
// If this is a destructured parameter, it is forbidden to redeclare
|
|
8893
|
+
existingVariable.declarations[0].parent.type === parseAst_js.CatchClause) {
|
|
8894
|
+
// If this is a var with the same name as the catch scope parameter,
|
|
8895
|
+
// the assignment actually goes to the parameter and the var is
|
|
8896
|
+
// hoisted without assignment. Locally, it is shadowed by the
|
|
8897
|
+
// parameter
|
|
8898
|
+
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
|
|
8899
|
+
// To avoid the need to rewrite the declaration, we link the variable
|
|
8900
|
+
// names. If we ever implement a logic that splits initialization and
|
|
8901
|
+
// assignment for hoisted vars, the "renderLikeHoisted" logic can be
|
|
8902
|
+
// removed again.
|
|
8903
|
+
// We do not need to check whether there already is a linked
|
|
8904
|
+
// variable because then declaredVariable would be that linked
|
|
8905
|
+
// variable.
|
|
8906
|
+
existingVariable.renderLikeHoisted(declaredVariable);
|
|
8907
|
+
this.addHoistedVariable(name, declaredVariable);
|
|
8908
|
+
return declaredVariable;
|
|
8838
8909
|
}
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
break;
|
|
8845
|
-
}
|
|
8846
|
-
case 'let':
|
|
8847
|
-
case 'const':
|
|
8848
|
-
case 'using':
|
|
8849
|
-
case 'await using':
|
|
8850
|
-
case 'class': {
|
|
8851
|
-
variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
|
|
8852
|
-
break;
|
|
8853
|
-
}
|
|
8854
|
-
case 'parameter': {
|
|
8855
|
-
variable = this.scope.addParameterDeclaration(this);
|
|
8856
|
-
break;
|
|
8857
|
-
}
|
|
8858
|
-
/* istanbul ignore next */
|
|
8859
|
-
default: {
|
|
8860
|
-
/* istanbul ignore next */
|
|
8861
|
-
throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
|
|
8910
|
+
if (existingKind === 'var') {
|
|
8911
|
+
existingVariable.addDeclaration(identifier, init);
|
|
8912
|
+
return existingVariable;
|
|
8913
|
+
}
|
|
8914
|
+
return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
8862
8915
|
}
|
|
8916
|
+
// We only add parameters to parameter scopes
|
|
8917
|
+
const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
|
|
8918
|
+
// Necessary to make sure the init is deoptimized for conditional declarations.
|
|
8919
|
+
// We cannot call deoptimizePath here.
|
|
8920
|
+
declaredVariable.markInitializersForDeoptimization();
|
|
8921
|
+
// We add the variable to this and all parent scopes to reliably detect conflicts
|
|
8922
|
+
this.addHoistedVariable(name, declaredVariable);
|
|
8923
|
+
return declaredVariable;
|
|
8863
8924
|
}
|
|
8864
|
-
return
|
|
8925
|
+
return super.addDeclaration(identifier, context, init, kind);
|
|
8865
8926
|
}
|
|
8866
|
-
|
|
8867
|
-
|
|
8927
|
+
}
|
|
8928
|
+
|
|
8929
|
+
class FunctionBodyScope extends ChildScope {
|
|
8930
|
+
constructor(parent) {
|
|
8931
|
+
super(parent, parent.context);
|
|
8868
8932
|
}
|
|
8869
|
-
|
|
8870
|
-
|
|
8871
|
-
|
|
8933
|
+
// There is stuff that is only allowed in function scopes, i.e. functions can
|
|
8934
|
+
// be redeclared, functions and var can redeclare each other
|
|
8935
|
+
addDeclaration(identifier, context, init, kind) {
|
|
8936
|
+
const name = identifier.name;
|
|
8937
|
+
const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
|
|
8938
|
+
if (existingVariable) {
|
|
8939
|
+
const existingKind = existingVariable.kind;
|
|
8940
|
+
if ((kind === 'var' || kind === 'function') &&
|
|
8941
|
+
(existingKind === 'var' || existingKind === 'function' || existingKind === 'parameter')) {
|
|
8942
|
+
existingVariable.addDeclaration(identifier, init);
|
|
8943
|
+
return existingVariable;
|
|
8944
|
+
}
|
|
8945
|
+
context.error(parseAst_js.logRedeclarationError(name), identifier.start);
|
|
8872
8946
|
}
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
}
|
|
8877
|
-
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
8878
|
-
return this.getVariableRespectingTDZ().getLiteralValueAtPath(path, recursionTracker, origin);
|
|
8879
|
-
}
|
|
8880
|
-
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|
|
8881
|
-
const [expression, isPure] = this.getVariableRespectingTDZ().getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
|
|
8882
|
-
return [expression, isPure || this.isPureFunction(path)];
|
|
8947
|
+
const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
|
|
8948
|
+
this.variables.set(name, newVariable);
|
|
8949
|
+
return newVariable;
|
|
8883
8950
|
}
|
|
8884
|
-
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
|
|
8891
|
-
|
|
8892
|
-
this.variable instanceof GlobalVariable &&
|
|
8893
|
-
!this.isPureFunction(EMPTY_PATH) &&
|
|
8894
|
-
this.variable.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
|
|
8951
|
+
}
|
|
8952
|
+
|
|
8953
|
+
class ParameterScope extends ChildScope {
|
|
8954
|
+
constructor(parent, isCatchScope) {
|
|
8955
|
+
super(parent, parent.context);
|
|
8956
|
+
this.parameters = [];
|
|
8957
|
+
this.hasRest = false;
|
|
8958
|
+
this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
|
|
8895
8959
|
}
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
}
|
|
8906
|
-
case INTERACTION_CALLED: {
|
|
8907
|
-
return (!this.isPureFunction(path) &&
|
|
8908
|
-
this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
|
|
8909
|
-
}
|
|
8960
|
+
/**
|
|
8961
|
+
* Adds a parameter to this scope. Parameters must be added in the correct
|
|
8962
|
+
* order, i.e. from left to right.
|
|
8963
|
+
*/
|
|
8964
|
+
addParameterDeclaration(identifier) {
|
|
8965
|
+
const { name, start } = identifier;
|
|
8966
|
+
const existingParameter = this.variables.get(name);
|
|
8967
|
+
if (existingParameter) {
|
|
8968
|
+
return this.context.error(parseAst_js.logDuplicateArgumentNameError(name), start);
|
|
8910
8969
|
}
|
|
8970
|
+
const variable = new ParameterVariable(name, identifier, this.context);
|
|
8971
|
+
this.variables.set(name, variable);
|
|
8972
|
+
// We also add it to the body scope to detect name conflicts with local
|
|
8973
|
+
// variables. We still need the intermediate scope, though, as parameter
|
|
8974
|
+
// defaults are NOT taken from the body scope but from the parameters or
|
|
8975
|
+
// outside scope.
|
|
8976
|
+
this.bodyScope.addHoistedVariable(name, variable);
|
|
8977
|
+
return variable;
|
|
8911
8978
|
}
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
if (this.variable !== null) {
|
|
8918
|
-
this.scope.context.includeVariableInModule(this.variable);
|
|
8979
|
+
addParameterVariables(parameters, hasRest) {
|
|
8980
|
+
this.parameters = parameters;
|
|
8981
|
+
for (const parameterList of parameters) {
|
|
8982
|
+
for (const parameter of parameterList) {
|
|
8983
|
+
parameter.alwaysRendered = true;
|
|
8919
8984
|
}
|
|
8920
8985
|
}
|
|
8986
|
+
this.hasRest = hasRest;
|
|
8921
8987
|
}
|
|
8922
8988
|
includeCallArguments(context, parameters) {
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
// we ignore possible TDZs due to circular module dependencies as
|
|
8934
|
-
// otherwise we get many false positives
|
|
8935
|
-
this.variable.module === this.scope.context.module)) {
|
|
8936
|
-
return (this.isTDZAccess = false);
|
|
8937
|
-
}
|
|
8938
|
-
let decl_id;
|
|
8939
|
-
if (this.variable.declarations &&
|
|
8940
|
-
this.variable.declarations.length === 1 &&
|
|
8941
|
-
(decl_id = this.variable.declarations[0]) &&
|
|
8942
|
-
this.start < decl_id.start &&
|
|
8943
|
-
closestParentFunctionOrProgram(this) === closestParentFunctionOrProgram(decl_id)) {
|
|
8944
|
-
// a variable accessed before its declaration
|
|
8945
|
-
// in the same function or at top level of module
|
|
8946
|
-
return (this.isTDZAccess = true);
|
|
8947
|
-
}
|
|
8948
|
-
// We ignore the case where the module is not yet executed because
|
|
8949
|
-
// moduleSideEffects are false.
|
|
8950
|
-
if (!this.variable.initReached && this.scope.context.module.isExecuted) {
|
|
8951
|
-
// Either a const/let TDZ violation or
|
|
8952
|
-
// var use before declaration was encountered.
|
|
8953
|
-
return (this.isTDZAccess = true);
|
|
8989
|
+
let calledFromTryStatement = false;
|
|
8990
|
+
let argumentIncluded = false;
|
|
8991
|
+
const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
|
|
8992
|
+
for (const checkedArgument of parameters) {
|
|
8993
|
+
if (checkedArgument instanceof SpreadElement) {
|
|
8994
|
+
for (const argument of parameters) {
|
|
8995
|
+
argument.include(context, false);
|
|
8996
|
+
}
|
|
8997
|
+
break;
|
|
8998
|
+
}
|
|
8954
8999
|
}
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
9000
|
+
for (let index = parameters.length - 1; index >= 0; index--) {
|
|
9001
|
+
const parameterVariables = this.parameters[index] || restParameter;
|
|
9002
|
+
const argument = parameters[index];
|
|
9003
|
+
if (parameterVariables) {
|
|
9004
|
+
calledFromTryStatement = false;
|
|
9005
|
+
if (parameterVariables.length === 0) {
|
|
9006
|
+
// handle empty destructuring
|
|
9007
|
+
argumentIncluded = true;
|
|
9008
|
+
}
|
|
9009
|
+
else {
|
|
9010
|
+
for (const variable of parameterVariables) {
|
|
9011
|
+
if (variable.included) {
|
|
9012
|
+
argumentIncluded = true;
|
|
9013
|
+
}
|
|
9014
|
+
if (variable.calledFromTryStatement) {
|
|
9015
|
+
calledFromTryStatement = true;
|
|
9016
|
+
}
|
|
9017
|
+
}
|
|
8970
9018
|
}
|
|
8971
9019
|
}
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
9020
|
+
if (!argumentIncluded && argument.shouldBeIncluded(context)) {
|
|
9021
|
+
argumentIncluded = true;
|
|
9022
|
+
}
|
|
9023
|
+
if (argumentIncluded) {
|
|
9024
|
+
argument.include(context, calledFromTryStatement);
|
|
8977
9025
|
}
|
|
8978
9026
|
}
|
|
8979
9027
|
}
|
|
8980
|
-
|
|
8981
|
-
|
|
9028
|
+
}
|
|
9029
|
+
|
|
9030
|
+
class ReturnValueScope extends ParameterScope {
|
|
9031
|
+
constructor() {
|
|
9032
|
+
super(...arguments);
|
|
9033
|
+
this.returnExpression = null;
|
|
9034
|
+
this.returnExpressions = [];
|
|
8982
9035
|
}
|
|
8983
|
-
|
|
8984
|
-
this.
|
|
8985
|
-
if (this.variable instanceof LocalVariable) {
|
|
8986
|
-
this.variable.consolidateInitializers();
|
|
8987
|
-
this.scope.context.requestTreeshakingPass();
|
|
8988
|
-
}
|
|
8989
|
-
if (this.isReferenceVariable) {
|
|
8990
|
-
this.variable.addUsedPlace(this);
|
|
8991
|
-
}
|
|
9036
|
+
addReturnExpression(expression) {
|
|
9037
|
+
this.returnExpressions.push(expression);
|
|
8992
9038
|
}
|
|
8993
|
-
|
|
8994
|
-
if (this.
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
return this.variable;
|
|
9039
|
+
getReturnExpression() {
|
|
9040
|
+
if (this.returnExpression === null)
|
|
9041
|
+
this.updateReturnExpression();
|
|
9042
|
+
return this.returnExpression;
|
|
8998
9043
|
}
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
}
|
|
9008
|
-
else {
|
|
9009
|
-
return false;
|
|
9044
|
+
updateReturnExpression() {
|
|
9045
|
+
if (this.returnExpressions.length === 1) {
|
|
9046
|
+
this.returnExpression = this.returnExpressions[0];
|
|
9047
|
+
}
|
|
9048
|
+
else {
|
|
9049
|
+
this.returnExpression = UNKNOWN_EXPRESSION;
|
|
9050
|
+
for (const expression of this.returnExpressions) {
|
|
9051
|
+
expression.deoptimizePath(UNKNOWN_PATH);
|
|
9010
9052
|
}
|
|
9011
9053
|
}
|
|
9012
|
-
return currentPureFunction?.[PureFunctionKey];
|
|
9013
|
-
}
|
|
9014
|
-
}
|
|
9015
|
-
function closestParentFunctionOrProgram(node) {
|
|
9016
|
-
while (node && !/^Program|Function/.test(node.type)) {
|
|
9017
|
-
node = node.parent;
|
|
9018
9054
|
}
|
|
9019
|
-
// one of: ArrowFunctionExpression, FunctionDeclaration, FunctionExpression or Program
|
|
9020
|
-
return node;
|
|
9021
9055
|
}
|
|
9022
9056
|
|
|
9023
9057
|
function treeshakeNode(node, code, start, end) {
|
|
@@ -9308,17 +9342,11 @@ class RestElement extends NodeBase {
|
|
|
9308
9342
|
}
|
|
9309
9343
|
}
|
|
9310
9344
|
|
|
9311
|
-
// This handler does nothing.
|
|
9312
|
-
// Since we always re-evaluate argument values in a new tree-shaking pass,
|
|
9313
|
-
// we don't need to get notified if it is deoptimized.
|
|
9314
|
-
const EMPTY_DEOPTIMIZABLE_HANDLER = { deoptimizeCache() { } };
|
|
9315
9345
|
class FunctionBase extends NodeBase {
|
|
9316
9346
|
constructor() {
|
|
9317
9347
|
super(...arguments);
|
|
9318
|
-
this.knownParameterValues = [];
|
|
9319
|
-
this.allArguments = [];
|
|
9320
9348
|
this.objectEntity = null;
|
|
9321
|
-
this.
|
|
9349
|
+
this.parameterVariableValuesDeoptimized = false;
|
|
9322
9350
|
}
|
|
9323
9351
|
get async() {
|
|
9324
9352
|
return isFlagSet(this.flags, 256 /* Flag.async */);
|
|
@@ -9338,84 +9366,22 @@ class FunctionBase extends NodeBase {
|
|
|
9338
9366
|
set generator(value) {
|
|
9339
9367
|
this.flags = setFlag(this.flags, 4194304 /* Flag.generator */, value);
|
|
9340
9368
|
}
|
|
9341
|
-
|
|
9342
|
-
* update knownParameterValues when a call is made to this function
|
|
9343
|
-
* @param newArguments arguments of the call
|
|
9344
|
-
*/
|
|
9345
|
-
updateKnownParameterValues(newArguments) {
|
|
9369
|
+
updateParameterVariableValues(_arguments) {
|
|
9346
9370
|
for (let position = 0; position < this.params.length; position++) {
|
|
9347
|
-
// only the "this" argument newArguments[0] can be null
|
|
9348
|
-
// it's possible that some arguments are empty, so the value is undefined
|
|
9349
|
-
const argument = newArguments[position + 1] ?? UNDEFINED_EXPRESSION;
|
|
9350
9371
|
const parameter = this.params[position];
|
|
9351
|
-
|
|
9352
|
-
if (parameter instanceof RestElement) {
|
|
9353
|
-
return;
|
|
9354
|
-
}
|
|
9355
|
-
const knownParameterValue = this.knownParameterValues[position];
|
|
9356
|
-
if (knownParameterValue === undefined) {
|
|
9357
|
-
this.knownParameterValues[position] = argument;
|
|
9358
|
-
continue;
|
|
9359
|
-
}
|
|
9360
|
-
if (knownParameterValue === UNKNOWN_EXPRESSION ||
|
|
9361
|
-
knownParameterValue === argument ||
|
|
9362
|
-
(knownParameterValue instanceof Identifier &&
|
|
9363
|
-
argument instanceof Identifier &&
|
|
9364
|
-
knownParameterValue.variable === argument.variable)) {
|
|
9372
|
+
if (!(parameter instanceof Identifier)) {
|
|
9365
9373
|
continue;
|
|
9366
9374
|
}
|
|
9367
|
-
const
|
|
9368
|
-
const
|
|
9369
|
-
|
|
9370
|
-
this.knownParameterValues[position] = UNKNOWN_EXPRESSION;
|
|
9371
|
-
} // else both are the same literal, no need to update
|
|
9372
|
-
}
|
|
9373
|
-
}
|
|
9374
|
-
forwardArgumentsForFunctionCalledOnce(newArguments) {
|
|
9375
|
-
for (let position = 0; position < this.params.length; position++) {
|
|
9376
|
-
const parameter = this.params[position];
|
|
9377
|
-
if (parameter instanceof Identifier) {
|
|
9378
|
-
const ParameterVariable = parameter.variable;
|
|
9379
|
-
const argument = newArguments[position + 1] ?? UNDEFINED_EXPRESSION;
|
|
9380
|
-
ParameterVariable?.setKnownValue(argument);
|
|
9381
|
-
}
|
|
9382
|
-
}
|
|
9383
|
-
}
|
|
9384
|
-
/**
|
|
9385
|
-
* each time tree-shake starts, this method should be called to reoptimize the parameters
|
|
9386
|
-
* a parameter's state will change at most twice:
|
|
9387
|
-
* `undefined` (no call is made) -> an expression -> `UnknownArgument`
|
|
9388
|
-
* we are sure it will converge, and can use state from last iteration
|
|
9389
|
-
*/
|
|
9390
|
-
applyFunctionParameterOptimization() {
|
|
9391
|
-
if (this.allArguments.length === 0) {
|
|
9392
|
-
return;
|
|
9393
|
-
}
|
|
9394
|
-
if (this.allArguments.length === 1) {
|
|
9395
|
-
// we are sure what knownParameterValues will be, so skip it and do setKnownValue
|
|
9396
|
-
this.forwardArgumentsForFunctionCalledOnce(this.allArguments[0]);
|
|
9397
|
-
return;
|
|
9398
|
-
}
|
|
9399
|
-
// reoptimize all arguments, that's why we save them
|
|
9400
|
-
for (const argumentsList of this.allArguments) {
|
|
9401
|
-
this.updateKnownParameterValues(argumentsList);
|
|
9402
|
-
}
|
|
9403
|
-
for (let position = 0; position < this.params.length; position++) {
|
|
9404
|
-
const parameter = this.params[position];
|
|
9405
|
-
// Parameters without default values
|
|
9406
|
-
if (parameter instanceof Identifier) {
|
|
9407
|
-
const parameterVariable = parameter.variable;
|
|
9408
|
-
// Only the RestElement may be undefined
|
|
9409
|
-
const knownParameterValue = this.knownParameterValues[position];
|
|
9410
|
-
parameterVariable?.setKnownValue(knownParameterValue);
|
|
9411
|
-
}
|
|
9375
|
+
const parameterVariable = parameter.variable;
|
|
9376
|
+
const argument = _arguments[position + 1] ?? UNDEFINED_EXPRESSION;
|
|
9377
|
+
parameterVariable.updateKnownValue(argument);
|
|
9412
9378
|
}
|
|
9413
9379
|
}
|
|
9414
|
-
|
|
9380
|
+
deoptimizeParameterVariableValues() {
|
|
9415
9381
|
for (const parameter of this.params) {
|
|
9416
9382
|
if (parameter instanceof Identifier) {
|
|
9417
9383
|
const parameterVariable = parameter.variable;
|
|
9418
|
-
parameterVariable
|
|
9384
|
+
parameterVariable.markReassigned();
|
|
9419
9385
|
}
|
|
9420
9386
|
}
|
|
9421
9387
|
}
|
|
@@ -9443,7 +9409,7 @@ class FunctionBase extends NodeBase {
|
|
|
9443
9409
|
this.addArgumentToBeDeoptimized(argument);
|
|
9444
9410
|
}
|
|
9445
9411
|
}
|
|
9446
|
-
this.
|
|
9412
|
+
this.updateParameterVariableValues(args);
|
|
9447
9413
|
}
|
|
9448
9414
|
else {
|
|
9449
9415
|
this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
@@ -9518,14 +9484,10 @@ class FunctionBase extends NodeBase {
|
|
|
9518
9484
|
return variable?.getOnlyFunctionCallUsed() ?? false;
|
|
9519
9485
|
}
|
|
9520
9486
|
include(context, includeChildrenRecursively) {
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
this.
|
|
9524
|
-
}
|
|
9525
|
-
else if (this.functionParametersOptimized) {
|
|
9526
|
-
this.deoptimizeFunctionParameters();
|
|
9487
|
+
if (!this.parameterVariableValuesDeoptimized && !this.onlyFunctionCallUsed()) {
|
|
9488
|
+
this.parameterVariableValuesDeoptimized = true;
|
|
9489
|
+
this.deoptimizeParameterVariableValues();
|
|
9527
9490
|
}
|
|
9528
|
-
this.functionParametersOptimized = shouldOptimizeFunctionParameters;
|
|
9529
9491
|
if (!this.deoptimized)
|
|
9530
9492
|
this.applyDeoptimizations();
|
|
9531
9493
|
this.included = true;
|
|
@@ -10280,7 +10242,7 @@ class MemberExpression extends NodeBase {
|
|
|
10280
10242
|
}
|
|
10281
10243
|
deoptimizeCache() {
|
|
10282
10244
|
const { expressionsToBeDeoptimized, object } = this;
|
|
10283
|
-
this.expressionsToBeDeoptimized =
|
|
10245
|
+
this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
|
|
10284
10246
|
this.propertyKey = UnknownKey;
|
|
10285
10247
|
object.deoptimizePath(UNKNOWN_PATH);
|
|
10286
10248
|
for (const expression of expressionsToBeDeoptimized) {
|
|
@@ -10431,6 +10393,7 @@ class MemberExpression extends NodeBase {
|
|
|
10431
10393
|
}
|
|
10432
10394
|
if (this.variable) {
|
|
10433
10395
|
this.variable.addUsedPlace(this);
|
|
10396
|
+
this.scope.context.requestTreeshakingPass();
|
|
10434
10397
|
}
|
|
10435
10398
|
}
|
|
10436
10399
|
applyAssignmentDeoptimization() {
|
|
@@ -10630,21 +10593,17 @@ class CallExpression extends CallExpressionBase {
|
|
|
10630
10593
|
};
|
|
10631
10594
|
}
|
|
10632
10595
|
hasEffects(context) {
|
|
10633
|
-
|
|
10634
|
-
|
|
10635
|
-
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
if (this.annotationPure) {
|
|
10639
|
-
return false;
|
|
10640
|
-
}
|
|
10641
|
-
return (this.callee.hasEffects(context) ||
|
|
10642
|
-
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
|
|
10596
|
+
if (!this.deoptimized)
|
|
10597
|
+
this.applyDeoptimizations();
|
|
10598
|
+
for (const argument of this.arguments) {
|
|
10599
|
+
if (argument.hasEffects(context))
|
|
10600
|
+
return true;
|
|
10643
10601
|
}
|
|
10644
|
-
|
|
10645
|
-
|
|
10646
|
-
this.applyDeoptimizations();
|
|
10602
|
+
if (this.annotationPure) {
|
|
10603
|
+
return false;
|
|
10647
10604
|
}
|
|
10605
|
+
return (this.callee.hasEffects(context) ||
|
|
10606
|
+
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
|
|
10648
10607
|
}
|
|
10649
10608
|
include(context, includeChildrenRecursively) {
|
|
10650
10609
|
if (!this.deoptimized)
|
|
@@ -11081,24 +11040,15 @@ class ConditionalExpression extends NodeBase {
|
|
|
11081
11040
|
this.alternate.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
11082
11041
|
}
|
|
11083
11042
|
deoptimizeCache() {
|
|
11084
|
-
if (this.usedBranch ||
|
|
11085
|
-
this.isBranchResolutionAnalysed ||
|
|
11086
|
-
this.expressionsToBeDeoptimized.length > 0) {
|
|
11087
|
-
// Request another pass because we need to ensure "include" runs again if it is rendered
|
|
11088
|
-
this.scope.context.requestTreeshakingPass();
|
|
11089
|
-
}
|
|
11090
|
-
const { expressionsToBeDeoptimized } = this;
|
|
11091
|
-
if (expressionsToBeDeoptimized.length > 0) {
|
|
11092
|
-
this.expressionsToBeDeoptimized = [];
|
|
11093
|
-
for (const expression of expressionsToBeDeoptimized) {
|
|
11094
|
-
expression.deoptimizeCache();
|
|
11095
|
-
}
|
|
11096
|
-
}
|
|
11097
|
-
this.isBranchResolutionAnalysed = false;
|
|
11098
11043
|
if (this.usedBranch !== null) {
|
|
11099
11044
|
const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent;
|
|
11100
11045
|
this.usedBranch = null;
|
|
11101
11046
|
unusedBranch.deoptimizePath(UNKNOWN_PATH);
|
|
11047
|
+
const { expressionsToBeDeoptimized } = this;
|
|
11048
|
+
this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
|
|
11049
|
+
for (const expression of expressionsToBeDeoptimized) {
|
|
11050
|
+
expression.deoptimizeCache();
|
|
11051
|
+
}
|
|
11102
11052
|
}
|
|
11103
11053
|
}
|
|
11104
11054
|
deoptimizePath(path) {
|
|
@@ -11112,10 +11062,10 @@ class ConditionalExpression extends NodeBase {
|
|
|
11112
11062
|
}
|
|
11113
11063
|
}
|
|
11114
11064
|
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
11115
|
-
this.expressionsToBeDeoptimized.push(origin);
|
|
11116
11065
|
const usedBranch = this.getUsedBranch();
|
|
11117
11066
|
if (!usedBranch)
|
|
11118
11067
|
return UnknownValue;
|
|
11068
|
+
this.expressionsToBeDeoptimized.push(origin);
|
|
11119
11069
|
return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
|
|
11120
11070
|
}
|
|
11121
11071
|
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|
|
@@ -11612,7 +11562,7 @@ class IfStatement extends NodeBase {
|
|
|
11612
11562
|
this.testValue = unset;
|
|
11613
11563
|
}
|
|
11614
11564
|
deoptimizeCache() {
|
|
11615
|
-
this.testValue =
|
|
11565
|
+
this.testValue = UnknownValue;
|
|
11616
11566
|
}
|
|
11617
11567
|
hasEffects(context) {
|
|
11618
11568
|
if (this.test.hasEffects(context)) {
|
|
@@ -12420,24 +12370,18 @@ class LogicalExpression extends NodeBase {
|
|
|
12420
12370
|
this.right.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
|
|
12421
12371
|
}
|
|
12422
12372
|
deoptimizeCache() {
|
|
12423
|
-
if (this.usedBranch ||
|
|
12424
|
-
this.isBranchResolutionAnalysed ||
|
|
12425
|
-
this.expressionsToBeDeoptimized.length > 0) {
|
|
12426
|
-
// Request another pass because we need to ensure "include" runs again if it is rendered
|
|
12427
|
-
this.scope.context.requestTreeshakingPass();
|
|
12428
|
-
}
|
|
12429
|
-
const { expressionsToBeDeoptimized } = this;
|
|
12430
|
-
if (expressionsToBeDeoptimized.length > 0) {
|
|
12431
|
-
this.expressionsToBeDeoptimized = [];
|
|
12432
|
-
for (const expression of expressionsToBeDeoptimized) {
|
|
12433
|
-
expression.deoptimizeCache();
|
|
12434
|
-
}
|
|
12435
|
-
}
|
|
12436
|
-
this.isBranchResolutionAnalysed = false;
|
|
12437
12373
|
if (this.usedBranch) {
|
|
12438
12374
|
const unusedBranch = this.usedBranch === this.left ? this.right : this.left;
|
|
12439
12375
|
this.usedBranch = null;
|
|
12440
12376
|
unusedBranch.deoptimizePath(UNKNOWN_PATH);
|
|
12377
|
+
const { scope: { context }, expressionsToBeDeoptimized } = this;
|
|
12378
|
+
this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
|
|
12379
|
+
for (const expression of expressionsToBeDeoptimized) {
|
|
12380
|
+
expression.deoptimizeCache();
|
|
12381
|
+
}
|
|
12382
|
+
// Request another pass because we need to ensure "include" runs again if
|
|
12383
|
+
// it is rendered
|
|
12384
|
+
context.requestTreeshakingPass();
|
|
12441
12385
|
}
|
|
12442
12386
|
}
|
|
12443
12387
|
deoptimizePath(path) {
|
|
@@ -12451,10 +12395,10 @@ class LogicalExpression extends NodeBase {
|
|
|
12451
12395
|
}
|
|
12452
12396
|
}
|
|
12453
12397
|
getLiteralValueAtPath(path, recursionTracker, origin) {
|
|
12454
|
-
this.expressionsToBeDeoptimized.push(origin);
|
|
12455
12398
|
const usedBranch = this.getUsedBranch();
|
|
12456
12399
|
if (!usedBranch)
|
|
12457
12400
|
return UnknownValue;
|
|
12401
|
+
this.expressionsToBeDeoptimized.push(origin);
|
|
12458
12402
|
return usedBranch.getLiteralValueAtPath(path, recursionTracker, origin);
|
|
12459
12403
|
}
|
|
12460
12404
|
getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
|