incubator-flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aha...@apache.org
Subject svn commit: r1413061 [7/14] - in /incubator/flex/falcon/trunk/compiler.js: ./ bin/ build/ in/ intermediates/ localization/ localization/src/ localization/src/org/ localization/src/org/apache/ localization/src/org/apache/flex/ localization/src/org/apach...
Date Fri, 23 Nov 2012 20:58:56 GMT
Added: incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSEmitter.java
URL: http://svn.apache.org/viewvc/incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSEmitter.java?rev=1413061&view=auto
==============================================================================
--- incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSEmitter.java (added)
+++ incubator/flex/falcon/trunk/compiler.js/src/org/apache/flex/compiler/internal/as/codegen/JSEmitter.java Fri Nov 23 20:58:50 2012
@@ -0,0 +1,3427 @@
+/*
+ *
+ *  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.as.codegen;
+
+import static org.apache.flex.abc.ABCConstants.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import org.apache.flex.abc.ABCConstants;
+import org.apache.flex.abc.visitors.IABCVisitor;
+import org.apache.flex.abc.visitors.IClassVisitor;
+import org.apache.flex.abc.visitors.IMetadataVisitor;
+import org.apache.flex.abc.visitors.IMethodBodyVisitor;
+import org.apache.flex.abc.visitors.IMethodVisitor;
+import org.apache.flex.abc.visitors.IScriptVisitor;
+import org.apache.flex.abc.visitors.ITraitVisitor;
+import org.apache.flex.abc.visitors.ITraitsVisitor;
+import org.apache.flex.abc.graph.IBasicBlock;
+import org.apache.flex.abc.semantics.ClassInfo;
+import org.apache.flex.abc.semantics.ExceptionInfo;
+import org.apache.flex.abc.semantics.InstanceInfo;
+import org.apache.flex.abc.semantics.Instruction;
+import org.apache.flex.abc.semantics.Label;
+import org.apache.flex.abc.semantics.Metadata;
+import org.apache.flex.abc.semantics.MethodBodyInfo;
+import org.apache.flex.abc.semantics.MethodInfo;
+import org.apache.flex.abc.semantics.Name;
+import org.apache.flex.abc.semantics.Namespace;
+import org.apache.flex.abc.semantics.Nsset;
+import org.apache.flex.abc.semantics.PooledValue;
+import org.apache.flex.abc.semantics.ScriptInfo;
+import org.apache.flex.abc.semantics.Trait;
+import org.apache.flex.abc.semantics.Traits;
+import org.apache.flex.abc.instructionlist.InstructionList;
+import org.apache.flex.compiler.constants.IMetaAttributeConstants;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.INamespaceDefinition;
+import org.apache.flex.compiler.internal.definitions.AmbiguousDefinition;
+import org.apache.flex.compiler.internal.definitions.ClassDefinition;
+import org.apache.flex.compiler.internal.definitions.FunctionDefinition;
+import org.apache.flex.compiler.internal.definitions.PackageDefinition;
+import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter;
+import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter.AccessValue;
+import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter.ClassificationValue;
+import org.apache.flex.compiler.internal.legacy.ASDefinitionFilter.SearchScopeValue;
+import org.apache.flex.compiler.internal.legacy.ASScopeUtils;
+import org.apache.flex.compiler.internal.legacy.MemberedDefinitionUtils;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.compiler.scopes.IASScope;
+import org.apache.flex.compiler.tree.as.IImportNode.ImportKind;
+import org.apache.flex.compiler.units.ICompilationUnit;
+import org.apache.flex.abc.ABCEmitter;
+
+/**
+ * JSEmitter is used in two different phases. During compilation it acts as a
+ * visitor that gets called for each layer in the AST (see Emitter*IVisitor
+ * classes). The second phase is triggered by JSCompilationUnit's
+ * handleABCBytesRequest() and uses emitCode() for building the JavaScript code
+ * (see emit* methods). This implementation is part of FalconJS. For more
+ * details on FalconJS see org.apache.flex.compiler.JSDriver.
+ */
+@SuppressWarnings("nls")
+public class JSEmitter implements IABCVisitor
+{
+    protected JSOutputStream w = new JSOutputStream();
+    protected Set<String> m_importNames = new TreeSet<String>();
+    protected Set<String> m_useNames = new TreeSet<String>();
+
+    private Vector<EmitterClassVisitor> definedClasses = new Vector<EmitterClassVisitor>();
+    private Vector<MethodInfo> methodInfos = new Vector<MethodInfo>();
+    private Vector<MethodBodyInfo> methodBodies = new Vector<MethodBodyInfo>();
+    private Vector<ScriptInfo> scriptInfos = new Vector<ScriptInfo>();
+    protected final Boolean emitExterns = JSSharedData.m_useClosureLib && false; // only set emitExterns to true if you want to generate extern files, i.e. svg.js.
+
+    private JSSharedData m_sharedData;
+    private EmitterClassVisitor m_currentClassVisitor;
+    private String m_methodPrologue = "";
+    private String m_methodPostlogue = "";
+    private static String EXTERN_PREFIX = "// EXTERN ";
+    // private ICompilationUnit.Operation m_buildPhase;
+    private IABCVisitor m_visitor = null;
+    protected ICompilerProject m_project = null;
+    private IASScope m_currentScope = null;
+    protected Map<MethodInfo, FunctionDefinition> m_methodInfoToDefinition = new HashMap<MethodInfo, FunctionDefinition>();
+    protected Map<FunctionDefinition, MethodInfo> m_definitionToMethodInfo = new HashMap<FunctionDefinition, MethodInfo>();
+    protected String m_packageName = null;
+
+    public JSEmitter(JSSharedData sharedData,
+                     ICompilationUnit.Operation buildPhase,
+                     ICompilerProject project)
+    {
+        this.w = new JSOutputStream();
+        m_sharedData = sharedData;
+        m_currentClassVisitor = null;
+        // m_buildPhase = buildPhase;
+        m_project = project;
+    }
+
+    protected void writeString(String str)
+    {
+        w.writeString(str);
+    }
+
+    public void setVisitor(IABCVisitor visitor)
+    {
+        m_visitor = visitor;
+    }
+
+    public byte[] emit()
+            throws Exception
+    {
+        // Metadata
+        /*
+         * for (Metadata md : metadataPool.getValues()) { // name final String
+         * name = md.getName(); // items count assert md.getKeys().length ==
+         * md.getValues().length; // metadata keys for (final String key :
+         * md.getKeys()) { writeString( "// META[" + name + "]: key=" + key +
+         * "\n" ); } // metadata values for (final String value :
+         * md.getValues()) { writeString( "// META[" + name + "]: value=" +
+         * value + "\n" ); } }
+         */
+        m_currentClassVisitor = null;
+
+        // first write out the framework class
+        EmitterClassVisitor frameWorkClassVisitor = null;
+        for (EmitterClassVisitor clz : this.definedClasses)
+        {
+            InstanceInfo ii = clz.instanceInfo;
+            if (!ii.isInterface() && JSGeneratingReducer.getBasenameFromName(ii.name).equals(JSSharedData.JS_FRAMEWORK_NAME))
+            {
+                m_currentClassVisitor = clz;
+                final IDefinition def = getDefinition(ii.name);
+                final String packageName = def.getPackageName();
+                if (packageName.isEmpty())
+                {
+                    frameWorkClassVisitor = clz;
+                    emitClass(clz);
+                }
+            }
+        }
+
+        // write out all the other classes
+        for (EmitterClassVisitor clz : this.definedClasses)
+        {
+            if (clz != frameWorkClassVisitor)
+            {
+                m_currentClassVisitor = clz;
+
+                if (clz.instanceInfo.isInterface())
+                    emitInterface(clz);
+                else
+                    emitClass(clz);
+            }
+        }
+
+        // static initializers?
+        /*
+         * for (EmitterClassVisitor clz : this.definedClasses) {
+         * m_currentClassVisitor = clz;
+         * w.writeU30(getMethodId(clz.classInfo.cInit));
+         * emitTraits(clz.classTraits); }
+         */
+
+        m_currentClassVisitor = null;
+
+        // write out free floating code: package functions and package variables. 
+        for (ScriptInfo si : this.scriptInfos)
+        {
+            emitScriptInfo(si);
+        }
+
+        return w.toByteArray();
+    }
+
+    protected MethodBodyInfo findMethodBodyInfo(MethodInfo mi)
+    {
+        for (int i = 0; i < this.methodBodies.size(); i++)
+        {
+            MethodBodyInfo mbi = methodBodies.elementAt(i);
+            if (mbi.getMethodInfo() == mi)
+                return mbi;
+        }
+
+        // Don't throw, because interfaces don't have  MethodBodyInfo:
+        // throw new IllegalArgumentException("Unable to find MethodBodyInfo for " + mi);
+        return null;
+    }
+
+    protected String emitParameters(MethodInfo mi) throws Exception
+    {
+        final FunctionDefinition fdef = this.m_methodInfoToDefinition.get(mi);
+        String[] chunk = JSGeneratingReducer.emitParameters(m_project, fdef, mi);
+        // String[] chunk = JSGeneratingReducer.emitParameters(mi);
+
+        final String a_priori_insns = chunk[0];
+        final String code = chunk[1];
+
+        writeString(code);
+        return a_priori_insns;
+    }
+
+    protected void emitInstanceTraits(Traits traits, MethodInfo ctor, String packageName, String className, String superClass,
+                                        Boolean isExtern, Boolean isInterface, Boolean isPackageFunction) throws Exception
+    {
+        // private void emitTraits(Traits traits, Boolean isInstanceTraits, MethodInfo ctor, String packageName, String className, String methodPrefix, String assignmentOp, String separator, String indent ) throws Exception
+
+        if (JSSharedData.m_useClosureLib)
+        {
+            if (isExtern)
+                emitTraits(traits, true, isExtern, isInterface, isPackageFunction, ctor, packageName, className, superClass, className + ".prototype.", "=", ";", EXTERN_PREFIX);
+            else
+            {
+                final String fullName = createFullName(packageName, className);
+                emitTraits(traits, true, isExtern, isInterface, isPackageFunction, ctor, packageName, className, superClass, fullName + ".prototype.", "=", ";", "");
+            }
+        }
+        else
+            emitTraits(traits, true, isExtern, isInterface, isPackageFunction, ctor, packageName, className, superClass, "", ":", ",", isExtern ? EXTERN_PREFIX : "\t");
+    }
+
+    protected Boolean isExtern(Name name)
+    {
+        if (name != null)
+        {
+            final IDefinition def = JSGeneratingReducer.getDefinitionForName(m_project, name);
+            if (def == null)
+            {
+                JSGeneratingReducer.getDefinitionForName(m_project, name);
+                throw new IllegalArgumentException("isExtern: can't find definition for name " + name.toString());
+            }
+
+            if (def.getMetaTagByName(JSSharedData.EXTERN_METATAG) != null)
+                return true;
+        }
+        return false;
+    }
+
+    /** packageName can be "" */
+    protected IDefinition getDefinition(Name name)
+    {
+        if (name == null)
+            return null;
+
+        final IDefinition def = JSGeneratingReducer.getDefinitionForNameByScope(m_project, m_project.getScope(), name);
+
+        if (def == null)
+        {
+            throw new IllegalArgumentException("getDefinition: can't find definition for name " + name.toString());
+        }
+
+        return def;
+    }
+
+    /** packageName can be "" */
+    private ClassDefinition getClassDefinition(String shortClassName, String packageName)
+    {
+        if (packageName.isEmpty())
+            return getClassDefinition(shortClassName);
+        else
+            return getClassDefinition(packageName + "." + shortClassName);
+    }
+
+    /** expects className to be fully-qualified if it's in a package */
+    private ClassDefinition getClassDefinition(String className)
+    {
+        IDefinition definitionContext = null;
+        ASDefinitionFilter filter = new ASDefinitionFilter(ClassificationValue.CLASSES_AND_INTERFACES, SearchScopeValue.ALL_SCOPES, AccessValue.ALL, definitionContext);
+        IDefinition def = ASScopeUtils.findDefinitionByName(m_project.getScope(), m_project, className, filter);
+        if (def instanceof ClassDefinition)
+        {
+            final ClassDefinition classDef = (ClassDefinition)def;
+            return classDef;
+        }
+        return null;
+    }
+
+    // Symbol support
+    private Boolean isSymbolClass(String className)
+    {
+        final ClassDefinition classDef = getClassDefinition(className);
+        if (classDef != null)
+        {
+            for (String implementedInterface : classDef.getImplementedInterfacesAsDisplayStrings())
+            {
+                if (implementedInterface.equals(JSSharedData.SYMBOL_INTERFACE_NAME))
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    private void emitClassInfo(String packageName, String className, String superClass, Boolean isDynamic, Boolean isFinal)
+    {
+        final String fullClassNameWithoutDot = createFullName(packageName, className);
+        String fullClassName = fullClassNameWithoutDot;
+        if (!fullClassName.isEmpty())
+            fullClassName += ".";
+
+        if (superClass.isEmpty())
+            superClass = "Object";
+
+        // add _PACKAGE member to class 
+        if (packageName.isEmpty())
+        {
+            // add _PACKAGE member to class 
+            writeString("/**\n");
+            writeString(" * Member: " + fullClassName + "_PACKAGE\n");
+            writeString(" * @const\n");
+            writeString(" * @type {" + fullClassNameWithoutDot + "}\n");
+            writeString(" */\n");
+            writeString(fullClassName + "_PACKAGE = adobe.globals;\n");
+            writeString("\n");
+        }
+        else
+        {
+            // add _PACKAGE member to class 
+            writeString("/**\n");
+            writeString(" * Member: " + fullClassName + "_PACKAGE\n");
+            writeString(" * @const\n");
+            writeString(" * @type {" + packageName + "}\n");
+            writeString(" */\n");
+            writeString(fullClassName + "_PACKAGE = " + packageName + ";\n");
+            writeString("\n");
+        }
+
+        // add _NAME member to class
+        writeString("\n");
+        writeString("/**\n");
+        writeString(" * Member: " + fullClassName + "_NAME\n");
+        writeString(" * @const\n");
+        writeString(" * @type {string}\n");
+        writeString(" */\n");
+        writeString(fullClassName + "_NAME = \"" + className + "\";\n");
+
+        // add _FULLNAME member to class
+        writeString("\n");
+        writeString("/**\n");
+        writeString(" * Member: " + fullClassName + "_FULLNAME\n");
+        writeString(" * @const\n");
+        writeString(" * @type {string}\n");
+        writeString(" */\n");
+        writeString(fullClassName + "_FULLNAME = \"" + fullClassNameWithoutDot + "\";\n");
+
+        // add _SUPER member to class
+        writeString("\n");
+        writeString("/**\n");
+        writeString(" * Member: " + fullClassName + "_SUPER\n");
+        writeString(" * @const\n");
+        writeString(" * @type {" + superClass + "}\n");
+        writeString(" */\n");
+        writeString(fullClassName + "_SUPER = " + superClass + ";\n");
+
+        // add _DYNAMIC member to class
+        if (isDynamic)
+        {
+            writeString("\n");
+            writeString("/**\n");
+            writeString(" * Member: " + fullClassName + "_DYNAMIC\n");
+            writeString(" * @const\n");
+            writeString(" * @type {boolean}\n");
+            writeString(" */\n");
+            writeString(fullClassName + "_DYNAMIC = true;\n");
+        }
+
+        // add _FINAL member to class
+        if (isFinal)
+        {
+            writeString("\n");
+            writeString("/**\n");
+            writeString(" * Member: " + fullClassName + "_FINAL\n");
+            writeString(" * @const\n");
+            writeString(" * @type {boolean}\n");
+            writeString(" */\n");
+            writeString(fullClassName + "_FINAL = true;\n");
+        }
+
+        // Symbol support
+        if (isSymbolClass(className))
+        {
+            // add instance member to class 
+            writeString("\n");
+            writeString("/**\n");
+            writeString(" * Member: " + fullClassName + JSSharedData.SYMBOL_INSTANCE + "\n");
+            writeString(" * @const\n");
+            writeString(" * @type {" + className + "}\n");
+            writeString(" */\n");
+            writeString(fullClassName + JSSharedData.SYMBOL_INSTANCE + " = null;\n");
+        }
+
+        // Namespace support
+        final IDefinition def = JSSharedData.instance.getDefinition(fullClassNameWithoutDot);
+        if (def != null)
+        {
+            def.getQualifiedName();
+        }
+    }
+
+    private void emitClassTraits(Traits traits, MethodInfo staticInitMI,
+                                String packageName, String className, String superClass,
+                                Boolean isExtern, Boolean isPackageFunction,
+                                Boolean isDynamicClass, Boolean isFinalClass,
+                                Boolean emitClassPrologue) throws Exception
+    {
+        final Boolean isInterface = false;
+        writeString("\n\n");
+
+        // TODO: generalize
+        if (isExtern || packageName.startsWith("goog"))
+            return;
+
+        if (emitClassPrologue && !className.isEmpty())
+        {
+            emitClassInfo(packageName, className, superClass, isDynamicClass, isFinalClass);
+        }
+
+        String fullClassName = createFullName(packageName, className);
+        if (!fullClassName.isEmpty())
+            fullClassName += ".";
+
+        emitTraits(traits, false, isExtern, isInterface, isPackageFunction, staticInitMI, packageName.replaceFirst(JSSharedData.ROOT_NAME, ""), className, superClass, fullClassName, "=", ";", "");
+
+        /*
+         * if( isExtern ) emitTraits( traits, false, isExtern, staticInitMI,
+         * packageName, className, superClass, fullClassName, "=", ";", "" );
+         * else emitTraits( traits, false, isExtern, staticInitMI,
+         * packageName.replaceFirst( JSSharedData.ROOT_NAME, ""), className,
+         * superClass, fullClassName, "=", ";", "" );
+         */
+    }
+
+    private String nameToString(Name name)
+    {
+        String baseName = JSGeneratingReducer.getBasenameFromName(name);
+        if (baseName == null || baseName.isEmpty())
+        {
+            String packageName = "";
+            final Nsset nsset = name.getQualifiers();
+            if (nsset != null && nsset.length() > 0)
+            {
+                packageName = nsset.iterator().next().getName();
+                if (!packageName.isEmpty())
+                    baseName = "{" + packageName + "}::" + baseName;
+            }
+        }
+        else
+        {
+            final IDefinition def = getDefinition(name);
+            if (name != null && !name.isTypeName())
+            {
+                final String packageName = def.getPackageName();
+                if (packageName != null && !packageName.isEmpty())
+                {
+                    final String fullName = "{" + packageName + "}::" + baseName;
+                    return fullName;
+                }
+            }
+        }
+        return baseName;
+
+    }
+
+    // see Namespace::getKindString
+    /*
+     * private String getKindString(Namespace ns) { switch(ns.getKind()) { case
+     * ABCConstants.CONSTANT_Namespace: return "Ns"; case
+     * ABCConstants.CONSTANT_PackageNs: return "PackageNs"; case
+     * ABCConstants.CONSTANT_PackageInternalNs: return "PackageInternalNs"; case
+     * ABCConstants.CONSTANT_ProtectedNs: return "ProtectedNs"; case
+     * ABCConstants.CONSTANT_ExplicitNamespace: return "ExplicitNs"; case
+     * ABCConstants.CONSTANT_StaticProtectedNs: return "StaticProtectedNs"; case
+     * ABCConstants.CONSTANT_PrivateNs: return "PrivateNs"; } return "UnknownNs"
+     * ; }
+     */
+
+    private String mangleName(String baseName, Namespace ns)
+    {
+        String name = baseName + "::";
+        String nsStr = ns.toString();
+
+        // workaround for Falcon bug.
+        // ns.toString() is now returning:
+        //      ProtectedNs:"tests:Test"
+        // instead of
+        //      ProtectedNs:"tests.Test"
+        if (ns.getName().contains(":") /*
+                                        * && ns.getKind() !=
+                                        * ABCConstants.CONSTANT_Namespace
+                                        */)
+        {
+            String tmp = ns.getName();
+
+            // support for "use namespace"
+            /*
+             * final INamespaceDefinition ins =
+             * JSSharedData.instance.getNamespace(tmp); if( ins != null ) { tmp
+             * = ins.getQualifiedName(); }
+             */
+            tmp = tmp.replaceAll(":", ".");
+
+            // another workaround for a Falcon bug.
+            // WRONG:       PrivateNs:"ClassPrivateNS:tests:Test"
+            // CORRECT:     PrivateNs:ClassPrivateNS:"tests:Test"
+            if (tmp.startsWith("ClassPrivateNS."))
+                tmp = tmp.replace("ClassPrivateNS.", "ClassPrivateNS:");
+            nsStr = nsStr.substring(0, nsStr.length() - ns.getName().length() - 2) + tmp;
+        }
+        nsStr = nsStr.replaceAll("\\\"", "");
+
+        Boolean colon = false;
+        for (String part : nsStr.split(":"))
+        {
+            if (colon)
+                name += ":";
+            else
+                colon = true;
+            part = part.replaceAll("\\\"", "");
+
+            if (part.equals("Ns"))
+                name += JSSharedData.CONSTANT_Namespace;
+            else if (part.equals("PackageNs"))
+                name += JSSharedData.CONSTANT_PackageNs;
+            else if (part.equals("PackageInternalNs"))
+                name += JSSharedData.CONSTANT_PackageInternalNs;
+            else if (part.equals("ProtectedNs"))
+                name += JSSharedData.CONSTANT_ProtectedNs;
+            else if (part.equals("ExplicitNs"))
+                name += JSSharedData.CONSTANT_ExplicitNamespace;
+            else if (part.equals("StaticProtectedNs"))
+                name += JSSharedData.CONSTANT_StaticProtectedNs;
+            else if (part.equals("PrivateNs"))
+                name += JSSharedData.CONSTANT_PrivateNs;
+            else if (part.equals("ClassPrivateNS"))
+                name += JSSharedData.CONSTANT_ClassPrivateNS;
+            else
+                name += part;
+        }
+
+        return name;
+    }
+
+    private void emitNamespaceInfo(EmitterClassVisitor clz,
+            String packageName, String className, String superClass) throws Exception
+    {
+        // check whether this class is tagged with [ClassInfo]
+        if (!className.isEmpty())
+        {
+            final Traits instanceTraits = clz.instanceTraits;
+            final String fullName = createFullName(packageName, className);
+            boolean comma = false;
+            String names = "";
+            for (Trait t : instanceTraits)
+            {
+                final Name name = t.getNameAttr("name");
+                final Nsset nsset = name.getQualifiers();
+                if (nsset != null && nsset.length() > 0)
+                {
+                    if (comma)
+                        names += ",\n";
+                    else
+                        comma = true;
+                    for (Namespace ns : nsset)
+                    {
+                        names += "\t\"" + mangleName(name.getBaseName(), ns) + "\" : true";
+                    }
+                }
+            }
+
+            // add _NAMESPACES member to class 
+            writeString("\n");
+            writeString("/**\n");
+            writeString(" * Member: " + fullName + "._NAMESPACES\n");
+            writeString(" * @const\n");
+            writeString(" * @type {Object}\n");
+            writeString(" */\n");
+
+            if (names.isEmpty())
+                writeString(fullName + "._NAMESPACES = {};\n");
+            else
+            {
+                writeString(fullName + "._NAMESPACES = {\n");
+                writeString(names + "\n");
+                writeString("}\n");
+            }
+
+            // add _USES member to class 
+            names = "";
+            comma = false;
+            for (String uses : m_useNames)
+            {
+                final INamespaceDefinition ns = JSSharedData.instance.getNamespaceForQName(uses);
+                if (ns != null)
+                {
+                    if (comma)
+                        names += ",\n";
+                    else
+                        comma = true;
+                    names += ("\t\"" + ns.getURI().replaceAll(":", ".") + "\" : \"" + uses + "\"");
+                }
+            }
+
+            if (!names.isEmpty())
+            {
+                writeString("\n");
+                writeString("/**\n");
+                writeString(" * Member: " + fullName + "._USES\n");
+                writeString(" * @const\n");
+                writeString(" * @type {Object}\n");
+                writeString(" */\n");
+
+                writeString(fullName + "._USES = {\n");
+                writeString(names + "\n");
+                writeString("}\n");
+            }
+        }
+    }
+
+    private Boolean needsClassInfo(Traits classTraits)
+    {
+        for (Trait t : classTraits)
+        {
+            final Vector<Metadata> metaData = t.getMetadata();
+            for (Metadata md : metaData)
+            {
+                if (md.getName().equals(JSSharedData.GENERATE_CLASSINFO))
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    /*
+     * tests.Test._CLASSINFO = { name : "", isDynamic : true, isFinal : true,
+     * isStatic : true, bases : [], traits : { bases : {}, interfaces : {},
+     * constructor : { {type: "", optional:false}, ... }, variables : { name:
+     * "", type: "", access: "readwrite", uri: "", metadata: { name : "", value
+     * : { {key:"", value:""}, ... } } } accessors : { name: "", type: "",
+     * access: "readwrite", declaredBy: "", uri: "", metadata: { name : "",
+     * value : { {key:"", value:""}, ... } } }, methods : { name: "",
+     * returnType: "", declaredBy: "", parameters: { }, uri: "", metadata: {
+     * name : "", value : { {key:"", value:""}, ... } } }, metadata: { name :
+     * "", value : { {key:"", value:""}, ... } } } }
+     */
+    private void emitJSONInfo(EmitterClassVisitor clz,
+            String packageName, String className, String superClass) throws Exception
+    {
+        final Traits classTraits = clz.classTraits;
+        // check whether this class is tagged with [ClassInfo]
+        if (!className.isEmpty() && needsClassInfo(classTraits))
+        {
+            final Traits instanceTraits = clz.instanceTraits;
+            final String fullName = createFullName(packageName, className);
+
+            // add _CLASSINFO member to class 
+            writeString("\n");
+            writeString("/**\n");
+            writeString(" * Member: " + fullName + "._CLASSINFO\n");
+            writeString(" * @const\n");
+            writeString(" * @type {Object}\n");
+            writeString(" */\n");
+            writeString(fullName + "._CLASSINFO =\n");
+            writeString("{\n");
+
+            final String indent = "\t";
+            final String indent2 = "\t\t";
+            final String indent3 = "\t\t\t";
+            final String indent4 = "\t\t\t\t";
+            final String indent5 = "\t\t\t\t\t";
+
+            // add name, bases, isDynamic, isFinal, isStatic
+            final InstanceInfo iinfo = clz.instanceInfo;
+            final Boolean isDynamic = !iinfo.isSealed();
+            final Boolean isFinal = iinfo.isFinal();
+            final Boolean isStatic = true;
+            if (packageName.isEmpty())
+                writeString(indent + "name : \"" + className + "\",\n");
+            else
+                writeString(indent + "name : \"{" + packageName + "}::" + className + "\",\n");
+            writeString(indent + "bases : [\"Class\"],\n");
+            writeString(indent + "isDynamic : " + (isDynamic ? "true" : "false") + ",\n");
+            writeString(indent + "isFinal : " + (isFinal ? "true" : "false") + ",\n");
+            writeString(indent + "isStatic : " + (isStatic ? "true" : "false") + ",\n");
+
+            // traits
+            writeString(indent + "traits:\n");
+            writeString(indent + "{\n");
+
+            // add traits.bases 
+            writeString(indent2 + "bases:\n");
+            writeString(indent2 + "{\n");
+
+            ClassDefinition classDef = getClassDefinition(className, packageName);
+
+            IClassDefinition superclassDef = classDef.resolveBaseClass(m_project);
+            while (superclassDef != null)
+            {
+                final String superPackageName = superclassDef.getPackageName();
+                if (superPackageName.isEmpty())
+                    writeString(indent3 + superclassDef.getBaseName() + ": \"" + superclassDef.getBaseName() + "\",\n");
+                else
+                    writeString(indent3 + superclassDef.getBaseName() + ": \"{" + superPackageName + "}::" + superclassDef.getBaseName() + "\",\n");
+
+                superclassDef = superclassDef.resolveBaseClass(m_project);
+            }
+            writeString(indent2 + "},\n");
+
+            // add traits.interfaces
+            writeString(indent2 + "interfaces:\n");
+            writeString(indent2 + "{\n");
+            for (Name iname : iinfo.interfaceNames)
+            {
+                writeString(indent3 + "\"" + nameToString(iname) + "\",\n");
+            }
+            writeString(indent2 + "},\n");
+
+            // add traits.constructor 
+            writeString(indent2 + "constructor:\n");
+            writeString(indent2 + "{\n");
+            final MethodInfo ctor = clz.instanceInfo.iInit;
+            writeString(getParameterInfo(ctor, indent3));
+            writeString(indent2 + "},\n");
+
+            // add variables, accessors, methods
+            List<String> variables = new ArrayList<String>();
+            List<String> methods = new ArrayList<String>();
+            Map<String, String> getters = new HashMap<String, String>();
+            Map<String, String> setters = new HashMap<String, String>();
+
+            for (Trait t : instanceTraits)
+            {
+                String str = new String();
+                final Name name = t.getNameAttr("name");
+                String propName = JSGeneratingReducer.getBasenameFromName(name);
+                String propType = "";
+                switch (t.getKind())
+                {
+                    // traits.variables
+                    case TRAIT_Var:
+                    case TRAIT_Const:
+                    {
+                        final Boolean isConst = t.getKind() == TRAIT_Const;
+                        final Name type = t.getNameAttr(Trait.TRAIT_TYPE);
+                        if (type == null)
+                            propType = "Object";
+                        else
+                            propType = nameToString(type);// JSGeneratingReducer.getBasenameFromName(type);
+                        str += indent3 + propName + ":\n";
+                        str += indent3 + "{\n";
+                        str += indent4 + "name : " + "\"" + propName + "\",\n";
+                        str += indent4 + "type : " + "\"" + propType + "\",\n";
+                        str += indent4 + "access : " + "\"" + (isConst ? "readonly" : "readwrite") + "\",\n";
+                        // str += indent4 + "uri : " + "\"" + ??? + "\"\n";
+                        // str += getMetaDataInfo( findMetadata(classTraits, propName, t.getKind()), indent4 );
+                        str += getMetaDataInfo(t.getMetadata(), indent4);
+                        str += indent3 + "}";
+                        variables.add(str);
+                        break;
+                    }
+                        // traits.accessors
+                    case TRAIT_Getter:
+                    case TRAIT_Setter:
+                    {
+                        final String declaredBy = "(unknown)"; // TODO
+                        final String access = t.getKind() == TRAIT_Getter ? "readonly" : "readwrite";
+                        str += indent3 + propName + ":\n";
+                        str += indent3 + "{\n";
+                        str += indent4 + "name : " + "\"" + propName + "\",\n";
+                        str += indent4 + "type : " + "\"" + propType + "\",\n";
+                        str += indent4 + "access : " + "\"" + access + "\",\n";
+                        str += indent4 + "declaredBy : " + "\"" + declaredBy + "\",\n";
+                        // str += indent4 + "uri : " + "\"" + ??? + "\"\n";
+                        // str += getMetaDataInfo( findMetadata(classTraits, propName, t.getKind()), indent4 );
+                        str += getMetaDataInfo(t.getMetadata(), indent4);
+                        str += indent3 + "}";
+
+                        if (t.getKind() == TRAIT_Getter)
+                            getters.put(propName, str);
+                        else
+                            setters.put(propName, str);
+                        break;
+                    }
+                        // traits.methods
+                    case TRAIT_Method:
+                    case TRAIT_Function:
+                    {
+                        final String declaredBy = "(unknown)"; // TODO
+                        final MethodInfo mi = (MethodInfo)t.getAttr("method_id");
+                        str += indent3 + propName + ":\n";
+                        str += indent3 + "{\n";
+                        str += indent4 + "name : " + "\"" + propName + "\",\n";
+                        str += indent4 + "returnType : " + "\"" + nameToString(mi.getReturnType()) + "\",\n";
+                        str += indent4 + "declaredBy : " + "\"" + declaredBy + "\",\n";
+                        // str += indent4 + "uri : " + "\"" + ??? + "\"\n";
+                        str += indent4 + "parameters:\n";
+                        str += indent4 + "{\n";
+                        str += getParameterInfo(mi, indent5);
+                        str += indent4 + "},\n";
+                        // str += getMetaDataInfo( findMetadata(classTraits, propName, t.getKind()), indent4 );
+                        str += getMetaDataInfo(t.getMetadata(), indent4);
+                        str += indent3 + "}";
+                        methods.add(str);
+
+                        break;
+                    }
+                }
+            }
+
+            // add variables
+            writeString(indent2 + "variables:\n");
+            writeString(indent2 + "{\n");
+            for (String var : variables)
+            {
+                writeString(var + ",\n");
+            }
+            writeString(indent2 + "},\n");
+
+            // add accessors
+            writeString(indent2 + "accessors:\n");
+            writeString(indent2 + "{\n");
+            for (Map.Entry<String, String> entry : getters.entrySet())
+            {
+                final String s = setters.get(entry.getKey());
+                if (s != null)
+                    writeString(s + ",\n");
+                else
+                    writeString(entry.getValue() + ",\n");
+            }
+            writeString(indent2 + "},\n");
+
+            // add methods
+            writeString(indent2 + "methods:\n");
+            writeString(indent2 + "{\n");
+            for (String met : methods)
+            {
+                writeString(met + ",\n");
+            }
+            writeString("\n");
+            writeString(indent2 + "},\n");
+
+            // closing traits
+            writeString(indent + "},\n");
+
+            // add class metadata
+            for (Trait t : classTraits)
+            {
+                if (t.getKind() == TRAIT_Class)
+                    writeString(getMetaDataInfo(t.getMetadata(), indent));
+            }
+
+            writeString("}\n");
+        }
+    }
+
+    /*
+     * private Vector<Metadata> findMetadata( Traits classTraits, String name,
+     * int traitKind ) { for( Trait t : classTraits ) { if( t.getKind() ==
+     * traitKind ) { final Name n = t.getNameAttr("name"); if(
+     * JSGeneratingReducer.getBasenameFromName(n).equals(name) ) return
+     * t.getMetadata(); } } return new Vector<Metadata>(); }
+     */
+
+    private String getMetaDataInfo(Vector<Metadata> metaData, String indent)
+    {
+        String s = "";
+        if (!metaData.isEmpty())
+        {
+            s += indent + "metadata:\n";
+            s += indent + "{\n";
+            for (Metadata md : metaData)
+            {
+                s += indent + "\t" + md.getName() + ":\n";
+                s += indent + "\t{\n";
+                s += indent + "\t\t" + "name : \"" + md.getName() + "\",\n";
+                final String[] keys = md.getKeys();
+                if (keys.length > 0)
+                {
+                    final String[] values = md.getValues();
+
+                    s += indent + "\t\t" + "value:\n";
+                    s += indent + "\t\t" + "{\n";
+                    for (int i = 0; i < keys.length; ++i)
+                    {
+                        s += indent + "\t\t\t" + keys[i] + ": {key: \"" + keys[i] + "\", value: \"" + values[i] + "\"},\n";
+                    }
+                    s += indent + "\t\t" + "}\n";
+                }
+                s += indent + "\t},\n";
+            }
+            s += indent + "}\n";
+        }
+        return s;
+    }
+
+    private String getParameterInfo(MethodInfo mi, String indent)
+    {
+        String s = "";
+        if (mi != null)
+        {
+            Vector<PooledValue> defaultValues = mi.getDefaultValues();
+            Vector<Name> paramTypes = mi.getParamTypes();
+            final int defaultsStartAt = paramTypes.size() - defaultValues.size();
+            int current = 0;
+            for (Name type : paramTypes)
+            {
+                final String optional = current >= defaultsStartAt ? "true" : "false";
+                s += indent + "p" + current + ": {type: \"" + nameToString(type) + "\", optional: " + optional + "},\n";
+                current++;
+            }
+        }
+        return s;
+    }
+
+    /*
+     * private void emitPackageNames() { writeString( "// Packages \n" ); // get
+     * all package names from the shared data object Set<String> packages =
+     * JSSharedData.instance.getPackages(); // "expand" the package names, i.e.
+     * "com.adobe" expands to "com", "com.adobe". Set<String> expanded = new
+     * TreeSet<String>(); for (String packageName : packages) { String path =
+     * ""; String[] parts = packageName.split("\\."); for( String part: parts )
+     * { if( path.length() == 0 ) path += part; else path += "." + part; if(
+     * path.length() > 0 ) expanded.add( path ); } } // create an entry for each
+     * expanded package name Iterator<String> it = expanded.iterator(); if(
+     * it.hasNext() ) { while (it.hasNext()) { writeString(
+     * JSSharedData.ROOT_NAME + it.next().toString() + " = {};\n" ); } }
+     * writeString( "\n" ); }
+     */
+
+    private String createFullName(String packageName, String className)
+    {
+        String fullName = "";
+
+        // root name
+        if (!JSSharedData.ROOT_NAME.isEmpty() && !className.startsWith(JSSharedData.ROOT_NAME))
+            fullName += JSSharedData.ROOT_NAME;
+
+        // package name
+        if (!packageName.isEmpty())
+        {
+            if (!fullName.isEmpty())
+                fullName += ".";
+            fullName += packageName;
+        }
+
+        // class name
+        if (!className.isEmpty())
+        {
+            if (!fullName.isEmpty())
+                fullName += ".";
+            fullName += className;
+        }
+
+        return fullName;
+    }
+
+    /*
+     * private int typeNameToAbcConstant( Name typeName ) { if( typeName != null
+     * ) { final String type =
+     * JSGeneratingReducer.getBasenameFromName(typeName); if( type.equals("int")
+     * ) return ABCConstants.CONSTANT_Int; if( type.equals("uint") ) return
+     * ABCConstants.CONSTANT_UInt; if( type.equals("Number") ) return
+     * ABCConstants.CONSTANT_Double; if( type.equals("String") ) return
+     * ABCConstants.CONSTANT_Utf8; if( type.equals("Boolean") ) return
+     * ABCConstants.CONSTANT_False; if( type.equals("null") ) return
+     * ABCConstants.CONSTANT_Null; } return ABCConstants.CONSTANT_Undefined; }
+     */
+    private Boolean isDataClassDefinition(IDefinition def)
+    {
+        if (def != null && def instanceof IClassDefinition)
+        {
+            IClassDefinition classDef = (IClassDefinition)def;
+            Iterator<IClassDefinition> superClassIterator = classDef.classIterator(m_project, true);
+
+            while (superClassIterator.hasNext())
+            {
+                final IClassDefinition superClass = superClassIterator.next();
+                if (superClass.getMetaTagByName("DataClass") != null)
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    protected void emitCtor(MethodInfo ctor, Boolean isExtern, Boolean isInterface, String packageName, String className, String superClassName,
+            String methodPrefix, String assignmentOp, String separator, String indent) throws Exception
+    {
+        final Boolean isFramework = className.equals(JSSharedData.JS_FRAMEWORK_NAME);
+
+        // first check whether there is any code...
+        final String body = getCodeForConstructor(ctor);
+        final String fullName = createFullName(packageName, className);
+
+        if (!body.isEmpty() || JSSharedData.instance.hasClassInit(fullName))
+        {
+            writeString("\n" + indent + "// Constructor\n");
+
+            m_methodPrologue = "";
+
+            // cleaning up static inits.
+            if (JSSharedData.instance.hasClassInit(fullName))
+                m_methodPrologue += "\t" + fullName + "." + JSSharedData.STATIC_INIT + "();\n";
+
+            // derived class without ctor don't call super()
+            // AJH remove for now
+            // if (!body.contains("goog.base(") && !JSGeneratingReducer.isDataType(superClassName))
+            //     m_methodPrologue += "\tgoog.base(this);\n";
+
+            if (!JSSharedData.m_useSelfParameter && !body.contains("var self "))
+                m_methodPrologue += "\tvar self = this;\n";
+
+            if (!body.contains("return " + JSSharedData.THIS + ";"))
+                m_methodPostlogue += "\treturn " + JSSharedData.THIS + ";\n";
+
+            final Boolean isPackageFunction = false;
+            if (JSSharedData.m_useClosureLib)
+            {
+                final String pkg = packageName.isEmpty() ? "" : (createFullName(packageName, "") + ".");
+                emitMethod(null, ctor, isFramework, isExtern, isInterface, isPackageFunction, fullName, className, "", pkg, assignmentOp, separator, indent);
+            }
+            else
+                emitMethod(null, ctor, isFramework, isExtern, isInterface, isPackageFunction, fullName, JSSharedData.CTOR_NAME, "", methodPrefix, assignmentOp, separator, indent);
+
+            writeString("\n");
+        }
+        else
+        {
+            if (JSSharedData.m_useClosureLib)
+                writeString(fullName + " = function(){}\n");
+        }
+
+        // inherits
+        if (JSSharedData.m_useClosureLib && (!JSGeneratingReducer.isDataType(superClassName) || superClassName.equals("Error")))
+        {
+            writeString("\n\n");
+            writeString("goog.inherits("
+                            + fullName + ", "
+                            + superClassName + ");\n");
+        }
+
+        // don't add _CLASS to DataClass instances.
+        final IDefinition def = JSSharedData.instance.getDefinition(fullName);
+        if (JSSharedData.m_useClosureLib && (def == null || !isDataClassDefinition(def)))
+        {
+            // add _CLASS member to instance 
+            writeString("\n");
+            writeString("/**\n");
+            writeString(" * Member: " + fullName + ".prototype._CLASS\n");
+            writeString(" * @const\n");
+            writeString(" * @type {" + fullName + "}\n");
+            writeString(" */\n");
+            writeString(fullName + ".prototype._CLASS = " + fullName + ";\n");
+        }
+    }
+
+    protected String emitSlotValue(Trait t)
+    {
+        Object trait_value = t.getAttr(Trait.SLOT_VALUE);
+        if (trait_value != null)
+        {
+            //  See also poolTraitValues(Traits), which
+            //  puts these values into the pools.
+            if (trait_value instanceof String)
+            {
+                return ((String)trait_value);
+            }
+            else if (trait_value instanceof Namespace)
+            {
+                return (((Namespace)trait_value).getName());
+            }
+            else if (trait_value instanceof Double)
+            {
+                return (((Double)trait_value).toString());
+            }
+            else if (trait_value instanceof Integer)
+            {
+                return (((Integer)trait_value).toString());
+            }
+            else if (trait_value instanceof Long)
+            {
+                return (((Long)trait_value).toString());
+            }
+            else if (trait_value instanceof Float)
+            {
+                return (((Float)trait_value).toString());
+            }
+            else if (trait_value.equals(Boolean.TRUE))
+            {
+                return ("true");
+            }
+            else if (trait_value.equals(Boolean.FALSE))
+            {
+                return ("false");
+            }
+            else if (trait_value == ABCConstants.NULL_VALUE)
+            {
+                return ("null");
+            }
+            else if (trait_value == ABCConstants.UNDEFINED_VALUE)
+            {
+                //  Undefined is a special case; it has no kind byte.
+                return ("undefined");
+            }
+            else
+            {
+                throw new IllegalStateException("Unrecognized initializer type: " + trait_value.getClass().toString());
+            }
+        }
+        else
+        {
+            final Name type = t.getNameAttr(Trait.TRAIT_TYPE);
+
+            // In AS, uninitialized variables have a type-specific default value (not always undefined).
+            // The local-var version of this fix is in JSGeneratingReducer.reduce_typedVariableDecl()
+            return (getDefaultInitializerForVariable(type));
+
+            /*
+             * // Flash assumes that uninitialized numbers default to "0" and
+             * not "undefined". String defaultVal = "undefined"; switch(
+             * typeNameToAbcConstant(type) ) { case ABCConstants.CONSTANT_Int :
+             * defaultVal = "0"; break; case ABCConstants.CONSTANT_UInt :
+             * defaultVal = "0"; break; case ABCConstants.CONSTANT_Double :
+             * defaultVal = "0.0"; break; case ABCConstants.CONSTANT_Utf8 :
+             * defaultVal = "null"; break; case ABCConstants.CONSTANT_False :
+             * defaultVal = "false"; break; case ABCConstants.CONSTANT_True :
+             * defaultVal = "true"; break; case ABCConstants.CONSTANT_Undefined
+             * : defaultVal = "undefined"; break; case
+             * ABCConstants.CONSTANT_Null : defaultVal = "null"; break; default
+             * : defaultVal = "undefined"; break; } return( defaultVal );
+             */
+        }
+    }
+
+    protected Boolean emitVariable(Trait t, String baseName,
+            String packageName, String className, String superClassName,
+            String methodPrefix, String assignmentOp, String separator, String indent) throws Exception
+    {
+        Boolean needsSkinPartProcessing = false;
+        final Name name = t.getNameAttr("name");
+        final Name type = t.getNameAttr(Trait.TRAIT_TYPE);
+
+        // JSDoc 
+        List<String> jsdoc = new ArrayList<String>();
+        jsdoc.add("Member: " + createFullName(packageName, className + "." + baseName));
+
+        if (name != null)
+        {
+            Namespace ns = name.getSingleQualifier();
+            if (ns.getKind() == CONSTANT_PrivateNs)
+                jsdoc.add("@private");
+            else if (ns.getKind() == CONSTANT_ProtectedNs)
+                jsdoc.add("@protected");
+        }
+        if (t.getKind() == TRAIT_Const)
+            jsdoc.add("@const");
+        if (type != null)
+        {
+            final StringBuilder sb = new StringBuilder();
+            JSGeneratingReducer.nameToJSDocType(m_project, type, sb);
+            jsdoc.add("@type {" + sb.toString() + "}");
+        }
+
+        if (jsdoc.size() > 0)
+        {
+            writeString("\n");
+            if (jsdoc.size() == 1)
+                writeString(indent + "/** " + jsdoc.get(0) + " */\n");
+            else
+            {
+                writeString(indent + "/**\n");
+                for (String decl : jsdoc)
+                {
+                    writeString(indent + " * " + decl + "\n");
+                }
+                writeString(indent + " */\n");
+            }
+        }
+
+        writeString(indent + methodPrefix + baseName + " ");
+
+        if (type != null)
+            writeString("/* : " + JSGeneratingReducer.getBasenameFromName(type) + " */ ");
+
+        writeString(assignmentOp + " ");
+
+        writeString(emitSlotValue(t));
+
+        // for ";"
+        if (!separator.equals(","))
+            writeString(separator + "\n");
+
+        // Examine var/const metadata
+        final Vector<Metadata> metaData = t.getMetadata();
+        for (Metadata md : metaData)
+        {
+            if (md.getName().equals(IMetaAttributeConstants.ATTRIBUTE_SKIN_PART))
+            {
+                needsSkinPartProcessing = true;
+                break;
+            }
+        }
+
+        return needsSkinPartProcessing;
+    }
+
+    private void emitTraits(Traits traits,
+                            Boolean isInstanceTraits, Boolean isExtern, Boolean isInterface, Boolean isPackageFunction,
+                            MethodInfo ctor, String packageName, String className, String superClassName,
+                            String methodPrefix, String assignmentOp, String separator, String indent) throws Exception
+    {
+        final Boolean isFramework = className.equals(JSSharedData.JS_FRAMEWORK_NAME);
+        Boolean emitComma = false;
+
+        // cache some data used by all the warnIfPrivateNameCollision() calls below
+        IClassDefinition classDef = getClassDefinition(className, packageName);
+        IClassDefinition baseClass = null;
+        ASDefinitionFilter filter = null;
+        if (classDef != null)
+        {
+            baseClass = classDef.resolveBaseClass(m_project);
+            filter = new ASDefinitionFilter(ClassificationValue.ALL,
+                                            ASDefinitionFilter.SearchScopeValue.INHERITED_MEMBERS,
+                                            ASDefinitionFilter.AccessValue.ALL,
+                                            baseClass);
+        }
+
+        // 1. emit constructor 
+        if (isInstanceTraits && ctor != null)
+        {
+            emitCtor(ctor, isExtern, isInterface, packageName, className, superClassName,
+                      methodPrefix, assignmentOp, separator, indent);
+            emitComma = true;
+        }
+
+        // Avoid emitting duplicate Traits, which starts happening after adding 
+        // this line to JSClassDirectiveProcessor::declareVariable():
+        // this.classScope.traitsVisitor = (is_static)? ctraits: itraits;
+        final Set<String> visitedTraits = new HashSet<String>();
+
+        // 2. emit all variables before any methods
+        boolean needsSkinPartProcessing = false;
+
+        for (Trait t : traits)
+        {
+            //  Get the kind byte with its flags set in the high nibble.
+            switch (t.getKind())
+            {
+                case TRAIT_Var:
+                case TRAIT_Const:
+
+                    final Name name = t.getNameAttr("name");
+                    final String baseName = JSGeneratingReducer.getBasenameFromName(name);
+
+                    if (!visitedTraits.contains(baseName))
+                    {
+                        visitedTraits.add(baseName);
+
+                        // see JSGlobalDirectiveProcessor::declareFunction.
+                        // Functions at the global scope create a var of type '*'
+                        Boolean emitVar = true;
+                        if (isPackageFunction)
+                        {
+                            final Name type = t.getNameAttr("type");
+                            if (type == null || type.equals("Function"))
+                            {
+                                for (MethodInfo mi : methodInfos)
+                                {
+                                    if (mi.getMethodName() != null && mi.getMethodName().equals(baseName))
+                                    {
+                                        emitMethod(t, mi, isFramework, isExtern, isInterface, isPackageFunction, baseName, baseName, "", "var ", assignmentOp, separator, indent);
+                                        emitVar = false;
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+
+                        if (emitVar)
+                        {
+                            if (emitComma)
+                                writeString(separator + "\n");
+                            else
+                                emitComma = separator.equals(",");
+                            
+                            boolean methodNeedsSkinPartProcessing = emitVariable(t, baseName,
+                                                                        packageName, className, superClassName,
+                                                                        methodPrefix, assignmentOp, separator, indent);
+
+                            needsSkinPartProcessing = needsSkinPartProcessing || methodNeedsSkinPartProcessing;
+
+                            // print warning in cases where FJS-24 is being hit
+                            String fullName = createFullName(packageName, className);
+                            if (!fullName.isEmpty())
+                                fullName += ".";
+                            fullName += baseName;
+
+                            warnIfPrivateNameCollision(baseClass, filter, baseName, fullName, "Field");
+                        }
+                    }
+                    break;
+                case TRAIT_Method:
+                case TRAIT_Function:
+                case TRAIT_Getter:
+                case TRAIT_Setter:
+                {
+                    // methods will be processed below.
+                }
+                    break;
+                case TRAIT_Class:
+                    // TODO: non-zero slot id
+                    // writeString( "\n\t// ClassInfo: " + ((ClassInfo)t.getAttr(Trait.TRAIT_CLASS)).toString() + "\n" );
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown trait kind " + t.getKind());
+            }
+        }
+
+        // 3. emit all other methods (ctor already emitted)
+        for (Trait t : traits)
+        {
+            //  Get the kind byte with its flags set in the high nibble.
+            switch (t.getKind())
+            {
+                case TRAIT_Method:
+                case TRAIT_Function:
+                case TRAIT_Getter:
+                case TRAIT_Setter:
+                {
+                    // we can't emit getter and setter for extern declarations.
+                    if (!isExtern || t.getKind() != TRAIT_Setter)
+                    {
+                        if (emitComma)
+                            writeString(separator + "\n");
+                        else
+                            emitComma = separator.equals(",");
+
+                        // write out full function name with package.
+                        Name name = t.getNameAttr("name");
+                        MethodInfo mi = (MethodInfo)t.getAttr("method_id");
+                        final String baseName = JSGeneratingReducer.getBasenameFromName(name);
+
+                        // write out comment with the full class name
+                        String fullName = createFullName(packageName, className);
+                        String xetter = "";
+
+                        // cleaning up static inits.
+                        // Static initializer is generated but not called for classes without explicit constructor
+                        if ((!isInstanceTraits || ctor == null) && JSSharedData.instance.hasClassInit(fullName))
+                            m_methodPrologue += "\t\t" + fullName + "." + JSSharedData.STATIC_INIT + "();\n";
+
+                        if (!isExtern)
+                        {
+                            if (t.getKind() == TRAIT_Getter)
+                                xetter = JSSharedData.GETTER_PREFIX;
+                            else if (t.getKind() == TRAIT_Setter)
+                                xetter = JSSharedData.SETTER_PREFIX;
+                        }
+
+                        if (!fullName.isEmpty())
+                            fullName += ".";
+                        fullName += xetter + baseName;
+
+                        // don't emit extern package functions
+                        if (!isExtern && isPackageFunction)
+                            isExtern = isExtern(name);
+
+                        // actually emit the JS code
+                        emitMethod(t, mi, isFramework, isExtern, isInterface, isPackageFunction, fullName, baseName, xetter, methodPrefix, assignmentOp, separator, indent);
+
+                        // print warning in cases where FJS-24 is being hit
+                        warnIfPrivateNameCollision(baseClass, filter, baseName, fullName, "Method");
+                    }
+                }
+                    break;
+            }
+        }
+
+        // 4. custom methods generated from metadata
+        if (needsSkinPartProcessing)
+        {
+            if (emitComma)
+                writeString(separator + "\n");
+            else
+                emitComma = separator.equals(",");
+
+            emitGeneratedSkinPartsMethod(className, packageName, methodPrefix, assignmentOp);
+        }
+
+        // 5. class constructor
+        if (ctor != null && !isInstanceTraits)
+        {
+            // first check whether there is any code...
+            final String body = getCodeForConstructor(ctor);
+            if (!body.isEmpty())
+            {
+                if (emitComma)
+                    writeString(separator + "\n");
+                else
+                    emitComma = separator.equals(",");
+
+                final String fullName = createFullName(packageName, className);
+
+                // writeString( "\n\t// Static inits:\n" );
+                emitMethod(null, ctor, isFramework, isExtern, isInterface, isPackageFunction, fullName, null, "", methodPrefix, assignmentOp, separator, indent);
+            }
+        }
+    }
+
+    /**
+     * Emits the skinParts getter definition that is implied by the use of
+     * [SkinPart] metadata on a Flex class. TODO: once Falcon starts handling
+     * [SkinPart] this code should probbly go away
+     */
+    private void emitGeneratedSkinPartsMethod(String className, String packageName, String methodPrefix, String assignmentOp)
+    {
+        IClassDefinition def = getClassDefinition(className, packageName);
+        String jsonResult = JSFlexUtils.generateGetSkinPartsJSON(def, m_project);
+
+        // Emit JSDoc -- based on emitJSDocForMethod()
+        String methodName = "get_skinParts";
+        String methodFullName = packageName + "." + className + "." + methodName;
+        String indent = "";
+        writeString(indent + "\n\n");
+        writeString(indent + "/**\n");
+        writeString(indent + " * Method: " + methodFullName + "()\n");
+        writeString(indent + " * @this {" + methodFullName.substring(0, methodFullName.lastIndexOf(".")) + "}\n");
+        writeString(indent + " * @protected\n");
+        writeString(indent + " * @override\n");
+        writeString(indent + " * @return {Object}\n");
+        writeString(indent + " */\n");
+
+        // Emit method definition itself -- based on emitMethod()
+        writeString(indent + methodPrefix + methodName);
+        writeString(" " + assignmentOp + " ");
+
+        writeString("function() /* : Object */\n");
+        writeString("{\n");
+
+        indent = "\t\t";
+        writeString(indent + "return " + jsonResult + ";\n");
+
+        writeString("}");
+    }
+
+    /**
+     * Given a var or const trait, return the default value it should be
+     * initialized to if there was no initializer in the AS code
+     */
+    public static String getDefaultInitializerForVariable(Name varType)
+    {
+        if (varType != null)
+        {
+            String typeName = JSGeneratingReducer.getBasenameFromName(varType);
+
+            // int/uint default to 0 in AS; this matters since, e.g.: 0++ = 1; undefined++ = NaN
+            if (typeName.equals("int") || typeName.equals("uint"))
+                return "0";
+
+            // Number defaults to naN
+            if (typeName.equals("Number"))
+                return "NaN";
+
+            // Boolean defaults to false in AS; this matters when comparing two bools: undefined != false
+            if (typeName.equals("Boolean"))
+                return "false";
+        }
+        return "undefined";
+    }
+
+    /**
+     * Given a class member and the class's base class, try to detect whether it
+     * will hit FJS-24 - and if so print a warning. Intended to be called from
+     * emitTraits().
+     */
+    public void warnIfPrivateNameCollision(IClassDefinition baseClass, ASDefinitionFilter baseClassAllFilter, String memberName, String memberFullName, String memberDescription)
+    {
+        // If baseClass is null, we're probably looking at a global function like trace() or setTimeout()
+        if (baseClass != null)
+        {
+            IDefinition conflict = MemberedDefinitionUtils.getMemberByName(baseClass, m_project, memberName, baseClassAllFilter);
+            if (conflict != null)
+            {
+                // If member is non-private, it's *expected* to be overridden (note: we could also check isOverride() on classDef's member)
+                // If member is static, FJS-24 doesn't apply and all is well
+                if (conflict.isPrivate() && !conflict.isStatic())
+                {
+                    m_sharedData.stderr("Warning: " + memberDescription + " " + memberFullName + " will unexpectedly override a private member of superclass " + conflict.getParent().getBaseName());
+                }
+            }
+        }
+    }
+
+    /*
+     * private String getCodeForMethodInfo( MethodInfo mi ) { String body = "";
+     * MethodBodyInfo mbi = findMethodBodyInfo( mi ); if( mbi != null ) { for
+     * (Block b : mbi.getBlocks()) { for (int i = 0; i < b.instructions.size()
+     * && !b.instructions.get(i).isBranch(); i++) { final Instruction insn =
+     * b.instructions.get(i); if( insn.getOpcode() == JSSharedData.OP_JS ) {
+     * final String str = (String)insn.getOperand(0); body +=
+     * JSGeneratingReducer.indentBlock(str,1); } } } } return body; }
+     */
+
+    protected String getCodeForConstructor(MethodInfo mi)
+    {
+        String body = "";
+        MethodBodyInfo mbi = findMethodBodyInfo(mi);
+
+        if (mbi != null)
+        {
+            for (IBasicBlock b : mbi.getCfg().getBlocksInEntryOrder())
+            {
+                for (int i = 0; i < b.size() && !b.get(i).isBranch(); i++)
+                {
+                    final Instruction insn = b.get(i);
+                    if (insn.getOpcode() == JSSharedData.OP_JS)
+                    {
+                        final String str = (String)insn.getOperand(0);
+
+                        // we are only interested in the instruction that initialize variables with a value.
+                        // if( str.contains("=") )
+                        body += JSGeneratingReducer.indentBlock(str, 1);
+                    }
+                }
+            }
+        }
+        return body;
+    }
+
+    private void emitJSDocForMethod(Trait t, MethodInfo mi, MethodBodyInfo mbi, String fullName, String indent)
+    {
+        final Boolean isCtor = t == null;
+        final Boolean isInterface = mbi == null;
+
+        writeString(indent + "\n\n");
+        writeString(indent + "/**\n");
+        if (isCtor)
+        {
+            writeString(indent + " * Constructor: " + fullName + "()\n");
+            writeString(indent + " * @constructor\n");
+        }
+        else if (isInterface)
+        {
+            writeString(indent + " * Interface: " + fullName + "()\n");
+        }
+        else
+        {
+            writeString(indent + " * Method: " + fullName + "()\n");
+        }
+
+        if (!isInterface)
+        {
+            if (fullName.contains("."))
+            {
+                if (fullName.substring(0, fullName.lastIndexOf(".")).equals(JSSharedData.JS_FRAMEWORK_NAME))
+                    writeString(indent + " * @this {" + JSSharedData.JS_FRAMEWORK_NAME + "}\n");
+                else
+                    writeString(indent + " * @this {" + fullName.substring(0, fullName.lastIndexOf(".")) + "}\n");
+            }
+
+            if (t != null)
+            {
+                final Name name = t.getNameAttr("name");
+                if (name != null)
+                {
+                    Namespace ns = name.getSingleQualifier();
+                    if (ns.getKind() == CONSTANT_PrivateNs)
+                        writeString(indent + " * @private\n");
+                    else if (ns.getKind() == CONSTANT_ProtectedNs)
+                        writeString(indent + " * @protected\n");
+                }
+                if (t.isOverride() ||
+                    (t.hasAttr("override") && (Boolean)(t.getAttr("override")) == true))
+                {
+                    writeString(indent + " * @override\n");
+                }
+            }
+        }
+
+        Vector<PooledValue> defaultValues = mi.getDefaultValues();
+        Vector<Name> paramTypes = mi.getParamTypes();
+        List<String> paramNames = mi.getParamNames();
+
+        int nthParam = 0;
+        final int defaultsStartAt = paramTypes.size() - defaultValues.size();
+        final Boolean needsRest = (mi.getFlags() & ABCConstants.NEED_REST) > 0;
+        final int restStartsAt = needsRest ? paramNames.size() - 1 : paramNames.size();
+
+        for (String argName : paramNames)
+        {
+            if (nthParam == restStartsAt)
+            {
+                // param is rest argument
+                writeString(indent + " * @param {...} " + argName + "\n");
+            }
+            else
+            {
+                Name nextParam = paramTypes.elementAt(nthParam);
+                final StringBuilder sb = new StringBuilder();
+                JSGeneratingReducer.nameToJSDocType(m_project, nextParam, sb);
+                final String argType = sb.toString();
+                if (nthParam < defaultsStartAt)
+                {
+                    // param without default value
+                    writeString(indent + " * @param {" + argType + "} " + argName + "\n");
+                }
+                else
+                {
+                    // param with default value
+                    writeString(indent + " * @param {" + argType + "=} " + argName);
+
+                    String defaultVal = "undefined";
+                    PooledValue val = defaultValues.elementAt(nthParam - defaultsStartAt);
+                    if (val != null)
+                    {
+                        switch (val.getKind())
+                        {
+                            case ABCConstants.CONSTANT_Int:
+                                defaultVal = val.getIntegerValue().toString();
+                                break;
+                            case ABCConstants.CONSTANT_UInt:
+                                defaultVal = val.getLongValue().toString();
+                                break;
+                            case ABCConstants.CONSTANT_Double:
+                                defaultVal = val.getDoubleValue().toString();
+                                break;
+                            case ABCConstants.CONSTANT_Utf8:
+                                defaultVal = val.getStringValue();
+                                break;
+                            case ABCConstants.CONSTANT_True:
+                                defaultVal = "true";
+                                break;
+                            case ABCConstants.CONSTANT_False:
+                                defaultVal = "false";
+                                break;
+                            case ABCConstants.CONSTANT_Undefined:
+                                defaultVal = "undefined";
+                                break;
+                            case ABCConstants.CONSTANT_Null:
+                                defaultVal = "null";
+                                break;
+                            default:
+                            {
+                                final Namespace ns = val.getNamespaceValue();
+                                if (ns != null)
+                                    defaultVal = ns.getName() + " /* (namespace) */";
+                            }
+                                break;
+                        }
+                    }
+                    writeString(" Defaults to " + defaultVal + "\n");
+                }
+            }
+
+            nthParam++;
+        }
+        if (mi.getReturnType() != null && !JSGeneratingReducer.getBasenameFromName(mi.getReturnType()).equals("void"))
+        {
+            final StringBuilder sb = new StringBuilder();
+            JSGeneratingReducer.nameToJSDocType(m_project, mi.getReturnType(), sb);
+
+            writeString(indent + " * @return {" + sb.toString() + "}\n");
+        }
+
+        writeString(indent + " */\n");
+    }
+
+    protected Boolean isPackageFunction(MethodInfo mi)
+    {
+        final FunctionDefinition fdef = m_methodInfoToDefinition.get(mi);
+        if (fdef != null && fdef.getParent() instanceof PackageDefinition)
+            return true;
+
+        return false;
+    }
+
+    protected void emitFrameworkInit()
+    {
+        writeString("\n");
+        writeString("// Overrides \n");
+
+        writeString("adobe.globals = __global;\n");
+
+        // auto-register classes
+        writeString("" + JSSharedData.JS_CLASSES + " = {};\n");
+        writeString("" + JSSharedData.JS_INT_CLASS + " = IntClass;\n");
+        writeString("" + JSSharedData.JS_UINT_CLASS + " = UIntClass;\n");
+
+        // override settings for adobe.USE_SELF and adobe.USE_STATIC
+        final Boolean useClosure = JSSharedData.m_useClosureLib;
+        final Boolean useSelfParameter = JSSharedData.m_useSelfParameter;
+        final Boolean convertToStatic = useSelfParameter && false; // see JSSharedData.m_convertToStatic
+        writeString("\n");
+        writeString("// Settings \n");
+        writeString("adobe.USE_CLOSURE = " + (useClosure ? "true" : "false") + ";\n");
+        writeString("adobe.USE_SELF = " + (useSelfParameter ? "true" : "false") + ";\n");
+        writeString("adobe.USE_STATIC = " + (convertToStatic ? "true" : "false") + ";\n");
+        writeString("adobe.ROOT_NAME = \"" + JSSharedData.ROOT_NAME + "\";\n");
+        writeString("adobe.NO_EXPORTS = " + JSSharedData.NO_EXPORTS + ";\n");
+        writeString("adobe.root = " + JSSharedData.JS_SYMBOLS + ";\n");
+    }
+
+    protected void emitMethod(Trait t, MethodInfo mi, Boolean isFramework, Boolean isExtern, Boolean isInterface, Boolean isPackageFunction, String fullName, String name, String xetter, String methodPrefix, String assignmentOp, String separator, String indent) throws Exception
+    {
+        // don't emit extern package functions
+        if (isExtern && isPackageFunction)
+            return;
+
+        MethodBodyInfo mbi = findMethodBodyInfo(mi);
+
+        if (name != null)
+        {
+            // Sometimes mi.name is empty
+            if (mi.getMethodName() == null || mi.getMethodName().isEmpty())
+                mi.setMethodName(name);
+
+            // set m_currentScope to classScope
+            if (m_currentScope != null)
+            {
+                IASScope methodScope = null;
+                IASScope scope = m_currentScope;
+                ASDefinitionFilter filter = new ASDefinitionFilter(ClassificationValue.MEMBERS_AND_TYPES,
+                        SearchScopeValue.ALL_SCOPES,
+                        AccessValue.ALL,
+                        scope.getDefinition());
+                IDefinition def = ASScopeUtils.findDefinitionByName(scope, m_project, name, filter);
+                if (def != null)
+                {
+                    //FunctionDefinition 
+                    // methodScope = new ASScope((ASScope)def.getContainingScope());
+                    methodScope = def.getContainingScope();
+                    m_currentScope = methodScope;
+                }
+            }
+
+            emitJSDocForMethod(t, mi, mbi, fullName, indent);
+
+            final Boolean isGetter = t != null && t.getKind() == TRAIT_Getter;
+            // final Boolean isPackageFunction = methodPrefix.isEmpty() && isPackageFunction(mi);
+
+            // regular constructor
+            writeString(indent + methodPrefix + xetter + name);
+            if (isInterface && isGetter)
+            {
+                writeString(";\n");
+                return;
+            }
+
+            writeString(" " + assignmentOp + " ");
+
+            writeString("function(");
+            String a_priori_insns = "";
+            // a_priori_insns = emitParameters( m_methodInfoToDefinition.get(mi) );
+            a_priori_insns = emitParameters(mi);
+            writeString(")");
+
+            // return type 
+            if (mi.getReturnType() != null)
+                writeString(" /* : " + JSGeneratingReducer.getBasenameFromName(mi.getReturnType()) + " */");
+
+            if (isInterface)
+            {
+                writeString(" {};\n");
+            }
+            else
+            {
+                writeString("\n");
+                writeString(indent + "{");
+                writeString("\n");
+                if (!a_priori_insns.isEmpty())
+                {
+                    writeString(a_priori_insns);
+                }
+                emitMethodBody(mbi);
+                writeString(indent + "}");
+            }
+
+        }
+        else
+        {
+            // all __static_inits need to be registered.
+            if (!JSSharedData.instance.hasClassInit(fullName))
+                JSSharedData.instance.registerClassInit(fullName);
+
+            final String staticInitName = methodPrefix + JSSharedData.STATIC_INIT;
+
+            writeString("\n\n");
+            writeString("/**\n");
+            writeString(" * Method: " + indent + staticInitName + "()\n");
+            writeString(" */\n");
+
+            writeString(indent + staticInitName + " = ");
+            writeString("function() /* : void */\n");
+            writeString(indent + "{\n");
+            writeString(indent + "\t" + staticInitName + " = " + JSSharedData.JS_EMPTY_FUNCTION + ";\n");
+
+            // static init
+            emitMethodBody(mbi);
+
+            writeString(indent + "}");
+        }
+    }
+
+    private void emitScriptInfo(ScriptInfo info) throws Exception
+    {
+        // w.writeU30(getScriptId(info.getInitId()));
+        // emitTraits(info.getTraits(), "", "\t" );
+
+        final Object init_id = info.getInit();
+        ;
+        if (init_id instanceof MethodInfo)
+        {
+            final MethodInfo mi = (MethodInfo)init_id;
+            final MethodBodyInfo mbi = this.findMethodBodyInfo(mi);
+            if (mbi != null)
+            {
+                final String str = extractCodeFromMethodBodyInfo(mbi);
+                if (!str.isEmpty())
+                {
+                    final StringBuilder scriptInfos = new StringBuilder();
+
+                    scriptInfos.append("// ScriptInfo \n");
+                    scriptInfos.append("{\n");
+                    scriptInfos.append("\tvar " + JSSharedData.THIS + " = ");
+                    if (m_packageName != null && !m_packageName.isEmpty())
+                    {
+                        scriptInfos.append(m_packageName + ";\n");
+                    }
+                    else
+                    {
+                        scriptInfos.append(JSSharedData.JS_FRAMEWORK_NAME + ".globals;\n");
+                    }
+
+                    // This is just crazy...
+                    // It looks like very variable declared in a script info block becomes a global variable.
+                    // See testUnicodeRangeHelper() in Tamarin's ecma3/Unicode/unicodeUtil.as, which for some
+                    // reasons uses "this.array" instead of just "array".
+                    final StringBuilder sb = new StringBuilder();
+                    for (String line : str.split("\n"))
+                    {
+                        if (line.startsWith("var "))
+                            sb.append(line.replaceFirst("var ", JSSharedData.THIS + "."));
+                        else
+                            sb.append(line);
+                        sb.append("\n");
+                    }
+
+                    // the meat of  emitCode(mbi);
+                    scriptInfos.append(JSGeneratingReducer.indentBlock(sb.toString(), 1));
+
+                    scriptInfos.append("}\n");
+
+                    JSSharedData.instance.registerScriptInfo(scriptInfos.toString());
+                }
+            }
+        }
+    }
+
+    protected void emitMethodBody(MethodBodyInfo f)
+            throws Exception
+    {
+        if (f == null)
+            return;
+
+        /*
+         * MethodInfo signature = f.getMethodInfo();
+         * w.writeU30(getMethodId(signature)); f.computeFrameCounts();
+         * w.writeU30(f.getMaxStack()); int max_local = f.getLocalCount(); if
+         * (signature.getParamCount() > max_local) max_local =
+         * signature.getParamCount(); w.writeU30(max_local);
+         * w.writeU30(f.getInitScopeDepth()); w.writeU30(f.getMaxScopeDepth());
+         */
+
+        if (!m_methodPrologue.isEmpty())
+        {
+            writeString(m_methodPrologue);
+            m_methodPrologue = "";
+        }
+
+        emitCode(f);
+
+        if (!m_methodPostlogue.isEmpty())
+        {
+            writeString(m_methodPostlogue);
+            m_methodPostlogue = "";
+        }
+    }
+
+    private void emitCode(MethodBodyInfo f)
+            throws Exception
+    {
+        String str = extractCodeFromMethodBodyInfo(f);
+
+        /*
+         * Experimental: ABC decompilation if( str.isEmpty() ) { final
+         * ByteArrayOutputStream out = new ByteArrayOutputStream(); final
+         * JSConverter converter = new JSConverter(m_project, m_currentScope,
+         * out ); final MethodInfo mi = f.getMethodInfo(); final IMethodVisitor
+         * mv = converter.visitMethod(mi); mv.visit(); final IMethodBodyVisitor
+         * mbv = mv.visitBody(f); mbv.visit(); mbv.visitEnd(); mv.visitEnd();
+         * str = out.toString(); }
+         */
+
+        if (!str.isEmpty())
+        {
+            writeString(JSGeneratingReducer.indentBlock(str, 1));
+        }
+    }
+
+    /*
+     * private String indentBlock( String block, int indentBy ) { Boolean
+     * firstPart = true; String s = ""; String[] parts = block.split( "\n" );
+     * for( String part : parts ) { if( firstPart ) firstPart = false; else s +=
+     * "\n"; for( int i = 0; i < indentBy; ++i ) s += "\t"; s += part; } return
+     * s; } private void emitNamespace(Namespace ns) { w.write(ns.getKind());
+     * w.writeU30(stringPool.id(ns.getName())); }
+     */
+
+    private String extractCodeFromBlock(IBasicBlock b)
+    {
+        String str = "";
+        for (int i = 0; i < b.size() && !b.get(i).isBranch(); i++)
+        {
+            final Instruction insn = b.get(i);
+            if (insn.getOpcode() == JSSharedData.OP_JS)
+                str += (String)insn.getOperand(0);
+        }
+        return str;
+    }
+
+    private String extractCodeFromMethodBodyInfo(MethodBodyInfo mbi)
+    {
+        String str = "";
+        for (IBasicBlock b : mbi.getCfg().getBlocksInEntryOrder())
+        {
+            str += extractCodeFromBlock(b);
+        }
+        return str;
+    }
+
+    class JSOutputStream extends ByteArrayOutputStream
+    {
+        void rewind(int n)
+        {
+            super.count -= n;
+        }
+
+        void writeString(String str)
+        {
+            try
+            {
+                write(str.getBytes());
+            }
+            catch (IOException e)
+            {
+
+            }
+        }
+
+        public void write(int i)
+        {
+            // super.write(i);
+        }
+
+        void writeU16(int i)
+        {
+            //write(i);
+            //write(i >> 8);
+        }
+
+        void writeS24(int i)
+        {
+            //writeU16(i);
+            //write(i >> 16);
+        }
+
+        void write64(long i)
+        {
+            //writeS24((int)i);
+            //writeS24((int)(i >> 24));
+            //writeU16((int)(i >> 48));
+        }
+
+        void writeU30(int v)
+        {
+            /*
+             * if (v < 128 && v >= 0) { write(v); } else if (v < 16384 && v >=
+             * 0) { write(v & 0x7F | 0x80); write(v >> 7); } else if (v <
+             * 2097152 && v >= 0) { write(v & 0x7F | 0x80); write(v >> 7 |
+             * 0x80); write(v >> 14); } else if (v < 268435456 && v >= 0) {
+             * write(v & 0x7F | 0x80); write(v >> 7 | 0x80); write(v >> 14 |
+             * 0x80); write(v >> 21); } else { write(v & 0x7F | 0x80); write(v
+             * >> 7 | 0x80); write(v >> 14 | 0x80); write(v >> 21 | 0x80);
+             * write(v >> 28); }
+             */
+        }
+
+        int sizeOfU30(int v)
+        {
+            if (v < 128 && v >= 0)
+            {
+                return 1;
+            }
+            else if (v < 16384 && v >= 0)
+            {
+                return 2;
+            }
+            else if (v < 2097152 && v >= 0)
+            {
+                return 3;
+            }
+            else if (v < 268435456 && v >= 0)
+            {
+                return 4;
+            }
+            else
+            {
+                return 5;
+            }
+        }
+    }
+
+    /**
+     * The nominal name given to a MultinameL.
+     * 
+     * @see http://bugs.adobe.com/jira/browse/CMP-393, this may not be
+     * necessary, and if under some circumstances it is necessary this is
+     * certainly not the name required.
+     */
+    private static Name indexAccessName;
+    /**
+     * The above Name packaged up into operand form.
+     */
+    private static Object[] indexAccessOperands;
+    /*
+     * Initialization code for indexAccessname and indexAccessOperands.
+     */
+    static
+    {
+        Vector<Namespace> usual_suspects = new Vector<Namespace>(2);
+        usual_suspects.add(new Namespace(CONSTANT_PrivateNs));
+        usual_suspects.add(new Namespace(CONSTANT_PackageNs));
+        indexAccessName = new Name(ABCConstants.CONSTANT_MultinameL, new Nsset(usual_suspects), null);
+        indexAccessOperands = new Object[] {indexAccessName};
+    }
+
+    /**
+     * Find all the operands in a method body and make sure they find their way
+     * into the appropriate pool.
+     * 
+     * @param mi - the method body.
+     * @post any runtime multinames have a dummy Name operand.
+     */
+    void _poolOperands(MethodBodyInfo mbi)
+    {
+        for (IBasicBlock b : mbi.getCfg().getBlocksInEntryOrder())
+            for (Instruction insn : b.getInstructions())
+                switch (insn.getOpcode())
+                {
+                    case OP_findproperty:
+                    case OP_findpropstrict:
+                    case OP_getlex:
+                    case OP_getsuper:
+                    case OP_setsuper:
+                    case OP_getdescendants:
+                    case OP_initproperty:
+                    case OP_istype:
+                    case OP_coerce:
+                    case OP_astype:
+                    case OP_finddef:
+                        visitPooledName((Name)insn.getOperand(0));
+                        break;
+                    case OP_deleteproperty:
+                    case OP_getproperty:
+                    case OP_setproperty:
+                        if (insn.getOperandCount() > 0 && insn.getOperand(0) != null)
+                        {
+                            visitPooledName((Name)insn.getOperand(0));
+                        }
+                        else
+                        {
+                            //  get/set/deleteproperty with no operands => runtime multiname.
+                            visitPooledName(indexAccessName);
+                            insn.setOperands(indexAccessOperands);
+                        }
+                        break;
+                    case OP_callproperty:
+                    case OP_callproplex:
+                    case OP_callpropvoid:
+                    case OP_callsuper:
+                    case OP_callsupervoid:
+                    case OP_constructprop:
+                        visitPooledName((Name)insn.getOperand(0));
+                        break;
+                    case OP_pushstring:
+                    case OP_dxns:
+                    case OP_debugfile:
+                        break;
+                    case OP_pushnamespace:
+                        visitPooledNamespace((Namespace)insn.getOperand(0));
+                        break;
+                    case OP_pushint:
+                        break;
+                    case OP_pushuint:
+                        break;
+                    case OP_pushdouble:
+                        break;
+                    case OP_debug:
+                        break;
+                }
+    }
+
+    /**
+     * Inspect a set of Traits and ensure that constant initializer values have
+     * been properly registered in the constant pools.
+     */
+    private void poolTraitValues(Traits ts)
+    {
+        for (Trait t : ts)
+        {
+            if (t.hasAttr(Trait.SLOT_VALUE))
+            {
+                Object trait_value = t.getAttr(Trait.SLOT_VALUE);
+                if (trait_value == null)
+                {
+                    //  No action required; the pool ID resolution logic
+                    //  handles a null pointer by returning the nil pool value.
+                }
+                else if (trait_value instanceof String)
+                {
+                    visitPooledString((String)trait_value);
+                }
+                else if (trait_value instanceof Namespace)
+                {
+                    visitPooledNamespace((Namespace)trait_value);
+                }
+                else if (trait_value instanceof Double)
+                {
+                    visitPooledDouble((Double)trait_value);
+                }
+                else if (trait_value instanceof Integer)
+                {
+                    visitPooledInt((Integer)trait_value);
+                }
+                else if (trait_value instanceof Long)
+                {
+                    visitPooledUInt((Long)trait_value);
+                }
+                else if (trait_value instanceof Float)
+                {

[... 1254 lines stripped ...]


Mime
View raw message