Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
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