Freigeben über


Native Debuggerobjekte in JavaScript-Erweiterungen – Debuggerobjektdetails

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

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

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

Allgemeine Informationen zum Arbeiten mit JavaScript finden Sie unter JavaScript-Debuggerskripting.

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

Debuggerobjekte in JavaScript-Erweiterungen

Übergeben nativer Objekte

Debuggerobjekte können auf verschiedene Arten an JavaScript-Erweiterungen übergeben oder in diese abgerufen werden.

  • Sie können an JavaScript-Funktionen oder -Methoden übergeben werden.
  • Sie können das instance-Objekt für einen JavaScript-Prototyp sein (als Visualizer für instance).
  • Sie können von Hostmethoden zurückgegeben werden, die zum Erstellen von nativen Debuggerobjekten entwickelt wurden.
  • Sie können von Hostmethoden zurückgegeben werden, die zum Erstellen nativer 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 für native Debuggerobjekte
  • Zusätzliche Attribute

Eigenschaftszugriff

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

  • Wenn propertyName der Name einer Eigenschaft ist, die vom JavaScript-Anbieter selbst auf das Objekt projiziert wurde, wird zuerst in diesen 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 aufgelöst. Andernfalls
  • Wenn propertyName der Name eines Felds des systemeigenen Objekts ist, wird es in diesen Namen third aufgelöst. Andernfalls
  • 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 Mittel des Eigenschaftenzugriffs in JavaScript -- object.propertyName und object[propertyName] -- greifen auf die zugrunde liegenden nativen Felder eines Objekts zu, ähnlich wie der Dx-Befehl im Debugger.

Projizierte Namen

Die folgenden Eigenschaften (und Methoden) werden auf native Objekte projiziert, die in JavaScript eingegeben werden.

Methode Signatur BESCHREIBUNG
hostContext Eigenschaft Gibt ein Objekt zurück, das den Kontext darstellt, in dem sich das Objekt befindet (Adressraum, Debugziel usw.).
targetLocation Eigenschaft Gibt ein Objekt zurück, das eine Abstraktion dessen ist, wo sich das Objekt innerhalb eines Adressraums befindet (virtuelle Adresse, Registrierung, Unterregistrierung usw.)
targetSize Eigenschaft Gibt die Größe des Objekts zurück (effektiv: sizeof(<TYPE OF OBJECT>)
addParentModel .addParentModel(object) Fügt dem Objekt ein neues übergeordnetes Modell hinzu (ähnlich einem JavaScript-Prototyp, aber auf der Datenmodellseite).
removeParentModel .removeParentModel(object) Entfernt ein bestimmtes übergeordnetes Modell aus dem -Objekt.
runtimeTypedObject Eigenschaft Führt eine Analyse für das Objekt durch und versucht, es in den Runtimetyp (am meisten abgeleitet) zu konvertieren.
targetType Eigenschaft JavaScript-Erweiterungen haben direkten Zugriff auf das Typsystem der zugrunde liegenden Sprache. Dieser Zugriff wird durch den Begriff typobjekte ausgedrückt. Weitere Informationen finden Sie unter Native Debugger-Objekte in JavaScript-Erweiterungen – Typobjekte.

Wenn es sich bei dem Objekt um einen Zeiger handelt, werden die folgenden Eigenschaften (und Methoden) auf den Zeiger projiziert, der javaScript wechselt:

Eigenschaftenname Signatur BESCHREIBUNG
add .add(value) Führt das Hinzufügen der Zeiger mathematisch zwischen dem Zeiger und dem angegebenen Wert aus.
address Eigenschaft Gibt die Adresse des Zeigers als 64-Bit-Ordnungsobjekt (bibliothekstyp) zurück.
Dereferenzieren .dereference() Leitet den Zeiger ab und gibt das zugrunde liegende Objekt zurück.
Isnull Eigenschaft Gibt zurück, ob der Zeigerwert nullptr (0) ist oder nicht.

Spezielle Typen für native Debuggerobjekte

Location-Objekte

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

Eigenschaftenname Signatur BESCHREIBUNG
add .add(value) Fügt dem Speicherort einen absoluten Byteoffset hinzu.
Subtrahieren .subtract(value) Subtrahiert einen absoluten Byteoffset von der Position.

Zusätzliche Attribute

Iterierbarkeit

Jedes Objekt, das vom Datenmodell als iterierbar verstanden wird (es ist ein natives Array oder es verfügt über einen Visualizer (NatVis oder anders), der es iterierbar macht), verfügt über eine Iteratorfunktion (die über den ES6-Standardsymbol.iterator indiziert wird). Dies bedeutet, dass Sie ein natives 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 Ordnungszahlen (z. B. native Arrays) als indizierbar verstanden werden, können in JavaScript über den Standard-Eigenschaftenzugriffsoperator -- object[index] indiziert werden. Wenn ein Objekt nach Name 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

Für jedes native Objekt, das über eine Anzeigezeichenfolgenkonvertierung über die Unterstützung von IStringDisplayableConcept oder ein NatVis DisplayString-Element verfügt, kann diese Zeichenfolgenkonvertierung über die Standardmäßige JavaScript toString-Methode zugänglich sein.

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

Erstellen von nativen Debuggerobjekten

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

Methode Signatur BESCHREIBUNG

host.getModuleSymbol

getModuleSymbol(moduleName, symbolName, [contextInheritor])

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 Modul und Symbol im gleichen Kontext (Adressraum, Debugziel) wie das übergebene Objekt gesucht. Wenn das Argument nicht angegeben wird, werden das Modul und das Symbol im aktuellen Kontext des Debuggers gesucht. 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 mit öffentlichen Symbolen für ein Modul arbeitet, immer einen expliziten Typnamen angeben 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 für das Modul private Symbole vorhanden sind, die die angegebene Adresse enthalten.

Wenn das optionale contextInheritor-Argument angegeben wird, werden Modul und Symbol im gleichen Kontext (Adressraum, Debugziel) wie das übergebene Objekt gesucht. Wenn das Argument nicht angegeben wird, werden das Modul und das Symbol im aktuellen Kontext des Debuggers gesucht. 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 contextInheritor-Argument angegeben wird, werden Modul und Symbol im gleichen Kontext (Adressraum, Debugziel) wie das übergebene Objekt gesucht. Wenn das Argument nicht angegeben wird, werden das Modul und das Symbol im aktuellen Kontext des Debuggers gesucht. 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 typisiertes Objekt im Adressraum eines Debugziels an der angegebenen Position darstellt. Der Modulname und der Typname sind Zeichenfolgen.

Wenn das optionale contextInheritor-Argument angegeben wird, werden Modul und Symbol im gleichen Kontext (Adressraum, Debugziel) wie das übergebene Objekt gesucht. Wenn das Argument nicht angegeben wird, werden das Modul und das Symbol im aktuellen Kontext des Debuggers gesucht. 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 namens host 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. Die Einrichtung erfolgt in zwei Phasen.

  • Phase 1: Bevor ein Skript ausgeführt wird, enthält das Hostobjekt nur den minimalen Funktionsumfang, der für ein Skript erforderlich ist, um sich selbst zu initialisieren und seine Erweiterbarkeitspunkte (sowohl als Producer als auch als Consumer) zu registrieren. Der Stamm- und Initialisierungscode ist nicht dazu bestimmt, den Zustand eines Debugziels zu ändern oder komplexe Vorgänge auszuführen. Daher wird der Host erst vollständig aufgefüllt, nachdem die initializeScript-Methode zurückgegeben wurde.

  • Phase 2: Nach der InitializeScript-Rückgabe wird das Hostobjekt mit allem aufgefüllt, was zum Ändern des Zustands von Debugzielen erforderlich ist.

Hostobjektebene

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

Namespace BESCHREIBUNG
Diagnose Funktionen zur Unterstützung bei der Diagnose und dem Debuggen von Skriptcode
Arbeitsspeicher Funktionalität zum Aktivieren des Lesens und Schreibens von Arbeitsspeicher in einem Debugziel

Stammebene

Direkt im Hostobjekt finden Sie die folgenden Eigenschaften, Methoden und Konstruktoren.

Name Signatur Phase vorhanden 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 typisiertes Objekt im Adressraum eines Debugziels an der angegebenen Position darstellt. Der Modulname und der Typname sind Zeichenfolgen. Das optionale contextInheritor-Argument funktioniert wie bei getModuleSymbol.
currentProcess

Eigenschaft

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

Eigenschaft

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

Eigenschaft

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

evaluateExpression(expression, [contextInheritor])

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

evaluateExpressionInContext(context, expression)

2 Dadurch wird der Debughost aufgerufen, um einen Ausdruck nur mithilfe der Sprache des Debugziels auszuwerten. Das Kontextargument gibt das implizite an, das dieser Zeiger für die Auswertung verwenden soll. Der Ausdruck wird im Kontext (z. B. Adressraum und Debugziel) ausgewertet, der durch das Kontextargument angegeben wird.
getModuleSymbol

getModuleSymbol(moduleName, symbolName, [contextInheritor])

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 Modul und Symbol im gleichen Kontext (Adressraum, Debugziel) wie das übergebene Objekt gesucht. Wenn das Argument nicht angegeben wird, werden das Modul und das Symbol im aktuellen Kontext des Debuggers gesucht. 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 angegebenen Namen registriert wurde. Beachten Sie, dass es völlig legal ist, dies für einen Namen zu nennen, der noch nicht registriert ist. Dadurch wird ein Stub für diesen Namen erstellt, und bei der Registrierung werden Bearbeitungen des Stubs am tatsächlichen Objekt vorgenommen.
indexedValue

new indexedValue(value, indicies)

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 Einzelargumentversion nimmt jeden Wert, der in einen Int64 (ohne Konvertierung) packen 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 dem von initializeScript zurückgegebenen Array platziert werden soll. Dies stellt die Verwendung eines JavaScript-Prototyps oder einer ES6-Klasse als übergeordnete Erweiterung eines Datenmodells eines Datenmodells mit dem angegebenen Namen dar.
namedModelRegistration

new namedModelRegistration(object, name)

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

Eigenschaft

2 Gewährt direkten Zugriff auf den Stammnamespace des Debuggers. Beispielsweise kann über host.namespace.Debugger.Sessions.First() auf die Prozessliste des ersten Debugziels zugegriffen werden. 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 zu finden und durch andere Skripts oder andere Debuggererweiterungen zu erweitern. Beachten Sie, dass ein Skript es vorziehen sollte, ein namedModelRegistration-Objekt von seiner initializeScript-Methode zurückzugeben, anstatt dies imperativ zu tun. Jedes Skript, das Änderungen zwingend vornimmt, muss über eine initializeScript-Methode verfügen, um sauber.
registerExtensionForTypeSignature

registerExtensionForTypeSignature(object, typeSignature)

2 Dadurch wird ein JavaScript-Prototyp oder eine ES6-Klasse als Erweiterungsdatenmodell für einen nativen Typ registriert, wie durch die angegebene Typsignatur angegeben. Beachten Sie, dass ein Skript es vorziehen sollte, ein typeSignatureExtension-Objekt von seiner initializeScript-Methode zurückzugeben, anstatt dies imperativ zu tun. Jedes Skript, das Änderungen zwingend vornimmt, muss über eine initializeScript-Methode verfügen, um sauber.
registerPrototypeForTypeSignature

registerPrototypeForTypeSignature(object, typeSignature)

2 Dadurch wird ein JavaScript-Prototyp oder eine ES6-Klasse als kanonisches Datenmodell (z. B. Visualizer) für einen nativen Typ registriert, wie in der angegebenen Typsignatur angegeben. Beachten Sie, dass ein Skript es vorziehen sollte, ein typeSignatureRegistration-Objekt von seiner initializeScript-Methode zurückzugeben, anstatt dies imperativ zu tun. Jedes Skript, das Änderungen zwingend vornimmt, muss über eine uninitializeScript-Methodeverfügen, um sauber.
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 Bibliothekstyp Int64 zurückgibt. Wenn ein Radix angegeben wird, tritt die Analyse entweder in Basis 2, 8, 10 oder 16 wie angegeben auf.
typeSignatureExtension

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

1 Ein Konstruktor für ein Objekt, das in dem von initializeScript zurückgegebenen Array platziert werden soll. Dies stellt 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.
typeSignatureRegistration

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

1 Ein Konstruktor für ein Objekt, das in das von initializeScript zurückgegebene Array eingefügt werden soll. Dies stellt eine kanonische Registrierung eines JavaScript-Prototyps oder einer ES6-Klasse für eine native Typsignatur dar. Eine solche Registrierung "übernimmt" die Visualisierung des Debuggers eines beliebigen Typs, der der Signatur entspricht, anstatt sie nur 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 Dadurch wird die Registrierung eines Datenmodells von der Suche nach dem angegebenen Namen aufgehoben und alle von registerNamedModel ausgeführten Vorgänge rückgängig gemacht.
unregisterExtensionForTypeSignature

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

2 Dadurch wird die Registrierung eines JavaScript-Prototyps oder einer ES6-Klasse als Erweiterungsdatenmodell für einen nativen Typ aufgehoben, wie in der angegebenen Typsignatur angegeben. Es ist das logische Rückgängigmachen von registerExtensionForTypeSignature. Beachten Sie, dass ein Skript es vorziehen sollte, ein typeSignatureExtension-Objekt von seiner initializeScript-Methode zurückzugeben, anstatt dies imperativ zu tun. Jedes Skript, das Änderungen zwingend vornimmt, muss über eine initializeScript-Methode verfügen, um sauber. 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 nativen Typ aufgehoben, wie in der angegebenen Typsignatur angegeben. Es ist das logische Rückgängigmachen von registerPrototypeForTypeSignature. Beachten Sie, dass ein Skript es vorziehen sollte, ein typeSignatureRegistration-Objekt von seiner initializeScript-Methode zurückzugeben, anstatt dies imperativ zu tun. Jedes Skript, das Änderungen zwingend vornimmt, muss über eine uninitializeScript-Methode verfügen, um sauber zu können. Ein optionaler Modulname und eine optionale Version können die Registrierung einschränken. Versionen werden als Zeichenfolgen im Format "1.2.3.4" angegeben.

Diagnosefunktionalität

Der Diagnose Unternamespace des Hostobjekts enthält Folgendes.

Name Signatur Phase vorhanden Beschreibung
debugLog debugLog(object...) 1 Dadurch wird das Debuggen im Printf-Format für eine Skripterweiterung bereitgestellt. Derzeit wird die Ausgabe von debugLog an die Ausgabekonsole des Debuggers weitergeleitet. Zu einem späteren Zeitpunkt ist geplant, flexibilität beim Routing dieser Ausgabe zu gewährleisten. HINWEIS: Dies sollte nicht als Mittel zum Drucken der Benutzerausgabe in der Konsole verwendet werden. Es wird möglicherweise in Zukunft nicht dorthin weitergeleitet.

Speicherfunktionalität

Der Speicherunternamespace des Hostobjekts enthält Folgendes.

Name Signatur Phase vorhanden Beschreibung
readMemoryValues

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

2 Dadurch wird ein unformatiertes Array von Werten aus dem Adressraum des Debugziels gelesen und ein typisiertes Array über der Ansicht dieses Arbeitsspeichers platziert. Der angegebene Speicherort kann eine Adresse (ein 64-Bit-Wert), ein Location-Objekt oder ein nativer Zeiger sein. Die Größe des Arrays wird durch das Argument numElements angegeben. Die Größe (und der Typ) jedes Elements des Arrays wird durch die optionalen Argumente elementSize und isSigned angegeben. Wenn keine solchen Argumente angegeben werden, ist der Standardwert Byte (unsigned / 1 Byte). Wenn das optionale argument contextInheritor angegeben wird, wird der Arbeitsspeicher im kontext (z. B. Adressraum und Debugziel) gelesen, der durch das Argument angegeben wird. Andernfalls wird es 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 schnelle typisierte Ansicht über den 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 deutlich teurer ist!
Readstring

readString(location, [contextInheritor])

readString(location, [length; [contextInheritor])

2 Dadurch wird eine schmale Zeichenfolge (aktuelle Codepage) aus dem Adressraum eines Debugziels gelesen, in UTF-16 konvertiert und das Ergebnis als JavaScript-Zeichenfolge zurückgegeben. Möglicherweise wird eine Ausnahme ausgelöst, wenn der Arbeitsspeicher nicht gelesen werden konnte. Der angegebene Speicherort kann eine Adresse (ein 64-Bit-Wert), ein Location-Objekt oder ein natives Zeichen sein. Wenn das optionale argument contextInheritor angegeben wird, wird der Arbeitsspeicher im kontext (z. B. Adressraum und Debugziel) gelesen, der durch das Argument angegeben wird. Andernfalls wird es aus dem aktuellen Kontext des Debuggers gelesen. Wenn das optionale Length-Argument angegeben wird, hat die Lesezeichenfolge die angegebene 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. Möglicherweise wird eine Ausnahme ausgelöst, wenn der Arbeitsspeicher nicht gelesen werden konnte. Der angegebene Speicherort kann eine Adresse (ein 64-Bit-Wert), ein Location-Objekt oder eine native wchar_t sein. Wenn das optionale argument contextInheritor angegeben wird, wird der Arbeitsspeicher im kontext (z. B. Adressraum und Debugziel) gelesen, der durch das Argument angegeben wird. Andernfalls wird es aus dem aktuellen Kontext des Debuggers gelesen. Wenn das optionale Length-Argument angegeben wird, hat die Lesezeichenfolge die angegebene Länge.

Datenmodellkonzepte in JavaScript

Datenmodellzuordnung

Die folgenden Datenmodellkonzepte sind JavaScript zugeordnet.

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

Zeichenfolgenkonvertierung

Das Zeichenfolgenkonvertierungskonzept (IStringDisplayableConcept) wird direkt in die Standardmäßige JavaScript toString-Methode übersetzt. Da alle JavaScript-Objekte über eine Zeichenfolgenkonvertierung verfügen (von Object.prototype bereitgestellt, wenn sie nicht an anderer Stelle bereitgestellt werden), kann jedes JavaScript-Objekt, das an das Datenmodell zurückgegeben wird, in eine Anzeigezeichenfolge konvertiert werden. Um die Zeichenfolgenkonvertierung zu überschreiben, müssen Sie einfach Eine eigene toString-Instanz 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, das über eine [Symbol.iterator]-Methode verfügt, gilt als iterierbar. Durch die Implementierung einer solchen wird das Objekt iterierbar.

Ein Objekt, das nur iterierbar ist, kann eine Implementierung wie die folgende 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";
    }
}

Besonderes Augenmerk muss auf Objekte gelegt werden, die sowohl iterierbar als auch indizierbar sind, da die vom Iterator zurückgegebenen Objekte sowohl den Index als auch den Wert über einen speziellen Rückgabetyp enthalten müssen.

Iterierbar und indizierbar

Ein Objekt, das iterierbar und indizierbar ist, erfordert einen speziellen Rückgabewert vom Iterator. Statt die Werte zu liefern, 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 der im Indexerprotokoll zurückgegebenen Dimensionalität entsprechen.

Dieser Code zeigt ein Beispiel für die Implementierung.

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 unterscheidet das Datenmodell sehr explizit 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 zurückgibt, und einem optionalen Paar von getValueAt- und setValueAt-Methoden, die Lese- und Schreibvorgänge des Objekts an den angegebenen Indicies ausführen. Es ist akzeptabel, entweder die getValueAt- oder setValueAt-Methode wegzulassen, wenn das Objekt schreibgeschützt oder schreibgeschützt 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 für typsystemeigene Typen registriert sind. Der Debugger ist häufig in der Lage, Analysen (z. B. Run-Time Type Information (RTTI) / V-Table-Analyse) durchzuführen, um den wahren Laufzeittyp eines Objekts aus einem statischen Typ zu ermitteln, der im Code ausgedrückt wird. Ein für einen nativen Typ registriertes Datenmodell kann dieses Verhalten über eine Implementierung von IPreferredRuntimeTypeConcept außer Kraft setzen. Ebenso kann eine für ein natives Objekt registrierte JavaScript-Klasse oder ein JavaScript-Prototyp eine eigene Implementierung über die Implementierung eines Protokolls bereitstellen, das aus der getPreferredRuntimeTypedObject-Methode besteht.

Beachten Sie, dass diese Methode zwar technisch gesehen alles zurückgeben kann, es aber als ungültig 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 für Dinge nützlich sein, z. B. für Header im C-Stil+ Objektstile der Implementierung 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 Debuggerobjekte in JavaScript-Erweiterungen : Überlegungen zu Entwurf und Test

JavaScript-Debuggerskripterstellung

Beispielskripts für JavaScript-Debugger