Freigeben über


Native Debugger-Objekte in JavaScript-Erweiterungen – Details zum Debugger-Objekt

In diesem Thema werden weitere Details zur Verwendung der systemeigenen Debuggerobjekte in JavaScript-Erweiterungen beschrieben.

Systemeigene Debuggerobjekte stellen verschiedene Konstrukte und Verhaltensweisen der Debuggerumgebung dar. Die Objekte können an JavaScript-Erweiterungen übergeben (oder erworben werden), um den Zustand des Debuggers zu bearbeiten.

Informationen zu JavaScript-Erweiterungen des Debuggerobjekts finden Sie unter Native Debugger Objects in JavaScript Extensions.

Allgemeine Informationen zum Arbeiten mit JavaScript finden Sie unter JavaScript Debugger Scripting.

Zum Beispiel JavaScript-Skripts und Erweiterungen hosten das Debuggerteam ein GitHub-Repository unter https://github.com/Microsoft/WinDbg-Samples.

Debuggerobjekte in JavaScript-Erweiterungen

Übergeben systemeigener Objekte

Debuggerobjekte können auf vielfältige Weise in JavaScript-Erweiterungen übergeben oder erworben werden.

  • Sie können an JavaScript-Funktionen oder -Methoden übergeben werden.
  • Sie können das Instanzobjekt für einen JavaScript-Prototyp sein (z. B. als Visualizer)
  • Sie können von Hostmethoden zurückgegeben werden, die zum Erstellen systemeigener Debuggerobjekte entwickelt wurden.
  • Sie können von Hostmethoden zurückgegeben werden, die zum Erstellen systemeigener Debuggerobjekte entwickelt wurden.

Debuggerobjekte, die an eine JavaScript-Erweiterung übergeben werden, verfügen über eine Reihe von Funktionen, die in diesem Abschnitt beschrieben werden.

  • Eigenschaftszugriff
  • Projizierte Namen
  • Spezielle Typen im Zusammenhang mit systemeigenen Debuggerobjekten
  • Zusätzliche Attribute

Eigenschaftszugriff

Obwohl es einige Eigenschaften für Objekte gibt, die vom JavaScript-Anbieter selbst platziert werden, werden die meisten Eigenschaften für ein systemeigenes Objekt, das JavaScript eingibt, vom Datenmodell bereitgestellt. Dies bedeutet, dass für einen Eigenschaftszugriff --- object.propertyName oder object[propertyName] Folgendes auftritt.

  • Wenn propertyName der Name einer Eigenschaft ist, die vom JavaScript-Anbieter selbst dem Objekt zugewiesen wird, wird sie zuerst aufgelöst; andernfalls
  • Wenn propertyName der Name eines Schlüssels ist, der vom Datenmodell (einem anderen Visualizer) auf das Objekt projiziert wird, wird er in diesen Namen second aufgelöst. sonst
  • Wenn propertyName der Name eines Feldes des systemeigenen Objekts ist, wird er als dritter zu diesem Namen aufgelöst, sonst.
  • Wenn das Objekt ein Zeiger ist, wird der Zeiger abgeleitet, und der obige Zyklus wird fortgesetzt (eine projizierte Eigenschaft des abgeleiteten Objekts gefolgt von einem Schlüssel, gefolgt von einem systemeigenen Feld)

Die normalen Methoden für den Eigenschaftenzugriff in JavaScript -- object.propertyName und object[propertyName] - greifen auf die zugrunde liegenden nativen Felder eines Objekts zu, ähnlich wie der Befehl "dx" innerhalb des Debuggers.

Projizierte Namen

Die folgenden Eigenschaften (und Methoden) werden auf systemeigene Objekte projiziert, die JavaScript eingeben.

Methode Unterschrift BESCHREIBUNG
Hostkontext Eigentum Gibt ein Objekt zurück, das den Kontext darstellt, in dem sich das Objekt befindet (Adressraum, Debugziel usw....)
ZielStandort Eigentum Gibt ein Objekt zurück, das eine Abstraktion davon ist, wo sich das Objekt innerhalb eines Adressraums befindet (virtuelle Adresse, Register, Unterregister usw....)
targetSize Eigentum Gibt die Größe des Objekts zurück (effektiv: sizeof(<TYPE OF OBJECT>)
ElternmodellHinzufügen .addParentModel(object) Fügt dem Objekt ein neues übergeordnetes Modell (ähnlich einem JavaScript-Prototyp, aber auf der Datenmodellseite) hinzu.
EntferneElternmodell .removeParentModel(object) Entfernt ein angegebenes übergeordnetes Modell aus dem Objekt.
LaufzeitgetyptesObjekt Eigentum Führt eine Analyse des Objekts durch und versucht, es in den Laufzeittyp (den am meisten abgeleiteten) zu konvertieren.
Zieltyp Eigentum JavaScript-Erweiterungen haben direkten Zugriff auf das Typsystem der zugrunde liegenden Sprache. Dieser Zugriff wird durch den Begriff der Typobjekte ausgedrückt. Weitere Informationen finden Sie unter Native Debugger Objects in JavaScript Extensions – Type Objects

Wenn das Objekt ein Zeiger ist, werden die folgenden Eigenschaften (und Methoden) auf den Zeiger projiziert, der JavaScript eingibt:

Objektname Unterschrift BESCHREIBUNG
hinzufügen .add(value) Führt Zeigerarithmetik aus, indem der Zeiger und der angegebene Wert addiert werden.
Adresse Eigentum Gibt die Adresse des Zeigers als 64-Bit-Ordinalobjekt (ein Bibliothekstyp) zurück.
dereferenzieren .dereference() Leitet den Zeiger ab und gibt das zugrunde liegende Objekt zurück.
isNull Eigentum Gibt zurück, ob der Zeigerwert nullptr (0) ist.

Spezielle Typen im Zusammenhang mit systemeigenen Debuggerobjekten

Location-Objekte

Das Location-Objekt, das von der targetLocation-Eigenschaft eines systemeigenen Objekts zurückgegeben wird, enthält die folgenden Eigenschaften (und Methoden).

Objektname Unterschrift BESCHREIBUNG
hinzufügen .add(value) Fügt der Position einen absoluten Byte-Offset hinzu.
Subtrahieren .subtrahieren(Wert) Subtrahiert einen absoluten Byte-Offset von der Position.

Zusätzliche Attribute

Iterierbarkeit

Jedes Objekt, das im Datenmodell als iterierbar angesehen wird (es handelt sich um ein natives Array oder verfügt über eine Visualisierung (sei es NatVis oder eine andere), die es iterierbar macht), wird eine Iteratorfunktion (definiert über das ES6-Standard-Symbol.iterator) erhalten. Dies bedeutet, dass Sie ein integriertes Objekt in JavaScript wie folgt durchlaufen können.

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++.
        //
    }
}

Indizierbarkeit

Objekte, die in einer Dimension über Ordinale (z. B. native Arrays) indizierbar sind, werden in JavaScript über den Standard-Eigenschaftszugriffsoperator -- object[index] indiziert. Wenn ein Objekt anhand des Namens indiziert oder in mehreren Dimensionen indiziert werden kann, werden die Methoden "getValueAt" und "setValueAt" auf das Objekt projiziert, sodass JavaScript-Code den Indexer verwenden kann.

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

Zeichenfolgenkonvertierung

Jedes systemeigene Objekt mit einer Anzeigezeichenfolgenkonvertierung über die Unterstützung von IStringDisplayableConcept oder ein NatVis DisplayString-Element verfügt über diese Zeichenfolgenkonvertierung, auf die über die standardmäßige JavaScript-toString-Methode zugegriffen werden kann.

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

Erstellen nativer Debuggerobjekte

Wie bereits erwähnt, kann ein JavaScript-Skript Zugriff auf systemeigene Objekte erhalten, indem sie auf eine von mehreren Arten an JavaScript übergeben werden, oder es kann sie über Aufrufe der Hostbibliothek erstellen. Verwenden Sie die folgenden Funktionen, um systemeigene Debuggerobjekte zu erstellen.

Methode Unterschrift BESCHREIBUNG

host.getModuleSymbol

ModulSymbolAbrufen(modulName, symbolName, [contextErbe])

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

Gibt ein Objekt für ein globales Symbol innerhalb eines bestimmten Moduls zurück. Der Modulname und der Symbolname sind Zeichenfolgen.

Wenn das optionale contextInheritor-Argument angegeben wird, werden das Modul und das Symbol innerhalb desselben Kontexts (Adressraum, Debugziel) wie das übergebene Objekt ermittelt. Wenn das Argument nicht angegeben wird, werden das Modul und das Symbol im aktuellen Kontext des Debuggers ermittelt. Eine JavaScript-Erweiterung, die kein einmaliges Testskript ist, sollte immer einen expliziten Kontext bereitstellen.

Wenn das optionale TypeName-Argument angegeben wird, wird davon ausgegangen, dass es sich um den übergebenen Typ handelt, und der in Symbol(n) angegebene Typ wird ignoriert. Beachten Sie, dass jeder Aufrufer, der erwartet, mit öffentlichen Symbolen eines Moduls zu arbeiten, stets einen expliziten Typnamen spezifizieren sollte.

host.getModuleContainingSymbol

getModuleContainingSymbol(location, [contextInheritor])

Gibt das Symbol (z. B. Funktion oder Daten) zurück, das die angegebene Adresse enthält. Beachten Sie, dass dies nur funktioniert, wenn private Symbole für das Modul vorhanden sind, das die angegebene Adresse enthält.

Wenn das optionale contextInheritor-Argument angegeben wird, werden das Modul und das Symbol innerhalb desselben Kontexts (Adressraum, Debugziel) wie das übergebene Objekt nachschlagen. Wenn das Argument nicht angegeben wird, werden das Modul oder das Symbol im aktuellen Kontext des Debuggers abgerufen. Eine JavaScript-Erweiterung, die kein einmaliges Testskript ist, sollte immer einen expliziten Kontext bereitstellen.

host.createPointerObject

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

Erstellt ein Zeigerobjekt an der angegebenen Adresse oder Position. Der Modulname und der Typname sind Zeichenfolgen.

Wenn das optionale Argument contextInheritor angegeben wird, werden das Modul und das Symbol innerhalb desselben Kontexts (Adressraum, Debugger-Ziel) wie das übergebene Objekt gesucht. Wenn das Argument nicht angegeben wird, werden das Modul und das Symbol im aktuellen Kontext des Debuggers nachgeschlagen. Eine JavaScript-Erweiterung, die kein einmaliges Testskript ist, sollte immer einen expliziten Kontext bereitstellen.

host.createTypedObject

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

Erstellt ein Objekt, das ein systemeigenes typiertes Objekt innerhalb des Adressraums eines Debugziels an der angegebenen Position darstellt. Der Modulname und der Typname sind Zeichenfolgen.

Wenn das optionale contextInheritor-Argument angegeben wird, werden das Modul und das Symbol innerhalb desselben Kontexts (Adressraum, Debugziel) wie das übergebene Objekt nachgeschlagen. Wenn das Argument nicht angegeben wird, werden Modul und Symbol im aktuellen Kontext des Debuggers nachgeschlagen. Eine JavaScript-Erweiterung, die kein einmaliges Testskript ist, sollte immer einen expliziten Kontext bereitstellen.

Host-APIs für JavaScript-Erweiterungen

Der JavaScript-Anbieter fügt ein Objekt, das als Host bezeichnet wird, in den globalen Namespace jedes Skripts ein, das geladen wird. Dieses Objekt bietet Zugriff auf kritische Funktionen für das Skript sowie Zugriff auf den Namespace des Debuggers. Sie wird in zwei Phasen eingerichtet.

  • Phase 1: Bevor ein Skript ausgeführt wird, enthält das Hostobjekt nur den minimalen Satz von Funktionen, der für die Initialisierung eines Skripts erforderlich ist, und registriert seine Erweiterbarkeitspunkte (sowohl als Produzent als auch Als Consumer). Der Stamm- und Initialisierungscode dient nicht dazu, den Status eines Debugziels zu bearbeiten oder komplexe Vorgänge auszuführen. Der Host wird daher erst nach dem Zurückgeben der InitializeScript-Methode vollständig ausgefüllt.

  • Phase 2: Nach dem InitializeScript-Zurückgeben wird das Hostobjekt mit allem gefüllt, was zum Bearbeiten des Zustands der Debugziele erforderlich ist.

Hostobjektebene

Einige wichtige Funktionen befinden sich direkt unter dem Hostobjekt. Der Rest ist unternamespaced. Namespaces umfassen Folgendes.

Namespace BESCHREIBUNG
Diagnostik Funktionalität zur Unterstützung der Diagnose und des Debuggens von Skriptcode
Arbeitsspeicher Funktionalität zum Aktivieren von Speicherlese- und Schreibvorgängen innerhalb eines Debugziels

Root-Ebene

Direkt innerhalb des Hostobjekts finden Sie die folgenden Eigenschaften, Methoden und Konstruktoren.

Name Unterschrift Aktuelle Phase BESCHREIBUNG
createPointerObject

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

2 Erstellt ein Zeigerobjekt an der angegebenen Adresse oder Position. Der Modulname und der Typname sind Zeichenfolgen. Das optionale contextInheritor-Argument funktioniert wie bei getModuleSymbol.
createTypedObject

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

2 Erstellt ein Objekt, das ein systemeigenes typiertes Objekt innerhalb des Adressraums eines Debugziels an der angegebenen Position darstellt. Der Modulname und der Typname sind Zeichenfolgen. Das optionale contextInheritor-Argument funktioniert wie bei getModuleSymbol.
aktuellerProzess

Eigentum

2 Gibt das Objekt zurück, das den aktuellen Prozess des Debuggers darstellt.
aktuelleSitzung

Eigentum

2 Gibt das Objekt zurück, das die aktuelle Sitzung des Debuggers darstellt (welches Ziel, Dump usw.) gedebuggt wird.
currentThread

Eigentum

2 Gibt das Objekt zurück, das den aktuellen Thread des Debuggers darstellt.
AusdruckAuswerten

evaluateExpression(Ausdruck; [contextInheritor])

2 Dadurch wird der Debug-Host aufgerufen, um einen Ausdruck unter Verwendung nur der Sprache des Debug-Ziels auszuwerten. Wenn das optionale contextInheritor-Argument angegeben wird, wird der Ausdruck im Kontext ausgewertet (z. B. Adressraum und Debugziel) des Arguments; andernfalls wird sie im aktuellen Kontext des Debuggers ausgewertet.
evaluateExpressionInContext

evaluateExpressionInContext(context, expression)

2 Dadurch wird der Debughost aufgerufen, um einen Ausdruck lediglich unter Verwendung der Programmiersprache des Debugziels auszuwerten. Das Kontextargument gibt den impliziten this-Zeiger an, der für die Auswertung verwendet werden soll. Der Ausdruck wird im Kontext ausgewertet (z. B. Adressraum und Debugziel), der durch das Kontextargument angegeben wird.
getModuleSymbol

ModulSymbolAbrufen(modulName, symbolName, [contextErbe])

2 Gibt ein Objekt für ein globales Symbol innerhalb eines bestimmten Moduls zurück. Der Modulname und der Symbolname sind Zeichenfolgen. Wenn das optionale contextInheritor-Argument angegeben wird, werden das Modul und das Symbol innerhalb desselben Kontexts (Adressraum, Debugziel) wie das übergebene Objekt nachgeschlagen. Wenn das Argument nicht angegeben wird, werden Modul und Symbol im aktuellen Kontext des Debuggers nachgeschlagen. Eine JavaScript-Erweiterung, die kein einmaliges Skript ist, sollte immer einen expliziten Kontext bereitstellen.
getNamedModel

getNamedModel(modelName)

2 Gibt das Datenmodell zurück, das für einen bestimmten Namen registriert wurde. Beachten Sie, dass es vollkommen legal ist, dies gegen einen Namen zu nennen, der noch nicht registriert ist. Dadurch wird ein Stub für diesen Namen erstellt, und Manipulationen am Stub werden bei der Registrierung auf das eigentliche Objekt übertragen.
indizierter Wert

new indexedValue(value, indizes)

2 Ein Konstruktor für ein Objekt, das von einem JavaScript-Iterator zurückgegeben werden kann, um dem iterierten Wert einen Standardsatz von Indicies zuzuweisen. Der Satz von Indicies muss als JavaScript-Array ausgedrückt werden.
Int64

new Int64(value, [highValue])

1 Dadurch wird ein Bibliothekstyp Int64 erstellt. Die Version mit einem einzigen Argument akzeptiert jeden Wert, der ohne Konvertierung in ein Int64 integriert werden kann, und platziert ihn darin. Wenn ein optionales zweites Argument angegeben wird, wird eine Konvertierung des ersten Arguments in die unteren 32-Bits gepackt, und eine Konvertierung des zweiten Arguments wird in die oberen 32 Bits gepackt.
namedModelParent

new namedModelParent(object, name)

1 Ein Konstruktor für ein Objekt, das in das array eingefügt werden soll, das von initializeScript zurückgegeben wird. Dies stellt die Verwendung eines JavaScript-Prototyps oder einer ES6-Klasse als übergeordnete Datenmodellerweiterung eines Datenmodells mit dem angegebenen Namen dar.
benannte Modellregistrierung

new namedModelRegistration(object, name)

1 Ein Konstruktor für ein Objekt, das in das array eingefügt werden soll, das von initializeScript zurückgegeben wird. Dies stellt die Registrierung eines JavaScript-Prototyps oder einer ES6-Klasse als Datenmodell über einen bekannten Namen dar, damit andere Erweiterungen suchen und erweitern können.
Namespace

Eigentum

2 Ermöglicht direkten Zugriff auf den Stammnamespace des Debuggers. Man könnte beispielsweise über host.namespace.Debugger.Sessions.First() auf die Prozessliste des ersten Debugziels zugreifen. Prozesse, die diese Eigenschaft verwenden
registerNamedModel

registerNamedModel(object, modelName)

2 Dadurch wird ein JavaScript-Prototyp oder eine ES6-Klasse als Datenmodell unter dem angegebenen Namen registriert. Eine solche Registrierung ermöglicht es, den Prototyp oder die Klasse durch andere Skripte oder andere Debugger-Erweiterungen zu lokalisieren und zu erweitern. Beachten Sie, dass ein Skript lieber ein namedModelRegistration-Objekt aus seiner initializeScript-Methode zurückgeben sollte, anstatt dies zwingend durchzuführen. Jedes Skript, das Änderungen vornimmt, muss eine initializeScript-Methode haben, um sie zu bereinigen.
registerExtensionForTypeSignature

registerExtensionForTypeSignature(object, typeSignature) (Registriere Erweiterung für Typensignatur)

2 Dadurch wird ein JavaScript-Prototyp oder eine ES6-Klasse als Erweiterungsdatenmodell für einen systemeigenen Typ registriert, wie durch die angegebene Typsignatur angegeben. Beachten Sie, dass ein Skript lieber ein typeSignatureExtension-Objekt aus seiner initializeScript-Methode zurückgeben sollte, anstatt dies zwingend durchzuführen. Jedes Skript, das Änderungen vornimmt, muss eine initializeScript-Methode verwenden, um die Änderungen zu bereinigen.
registerPrototypeForTypeSignature

registerPrototypeForTypeSignature(object, typeSignature)

2 Dadurch wird ein JavaScript-Prototyp oder eine ES6-Klasse als kanonisches Datenmodell (z. B. Visualizer) für einen systemeigenen Typ registriert, wie von der angegebenen Typsignatur angegeben. Beachten Sie, dass ein Skript lieber ein typeSignatureRegistration-Objekt aus seiner initializeScript-Methode zurückgeben sollte, anstatt dies im Imperativen zu tun. Ein Skript, das Änderungen vornimmt, muss eine uninitializeScript-Methode haben, um bereinigt zu werden.
parseInt64

parseInt64(string; [radix])

1 Diese Methode verhält sich ähnlich wie die standardmäßige JavaScript parseInt-Methode, mit der Ausnahme, dass sie stattdessen einen Int64-Bibliothekstyp zurückgibt. Wenn ein Radix bereitgestellt wird, erfolgt die Analyse entweder in der Basis 2, 8, 10 oder 16 wie angegeben.
Typsignatur-Erweiterung

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

1 Ein Konstruktor für ein Objekt, das in das array eingefügt werden soll, das von initializeScript zurückgegeben wird, stellt dies eine Erweiterung eines nativen Typs dar, der über eine Typsignatur durch einen JavaScript-Prototyp oder eine ES6-Klasse beschrieben wird. Eine solche Registrierung fügt der Visualisierung des Debuggers Felder eines beliebigen Typs hinzu, der der Signatur entspricht, anstatt sie vollständig zu übernehmen. Ein optionaler Modulname und eine optionale Version können die Registrierung einschränken. Versionen werden als Zeichenfolgen im Format "1.2.3.4" angegeben.
Typensignatur Registrierung

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

1 Ein Konstruktor für ein Objekt, das in das Array eingefügt werden soll, welches von initializeScript zurückgegeben wird. Dies stellt eine kanonische Registrierung eines JavaScript-Prototyps oder einer ES6-Klasse in Bezug auf eine systemeigene Typsignatur dar. Eine solche Registrierung ersetzt die Darstellung des Debuggers für jeden Typ, der mit der Signatur übereinstimmt, anstatt sie lediglich zu erweitern. Ein optionaler Modulname und eine optionale Version können die Registrierung einschränken. Versionen werden als Zeichenfolgen im Format "1.2.3.4" angegeben.
unregisterNamedModel

unregisterNamedModel(modelName)

2 Dies hebt die Registrierung eines Datenmodells aus der Nachschlagesuche mit dem angegebenen Namen auf, wodurch die von registerNamedModel durchgeführte Registrierung rückgängig gemacht wird.
unregisterExtensionForTypeSignature

unregisterExtensionForTypeSignature(object, typeSignature, [moduleName], [minVersion], [maxVersion]) – Deregistriert eine Erweiterung für einen Typ-Signatur.

2 Dadurch wird die Registrierung eines JavaScript-Prototyps oder einer ES6-Klasse als Erweiterungsdatenmodell für einen systemeigenen Typ aufgehoben, wie durch die bereitgestellte Typsignatur angegeben. Dies ist das logische Rückgängigmachen von registerExtensionForTypeSignature. Beachten Sie, dass ein Skript lieber ein typeSignatureExtension-Objekt aus seiner initializeScript-Methode zurückgeben sollte, anstatt dies zwingend durchzuführen. Jedes Skript, das Änderungen vornimmt, muss eine initializeScript-Methode haben, um aufzuräumen. Ein optionaler Modulname und eine optionale Version können die Registrierung einschränken. Versionen werden als Zeichenfolgen im Format "1.2.3.4" angegeben.
unregisterPrototypeForTypeSignature

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

2 Dadurch wird die Registrierung eines JavaScript-Prototyps oder einer ES6-Klasse als kanonisches Datenmodell (z. B. Visualizer) für einen systemeigenen Typ aufgehoben, wie durch die angegebene Typsignatur angegeben. Dies ist das logische Rückgängigmachen von registerPrototypeForTypeSignature. Beachten Sie, dass ein Skript lieber ein typeSignatureRegistration-Objekt aus seiner initializeScript-Methode zurückgeben sollte, anstatt dies im Imperativen zu tun. Jedes Skript, das Änderungen vornimmt, muss eine uninitializeScript-Methode haben, um Bereinigungen durchzuführen. Ein optionaler Modulname und eine optionale Version können die Registrierung einschränken. Versionen werden als Zeichenfolgen im Format "1.2.3.4" angegeben.

Diagnosefunktionen

Der Diagnose-Unternamespace des Hostobjekts enthält Folgendes.

Name Unterschrift Aktuelle Phase BESCHREIBUNG
debugLog debugLog(object...) 1 Dadurch wird printf-Stil-Debuggen für eine Skripterweiterung bereitgestellt. Derzeit wird die Ausgabe aus debugLog an die Ausgabekonsole des Debuggers weitergeleitet. Zu einem späteren Zeitpunkt gibt es Pläne, das Routing dieser Ausgabe flexibel zu gestalten. HINWEIS: Dies sollte nicht als Mittel zum Drucken der Benutzerausgabe in der Konsole verwendet werden. Es kann in Zukunft nicht dorthin geleitet werden.

Speicherfunktionalität

Der Speicher-Unternamespace des Hostobjekts enthält Folgendes.

Name Unterschrift Aktuelle Phase BESCHREIBUNG
SpeicherwerteLesen

readMemoryValues(Speicherort, AnzahlDerElemente, [Elementgröße], [istSigniert], [KontextErbe])

2 Dadurch wird ein unformatiertes Array von Werten aus dem Adressraum des Debugziels gelesen und ein typiertes Array in der Ansicht dieses Speichers platziert. Die angegebene Position kann eine Adresse (ein 64-Bit-Wert), ein Ortsobjekt oder ein systemeigener Zeiger sein. Die Größe des Arrays wird durch das numElements-Argument angegeben. Die Größe (und der Typ) jedes Elements des Arrays wird durch das optionale ElementSize und isSigned-Argumente angegeben. Wenn keine solchen Argumente angegeben werden, ist das Standardbyte (nicht signiert/ 1 Byte). Wenn das optionale contextInheritor-Argument angegeben wird, wird der Speicher im Kontext gelesen (z. B. Adressraum und Debugziel), der durch das Argument angegeben ist; andernfalls wird sie aus dem aktuellen Kontext des Debuggers gelesen. Beachten Sie, dass die Verwendung dieser Methode für 8-, 16- und 32-Bit-Werte dazu führt, dass eine schnell eingegebene Ansicht über dem Lesespeicher platziert wird. Die Verwendung dieser Methode für 64-Bit-Werte führt dazu, dass ein Array von 64-Bit-Bibliothekstypen erstellt wird, was erheblich teurer ist!
readString

readString(location; [contextInheritor])

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

2 Dadurch wird eine schmale (aktuelle Codepage)-Zeichenfolge aus dem Adressraum eines Debugziels gelesen, in UTF-16 konvertiert und das Ergebnis als JavaScript-Zeichenfolge zurückgegeben. Es kann eine Ausnahme auslösen, wenn der Speicher nicht gelesen werden konnte. Der angegebene Speicherort kann eine Adresse (ein 64-Bit-Wert), ein Speicherortobjekt oder ein systemeigenes Zeichen sein. Wenn das optionale contextInheritor-Argument angegeben wird, wird der Speicher im Kontext gelesen (z. B. Adressraum und Debugziel), der durch das Argument angegeben ist; andernfalls wird sie aus dem aktuellen Kontext des Debuggers gelesen. Wenn das optionale Längenargument angegeben wird, entspricht die Lesezeichenfolge der angegebenen Länge.
readWideString

readWideString(location; [contextInheritor])

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

2 Dadurch wird eine wide(UTF-16)-Zeichenfolge aus dem Adressraum eines Debugziels gelesen und das Ergebnis als JavaScript-Zeichenfolge zurückgegeben. Es kann eine Ausnahme auslösen, wenn der Speicher nicht gelesen werden konnte. Der angegebene Ort kann eine Adresse (ein 64-Bit-Wert), ein Standortobjekt oder ein einheimisches wchar_t sein. Wenn das optionale contextInheritor-Argument angegeben wird, wird der Speicher im Kontext gelesen (z. B. Adressraum und Debugziel), der durch das Argument angegeben ist; andernfalls wird sie aus dem aktuellen Kontext des Debuggers gelesen. Wenn das optionale Längenargument angegeben wird, entspricht die Lesezeichenfolge der angegebenen Länge.

Datenmodellkonzepte in JavaScript

Datenmodellzuordnung

Die folgenden Datenmodellkonzepte sind JavaScript zugeordnet.

Begriff Native Schnittstelle JavaScript-Entsprechung
Zeichenfolgenkonvertierung IStringDarstellbaresKonzept Standard: toString(...){...}
Iterierbarkeit IIterableConcept standard: [Symbol.iterator](){...}
Indizierbarkeit IIndexableConcept Protokoll: getDimensionality(...) / getValueAt(...) / setValueAt(...)
Laufzeittypkonvertierung IPreferredRuntimeTypeConcept Protokoll: getPreferredRuntimeTypedObject(...)

Zeichenfolgenkonvertierung

Das Zeichenfolgenkonvertierungskonzept (IStringDisplayableConcept) entspricht direkt der JavaScript-toString-Methode. Da alle JavaScript-Objekte eine Zeichenfolgenkonvertierung aufweisen (sofern nicht an anderer Stelle bereitgestellt), kann jedes javaScript-Objekt, das an das Datenmodell zurückgegeben wird, in eine Anzeigezeichenfolge konvertiert werden. Zum Überschreiben der Zeichenfolgenkonvertierung müssen Sie lediglich Ihre eigene toString-Methode implementieren.

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

Iterierbarkeit

Das Konzept des Datenmodells, ob ein Objekt iterierbar ist oder nicht, wird direkt dem ES6-Protokoll zugeordnet, ob ein Objekt iterierbar ist. Jedes Objekt mit einer [Symbol.iterator]-Methode wird als iterierbar betrachtet. Durch die Implementierung dieser Objekte kann das Objekt iterierbar werden.

Ein Objekt, das nur iterierbar ist, kann eine Implementierung wie folgt aufweisen.

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";
    }
}

Für Objekte, die sowohl iterierbar als auch indiziert werden können, müssen besondere Überlegungen berücksichtigt werden, da die vom Iterator zurückgegebenen Objekte den Index sowie den Wert über einen speziellen Rückgabetyp enthalten müssen.

Iterable und indizierbar

Ein Objekt, das iterierbar und indiziert werden kann, erfordert einen speziellen Rückgabewert vom Iterator. Anstatt die Werte zurückzugeben, liefert der Iterator Instanzen von indexedValue. Die Indicies werden als Array im zweiten Argument an den indexedValue-Konstruktor übergeben. Sie können mehrdimensional sein, müssen aber mit der im Indexerprotokoll zurückgegebenen Dimensionalität übereinstimmen.

Dieser Code zeigt eine Beispielimplementierung.

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]);
    }
}

Indizierbarkeit

Im Gegensatz zu JavaScript macht das Datenmodell eine sehr explizite Differenzierung zwischen Eigenschaftszugriff und Indizierung. Jedes JavaScript-Objekt, das sich im Datenmodell als indizierbar präsentieren möchte, muss ein Protokoll implementieren, das aus einer getDimensionality-Methode besteht, die die Dimensionalität des Indexers und ein optionales Paar von getValueAt- und setValueAt-Methoden zurückgibt, die Lese- und Schreibvorgänge des Objekts an den angegebenen Indicies ausführen. Es ist zulässig, die Methoden "getValueAt" oder "setValueAt" auszulassen, wenn das Objekt entweder schreibgeschützt oder schreibbar ist.

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;
    }
}

Laufzeittypkonvertierung

Dies ist nur für JavaScript-Prototypen/Klassen relevant, die gegen ein Typsystem (natives) Typen registriert sind. Der Debugger ist häufig in der Lage, Analysen durchzuführen (z. B. Run-Time Typinformation (RTTI) / v-Table-Analyse), um den tatsächlichen Laufzeittyp eines Objekts aus einem statischen Typ zu bestimmen, der im Code ausgedrückt wird. Ein Datenmodell, das gegen einen systemeigenen Typ registriert ist, kann dieses Verhalten durch eine Implementierung des IPreferredRuntimeTypeConcept überschreiben. Ebenso kann eine für ein systemeigenes Objekt registrierte JavaScript-Klasse oder ein Prototyp eine eigene Implementierung über die Implementierung eines Protokolls bereitstellen, das aus der getPreferredRuntimeTypedObject-Methode besteht.

Beachten Sie, dass diese Methode zwar technisch etwas zurückgeben kann, es jedoch als schlechte Praxis angesehen wird, etwas zurückzugeben, das nicht wirklich der Laufzeittyp oder ein abgeleiteter Typ ist. Dies kann zu erheblichen Verwirrungen für Benutzer des Debuggers führen. Das Überschreiben dieser Methode kann jedoch bei Aspekten wie C-Style Header- und Objektimplementierungsstilen hilfreich sein usw.

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);
    }
}

Siehe auch

native Debuggerobjekte in JavaScript-Erweiterungen

Native Debugger-Objekte in JavaScript-Erweiterungen – Entwurfs- und Testüberlegungen

JavaScript-Debugging-Skripting

JavaScript-Debuggerbeispielskripts