Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym temacie opisano dodatkowe szczegóły dotyczące używania natywnych obiektów debugera w rozszerzeniach języka JavaScript.
Natywne obiekty debugera reprezentują różne konstrukcje i zachowania środowiska debugera. Obiekty można przekazać do rozszerzeń języka JavaScript (lub uzyskanych w nich), aby zarządzać stanem debugera.
Aby uzyskać informacje o rozszerzeniach JavaScript obiektu debugera, zobacz Native Debugger Objects in JavaScript Extensions (Natywne obiekty debugera w rozszerzeniach języka JavaScript).
Aby uzyskać ogólne informacje na temat pracy z językiem JavaScript, zobacz JavaScript Debugger Scripting (Skrypty debugera języka JavaScript).
Na przykład skrypty i rozszerzenia języka JavaScript zespół debugera hostuje repozytorium GitHub pod adresem https://github.com/Microsoft/WinDbg-Samples.
Obiekty debugera w rozszerzeniach języka JavaScript
Przekazywanie obiektów natywnych
Obiekty debugera można przekazywać lub uzyskiwać w rozszerzeniach języka JavaScript na różne sposoby.
- Mogą być przekazywane do funkcji lub metod języka JavaScript
- Mogą być obiektami instancji prototypu JavaScript (na przykład jako wizualizator)
- Można je zwrócić z metod wykonywanych przez hosta, zaprojektowanych w celu utworzenia natywnych obiektów debugera
- Można je zwrócić z metod hosta zaprojektowanych do tworzenia natywnych obiektów debugera.
Obiekty debugera przekazywane do rozszerzenia JavaScript mają zestaw funkcji opisanych w tej sekcji.
- Dostęp do właściwości
- Przewidywane nazwy
- Typy specjalne dotyczące obiektów natywnego debugera
- Dodatkowe atrybuty
Dostęp do właściwości
Chociaż istnieją pewne właściwości obiektów, które są umieszczane przez samego dostawcę języka JavaScript, większość właściwości na obiekcie natywnym, który wprowadza kod JavaScript, są dostarczane przez model danych. Oznacza to, że w przypadku dostępu do właściwości --- object.propertyName lub object[propertyName] wystąpią następujące elementy.
- Jeśli propertyName jest nazwą właściwości rzutowanej na obiekt przez dostawcę JavaScript, będzie najpierw rozpoznana jako ta właściwość; w przeciwnym razie
- Jeśli propertyName to nazwa klucza przewidywanego na obiekt przez model danych (inny wizualizator), zostanie rozpoznana jako druga nazwa; inaczej
- Jeśli propertyName jest nazwą pola obiektu natywnego, zostanie rozpoznana jako trzecia nazwa; inaczej
- Jeśli obiekt jest wskaźnikiem, wskaźnik będzie dereferencjonowany, a powyższy cykl będzie kontynuowany (przewidywana właściwość obiektu dereferencjonowanego, a następnie klucz, a następnie pole natywne)
Normalne środki dostępu do właściwości w języku JavaScript - object.propertyName i object[propertyName] - będą uzyskiwać dostęp do podstawowych pól natywnych obiektu, podobnie jak polecenie "dx" w debugerze.
Przewidywane nazwy
Następujące właściwości (i metody) są projektowane na obiektach natywnych, które wchodzą w kod JavaScript.
| Metoda | Podpis | Opis |
|---|---|---|
| hostContext | Majątek | Zwraca obiekt reprezentujący kontekst, w którym znajduje się obiekt (przestrzeń adresowa, obiekt docelowy debugowania itp.) |
| targetLocation (lokalizacja celu) | Majątek | Zwraca obiekt, który jest abstrakcją miejsca, w którym obiekt znajduje się w przestrzeni adresowej (adres wirtualny, rejestr, rejestr podrzędny itp.) |
| targetSize (rozmiar docelowy) | Majątek | Zwraca rozmiar obiektu (skutecznie: sizeof(<TYP OBIEKTU>) |
| addParentModel | .addParentModel(object) | Dodaje nowy model nadrzędny (taki jak prototyp języka JavaScript, ale po stronie modelu danych) do obiektu |
| removeParentModel | .removeParentModel(object) | Usuwa dany model nadrzędny z obiektu |
| runtimeTypedObject | Majątek | Wykonuje analizę obiektu i próbuje przekonwertować go na typ środowiska uruchomieniowego (najbardziej pochodnego) |
| typ celu | Majątek | Rozszerzenia języka JavaScript mają bezpośredni dostęp do systemu typów języka bazowego. Ten dostęp jest wyrażany za pośrednictwem pojęcia obiektów typu. Aby uzyskać więcej informacji, zobacz Native Debugger Objects in JavaScript Extensions - Type Objects (Obiekty natywnego debugera w rozszerzeniach Języka JavaScript — obiekty typu) |
Jeśli obiekt jest wskaźnikiem, następujące właściwości (i metody) są rzutowane na wskaźnik, który wprowadza kod JavaScript:
| Nazwa właściwości | Podpis | Opis |
|---|---|---|
| dodawać | .add(value) | Wykonuje dodawanie wskaźników matematycznych między wskaźnikiem a określoną wartością |
| adres | Majątek | Zwraca adres wskaźnika jako obiekt porządkowy 64-bitowy (typ biblioteki) |
| wyłuskanie | .dereference() | Wyłusza wskaźnik i zwraca obiekt źródłowy |
| isNull | Majątek | Zwraca, czy wartość wskaźnika ma wartość nullptr (0) |
Typy specjalne dotyczące obiektów natywnego debugera
Obiekty lokalizacji
Obiekt location zwracany z właściwości targetLocation obiektu natywnego zawiera następujące właściwości (i metody).
| Nazwa właściwości | Podpis | Opis |
|---|---|---|
| dodawać | .add(value) | Dodaje bezwzględne przesunięcie bajtu do lokalizacji. |
| odejmować | .subtract(wartość) | Odejmuje bezwzględne przesunięcie bajtu od lokalizacji. |
Dodatkowe atrybuty
Iterowalność (Iterability)
Każdy obiekt, który jest rozumiany jako iterowany przez model danych (jest natywną tablicą lub ma wizualizator (NatVis lub inny), który sprawia, że jest iterowalny), będzie miał przypisaną funkcję iteratora (zgodnie z ES6 standardem Symbol.iterator). Oznacza to, że można iterować obiekt natywny w języku JavaScript w następujący sposób.
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++.
//
}
}
Indeksowalność
Obiekty, które są zrozumiałe jako indeksowalne w jednym wymiarze za pomocą liczb porządkowych (np. natywne tablice), będą indeksowalne w JavaScript przy użyciu standardowego operatora dostępu do właściwości -- object[index]. Jeśli obiekt można indeksować według nazwy lub jest indeksowalny w więcej niż jednym wymiarze, metody getValueAt i setValueAt będą projektowane na obiekt, aby kod JavaScript mógł korzystać z indeksatora.
function indexNative(nativeArray)
{
var first = nativeArray[0];
}
Konwersja ciągu
Każdy obiekt macierzysty, który ma konwersję ciągu wyświetlania za pośrednictwem obsługi interfejsu IStringDisplayableConcept lub elementu NatVis DisplayString, będzie miał tę konwersję ciągów dostępną za pośrednictwem standardowej metody toString języka JavaScript.
function stringifyNative(nativeObject)
{
var myString = nativeObject.toString();
}
Tworzenie obiektów natywnego debugera
Jak wspomniano, skrypt języka JavaScript może uzyskać dostęp do obiektów natywnych przez przekazanie ich do języka JavaScript na jeden z kilku sposobów lub może utworzyć je za pośrednictwem wywołań do biblioteki hostów. Użyj następujących funkcji, aby utworzyć natywne obiekty debugera.
| Metoda | Podpis | Opis |
|---|---|---|
host.getModuleSymbol |
getModuleSymbol(nazwaModułu, nazwaSymbolu, [contextInheritor]) getModuleSymbol(moduleName, symbolName, [typeName], [contextInheritor]) |
Zwraca obiekt symbolu globalnego w określonym module. Nazwa modułu i nazwa symbolu to ciągi. Jeśli zostanie podany opcjonalny argument contextInheritor , moduł i symbol zostaną wyszukane w tym samym kontekście (przestrzeni adresowej, celu debugowania) co przekazany obiekt. Jeśli argument nie zostanie podany, moduł i symbol zostaną wyszukane w bieżącym kontekście debugera. Rozszerzenie języka JavaScript, które nie jest jednorazowym skryptem testowym, zawsze powinno dostarczać jawny kontekst. Jeśli zostanie podany opcjonalny argument typeName , przyjmuje się, że symbol będzie typu przekazywanego, a typ wskazany w symbolach zostanie zignorowany. Należy pamiętać, że każdy wywołujący, który oczekuje operacji na symbolach publicznych modułu, powinien zawsze podać jawną nazwę typu. |
host.getModuleContainingSymbol |
getModuleContainingSymbol(location, [contextInheritor]) | Zwraca symbol (np. funkcja lub dane), który zawiera dany adres. Należy pamiętać, że będzie to działać tylko wtedy, gdy dla modułu zawierającego dany adres znajdują się prywatne symbole. Jeśli zostanie podany opcjonalny argument contextInheritor , moduł i symbol zostaną wyszukane w tym samym kontekście (przestrzeni adresowej, celu debugowania) co przekazany obiekt. Jeśli argument nie zostanie podany, moduł i symbol zostaną wyszukane w obecnym kontekście debugera. Rozszerzenie języka JavaScript, które nie jest jednorazowym skryptem testowym, zawsze powinno dostarczać jawny kontekst. |
host.createPointerObject |
createPointerObject(address, moduleName, typeName, [contextInheritor]) |
Tworzy obiekt wskaźnika pod określonym adresem lub lokalizacją. Nazwa modułu i nazwa typu są ciągami. Jeśli zostanie podany opcjonalny argument contextInheritor , moduł i symbol zostaną wyszukane w tym samym kontekście (przestrzeni adresowej, celu debugowania) co przekazany obiekt. Jeśli argument nie zostanie podany, moduł i symbol zostaną automatycznie wyszukane w bieżącym kontekście debugera. Rozszerzenie języka JavaScript, które nie jest jednorazowym skryptem testowym, zawsze powinno dostarczać jawny kontekst. |
host.createTypedObject |
createTypedObject(location, moduleName, typeName, [contextInheritor]) |
Tworzy obiekt, który reprezentuje rodzimy typizowany obiekt znajdujący się w przestrzeni adresowej docelowego obiektu debugowania w określonej lokalizacji. Nazwa modułu i nazwa typu są ciągami. Jeśli zostanie podany opcjonalny argument contextInheritor , moduł i symbol zostaną wyszukane w tym samym kontekście (przestrzeni adresowej, celu debugowania) co przekazany obiekt. Jeśli argument nie zostanie podany, moduł i symbol zostaną wyszukane w bieżącym kontekście debugera. Rozszerzenie języka JavaScript, które nie jest jednorazowym skryptem testowym, zawsze powinno dostarczać jawny kontekst. |
Interfejsy API hosta dla rozszerzeń języka JavaScript
Dostawca języka JavaScript wstawia obiekt o nazwie host do globalnej przestrzeni nazw każdego ładowanego skryptu. Ten obiekt zapewnia dostęp do krytycznych funkcji skryptu oraz dostępu do przestrzeni nazw debugera. Jest on konfigurowany w dwóch fazach.
Faza 1: Przed wykonaniem skryptu obiekt hosta zawiera tylko minimalny zestaw funkcji niezbędnych do zainicjowania skryptu i zarejestrowania punktów rozszerzalności (zarówno jako producenta, jak i konsumenta). Kod główny i inicjalizacji nie jest przeznaczony do manipulowania stanem obiektu docelowego debugowania lub wykonywania złożonych operacji, a w związku z tym host nie jest w pełni wypełniany, dopóki nie zostanie zwrócona metoda initializeScript.
Faza 2. Po zainicjowaniu koduScript obiekt hosta jest wypełniany wszystkimi elementami niezbędnymi do manipulowania stanem obiektów docelowych debugowania.
Poziom obiektu hosta
Kilka kluczowych elementów funkcjonalności znajdują się bezpośrednio pod obiektem hosta. Pozostałe są przestrzeniami nazw podrzędnych. Przestrzenie nazw obejmują następujące elementy.
| Namespace | Opis |
|---|---|
| Diagnostyka | Funkcje ułatwiające diagnozowanie i debugowanie kodu skryptu |
| pamięć | Funkcje umożliwiające odczytywanie i zapisywanie pamięci w obiekcie docelowym debugowania |
Poziom główny
Bezpośrednio w obiekcie hosta można znaleźć następujące właściwości, metody i konstruktory.
| Nazwa | Podpis | Faza obecna | Opis |
|---|---|---|---|
| stwórzObiektWskaźnikowy | createPointerObject(address, moduleName, typeName, [contextInheritor]) |
2 | Tworzy obiekt wskaźnika pod określonym adresem lub lokalizacją. Nazwa modułu i nazwa typu są ciągami. Opcjonalny argument contextInheritor działa podobnie jak w przypadku polecenia getModuleSymbol. |
| createTypedObject | createTypedObject(location, moduleName, typeName, [contextInheritor]) |
2 | Tworzy obiekt, który reprezentuje rodzimy typizowany obiekt znajdujący się w przestrzeni adresowej docelowego obiektu debugowania w określonej lokalizacji. Nazwa modułu i nazwa typu są ciągami. Opcjonalny argument contextInheritor działa podobnie jak w przypadku polecenia getModuleSymbol. |
| aktualnyProces | Majątek |
2 | Zwraca obiekt reprezentujący bieżący proces debugera |
| bieżącaSesja | Majątek |
2 | Zwraca obiekt reprezentujący bieżącą sesję debugera (który element docelowy, zrzut itp.) jest debugowany |
| bieżącyWątek | Majątek |
2 | Zwraca obiekt reprezentujący bieżący wątek debugera |
| evaluateExpression | evaluateExpression(wyrażenie, [contextInheritor]) |
2 | To powoduje wywołanie hosta debugowania w celu oceny wyrażenia, używając jedynie języka docelowego debugowania. Jeśli zostanie podany opcjonalny argument contextInheritor , wyrażenie zostanie obliczone w kontekście (np. przestrzeń adresowa i element docelowy debugowania) argumentu; w przeciwnym razie zostanie on oceniony w bieżącym kontekście debugera |
| evaluateExpressionInContext | ocenaWyrażeniaWKontekście(context, expression) |
2 | Spowoduje to wywołanie hosta debugowania w celu oceny wyrażenia przy użyciu wyłącznie języka celu debugowania. Argument kontekstu wskazuje niejawny wskaźnik this do wykorzystania przy ocenie. Wyrażenie zostanie ocenione w kontekście (np. przestrzeni adresowej i celu debugowania) wskazanym przez argument kontekstu. |
| getModuleSymbol | getModuleSymbol(nazwaModułu, nazwaSymbolu, [contextInheritor]) |
2 | Zwraca obiekt symbolu globalnego w określonym module. Nazwa modułu i nazwa symbolu to ciągi. Jeśli zostanie podany opcjonalny argument contextInheritor , moduł i symbol zostaną wyszukane w tym samym kontekście (przestrzeni adresowej, celu debugowania) co przekazany obiekt. Jeśli argument nie zostanie podany, moduł i symbol zostaną wyszukane w bieżącym kontekście debugera. Rozszerzenie języka JavaScript, które nie jest jednorazowym skryptem, zawsze powinno podawać jawny kontekst |
| getNamedModel | getNamedModel(modelName) |
2 | Zwraca model danych, który został zarejestrowany pod daną nazwą. Należy pamiętać, że jest całkowicie legalne użycie tego dla nazwy, która nie jest jeszcze zarejestrowana. Spowoduje to utworzenie atrapy dla tej nazwy, a wszelkie manipulacje na atrapie zostaną zastosowane do rzeczywistego obiektu podczas rejestracji. |
| wartość indeksowana | new indexedValue(value, indicies) |
2 | Konstruktor dla obiektu, który można zwrócić z iteratora JavaScript, aby przypisać domyślny zestaw indeksów do iterowanej wartości. Zestaw wskaźników musi być wyrażony jako tablica Języka JavaScript. |
| Int64 | new Int64(value, [highValue]) |
1 | Tworzy bibliotekę typu Int64. Wersja pojedynczego argumentu przyjmie dowolną wartość, którą można umieścić bezpośrednio w Int64 (bez konwersji). Jeśli zostanie podany opcjonalny drugi argument, konwersja pierwszego argumentu jest pakowana w dolne 32 bity, a drugiego argumentu w górne 32 bity. |
| namedModelParent | new namedModelParent(object, name) |
1 | Konstruktor obiektu, który ma zostać umieszczony w tablicy zwróconej z initializeScript, to oznacza użycie prototypu JavaScript lub klasy ES6 jako nadrzędnego rozszerzenia modelu danych o podanej nazwie. |
| namedModelRegistration | new namedModelRegistration(object, name) |
1 | Konstruktor obiektu, który ma zostać umieszczony w tablicy zwróconej z initializeScript, reprezentuje rejestrację prototypu JavaScript lub klasy ES6 jako modelu danych pod znaną nazwą, aby inne rozszerzenia mogły ją znaleźć i rozszerzyć. |
| obszar nazw | Majątek |
2 | Zapewnia bezpośredni dostęp do korzeniowej przestrzeni nazw debugera. Można na przykład uzyskać dostęp do listy procesów pierwszego obiektu docelowego debugowania za pośrednictwem host.namespace.Debugger.Sessions.First(). Procesy korzystające z tej właściwości |
| registerNamedModel | registerNamedModel(object, modelName) |
2 | Spowoduje to zarejestrowanie prototypu języka JavaScript lub klasy ES6 jako modelu danych pod daną nazwą. Taka rejestracja umożliwia zlokalizowanie i rozszerzenie prototypu lub klasy przez inne skrypty lub inne rozszerzenia debugera. Należy pamiętać, że skrypt powinien preferować zwracanie obiektu o nazwieModelRegistration z jego metody initializeScript zamiast robić to imperatywnie. Każdy skrypt, który wprowadza zmiany, musi posiadać metodę initializeScript w celu wyczyszczenia. |
| zarejestrujRozszerzenieDlaSygnaturyTypu | registerExtensionForTypeSignature(object, typeSignature) |
2 | Rejestruje to prototyp języka JavaScript lub klasę ES6 jako model danych rozszerzenia dla typu natywnego określonego przez podany podpis typu. Należy pamiętać, że skrypt powinien preferować zwracanie obiektu typeSignatureExtension z jego metody initializeScript zamiast robić to imperatywnie. Każdy skrypt, który wprowadza zmiany imperatywnie, musi posiadać metodę initializeScript do wyczyszczenia. |
| registerPrototypeForTypeSignature | zarejestrujPrototypDlaPodpisuTypu(obiekt, podpisTypu) |
2 | Spowoduje to zarejestrowanie prototypu języka JavaScript lub klasy ES6 jako kanonicznego modelu danych (np. wizualizatora) dla typu natywnego podanego przez podany podpis typu. Należy pamiętać, że skrypt powinien preferować zwracanie obiektu typeSignatureRegistration z jego metody initializeScript zamiast robić to imperatywnie. Każdy skrypt, który wprowadza zmiany, musi mieć metodę uninitializeScript do czyszczenia. |
| parseInt64 | parseInt64(string, [radix]) |
1 | Ta metoda działa podobnie do standardowej metody javaScript parseInt, z tą różnicą, że zwraca ona zamiast tego typ biblioteki Int64. Jeśli podana jest podstawa, parsowanie odbędzie się w systemie liczbowym 2, 8, 10 lub 16, jak wskazano. |
| typSygnaturaRozszerzenie | new typeSignatureExtension(object, typeSignature, [moduleName], [minVersion], [maxVersion]) |
1 | Konstruktor obiektu, który ma zostać umieszczony w tablicy zwróconej przez initializeScript, reprezentuje rozszerzenie typu natywnego opisanego za pomocą sygnatury typu przez prototyp JavaScript lub klasę ES6. Tego rodzaju rejestracja "dodaje pola" do wizualizacji debugera dla dowolnego typu, który pasuje do sygnatury, zamiast całkowicie ją przejmować. Opcjonalna nazwa i wersja modułu mogą ograniczyć rejestrację. Wersje są określane jako ciągi stylu "1.2.3.4". |
| typeSignatureRegistration | new typeSignatureRegistration(object, typeSignature, [moduleName], [minVersion], [maxVersion]) |
1 | Konstruktor obiektu, który ma zostać umieszczony w tablicy zwróconej z initializeScript, reprezentuje kanoniczną rejestrację prototypu JavaScript lub klasy ES6 dla natywnego podpisu typu. Taka rejestracja "przejmuje" wizualizację debugera dowolnego typu, który pasuje do podpisu, zamiast jedynie rozszerzać jego funkcjonalność. Opcjonalna nazwa i wersja modułu mogą ograniczyć rejestrację. Wersje są określane jako ciągi stylu "1.2.3.4". |
| unregisterNamedModel | unregisterNamedModel(modelName) |
2 | Spowoduje to wyrejestrowanie modelu danych z wyszukiwania według podanej nazwy cofającej dowolną operację wykonywaną przez registerNamedModel |
| wyrejestrowaćRozszerzenieDlaPodpisuTypu | unregisterExtensionForTypeSignature(object, typeSignature, [moduleName], [minVersion], [maxVersion]) |
2 | Spowoduje to wyrejestrowanie prototypu JavaScript lub klasy ES6 jako modelu danych rozszerzenia dla natywnego typu określonego przez dostarczony podpis typu. Jest to logiczne cofnięcie funkcji registerExtensionForTypeSignature. Należy pamiętać, że skrypt powinien preferować zwracanie obiektu typeSignatureExtension z jego metody initializeScript zamiast robić to imperatywnie. Każdy skrypt, który wprowadza zmiany imperatywnie, musi posiadać metodę initializeScript do wyczyszczenia. Opcjonalna nazwa i wersja modułu mogą ograniczyć rejestrację. Wersje są określane jako ciągi stylu "1.2.3.4". |
| wyrejestrowaćPrototypeDlaPodpisuTypu | unregisterPrototypeForTypeSignature(object, typeSignature, [moduleName], [minVersion], [maxVersion]) |
2 | Powoduje to wyrejestrowanie prototypu JavaScript lub klasy ES6 jako kanonicznego modelu danych (np. wizualizatora) dla natywnego typu określonego przez dostarczony podpis typu. Jest to logiczne cofnięcie operacji registerPrototypeForTypeSignature. Należy pamiętać, że skrypt powinien preferować zwracanie obiektu typeSignatureRegistration z jego metody initializeScript zamiast robić to imperatywnie. Każdy skrypt, który wprowadza zmiany, musi mieć metodę dezinicjalizacji skryptu do czyszczenia. Opcjonalna nazwa i wersja modułu mogą ograniczyć rejestrację. Wersje są określane jako ciągi stylu "1.2.3.4". |
Funkcje diagnostyki
Podprzestrzeń nazw diagnostyki obiektu hosta zawiera następujące elementy.
| Nazwa | Podpis | Faza obecna | Opis |
|---|---|---|---|
| dziennik debugowania | debugLog(obiekt...) | 1 | Zapewnia to debugowanie stylu printf w rozszerzeniu skryptu. Obecnie dane wyjściowe z debugLog są kierowane do konsoli wyjściowej debugera. W późniejszym momencie istnieją plany zapewnienia elastyczności routingu tych danych wyjściowych. UWAGA: Nie należy jej używać jako środka drukowania danych wyjściowych użytkownika do konsoli. Może nie być kierowany tam w przyszłości. |
Funkcjonalność pamięci
Podnazwa pamięci obiektu hosta zawiera następujące elementy.
| Nazwa | Podpis | Faza obecna | Opis |
|---|---|---|---|
| readMemoryValues | readMemoryValues(lokalizacja, liczbaElementów, [rozmiarElementu], [czyPodpisane], [kontekstDziedziczący]) |
2 | Spowoduje to odczytanie surowej tablicy wartości z przestrzeni adresowej obiektu docelowego debugowania i umieszczenie typowanej tablicy na widoku tej pamięci. Podana lokalizacja może być adresem (wartością 64-bitową), obiektem lokalizacji lub wskaźnikiem natywnym. Rozmiar tablicy jest wskazywany przez argument numElements . Rozmiar (i typ) każdego elementu tablicy jest określany przez opcjonalne argumenty elementSize i isSigned. Jeśli nie podano żadnych takich argumentów, wartość domyślna to bajt (bez znaku /1 bajt). Jeśli zostanie podany opcjonalny argument contextInheritor, pamięć będzie odczytywana w kontekście wskazanym przez ten argument (np. przestrzeń adresowa i cel debugowania); w przeciwnym razie zostanie odczytana z bieżącego kontekstu debugera. Należy pamiętać, że użycie tej metody na wartościach 8, 16 i 32-bitowych powoduje umieszczenie szybkiego widoku typowego nad pamięcią odczytywaną. Użycie tej metody na wartościach 64-bitowych powoduje utworzenie tablicy 64-bitowych typów bibliotek, co jest znacznie droższe! |
| readString | readString(location, [contextInheritor]) readString(lokalizacja, [length], [contextInheritor]) |
2 | Spowoduje to odczytanie wąskiego ciągu (bieżącej strony kodowej) z przestrzeni adresowej obiektu docelowego debugowania, przekonwertowanie go na utF-16 i zwrócenie wyniku jako ciągu języka JavaScript. Może zgłosić wyjątek, jeśli nie można odczytać pamięci. Podana lokalizacja może być adresem (wartością 64-bitową), obiektem lokalizacji lub natywnym znakiem. Jeśli zostanie podany opcjonalny argument contextInheritor, pamięć będzie odczytywana w kontekście wskazywanym przez ten argument (np. przestrzeń adresowa i element docelowy debugowania); w przeciwnym razie odczyt nastąpi z bieżącego kontekstu debugera. Jeśli zostanie podany opcjonalny argument długości , ciąg odczytu będzie mieć określoną długość. |
| readWideString | readWideString(lokalizacja, [contextInheritor]) readWideString(lokalizacja, [length], [contextInheritor]) |
2 | Odczytuje to szeroki ciąg (UTF-16) z przestrzeni adresowej obiektu docelowego debugowania i zwraca wynik jako ciąg JavaScript. Może wystąpić wyjątek, jeśli pamięci nie można odczytać. Podana lokalizacja może być adresem (wartością 64-bitową), obiektem lokalizacji lub natywnym wchar_t. Jeśli zostanie podany opcjonalny argument contextInheritor, pamięć będzie odczytywana w kontekście (np. przestrzeń adresowa i cel debugowania) wskazywanym przez argument; w przeciwnym razie będzie odczytywana z bieżącego kontekstu debugera. Jeśli zostanie podany opcjonalny argument długości , ciąg odczytu będzie mieć określoną długość. |
Pojęcia dotyczące modelu danych w języku JavaScript
Mapowanie modelu danych
Poniższe pojęcia modelu danych odpowiadają językowi JavaScript.
| Pojęcie | Interfejs macierzysty | Odpowiednik języka JavaScript |
|---|---|---|
| Konwersja ciągu | IStringDisplayableConcept | standard: toString(...){...} |
| Iterowalność | IIterableConcept | standard: [Symbol.iterator](){...} |
| Indeksowanie | IIndexableConcept | protokół: getDimensionality(...) / getValueAt(...) / setValueAt(...) |
| Konwersja typu środowiska uruchomieniowego | IPreferredRuntimeTypeConcept | protokół: getPreferredRuntimeTypedObject(...) |
Konwersja ciągu
Koncepcja konwersji ciągów (IStringDisplayableConcept) bezpośrednio przekłada się na standardową metodę JavaScript toString . Ponieważ wszystkie obiekty Języka JavaScript mają konwersję ciągu (dostarczoną przez obiekt Object.prototype, jeśli nie podano gdzie indziej), każdy obiekt JavaScript zwrócony do modelu danych może zostać przekonwertowany na ciąg wyświetlania. Zastąpienie konwersji ciągu znaków wymaga po prostu zaimplementowania własnej metody toString.
class myObject
{
//
// This method will be called whenever any native code calls IStringDisplayableConcept::ToDisplayString(...)
//
toString()
{
return "This is my own string conversion!";
}
}
Iterowalność (Iterability)
Koncepcja modelu danych dotycząca tego, czy obiekt jest iterowalny, czy nie, odpowiada bezpośrednio protokołowi ES6 w kwestii iterowalności obiektu. Każdy obiekt, który ma metodę [Symbol.iterator], jest uważany za iterowalny. Implementacja tego typu sprawi, że obiekt będzie iterowalny.
Obiekt, który jest tylko iterowalny, może mieć implementację, taką jak poniżej.
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";
}
}
Należy zwrócić szczególną uwagę na obiekty, które są zarówno iterowalne, jak i indeksowalne, ponieważ obiekty zwracane z iteratora muszą zawierać indeks, a także wartość za pośrednictwem specjalnego typu zwracanego.
Iterowalne i indeksowalne
Obiekt, który jest iterowalny i indeksowalny, wymaga specjalnej wartości zwracanej z iteratora. Zamiast zwracać wartości, iterator zwraca wystąpienia obiektu IndexedValue. Indeksy są przekazywane jako tablica w drugim argumencie do konstruktora indexedValue. Mogą być wielowymiarowe, ale muszą być zgodne z wymiarowością zwracaną w protokole indeksatora.
Ten kod przedstawia przykładową implementację.
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]);
}
}
Indeksowalność
W przeciwieństwie do języka JavaScript, model danych wyraźnie rozróżnia pomiędzy dostępem do właściwości a indeksowaniem. Każdy obiekt JavaScript, który chce przedstawić się jako indeksowalny w modelu danych, musi zaimplementować protokół składający się z metody getDimensionality, która zwraca wymiarowość indeksatora i opcjonalną parę metod getValueAt i setValueAt, które wykonują odczyty i zapisy obiektu w podanych danych. Dopuszczalne jest pominięcie metod getValueAt lub setValueAt, jeśli obiekt jest tylko do odczytu lub tylko do zapisu
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;
}
}
Konwersja typu środowiska uruchomieniowego
Dotyczy to tylko prototypów/klas języka JavaScript zarejestrowanych w typach systemowych (natywnych). Debuger jest często w stanie przeprowadzić analizę (np. Run-Time informacje o typie (RTTI) / analiza tabeli v- w celu określenia rzeczywistego typu środowiska uruchomieniowego obiektu ze statycznego typu wyrażonego w kodzie. Model danych zarejestrowany względem typu natywnego może zastąpić to zachowanie za pomocą implementacji interfejsu IPreferredRuntimeTypeConcept. Podobnie klasa JavaScript lub prototyp zarejestrowany względem obiektu natywnego może zapewnić własną implementację za pomocą implementacji protokołu, który zawiera metodę getPreferredRuntimeTypedObject.
Należy pamiętać, że chociaż ta metoda może technicznie zwrócić wszystko, jest uważana za nieprawidłową formę, aby zwrócić coś, co nie jest tak naprawdę typem środowiska uruchomieniowego ani typem pochodnym. Może to spowodować znaczne zamieszanie dla użytkowników debugera. Zastąpienie tej metody może jednak być cenne dla takich elementów jak nagłówek w stylu C i style obiektów implementacji itp.
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);
}
}
Zobacz również
natywnych obiektów debugera w rozszerzeniach Języka JavaScript