Condividi tramite


Oggetti debugger nativi nelle estensioni JavaScript - Dettagli oggetto debugger

In questo argomento vengono descritti dettagli aggiuntivi sull'uso degli oggetti debugger nativi nelle estensioni JavaScript.

Gli oggetti debugger nativi rappresentano vari costrutti e comportamenti dell'ambiente del debugger. Gli oggetti possono essere passati o acquisiti nelle estensioni JavaScript per modificare lo stato del debugger.

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

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

Ad esempio, script ed 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 dell'istanza per un prototipo JavaScript (ad esempio, come 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 previsti
  • Tipi speciali relativi agli oggetti debugger nativi
  • Attributi aggiuntivi

Accesso alle proprietà

Anche se esistono alcune proprietà sugli oggetti posizionati dal provider JavaScript stesso, la maggior parte delle proprietà di un oggetto nativo che immette JavaScript viene fornita dal modello di dati. Ciò significa che per l'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), si risolverà in questo nome come seconda opzione; 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 dereferenziato seguito da una chiave seguita da un campo nativo)

I normali mezzi di accesso alle proprietà in JavaScript -- object.propertyName e object[propertyName] -- accederanno ai campi nativi sottostanti di un oggetto, in quanto il comando 'dx' si troverebbe all'interno del debugger.

Nomi proposti

Le proprietà e i metodi seguenti vengono proiettate in oggetti nativi che immettono JavaScript.

Metodo Firma Descrizione
hostContext Proprietà Restituisce un oggetto che rappresenta il contesto in cui si trova l'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 del modello di dati) all'oggetto
rimuoviModelloPadre .removeParentModel(object) Rimuove un determinato modello padre dall'oggetto
oggetto tipizzato a tempo di esecuzione Proprietà Esegue l'analisi sull'oggetto e tenta di convertirlo nel tipo di runtime (più derivato)
tipo di obiettivo Proprietà Le estensioni JavaScript hanno accesso diretto al sistema di tipi del linguaggio sottostante. Questo accesso viene espresso tramite il concetto 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 proiettate sul puntatore che immette JavaScript:

Nome della proprietà Firma Descrizione
Aggiungere .add(value) Esegue l'addizione matematica del puntatore tra il puntatore e il valore specificato
indirizzo Proprietà Restituisce l'indirizzo del puntatore come oggetto ordinale a 64 bit (tipo di libreria)
dereferenziare .dereference() Dereferenzia il puntatore e restituisce l'oggetto sottostante
isNull Proprietà Restituisce un valore che indica se il valore del puntatore è nullptr (0)

Tipi speciali relativi agli oggetti debugger nativi

Oggetti di Posizione

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

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

Attributi aggiuntivi

Iterabilità

Qualsiasi oggetto compreso come iterabile dal modello di dati (si tratta di una matrice nativa o ha un visualizzatore (NatVis o altro) che lo rende iterabile, avrà una funzione iteratore (indicizzata tramite symbol.iterator standard ES6) posizionata su di essa. Ciò significa che è possibile scorrere 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++.
        //
    }
}

Indicizzabilità

Gli oggetti considerati indicizzati in una dimensione tramite ordinali (ad esempio, matrici native) saranno indicizzabili in JavaScript tramite l'operatore standard di accesso alle proprietà -- object[index]. Se un oggetto è indicizzabile per nome o è indicizzabile 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 di stringhe

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

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

Creazione di oggetti debugger nativi

Come accennato, uno script JavaScript può ottenere l'accesso agli oggetti nativi avendoli passati in JavaScript in uno dei diversi modi oppure può 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 nello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene fornito, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script di test occasionale 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.getModuleContainingSymbol

getModuleContainingSymbol(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 nello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene fornito, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script di test occasionale 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 nello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene fornito, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script di test occasionale 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 nello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene fornito, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script di test occasionale 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 configurato in due fasi.

  • Fase 1: prima dell'esecuzione di qualsiasi script, l'oggetto host contiene solo il set minimo di funzionalità necessario per inizializzare uno 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 tutti gli elementi necessari per modificare lo stato delle destinazioni di debug.

Livello oggetto host

Alcuni elementi chiave di funzionalità si trovano direttamente nell'oggetto host. Il resto è sotto-namespace. I 'namespace' includono quanto segue.

Namespace Descrizione
Diagnosi 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 di root

È possibile trovare direttamente all'interno dell'oggetto host 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 facoltativo contextInheritor opera allo stesso modo di getModuleSymbol.
currentProcess

Proprietà

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

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 dell'obiettivo 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 eseguita una chiamata nell'host di debug per valutare un'espressione utilizzando solo il linguaggio del target di debug. L'argomento di contesto indica il puntatore implicito 'this' da utilizzare per la valutazione. L'espressione verrà valutata nel contesto (ad esempio, spazio degli indirizzi e destinazione di debug) indicato dall'argomento 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 nello stesso contesto (spazio indirizzi, destinazione di debug) dell'oggetto passato. Se l'argomento non viene fornito, il modulo e il simbolo verranno cercati nel contesto corrente del debugger. Un'estensione JavaScript che non è uno script non ricorrente deve sempre fornire un contesto esplicito
getNamedModel

getNamedModel(modelName)

2 Restituisce il modello di dati registrato in base a un determinato nome. Si noti che è perfettamente legale effettuare una chiamata contro un nome che non è ancora registrato. In questo modo verrà creato uno stub per quel nome e le manipolazioni sullo stub verranno applicate all'oggetto effettivo durante la registrazione.
indexedValue

new indexedValue(value, indicies)

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 creato un tipo Int64 della libreria. La versione a singolo argomento accetta qualsiasi valore che possa essere inserito in un Int64 (senza conversione) e lo colloca in tale struttura. Se viene fornito un secondo argomento facoltativo, una conversione del primo argomento viene compressa nei 32 bit inferiori e una conversione del secondo argomento viene compressa nei 32 bit superiori.
namedModelParent

new namedModelParent(object, name)

1 Un costruttore per un oggetto che deve essere inserito nella matrice restituita da initializeScript, che 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
registrazioneModelloNominale

new namedModelRegistration(object, name)

1 Un costruttore per un oggetto che deve essere inserito nella matrice restituita da initializeScript, che 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, è possibile accedere all'elenco di processi della prima destinazione di debug tramite host.namespace.Debugger.Sessions.First(). Processi che usano questa proprietà
registraModelloNominato

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 metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario avere un metodo initializeScript per eseguire la pulizia.
registraEstensionePerFirmaTipo

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 fornita. Si noti che uno script deve preferire restituire un oggetto typeSignatureExtension dal metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario avere un metodo initializeScript per eseguire la pulizia.
registerPrototypeForTypeSignature

registerPrototypeForTypeSignature(object, typeSignature)

2 In questo modo viene registrato un prototipo JavaScript o una classe ES6 come modello di dati canonico (ad esempio, visualizzatore) per un tipo nativo, come indicato dalla firma del tipo fornita. Si noti che uno script deve preferire restituire un oggetto typeSignatureRegistration dal metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario disporre di un metodo uninitializeScriptper eseguire la pulizia.
parseInt64

parseInt64(string, [radix])

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

new typeSignatureExtension(oggetto, typeSignature, [nomeModulo], [versioneMinima], [versioneMassima])

1 Un costruttore per un oggetto che deve essere inserito nella matrice restituita da initializeScript, 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 corrisponda alla firma, piuttosto che sostituirla completamente. Un nome e una versione di modulo facoltativi possono limitare la registrazione. Le versioni vengono specificate come stringhe di stile "1.2.3.4".
registrazioneDellaFirmaDiTipo

new typeSignatureRegistration(object, typeSignature, [moduleName], [minVersion], [maxVersion])

1 Un costruttore per un oggetto che deve essere inserito nella matrice restituita da initializeScript, rappresenta una registrazione canonica di un prototipo JavaScript o di una classe ES6 rispetto a una firma di tipo nativo. Tale registrazione "si appropria" della visualizzazione del debugger di qualsiasi tipo che corrisponde alla firma, invece di limitarsi semplicemente ad estenderla. 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 qualsiasi operazione eseguita da registerNamedModel
unregisterExtensionForTypeSignature

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

2 Questa operazione annulla la registrazione di un prototipo JavaScript o di una classe ES6 da essere un modello di dati di estensione per un tipo nativo, come specificato dalla firma del tipo fornita. Si tratta dell'annullamento logico di registerExtensionForTypeSignature. Si noti che uno script deve preferire restituire un oggetto typeSignatureExtension dal metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario avere un metodo initializeScript per eseguire la pulizia. Un nome e una versione di modulo facoltativi possono limitare la registrazione. Le versioni vengono specificate come stringhe di stile "1.2.3.4".
unregisterPrototipoPerFirmaTipo

unregisterPrototypeForTypeSignature(oggetto, firmaTipo, [nomeModulo], [versioneMinima], [versioneMassima])

2 Questa operazione deregistra un prototipo JavaScript o una classe ES6 dal diventare il modello di dati canonico (ad esempio, visualizzatore) per un tipo nativo, come specificato dalla firma del tipo fornita. Si tratta dell'annullamento logico di registerPrototypeForTypeSignature. Si noti che uno script deve preferire restituire un oggetto typeSignatureRegistration dal metodo initializeScript anziché eseguire questa operazione in modo imperativo. Qualsiasi script che apporta modifiche in modo imperativo è necessario disporre di un metodo uninitializeScript per eseguire la pulizia. 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 ciò che 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 di debugLog viene indirizzato alla console di output del debugger. In un secondo momento, si prevede di offrire flessibilità nel routing di questo output. NOTA: questa operazione non deve essere utilizzata come mezzo per stampare l'output dell'utente nella console. Potrebbe non essere instradato lì in futuro.

Funzionalità di memoria

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

Nome Firma Fase presente Descrizione
readMemoryValues

Utilizzare la funzione `readMemoryValues(location, numElements, [elementSize], [isSigned], [contextInheritor])` per leggere i valori della memoria specificati nel codice.

2 In questo modo viene letta una matrice non elaborata di valori dallo spazio indirizzi della destinazione di debug e viene memorizzata una matrice tipizzata sopra la visualizzazione di questa memoria. La posizione specificata può essere un indirizzo (un valore a 64 bit), un oggetto posizione o un puntatore nativo. La dimensione della matrice è indicata dall'argomento numElements . Le dimensioni (e il tipo) di ogni elemento della matrice vengono fornite dagli argomenti elementSize facoltativi e isSigned . Se non vengono forniti argomenti di questo tipo, il valore predefinito è byte (unsigned / 1 byte). Se viene fornito l'argomento contextInheritor facoltativo, la memoria verrà letta nel contesto (ad esempio: spazio indirizzi e destinazione di debug) indicata 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 32 bit comporta una vista tipizzata rapida collocata sulla memoria letta. L'uso di questo metodo su valori a 64 bit comporta la costruzione di una matrice di tipi di libreria a 64 bit che è notevolmente più costosa.
readString

readString(location, [contextInheritor])

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

2 In questo modo viene letta 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. La posizione specificata 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à letta nel contesto (ad esempio: spazio indirizzi e destinazione di debug) indicata dall'argomento; in caso contrario, verrà letto dal contesto corrente del debugger. Se viene fornito l'argomento lunghezza facoltativa, la stringa di lettura sarà della lunghezza specificata.
readWideString

readWideString(location, [contextInheritor])

readWideString(posizione, [lunghezza], [eredeContesto])

2 In questo modo viene letta 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. La posizione specificata può essere un indirizzo (un valore a 64 bit), un oggetto posizione o un wchar_t nativo. Se viene fornito l'argomento contextInheritor facoltativo, la memoria verrà letta nel contesto (ad esempio: spazio indirizzi e destinazione di debug) indicata dall'argomento; in caso contrario, verrà letto dal contesto corrente del debugger. Se viene fornito l'argomento lunghezza facoltativa, la stringa di lettura sarà della lunghezza specificata.

Concetti relativi al modello di dati in JavaScript

Mapping del modello di dati

I seguenti concetti del modello di dati corrispondono a JavaScript.

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

Conversione di stringhe

Il concetto di conversione di stringhe (IStringDisplayableConcept) si traduce direttamente nel metodo JavaScript toString standard. Poiché tutti gli oggetti JavaScript hanno una conversione di stringhe (fornita da Object.prototype se non specificato altrove), ogni oggetto JavaScript restituito al modello di dati può essere convertito in una stringa di visualizzazione. Per eseguire l'override della conversione di stringhe è sufficiente implementare il proprio toString.

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 di se un oggetto è iterabile o meno corrisponde direttamente al protocollo ES6 di se un oggetto è iterabile. Qualsiasi oggetto con un metodo [Symbol.iterator] è considerato iterabile. L'implementazione di tale renderà l'oggetto iterabile.

Un oggetto che è 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 indicizzabili perché gli oggetti restituiti dall'iteratore devono includere l'indice e il valore tramite un tipo restituito speciale.

Iterabile e indicizzatore

Un oggetto iterabile e indicizzatore richiede un valore restituito speciale dall'iteratore. Anziché produrre 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]);
    }
}

Indicizzabilità

A differenza di JavaScript, il modello di dati fa una differenziazione molto esplicita tra l'accesso alle proprietà e l'indicizzazione. Qualsiasi oggetto JavaScript che desidera presentarsi come indicizzatore nel modello di dati deve implementare un protocollo costituito da un metodo getDimensionality che restituisce la dimensionalità dell'indicizzatore e una coppia facoltativa di metodi getValueAt e setValueAt che eseguono operazioni di lettura e scrittura 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 dei tipi di runtime

Questo è rilevante solo per i prototipi/classi JavaScript che sono registrati nei tipi di sistema nativi. Il debugger è spesso in grado di eseguire analisi (ad esempio, Run-Time'analisi delle informazioni sul tipo (RTTI) /v-table, per determinare il tipo di runtime reale di un oggetto da un tipo statico espresso nel codice. Un modello di dati registrato contro 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 anche se questo metodo può tecnicamente restituire qualsiasi elemento, è considerato una forma non valida per restituire qualcosa che non è realmente il tipo di runtime o un tipo derivato. Questo può causare confusione significativa per gli utenti del debugger. Sovrascrivere questo metodo può tuttavia essere utile per elementi quali stili di intestazione e oggetto in stile C di implementazione, ecc...

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

JavaScript Debugger Scripting

Script di esempio del debugger JavaScript