jsinstrumentation.js
author Gregor Richards <hg-yff@gregor.im>
Tue, 23 Jul 2013 13:31:47 -0400
changeset 332 323eb38c39a6e06fe242b65ca3ff3287b85af1f5
parent 185 bd663ff3198f50336026eb194bcfc0835017a382
permissions -rw-r--r--
More global objects!

/*
 * Copyright (C) 2010, 2011 Purdue University
 * Written by Gregor Richards
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

JSBNG.JSI = new (function() {
    eval(Narcissus.definitions.consts);

    var instrument = this.instrument = function(n, tdf, buf) {
        function sub(n) { return instrument(n, tdf, buf); }

        // first do top-down
        if (tdf !== null) n = tdf(n);

        // then recurse
        switch (n.type) {
            case FUNCTION:
            case GETTER:
            case SETTER:
                n.body = sub(n.body);
                break;

            case SCRIPT:
            case BLOCK:
                for (var i = 0, j = n.children.length; i < j; i++) {
                    n.children[i] = sub(n.children[i]);
                }
                break;

            case LET_BLOCK:
                n.variables = sub(n.variables);
                if (n.expression)
                    n.expression = sub(n.expression);
                else
                    n.block = sub(n.block);
                break;

            case IF:
                n.condition = sub(n.condition);
                n.thenPart = sub(n.thenPart);
                if (n.elsePart) n.elsePart = sub(n.elsePart);
                break;

            case SWITCH:
                n.discriminant = sub(n.discriminant);
                for (var i = 0, j = n.cases.length; i < j; i++) {
                    n.cases[i] = sub(n.cases[i]);
                }
                break;

            case CASE:
                n.caseLabel = sub(n.caseLabel);
            case DEFAULT:
                n.statements = sub(n.statements);
                break;

            case FOR:
                if (n.setup) n.setup = sub(n.setup);
                if (n.condition) n.condition = sub(n.condition);
                if (n.update) n.update = sub(n.update);
                if (n.body) n.body = sub(n.body);
                break;

            case WHILE:
                n.condition = sub(n.condition);
                if (n.body) n.body = sub(n.body);
                break;

            case FOR_IN:
                if (n.varDecl)
                    n.varDecl = sub(n.varDecl);
                else
                    n.iterator = sub(n.iterator);
                n.object = sub(n.object);
                if (n.body) n.body = sub(n.body);
                break;

            case DO:
                n.body = sub(n.body);
                n.condition = sub(n.condition);
                break;

            case TRY:
                n.tryBlock = sub(n.tryBlock);
                for (var i = 0, j = n.catchClauses.length; i < j; i++) {
                    var t = n.catchClauses[i];
                    if (t.guard) t.guard = sub(t.guard);
                    t.block = sub(t.block);
                }
                if (n.finallyBlock) n.finallyBlock = sub(n.finallyBlock);
                break;

            case THROW:
                n.exception = sub(n.exception);
                break;

            case RETURN:
                if (n.value) n.value = sub(n.value);
                break;

            case YIELD:
                if (n.value.type) n.value = sub(n.value);
                break;

            case GENERATOR:
                n.expression = sub(n.expression);
                n.tail = sub(n.tail);
                break;

            case WITH:
                n.object = sub(n.object);
                n.body = sub(n.body);
                break;

            case LET:
            case VAR:
            case CONST:
                for (var i = 0, j = n.children.length; i < j; i++) {
                    var u = n.children[i];
                    if (u.initializer) u.initializer = sub(u.initializer);
                }
                break;

            case SEMICOLON:
                if (n.expression) n.expression = sub(n.expression);
                break;

            case LABEL:
                n.statement = sub(n.statement);
                break;

            // easy things:
            case COMMA:
            case LIST:
            case ASSIGN:
            case HOOK:
            case OR:
            case AND:
            case BITWISE_OR:
            case BITWISE_XOR:
            case BITWISE_AND:
            case EQ:
            case NE:
            case STRICT_EQ:
            case STRICT_NE:
            case LT:
            case LE:
            case GE:
            case GT:
            case IN:
            case INSTANCEOF:
            case LSH:
            case RSH:
            case URSH:
            case PLUS:
            case MINUS:
            case MUL:
            case DIV:
            case MOD:
            case DELETE:
            case VOID:
            case TYPEOF:
            case NOT:
            case BITWISE_NOT:
            case UNARY_PLUS:
            case UNARY_MINUS:
            case INCREMENT:
            case DECREMENT:
            case DOT:
            case INDEX:
            case CALL:
            case NEW:
            case NEW_WITH_ARGS:
            case ARRAY_INIT:
            case ARRAY_COMP:
            case COMP_TAIL:
            case OBJECT_INIT:
            case PROPERTY_INIT:
            case GROUP:
                for (var i = 0, j = n.children.length; i < j; i++) {
                    if (n.children[i] !== null)
                        n.children[i] = sub(n.children[i]);
                }
                break;

            // no-children things:
            case BREAK:
            case CONTINUE:
            case DEBUGGER:
            case NULL:
            case THIS:
            case TRUE:
            case FALSE:
            case IDENTIFIER:
            case NUMBER:
            case REGEXP:
            case STRING:
                break;

            default:
                JSBNG.Util.debug("Unrecognized node type " + n.type + "!");
                throw new Error();
        }

        // then do bottom-up
        if (buf !== null) n = buf(n, b);

        return n;
    };
})();