Dynamic Analysis With Babel
Matt Zeunert
What is Dynamic Analysis?
if (arr.length = 1){
// do something
}
if (arr.length === 1){
// do something
}
if (arr.length === 1){
// do something
}
var a = 5
console.log(a)
a = 10
console.log(a)
Instrumentation
var a = 5
a = 10
var a = 5
console.log(a)
a = 10
console.log(a)
Babel
Babel
6to5
var square = (n) => n * n
"use strict";
var square = function (n) {
return n * n;
};
Babel
ES6
ES7
JSX
...
.babelrc
{
"plugins": [
"check-es2015-constants",
"transform-es2015-arrow-functions",
"transform-es2015-block-scoped-functions",
"transform-es2015-block-scoping",
"transform-es2015-classes",
"transform-es2015-computed-properties",
"transform-es2015-destructuring",
"transform-es2015-duplicate-keys",
"transform-es2015-for-of",
"transform-es2015-function-name",
"transform-es2015-literals",
"transform-es2015-modules-commonjs",
"and 9 other plugins"
]
}
.babelrc
{
"plugins": [],
"presets": ["es2015"]
}
Compilation
Parse
Traverse & Transform
Generate
Plugins
Plugin Example
var greeting = "Hello"
var greeting = "Hi";
Parse
var greeting = "Hello"
Traverse & Transform
module.exports = function(babel) {
return {
visitor: {
StringLiteral: function(path) {
path.node.value = "Hi"
}
}
}
}
Generate
var greeting = "Hi";
StringLiteral: function(path) {
}
var greeting = getGreeting()
var greeting = "Hi";
var call = babel.types.callExpression(
babel.types.identifier("getGreeting"),
[]
)
path.replaceWith(call)
Dynamic Analysis With Babel
How It Should Work
Problem
Where did the commitsByAuthor object change?
Our End Goal
obj.a = 55
obj.a = 55
trackAssignment(obj, "a", 55)
obj.a = 55
assignProperty(obj, "a", 55)
obj.a = 55
AssignmentExpression
Left
Right
obj.a
MemberExpression
Object
Property
Demo
AssignmentExpression(path) {
var assignmentExpression = path.node
if (assignmentExpression.left.type !== "MemberExpression") {
return
}
var memberExpression = assignmentExpression.left
var value = assignmentExpression.right
var propertyName = memberExpression.property
if (!memberExpression.computed) {
propertyName = t.stringLiteral(propertyName.name)
}
var call = t.callExpression(
t.identifier("assignProperty"), [
memberExpression.object,
propertyName,
assignmentExpression.right
]
)
path.replaceWith(call)
}
function assignProperty(obj, propName, value){
obj[propName] = value
if (!obj[propName + "__history__"]){
Object.defineProperty(obj, propName + "__history__", {
enumerable: false,
value: []
})
}
obj[propName + "__history__"].push({
value: value,
stack: Error().stack
})
}
Other Examples
Visualizing Program Execution - Jan Paul Posma
DLint
https://github.com/Berkeley-Correctness-Group/DLint
JITProf
FromJS
Instrumentation
Compilation
Method Patching
Instrumentation Through Method Patching
var nativeCreateElement = document.createElement
document.createElement = function(tagName){
var el = nativeCreateElement.call(document, tagName)
el.createdAtStackTrace = Error().stack
return el
}
Limitations
Execution Speed
Memory
Breaking Functionality
Node-ChakraCore
node -TTRecord:log test.js
Jan Paul Posma: Visualizing program execution
Ariya Hidayat: Dynamic Code Analysis for JavaScript
Time-Travel Debugging for JavaScript/HTML Applications
Resources
FromJS
Twitter: @mattzeunert
Thank You
Slides
Dynamic Analysis with Babel - Rolling Scopes Minks
By Matt Zeunert
Dynamic Analysis with Babel - Rolling Scopes Minks
- 1,419