From 5e1cc31e317a45098c3c9ac951fa0da149b9804e Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 31 Oct 2024 12:11:55 -0700 Subject: [PATCH] fix: incremental Performance Degradation with session.customRequest("variables") Calls Fixes #2119 --- src/adapter/variableStore.ts | 66 ++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/src/adapter/variableStore.ts b/src/adapter/variableStore.ts index 9450bc93e..96a12dfd8 100644 --- a/src/adapter/variableStore.ts +++ b/src/adapter/variableStore.ts @@ -428,20 +428,8 @@ class VariableContext { } let variable: Variable | undefined; - if ( - p.name === '[[FunctionLocation]]' - && p.value - && (p.value.subtype as string) === 'internal#location' - ) { - variable = this.createVariable( - FunctionLocationVariable, - { - name: p.name, - presentationHint: { visibility: 'internal', attributes: ['readOnly'] }, - sortOrder: SortOrder.Internal, - }, - p.value, - ); + if (isFunctionLocation(p)) { + variable = this.createFunctionLocationVariable(p); } else if (p.value !== undefined) { variable = this.createVariableByType( { @@ -461,6 +449,18 @@ class VariableContext { return flatten(await Promise.all(properties)); } + public createFunctionLocationVariable(p: FunctionLocationDescriptor) { + return this.createVariable( + FunctionLocationVariable, + { + name: p.name, + presentationHint: { visibility: 'internal', attributes: ['readOnly'] }, + sortOrder: SortOrder.Internal, + }, + p.value, + ); + } + private async createPropertyVar( p: AnyPropertyDescriptor, owner: Cdp.Runtime.RemoteObject, @@ -971,16 +971,19 @@ class NodeVariable extends Variable { } class FunctionVariable extends ObjectVariable { - private readonly baseChildren = once(() => super.getChildren({ variablesReference: this.id })); - public override async toDap(previewContext: PreviewContextType): Promise { - const [dap, children] = await Promise.all([ + const [dap, props] = await Promise.all([ super.toDap(previewContext), - this.baseChildren(), + this.context.cdp.Runtime.getProperties({ + objectId: this.remoteObject.objectId!, + ownProperties: true, + nonIndexedPropertiesOnly: true, + }), ]); - if (children.some(c => c instanceof FunctionLocationVariable)) { - dap.valueLocationReference = this.id; + const location = props?.internalProperties?.find(isFunctionLocation); + if (location) { + dap.valueLocationReference = this.context.createFunctionLocationVariable(location).id; } return dap; @@ -1580,15 +1583,8 @@ export class VariableStore { } public async getLocations(variablesReference: number): Promise { - const container = this.vars.get(variablesReference); - if (!container) { - throw errors.locationNotFound(); - } - - // note: is actually free because the container will have cached its children - const children = await container.getChildren({ variablesReference }); - const locationVar = children.find(isInstanceOf(FunctionLocationVariable)); - if (!locationVar) { + const locationVar = this.vars.get(variablesReference); + if (!locationVar || !(locationVar instanceof FunctionLocationVariable)) { throw errors.locationNotFound(); } @@ -1630,3 +1626,15 @@ function errorFromException(details: Cdp.Runtime.ExceptionDetails): Dap.Error { || details.text; return errors.createUserError(message); } + +type FunctionLocationDescriptor = Cdp.Runtime.InternalPropertyDescriptor & { + value: Cdp.Debugger.Location; +}; + +function isFunctionLocation( + p: Cdp.Runtime.InternalPropertyDescriptor, +): p is FunctionLocationDescriptor { + return p.name === '[[FunctionLocation]]' + && !!p.value + && (p.value.subtype as string) === 'internal#location'; +}