From df42bb5093ee64f433e38ef08c03039ed06746a1 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Fri, 13 May 2022 17:21:55 +0200 Subject: [PATCH] Ensure properties are deoptimized by default --- src/ast/nodes/ObjectExpression.ts | 1 - src/ast/nodes/shared/Node.ts | 21 +++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/ast/nodes/ObjectExpression.ts b/src/ast/nodes/ObjectExpression.ts index 39059ffff5c..77629181976 100644 --- a/src/ast/nodes/ObjectExpression.ts +++ b/src/ast/nodes/ObjectExpression.ts @@ -26,7 +26,6 @@ import { NodeBase } from './shared/Node'; import { ObjectEntity, type ObjectProperty } from './shared/ObjectEntity'; import { OBJECT_PROTOTYPE } from './shared/ObjectPrototype'; -// TODO Lukas ensure deoptimizations always happen twice in hasEffects and include export default class ObjectExpression extends NodeBase implements DeoptimizableEntity { declare properties: readonly (Property | SpreadElement)[]; declare type: NodeType.tObjectExpression; diff --git a/src/ast/nodes/shared/Node.ts b/src/ast/nodes/shared/Node.ts index cc65262dbcc..9ed06b9b1b7 100644 --- a/src/ast/nodes/shared/Node.ts +++ b/src/ast/nodes/shared/Node.ts @@ -12,6 +12,7 @@ import { } from '../../ExecutionContext'; import { getAndCreateKeys, keys } from '../../keys'; import type ChildScope from '../../scopes/ChildScope'; +import { UNKNOWN_PATH } from '../../utils/PathTracker'; import type Variable from '../../variables/Variable'; import * as NodeType from '../NodeType'; import { ExpressionEntity, InclusionOptions } from './Expression'; @@ -23,7 +24,6 @@ export interface GenericEsTreeNode extends acorn.Node { export const INCLUDE_PARAMETERS = 'variables' as const; export type IncludeChildren = boolean | typeof INCLUDE_PARAMETERS; -// TODO Lukas consider deoptimizing all properties by default unless explicitly overridden export interface Node extends Entity { annotations?: acorn.Comment[]; context: AstContext; @@ -240,7 +240,24 @@ export class NodeBase extends ExpressionEntity implements ExpressionNode { return this.included || (!context.brokenFlow && this.hasEffects(createHasEffectsContext())); } - protected applyDeoptimizations(): void {} + /** + * Just deoptimize everything by default so that when e.g. we do not track + * something properly, it is deoptimized. + * @protected + */ + protected applyDeoptimizations(): void { + for (const key of this.keys) { + const value = (this as GenericEsTreeNode)[key]; + if (value === null) continue; + if (Array.isArray(value)) { + for (const child of value) { + child?.deoptimizePath(UNKNOWN_PATH); + } + } else { + value.deoptimizePath(UNKNOWN_PATH); + } + } + } } export { NodeBase as StatementBase };