@@ -21,6 +21,7 @@ import { StackFrame, StackTrace } from './stackTrace';
21
21
import { getSourceSuffix , RemoteException } from './templates' ;
22
22
import { getArrayProperties } from './templates/getArrayProperties' ;
23
23
import { getArraySlots } from './templates/getArraySlots' ;
24
+ import { getStringyProps , getToStringIfCustom } from './templates/getStringyProps' ;
24
25
import { invokeGetter } from './templates/invokeGetter' ;
25
26
import { readMemory } from './templates/readMemory' ;
26
27
import { writeMemory } from './templates/writeMemory' ;
@@ -220,13 +221,17 @@ class VariableContext {
220
221
return v ;
221
222
}
222
223
223
- public createVariableByType ( ctx : IContextInit , object : Cdp . Runtime . RemoteObject ) {
224
+ public createVariableByType (
225
+ ctx : IContextInit ,
226
+ object : Cdp . Runtime . RemoteObject ,
227
+ customStringRepr ?: string ,
228
+ ) {
224
229
if ( objectPreview . isArray ( object ) ) {
225
230
return this . createVariable ( ArrayVariable , ctx , object ) ;
226
231
}
227
232
228
233
if ( object . objectId && ! objectPreview . subtypesWithoutPreview . has ( object . subtype ) ) {
229
- return this . createVariable ( ObjectVariable , ctx , object ) ;
234
+ return this . createVariable ( ObjectVariable , ctx , object , customStringRepr ) ;
230
235
}
231
236
232
237
return this . createVariable ( Variable , ctx , object ) ;
@@ -265,7 +270,7 @@ class VariableContext {
265
270
return [ ] ;
266
271
}
267
272
268
- const [ accessorsProperties , ownProperties ] = await Promise . all ( [
273
+ const [ accessorsProperties , ownProperties , stringyProps ] = await Promise . all ( [
269
274
this . cdp . Runtime . getProperties ( {
270
275
objectId : object . objectId ,
271
276
accessorPropertiesOnly : true ,
@@ -277,6 +282,13 @@ class VariableContext {
277
282
ownProperties : true ,
278
283
generatePreview : true ,
279
284
} ) ,
285
+ getStringyProps ( {
286
+ cdp : this . cdp ,
287
+ args : [ 64 ] ,
288
+ objectId : object . objectId ,
289
+ throwOnSideEffect : true ,
290
+ returnByValue : true ,
291
+ } ) . catch ( ( ) => ( { value : { } as Record < string , string > } ) ) ,
280
292
] ) ;
281
293
if ( ! accessorsProperties || ! ownProperties ) return [ ] ;
282
294
@@ -311,7 +323,13 @@ class VariableContext {
311
323
// Push own properties & accessors and symbols
312
324
for ( const propertiesCollection of [ propertiesMap . values ( ) , propertySymbols . values ( ) ] ) {
313
325
for ( const p of propertiesCollection ) {
314
- properties . push ( this . createPropertyVar ( p , object ) ) ;
326
+ properties . push (
327
+ this . createPropertyVar (
328
+ p ,
329
+ object ,
330
+ stringyProps . hasOwnProperty ( p . name ) ? stringyProps . value [ p . name ] : undefined ,
331
+ ) ,
332
+ ) ;
315
333
}
316
334
}
317
335
@@ -393,6 +411,7 @@ class VariableContext {
393
411
private async createPropertyVar (
394
412
p : AnyPropertyDescriptor ,
395
413
owner : Cdp . Runtime . RemoteObject ,
414
+ customStringRepr : string | undefined ,
396
415
) : Promise < Variable [ ] > {
397
416
const result : Variable [ ] = [ ] ;
398
417
const ctx : Required < IContextInit > = {
@@ -421,7 +440,7 @@ class VariableContext {
421
440
422
441
// If the value is simply present, add that
423
442
if ( 'value' in p && p . value ) {
424
- result . push ( this . createVariableByType ( ctx , p . value ) ) ;
443
+ result . push ( this . createVariableByType ( ctx , p . value , customStringRepr ) ) ;
425
444
}
426
445
427
446
// if it's a getter, auto expand as requested
@@ -680,26 +699,67 @@ class ErrorVariable extends Variable {
680
699
}
681
700
}
682
701
702
+ const NoCustomStringRepr = Symbol ( 'NoStringRepr' ) ;
703
+
683
704
class ObjectVariable extends Variable implements IMemoryReadable {
705
+ constructor (
706
+ context : VariableContext ,
707
+ remoteObject : Cdp . Runtime . RemoteObject ,
708
+ private customStringRepr ?: string | typeof NoCustomStringRepr ,
709
+ ) {
710
+ super ( context , remoteObject ) ;
711
+ }
712
+
684
713
public override async toDap (
685
714
previewContext : PreviewContextType ,
686
715
valueFormat ?: Dap . ValueFormat ,
687
716
) : Promise < Dap . Variable > {
717
+ const [ parentDap , value ] = await Promise . all ( [
718
+ await super . toDap ( previewContext , valueFormat ) ,
719
+ await this . getValueRepresentation ( previewContext ) ,
720
+ ] ) ;
721
+
688
722
return {
689
- ...( await super . toDap ( previewContext , valueFormat ) ) ,
723
+ ...parentDap ,
690
724
type : this . remoteObject . className || this . remoteObject . subtype || this . remoteObject . type ,
691
725
variablesReference : this . id ,
692
726
memoryReference : memoryReadableTypes . has ( this . remoteObject . subtype )
693
727
? String ( this . id )
694
728
: undefined ,
695
- value : await this . context . getCustomObjectDescription (
696
- this . context . name ,
697
- this . remoteObject ,
698
- previewContext ,
699
- ) ,
729
+ value,
700
730
} ;
701
731
}
702
732
733
+ private async getValueRepresentation ( previewContext : PreviewContextType ) {
734
+ if ( typeof this . customStringRepr === 'string' ) {
735
+ return this . customStringRepr ;
736
+ }
737
+
738
+ // for the first level of evaluations, toString it on-demand
739
+ if ( ! this . context . parent && this . customStringRepr !== NoCustomStringRepr ) {
740
+ try {
741
+ const result = await getToStringIfCustom ( {
742
+ cdp : this . context . cdp ,
743
+ args : [ 64 ] ,
744
+ objectId : this . remoteObject . objectId ,
745
+ returnByValue : true ,
746
+ } ) ;
747
+ if ( result . value ) {
748
+ return ( this . customStringRepr = result . value ) ;
749
+ }
750
+ } catch ( e ) {
751
+ this . customStringRepr = NoCustomStringRepr ;
752
+ // ignored
753
+ }
754
+ }
755
+
756
+ return await this . context . getCustomObjectDescription (
757
+ this . context . name ,
758
+ this . remoteObject ,
759
+ previewContext ,
760
+ ) ;
761
+ }
762
+
703
763
/** @inheritdoc */
704
764
public async readMemory ( offset : number , count : number ) : Promise < Buffer | undefined > {
705
765
const result = await readMemory ( {
@@ -733,7 +793,7 @@ class ArrayVariable extends ObjectVariable {
733
793
private length = 0 ;
734
794
735
795
constructor ( context : VariableContext , remoteObject : Cdp . Runtime . RemoteObject ) {
736
- super ( context , remoteObject ) ;
796
+ super ( context , remoteObject , NoCustomStringRepr ) ;
737
797
const match = String ( remoteObject . description ) . match ( / \( ( [ 0 - 9 ] + ) \) / ) ;
738
798
this . length = match ? + match [ 1 ] : 0 ;
739
799
}
0 commit comments