Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este tópico descreve detalhes adicionais sobre como usar os objetos de depurador nativos em extensões JavaScript.
Os objetos nativos do depurador representam várias construções e comportamentos do ambiente do depurador. Os objetos podem ser passados para (ou adquiridos em) extensões JavaScript para manipular o estado do depurador.
Para obter informações sobre extensões JavaScript de objeto de depurador, consulte Objetos de depurador nativos em extensões JavaScript.
Para obter informações gerais sobre como trabalhar com JavaScript, consulte JavaScript Debugger Scripting.
Por exemplo, para scripts e extensões JavaScript, a equipa do depurador hospeda o repositório GitHub em https://github.com/Microsoft/WinDbg-Samples.
Objetos do depurador em extensões JavaScript
Passando objetos nativos
Os objetos do depurador podem ser passados ou adquiridos em extensões JavaScript de várias maneiras.
- Eles podem ser passados para funções ou métodos JavaScript
- Eles podem ser o objeto de instância para um protótipo JavaScript (como um visualizador, por exemplo)
- Eles podem ser retornados de métodos de host projetados para criar objetos depuradores nativos
- Eles podem ser retornados de métodos de host projetados para criar objetos nativos do depurador
Os objetos do depurador que são passados para uma extensão JavaScript têm um conjunto de funcionalidades descrito nesta seção.
- Acesso à propriedade
- Nomes projetados
- Tipos especiais associados a objetos de debugger nativos
- Atributos adicionais
Acesso à propriedade
Embora existam algumas propriedades em objetos que são colocados lá pelo próprio provedor JavaScript, a maioria das propriedades em um objeto nativo que entra em JavaScript são fornecidas pelo modelo de dados. Isso significa que, para um acesso de propriedade — object.propertyName ou object[propertyName] — ocorrerá o seguinte.
- Se propertyName for o nome de uma propriedade projetada no objeto pelo próprio provedor JavaScript, esta será a primeira a ser resolvida; caso contrário,
- Se propertyName for o nome de uma chave projetada no objeto pelo modelo de dados (outro Visualizador), ele será resolvido para esse nome em segundo lugar; caso contrário,
- Se propertyName for o nome de um campo do objeto nativo, ele será resolvido para esse terceiro nome; caso contrário,
- Se o objeto for um ponteiro, o ponteiro será desreferenciado e o ciclo acima continuará (uma propriedade projetada do objeto desreferenciado seguida por uma chave seguida por um campo nativo)
Os meios normais de acesso à propriedade em JavaScript -- object.propertyName e object[propertyName] -- acessarão os campos nativos subjacentes de um objeto, da mesma forma que o comando 'dx' dentro do depurador.
Nomes projetados
As seguintes propriedades (e métodos) são projetadas em objetos nativos que entram em JavaScript.
| Método | Assinatura | Descrição |
|---|---|---|
| hostContext | Propriedade | Retorna um objeto que representa o contexto em que o objeto está (o espaço de endereço, o destino de depuração, etc...) |
| DestinoLocalização | Propriedade | Retorna um objeto que é uma abstração de onde o objeto está dentro de um espaço de endereço (endereço virtual, registro, sub-registro, etc...) |
| targetSize | Propriedade | Retorna o tamanho do objeto (efetivamente: sizeof(<TIPO DE OBJETO>)) |
| addParentModel | .addParentModel(objeto) | Adiciona um novo modelo pai (semelhante a um protótipo JavaScript, mas no lado do modelo de dados) ao objeto |
| removeParentModel | .removeParentModel(objeto) | Remove um determinado modelo pai do objeto |
| ObjetoTipadoEmTempoDeExecução | Propriedade | Executa a análise no objeto e tenta convertê-lo para o tipo mais derivado em tempo de execução. |
| Tipo de destino | Propriedade | As extensões JavaScript têm acesso direto ao sistema de tipos da linguagem subjacente. Este acesso é expresso através da noção de objetos tipo. Para obter mais informações, consulte Native Debugger Objects in JavaScript Extensions - Type Objects |
Se o objeto for um ponteiro, as seguintes propriedades (e métodos) serão projetadas no ponteiro que insere JavaScript:
| Nome da propriedade | Assinatura | Descrição |
|---|---|---|
| adicionar | .add(valor) | Executa a adição matemática do ponteiro entre o ponteiro e o valor especificado |
| Endereço | Propriedade | Retorna o endereço do ponteiro como um objeto ordinal de 64 bits (um tipo de biblioteca) |
| desreferenciação | .dereference() | Anula a referência do ponteiro e retorna o objeto subjacente |
| isNull | Propriedade | Retorna se o valor do ponteiro é ou não nullptr (0) |
Tipos especiais pertencentes a objetos de depurador nativos
Objetos de localização
O objeto location que é retornado da propriedade targetLocation de um objeto nativo contém as seguintes propriedades (e métodos).
| Nome da propriedade | Assinatura | Descrição |
|---|---|---|
| adicionar | .add(valor) | Adiciona um deslocamento absoluto de bytes à localização. |
| subtrair | .subtrair(valor) | Subtrai um deslocamento absoluto de bytes da posição. |
Atributos adicionais
Iterabilidade
Qualquer objeto que seja entendido como iterável pelo modelo de dados (é uma matriz nativa ou tem um visualizador (NatVis ou outro) que o torna iterável) terá uma função iteradora (indexada através do padrão ES6 Symbol.iterator) colocada sobre ele. Isso significa que você pode iterar um objeto nativo em JavaScript da seguinte maneira.
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++.
//
}
}
Indexabilidade
Objetos que são entendidos como indexáveis em uma dimensão via ordinais (por exemplo: matrizes nativas) serão indexáveis em JavaScript através do operador de acesso à propriedade padrão -- object[index]. Se um objeto for indexável por nome ou for indexável em mais de uma dimensão, os métodos getValueAt e setValueAt serão projetados no objeto para que o código JavaScript possa utilizar o indexador.
function indexNative(nativeArray)
{
var first = nativeArray[0];
}
Conversão de String
Qualquer objeto nativo que tenha uma conversão de sequência de exibição através do suporte de IStringDisplayableConcept ou de um elemento DisplayString NatVis terá essa conversão acessível por meio do método padrão toString do JavaScript.
function stringifyNative(nativeObject)
{
var myString = nativeObject.toString();
}
Criando objetos de depurador nativos
Como mencionado, um script JavaScript pode obter acesso a objetos nativos fazendo-os passar para JavaScript de uma das várias maneiras ou pode criá-los por meio de chamadas para a biblioteca do host. Use as seguintes funções para criar objetos de depurador nativos.
| Método | Assinatura | Descrição |
|---|---|---|
host.getModuleSymbol |
getModuleSymbol(moduleName, symbolName, [contextInheritor]) getModuleSymbol(moduleName, symbolName, [typeName], [contextInheritor]) |
Retorna um objeto para um símbolo global dentro de um módulo específico. O nome do módulo e o nome do símbolo são cadeias de caracteres. Se o argumento opcional contextInheritor for fornecido, o módulo e o símbolo serão procurados dentro do mesmo contexto (espaço de endereço, destino de depuração) que o objeto fornecido. Se o argumento não for fornecido, o módulo e o símbolo serão pesquisados no contexto atual do depurador. Uma extensão JavaScript que não seja um script de teste único deve sempre fornecer um contexto explícito. Se o argumento typeName opcional for fornecido, o símbolo será assumido como sendo do tipo passado e o tipo indicado no(s) símbolo(s) será ignorado. Observe que qualquer chamador que espera operar em símbolos públicos para um módulo deve sempre fornecer um nome de tipo explícito. |
host.getModuleContainingSymbol |
getModuleContainingSymbol(localização, [contextInheritor]) | Devolve o símbolo (por exemplo: função ou dados) que contém o endereço fornecido. Observe que isso só funcionará se houver símbolos privados para o módulo que contém o endereço fornecido. Se o argumento opcional contextInheritor for fornecido, o módulo e o símbolo serão pesquisados dentro do mesmo contexto (espaço de endereço, alvo de depuração) que o objeto passado. Se o argumento não for fornecido, o módulo e o símbolo serão pesquisados no contexto atual do depurador. Uma extensão JavaScript que não seja um script de teste único deve sempre fornecer um contexto explícito. |
host.createPointerObject |
createPointerObject(endereço, moduleName, typeName, [contextInheritor]) |
Cria um objeto de ponteiro no endereço ou local especificado. O nome do módulo e o nome do tipo são strings. Se o argumento opcional contextInheritor for fornecido, o módulo e o símbolo serão pesquisados no mesmo contexto (espaço de endereço, alvo de depuração) que o objeto passado. Se o argumento não for fornecido, o módulo e o símbolo serão pesquisados no contexto atual do depurador. Uma extensão JavaScript que não seja um script de teste único deve sempre fornecer um contexto explícito. |
host.createTypedObject |
createTypedObject(location, moduleName, typeName, [contextInheritor]) |
Cria um objeto que representa um objeto tipado nativo dentro do espaço de endereço de um alvo de depuração num local especificado. O nome do módulo e o nome do tipo são strings. Se o argumento opcional contextInheritor for fornecido, o módulo e o símbolo serão pesquisados dentro do mesmo contexto (espaço de endereço, alvo de depuração) que o objeto passado. Se o argumento não for fornecido, o módulo e o símbolo serão pesquisados no contexto atual do depurador. Uma extensão JavaScript que não seja um script de teste único deve sempre fornecer um contexto explícito. |
APIs de host para extensões JavaScript
O provedor JavaScript insere um objeto chamado host no namespace global de cada script que carrega. Este objeto fornece acesso à funcionalidade crítica para o script, bem como acesso ao namespace do depurador. Articula-se em duas fases.
Fase 1: Antes de qualquer script ser executado, o objeto host contém apenas o conjunto mínimo de funcionalidades necessárias para que um script se inicialize e registre seus pontos de extensibilidade (como produtor e consumidor). O código raiz e de inicialização não se destina a manipular o estado de um destino de depuração ou executar operações complexas e, como tal, o host não é totalmente preenchido até que o método initializeScript retorne.
Fase 2: Depois que initializeScript retorna, o objeto host é preenchido com tudo o que é necessário para manipular o estado dos destinos de depuração.
Nível de objeto do host
Algumas peças-chave de funcionalidade estão diretamente sob o objeto host. O restante é sub-namespaced. Os namespaces incluem o seguinte.
| Namespace | Descrição |
|---|---|
| Diagnóstico | Funcionalidade para auxiliar no diagnóstico e depuração de código de script |
| memória | Funcionalidade para habilitar a leitura e gravação de memória em um destino de depuração |
Nível de raiz
Diretamente no objeto host, as seguintes propriedades, métodos e construtores podem ser encontrados.
| Nome | Assinatura | Fase Presente | Descrição |
|---|---|---|---|
| criarObjetoPonteiro | createPointerObject(endereço, moduleName, typeName, [contextInheritor]) |
2 | Cria um objeto de ponteiro no endereço ou local especificado. O nome do módulo e o nome do tipo são strings. O argumento opcional contextInheritor funciona como getModuleSymbol. |
| criarObjetoTipado | createTypedObject(location, moduleName, typeName, [contextInheritor]) |
2 | Cria um objeto que representa um objeto tipado nativo dentro do espaço de endereço de um alvo de depuração num local especificado. O nome do módulo e o nome do tipo são strings. O argumento opcional contextInheritor funciona como getModuleSymbol. |
| processo atual | Propriedade |
2 | Retorna o objeto que representa o processo atual do depurador |
| sessãoAtual | Propriedade |
2 | Devolve o objeto que representa a sessão atual do depurador, incluindo o destino, o dump, entre outros, que está a ser depurado. |
| currentThread | Propriedade |
2 | Retorna o objeto que representa o thread atual do depurador |
| evaluateExpression | evaluateExpression(expressão, [contextInheritor]) |
2 | Isso chama o host de depuração para avaliar uma expressão usando apenas o idioma do destino de depuração. Se o argumento contextInheritor for fornecido, a expressão será avaliada no contexto (por exemplo: espaço de endereço e destino de depuração) do argumento; caso contrário, será avaliada no contexto atual do depurador |
| evaluateExpressionInContext | evaluateExpressionInContext(contexto, expressão) |
2 | Isso chama o host de depuração para avaliar uma expressão usando apenas o idioma do destino de depuração. O argumento de contexto indica o implícito que este ponteiro deve utilizar para a avaliação. A expressão será avaliada no contexto (por exemplo: espaço de endereço e alvo de depuração) indicado pelo argumento context. |
| obterSímboloDoMódulo | getModuleSymbol(moduleName, symbolName, [contextInheritor]) |
2 | Retorna um objeto para um símbolo global dentro de um módulo específico. O nome do módulo e o nome do símbolo são cadeias de caracteres. Se o argumento opcional contextInheritor for fornecido, o módulo e o símbolo serão pesquisados dentro do mesmo contexto (espaço de endereço, alvo de depuração) que o objeto passado. Se o argumento não for fornecido, o módulo e o símbolo serão pesquisados no contexto atual do depurador. Uma extensão JavaScript que não seja um script único deve sempre fornecer um contexto explícito |
| getNamedModel | getNamedModel(nome_modelo) |
2 | Retorna o modelo de dados que foi registrado em relação a um determinado nome. Note-se que é perfeitamente legal aplicá-lo a um nome que ainda não está registado. Fazer isso criará uma representação para esse nome e as manipulações da representação serão aplicadas ao objeto real no momento do registro. |
| valor indexado | new indexedValue(valor, índices) |
2 | Um construtor para um objeto que pode ser retornado de um iterador JavaScript para atribuir um conjunto padrão de índices ao valor iterado. O conjunto de índices deve ser expresso como uma matriz JavaScript. |
| Int64 | novo Int64(value, [highValue]) |
1 | Isso constrói um tipo de biblioteca Int64. A versão com um único argumento aceitará qualquer valor que possa ser embalado num Int64 (sem conversão) e colocará o valor no mesmo. Se um segundo argumento opcional for fornecido, uma conversão do primeiro argumento será empacotada nos 32 bits inferiores e uma conversão do segundo argumento será empacotada nos 32 bits superiores. |
| nomedModelParent | new namedModelParent(objeto, nome) |
1 | Um construtor para um objeto destinado a ser colocado na matriz retornada de initializeScript. Isso representa o uso de um protótipo JavaScript ou de uma classe ES6 como extensão de um modelo de dados pai para um modelo de dados com o nome fornecido. |
| namedModelRegistration | new namedModelRegistration(objeto, nome) |
1 | Um construtor para um objeto destinado a ser colocado na matriz retornada de initializeScript, isso representa o registro de um protótipo JavaScript ou classe ES6 como um modelo de dados através de um nome conhecido para que outras extensões possam localizar e estender |
| espaço de nomes | Propriedade |
2 | Dá acesso direto ao namespace raiz do depurador. Pode-se, por exemplo, acessar a lista de processos do primeiro destino de depuração via host.namespace.Debugger.Sessions.First(). Processos usando esta propriedade |
| registerNamedModel | registerNamedModel(objeto, modelName) |
2 | Isso registra um protótipo JavaScript ou classe ES6 como um modelo de dados sob o nome próprio. Tal registro permite que o protótipo ou classe seja localizado e estendido por outros scripts ou outras extensões do depurador. Observe que um script deve preferir retornar um objeto namedModelRegistration de seu método initializeScript em vez de fazer isso imperativamente. Qualquer script que faça alterações imperativamente é necessário ter um método initializeScript para limpar. |
| registerExtensionForTypeSignature | registerExtensionForTypeSignature(objeto, typeSignature) |
2 | Isso registra um protótipo JavaScript ou classe ES6 como um modelo de dados de extensão para um tipo nativo, conforme fornecido pela assinatura de tipo fornecida. Observe que um script deve preferir retornar um objeto typeSignatureExtension de seu método initializeScript em vez de fazer isso imperativamente. Qualquer script que faça alterações imperativamente é necessário ter um método initializeScript para limpar. |
| registerPrototypeForTypeSignature | registerPrototypeForTypeSignature(objeto, typeSignature) |
2 | Isso registra um protótipo JavaScript ou classe ES6 como o modelo de dados canônico (por exemplo: visualizador) para um tipo nativo, conforme fornecido pela assinatura de tipo fornecida. Observe que um script deve preferir retornar um objeto typeSignatureRegistration de seu método initializeScript em vez de fazer isso imperativamente. Qualquer script que faça alterações imperativamente é necessário ter um método uninitializeScriptpara limpar. |
| parseInt64 | parseInt64(string, [radix]) |
1 | Esse método age de forma semelhante ao método padrão JavaScript parseInt, exceto que ele retorna um tipo Int64 biblioteca em vez disso. Se um radix for fornecido, a análise ocorrerá na base 2, 8, 10 ou 16, conforme indicado. |
| extensãoDeAssinaturaDeTipo | new typeSignatureExtension(objeto, typeSignature, [moduleName], [minVersion], [maxVersion]) |
1 | Um construtor para um objeto destinado a ser colocado na matriz retornada de initializeScript, isso representa uma extensão de um tipo nativo descrito por meio de uma assinatura de tipo por um protótipo JavaScript ou classe ES6. Tal registo "adiciona campos" à visualização do depurador de qualquer tipo que corresponda à assinatura, em vez de substituí-la completamente. Um nome de módulo opcional e uma versão podem restringir o registo. As versões são especificadas como cadeias de caracteres de estilo "1.2.3.4". |
| tipoAssinaturaRegistro | new typeSignatureRegistration(objeto, typeSignature, [moduleName], [minVersion], [maxVersion]) |
1 | Um construtor para um objeto destinado a ser colocado na matriz retornada de initializeScript, isso representa um registro canônico de um protótipo JavaScript ou classe ES6 em relação a uma assinatura de tipo nativa. Tal registro toma o controlo da visualização feita pelo depurador de qualquer tipo que corresponda à assinatura, em vez de simplesmente estendê-la. Um nome de módulo opcional e uma versão podem restringir o registo. As versões são especificadas como cadeias de caracteres de estilo "1.2.3.4". |
| unregisterNamedModel | unregisterNamedModel(modelName) |
2 | Isso revoga o registo de um modelo de dados para pesquisa pelo nome especificado, desfazendo qualquer operação executada por registerNamedModel |
| desregistarExtensãoParaAssinaturaDeTipo | unregisterExtensionForTypeSignature(objeto, assinaturaTipo, [nomeMódulo], [versãoMínima], [versãoMáxima]) |
2 | Isso cancela o registo de um protótipo JavaScript ou classe ES6 como modelo de dados de extensão para um tipo nativo, conforme a assinatura de tipo especificada. É o desfazer lógico de registerExtensionForTypeSignature. Observe que um script deve preferir retornar um objeto typeSignatureExtension de seu método initializeScript em vez de fazer isso imperativamente. Qualquer script que faça alterações imperativamente é necessário ter um método initializeScript para limpar. Um nome de módulo opcional e uma versão podem restringir o registo. As versões são especificadas como cadeias de caracteres de estilo "1.2.3.4". |
| unregisterPrototypeForTypeSignature | unregisterPrototypeForTypeSignature(objeto, typeSignature, [moduleName], [minVersion], [maxVersion]) |
2 | Isso cancela o registro de um protótipo JavaScript ou classe ES6 como modelo de dados canônico (por exemplo: visualizador) para um tipo nativo, conforme a assinatura de tipo fornecida. É a reversão lógica da função registerPrototypeForTypeSignature. Observe que um script deve preferir retornar um objeto typeSignatureRegistration de seu método initializeScript em vez de fazer isso imperativamente. Qualquer script que faça alterações imperativamente é necessário ter um método uninitializeScript para limpar. Um nome de módulo opcional e uma versão podem restringir o registo. As versões são especificadas como cadeias de caracteres de estilo "1.2.3.4". |
Funcionalidade de diagnóstico
O subnamespace de diagnóstico do objeto host contém o seguinte.
| Nome | Assinatura | Fase Presente | Descrição |
|---|---|---|---|
| debugLog | debugLog(objeto...) | 1 | Isso fornece depuração de estilo printf para uma extensão de script. No momento, a saída de debugLog é roteada para o console de saída do depurador. Em um momento posterior, há planos para fornecer flexibilidade no roteamento dessa saída. Observação : isso não deve ser usado como um meio de imprimir a saída do usuário para o console. Pode não ser encaminhado para lá no futuro. |
Funcionalidade de memória
O subnamespace de memória do objeto host contém o seguinte.
| Nome | Assinatura | Fase Presente | Descrição |
|---|---|---|---|
| readMemoryValues | readMemoryValues(location, numElements, [elementSize], [isSigned], [contextInheritor]) |
2 | Isso lê uma matriz bruta de valores do espaço de endereço do destino de depuração e coloca uma matriz digitada na parte superior da exibição dessa memória. O local fornecido pode ser um endereço (um valor de 64 bits), um objeto de local ou um ponteiro nativo. O tamanho da matriz é indicado pelo argumento numElements . O tamanho (e tipo) de cada elemento da matriz é dado pelos argumentos opcionais elementSize e isSigned . Se esses argumentos não forem fornecidos, o padrão será byte (não assinado / 1 byte). Se o argumento opcional contextInheritor for fornecido, a memória será lida no contexto (por exemplo: espaço de endereço e destino de depuração) indicado pelo argumento; caso contrário, será lido a partir do contexto atual do depurador. Observe que o uso desse método em valores de 8, 16 e 32 bits resulta em uma exibição digitada rápida sendo colocada sobre a memória de leitura. Usar esse método em valores de 64 bits resulta em uma matriz de tipos de biblioteca de 64 bits sendo construída, o que é significativamente mais caro! |
| readString | readString(localização, [contextInheritor]) readString(localização, [tamanho], [herdeiroDeContexto]) |
2 | Isso lê uma cadeia de caracteres estreita (página de código atual) do espaço de endereço de um destino de depuração, converte-a em UTF-16 e retorna o resultado como uma cadeia de caracteres JavaScript. Ele pode lançar uma exceção se a memória não pôde ser lida. O local fornecido pode ser um endereço (um valor de 64 bits), um objeto de local ou um char nativo. Se o argumento opcional contextInheritor for fornecido, a memória será lida no contexto (por exemplo: espaço de endereço e destino de depuração) indicado pelo argumento; caso contrário, será lido a partir do contexto atual do depurador. Se o argumento de comprimento opcional for fornecido, a cadeia de caracteres de leitura será do comprimento especificado. |
| readWideString | readWideString(localização, [contextInheritor]) readWideString(localização, [comprimento], [herdeiroDeContexto]) |
2 | Isso lê uma cadeia de caracteres em formato wide (UTF-16) do espaço de endereço de um alvo de depuração e retorna o resultado como uma cadeia de caracteres JavaScript. Ele pode lançar uma exceção se a memória não pôde ser lida. O local fornecido pode ser um endereço (um valor de 64 bits), um objeto de local ou um wchar_t nativo. Se o argumento opcional contextInheritor for fornecido, a memória será lida no contexto (por exemplo: espaço de endereço e destino de depuração) indicado pelo argumento; caso contrário, será lido a partir do contexto atual do depurador. Se o argumento de comprimento opcional for fornecido, a cadeia de caracteres de leitura será do comprimento especificado. |
Conceitos de modelo de dados em JavaScript
Mapeamento de modelo de dados
Os seguintes conceitos de modelo de dados correspondem a JavaScript.
| Conceito | Interface nativa | JavaScript Equivalente |
|---|---|---|
| Conversão de cadeia de caracteres | IStringDisplayableConcept | padrão: toString(...){...} |
| Iterabilidade | IIterableConcept | padrão: [Symbol.iterator](){...} |
| Indexabilidade | IIndexableConcept | protocolo: getDimensionality(...) / getValueAt(...) / setValueAt(...) |
| Conversão de tipo de tempo de execução | IPreferredRuntimeTypeConcept (conceito de tipo de tempo de execução preferido) | protocolo: getPreferredRuntimeTypedObject(...) |
Conversão de String
O conceito de transformação de cadeia de caracteres (IStringDisplayableConcept) traduz-se diretamente para o método padrão toString do JavaScript. Como todos os objetos JavaScript têm uma conversão de cadeia de caracteres (fornecida por Object.prototype se não for fornecida em outro lugar), cada objeto JavaScript retornado ao modelo de dados pode ser convertido em uma cadeia de caracteres de exibição. Substituir a conversão de cadeia de caracteres simplesmente requer a implementação de seu próprio toString.
class myObject
{
//
// This method will be called whenever any native code calls IStringDisplayableConcept::ToDisplayString(...)
//
toString()
{
return "This is my own string conversion!";
}
}
Iterabilidade
O conceito do modelo de dados de se um objeto é iterável ou não é mapeado diretamente para o protocolo ES6 de se um objeto é iterável. Qualquer objeto que tenha um método [Symbol.iterator] é considerado iterável. A implementação de tal tornará o objeto iterável.
Um objeto que é apenas iterável pode ter uma implementação como a seguinte.
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";
}
}
Atenção especial deve ser dada para objetos que são iteráveis e indexáveis, pois os objetos retornados do iterador devem incluir o índice, bem como o valor por meio de um tipo de retorno especial.
Iterável e indexável
Um objeto que é iterável e indexável requer um valor de retorno especial do iterador. Em vez de produzir os valores, o iterador produz instâncias de indexedValue. Os índices são passados como uma matriz no segundo argumento para o construtor indexedValue. Eles podem ser multidimensionais, mas devem corresponder à dimensionalidade retornada no protocolo indexador.
Este código mostra um exemplo de implementação.
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]);
}
}
Indexabilidade
Ao contrário do JavaScript, o modelo de dados faz uma diferenciação muito explícita entre acesso à propriedade e indexação. Qualquer objeto JavaScript que deseje apresentar-se como indexável no modelo de dados deve implementar um protocolo que consiste em um método getDimensionality que retorna a dimensionalidade do indexador e um par opcional de métodos getValueAt e setValueAt que executam leituras e gravações do objeto nos índices fornecidos. É aceitável omitir os métodos getValueAt ou setValueAt se o objeto for somente leitura ou somente gravação
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;
}
}
Conversão de tipo durante a execução
Isso só é relevante para protótipos/classes JavaScript que são registrados em tipos de sistema de tipo (nativos). O depurador é muitas vezes capaz de executar análises (por exemplo, Run-Time Type Information (RTTI) / v-table analysis) para determinar o verdadeiro tipo de tempo de execução de um objeto a partir de um tipo estático expresso em código. Um modelo de dados registrado em relação a um tipo nativo pode substituir esse comportamento por meio de uma implementação do IPreferredRuntimeTypeConcept. Da mesma forma, uma classe JavaScript ou protótipo registrado em um objeto nativo pode fornecer sua própria implementação por meio da implementação de um protocolo que consiste no método getPreferredRuntimeTypedObject.
Observe que, embora este método possa tecnicamente retornar qualquer coisa, é considerado má prática retornar algo que não seja realmente o tipo em tempo de execução ou um tipo derivado. Isso pode resultar em confusão significativa para os usuários do depurador. Substituir este método pode, no entanto, ser valioso para elementos como cabeçalho estilo C, estilos de implementação de objetos, etc...
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);
}
}
Ver também
objetos depuradores nativos em extensões JavaScript
Objetos de depurador nativos em extensões JavaScript - Considerações de design e teste
Depuração com Script em JavaScript
Scripts de exemplo do depurador JavaScript