private void transformCompilationUnit_r (ScriptOrFnNode tree, Node parent)
        {
            Node node = null;

            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (1024)) {
                for (; ; ) {
                    Node previous = null;
                    if (node == null) {
                        node = parent.FirstChild;
                    }
                    else {
                        previous = node;
                        node = node.Next;
                    }
                    if (node == null) {
                        break;
                    }

                    int type = node.Type;

                    switch (type) {


                        case Token.LABEL:
                        case Token.SWITCH:
                        case Token.LOOP:
                            loops.push (node);
                            loopEnds.push (((Node.Jump)node).target);
                            break;


                        case Token.WITH: {
                                loops.push (node);
                                Node leave = node.Next;
                                if (leave.Type != Token.LEAVEWITH) {
                                    Context.CodeBug ();
                                }
                                loopEnds.push (leave);
                                break;
                            }


                        case Token.TRY: {
                                Node.Jump jump = (Node.Jump)node;
                                Node finallytarget = jump.Finally;
                                if (finallytarget != null) {
                                    hasFinally = true;
                                    loops.push (node);
                                    loopEnds.push (finallytarget);
                                }
                                break;
                            }


                        case Token.TARGET:
                        case Token.LEAVEWITH:
                            if (!loopEnds.Empty && loopEnds.peek () == node) {
                                loopEnds.pop ();
                                loops.pop ();
                            }
                            break;


                        case Token.RETURN: {
                                /* If we didn't support try/finally, it wouldn't be
                                * necessary to put LEAVEWITH nodes here... but as
                                * we do need a series of JSR FINALLY nodes before
                                * each RETURN, we need to ensure that each finally
                                * block gets the correct scope... which could mean
                                * that some LEAVEWITH nodes are necessary.
                                */
                                if (!hasFinally)
                                    break; // skip the whole mess.
                                Node unwindBlock = null;
                                for (int i = loops.size () - 1; i >= 0; i--) {
                                    Node n = (Node)loops.Get (i);
                                    int elemtype = n.Type;
                                    if (elemtype == Token.TRY || elemtype == Token.WITH) {
                                        Node unwind;
                                        if (elemtype == Token.TRY) {
                                            Node.Jump jsrnode = new Node.Jump (Token.JSR);
                                            Node jsrtarget = ((Node.Jump)n).Finally;
                                            jsrnode.target = jsrtarget;
                                            unwind = jsrnode;
                                        }
                                        else {
                                            unwind = new Node (Token.LEAVEWITH);
                                        }
                                        if (unwindBlock == null) {
                                            unwindBlock = new Node (Token.BLOCK, node.Lineno);
                                        }
                                        unwindBlock.addChildToBack (unwind);
                                    }
                                }
                                if (unwindBlock != null) {
                                    Node returnNode = node;
                                    Node returnExpr = returnNode.FirstChild;
                                    node = replaceCurrent (parent, previous, node, unwindBlock);
                                    if (returnExpr == null) {
                                        unwindBlock.addChildToBack (returnNode);
                                    }
                                    else {
                                        Node store = new Node (Token.EXPR_RESULT, returnExpr);
                                        unwindBlock.addChildToFront (store);
                                        returnNode = new Node (Token.RETURN_RESULT);
                                        unwindBlock.addChildToBack (returnNode);
                                        // transform return expression
                                        transformCompilationUnit_r (tree, store);
                                    }
                                    // skip transformCompilationUnit_r to avoid infinite loop

                                    goto siblingLoop;
                                }
                                break;
                            }


                        case Token.BREAK:
                        case Token.CONTINUE: {
                                Node.Jump jump = (Node.Jump)node;
                                Node.Jump jumpStatement = jump.JumpStatement;
                                if (jumpStatement == null)
                                    Context.CodeBug ();

                                for (int i = loops.size (); ; ) {
                                    if (i == 0) {
                                        // Parser/IRFactory ensure that break/continue
                                        // always has a jump statement associated with it
                                        // which should be found
                                        throw Context.CodeBug ();
                                    }
                                    --i;
                                    Node n = (Node)loops.Get (i);
                                    if (n == jumpStatement) {
                                        break;
                                    }

                                    int elemtype = n.Type;
                                    if (elemtype == Token.WITH) {
                                        Node leave = new Node (Token.LEAVEWITH);
                                        previous = addBeforeCurrent (parent, previous, node, leave);
                                    }
                                    else if (elemtype == Token.TRY) {
                                        Node.Jump tryNode = (Node.Jump)n;
                                        Node.Jump jsrFinally = new Node.Jump (Token.JSR);
                                        jsrFinally.target = tryNode.Finally;
                                        previous = addBeforeCurrent (parent, previous, node, jsrFinally);
                                    }
                                }

                                if (type == Token.BREAK) {
                                    jump.target = jumpStatement.target;
                                }
                                else {
                                    jump.target = jumpStatement.Continue;
                                }
                                jump.Type = Token.GOTO;

                                break;
                            }


                        case Token.CALL:
                            visitCall (node, tree);
                            break;


                        case Token.NEW:
                            visitNew (node, tree);
                            break;


                        case Token.CONST:
                        case Token.VAR: {
                                Node result = new Node (Token.BLOCK);
                                for (Node cursor = node.FirstChild; cursor != null; ) {
                                    // Move cursor to next before createAssignment get chance
                                    // to change n.next
                                    Node n = cursor;
                                    if (n.Type != Token.NAME)
                                        Context.CodeBug ();
                                    cursor = cursor.Next;
                                    if (!n.hasChildren ())
                                        continue;
                                    Node init = n.FirstChild;
                                    n.removeChild (init);
                                    n.Type = Token.BINDNAME;
                                    n = new Node ((node.Type == Token.VAR) ? Token.SETNAME : Token.SETNAME_CONST, n, init);
                                    Node pop = new Node (Token.EXPR_VOID, n, node.Lineno);
                                    result.addChildToBack (pop);
                                }
                                node = replaceCurrent (parent, previous, node, result);
                                break;
                            }


                        case Token.NAME:
                        case Token.SETNAME:
                        case Token.DELPROP: {
                                // Turn name to var for faster access if possible
                                if (tree.Type != Token.FUNCTION || ((FunctionNode)tree).RequiresActivation) {
                                    break;
                                }
                                Node nameSource;
                                if (type == Token.NAME) {
                                    nameSource = node;
                                }
                                else {
                                    nameSource = node.FirstChild;
                                    if (nameSource.Type != Token.BINDNAME) {
                                        if (type == Token.DELPROP) {
                                            break;
                                        }
                                        throw Context.CodeBug ();
                                    }
                                }
                                string name = nameSource.String;
                                if (tree.hasParamOrVar (name)) {
                                    if (type == Token.NAME) {
                                        node.Type = Token.GETVAR;
                                    }
                                    else if (type == Token.SETNAME) {
                                        node.Type = Token.SETVAR;
                                        nameSource.Type = Token.STRING;
                                    }
                                    else if (type == Token.DELPROP) {
                                        // Local variables are by definition permanent
                                        Node n = new Node (Token.FALSE);
                                        node = replaceCurrent (parent, previous, node, n);
                                    }
                                    else {
                                        throw Context.CodeBug ();
                                    }
                                }
                                break;
                            }
                    }

                    transformCompilationUnit_r (tree, node);

                siblingLoop:
                    ;
                }
            }
        }
        internal static object Interpret (InterpretedFunction ifun, Context cx, IScriptable scope, IScriptable thisObj, object [] args)
        {
            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (128)) {
                if (!ScriptRuntime.hasTopCall (cx))
                    Context.CodeBug ();

                if (cx.interpreterSecurityDomain != ifun.securityDomain) {
                    object savedDomain = cx.interpreterSecurityDomain;
                    cx.interpreterSecurityDomain = ifun.securityDomain;
                    try {
                        return ifun.securityController.callWithDomain (ifun.securityDomain, cx, ifun, scope, thisObj, args);
                    }
                    finally {
                        cx.interpreterSecurityDomain = savedDomain;
                    }
                }

                CallFrame frame = new CallFrame ();
                initFrame (cx, scope, thisObj, args, null, 0, args.Length, ifun, null, frame);

                return InterpretLoop (cx, frame, (object)null);
            }
        }
        internal static string defaultObjectToSource(Context cx, IScriptable scope, IScriptable thisObj, object [] args)
        {
            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (1024)) {
                bool toplevel, iterating;
                if (cx.iterating == null) {
                    toplevel = true;
                    iterating = false;
                    cx.iterating = new ObjToIntMap (31);
                }
                else {
                    toplevel = false;
                    iterating = cx.iterating.has (thisObj);
                }

                System.Text.StringBuilder result = new System.Text.StringBuilder (128);
                if (toplevel) {
                    result.Append ("(");
                }
                result.Append ('{');

                // Make sure cx.iterating is set to null when done
                // so we don't leak memory
                try {
                    if (!iterating) {
                        cx.iterating.intern (thisObj); // stop recursion.
                        object [] ids = thisObj.GetIds ();
                        for (int i = 0; i < ids.Length; i++) {
                            if (i > 0)
                                result.Append (", ");
                            object id = ids [i];
                            object value;
                            if (id is int) {
                                int intId = ((int)id);
                                value = thisObj.Get (intId, thisObj);
                                result.Append (intId);
                            }
                            else {
                                string strId = (string)id;
                                value = thisObj.Get (strId, thisObj);
                                if (ScriptRuntime.isValidIdentifierName (strId)) {
                                    result.Append (strId);
                                }
                                else {
                                    result.Append ('\'');
                                    result.Append (ScriptRuntime.escapeString (strId, '\''));
                                    result.Append ('\'');
                                }
                            }
                            result.Append (':');
                            result.Append (ScriptRuntime.uneval (cx, scope, value));
                        }
                    }
                }
                finally {
                    if (toplevel) {
                        cx.iterating = null;
                    }
                }

                result.Append ('}');
                if (toplevel) {
                    result.Append (')');
                }
                return result.ToString ();
            }
        }
 /*
 * Top-down regular expression grammar, based closely on Perl4.
 *
 *  regexp:     altern                  A regular expression is one or more
 *              altern '|' regexp       alternatives separated by vertical bar.
 */
 private static bool parseDisjunction(CompilerState state)
 {
     using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (1024)) {
         if (!parseAlternative (state))
             return false;
         char [] source = state.cpbegin;
         int index = state.cp;
         if (index != source.Length && source [index] == '|') {
             RENode altResult;
             ++state.cp;
             altResult = new RENode (REOP_ALT);
             altResult.kid = state.result;
             if (!parseDisjunction (state))
                 return false;
             altResult.kid2 = state.result;
             state.result = altResult;
             /* ALT, <next>, ..., JUMP, <end> ... JUMP <end> */
             state.progLength += 9;
         }
         return true;
     }
 }
Exemple #5
0
        Node statement ()
        {
            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (512)) {
                try {
                    Node pn = statementHelper (null);
                    if (pn != null) {
                        return pn;
                    }
                }
                catch (ParserException) {
                }
            }

            // skip to end of statement
            int lineno = ts.Lineno;
            for (; ; ) {
                int tt = peekTokenOrEOL ();
                consumeToken ();
                switch (tt) {

                    case Token.ERROR:
                    case Token.EOF:
                    case Token.EOL:
                    case Token.SEMI:

                        goto guessingStatementEnd_brk;
                }
            }

        guessingStatementEnd_brk:
            ;

            return nf.CreateExprStatement (nf.CreateName ("error"), lineno);
        }
Exemple #6
0
        Node function (int functionType)
        {
            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (1024)) {
                int syntheticType = functionType;
                int baseLineno = ts.Lineno; // line number where source starts

                int functionSourceStart = decompiler.MarkFunctionStart (functionType);
                string name;
                Node memberExprNode = null;
                
                int tt = peekToken ();                
                if (tt == Token.NAME) {
                    consumeToken ();    
                    name = ts.String;
                    decompiler.AddName (name);
                    if (!matchToken (Token.LP)) {
                        if (compilerEnv.isAllowMemberExprAsFunctionName ()) {
                            // Extension to ECMA: if 'function <name>' does not follow
                            // by '(', assume <name> starts memberExpr
                            Node memberExprHead = nf.CreateName (name);
                            name = "";
                            memberExprNode = memberExprTail (false, memberExprHead);
                        }
                        mustMatchToken (Token.LP, "msg.no.paren.parms");
                    }
                }
                else if (matchToken (Token.LP)) {
                    // Anonymous function
                    name = "";
                }
                else {
                    name = "";
                    if (compilerEnv.isAllowMemberExprAsFunctionName ()) {
                        // Note that memberExpr can not start with '(' like
                        // in function (1+2).toString(), because 'function (' already
                        // processed as anonymous function
                        memberExprNode = memberExpr (false);
                    }
                    mustMatchToken (Token.LP, "msg.no.paren.parms");
                }

                if (memberExprNode != null) {
                    syntheticType = FunctionNode.FUNCTION_EXPRESSION;
                }

                bool nested = insideFunction ();

                FunctionNode fnNode = nf.CreateFunction (name);
                if (nested || nestingOfWith > 0) {
                    // 1. Nested functions are not affected by the dynamic scope flag
                    // as dynamic scope is already a parent of their scope.
                    // 2. Functions defined under the with statement also immune to
                    // this setup, in which case dynamic scope is ignored in favor
                    // of with object.
                    fnNode.itsIgnoreDynamicScope = true;
                }

                int functionIndex = currentScriptOrFn.addFunction (fnNode);

                int functionSourceEnd;

                ScriptOrFnNode savedScriptOrFn = currentScriptOrFn;
                currentScriptOrFn = fnNode;
                int savedNestingOfWith = nestingOfWith;
                nestingOfWith = 0;
                Hashtable savedLabelSet = labelSet;
                labelSet = null;
                ObjArray savedLoopSet = loopSet;
                loopSet = null;
                ObjArray savedLoopAndSwitchSet = loopAndSwitchSet;
                loopAndSwitchSet = null;

                Node body;
                try {
                    decompiler.AddToken (Token.LP);
                    if (!matchToken (Token.RP)) {
                        bool first = true;
                        do {
                            if (!first)
                                decompiler.AddToken (Token.COMMA);
                            first = false;
                            mustMatchToken (Token.NAME, "msg.no.parm");
                            string s = ts.String;
                            if (fnNode.hasParamOrVar (s)) {
                                AddWarning ("msg.dup.parms", s);
                            }
                            fnNode.addParam (s);
                            decompiler.AddName (s);
                        }
                        while (matchToken (Token.COMMA));

                        mustMatchToken (Token.RP, "msg.no.paren.after.parms");
                    }
                    decompiler.AddToken (Token.RP);

                    mustMatchToken (Token.LC, "msg.no.brace.body");
                    decompiler.AddEol (Token.LC);
                    body = parseFunctionBody ();
                    mustMatchToken (Token.RC, "msg.no.brace.after.body");

                    decompiler.AddToken (Token.RC);
                    functionSourceEnd = decompiler.MarkFunctionEnd (functionSourceStart);
                    if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
                        if (compilerEnv.LanguageVersion >= Context.Versions.JS1_2) {
                            // function f() {} function g() {} is not allowed in 1.2
                            // or later but for compatibility with old scripts
                            // the check is done only if language is
                            // explicitly set.
                            //  TODO: warning needed if version == VERSION_DEFAULT ?
                            tt = peekTokenOrEOL ();
                            if (tt == Token.FUNCTION) {
                                ReportError ("msg.no.semi.stmt");
                            }
                        }
                        // Add EOL only if function is not part of expression
                        // since it gets SEMI + EOL from Statement in that case
                        decompiler.AddToken (Token.EOL);
                    }
                }
                finally {
                    loopAndSwitchSet = savedLoopAndSwitchSet;
                    loopSet = savedLoopSet;
                    labelSet = savedLabelSet;
                    nestingOfWith = savedNestingOfWith;
                    currentScriptOrFn = savedScriptOrFn;
                }

                fnNode.setEncodedSourceBounds (functionSourceStart, functionSourceEnd);
                fnNode.SourceName = sourceURI;
                fnNode.BaseLineno = baseLineno;
                fnNode.EndLineno = ts.Lineno;

                Node pn = nf.initFunction (fnNode, functionIndex, body, syntheticType);
                if (memberExprNode != null) {
                    pn = nf.CreateAssignment (Token.ASSIGN, memberExprNode, pn, false);
                    if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
                        // TOOD: check JScript behavior: should it be createExprStatement?
                        pn = nf.CreateExprStatementNoReturn (pn, baseLineno);
                    }
                }
                return pn;
            }
        }
Exemple #7
0
        Node unaryExpr ()
        {
            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (4096)) {
                int tt;

                tt = peekToken ();

                switch (tt) {

                    case Token.VOID:
                    case Token.NOT:
                    case Token.BITNOT:
                    case Token.TYPEOF:
                        consumeToken ();
                        decompiler.AddToken (tt);
                        return nf.CreateUnary (tt, unaryExpr ());


                    case Token.ADD:
                        consumeToken ();
                        // Convert to special POS token in decompiler and parse tree
                        decompiler.AddToken (Token.POS);
                        return nf.CreateUnary (Token.POS, unaryExpr ());


                    case Token.SUB:
                        consumeToken ();
                        // Convert to special NEG token in decompiler and parse tree
                        decompiler.AddToken (Token.NEG);
                        return nf.CreateUnary (Token.NEG, unaryExpr ());


                    case Token.INC:
                    case Token.DEC:
                        consumeToken ();
                        decompiler.AddToken (tt);
                        return nf.CreateIncDec (tt, false, memberExpr (true));


                    case Token.DELPROP:
                        consumeToken ();
                        decompiler.AddToken (Token.DELPROP);
                        return nf.CreateUnary (Token.DELPROP, unaryExpr ());


                    case Token.ERROR:
                        consumeToken ();
                        break;

                    // XML stream encountered in expression.

                    case Token.LT:
                        if (compilerEnv.isXmlAvailable ()) {
                            consumeToken ();
                            Node pn = xmlInitializer ();
                            return memberExprTail (true, pn);
                        }
                        // Fall thru to the default handling of RELOP
                        goto default;


                    default: {
                            Node pn = memberExpr (true);

                            // Don't look across a newline boundary for a postfix incop.
                            tt = peekTokenOrEOL ();
                            if (tt == Token.INC || tt == Token.DEC) {
                                consumeToken ();
                                decompiler.AddToken (tt);
                                return nf.CreateIncDec (tt, true, pn);
                            }
                            return pn;
                        }

                }
                return nf.CreateName ("err"); // Only reached on error.  Try to continue.
            }
        }
Exemple #8
0
        private void transformCompilationUnit_r(ScriptOrFnNode tree, Node parent)
        {
            Node node = null;

            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier(1024)) {
                for (; ;)
                {
                    Node previous = null;
                    if (node == null)
                    {
                        node = parent.FirstChild;
                    }
                    else
                    {
                        previous = node;
                        node     = node.Next;
                    }
                    if (node == null)
                    {
                        break;
                    }

                    int type = node.Type;

                    switch (type)
                    {
                    case Token.LABEL:
                    case Token.SWITCH:
                    case Token.LOOP:
                        loops.push(node);
                        loopEnds.push(((Node.Jump)node).target);
                        break;


                    case Token.WITH: {
                        loops.push(node);
                        Node leave = node.Next;
                        if (leave.Type != Token.LEAVEWITH)
                        {
                            Context.CodeBug();
                        }
                        loopEnds.push(leave);
                        break;
                    }


                    case Token.TRY: {
                        Node.Jump jump          = (Node.Jump)node;
                        Node      finallytarget = jump.Finally;
                        if (finallytarget != null)
                        {
                            hasFinally = true;
                            loops.push(node);
                            loopEnds.push(finallytarget);
                        }
                        break;
                    }


                    case Token.TARGET:
                    case Token.LEAVEWITH:
                        if (!loopEnds.Empty && loopEnds.peek() == node)
                        {
                            loopEnds.pop();
                            loops.pop();
                        }
                        break;


                    case Token.RETURN: {
                        /* If we didn't support try/finally, it wouldn't be
                         * necessary to put LEAVEWITH nodes here... but as
                         * we do need a series of JSR FINALLY nodes before
                         * each RETURN, we need to ensure that each finally
                         * block gets the correct scope... which could mean
                         * that some LEAVEWITH nodes are necessary.
                         */
                        if (!hasFinally)
                        {
                            break;         // skip the whole mess.
                        }
                        Node unwindBlock = null;
                        for (int i = loops.size() - 1; i >= 0; i--)
                        {
                            Node n        = (Node)loops.Get(i);
                            int  elemtype = n.Type;
                            if (elemtype == Token.TRY || elemtype == Token.WITH)
                            {
                                Node unwind;
                                if (elemtype == Token.TRY)
                                {
                                    Node.Jump jsrnode   = new Node.Jump(Token.JSR);
                                    Node      jsrtarget = ((Node.Jump)n).Finally;
                                    jsrnode.target = jsrtarget;
                                    unwind         = jsrnode;
                                }
                                else
                                {
                                    unwind = new Node(Token.LEAVEWITH);
                                }
                                if (unwindBlock == null)
                                {
                                    unwindBlock = new Node(Token.BLOCK, node.Lineno);
                                }
                                unwindBlock.addChildToBack(unwind);
                            }
                        }
                        if (unwindBlock != null)
                        {
                            Node returnNode = node;
                            Node returnExpr = returnNode.FirstChild;
                            node = replaceCurrent(parent, previous, node, unwindBlock);
                            if (returnExpr == null)
                            {
                                unwindBlock.addChildToBack(returnNode);
                            }
                            else
                            {
                                Node store = new Node(Token.EXPR_RESULT, returnExpr);
                                unwindBlock.addChildToFront(store);
                                returnNode = new Node(Token.RETURN_RESULT);
                                unwindBlock.addChildToBack(returnNode);
                                // transform return expression
                                transformCompilationUnit_r(tree, store);
                            }
                            // skip transformCompilationUnit_r to avoid infinite loop

                            goto siblingLoop;
                        }
                        break;
                    }


                    case Token.BREAK:
                    case Token.CONTINUE: {
                        Node.Jump jump          = (Node.Jump)node;
                        Node.Jump jumpStatement = jump.JumpStatement;
                        if (jumpStatement == null)
                        {
                            Context.CodeBug();
                        }

                        for (int i = loops.size(); ;)
                        {
                            if (i == 0)
                            {
                                // Parser/IRFactory ensure that break/continue
                                // always has a jump statement associated with it
                                // which should be found
                                throw Context.CodeBug();
                            }
                            --i;
                            Node n = (Node)loops.Get(i);
                            if (n == jumpStatement)
                            {
                                break;
                            }

                            int elemtype = n.Type;
                            if (elemtype == Token.WITH)
                            {
                                Node leave = new Node(Token.LEAVEWITH);
                                previous = addBeforeCurrent(parent, previous, node, leave);
                            }
                            else if (elemtype == Token.TRY)
                            {
                                Node.Jump tryNode    = (Node.Jump)n;
                                Node.Jump jsrFinally = new Node.Jump(Token.JSR);
                                jsrFinally.target = tryNode.Finally;
                                previous          = addBeforeCurrent(parent, previous, node, jsrFinally);
                            }
                        }

                        if (type == Token.BREAK)
                        {
                            jump.target = jumpStatement.target;
                        }
                        else
                        {
                            jump.target = jumpStatement.Continue;
                        }
                        jump.Type = Token.GOTO;

                        break;
                    }


                    case Token.CALL:
                        visitCall(node, tree);
                        break;


                    case Token.NEW:
                        visitNew(node, tree);
                        break;


                    case Token.VAR: {
                        Node result = new Node(Token.BLOCK);
                        for (Node cursor = node.FirstChild; cursor != null;)
                        {
                            // Move cursor to next before createAssignment get chance
                            // to change n.next
                            Node n = cursor;
                            if (n.Type != Token.NAME)
                            {
                                Context.CodeBug();
                            }
                            cursor = cursor.Next;
                            if (!n.hasChildren())
                            {
                                continue;
                            }
                            Node init = n.FirstChild;
                            n.removeChild(init);
                            n.Type = Token.BINDNAME;
                            n      = new Node(Token.SETNAME, n, init);
                            Node pop = new Node(Token.EXPR_VOID, n, node.Lineno);
                            result.addChildToBack(pop);
                        }
                        node = replaceCurrent(parent, previous, node, result);
                        break;
                    }


                    case Token.NAME:
                    case Token.SETNAME:
                    case Token.DELPROP: {
                        // Turn name to var for faster access if possible
                        if (tree.Type != Token.FUNCTION || ((FunctionNode)tree).RequiresActivation)
                        {
                            break;
                        }
                        Node nameSource;
                        if (type == Token.NAME)
                        {
                            nameSource = node;
                        }
                        else
                        {
                            nameSource = node.FirstChild;
                            if (nameSource.Type != Token.BINDNAME)
                            {
                                if (type == Token.DELPROP)
                                {
                                    break;
                                }
                                throw Context.CodeBug();
                            }
                        }
                        string name = nameSource.String;
                        if (tree.hasParamOrVar(name))
                        {
                            if (type == Token.NAME)
                            {
                                node.Type = Token.GETVAR;
                            }
                            else if (type == Token.SETNAME)
                            {
                                node.Type       = Token.SETVAR;
                                nameSource.Type = Token.STRING;
                            }
                            else if (type == Token.DELPROP)
                            {
                                // Local variables are by definition permanent
                                Node n = new Node(Token.FALSE);
                                node = replaceCurrent(parent, previous, node, n);
                            }
                            else
                            {
                                throw Context.CodeBug();
                            }
                        }
                        break;
                    }
                    }

                    transformCompilationUnit_r(tree, node);

siblingLoop:
                    ;
                }
            }
        }