Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
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