diff --git a/src/ast/nodes/shared/ArrayPrototype.ts b/src/ast/nodes/shared/ArrayPrototype.ts index 0b3c0e728d2..898ac8683b3 100644 --- a/src/ast/nodes/shared/ArrayPrototype.ts +++ b/src/ast/nodes/shared/ArrayPrototype.ts @@ -148,5 +148,6 @@ export const ARRAY_PROTOTYPE = new ObjectEntity( unshift: METHOD_MUTATES_SELF_RETURNS_NUMBER, values: METHOD_DEOPTS_SELF_RETURNS_UNKNOWN } as unknown as PropertyMap, - OBJECT_PROTOTYPE + OBJECT_PROTOTYPE, + true ); diff --git a/src/ast/nodes/shared/ObjectEntity.ts b/src/ast/nodes/shared/ObjectEntity.ts index d99c3730bc6..eef121c9b01 100644 --- a/src/ast/nodes/shared/ObjectEntity.ts +++ b/src/ast/nodes/shared/ObjectEntity.ts @@ -50,7 +50,8 @@ export class ObjectEntity extends ExpressionEntity { // and we assume there are no setters or getters constructor( properties: ObjectProperty[] | PropertyMap, - private prototypeExpression: ExpressionEntity | null + private prototypeExpression: ExpressionEntity | null, + private immutable = false ) { super(); if (Array.isArray(properties)) { @@ -96,7 +97,7 @@ export class ObjectEntity extends ExpressionEntity { } deoptimizePath(path: ObjectPath): void { - if (this.hasUnknownDeoptimizedProperty) return; + if (this.hasUnknownDeoptimizedProperty || this.immutable) return; const key = path[0]; if (path.length === 1) { if (typeof key !== 'string') { @@ -171,7 +172,9 @@ export class ObjectEntity extends ExpressionEntity { property.deoptimizeThisOnEventAtPath(event, subPath, thisParameter, recursionTracker); } } - this.thisParametersToBeDeoptimized.add(thisParameter); + if (!this.immutable) { + this.thisParametersToBeDeoptimized.add(thisParameter); + } return; } for (const property of relevantUnmatchableProperties) { @@ -194,7 +197,9 @@ export class ObjectEntity extends ExpressionEntity { property.deoptimizeThisOnEventAtPath(event, subPath, thisParameter, recursionTracker); } } - this.thisParametersToBeDeoptimized.add(thisParameter); + if (!this.immutable) { + this.thisParametersToBeDeoptimized.add(thisParameter); + } this.prototypeExpression?.deoptimizeThisOnEventAtPath( event, path, @@ -467,7 +472,7 @@ export class ObjectEntity extends ExpressionEntity { return UNKNOWN_EXPRESSION; } const expression = this.getMemberExpression(key); - if (expression !== UNKNOWN_EXPRESSION) { + if (!(expression === UNKNOWN_EXPRESSION || this.immutable)) { const expressionsToBeDeoptimized = (this.expressionsToBeDeoptimizedByKey[key] = this.expressionsToBeDeoptimizedByKey[key] || []); expressionsToBeDeoptimized.push(origin); diff --git a/src/ast/nodes/shared/ObjectPrototype.ts b/src/ast/nodes/shared/ObjectPrototype.ts index 0faa5b81a67..96aa39682a3 100644 --- a/src/ast/nodes/shared/ObjectPrototype.ts +++ b/src/ast/nodes/shared/ObjectPrototype.ts @@ -15,5 +15,6 @@ export const OBJECT_PROTOTYPE = new ObjectEntity( toString: METHOD_RETURNS_STRING, valueOf: METHOD_RETURNS_UNKNOWN } as unknown as PropertyMap, - null + null, + true );