Para realizar algunos experimentos simples, descargue Esprima, Escodegen y una copia en bruto de instrumenter.js del GitHub de Estambul.
Crear un nuevo archivo HTML; si los pones todos en la misma carpeta:
- ¿Cuáles son buenos ejemplos de proyectos abandonados (o reiniciados) debido a limitaciones del lenguaje de programación?
- ¿Quién tiene una gran idea de desarrollo de software que necesita implementación?
- ¿Cuáles son las mejores bibliotecas (en cualquier idioma) para hacer análisis de red?
- ¿Hay alguna diferencia entre ser un DevOps en una gran empresa y un ingeniero de software en una startup?
- ¿Existen soluciones de hardware / software para evitar el uso de cámaras de teléfonos inteligentes en eventos o ubicaciones sensibles?
Abra esto en su navegador y abra la consola (F12).
>> var someJS = “var i = 0; if (i> = 0) {console.log (‘hi’)}”
>> var ast = esprima.parse (someJS)
>> ast
Object {type: “Program”, body: Array [2], sourceType: “script”}
>> ast.body [0]
Object {type: “VariableDeclaration”, declaraciones: Array [1], kind: “var”}
>> ast.body [1]
Objeto {tipo: “IfStatement”, prueba: Objeto, consecuente: Objeto, alternativo: nulo}
>> ast.body [0] .declaraciones [0]
Objeto {tipo: “VariableDeclarator”, id: Object, init: Object}
>> ast.body [0] .declarations [0] .id.name
“yo”
>> ast.body [0] .declaraciones [0] .init
Objeto {tipo: “Literal”, valor: 0, sin formato: “0”}
>> ast.body [0] .declarations [0] .init.value = 1
Entonces, Esprima toma un fragmento de JavaScript, como una cadena, y genera un árbol de sintaxis abstracta, una estructura de datos que representa el programa, que podemos navegar fácilmente, o incluso modificar. Escodegen hace la transformación inversa:
>> escodegen.generate (ast)
“var i = 1;
si (i> = 0) {
console.log (‘hola’);
} ”
Entonces, ¿qué hace instrumenter.js? Bueno, puedes leer el código tú mismo; pero aquí hay un ejemplo:
>> var inst = nuevo Instrumentador ()
>> inst.instrumentSync (someJS)
”
var __cov_1 = (Función (‘devolver esto’)) ();
si (! __ cov_1 .__ cobertura__) {__cov_1 .__ cobertura__ = {}; }
__cov_1 = __cov_1 .__ cobertura__;
if (! (__ cov_1 [‘1457994561008.js’])) {
__cov_1 [‘1457994561008.js’] = {“ruta”: “1457994561008.js”, “s”: {“1”: 0, “2”: 0, “3”: 0}, “b”: {” 1 “: [0,0]},” f “: {},” fnMap “: {},” StatementMap “: {” 1 “: {” start “: {” line “: 1,” column “: 0 }, “fin”: {“línea”: 1, “columna”: 10}}, “2”: {“inicio”: {“línea”: 1, “columna”: 11}, “fin”: {” línea “: 1,” columna “: 44}},” 3 “: {” inicio “: {” línea “: 1,” columna “: 25},” final “: {” línea “: 1,” columna ” : 43}}}, “branchMap”: {“1”: {“line”: 1, “type”: “if”, “ubicaciones”: [{“start”: {“line”: 1, “column” : 11}, “fin”: {“línea”: 1, “columna”: 11}}, {“inicio”: {“línea”: 1, “columna”: 11}, “fin”: {“línea” : 1, “columna”: 11}}]}}};
}
__cov_1 = __cov_1 [‘1457994561008.js’];
__cov_1.s [‘1’] ++; var i = 0; __ cov_1.s [‘2’] ++; if (i> = 0) {__ cov_1.b [‘1’] [0] ++; __ cov_1 .s [‘3’] ++; console.log (‘hi’);} else {__ cov_1.b [‘1’] [1] ++;}
”
Simplemente cambia el código a otro código, que contiene un objeto de contador y declaraciones de incremento en todas las ramas posibles (también puede notar que donde no había else
, agregó uno, para que pueda rastrear cuando no se cumplió la condición). Parece que el algoritmo de qué ignorar está completamente contenido dentro de ese archivo instrumenter.js; también hay una parte que reconoce sugerencias de “no rastrear” (en forma de un comentario como /* istanbul ignore next */
), que ignora la rama de la AST que sigue.
Uf, eso fue mucho para lo que habría sido una macro Lisp de 3 líneas 😀