Compartir a través de


Objetos de depurador nativos en extensiones de JavaScript: detalles del objeto del depurador

En este tema se describen detalles adicionales sobre el uso de los objetos de depurador nativos en extensiones de JavaScript.

Los objetos de depurador nativos representan diversas construcciones y comportamientos del entorno del depurador. Los objetos se pueden pasar a extensiones de JavaScript (o adquiridas en) para manipular el estado del depurador.

Para obtener información sobre las extensiones javaScript del objeto Debugger, vea Objetos de depurador nativos en extensiones de JavaScript.

Para obtener información general sobre cómo trabajar con JavaScript, consulte Scripting del depurador de JavaScript.

Por ejemplo, scripts y extensiones de JavaScript, el equipo del depurador hospeda un repositorio de GitHub en https://github.com/Microsoft/WinDbg-Samples.

Objetos del depurador en extensiones de JavaScript

Pasar objetos nativos

Los objetos del depurador se pueden pasar o adquirir en extensiones de JavaScript de varias maneras.

  • Se pueden pasar a funciones o métodos de JavaScript.
  • Pueden ser el objeto de instancia de un prototipo de JavaScript (como visualizador, por ejemplo)
  • Se pueden devolver desde métodos host diseñados para crear objetos de depurador nativos.
  • Se pueden devolver desde métodos host diseñados para crear objetos nativos del depurador

Los objetos del depurador que se pasan a una extensión de JavaScript tienen un conjunto de funcionalidades que se describen en esta sección.

  • Acceso a propiedades
  • Nombres proyectados
  • Tipos especiales pertenecientes a objetos de depurador nativos
  • Atributos adicionales

Acceso a propiedades

Aunque hay algunas propiedades en objetos que el propio proveedor de JavaScript coloca, la mayoría de las propiedades de un objeto nativo que entra en JavaScript se proporcionan mediante el modelo de datos. Esto significa que para un acceso de propiedad --- object.propertyName o object[propertyName], se producirá lo siguiente.

  • Si propertyName es el nombre de una propiedad proyectada en el objeto por el propio proveedor de JavaScript, se resolverá en este primero; Lo contrario
  • Si propertyName es el nombre de una clave proyectada en el objeto por el modelo de datos (otro visualizador), se resolverá en este segundo nombre; Lo contrario
  • Si propertyName es el nombre de un campo del objeto nativo, se resolverá en este nombre tercero; Lo contrario
  • Si el objeto es un puntero, el puntero se desreferenciará y el ciclo anterior continuará (una propiedad proyectada del objeto desreferenciado seguida de una clave seguida de un campo nativo).

Los medios normales de acceso a propiedades en JavaScript -- object.propertyName y object[propertyName] -- tendrán acceso a los campos nativos subyacentes de un objeto, como lo haría el comando 'dx' dentro del depurador.

Nombres proyectados

Las siguientes propiedades (y métodos) se proyectan en objetos nativos que escriben JavaScript.

Método Firma Descripción
hostContext Propiedad Devuelve un objeto que representa el contexto en el que se encuentra el objeto (el espacio de direcciones, el destino de depuración, etc....)
targetLocation Propiedad Devuelve un objeto que es una abstracción de dónde se encuentra el objeto dentro de un espacio de direcciones (dirección virtual, registro, sub-registro, etc.).
targetSize Propiedad Devuelve el tamaño del objeto (eficazmente: sizeof(<TYPE OF OBJECT>)
addParentModel .addParentModel(object) Agrega un nuevo modelo primario (similar a un prototipo de JavaScript, pero en el lado del modelo de datos) al objeto
removeParentModel .removeParentModel(object) Quita un modelo primario determinado del objeto .
runtimeTypedObject Propiedad Realiza análisis en el objeto e intenta convertirlo al tipo en tiempo de ejecución (más derivado).
targetType Propiedad Las extensiones de JavaScript tienen acceso directo al sistema de tipos del lenguaje subyacente. Este acceso se expresa a través de la noción de objetos de tipo. Para obtener más información, vea Objetos de depurador nativos en extensiones de JavaScript: objetos de tipo.

Si el objeto es un puntero, las siguientes propiedades (y métodos) se proyectan en el puntero que entra en JavaScript:

Nombre de la propiedad Firma Descripción
add .add(value) Realiza la suma matemática del puntero entre el puntero y el valor especificado.
address Propiedad Devuelve la dirección del puntero como un objeto ordinal de 64 bits (un tipo de biblioteca).
desreferencia .dereference() Desreferencia el puntero y devuelve el objeto subyacente.
isNull Propiedad Devuelve si el valor de puntero es nullptr (0)

Tipos especiales pertenecientes a objetos de depurador nativos

Objetos de ubicación

El objeto location que se devuelve de la propiedad targetLocation de un objeto nativo contiene las siguientes propiedades (y métodos).

Nombre de propiedad Firma Descripción
add .add(value) Agrega un desplazamiento de bytes absoluto a la ubicación.
restar .subtract(value) Resta un desplazamiento de bytes absoluto de la ubicación.

Atributos adicionales

Iterabilidad

Cualquier objeto que se entiende como iterable por el modelo de datos (es una matriz nativa o tiene un visualizador (NatVis o de otro modo) que hace iterable) tendrá una función de iterador (indizada a través del estándar Symbol.iterator ES6) colocada en él. Esto significa que puede iterar un objeto nativo en JavaScript como se indica a continuación.

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

Indexabilidad

Los objetos que se entienden como indexables en una dimensión a través de ordinales (por ejemplo, matrices nativas) se pueden indexar en JavaScript a través del operador de acceso a propiedades estándar -- object[index]. Si un objeto se puede indexar por nombre o se puede indexar en más de una dimensión, los métodos getValueAt y setValueAt se proyectarán en el objeto para que el código javaScript pueda utilizar el indexador.

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

Conversión de cadenas

Cualquier objeto nativo que tenga una conversión de cadena de visualización a través de la compatibilidad con IStringDisplayableConcept o un elemento NatVis DisplayString tendrá esa conversión de cadena accesible a través del método estándar de JavaScript toString.

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

Crear objetos de depurador nativos

Como se mencionó, un script de JavaScript puede obtener acceso a objetos nativos si se pasan a JavaScript de varias maneras o puede crearlos a través de llamadas a la biblioteca host. Use las siguientes funciones para crear objetos de depurador nativos.

Método Firma Descripción

host.getModuleSymbol

getModuleSymbol(moduleName, symbolName, [contextInheritor])

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

Devuelve un objeto para un símbolo global dentro de un módulo determinado. El nombre del módulo y el nombre del símbolo son cadenas.

Si se proporciona el argumento contextInheritor opcional, el módulo y el símbolo se buscarán en el mismo contexto (espacio de direcciones, destino de depuración) que el objeto pasado. Si no se proporciona el argumento, se buscará el módulo y el símbolo en el contexto actual del depurador. Una extensión de JavaScript que no es un script de prueba único siempre debe proporcionar un contexto explícito.

Si se proporciona el argumento typeName opcional, se supone que el símbolo es del tipo pasado y se omitirá el tipo indicado en símbolos. Tenga en cuenta que cualquier llamador que espera operar en símbolos públicos para un módulo siempre debe proporcionar un nombre de tipo explícito.

host.getModuleContainingSymbol

getModuleContainingSymbol(location, [contextInheritor])

Devuelve el símbolo (por ejemplo, función o datos) que contiene la dirección especificada. Tenga en cuenta que esto solo funcionará si hay símbolos privados para el módulo que contiene la dirección especificada.

Si se proporciona el argumento contextInheritor opcional, el módulo y el símbolo se buscarán en el mismo contexto (espacio de direcciones, destino de depuración) que el objeto pasado. Si no se proporciona el argumento, se buscará el módulo y el símbolo en el contexto actual del depurador. Una extensión de JavaScript que no es un script de prueba único siempre debe proporcionar un contexto explícito.

host.createPointerObject

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

Crea un objeto de puntero en la dirección o ubicación especificadas. El nombre del módulo y el nombre de tipo son cadenas.

Si se proporciona el argumento contextInheritor opcional, el módulo y el símbolo se buscarán en el mismo contexto (espacio de direcciones, destino de depuración) que el objeto pasado. Si no se proporciona el argumento, se buscará el módulo y el símbolo en el contexto actual del depurador. Una extensión de JavaScript que no es un script de prueba único siempre debe proporcionar un contexto explícito.

host.createTypedObject

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

Crea un objeto que representa un objeto de tipo nativo dentro del espacio de direcciones de un destino de depuración en la ubicación especificada. El nombre del módulo y el nombre de tipo son cadenas.

Si se proporciona el argumento contextInheritor opcional, el módulo y el símbolo se buscarán en el mismo contexto (espacio de direcciones, destino de depuración) que el objeto pasado. Si no se proporciona el argumento, se buscará el módulo y el símbolo en el contexto actual del depurador. Una extensión de JavaScript que no es un script de prueba único siempre debe proporcionar un contexto explícito.

API de host para extensiones de JavaScript

El proveedor de JavaScript inserta un objeto denominado host en el espacio de nombres global de cada script que carga. Este objeto proporciona acceso a la funcionalidad crítica del script, así como al acceso al espacio de nombres del depurador. Se configura en dos fases.

  • Fase 1: Antes de que se ejecute cualquier script, el objeto host solo contiene el conjunto mínimo de funciones necesarias para que un script se inicialice y registre sus puntos de extensibilidad (tanto como productor como consumidor). El código raíz e inicialización no está pensado para manipular el estado de un destino de depuración o realizar operaciones complejas y, como tal, el host no se rellena completamente hasta que se devuelve el método initializeScript.

  • Fase 2: después de que initializeScript devuelva, el objeto host se rellena con todo lo necesario para manipular el estado de los destinos de depuración.

Nivel de objeto de host

Algunas partes clave de la funcionalidad se encuentran directamente bajo el objeto host. El resto tiene un espacio de nombres secundario. Los espacios de nombres incluyen lo siguiente.

Espacio de nombres Descripción
diagnóstico Funcionalidad para ayudar en el diagnóstico y la depuración del código de script
memoria Funcionalidad para habilitar la lectura y escritura de memoria dentro de un destino de depuración

Nivel raíz

Directamente dentro del objeto host, se pueden encontrar las siguientes propiedades, métodos y constructores.

Nombre Signature Fase presente Descripción
createPointerObject

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

2 Crea un objeto de puntero en la dirección o ubicación especificadas. El nombre del módulo y el nombre de tipo son cadenas. El argumento contextInheritor opcional funciona como con getModuleSymbol.
createTypedObject

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

2 Crea un objeto que representa un objeto de tipo nativo dentro del espacio de direcciones de un destino de depuración en la ubicación especificada. El nombre del módulo y el nombre de tipo son cadenas. El argumento contextInheritor opcional funciona como con getModuleSymbol.
currentProcess

Propiedad

2 Devuelve el objeto que representa el proceso actual del depurador.
currentSession

Propiedad

2 Devuelve el objeto que representa la sesión actual del depurador (destino, volcado de memoria, etc.) que se está depurando.
currentThread

Propiedad

2 Devuelve el objeto que representa el subproceso actual del depurador.
evaluateExpression

evaluateExpression(expression, [contextInheritor])

2 Esto llama al host de depuración para evaluar una expresión mediante el lenguaje del destino de depuración solo. Si se proporciona el argumento contextInheritor opcional, la expresión se evaluará en el contexto (por ejemplo: espacio de direcciones y destino de depuración) del argumento; de lo contrario, se evaluará en el contexto actual del depurador.
evaluateExpressionInContext

evaluateExpressionInContext(context, expression)

2 Esto llama al host de depuración para evaluar una expresión mediante el lenguaje del destino de depuración solo. El argumento context indica el puntero implícito que se va a utilizar para la evaluación. La expresión se evaluará en el contexto (por ejemplo: espacio de direcciones y destino de depuración) indicado por el argumento context .
getModuleSymbol

getModuleSymbol(moduleName, symbolName, [contextInheritor])

2 Devuelve un objeto para un símbolo global dentro de un módulo determinado. El nombre del módulo y el nombre del símbolo son cadenas. Si se proporciona el argumento contextInheritor opcional, el módulo y el símbolo se buscarán en el mismo contexto (espacio de direcciones, destino de depuración) que el objeto pasado. Si no se proporciona el argumento, se buscará el módulo y el símbolo en el contexto actual del depurador. Una extensión de JavaScript que no es un script único siempre debe proporcionar un contexto explícito.
getNamedModel

getNamedModel(modelName)

2 Devuelve el modelo de datos que se registró con un nombre determinado. Tenga en cuenta que es perfectamente legal llamarlo con un nombre que aún no está registrado. Al hacerlo, se creará un código auxiliar para ese nombre y manipulaciones del código auxiliar en el objeto real tras el registro.
indexedValue

new indexedValue(value, indicies)

2 Constructor de un objeto que se puede devolver desde un iterador de JavaScript para asignar un conjunto predeterminado de indicies al valor iterado. El conjunto de indicciones debe expresarse como una matriz de JavaScript.
Int64

new Int64(value, [highValue])

1 Esto construye un tipo Int64 de biblioteca. La versión del argumento único tomará cualquier valor que pueda empaquetar en un Int64 (sin conversión) y colocarlo en tal. Si se proporciona un segundo argumento opcional, se empaqueta una conversión del primer argumento en los 32 bits inferiores y se empaqueta una conversión del segundo argumento en los 32 bits superiores.
namedModelParent

new namedModelParent(object, name)

1 Constructor de un objeto destinado a colocarse en la matriz devuelta desde initializeScript, esto representa el uso de un prototipo de JavaScript o una clase ES6 como una extensión primaria del modelo de datos de un modelo de datos con el nombre especificado.
namedModelRegistration

new namedModelRegistration(object, name)

1 Un constructor para un objeto destinado a colocarse en la matriz devuelta desde initializeScript, esto representa el registro de un prototipo de JavaScript o una clase ES6 como modelo de datos a través de un nombre conocido para que otras extensiones puedan buscar y extender.
espacio de nombres

Propiedad

2 Proporciona acceso directo al espacio de nombres raíz del depurador. Por ejemplo, podría tener acceso a la lista de procesos del primer destino de depuración a través de host.namespace.Debugger.Sessions.First(). Procesos que usan esta propiedad
registerNamedModel

registerNamedModel(object, modelName)

2 Esto registra un prototipo de JavaScript o una clase ES6 como modelo de datos con el nombre especificado. Este registro permite que otros scripts u otras extensiones del depurador encuentren y extiendan el prototipo o la clase. Tenga en cuenta que un script debe preferir devolver un objeto namedModelRegistration desde su método initializeScript en lugar de hacerlo de forma imperativa. Cualquier script que realice cambios de forma imperativa es necesario tener un método initializeScript para limpiarlo.
registerExtensionForTypeSignature

registerExtensionForTypeSignature(object, typeSignature)

2 Esto registra un prototipo de JavaScript o una clase ES6 como un modelo de datos de extensión para un tipo nativo según la firma de tipo proporcionada. Tenga en cuenta que un script debe preferir devolver un objeto typeSignatureExtension desde su método initializeScript en lugar de hacerlo de forma imperativa. Cualquier script que realice cambios de forma imperativa es necesario tener un método initializeScript para limpiarlo.
registerPrototypeForTypeSignature

registerPrototypeForTypeSignature(object, typeSignature)

2 Esto registra un prototipo de JavaScript o una clase ES6 como modelo de datos canónicos (por ejemplo: visualizador) para un tipo nativo según la firma de tipo proporcionada. Tenga en cuenta que un script debe preferir devolver un objeto typeSignatureRegistration desde su método initializeScript en lugar de hacerlo de forma imperativa. Cualquier script que realice cambios de forma imperativa es necesario tener un método uninitializeScriptpara limpiar.
parseInt64

parseInt64(string, [radix])

1 Este método actúa de forma similar al método estándar parseInt de JavaScript, salvo que devuelve un tipo Int64 de biblioteca en su lugar. Si se proporciona un radix, el análisis se producirá en base 2, 8, 10 o 16, como se indica.
typeSignatureExtension

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

1 Un constructor de un objeto destinado a colocarse en la matriz devuelta desde initializeScript, representa una extensión de un tipo nativo descrito a través de una firma de tipo mediante un prototipo de JavaScript o una clase ES6. Este registro "agrega campos" a la visualización del depurador de cualquier tipo que coincida con la firma en lugar de tomarla por completo. Un nombre y una versión de módulo opcionales pueden restringir el registro. Las versiones se especifican como cadenas de estilo "1.2.3.4".
typeSignatureRegistration

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

1 Un constructor de un objeto destinado a colocarse en la matriz devuelta desde initializeScript, representa un registro canónico de un prototipo de JavaScript o una clase ES6 en una firma de tipo nativo. Este registro "toma el control" de la visualización del depurador de cualquier tipo que coincida con la firma en lugar de simplemente ampliarla. Un nombre y una versión de módulo opcionales pueden restringir el registro. Las versiones se especifican como cadenas de estilo "1.2.3.4".
unregisterNamedModel

unregisterNamedModel(modelName)

2 Esto anula el registro de un modelo de datos de la búsqueda por el nombre especificado, lo que deshace cualquier operación realizada por registerNamedModel.
unregisterExtensionForTypeSignature

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

2 Esto anula el registro de un prototipo de JavaScript o una clase ES6 de ser un modelo de datos de extensión para un tipo nativo según la firma de tipo proporcionada. Es el deshacer lógico de registerExtensionForTypeSignature. Tenga en cuenta que un script debe preferir devolver un objeto typeSignatureExtension desde su método initializeScript en lugar de hacerlo de forma imperativa. Cualquier script que realice cambios de forma imperativa es necesario tener un método initializeScript para limpiarlo. Un nombre y una versión de módulo opcionales pueden restringir el registro. Las versiones se especifican como cadenas de estilo "1.2.3.4".
unregisterPrototypeForTypeSignature

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

2 Esto anula el registro de un prototipo de JavaScript o una clase ES6 de ser el modelo de datos canónicos (por ejemplo: visualizador) para un tipo nativo tal y como lo proporciona la firma de tipo proporcionada. Es la deshacer lógica de registerPrototypeForTypeSignature. Tenga en cuenta que un script debe preferir devolver un objeto typeSignatureRegistration desde su método initializeScript en lugar de hacerlo de forma imperativa. Cualquier script que realice cambios de forma imperativa es necesario tener un método uninitializeScript para limpiar. Un nombre y una versión de módulo opcionales pueden restringir el registro. Las versiones se especifican como cadenas de estilo "1.2.3.4".

Funcionalidad de diagnóstico

El subespacio de nombres diagnostics del objeto host contiene lo siguiente.

Nombre Signature Fase presente Descripción
debugLog debugLog(object...) 1 Esto proporciona depuración de estilo printf en una extensión de script. En la actualidad, la salida de debugLog se enruta a la consola de salida del depurador. En un momento posterior, hay planes para proporcionar flexibilidad en el enrutamiento de esta salida. NOTA: Esto no se debe usar como medio para imprimir la salida del usuario en la consola. Es posible que no se enrute allí en el futuro.

Funcionalidad de memoria

El subespacio de nombres de memoria del objeto host contiene lo siguiente.

Nombre Signature Fase presente Descripción
readMemoryValues

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

2 Esto lee una matriz sin procesar de valores del espacio de direcciones del destino de depuración y coloca una matriz con tipo en la parte superior de la vista de esta memoria. La ubicación proporcionada puede ser una dirección (un valor de 64 bits), un objeto de ubicación o un puntero nativo. El tamaño de la matriz se indica mediante el argumento numElements . El tamaño (y tipo) de cada elemento de la matriz lo proporcionan los argumentos opcionales elementSize y isSigned . Si no se proporciona ningún argumento de este tipo, el valor predeterminado es byte (unsigned / 1 byte). Si se proporciona el argumento contextInheritor opcional, la memoria se leerá en el contexto (por ejemplo: espacio de direcciones y destino de depuración) indicado por el argumento ; de lo contrario, se leerá desde el contexto actual del depurador. Tenga en cuenta que el uso de este método en valores de 8, 16 y 32 bits da como resultado una vista rápida con tipo que se coloca sobre la memoria de lectura. El uso de este método en valores de 64 bits da como resultado una matriz de tipos de biblioteca de 64 bits que se construyen, lo que es significativamente más caro.
readString

readString(location, [contextInheritor])

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

2 Esto lee una cadena estrecha (página de códigos actual) del espacio de direcciones de un destino de depuración, la convierte en UTF-16 y devuelve el resultado como una cadena de JavaScript. Puede producir una excepción si no se pudo leer la memoria. La ubicación proporcionada puede ser una dirección (un valor de 64 bits), un objeto de ubicación o un carácter nativo. Si se proporciona el argumento contextInheritor opcional, la memoria se leerá en el contexto (por ejemplo: espacio de direcciones y destino de depuración) indicado por el argumento ; de lo contrario, se leerá desde el contexto actual del depurador. Si se proporciona el argumento de longitud opcional, la cadena de lectura será de la longitud especificada.
readWideString

readWideString(location, [contextInheritor])

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

2 Esto lee una cadena wide(UTF-16) del espacio de direcciones de un destino de depuración y devuelve el resultado como una cadena de JavaScript. Puede producir una excepción si no se pudo leer la memoria. La ubicación proporcionada puede ser una dirección (un valor de 64 bits), un objeto de ubicación o un wchar_t nativo. Si se proporciona el argumento contextInheritor opcional, la memoria se leerá en el contexto (por ejemplo: espacio de direcciones y destino de depuración) indicado por el argumento ; de lo contrario, se leerá desde el contexto actual del depurador. Si se proporciona el argumento de longitud opcional, la cadena de lectura será de la longitud especificada.

Conceptos del modelo de datos en JavaScript

Asignación de modelos de datos

Los siguientes conceptos del modelo de datos se asignan a JavaScript.

Concepto Interfaz nativa Equivalente de JavaScript
Conversión de cadenas IStringDisplayableConcept estándar: toString(...) {...}
Iterabilidad IIterableConcept standard: [Symbol.iterator](){...}
Indexabilidad IIndexableConcept protocol: getDimensionality(...) / getValueAt(...) / setValueAt(...)
Conversión de tipos en tiempo de ejecución IPreferredRuntimeTypeConcept protocol: getPreferredRuntimeTypedObject(...)

Conversión de cadenas

El concepto de conversión de cadenas (IStringDisplayableConcept) se traduce directamente al método estándar de JavaScript toString . Como todos los objetos JavaScript tienen una conversión de cadena (proporcionada por Object.prototype si no se proporciona en otro lugar), todos los objetos javaScript devueltos al modelo de datos se pueden convertir en una cadena de visualización. La invalidación de la conversión de cadenas simplemente requiere implementar su propio toString.

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

Iterabilidad

El concepto del modelo de datos de si un objeto es iterable o no se asigna directamente al protocolo ES6 de si un objeto es iterable. Cualquier objeto que tenga un método [Symbol.iterator] se considera iterable. La implementación de este tipo hará que el objeto sea iterable.

Un objeto que solo se puede iterable puede tener una implementación como la siguiente.

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

Se debe tener en cuenta especial para los objetos que son iterables e indizables, ya que los objetos devueltos por el iterador deben incluir el índice, así como el valor a través de un tipo de valor devuelto especial.

Iterable e indizable

Un objeto que es iterable e indizable requiere un valor devuelto especial del iterador. En lugar de producir los valores, el iterador produce instancias de indexedValue. Las indicciones se pasan como una matriz en el segundo argumento al constructor indexedValue. Pueden ser multidimensionales, pero deben coincidir con la dimensionalidad devuelta en el protocolo del indexador.

Este código muestra una implementación de ejemplo.

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

Indexabilidad

A diferencia de JavaScript, el modelo de datos hace una diferenciación muy explícita entre el acceso a las propiedades y la indexación. Cualquier objeto JavaScript que desee presentarse como indizable en el modelo de datos debe implementar un protocolo que consta de un método getDimensionality que devuelve la dimensionalidad del indexador y un par opcional de métodos getValueAt y setValueAt que realizan lecturas y escrituras del objeto en indicies proporcionados. Es aceptable omitir los métodos getValueAt o setValueAt si el objeto es de solo lectura o de solo escritura.

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

Conversión de tipos en tiempo de ejecución

Esto solo es relevante para prototipos o clases de JavaScript que se registran en tipos del sistema de tipos (nativos). El depurador suele ser capaz de realizar análisis (por ejemplo, Run-Time información de tipos (RTTI) o análisis de tabla virtual) para determinar el verdadero tipo en tiempo de ejecución de un objeto a partir de un tipo estático expresado en el código. Un modelo de datos registrado en un tipo nativo puede invalidar este comportamiento a través de una implementación de IPreferredRuntimeTypeConcept. Del mismo modo, una clase de JavaScript o un prototipo registrados en un objeto nativo puede proporcionar su propia implementación a través de la implementación de un protocolo que consta del método getPreferredRuntimeTypedObject.

Tenga en cuenta que, aunque este método puede devolver técnicamente cualquier cosa, se considera una forma incorrecta para que devuelva algo que realmente no es el tipo en tiempo de ejecución o un tipo derivado. Esto puede dar lugar a una confusión significativa para los usuarios del depurador. Sin embargo, la invalidación de este método puede ser valiosa para cosas como los estilos de encabezado de estilo C+objeto de implementación, 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);
    }
}

Vea también

Objetos de depurador nativos en extensiones de JavaScript

Objetos de depurador nativos en extensiones de JavaScript: consideraciones de diseño y pruebas

Scripting del depurador de JavaScript

Scripts de ejemplo del depurador de JavaScript