src/js/instrument/astUtil.js
function serialize(root) {
        // Stores a pointer to the most-recently encountered node representing a function or a
        // top-level script.  We need this stored pointer since a function expression or declaration
        // has no associated IID, but we'd like to have the ASTs as entries in the table.  Instead,
        // we associate the AST with the IID for the corresponding function-enter or script-enter IID.
        // We don't need a stack here since we only use this pointer at the next function-enter or script-enter,
        // and there cannot be a nested function declaration in-between.
        var parentFunOrScript = root;
        var iidToAstTable = {};

        function handleFun(node) {
            parentFunOrScript = node;
        }

        var visitorPre = {
            'Program':handleFun,
            'FunctionDeclaration':handleFun,
            'FunctionExpression':handleFun
        };

        function canMakeSymbolic(node) {
            if (node.callee.object) {
                var callee = node.callee;
                // we can replace calls to J$ functions with a SymbolicReference iff they have an IID as their first
                // argument.  'instrumentCode', 'getConcrete', and 'I' do not take an IID.
                // TODO are we missing other cases?
                if (callee.object.name === 'J$' && callee.property.name !== "instrumentCode" &&
                    callee.property.name !== "getConcrete" &&
                    callee.property.name !== "I" && node.arguments[0]) {
                    return true;
                }
            }
            return false;
        }

        function setSerializedAST(iid, ast) {
            var entry = iidToAstTable[iid];
            if (!entry) {
                entry = {};
                iidToAstTable[iid] = entry;
            }
            entry.serializedAST = ast;
        }
        var visitorPost = {
            'CallExpression':function (node) {
                try {
                    if (node.callee.object && node.callee.object.name === 'J$' && (node.callee.property.name === 'Se' || node.callee.property.name === 'Fe')) {
                        // associate IID with the AST of the containing function / script
                        setSerializedAST(node.arguments[0].value, parentFunOrScript);
                        return node;
                    } else if (canMakeSymbolic(node)) {
                        setSerializedAST(node.arguments[0].value, node);
                        return {type:"SymbolicReference", value:node.arguments[0].value};
                    }
                    return node;
                } catch (e) {
                    console.log(JSON.stringify(node));
                    throw e;
                }
            }
        };

        transformAst(root, visitorPost, visitorPre);
        return iidToAstTable;
    }
function serialize(root) {
        // Stores a pointer to the most-recently encountered node representing a function or a
        // top-level script.  We need this stored pointer since a function expression or declaration
        // has no associated IID, but we'd like to have the ASTs as entries in the table.  Instead,
        // we associate the AST with the IID for the corresponding function-enter or script-enter IID.
        // We don't need a stack here since we only use this pointer at the next function-enter or script-enter,
        // and there cannot be a nested function declaration in-between.
        var parentFunOrScript = root;
        var iidToAstTable = {};

        function handleFun(node) {
            parentFunOrScript = node;
        }

        var visitorPre = {
            'Program':handleFun,
            'FunctionDeclaration':handleFun,
            'FunctionExpression':handleFun
        };

        function canMakeSymbolic(node) {
            if (node.callee.object) {
                var callee = node.callee;
                // we can replace calls to J$ functions with a SymbolicReference iff they have an IID as their first
                // argument.  'instrumentCode', 'getConcrete', and 'I' do not take an IID.
                // TODO are we missing other cases?
                if (callee.object.name === 'J$' && callee.property.name !== "instrumentCode" &&
                    callee.property.name !== "getConcrete" &&
                    callee.property.name !== "I" && node.arguments[0]) {
                    return true;
                }
            }
            return false;
        }

        function setSerializedAST(iid, ast) {
            var entry = iidToAstTable[iid];
            if (!entry) {
                entry = {};
                iidToAstTable[iid] = entry;
            }
            entry.serializedAST = ast;
        }
        var visitorPost = {
            'CallExpression':function (node) {
                try {
                    if (node.callee.object && node.callee.object.name === 'J$' && (node.callee.property.name === 'Se' || node.callee.property.name === 'Fe')) {
                        // associate IID with the AST of the containing function / script
                        setSerializedAST(node.arguments[0].value, parentFunOrScript);
                        return node;
                    } else if (canMakeSymbolic(node)) {
                        setSerializedAST(node.arguments[0].value, node);
                        return {type:"SymbolicReference", value:node.arguments[0].value};
                    }
                    return node;
                } catch (e) {
                    console.log(JSON.stringify(node));
                    throw e;
                }
            }
        };

        transformAst(root, visitorPost, visitorPre);
        return iidToAstTable;
    }
function serialize ( root ) { // Stores a pointer to the most-recently encountered node representing a function or a // top-level script.  We need this stored pointer since a function expression or declaration // has no associated IID, but we'd like to have the ASTs as entries in the table.  Instead, // we associate the AST with the IID for the corresponding function-enter or script-enter IID. // We don't need a stack here since we only use this pointer at the next function-enter or script-enter, // and there cannot be a nested function declaration in-between. var parentFunOrScript = root ; var iidToAstTable = { } ; function handleFun ( node ) { parentFunOrScript = node ; } var visitorPre = { 'Program' : handleFun , 'FunctionDeclaration' : handleFun , 'FunctionExpression' : handleFun } ; function canMakeSymbolic ( node ) { if ( node . callee . object ) { var callee = node . callee ; // we can replace calls to J$ functions with a SymbolicReference iff they have an IID as their first // argument.  'instrumentCode', 'getConcrete', and 'I' do not take an IID. // TODO are we missing other cases? if ( callee . object . name === 'J$' && callee . property . name !== "instrumentCode" && callee . property . name !== "getConcrete" && callee . property . name !== "I" && node . arguments [ 0 ] ) { return true ; } } return false ; } function setSerializedAST ( iid , ast ) { var entry = iidToAstTable [ iid ] ; if ( ! entry ) { entry = { } ; iidToAstTable [ iid ] = entry ; } entry . serializedAST = ast ; } var visitorPost = { 'CallExpression' : function ( node ) { try { if ( node . callee . object && node . callee . object . name === 'J$' && ( node . callee . property . name === 'Se' || node . callee . property . name === 'Fe' ) ) { // associate IID with the AST of the containing function / script setSerializedAST ( node . arguments [ 0 ] . value , parentFunOrScript ) ; return node ; } else if ( canMakeSymbolic ( node ) ) { setSerializedAST ( node . arguments [ 0 ] . value , node ) ; return { type : "SymbolicReference" , value : node . arguments [ 0 ] . value } ; } return node ; } catch ( e ) { console . log ( JSON . stringify ( node ) ) ; throw e ; } } } ; transformAst ( root , visitorPost , visitorPre ) ; return iidToAstTable ; }
computes a map from iids to the corresponding AST nodes for root.  The root AST is destructively updated to
include SymbolicReference nodes that reference other nodes by iid, in order to save space in the map.
computes a map from iids to the corresponding AST nodes for root . The root AST is destructively updated to include SymbolicReference nodes that reference other nodes by iid in order to save space in the map .