You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2016/04/13 20:56:29 UTC

[37/51] [partial] git commit: [flex-falcon] [refs/heads/feature/maven-migration-test] - - Check-In of the migrated project to make error analysis easier

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSDocEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSDocEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSDocEmitter.java
new file mode 100644
index 0000000..3147c20
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSDocEmitter.java
@@ -0,0 +1,270 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.codegen.js.vf2js;
+
+import org.apache.flex.compiler.asdoc.flexjs.ASDocComment;
+import org.apache.flex.compiler.clients.MXMLJSC;
+import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.common.DependencyType;
+import org.apache.flex.compiler.constants.IASKeywordConstants;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.definitions.references.IReference;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
+import org.apache.flex.compiler.internal.definitions.InterfaceDefinition;
+import org.apache.flex.compiler.internal.scopes.ASScope;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.tree.as.IDefinitionNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IParameterNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+
+public class JSVF2JSDocEmitter extends JSGoogDocEmitter
+{
+
+    public JSVF2JSDocEmitter(IJSEmitter emitter)
+    {
+        super(emitter);
+    }
+
+    @Override
+    public void emitMethodDoc(IFunctionNode node, ICompilerProject project)
+    {
+        IClassDefinition classDefinition = resolveClassDefinition(node);
+
+        ASDocComment asDoc = (ASDocComment) node.getASDocComment();
+        
+        if (node instanceof IFunctionNode)
+        {
+            boolean hasDoc = false;
+
+            if (node.isConstructor())
+            {
+                if (asDoc != null && MXMLJSC.keepASDoc)
+                    write(asDoc.commentNoEnd());
+                else
+                    begin();
+                hasDoc = true;
+
+                emitJSDocLine(JSEmitterTokens.CONSTRUCTOR);
+
+                IClassDefinition parent = (IClassDefinition) node
+                        .getDefinition().getParent();
+                IClassDefinition superClass = parent.resolveBaseClass(project);
+                String qname = (superClass != null) ? superClass.getQualifiedName() : null;
+
+                if (superClass != null
+                        && !qname.equals(IASLanguageConstants.Object))
+                    emitExtends(superClass, superClass.getPackageName());
+
+                IReference[] references = classDefinition
+                        .getImplementedInterfaceReferences();
+                for (IReference iReference : references)
+                {
+                    ITypeDefinition type = (ITypeDefinition) iReference
+                            .resolve(project, (ASScope) classDefinition
+                                    .getContainingScope(),
+                                    DependencyType.INHERITANCE, true);
+                    if (type == null)
+                    	System.out.println(iReference.getDisplayString() + " not resolved in " + classDefinition.getQualifiedName());
+                    emitImplements(type, type.getPackageName());
+                }
+            }
+            else
+            {
+                String ns = node.getNamespace();
+                if (ns != null)
+                {
+                    if (asDoc != null && MXMLJSC.keepASDoc)
+                        write(asDoc.commentNoEnd());
+                    else
+                        begin();
+                    emitMethodAccess(node);
+                    hasDoc = true;
+                }
+            }
+
+            // @param
+            IParameterNode[] parameters = node.getParameterNodes();
+            for (IParameterNode pnode : parameters)
+            {
+                if (!hasDoc)
+                {
+                    if (asDoc != null && MXMLJSC.keepASDoc)
+                        write(asDoc.commentNoEnd());
+                    else
+                        begin();
+                    emitMethodAccess(node);
+                    hasDoc = true;
+                }
+
+                IExpressionNode enode = pnode.getNameExpressionNode();
+
+                // ToDo (erikdebruin): add VF2JS conditional -> only use check during full SDK compilation
+                ITypeDefinition tdef = enode.resolveType(project);
+                if (tdef == null)
+                    continue;
+                
+                emitParam(pnode, tdef.getPackageName());
+            }
+
+            if (!node.isConstructor())
+            {
+                // @return
+                String returnType = node.getReturnType();
+                if (returnType != ""
+                        && returnType != ASEmitterTokens.VOID.getToken())
+                {
+                    if (!hasDoc)
+                    {
+                        if (asDoc != null && MXMLJSC.keepASDoc)
+                            write(asDoc.commentNoEnd());
+                        else
+                            begin();
+                        emitMethodAccess(node);
+                        hasDoc = true;
+                    }
+
+                    ITypeDefinition tdef = ((IFunctionDefinition)node.getDefinition())
+                            .resolveReturnType(project);
+
+                    String packageName = "";
+                    if (tdef instanceof InterfaceDefinition)
+                        packageName = tdef.getPackageName();
+                    else
+                        packageName = node.getPackageName();
+                    
+                    emitReturn(node, packageName);
+                }
+
+                // @override
+                Boolean override = node.hasModifier(ASModifier.OVERRIDE);
+                if (override)
+                {
+                    if (!hasDoc)
+                    {
+                        if (asDoc != null && MXMLJSC.keepASDoc)
+                            write(asDoc.commentNoEnd());
+                        else
+                            begin();
+                        emitMethodAccess(node);
+                        hasDoc = true;
+                    }
+
+                    emitOverride(node);
+                }
+            }
+
+            if (hasDoc)
+                end();
+        }
+    }
+    
+    @Override
+    public void emitVarDoc(IVariableNode node, IDefinition def, ICompilerProject project)
+    {
+        String packageName = "";
+        if (def != null)
+            packageName = def.getPackageName();
+
+        if (!node.isConst())
+        {
+            IDefinition ndef = node.getDefinition();
+            if (emitter != null && emitter instanceof JSVF2JSEmitter)
+            {
+                if (project != null)
+                {
+                    packageName = ((ITypeDefinition)ndef.resolveType(project))
+                            .getPackageName();
+                }
+            }
+        }
+        
+        emitTypeShort(node, packageName);
+    }
+
+    
+    public void emitInterfaceMemberDoc(IDefinitionNode node, ICompilerProject project)
+    {
+        boolean hasDoc = false;
+        
+        ASDocComment asDoc = (ASDocComment) ((IFunctionNode) node).getASDocComment();
+        
+        String returnType = ((IFunctionNode) node).getReturnType();
+        if (returnType != ""
+                && returnType != ASEmitterTokens.VOID.getToken()) // has return
+        {
+            if (asDoc != null && MXMLJSC.keepASDoc)
+                write(asDoc.commentNoEnd());
+            else
+                begin();
+            hasDoc = true;
+
+            ITypeDefinition tdef = ((IFunctionDefinition)node.getDefinition())
+                    .resolveReturnType(project);
+
+            emitReturn((IFunctionNode) node, tdef.getPackageName());
+        }
+
+        IParameterNode[] parameters = ((IFunctionNode) node).getParameterNodes();
+        for (IParameterNode pnode : parameters)
+        {
+            if (!hasDoc)
+            {
+                if (asDoc != null && MXMLJSC.keepASDoc)
+                    write(asDoc.commentNoEnd());
+                else
+                    begin();
+                hasDoc = true;
+            }
+
+            IExpressionNode enode = pnode.getNameExpressionNode();
+            emitParam(pnode, enode.resolveType(project).getPackageName());
+        }
+
+        if (hasDoc)
+            end();
+    }
+
+    @Override
+    public void emitMethodAccess(IFunctionNode node)
+    {
+        String ns = node.getNamespace();
+        if (ns == IASKeywordConstants.PRIVATE)
+        {
+            emitPrivate(node);
+        }
+        else if (ns == IASKeywordConstants.PROTECTED)
+        {
+            emitProtected(node);
+        }
+        else if (ns == IASKeywordConstants.PUBLIC)
+        {
+            emitPublic(node);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/c3dce49f/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSEmitter.java
new file mode 100644
index 0000000..4f9d5f2
--- /dev/null
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/vf2js/JSVF2JSEmitter.java
@@ -0,0 +1,1950 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.codegen.js.vf2js;
+
+import java.io.FilterWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.flex.compiler.codegen.IASGlobalFunctionConstants;
+import org.apache.flex.compiler.codegen.js.goog.IJSGoogDocEmitter;
+import org.apache.flex.compiler.codegen.js.vf2js.IJSVF2JSEmitter;
+import org.apache.flex.compiler.common.ASModifier;
+import org.apache.flex.compiler.common.ModifiersSet;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition;
+import org.apache.flex.compiler.definitions.IFunctionDefinition.FunctionClassification;
+import org.apache.flex.compiler.definitions.INamespaceDefinition;
+import org.apache.flex.compiler.definitions.IPackageDefinition;
+import org.apache.flex.compiler.definitions.IParameterDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.JSSessionModel;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitter;
+import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
+import org.apache.flex.compiler.internal.codegen.js.utils.EmitterUtils;
+import org.apache.flex.compiler.internal.definitions.AccessorDefinition;
+import org.apache.flex.compiler.internal.definitions.ClassDefinition;
+import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
+import org.apache.flex.compiler.internal.definitions.InterfaceDefinition;
+import org.apache.flex.compiler.internal.definitions.ParameterDefinition;
+import org.apache.flex.compiler.internal.definitions.VariableDefinition;
+import org.apache.flex.compiler.internal.projects.CompilerProject;
+import org.apache.flex.compiler.internal.projects.FlexJSProject;
+import org.apache.flex.compiler.internal.scopes.ASProjectScope;
+import org.apache.flex.compiler.internal.scopes.PackageScope;
+import org.apache.flex.compiler.internal.scopes.TypeScope;
+import org.apache.flex.compiler.internal.tree.as.BinaryOperatorAssignmentNode;
+import org.apache.flex.compiler.internal.tree.as.ChainedVariableNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionCallNode;
+import org.apache.flex.compiler.internal.tree.as.FunctionNode;
+import org.apache.flex.compiler.internal.tree.as.NonResolvingIdentifierNode;
+import org.apache.flex.compiler.internal.tree.as.ParameterNode;
+import org.apache.flex.compiler.internal.tree.as.RegExpLiteralNode;
+import org.apache.flex.compiler.internal.tree.as.UnaryOperatorAtNode;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.scopes.IASScope;
+import org.apache.flex.compiler.tree.ASTNodeID;
+import org.apache.flex.compiler.tree.as.IASNode;
+import org.apache.flex.compiler.tree.as.IAccessorNode;
+import org.apache.flex.compiler.tree.as.IBinaryOperatorNode;
+import org.apache.flex.compiler.tree.as.IClassNode;
+import org.apache.flex.compiler.tree.as.IContainerNode;
+import org.apache.flex.compiler.tree.as.IDefinitionNode;
+import org.apache.flex.compiler.tree.as.IEmbedNode;
+import org.apache.flex.compiler.tree.as.IExpressionNode;
+import org.apache.flex.compiler.tree.as.IForLoopNode;
+import org.apache.flex.compiler.tree.as.IFunctionCallNode;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IGetterNode;
+import org.apache.flex.compiler.tree.as.IIdentifierNode;
+import org.apache.flex.compiler.tree.as.IInterfaceNode;
+import org.apache.flex.compiler.tree.as.IKeywordNode;
+import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
+import org.apache.flex.compiler.tree.as.ILiteralNode;
+import org.apache.flex.compiler.tree.as.ILiteralNode.LiteralType;
+import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode;
+import org.apache.flex.compiler.tree.as.IParameterNode;
+import org.apache.flex.compiler.tree.as.ISetterNode;
+import org.apache.flex.compiler.tree.as.ITypeNode;
+import org.apache.flex.compiler.tree.as.ITypedExpressionNode;
+import org.apache.flex.compiler.tree.as.IVariableExpressionNode;
+import org.apache.flex.compiler.tree.as.IVariableNode;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.compiler.utils.ASNodeUtils;
+import org.apache.flex.compiler.utils.NativeUtils;
+
+/**
+ * Concrete implementation of the 'vf2js' JavaScript production.
+ * 
+ * @author Erik de Bruin
+ */
+public class JSVF2JSEmitter extends JSGoogEmitter implements IJSVF2JSEmitter
+{
+
+    public JSVF2JSEmitter(FilterWriter out)
+    {
+        super(out);
+    }
+
+    @Override
+    protected String getIndent(int numIndent)
+    {
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < numIndent; i++)
+            sb.append(JSFlexJSEmitterTokens.INDENT.getToken());
+        return sb.toString();
+    }
+
+    @Override
+    protected void emitMemberName(IDefinitionNode node)
+    {
+        write(node.getName());
+    }
+
+    @Override
+    public void emitClass(IClassNode node)
+    {
+        IClassDefinition definition = node.getDefinition();
+        getModel().setCurrentClass(definition);
+
+        project = getWalker().getProject();
+
+        IFunctionDefinition ctorDefinition = definition.getConstructor();
+
+        // Static-only (Singleton) classes may not have a constructor
+        if (ctorDefinition != null)
+        {
+            IFunctionNode ctorNode = (IFunctionNode) ctorDefinition.getNode();
+            if (ctorNode != null)
+            {
+                // constructor
+                emitMethod(ctorNode);
+                write(ASEmitterTokens.SEMICOLON);
+            }
+            else
+            {
+                String qname = parseQualifiedName(definition);
+                if (qname != null && !qname.equals(""))
+                {
+                    write(qname);
+                    write(ASEmitterTokens.SPACE);
+                    writeToken(ASEmitterTokens.EQUAL);
+                    write(ASEmitterTokens.FUNCTION);
+                    write(ASEmitterTokens.PAREN_OPEN);
+                    write(ASEmitterTokens.PAREN_CLOSE);
+                    write(ASEmitterTokens.SPACE);
+                    write(ASEmitterTokens.BLOCK_OPEN);
+                    writeNewline();
+                    write(ASEmitterTokens.BLOCK_CLOSE);
+                    write(ASEmitterTokens.SEMICOLON);
+                }
+            }
+        }
+
+        IDefinitionNode[] dnodes = node.getAllMemberNodes();
+        for (IDefinitionNode dnode : dnodes)
+        {
+            if (dnode.getNodeID() == ASTNodeID.VariableID)
+            {
+                writeNewline();
+                writeNewline();
+                writeNewline();
+                emitField((IVariableNode) dnode);
+                write(ASEmitterTokens.SEMICOLON);
+            }
+            else if (dnode.getNodeID() == ASTNodeID.FunctionID)
+            {
+                if (!((IFunctionNode) dnode).isConstructor())
+                {
+                    writeNewline();
+                    writeNewline();
+                    writeNewline();
+                    emitMethod((IFunctionNode) dnode);
+                    write(ASEmitterTokens.SEMICOLON);
+                }
+            }
+            else if (dnode.getNodeID() == ASTNodeID.GetterID
+                    || dnode.getNodeID() == ASTNodeID.SetterID)
+            {
+                writeNewline();
+                writeNewline();
+                writeNewline();
+                emitAccessors((IAccessorNode) dnode);
+                write(ASEmitterTokens.SEMICOLON);
+            }
+        }
+    }
+
+    @Override
+    public void emitInterface(IInterfaceNode node)
+    {
+        ICompilerProject project = getWalker().getProject();
+
+        getDocEmitter().emitInterfaceDoc(node, project);
+
+        String qname = parseQualifiedName(node);
+        if (qname != null && !qname.equals(""))
+        {
+            write(qname);
+            write(ASEmitterTokens.SPACE);
+            writeToken(ASEmitterTokens.EQUAL);
+            write(ASEmitterTokens.FUNCTION);
+            write(ASEmitterTokens.PAREN_OPEN);
+            write(ASEmitterTokens.PAREN_CLOSE);
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.BLOCK_OPEN);
+            writeNewline();
+            write(ASEmitterTokens.BLOCK_CLOSE);
+            write(ASEmitterTokens.SEMICOLON);
+        }
+
+        final IDefinitionNode[] members = node.getAllMemberDefinitionNodes();
+        for (IDefinitionNode mnode : members)
+        {
+            boolean isAccessor = mnode.getNodeID() == ASTNodeID.GetterID
+                    || mnode.getNodeID() == ASTNodeID.SetterID;
+
+            writeNewline();
+            writeNewline();
+            writeNewline();
+
+            getDocEmitter().emitInterfaceMemberDoc(mnode, project);
+
+            write(qname);
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(JSEmitterTokens.PROTOTYPE);
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            if (isAccessor)
+            {
+                writeGetSetPrefix(mnode.getNodeID() == ASTNodeID.GetterID);
+            }
+            write(parseQualifiedName(mnode));
+            write(ASEmitterTokens.SPACE);
+            writeToken(ASEmitterTokens.EQUAL);
+            write(ASEmitterTokens.FUNCTION);
+            emitParameters(((IFunctionNode) mnode).getParametersContainerNode());
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.BLOCK_OPEN);
+            write(ASEmitterTokens.BLOCK_CLOSE);
+            write(ASEmitterTokens.SEMICOLON);
+        }
+    }
+
+    @Override
+    public void emitFunctionBlockHeader(IFunctionNode node)
+    {
+        IDefinition def = node.getDefinition();
+        boolean isStatic = false;
+        if (def != null && def.isStatic())
+            isStatic = true;
+        boolean isLocal = false;
+        if (node.getFunctionClassification() == IFunctionDefinition.FunctionClassification.LOCAL)
+            isLocal = true;
+        if (EmitterUtils.hasBody(node) && !isStatic && !isLocal)
+            emitSelfReference(node);
+
+        emitRestParameterCodeBlock(node);
+
+        emitDefaultParameterCodeBlock(node);
+
+        if (node.isConstructor())
+        {
+            emitVarNonLiteralAssignments();
+        }
+
+        if (node.isConstructor() && hasSuperClass(node)
+                && !EmitterUtils.hasSuperCall(node.getScopedNode()))
+            emitSuperCall(node, JSSessionModel.CONSTRUCTOR_FULL);
+    }
+
+    private void emitVarNonLiteralAssignments()
+    {
+        // (erikdebruin): If the initial value of a variable is set using
+        //                a method, JS needs this initialization to be done
+        //                in the constructor
+        IClassNode cdnode = (IClassNode) getModel().getCurrentClass().getNode();
+        IDefinitionNode[] dnodes = cdnode.getAllMemberNodes();
+        for (IDefinitionNode dnode : dnodes)
+        {
+            if (dnode.getNodeID() == ASTNodeID.VariableID)
+            {
+                IVariableNode vnode = (IVariableNode) dnode;
+                IExpressionNode avnode = vnode.getAssignedValueNode();
+                if (avnode != null && !(avnode instanceof ILiteralNode)
+                        && !(avnode instanceof IEmbedNode))
+                {
+                    writeNewline("", true);
+                    if (vnode.hasModifier(ASModifier.STATIC))
+                    {
+                        write(parseQualifiedName(cdnode));
+                    }
+                    else
+                    {
+                        write(ASEmitterTokens.THIS);
+                    }
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    writeToken(vnode.getName());
+                    writeToken(ASEmitterTokens.EQUAL);
+                    getWalker().walk(avnode);
+                    indentPop();
+                    writeNewline(ASEmitterTokens.SEMICOLON);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void emitVarDeclaration(IVariableNode node)
+    {
+        if (!(node instanceof ChainedVariableNode))
+        {
+            // (erikdebruin): check for 'var i:int = 0, j:int = 0' containers
+            IASNode pnode = node.getParent();
+            if (!(pnode instanceof IVariableExpressionNode)
+                    || node.getChild(0) instanceof IKeywordNode)
+            {
+                emitMemberKeyword(node);
+            }
+        }
+
+        IExpressionNode avnode = node.getAssignedValueNode();
+        if (avnode != null)
+        {
+            IDefinition def = avnode.resolveType(getWalker().getProject());
+
+            String opcode = avnode.getNodeID().getParaphrase();
+            if (opcode != "AnonymousFunction")
+                getDocEmitter().emitVarDoc(node, def, getWalker().getProject());
+        }
+        else
+        {
+            getDocEmitter().emitVarDoc(node, null, getWalker().getProject());
+        }
+
+        emitDeclarationName(node);
+        if (avnode != null && !(avnode instanceof IEmbedNode))
+        {
+            write(ASEmitterTokens.SPACE);
+            writeToken(ASEmitterTokens.EQUAL);
+            emitAssignedValue(avnode);
+        }
+
+        if (!(node instanceof ChainedVariableNode))
+        {
+            // check for chained variables
+            int len = node.getChildCount();
+            for (int i = 0; i < len; i++)
+            {
+                IASNode child = node.getChild(i);
+                if (child instanceof ChainedVariableNode)
+                {
+                    writeToken(ASEmitterTokens.COMMA);
+                    emitVarDeclaration((IVariableNode) child);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void emitMemberKeyword(IDefinitionNode node)
+    {
+        if (node instanceof IFunctionNode)
+        {
+            writeToken(ASEmitterTokens.FUNCTION);
+        }
+        else if (node instanceof IVariableNode)
+        {
+            writeToken(ASEmitterTokens.VAR);
+        }
+    }
+
+    @Override
+    public void emitField(IVariableNode node)
+    {
+        IDefinition definition = EmitterUtils.getClassDefinition(node);
+
+        IDefinition def = null;
+        IExpressionNode enode = node.getVariableTypeNode();//getAssignedValueNode();
+        if (enode != null)
+        {
+            if (project == null)
+                project = getWalker().getProject();
+
+            def = enode.resolveType(project);
+        }
+
+        getDocEmitter().emitFieldDoc(node, def, project);
+
+        IDefinition ndef = node.getDefinition();
+
+        ModifiersSet modifierSet = ndef.getModifiers();
+        String root = "";
+        if (modifierSet != null && !modifierSet.hasModifier(ASModifier.STATIC))
+        {
+            root = JSEmitterTokens.PROTOTYPE.getToken();
+            root += ASEmitterTokens.MEMBER_ACCESS.getToken();
+        }
+
+        if (definition == null)
+            definition = ndef.getContainingScope().getDefinition();
+
+        write(parseQualifiedName(definition)
+                + ASEmitterTokens.MEMBER_ACCESS.getToken() + root
+                + node.getName());
+
+        IExpressionNode vnode = node.getAssignedValueNode();
+        if (vnode != null && vnode instanceof ILiteralNode)
+        {
+            write(ASEmitterTokens.SPACE);
+            writeToken(ASEmitterTokens.EQUAL);
+            getWalker().walk(vnode);
+        }
+
+        if (!(node instanceof ChainedVariableNode))
+        {
+            int len = node.getChildCount();
+            for (int i = 0; i < len; i++)
+            {
+                IASNode child = node.getChild(i);
+                if (child instanceof ChainedVariableNode)
+                {
+                    writeNewline(ASEmitterTokens.SEMICOLON);
+                    writeNewline();
+                    emitField((IVariableNode) child);
+                }
+            }
+        }
+        if (node.getNodeID() == ASTNodeID.BindableVariableID)
+        {
+            // [Bindable]
+            writeNewline(ASEmitterTokens.SEMICOLON.getToken());
+            writeNewline();
+            writeNewline("/**");
+            writeNewline("@export");
+            writeNewline(" */");
+            writeNewline(parseQualifiedName(definition)
+                    + ASEmitterTokens.MEMBER_ACCESS.getToken() + root + "get_"
+                    + node.getName() + ASEmitterTokens.SPACE.getToken()
+                    + ASEmitterTokens.EQUAL.getToken()
+                    + ASEmitterTokens.SPACE.getToken()
+                    + ASEmitterTokens.FUNCTION.getToken()
+                    + ASEmitterTokens.PAREN_OPEN.getToken()
+                    + ASEmitterTokens.PAREN_CLOSE.getToken()
+                    + ASEmitterTokens.SPACE.getToken()
+                    + ASEmitterTokens.BLOCK_OPEN.getToken());
+            writeNewline(ASEmitterTokens.RETURN.getToken()
+                    + ASEmitterTokens.SPACE.getToken()
+                    + ASEmitterTokens.THIS.getToken()
+                    + ASEmitterTokens.MEMBER_ACCESS.getToken() + node.getName()
+                    + ASEmitterTokens.SEMICOLON.getToken());
+            writeNewline(ASEmitterTokens.BLOCK_CLOSE.getToken()
+                    + ASEmitterTokens.SEMICOLON.getToken());
+            writeNewline();
+            writeNewline("/**");
+            writeNewline("@export");
+            writeNewline(" */");
+            writeNewline(parseQualifiedName(definition)
+                    + ASEmitterTokens.MEMBER_ACCESS.getToken() + root + "set_"
+                    + node.getName() + ASEmitterTokens.SPACE.getToken()
+                    + ASEmitterTokens.EQUAL.getToken()
+                    + ASEmitterTokens.SPACE.getToken()
+                    + ASEmitterTokens.FUNCTION.getToken()
+                    + ASEmitterTokens.PAREN_OPEN.getToken() + "value"
+                    + ASEmitterTokens.PAREN_CLOSE.getToken()
+                    + ASEmitterTokens.SPACE.getToken()
+                    + ASEmitterTokens.BLOCK_OPEN.getToken());
+            writeNewline("if (value != " + ASEmitterTokens.THIS.getToken()
+                    + ASEmitterTokens.MEMBER_ACCESS.getToken() + node.getName()
+                    + ") {");
+            writeNewline("    var oldValue = "
+                    + ASEmitterTokens.THIS.getToken()
+                    + ASEmitterTokens.MEMBER_ACCESS.getToken() + node.getName()
+                    + ASEmitterTokens.SEMICOLON.getToken());
+            writeNewline("    " + ASEmitterTokens.THIS.getToken()
+                    + ASEmitterTokens.MEMBER_ACCESS.getToken() + node.getName()
+                    + " = value;");
+            writeNewline("    this.dispatchEvent(org.apache.flex.events.ValueChangeEvent.createUpdateEvent(");
+            writeNewline("         this, \"" + node.getName()
+                    + "\", oldValue, value));");
+            writeNewline("}");
+            write(ASEmitterTokens.BLOCK_CLOSE.getToken());
+
+        }
+    }
+
+    @Override
+    public void emitAccessors(IAccessorNode node)
+    {
+        if (node.getNodeID() == ASTNodeID.GetterID)
+        {
+            emitGetAccessor((IGetterNode) node);
+        }
+        else if (node.getNodeID() == ASTNodeID.SetterID)
+        {
+            emitSetAccessor((ISetterNode) node);
+        }
+    }
+
+    @Override
+    public void emitMethod(IFunctionNode node)
+    {
+        FunctionNode fn = (FunctionNode) node;
+        fn.parseFunctionBody(getProblems());
+
+        ICompilerProject project = getWalker().getProject();
+
+        getDocEmitter().emitMethodDoc(node, project);
+
+        boolean isConstructor = node.isConstructor();
+
+        String qname = parseQualifiedName(getTypeDefinition(node));
+        if (qname != null && !qname.equals(""))
+        {
+            write(qname);
+            if (!isConstructor)
+            {
+                write(ASEmitterTokens.MEMBER_ACCESS);
+                if (!fn.hasModifier(ASModifier.STATIC))
+                {
+                    write(JSEmitterTokens.PROTOTYPE);
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                }
+            }
+        }
+
+        if (!isConstructor)
+            emitMemberName(node);
+
+        write(ASEmitterTokens.SPACE);
+        writeToken(ASEmitterTokens.EQUAL);
+        write(ASEmitterTokens.FUNCTION);
+
+        emitParameters(node.getParametersContainerNode());
+
+        boolean hasSuperClass = hasSuperClass(node);
+
+        if (isConstructor && node.getScopedNode().getChildCount() == 0)
+        {
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.BLOCK_OPEN);
+            emitVarNonLiteralAssignments();
+            if (hasSuperClass)
+            {
+                emitSuperCall(node, JSSessionModel.CONSTRUCTOR_EMPTY);
+                writeNewline();
+            }
+            write(ASEmitterTokens.BLOCK_CLOSE);
+        }
+
+        if (!isConstructor || node.getScopedNode().getChildCount() > 0)
+            emitMethodScope(node.getScopedNode());
+
+        if (isConstructor && hasSuperClass)
+        {
+            writeNewline(ASEmitterTokens.SEMICOLON);
+            write(JSGoogEmitterTokens.GOOG_INHERITS);
+            write(ASEmitterTokens.PAREN_OPEN);
+            write(qname);
+            writeToken(ASEmitterTokens.COMMA);
+            String sname = parseQualifiedName(getSuperClassDefinition(node,
+                    project));
+            if (sname.equals(IASLanguageConstants.Object))
+                sname = IASLanguageConstants.Class;
+            write(sname);
+            write(ASEmitterTokens.PAREN_CLOSE);
+        }
+    }
+
+    protected boolean hasSuperClass(IDefinitionNode node)
+    {
+        ICompilerProject project = getWalker().getProject();
+        IClassDefinition superClassDefinition = getSuperClassDefinition(node,
+                project);
+
+        if (superClassDefinition == null)
+            return false;
+
+        String qname = parseQualifiedName(superClassDefinition);
+
+        // ToDo (erikdebruin): need this to get the JS version of the SDK in 
+        //                     shape?
+        boolean useClassAsSuperClass = !qname
+                .equals(IASLanguageConstants.Object);
+        if (!useClassAsSuperClass)
+        {
+            if (parseQualifiedName(node).equals("mx.core.EmbeddedFontRegistry")
+                    || parseQualifiedName(node).equals(
+                            "mx.managers.HistoryManagerImpl")
+                    || parseQualifiedName(node).equals(
+                            "mx.core.TextFieldFactory"))
+            {
+                useClassAsSuperClass = true;
+            }
+        }
+
+        return superClassDefinition != null && useClassAsSuperClass;
+    }
+
+    @Override
+    public void emitFunctionCall(IFunctionCallNode node)
+    {
+        IASNode cnode = node.getChild(0);
+
+        if (cnode.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+            cnode = cnode.getChild(0);
+
+        ASTNodeID id = cnode.getNodeID();
+        if (id != ASTNodeID.SuperID)
+        {
+            ICompilerProject project = null;
+            IDefinition def = null;
+
+            boolean isClassCast = false;
+
+            if (node.isNewExpression())
+            {
+                writeToken(ASEmitterTokens.NEW);
+            }
+            else
+            {
+                if (project == null)
+                    project = getWalker().getProject();
+
+                def = node.getNameNode().resolve(project);
+
+                isClassCast = (def instanceof ClassDefinition || def instanceof InterfaceDefinition)
+                        && !(NativeUtils.isJSNative(def.getBaseName()));
+            }
+
+            if (node.isNewExpression())
+            {
+                if (project == null)
+                    project = getWalker().getProject();
+
+                def = node.resolveCalledExpression(project);
+                // all new calls to a class should be fully qualified names
+                if (def instanceof ClassDefinition)
+                    write(parseQualifiedName(def));
+                else
+                    // I think we still need this for "new someVarOfTypeClass"
+                    getWalker().walk(node.getNameNode());
+                emitArguments(node.getArgumentsNode());
+            }
+            else if (!isClassCast)
+            {
+                if (def != null)
+                {
+                    boolean isInt = def.getBaseName().equals(
+                            IASGlobalFunctionConstants._int);
+                    if (isInt
+                            || def.getBaseName().equals(
+                                    IASGlobalFunctionConstants.trace)
+                            || def.getBaseName().equals(
+                                    IASGlobalFunctionConstants.uint))
+                    {
+                        write(JSFlexJSEmitterTokens.LANGUAGE_QNAME);
+                        write(ASEmitterTokens.MEMBER_ACCESS);
+                        if (isInt)
+                            write(JSFlexJSEmitterTokens.UNDERSCORE);
+                    }
+                }
+                getWalker().walk(node.getNameNode());
+                emitArguments(node.getArgumentsNode());
+            }
+            else
+            {
+                emitIsAs(node.getArgumentNodes()[0], node.getNameNode(),
+                        ASTNodeID.Op_AsID, true);
+            }
+        }
+        else
+        {
+            emitSuperCall(node, JSSessionModel.SUPER_FUNCTION_CALL);
+        }
+    }
+
+    //--------------------------------------------------------------------------
+
+    @Override
+    protected void emitSelfReference(IFunctionNode node)
+    {
+        // we don't want 'var self = this;' in FlexJS
+    }
+
+    private boolean writeThis(IIdentifierNode node)
+    {
+        if (node instanceof NonResolvingIdentifierNode)
+            return false;
+
+        IClassNode classNode = (IClassNode) node
+                .getAncestorOfType(IClassNode.class);
+
+        IDefinition nodeDef = node.resolve(project);
+
+        IASNode parentNode = node.getParent();
+        ASTNodeID parentNodeId = parentNode.getNodeID();
+
+        IASNode firstChild = parentNode.getChild(0);
+        IClassDefinition thisClass = getModel().getCurrentClass();
+
+        boolean identifierIsMemberAccess = parentNodeId == ASTNodeID.MemberAccessExpressionID;
+
+        if (classNode == null) // script in MXML and AS interface definitions
+        {
+            if (nodeDef instanceof ParameterDefinition)
+                return false;
+
+            if (nodeDef instanceof VariableDefinition)
+            {
+                IDefinition pdef = ((VariableDefinition) nodeDef).getParent();
+
+                if (thisClass == null || !isSameClass(pdef, thisClass, project))
+                    return false;
+
+                if (identifierIsMemberAccess)
+                    return node == firstChild;
+
+                return parentNodeId == ASTNodeID.ContainerID
+                        || !(parentNode instanceof ParameterNode);
+            }
+            else if (nodeDef instanceof AccessorDefinition)
+            {
+                IDefinition pdef = ((AccessorDefinition) nodeDef).getParent();
+
+                if (thisClass == null || !isSameClass(pdef, thisClass, project))
+                    return false;
+
+                if (identifierIsMemberAccess)
+                    return node == firstChild;
+
+                return true;
+            }
+            else if (parentNodeId == ASTNodeID.ContainerID
+                    && nodeDef instanceof FunctionDefinition)
+            {
+                return ((FunctionDefinition) nodeDef)
+                        .getFunctionClassification() == FunctionClassification.CLASS_MEMBER; // for 'goog.bind'
+            }
+            else
+            {
+                return parentNodeId == ASTNodeID.FunctionCallID
+                        && !(nodeDef instanceof AccessorDefinition)
+                        && !identifierIsMemberAccess;
+            }
+        }
+        else
+        {
+            if (nodeDef != null && !nodeDef.isInternal()
+                    && isClassMember(nodeDef, classNode))
+            {
+                if (identifierIsMemberAccess)
+                {
+                    if (parentNode.getNodeID() == ASTNodeID.MemberAccessExpressionID
+                            && parentNode.getChild(0).getNodeID() == ASTNodeID.SuperID
+                            && !isSuperCallForOverride(node))
+                    {
+                        return true;
+                    }
+
+                    return node == firstChild;
+                }
+                else
+                {
+                    boolean identifierIsLocalFunction = nodeDef instanceof FunctionDefinition
+                            && !(nodeDef instanceof AccessorDefinition)
+                            && ((FunctionDefinition) nodeDef)
+                                    .getFunctionClassification() == IFunctionDefinition.FunctionClassification.LOCAL;
+
+                    if (nodeDef instanceof IParameterDefinition)
+                        return false;
+
+                    return !identifierIsLocalFunction;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private boolean isClassMember(IDefinition nodeDef, IClassNode classNode)
+    {
+        TypeScope cscope = (TypeScope) classNode.getDefinition()
+                .getContainedScope();
+
+        Set<INamespaceDefinition> nsSet = cscope.getNamespaceSet(project);
+        Collection<IDefinition> defs = new HashSet<IDefinition>();
+
+        cscope.getAllPropertiesForMemberAccess((CompilerProject) project, defs,
+                nsSet);
+
+        Iterator<IDefinition> visiblePropertiesIterator = defs.iterator();
+        while (visiblePropertiesIterator.hasNext())
+        {
+            if (parseQualifiedName(nodeDef).equals(
+                    parseQualifiedName(visiblePropertiesIterator.next())))
+                return true;
+        }
+
+        return false;
+    }
+
+    private boolean isSameClass(IDefinition pdef, IDefinition thisClass,
+            ICompilerProject project)
+    {
+        if (pdef == thisClass)
+            return true;
+
+        IDefinition cdef = ((ClassDefinition) thisClass)
+                .resolveBaseClass(project);
+        while (cdef != null)
+        {
+            // needs to be a loop
+            if (cdef == pdef)
+                return true;
+            cdef = ((ClassDefinition) cdef).resolveBaseClass(project);
+        }
+        return false;
+    }
+
+    @Override
+    public void emitIdentifier(IIdentifierNode node)
+    {
+        if (project == null)
+            project = getWalker().getProject();
+
+        IDefinition nodeDef = node.resolve(project);
+
+        IASNode parentNode = node.getParent();
+        ASTNodeID parentNodeId = parentNode.getNodeID();
+
+        boolean identifierIsAccessorFunction = nodeDef instanceof AccessorDefinition;
+        boolean identifierIsPlainFunction = nodeDef instanceof FunctionDefinition
+                && !identifierIsAccessorFunction;
+
+        boolean emitName = true;
+
+        if (nodeDef != null && nodeDef.isStatic()
+                && nodeDef.getParent() != null)
+        {
+            String sname = parseQualifiedName(nodeDef.getParent());
+            if (sname.length() > 0)
+            {
+                write(sname);
+                write(ASEmitterTokens.MEMBER_ACCESS);
+            }
+        }
+        else if (!NativeUtils.isNative(node.getName()))
+        {
+            // an instance method as a parameter or
+            // a local function
+            boolean useGoogBind = (parentNodeId == ASTNodeID.ContainerID
+                    && identifierIsPlainFunction && ((FunctionDefinition) nodeDef)
+                    .getFunctionClassification() == FunctionClassification.CLASS_MEMBER)
+                    || (identifierIsPlainFunction && ((FunctionDefinition) nodeDef)
+                            .getFunctionClassification() == FunctionClassification.LOCAL);
+
+            if (useGoogBind)
+            {
+                write(JSGoogEmitterTokens.GOOG_BIND);
+                write(ASEmitterTokens.PAREN_OPEN);
+            }
+
+            if (writeThis(node))
+            {
+                write(ASEmitterTokens.THIS);
+
+                write(ASEmitterTokens.MEMBER_ACCESS);
+            }
+
+            if (useGoogBind)
+            {
+                write(node.getName());
+
+                writeToken(ASEmitterTokens.COMMA);
+                write(ASEmitterTokens.THIS);
+                write(ASEmitterTokens.PAREN_CLOSE);
+
+                emitName = false;
+            }
+        }
+
+        IDefinition parentDef = (nodeDef != null) ? nodeDef.getParent() : null;
+        boolean isNative = (parentDef != null)
+                && NativeUtils.isNative(parentDef.getBaseName());
+        if ((identifierIsAccessorFunction && !isNative)
+                || (nodeDef instanceof VariableDefinition && ((VariableDefinition) nodeDef)
+                        .isBindable()))
+        {
+            IASNode anode = node
+                    .getAncestorOfType(BinaryOperatorAssignmentNode.class);
+
+            boolean isAssignment = false;
+            if (anode != null)
+            {
+                IASNode leftNode = anode.getChild(0);
+                if (anode == parentNode)
+                {
+                    if (node == leftNode)
+                        isAssignment = true;
+                }
+                else
+                {
+                    IASNode pnode = parentNode;
+                    IASNode thisNode = node;
+                    while (anode != pnode)
+                    {
+                        if (pnode instanceof IMemberAccessExpressionNode)
+                        {
+                            if (thisNode != pnode.getChild(1))
+                            {
+                                // can't be an assignment because 
+                                // we're on the left side of a memberaccessexpression
+                                break;
+                            }
+                        }
+                        if (pnode == leftNode)
+                        {
+                            isAssignment = true;
+                        }
+                        thisNode = pnode;
+                        pnode = pnode.getParent();
+                    }
+                }
+                String op = ((IBinaryOperatorNode) anode).getOperator()
+                        .getOperatorText();
+                if (op.contains("==") || !op.contains("="))
+                    isAssignment = false;
+            }
+
+            if (parentNode.getNodeID() == ASTNodeID.MemberAccessExpressionID
+                    && parentNode.getChild(0).getNodeID() == ASTNodeID.SuperID
+                    && isSuperCallForOverride(node))
+            {
+                IClassNode cnode = (IClassNode) node
+                        .getAncestorOfType(IClassNode.class);
+
+                // ToDo (erikdebruin): add VF2JS conditional -> only use check during full SDK compilation
+                if (cnode == null)
+                    return;
+
+                write(parseQualifiedName(cnode));
+                write(ASEmitterTokens.MEMBER_ACCESS);
+                write(JSGoogEmitterTokens.GOOG_BASE);
+                write(ASEmitterTokens.PAREN_OPEN);
+                write(ASEmitterTokens.THIS);
+                writeToken(ASEmitterTokens.COMMA);
+                write(ASEmitterTokens.SINGLE_QUOTE);
+                writeGetSetPrefix(!isAssignment);
+                write(parseQualifiedName(nodeDef));
+                write(ASEmitterTokens.SINGLE_QUOTE);
+                if (isAssignment)
+                {
+                    writeToken(ASEmitterTokens.COMMA);
+                }
+            }
+            else if (node instanceof NonResolvingIdentifierNode)
+            {
+                write(node.getName());
+            }
+            else
+            {
+                writeGetSetPrefix(!isAssignment);
+                write(node.getName());
+                write(ASEmitterTokens.PAREN_OPEN);
+            }
+
+            if (anode != null && isAssignment)
+            {
+                getWalker().walk(
+                        ((BinaryOperatorAssignmentNode) anode)
+                                .getRightOperandNode());
+            }
+
+            if (!(node instanceof NonResolvingIdentifierNode))
+                write(ASEmitterTokens.PAREN_CLOSE);
+        }
+        else if (emitName)
+        {
+            if (nodeDef != null)
+                write(parseQualifiedName(nodeDef));
+            else
+                write(node.getName());
+        }
+    }
+
+    private boolean isSuperCallForOverride(IIdentifierNode node)
+    {
+        IFunctionNode pfnode = (IFunctionNode) node
+                .getAncestorOfType(FunctionNode.class);
+
+        if (pfnode == null)
+            return false;
+
+        return pfnode.getName().equals(node.getName());
+    }
+
+    //--------------------------------------------------------------------------
+
+    @Override
+    protected void emitSuperCall(IASNode node, String type)
+    {
+        IFunctionNode fnode = (node instanceof IFunctionNode) ? (IFunctionNode) node
+                : null;
+        IFunctionCallNode fcnode = (node instanceof IFunctionCallNode) ? (FunctionCallNode) node
+                : null;
+
+        if (type == JSSessionModel.CONSTRUCTOR_EMPTY)
+        {
+            indentPush();
+            writeNewline();
+            indentPop();
+        }
+        else if (type == JSSessionModel.SUPER_FUNCTION_CALL)
+        {
+            if (fnode == null)
+                fnode = (IFunctionNode) fcnode
+                        .getAncestorOfType(IFunctionNode.class);
+        }
+
+        if (fnode != null && fnode.isConstructor() && !hasSuperClass(fnode))
+            return;
+
+        IClassNode cnode = (IClassNode) node
+                .getAncestorOfType(IClassNode.class);
+
+        if (cnode == null)
+            return;
+
+        // (erikdebruin): Catch when a 'super' call does NOT match the enclosing
+        //                function call. The GCC only allows '.base()' calls
+        //                to matching super methods, so we need to use 
+        //                'goog.base' for these ...
+        boolean isCallToOtherSuperMethod = false;
+        try
+        {
+            IExpressionNode d = fcnode.getNameNode();
+            if (d != null && d instanceof IMemberAccessExpressionNode)
+            {
+                IIdentifierNode b = (IIdentifierNode) ((IMemberAccessExpressionNode) d)
+                        .getRightOperandNode();
+
+                isCallToOtherSuperMethod = b != null
+                        && !b.getName().equals(fnode.getName());
+            }
+        }
+        catch (Exception e)
+        { /* Eat it! */
+        }
+
+        if (isCallToOtherSuperMethod)
+        {
+            write(ASEmitterTokens.THIS);
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(JSGoogEmitterTokens.SUPERCLASS);
+            write(ASEmitterTokens.MEMBER_ACCESS);
+        }
+        else
+        {
+            write(parseQualifiedName(cnode));
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(JSGoogEmitterTokens.GOOG_BASE);
+            write(ASEmitterTokens.PAREN_OPEN);
+            write(ASEmitterTokens.THIS);
+        }
+
+        if (fnode != null && fnode.isConstructor())
+        {
+            writeToken(ASEmitterTokens.COMMA);
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            write(JSGoogEmitterTokens.GOOG_CONSTRUCTOR);
+            write(ASEmitterTokens.SINGLE_QUOTE);
+        }
+
+        if (fnode != null && !fnode.isConstructor())
+        {
+            if (!isCallToOtherSuperMethod)
+            {
+                writeToken(ASEmitterTokens.COMMA);
+                write(ASEmitterTokens.SINGLE_QUOTE);
+            }
+
+            if (fnode.getNodeID() == ASTNodeID.GetterID
+                    || fnode.getNodeID() == ASTNodeID.SetterID)
+                writeGetSetPrefix(fnode.getNodeID() == ASTNodeID.GetterID);
+
+            // (erikdebruin): write(fnode.getName());
+            IMemberAccessExpressionNode aenode = (IMemberAccessExpressionNode) fcnode
+                    .getNameNode();
+            write(((IIdentifierNode) aenode.getRightOperandNode()).getName());
+
+            if (!isCallToOtherSuperMethod)
+            {
+                write(ASEmitterTokens.SINGLE_QUOTE);
+            }
+            else
+            {
+                write(ASEmitterTokens.MEMBER_ACCESS);
+                write(JSGoogEmitterTokens.GOOG_CALL);
+                write(ASEmitterTokens.PAREN_OPEN);
+                write(ASEmitterTokens.THIS);
+            }
+        }
+
+        IASNode[] anodes = null;
+        boolean writeArguments = false;
+        if (fcnode != null)
+        {
+            anodes = fcnode.getArgumentNodes();
+
+            writeArguments = anodes.length > 0;
+        }
+        else if (fnode != null && fnode.isConstructor())
+        {
+            anodes = fnode.getParameterNodes();
+
+            writeArguments = (anodes != null && anodes.length > 0);
+        }
+        else if (fnode == null && node instanceof BinaryOperatorAssignmentNode)
+        {
+            BinaryOperatorAssignmentNode bnode = (BinaryOperatorAssignmentNode) node;
+
+            IFunctionNode pnode = (IFunctionNode) bnode
+                    .getAncestorOfType(IFunctionNode.class);
+
+            if (pnode.getNodeID() == ASTNodeID.SetterID)
+            {
+                writeToken(ASEmitterTokens.COMMA);
+                write(ASEmitterTokens.SINGLE_QUOTE);
+                writeGetSetPrefix(false);
+                getWalker().walk(bnode.getLeftOperandNode());
+                write(ASEmitterTokens.SINGLE_QUOTE);
+                writeToken(ASEmitterTokens.COMMA);
+                getWalker().walk(bnode.getRightOperandNode());
+            }
+        }
+
+        if (writeArguments)
+        {
+            int len = anodes.length;
+            for (int i = 0; i < len; i++)
+            {
+                writeToken(ASEmitterTokens.COMMA);
+
+                getWalker().walk(anodes[i]);
+            }
+        }
+
+        write(ASEmitterTokens.PAREN_CLOSE);
+
+        if (type == JSSessionModel.CONSTRUCTOR_FULL)
+        {
+            write(ASEmitterTokens.SEMICOLON);
+            writeNewline();
+        }
+        else if (type == JSSessionModel.CONSTRUCTOR_EMPTY)
+        {
+            write(ASEmitterTokens.SEMICOLON);
+        }
+    }
+
+    @Override
+    protected void emitDefaultParameterCodeBlock(IFunctionNode node)
+    {
+        IParameterNode[] pnodes = node.getParameterNodes();
+        if (pnodes.length == 0)
+            return;
+
+        Map<Integer, IParameterNode> defaults = EmitterUtils
+                .getDefaults(pnodes);
+
+        if (defaults != null)
+        {
+            final StringBuilder code = new StringBuilder();
+
+            if (!EmitterUtils.hasBody(node))
+            {
+                indentPush();
+                write(JSFlexJSEmitterTokens.INDENT);
+            }
+
+            List<IParameterNode> parameters = new ArrayList<IParameterNode>(
+                    defaults.values());
+
+            for (int i = 0, n = parameters.size(); i < n; i++)
+            {
+                IParameterNode pnode = parameters.get(i);
+
+                if (pnode != null)
+                {
+                    code.setLength(0);
+
+                    /* x = typeof y !== 'undefined' ? y : z;\n */
+                    code.append(pnode.getName());
+                    code.append(ASEmitterTokens.SPACE.getToken());
+                    code.append(ASEmitterTokens.EQUAL.getToken());
+                    code.append(ASEmitterTokens.SPACE.getToken());
+                    code.append(ASEmitterTokens.TYPEOF.getToken());
+                    code.append(ASEmitterTokens.SPACE.getToken());
+                    code.append(pnode.getName());
+                    code.append(ASEmitterTokens.SPACE.getToken());
+                    code.append(ASEmitterTokens.STRICT_NOT_EQUAL.getToken());
+                    code.append(ASEmitterTokens.SPACE.getToken());
+                    code.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
+                    code.append(ASEmitterTokens.UNDEFINED.getToken());
+                    code.append(ASEmitterTokens.SINGLE_QUOTE.getToken());
+                    code.append(ASEmitterTokens.SPACE.getToken());
+                    code.append(ASEmitterTokens.TERNARY.getToken());
+                    code.append(ASEmitterTokens.SPACE.getToken());
+                    code.append(pnode.getName());
+                    code.append(ASEmitterTokens.SPACE.getToken());
+                    code.append(ASEmitterTokens.COLON.getToken());
+                    code.append(ASEmitterTokens.SPACE.getToken());
+                    code.append(pnode.getDefaultValue());
+                    code.append(ASEmitterTokens.SEMICOLON.getToken());
+
+                    write(code.toString());
+
+                    if (i == n - 1 && !EmitterUtils.hasBody(node))
+                        indentPop();
+
+                    writeNewline();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void emitBinaryOperator(IBinaryOperatorNode node)
+    {
+        ASTNodeID id = node.getNodeID();
+        if (id == ASTNodeID.Op_InID || id == ASTNodeID.Op_LogicalAndAssignID
+                || id == ASTNodeID.Op_LogicalOrAssignID)
+        {
+            super.emitBinaryOperator(node);
+        }
+        else if (id == ASTNodeID.Op_IsID || id == ASTNodeID.Op_AsID)
+        {
+            emitIsAs(node.getLeftOperandNode(), node.getRightOperandNode(), id,
+                    false);
+        }
+        else if (id == ASTNodeID.Op_InstanceOfID)
+        {
+            getWalker().walk(node.getLeftOperandNode());
+
+            write(ASEmitterTokens.SPACE);
+            writeToken(ASEmitterTokens.INSTANCEOF);
+
+            IDefinition dnode = (node.getRightOperandNode()).resolve(project);
+            if (dnode != null)
+                write(parseQualifiedName(dnode));
+            else
+                getWalker().walk(node.getRightOperandNode());
+        }
+        else
+        {
+            IExpressionNode leftSide = node.getLeftOperandNode();
+
+            IExpressionNode property = null;
+            int leftSideChildCount = leftSide.getChildCount();
+            if (leftSideChildCount > 0)
+            {
+                IASNode childNode = leftSide.getChild(leftSideChildCount - 1);
+                if (childNode instanceof IExpressionNode)
+                    property = (IExpressionNode) childNode;
+                else
+                    property = leftSide;
+            }
+            else
+                property = leftSide;
+
+            IDefinition def = null;
+            if (property instanceof IIdentifierNode)
+                def = ((IIdentifierNode) property).resolve(getWalker()
+                        .getProject());
+
+            boolean isSuper = false;
+            if (leftSide.getNodeID() == ASTNodeID.MemberAccessExpressionID)
+            {
+                IASNode cnode = leftSide.getChild(0);
+                ASTNodeID cId = cnode.getNodeID();
+
+                isSuper = cId == ASTNodeID.SuperID;
+            }
+
+            String op = node.getOperator().getOperatorText();
+            boolean isAssignment = !(op.contains("==") || !op.contains("="));
+
+            if (def instanceof AccessorDefinition && isAssignment)
+            {
+                getWalker().walk(leftSide);
+            }
+            else if (isSuper)
+            {
+                emitSuperCall(node, "");
+            }
+            else
+            {
+                if (ASNodeUtils.hasParenOpen(node))
+                    write(ASEmitterTokens.PAREN_OPEN);
+
+                getWalker().walk(leftSide);
+
+                if (node.getNodeID() != ASTNodeID.Op_CommaID)
+                    write(ASEmitterTokens.SPACE);
+
+                writeToken(node.getOperator().getOperatorText());
+
+                getWalker().walk(node.getRightOperandNode());
+
+                if (ASNodeUtils.hasParenClose(node))
+                    write(ASEmitterTokens.PAREN_CLOSE);
+            }
+        }
+    }
+
+    private void emitIsAs(IExpressionNode left, IExpressionNode right,
+            ASTNodeID id, boolean coercion)
+    {
+        write(JSFlexJSEmitterTokens.LANGUAGE_QNAME);
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        if (id == ASTNodeID.Op_IsID)
+            write(ASEmitterTokens.IS);
+        else
+            write(ASEmitterTokens.AS);
+        write(ASEmitterTokens.PAREN_OPEN);
+        getWalker().walk(left);
+        writeToken(ASEmitterTokens.COMMA);
+
+        IDefinition dnode = (right).resolve(project);
+        if (dnode != null)
+            write(parseQualifiedName(dnode));
+        else
+            getWalker().walk(right);
+
+        if (coercion)
+        {
+            writeToken(ASEmitterTokens.COMMA);
+            write(ASEmitterTokens.TRUE);
+        }
+
+        write(ASEmitterTokens.PAREN_CLOSE);
+    }
+
+    @Override
+    public void emitMemberAccessExpression(IMemberAccessExpressionNode node)
+    {
+        IASNode leftNode = node.getLeftOperandNode();
+        IASNode rightNode = node.getRightOperandNode();
+
+        if (project == null)
+            project = getWalker().getProject();
+
+        IDefinition def = node.resolve(project);
+        boolean isStatic = false;
+        if (def != null && def.isStatic())
+            isStatic = true;
+
+        boolean continueWalk = true;
+        if (!isStatic)
+        {
+            if (!(leftNode instanceof ILanguageIdentifierNode && ((ILanguageIdentifierNode) leftNode)
+                    .getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.THIS))
+            {
+                if (rightNode instanceof UnaryOperatorAtNode)
+                {
+                    // ToDo (erikdebruin): properly handle E4X
+
+                    write(ASEmitterTokens.THIS);
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    getWalker().walk(node.getLeftOperandNode());
+                    write(ASEmitterTokens.SQUARE_OPEN);
+                    write(ASEmitterTokens.SINGLE_QUOTE);
+                    write("E4XOperator");
+                    write(ASEmitterTokens.SINGLE_QUOTE);
+                    write(ASEmitterTokens.SQUARE_CLOSE);
+                    continueWalk = false;
+                }
+                else if (node.getNodeID() == ASTNodeID.Op_DescendantsID)
+                {
+                    // ToDo (erikdebruin): properly handle E4X
+
+                    write(ASEmitterTokens.THIS);
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    getWalker().walk(node.getLeftOperandNode());
+                    write(ASEmitterTokens.SQUARE_OPEN);
+                    write(ASEmitterTokens.SINGLE_QUOTE);
+                    write("E4XSelector");
+                    write(ASEmitterTokens.SINGLE_QUOTE);
+                    write(ASEmitterTokens.SQUARE_CLOSE);
+                    continueWalk = false;
+                }
+                else if (leftNode.getNodeID() != ASTNodeID.SuperID)
+                {
+                    getWalker().walk(node.getLeftOperandNode());
+                    write(node.getOperator().getOperatorText());
+                }
+            }
+            else
+            {
+                write(ASEmitterTokens.THIS);
+                write(node.getOperator().getOperatorText());
+            }
+
+        }
+
+        if (continueWalk)
+            getWalker().walk(node.getRightOperandNode());
+    }
+
+    private static ITypeDefinition getTypeDefinition(IDefinitionNode node)
+    {
+        ITypeNode tnode = (ITypeNode) node.getAncestorOfType(ITypeNode.class);
+        return (ITypeDefinition) tnode.getDefinition();
+    }
+
+    private static IClassDefinition getSuperClassDefinition(
+            IDefinitionNode node, ICompilerProject project)
+    {
+        IClassDefinition parent = (IClassDefinition) node.getDefinition()
+                .getParent();
+        IClassDefinition superClass = parent.resolveBaseClass(project);
+        return superClass;
+    }
+
+    @Override
+    protected void emitObjectDefineProperty(IAccessorNode node)
+    {
+        FunctionNode fn = (FunctionNode) node;
+        fn.parseFunctionBody(getProblems());
+
+        IFunctionDefinition definition = node.getDefinition();
+        ITypeDefinition type = (ITypeDefinition) definition.getParent();
+
+        // ToDo (erikdebruin): add VF2JS conditional -> only use check during full SDK compilation
+        if (type == null)
+            return;
+
+        if (project == null)
+            project = getWalker().getProject();
+
+        getDocEmitter().emitMethodDoc(fn, project);
+        write(parseQualifiedName(type));
+        if (!node.hasModifier(ASModifier.STATIC))
+        {
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(JSEmitterTokens.PROTOTYPE);
+        }
+
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        writeGetSetPrefix(node instanceof IGetterNode);
+        writeToken(node.getName());
+        writeToken(ASEmitterTokens.EQUAL);
+        write(ASEmitterTokens.FUNCTION);
+        emitParameters(node.getParametersContainerNode());
+        //writeNewline();
+        emitMethodScope(node.getScopedNode());
+    }
+
+    private void writeGetSetPrefix(boolean isGet)
+    {
+        if (isGet)
+            write(ASEmitterTokens.GET);
+        else
+            write(ASEmitterTokens.SET);
+        write("_");
+    }
+
+    @Override
+    public IJSGoogDocEmitter getDocEmitter()
+    {
+        return new JSVF2JSDocEmitter(this);
+    }
+
+    @Override
+    public void emitPackageHeader(IPackageDefinition definition)
+    {
+        IASScope containedScope = definition.getContainedScope();
+        ITypeDefinition type = findType(containedScope.getAllLocalDefinitions());
+        if (type == null)
+            return;
+
+        writeNewline("/**");
+        writeNewline(" * " + parseQualifiedName(type));
+        writeNewline(" *");
+        writeNewline(" * @fileoverview");
+        writeNewline(" *");
+        writeNewline(" * @suppress {checkTypes}");
+        writeNewline(" */");
+        writeNewline();
+
+        /* goog.provide('x');\n\n */
+        write(JSGoogEmitterTokens.GOOG_PROVIDE);
+        write(ASEmitterTokens.PAREN_OPEN);
+        write(ASEmitterTokens.SINGLE_QUOTE);
+        write(parseQualifiedName(type));
+        write(ASEmitterTokens.SINGLE_QUOTE);
+        write(ASEmitterTokens.PAREN_CLOSE);
+        writeNewline(ASEmitterTokens.SEMICOLON);
+        writeNewline();
+    }
+
+    @Override
+    public void emitPackageHeaderContents(IPackageDefinition definition)
+    {
+        PackageScope containedScope = (PackageScope) definition
+                .getContainedScope();
+
+        ITypeDefinition type = findType(containedScope.getAllLocalDefinitions());
+        if (type == null)
+            return;
+
+        if (project == null)
+            project = getWalker().getProject();
+
+        FlexJSProject flexProject = (FlexJSProject) project;
+        ASProjectScope projectScope = flexProject.getScope();
+        ICompilationUnit cu = projectScope
+                .getCompilationUnitForDefinition(type);
+        ArrayList<String> requiresList = flexProject.getRequires(cu);
+        ArrayList<String> interfacesList = flexProject.getInterfaces(cu);
+
+        String cname = parseQualifiedName(type);
+        ArrayList<String> writtenInstances = new ArrayList<String>();
+        writtenInstances.add(cname); // make sure we don't add ourselves
+
+        boolean emitsRequires = false;
+        if (requiresList != null)
+        {
+            Collections.sort(requiresList);
+            for (String imp : requiresList)
+            {
+                if (imp.indexOf(JSGoogEmitterTokens.AS3.getToken()) != -1)
+                    continue;
+
+                if (imp.equals(cname))
+                    continue;
+
+                if (NativeUtils.isNative(imp))
+                    continue;
+
+                if (writtenInstances.indexOf(imp) == -1)
+                {
+
+                    /* goog.require('x');\n */
+                    write(JSGoogEmitterTokens.GOOG_REQUIRE);
+                    write(ASEmitterTokens.PAREN_OPEN);
+                    write(ASEmitterTokens.SINGLE_QUOTE);
+                    write(imp);
+                    write(ASEmitterTokens.SINGLE_QUOTE);
+                    write(ASEmitterTokens.PAREN_CLOSE);
+                    writeNewline(ASEmitterTokens.SEMICOLON);
+
+                    writtenInstances.add(imp);
+
+                    emitsRequires = true;
+                }
+            }
+        }
+
+        boolean emitsInterfaces = false;
+        if (interfacesList != null)
+        {
+            Collections.sort(interfacesList);
+            for (String imp : interfacesList)
+            {
+                write(JSGoogEmitterTokens.GOOG_REQUIRE);
+                write(ASEmitterTokens.PAREN_OPEN);
+                write(ASEmitterTokens.SINGLE_QUOTE);
+                write(imp);
+                write(ASEmitterTokens.SINGLE_QUOTE);
+                write(ASEmitterTokens.PAREN_CLOSE);
+                writeNewline(ASEmitterTokens.SEMICOLON);
+
+                emitsInterfaces = true;
+            }
+        }
+
+        // erikdebruin: Add missing language feature support, with e.g. 'is' and 
+        //              'as' operators. We don't need to worry about requiring
+        //              this in every project: ADVANCED_OPTIMISATIONS will NOT
+        //              include any of the code if it is not used in the project.
+        boolean isMainCU = flexProject.mainCU != null
+                && cu.getName().equals(flexProject.mainCU.getName());
+        if (isMainCU)
+        {
+            write(JSGoogEmitterTokens.GOOG_REQUIRE);
+            write(ASEmitterTokens.PAREN_OPEN);
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            write(JSFlexJSEmitterTokens.LANGUAGE_QNAME);
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            write(ASEmitterTokens.PAREN_CLOSE);
+            writeNewline(ASEmitterTokens.SEMICOLON);
+        }
+
+        if (emitsRequires || emitsInterfaces || isMainCU)
+        {
+            writeNewline();
+        }
+
+        writeNewline();
+        writeNewline();
+    }
+
+    @Override
+    public void emitPackageFooter(IPackageDefinition definition)
+    {
+        IASScope containedScope = definition.getContainedScope();
+        ITypeDefinition type = findType(containedScope.getAllLocalDefinitions());
+        if (type == null)
+            return;
+
+        ITypeNode tnode = findTypeNode(definition.getNode());
+        if (tnode != null)
+        {
+            /*
+             * Metadata
+             * 
+             * @type {Object.<string, Array.<Object>>}
+             */
+            writeNewline();
+            writeNewline();
+            writeNewline();
+            getDocEmitter().begin();
+            writeNewline(" * Metadata");
+            writeNewline(" *");
+            writeNewline(" * @type {Object.<string, Array.<Object>>}");
+            getDocEmitter().end();
+
+            // a.B.prototype.AFJS_CLASS_INFO = {  };
+            write(parseQualifiedName(type));
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(JSEmitterTokens.PROTOTYPE);
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            writeToken(JSFlexJSEmitterTokens.FLEXJS_CLASS_INFO);
+            writeToken(ASEmitterTokens.EQUAL);
+            writeToken(ASEmitterTokens.BLOCK_OPEN);
+
+            // names: [{ name: '', qName: '' }]
+            write(JSFlexJSEmitterTokens.NAMES);
+            writeToken(ASEmitterTokens.COLON);
+            write(ASEmitterTokens.SQUARE_OPEN);
+            writeToken(ASEmitterTokens.BLOCK_OPEN);
+            write(JSFlexJSEmitterTokens.NAME);
+            writeToken(ASEmitterTokens.COLON);
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            write(tnode.getName());
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            writeToken(ASEmitterTokens.COMMA);
+            write(JSFlexJSEmitterTokens.QNAME);
+            writeToken(ASEmitterTokens.COLON);
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            write(parseQualifiedName(tnode));
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            write(ASEmitterTokens.BLOCK_CLOSE);
+            write(ASEmitterTokens.SQUARE_CLOSE);
+
+            IExpressionNode[] enodes;
+            if (tnode instanceof IClassNode)
+                enodes = ((IClassNode) tnode).getImplementedInterfaceNodes();
+            else
+                enodes = ((IInterfaceNode) tnode).getExtendedInterfaceNodes();
+
+            if (enodes.length > 0)
+            {
+                writeToken(ASEmitterTokens.COMMA);
+
+                // interfaces: [a.IC, a.ID]
+                write(JSFlexJSEmitterTokens.INTERFACES);
+                writeToken(ASEmitterTokens.COLON);
+                write(ASEmitterTokens.SQUARE_OPEN);
+                int i = 0;
+                for (IExpressionNode enode : enodes)
+                {
+                    write(parseQualifiedName(enode.resolve(project)));
+                    if (i < enodes.length - 1)
+                        writeToken(ASEmitterTokens.COMMA);
+                    i++;
+                }
+                write(ASEmitterTokens.SQUARE_CLOSE);
+            }
+
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.BLOCK_CLOSE);
+            writeNewline(ASEmitterTokens.SEMICOLON);
+        }
+    }
+
+    private int foreachLoopCounter = 0;
+
+    @Override
+    public void emitForEachLoop(IForLoopNode node)
+    {
+        IBinaryOperatorNode bnode = (IBinaryOperatorNode) node
+                .getConditionalsContainerNode().getChild(0);
+        IASNode childNode = bnode.getChild(0);
+
+        String iterName = "foreachiter"
+                + new Integer(foreachLoopCounter).toString();
+        foreachLoopCounter++;
+
+        write(ASEmitterTokens.FOR);
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.PAREN_OPEN);
+        write(ASEmitterTokens.VAR);
+        write(ASEmitterTokens.SPACE);
+        write(iterName);
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.IN);
+        write(ASEmitterTokens.SPACE);
+        getWalker().walk(bnode.getChild(1));
+        writeToken(ASEmitterTokens.PAREN_CLOSE);
+        writeNewline();
+        write(ASEmitterTokens.BLOCK_OPEN);
+        writeNewline();
+        if (childNode instanceof IVariableExpressionNode)
+        {
+            write(ASEmitterTokens.VAR);
+            write(ASEmitterTokens.SPACE);
+            write(((IVariableNode) childNode.getChild(0)).getName());
+        }
+        else
+            write(((IIdentifierNode) childNode).getName());
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.EQUAL);
+        write(ASEmitterTokens.SPACE);
+        getWalker().walk(bnode.getChild(1));
+        write(ASEmitterTokens.SQUARE_OPEN);
+        write(iterName);
+        write(ASEmitterTokens.SQUARE_CLOSE);
+        write(ASEmitterTokens.SEMICOLON);
+        writeNewline();
+        getWalker().walk(node.getStatementContentsNode());
+        write(ASEmitterTokens.BLOCK_CLOSE);
+        writeNewline();
+
+    }
+
+    /*
+    @Override
+    public void emitForEachLoop(IForLoopNode node)
+    {
+        IContainerNode xnode = (IContainerNode) node.getChild(1);
+        IBinaryOperatorNode bnode = (IBinaryOperatorNode) node
+                .getConditionalsContainerNode().getChild(0);
+        IASNode childNode = bnode.getChild(0);
+
+        write(ASEmitterTokens.TRY);
+        write(ASEmitterTokens.BLOCK_OPEN);
+        writeNewline();
+        
+        write(JSGoogEmitterTokens.GOOG_ARRAY_FOREACH);
+        write(ASEmitterTokens.PAREN_OPEN);
+        getWalker().walk(bnode.getChild(1));
+        writeToken(ASEmitterTokens.COMMA);
+        writeToken(ASEmitterTokens.FUNCTION);
+        write(ASEmitterTokens.PAREN_OPEN);
+        if (childNode instanceof IVariableExpressionNode)
+        	write(((IVariableNode) childNode.getChild(0)).getName());
+        else
+        	write(((IIdentifierNode) childNode).getName());
+        writeToken(ASEmitterTokens.PAREN_CLOSE);
+        if (isImplicit(xnode))
+            write(ASEmitterTokens.BLOCK_OPEN);
+        getWalker().walk(node.getStatementContentsNode());
+        if (isImplicit(xnode))
+        {
+            writeNewline();
+            write(ASEmitterTokens.BLOCK_CLOSE);
+        }
+        write(ASEmitterTokens.PAREN_CLOSE);
+        writeNewline();
+        write(ASEmitterTokens.BLOCK_CLOSE);
+        writeNewline();
+        write(ASEmitterTokens.CATCH);
+        write(ASEmitterTokens.PAREN_OPEN);
+        write("foreachbreakerror");
+        write(ASEmitterTokens.PAREN_CLOSE);
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.BLOCK_OPEN);
+        write(ASEmitterTokens.BLOCK_CLOSE);
+        writeNewline();
+        
+    }
+
+    @Override
+    public void emitIterationFlow(IIterationFlowNode node)
+    {
+    	// look for break in foreach and throw error instead
+    	if (node.getKind() == IIterationFlowNode.IterationFlowKind.BREAK)
+    	{
+    		IASNode pNode = node.getParent();
+    		while (pNode != null)
+    		{
+    			ASTNodeID id = pNode.getNodeID();
+    			if (id == ASTNodeID.ForEachLoopID)
+    			{
+    				write(ASEmitterTokens.THROW);
+    				write(ASEmitterTokens.SPACE);
+    				write(ASEmitterTokens.NEW);
+    				write(ASEmitterTokens.SPACE);
+    				write(JSGoogEmitterTokens.ERROR);
+    				write(ASEmitterTokens.PAREN_OPEN);
+    				write(ASEmitterTokens.PAREN_CLOSE);
+    				write(ASEmitterTokens.SEMICOLON);
+    				return;
+    			}
+    			else if (id == ASTNodeID.ForLoopID ||
+    					id == ASTNodeID.DoWhileLoopID ||
+    					id == ASTNodeID.WhileLoopID)
+    				break;
+    			pNode = pNode.getParent();
+    		}
+    	}
+        write(node.getKind().toString().toLowerCase());
+        IIdentifierNode lnode = node.getLabelNode();
+        if (lnode != null)
+        {
+            write(ASEmitterTokens.SPACE);
+            getWalker().walk(lnode);
+        }
+    }
+    */
+
+    @Override
+    public void emitTypedExpression(ITypedExpressionNode node)
+    {
+        write(JSGoogEmitterTokens.ARRAY);
+    }
+
+    @Override
+    public void emitLiteral(ILiteralNode node)
+    {
+        boolean isWritten = false;
+
+        String s = node.getValue(true);
+        if (!(node instanceof RegExpLiteralNode))
+        {
+            if (node.getLiteralType() == LiteralType.XML)
+            {
+                // ToDo (erikdebruin): VF2JS -> handle XML output properly...
+
+                write("'" + s + "'");
+
+                isWritten = true;
+            }
+            s = s.replaceAll("\n", "__NEWLINE_PLACEHOLDER__");
+            s = s.replaceAll("\r", "__CR_PLACEHOLDER__");
+            s = s.replaceAll("\t", "__TAB_PLACEHOLDER__");
+            s = s.replaceAll("\f", "__FORMFEED_PLACEHOLDER__");
+            s = s.replaceAll("\b", "__BACKSPACE_PLACEHOLDER__");
+            s = s.replaceAll("\\\\\"", "__QUOTE_PLACEHOLDER__");
+            s = s.replaceAll("\\\\", "__ESCAPE_PLACEHOLDER__");
+            //s = "\'" + s.replaceAll("\'", "\\\\\'") + "\'";
+            s = s.replaceAll("__ESCAPE_PLACEHOLDER__", "\\\\\\\\");
+            s = s.replaceAll("__QUOTE_PLACEHOLDER__", "\\\\\"");
+            s = s.replaceAll("__BACKSPACE_PLACEHOLDER__", "\\\\b");
+            s = s.replaceAll("__FORMFEED_PLACEHOLDER__", "\\\\f");
+            s = s.replaceAll("__TAB_PLACEHOLDER__", "\\\\t");
+            s = s.replaceAll("__CR_PLACEHOLDER__", "\\\\r");
+            s = s.replaceAll("__NEWLINE_PLACEHOLDER__", "\\\\n");
+
+            Character c = s.charAt(0);
+            if (c.equals('"'))
+            {
+                s = s.substring(1, s.length() - 1);
+                s = s.replaceAll("\"", "\\\\\"");
+                s = "\"" + s + "\"";
+            }
+            if (s.length() == 3)
+            {
+                c = s.charAt(1);
+                if (c.equals('\\'))
+                {
+                    s = "\"\\\\\"";
+                }
+            }
+        }
+
+        if (!isWritten)
+        {
+            write(s);
+        }
+    }
+
+    @Override
+    public void emitE4XFilter(IMemberAccessExpressionNode node)
+    {
+        // ToDo (erikdebruin): implement E4X replacement !?!
+        write(ASEmitterTokens.SINGLE_QUOTE);
+        write("E4XFilter");
+        write(ASEmitterTokens.SINGLE_QUOTE);
+    }
+
+    @Override
+    public void emitContainer(IContainerNode node)
+    {
+        int nodeCount = node.getChildCount();
+        for (int i = 0; i < nodeCount; i++)
+        {
+            getWalker().walk(node.getChild(i));
+
+            if (i < nodeCount - 1)
+                writeToken(ASEmitterTokens.COMMA);
+        }
+    }
+
+    private String parseQualifiedName(IDefinitionNode def)
+    {
+        return parseQualifiedNameString(def.getQualifiedName());
+    }
+
+    private String parseQualifiedName(IDefinition def)
+    {
+        return parseQualifiedNameString(def.getQualifiedName());
+    }
+
+    private String parseQualifiedNameString(String qNameString)
+    {
+        // ToDo (erikdebruin): Ugly hacks for VF2JS ...
+        if (qNameString.equals(IASLanguageConstants._int))
+        {
+            qNameString = qNameString.toUpperCase();
+        }
+
+        if (qNameString.equals("byte"))
+        {
+            qNameString = "$" + qNameString;
+        }
+
+        return qNameString;
+    }
+
+}