Condividi tramite


Oggetti debugger nativi nelle estensioni JavaScript - Dettagli dell'oggetto debugger

Questo argomento descrive altri dettagli sull'uso degli oggetti debugger nativi nelle estensioni JavaScript.

Gli oggetti debugger nativi rappresentano vari costrutti e comportamenti dell'ambiente debugger. Gli oggetti possono essere passati a estensioni JavaScript (o acquisite in) per modificare lo stato del debugger.

Per informazioni sulle estensioni JavaScript dell'oggetto Debugger, vedere Oggetti debugger nativi in Estensioni JavaScript.

Per informazioni generali sull'uso di JavaScript, vedere Scripting del debugger JavaScript.

Ad esempio, script e estensioni JavaScript, il team del debugger ospita un repository GitHub all'indirizzo https://github.com/Microsoft/WinDbg-Samples.

Oggetti debugger nelle estensioni JavaScript

Passaggio di oggetti nativi

Gli oggetti debugger possono essere passati o acquisiti nelle estensioni JavaScript in diversi modi.

  • Possono essere passati a funzioni o metodi JavaScript
  • Possono essere l'oggetto istanza di un prototipo JavaScript (ad esempio un visualizzatore)
  • Possono essere restituiti dai metodi host progettati per creare oggetti debugger nativi
  • Possono essere restituiti dai metodi host progettati per creare oggetti nativi del debugger

Gli oggetti debugger passati a un'estensione JavaScript hanno un set di funzionalità descritte in questa sezione.

  • Accesso alle proprietà
  • Nomi proiettati
  • Tipi speciali relativi agli oggetti debugger nativi
  • Attributi aggiuntivi

Accesso alle proprietà

Sebbene siano presenti alcune proprietà sugli oggetti che vengono inseriti dal provider JavaScript stesso, la maggior parte delle proprietà in un oggetto nativo che immette JavaScript vengono fornite dal modello di dati. Ciò significa che per un accesso a una proprietà --- object.propertyName o object[propertyName], si verificherà quanto segue.

  • Se propertyName è il nome di una proprietà proiettata nell'oggetto dal provider JavaScript stesso, verrà risolto in questo primo modo; Altrimenti
  • Se propertyName è il nome di una chiave proiettata nell'oggetto dal modello di dati (un altro visualizzatore), verrà risolto al secondo nome; Altrimenti
  • Se propertyName è il nome di un campo dell'oggetto nativo, verrà risolto in questo nome terzo; Altrimenti
  • Se l'oggetto è un puntatore, il puntatore verrà dereferenziato e il ciclo precedente continuerà (una proprietà proiettata dell'oggetto dereference seguito da una chiave seguita da un campo nativo)

Il normale mezzo di accesso alla proprietà in JavaScript -- object.propertyName e object[propertyName] -- accederà ai campi nativi sottostanti di un oggetto, in modo che il comando 'dx' si trova all'interno del debugger.

Nomi proiettati

Le proprietà seguenti (e metodi) vengono proiettate in oggetti nativi che entrano in JavaScript.

Metodo Firma Descrizione
hostContext Proprietà Restituisce un oggetto che rappresenta il contesto all'interno dell'oggetto (lo spazio degli indirizzi, la destinazione di debug e così via...)
targetLocation Proprietà Restituisce un oggetto che è un'astrazione di dove l'oggetto si trova all'interno di uno spazio indirizzi (indirizzo virtuale, registro, registro secondario e così via...)
targetSize Proprietà Restituisce le dimensioni dell'oggetto (in modo efficace: sizeof(<TYPE OF OBJECT>)
addParentModel .addParentModel(object) Aggiunge un nuovo modello padre (simile a un prototipo JavaScript ma sul lato modello di dati) all'oggetto
removeParentModel .removeParentModel(object) Rimuove un determinato modello padre dall'oggetto
runtimeTypedObject Proprietà Esegue l'analisi sull'oggetto e tenta di convertirla nel tipo runtime (la maggior parte derivata)
targetType Proprietà Le estensioni JavaScript hanno accesso diretto al sistema di tipi del linguaggio sottostante. Questo accesso viene espresso tramite la nozione di oggetti di tipo. Per altre informazioni, vedere Oggetti debugger nativi nelle estensioni JavaScript - Oggetti di tipo

Se l'oggetto è un puntatore, le proprietà e i metodi seguenti vengono proiettati sul puntatore che immette JavaScript:

Nome proprietà Firma Descrizione
add .add(value) Esegue l'aggiunta matematica del puntatore tra il puntatore e il valore specificato
address Proprietà Restituisce l'indirizzo del puntatore come oggetto ordinale a 64 bit (tipo di libreria)
Dereferenziare .dereference() Dereference il puntatore e restituisce l'oggetto sottostante
Isnull Proprietà Restituisce se il valore del puntatore è nullptr (0)

Tipi speciali relativi agli oggetti debugger nativi

Oggetti location

L'oggetto location restituito dalla proprietà targetLocation di un oggetto nativo contiene le proprietà e i metodi seguenti.

Nome proprietà Firma Descrizione
add .add(value) Aggiunge un offset di byte assoluto alla posizione.
sottrarre .sottrazione(valore) Sottrae un offset di byte assoluto dalla posizione.

Attributi aggiuntivi

Iterabilità

Qualsiasi oggetto compreso come iterabile dal modello di dati (è una matrice nativa o ha un visualizzatore (NatVis o altrimenti) che lo rende iterabile, avrà una funzione iteratore (indicizzata tramite il simbolo standard ES6) posizionata su di essa. Ciò significa che è possibile eseguire l'iterazione di un oggetto nativo in JavaScript come indicato di seguito.

function iterateNative(nativeObject)
{
    for (var val of nativeObject)
    {
        // 
        // val will contain each element iterated from the native object.  This would be each element of an array,
        // each element of an STL structure which is made iterable through NatVis, each element of a data structure
        // which has a JavaScript iterator accessible via [Symbol.iterator], or each element of something
        // which is made iterable via support of IIterableConcept in C/C++.
        //
    }
}

Indicizzazione

Gli oggetti che sono compresi come indicizzati in una dimensione tramite ordinali (ad esempio: matrici native) saranno indicizzati in JavaScript tramite l'operatore di accesso alle proprietà standard -- object[index]. Se un oggetto è indicizzato per nome o è indicizzato in più dimensioni, i metodi getValueAt e setValueAt verranno proiettati nell'oggetto in modo che il codice JavaScript possa utilizzare l'indicizzatore.

function indexNative(nativeArray)
{
    var first = nativeArray[0];
}

Conversione stringhe

Qualsiasi oggetto nativo che ha una conversione stringa di visualizzazione tramite il supporto di IStringDisplayableConcept o un elemento NatVis DisplayString avrà tale conversione stringa accessibile tramite il metodo JavaScript standard toString.

function stringifyNative(nativeObject)
{
    var myString = nativeObject.toString();
}

Creazione di oggetti debugger nativi

Come accennato, uno script JavaScript può accedere agli oggetti nativi passandoli in JavaScript in uno dei diversi modi oppure possono crearli tramite chiamate alla libreria host. Usare le funzioni seguenti per creare oggetti debugger nativi.

Metodo Firma Descrizione

host.getModuleSymbol

getModuleSymbol(moduleName, symbolName, [contextInheritor])

getModuleSymbol(moduleName, symbolName, [typeName], [contextInheritor])

Restituisce un oggetto per un simbolo globale all'interno di un modulo specifico. Il nome del modulo e il nome del simbolo sono stringhe.

Se viene fornito l'argomento contextInheritor facoltativo, il modulo e il simbolo verranno cercati all'interno dello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene specificato, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script di test uno-off deve sempre fornire un contesto esplicito.

Se viene fornito l'argomento typeName facoltativo, si presuppone che il simbolo sia del tipo passato e il tipo indicato nei simboli verrà ignorato. Si noti che qualsiasi chiamante che prevede di operare sui simboli pubblici per un modulo deve sempre fornire un nome di tipo esplicito.

host.getModuleContainSymbol

getModuleContainSymbol(location, [contextInheritor])

Restituisce il simbolo (ad esempio, funzione o dati) che contiene l'indirizzo specificato. Si noti che questa operazione funzionerà solo se sono presenti simboli privati per il modulo contenente l'indirizzo specificato.

Se viene fornito l'argomento contextInheritor facoltativo, il modulo e il simbolo verranno cercati all'interno dello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene specificato, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script di test uno-off deve sempre fornire un contesto esplicito.

host.createPointerObject

createPointerObject(address, moduleName, typeName, [contextInheritor])

Crea un oggetto puntatore in corrispondenza dell'indirizzo o della posizione specificati. Il nome del modulo e il nome del tipo sono stringhe.

Se viene fornito l'argomento contextInheritor facoltativo, il modulo e il simbolo verranno cercati all'interno dello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene specificato, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script di test uno-off deve sempre fornire un contesto esplicito.

host.createTypedObject

createTypedObject(location, moduleName, typeName, [contextInheritor])

Crea un oggetto che rappresenta un oggetto tipizzato nativo all'interno dello spazio indirizzi di una destinazione di debug nella posizione specificata. Il nome del modulo e il nome del tipo sono stringhe.

Se viene fornito l'argomento contextInheritor facoltativo, il modulo e il simbolo verranno cercati all'interno dello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene specificato, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script di test uno-off deve sempre fornire un contesto esplicito.

API host per le estensioni JavaScript

Il provider JavaScript inserisce un oggetto denominato host nello spazio dei nomi globale di ogni script caricato. Questo oggetto fornisce l'accesso alle funzionalità critiche per lo script e l'accesso allo spazio dei nomi del debugger. Viene configurata in due fasi.

  • Fase 1: prima dell'esecuzione di qualsiasi script, l'oggetto host contiene solo il set minimo di funzionalità necessario per inizializzare lo script e registrarne i punti di estendibilità (sia come producer che consumer). Il codice radice e di inizializzazione non è progettato per modificare lo stato di una destinazione di debug o eseguire operazioni complesse e, di conseguenza, l'host non viene popolato completamente finché non viene restituito il metodo initializeScript.

  • Fase 2: dopo la restituzione di initializeScript, l'oggetto host viene popolato con tutto il necessario per modificare lo stato delle destinazioni di debug.

Livello oggetto host

Alcune funzionalità chiave si trovano direttamente nell'oggetto host. La parte restante è sub-namespaced. Gli spazi dei nomi includono quanto segue.

Spazio dei nomi Descrizione
diagnostica Funzionalità per facilitare la diagnosi e il debug del codice script
memoria Funzionalità per abilitare la lettura e la scrittura della memoria all'interno di una destinazione di debug

Livello radice

Direttamente all'interno dell'oggetto host, sono disponibili le proprietà, i metodi e i costruttori seguenti.

Nome Firma Fase presente Descrizione
createPointerObject

createPointerObject(address, moduleName, typeName, [contextInheritor])

2 Crea un oggetto puntatore in corrispondenza dell'indirizzo o della posizione specificati. Il nome del modulo e il nome del tipo sono stringhe. L'argomento contextInheritor facoltativo funziona come con getModuleSymbol.
createTypedObject

createTypedObject(location, moduleName, typeName, [contextInheritor])

2 Crea un oggetto che rappresenta un oggetto tipizzato nativo all'interno dello spazio indirizzi di una destinazione di debug nella posizione specificata. Il nome del modulo e il nome del tipo sono stringhe. L'argomento contextInheritor facoltativo funziona come con getModuleSymbol.
currentProcess

Proprietà

2 Restituisce l'oggetto che rappresenta il processo corrente del debugger
currentSession

Proprietà

2 Restituisce l'oggetto che rappresenta la sessione corrente del debugger (destinazione, dump e così via) di cui viene eseguito il debug
currentThread

Proprietà

2 Restituisce l'oggetto che rappresenta il thread corrente del debugger
Evaluateexpression

evaluateExpression(expression, [contextInheritor])

2 Viene chiamato nell'host di debug per valutare un'espressione usando solo il linguaggio della destinazione di debug. Se viene fornito l'argomento contextInheritor facoltativo, l'espressione verrà valutata nel contesto (ad esempio, spazio indirizzi e destinazione di debug) dell'argomento; in caso contrario, verrà valutato nel contesto corrente del debugger
evaluateExpressionInContext

evaluateExpressionInContext(context, expression)

2 Viene chiamato nell'host di debug per valutare un'espressione usando solo il linguaggio della destinazione di debug. L'argomento di contesto indica il puntatore implicito da utilizzare per la valutazione. L'espressione verrà valutata nel contesto (ad esempio, spazio indirizzi e destinazione di debug) indicata dall'argomento di contesto .
getModuleSymbol

getModuleSymbol(moduleName, symbolName, [contextInheritor])

2 Restituisce un oggetto per un simbolo globale all'interno di un modulo specifico. Il nome del modulo e il nome del simbolo sono stringhe. Se viene fornito l'argomento contextInheritor facoltativo, il modulo e il simbolo verranno cercati all'interno dello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene specificato, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script uno-off deve sempre fornire un contesto esplicito
getNamedModel

getNamedModel(modelName)

2 Restituisce il modello di dati registrato in base a un nome specificato. Si noti che è perfettamente legale chiamare questo contro un nome che non è ancora registrato. In questo modo verrà creato uno stub per tale nome e manipolazione dello stub verrà eseguito all'oggetto effettivo al momento della registrazione
indexedValue

new indexedValue(value, indici)

2 Costruttore per un oggetto che può essere restituito da un iteratore JavaScript per assegnare un set predefinito di indici al valore iterato. Il set di indici deve essere espresso come matrice JavaScript.
Int64

new Int64(value, [highValue])

1 In questo modo viene costruito un tipo di libreria Int64. La versione dell'argomento singolo accetta qualsiasi valore che può essere inserito in un oggetto Int64 (senza conversione) e inserirlo in tale valore. Se viene fornito un secondo argomento facoltativo, viene inserita una conversione del primo argomento nei 32 bit inferiori e viene inserita una conversione del secondo argomento nella parte superiore di 32 bit.
namedModelParent

new namedModelParent(object, name)

1 Un costruttore per un oggetto da inserire nella matrice restituita dall'inizializzazioneScript, questo rappresenta l'uso di un prototipo JavaScript o di una classe ES6 come estensione padre del modello di dati di un modello di dati con il nome specificato
namedModelRegistration

new namedModelRegistration(object, name)

1 Un costruttore per un oggetto da inserire nella matrice restituita dall'inizializzazioneScript, rappresenta la registrazione di un prototipo JavaScript o di una classe ES6 come modello di dati tramite un nome noto in modo che altre estensioni possano trovare ed estendere
namespace

Proprietà

2 Consente l'accesso diretto allo spazio dei nomi radice del debugger. Ad esempio, accedere all'elenco di processi della prima destinazione di debug tramite host.namespace.Debugger.Sessions.First(). Processi che usano questa proprietà
registerNamedModel

registerNamedModel(object, modelName)

2 In questo modo viene registrato un prototipo JavaScript o una classe ES6 come modello di dati con il nome specificato. Tale registrazione consente di individuare e estendere il prototipo o la classe da altri script o altre estensioni del debugger. Si noti che uno script deve preferire restituire un oggetto namedModelRegistration dal relativo metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario avere un metodo initializeScript per pulire.
registerExtensionForTypeSignature

registerExtensionForTypeSignature(object, typeSignature)

2 In questo modo viene registrato un prototipo JavaScript o una classe ES6 come modello di dati di estensione per un tipo nativo, come indicato dalla firma del tipo fornito. Si noti che uno script deve preferire restituire un oggetto typeSignatureExtension dal relativo metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario avere un metodo initializeScript per pulire.
registerPrototypeForTypeSignature

registerPrototypeForTypeSignature(object, typeSignature)

2 Questo registra un prototipo JavaScript o una classe ES6 come modello di dati canonico (ad esempio: visualizzatore) per un tipo nativo come specificato dalla firma del tipo fornito. Si noti che uno script deve preferire restituire un oggetto typeSignatureRegistration dal relativo metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario avere un metodo uninitializeScriptper pulire.
parseInt64

parseInt64(string, [radix])

1 Questo metodo agisce in modo analogo al metodo di analisi JavaScript standard, ad eccezione del fatto che restituisce invece un tipo di libreria Int64. Se viene fornito un radix, l'analisi si verificherà in base 2, 8, 10 o 16, come indicato.
typeSignatureExtension

nuovo tipoSignatureExtension(object, typeSignature, [moduleName], [minVersion], [maxVersion])

1 Un costruttore per un oggetto da inserire nella matrice restituita dall'inizializzazioneScript, rappresenta un'estensione di un tipo nativo descritto tramite una firma di tipo da un prototipo JavaScript o da una classe ES6. Tale registrazione "aggiunge campi" alla visualizzazione del debugger di qualsiasi tipo che corrisponde alla firma anziché prenderla interamente. Un nome e una versione di modulo facoltativi possono limitare la registrazione. Le versioni vengono specificate come stringhe di stile "1.2.3.4".
typeSignatureRegistration

nuovo tipoSignatureRegistration(object, typeSignature, [moduleName], [minVersion], [maxVersion])

1 Un costruttore per un oggetto da inserire nella matrice restituita dall'inizializzazioneScript, rappresenta una registrazione canonica di un prototipo JavaScript o una classe ES6 su una firma del tipo nativo. Tale registrazione "accetta" la visualizzazione del debugger di qualsiasi tipo che corrisponde alla firma anziché semplicemente all'estensione. Un nome e una versione di modulo facoltativi possono limitare la registrazione. Le versioni vengono specificate come stringhe di stile "1.2.3.4".
unregisterNamedModel

unregisterNamedModel(modelName)

2 Questa operazione annulla la registrazione di un modello di dati dalla ricerca in base al nome specificato annullando l'operazione eseguita da registerNamedModel
unregisterExtensionForTypeSignature

unregisterExtensionForTypeSignature(object, typeSignature, [moduleName], [minVersion], [maxVersion])

2 In questo modo viene annullata la registrazione di un prototipo JavaScript o di una classe ES6 da un modello di dati di estensione per un tipo nativo, come indicato dalla firma del tipo fornito. È l'annullamento logico di registerExtensionForTypeSignature. Si noti che uno script deve preferire restituire un oggetto typeSignatureExtension dal relativo metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario avere un metodo initializeScript per pulire. Un nome e una versione di modulo facoltativi possono limitare la registrazione. Le versioni vengono specificate come stringhe di stile "1.2.3.4".
unregisterPrototypeForTypeSignature

unregisterPrototypeForTypeSignature(object, typeSignature, [moduleName], [minVersion], [maxVersion])

2 In questo modo viene annullata la registrazione di un prototipo JavaScript o di una classe ES6 dal modello di dati canonico (ad esempio: visualizzatore) per un tipo nativo, come indicato dalla firma del tipo specificato. È l'annullamento logico di registerPrototypeForTypeSignature. Si noti che uno script deve preferire restituire un oggetto typeSignatureRegistration dal relativo metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario avere un metodo uninitializeScript per pulire. Un nome e una versione di modulo facoltativi possono limitare la registrazione. Le versioni vengono specificate come stringhe di stile "1.2.3.4".

Funzionalità di diagnostica

Lo spazio dei nomi secondario di diagnostica dell'oggetto host contiene quanto segue.

Nome Firma Fase presente Descrizione
debugLog debugLog(object...) 1 In questo modo viene fornito il debug dello stile printf in un'estensione di script. Attualmente, l'output da debugLog viene instradato alla console di output del debugger. In un secondo momento, ci sono piani per offrire flessibilità sul routing di questo output. NOTA: non deve essere usato come mezzo per stampare l'output utente nella console. Potrebbe non essere instradato lì in futuro.

Funzionalità di memoria

Lo spazio dei nomi secondario di memoria dell'oggetto host contiene quanto segue.

Nome Firma Fase presente Descrizione
readMemoryValues

readMemoryValues(location, numElements, [elementSize], [isSigned], [contextInheritor])

2 Questa operazione legge una matrice non elaborata di valori dallo spazio indirizzi della destinazione di debug e inserisce una matrice tipizzata nella parte superiore della visualizzazione di questa memoria. Il percorso fornito può essere un indirizzo (un valore a 64 bit), un oggetto location o un puntatore nativo. Le dimensioni della matrice sono indicate dall'argomento numElements . Le dimensioni (e il tipo) di ogni elemento della matrice vengono date dall'elemento facoltativoSize e dagli argomenti isSigned . Se non vengono forniti argomenti di questo tipo, il valore predefinito è byte (byte senza segno /1 byte). Se viene fornito l'argomento contextInheritor facoltativo, la memoria verrà letto nel contesto (ad esempio: spazio indirizzi e destinazione di debug) indicato dall'argomento; in caso contrario, verrà letto dal contesto corrente del debugger. Si noti che l'uso di questo metodo su valori a 8, 16 e a 32 bit genera una visualizzazione tipizzata veloce posizionata sulla memoria di lettura. L'uso di questo metodo su valori a 64 bit comporta la costruzione di una matrice di tipi di libreria a 64 bit che sono notevolmente più costosi!
Readstring

readString(location, [contextInheritor])

readString(location, [length], [contextInheritor])

2 Questa operazione legge una stringa stretta (tabella codici corrente) dallo spazio indirizzi di una destinazione di debug, la converte in UTF-16 e restituisce il risultato come stringa JavaScript. Potrebbe generare un'eccezione se non è stato possibile leggere la memoria. Il percorso fornito può essere un indirizzo (un valore a 64 bit), un oggetto location o un carattere nativo. Se viene fornito l'argomento contextInheritor facoltativo, la memoria verrà letto nel contesto (ad esempio: spazio indirizzi e destinazione di debug) indicato dall'argomento; in caso contrario, verrà letto dal contesto corrente del debugger. Se viene fornito l'argomento di lunghezza facoltativo, la stringa di lettura sarà della lunghezza specificata.
readWideString

readWideString(location, [contextInheritor])

readWideString(location, [length], [contextInheritor])

2 Questa operazione legge una stringa wide(UTF-16) dallo spazio indirizzi di una destinazione di debug e restituisce il risultato come stringa JavaScript. Potrebbe generare un'eccezione se non è stato possibile leggere la memoria. Il percorso fornito può essere un indirizzo (un valore a 64 bit), un oggetto location o un wchar_t nativo. Se viene fornito l'argomento contextInheritor facoltativo, la memoria verrà letto nel contesto (ad esempio: spazio indirizzi e destinazione di debug) indicato dall'argomento; in caso contrario, verrà letto dal contesto corrente del debugger. Se viene fornito l'argomento di lunghezza facoltativo, la stringa di lettura sarà della lunghezza specificata.

Concetti relativi al modello di dati in JavaScript

Mapping del modello di dati

I concetti del modello di dati seguenti sono mappati a JavaScript.

Concetto Interfaccia nativa JavaScript Equivalente
Conversione stringhe IStringDisplayableConcept standard: toString (...) {...}
Iterabilità IIterableConcept standard: [Symbol.iterator](){...}
Indicizzazione IIndexableConcept protocollo: getDimensionality (...) / getValueAt(...) / setValueAt (...)
Conversione del tipo di runtime IPreferredRuntimeTypeConcept protocollo: getPreferredRuntimeTypedObject (...)

Conversione stringhe

Il concetto di conversione stringa (IStringDisplayableConcept) si traduce direttamente nel metodo JavaScript standard toString . Poiché tutti gli oggetti JavaScript hanno una conversione stringa (fornita da Object.prototype se non specificato altrove), ogni oggetto JavaScript restituito al modello di dati può essere convertito in una stringa di visualizzazione. L'override della conversione della stringa richiede semplicemente l'implementazione di toString personalizzata.

class myObject
{
    //
    // This method will be called whenever any native code calls IStringDisplayableConcept::ToDisplayString(...)
    //
    toString()
    { 
        return "This is my own string conversion!";
    }
}

Iterabilità

Il concetto del modello di dati indica se un oggetto è iterabile o meno esegue il mapping diretto al protocollo ES6 di se un oggetto è iterabile. Qualsiasi oggetto con un metodo [Symbol.iterator] è considerato iterabile. L'implementazione di tale operazione renderà l'iterabile dell'oggetto.

Un oggetto che è solo iterabile può avere un'implementazione come indicato di seguito.

class myObject
{
    //
    // This method will be called whenever any native code calls IIterableConcept::GetIterator
    //
    *[Symbol.iterator]()
    {
        yield "First Value";
        yield "Second Value";
        yield "Third Value";
    }
}

È necessario prestare particolare considerazione per gli oggetti che sono sia iterabili che indicizzati perché gli oggetti restituiti dall'iteratore devono includere l'indice e il valore tramite un tipo restituito speciale.

Iterabile e indicizzato

Un oggetto iterabile e indicizzato richiede un valore restituito speciale dall'iteratore. Anziché restituire i valori, l'iteratore restituisce istanze di indexedValue. Gli indici vengono passati come matrice nel secondo argomento al costruttore indexedValue. Possono essere multidimensionali, ma devono corrispondere alla dimensionalità restituita nel protocollo dell'indicizzatore.

Questo codice mostra un esempio di implementazione.

class myObject
{
    //
    // This method will be called whenever any native code calls IIterableConcept::GetIterator
    //
    *[Symbol.iterator]()
    {
        //
        // Consider this a map which mapped 42->"First Value", 99->"Second Value", and 107->"Third Value"
        //
        yield new host.indexedValue("First Value", [42]);
        yield new host.indexedValue("Second Value", [99]);
        yield new host.indexedValue("Third Value", [107]);
    }
}

Indicizzazione

A differenza di JavaScript, il modello di dati rende una differenziazione molto esplicita tra l'accesso alle proprietà e l'indicizzazione. Qualsiasi oggetto JavaScript che desidera presentarsi come indicizzato nel modello di dati deve implementare un protocollo costituito da un metodo getDimensionality che restituisce la dimensione dell'indicizzatore e una coppia facoltativa di metodi getValueAt e setValueAt che eseguono letture e scritture dell'oggetto in indici forniti. È accettabile omettere i metodi getValueAt o setValueAt se l'oggetto è di sola lettura o di sola scrittura

class myObject
{
    //
    // This method will be called whenever any native code calls IIndexableConcept::GetDimensionality or IIterableConcept::GetDefaultIndexDimensionality
    //
    getDimensionality()
    {
        //
        // Pretend we are a two dimensional array.
        //
        return 2;
    } 

    //
    // This method will be called whenever any native code calls IIndexableConcept::GetAt
    //
    getValueAt(row, column)
    {
        return this.__values[row * this.__columnCount + column];
    }

    //
    // This method will be called whenever any native code calls IIndexableConcept::SetAt
    //
    setValueAt(value, row, column)
    {
        this.__values[row * this.__columnCount + column] = value;
    }
}

Conversione del tipo di runtime

Questo è rilevante solo per i prototipi/classi JavaScript registrati nei tipi di sistema di tipo (nativo). Il debugger è spesso in grado di eseguire analisi (ad esempio Run-Time tipo Information (RTTI) /v-table analysis) per determinare il tipo di runtime true di un oggetto da un tipo statico espresso nel codice. Un modello di dati registrato in un tipo nativo può eseguire l'override di questo comportamento tramite un'implementazione di IPreferredRuntimeTypeConcept. Analogamente, una classe JavaScript o un prototipo registrato in un oggetto nativo può fornire la propria implementazione tramite l'implementazione di un protocollo costituito dal metodo getPreferredRuntimeTypedObject.

Si noti che, mentre questo metodo può restituire tecnicamente qualsiasi elemento, è considerato un modulo non valido per restituire un elemento che non è effettivamente il tipo di runtime o un tipo derivato. Ciò può causare confusione significativa per gli utenti del debugger. L'override di questo metodo può tuttavia essere utile per gli elementi come intestazione di stile C+stili di oggetto dell'implementazione e così via...

class myNativeModel
{
    //
    // This method will be called whenever the data model calls IPreferredRuntimeTypeConcept::CastToPreferredRuntimeType
    //
    getPreferredRuntimeTypedObject()
    {
        var loc = this.targetLocation;

        //
        // Perform analysis...
        //
        var runtimeLoc = loc.Add(runtimeObjectOffset);
  
        return host.createTypedObject(runtimeLoc, runtimeModule, runtimeTypeName);
    }
}

Vedere anche

Oggetti debugger nativi nelle estensioni JavaScript

Oggetti debugger nativi nelle estensioni JavaScript - Considerazioni sulla progettazione e sul test

Script del debugger JavaScript

Script di esempio di debugger JavaScript