mxml-reflect-object-property compiler option
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogEmitterTokens.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogEmitterTokens.java
index 8afd294..75ffea6 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogEmitterTokens.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/goog/JSGoogEmitterTokens.java
@@ -38,7 +38,8 @@
     ARRAY("Array"),
     ERROR("Error"),
     SELF("self"),
-    SUPERCLASS("superClass_");
+    SUPERCLASS("superClass_"),
+    GOOG_REFLECT_OBJECTPROPERTY("goog.reflect.objectProperty");
 
     private String token;
 
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleBasicMXMLDescriptorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleBasicMXMLDescriptorEmitter.java
index ea11bf7..934569b 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleBasicMXMLDescriptorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleBasicMXMLDescriptorEmitter.java
@@ -22,12 +22,16 @@
 import org.apache.royale.compiler.codegen.ISubEmitter;
 import org.apache.royale.compiler.codegen.mxml.js.IMXMLJSEmitter;
 import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
+import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
 import org.apache.royale.compiler.internal.codegen.mxml.MXMLSubEmitter;
 import org.apache.royale.compiler.internal.codegen.mxml.royale.MXMLDescriptorSpecifier;
 import org.apache.royale.compiler.internal.codegen.mxml.royale.MXMLEventSpecifier;
+import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
 
 public class JSRoyaleBasicMXMLDescriptorEmitter extends MXMLSubEmitter implements ISubEmitter<MXMLDescriptorSpecifier>
 {
+    private boolean useGoogReflectObjectProperty = false;
+
     public JSRoyaleBasicMXMLDescriptorEmitter(IMXMLJSEmitter emitter)
     {
         super(emitter);
@@ -36,6 +40,8 @@
     @Override
     public void emit(MXMLDescriptorSpecifier root)
     {
+        RoyaleJSProject project = (RoyaleJSProject) getMXMLWalker().getProject();
+        useGoogReflectObjectProperty = project.config != null && project.config.getMxmlReflectObjectProperty();
 		outputDescriptorSpecifier(root, true);
 	}
 
@@ -201,9 +207,35 @@
 
     private void outputPropertySpecifier(MXMLDescriptorSpecifier specifier, boolean writeNewline)
     {
-        write((specifier.isProperty) ? ASEmitterTokens.SINGLE_QUOTE.getToken() : "");
-        write(specifier.name);
-        write((specifier.isProperty) ? ASEmitterTokens.SINGLE_QUOTE.getToken() : "");
+        if(specifier.isProperty)
+        {
+            if(useGoogReflectObjectProperty)
+            {
+                write(JSGoogEmitterTokens.GOOG_REFLECT_OBJECTPROPERTY);
+                write(ASEmitterTokens.PAREN_OPEN);
+            }
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            write(specifier.name);
+            write(ASEmitterTokens.SINGLE_QUOTE);
+            if(useGoogReflectObjectProperty)
+            {
+                MXMLDescriptorSpecifier parentSpecifier = specifier.parent;
+                String id = (parentSpecifier.id != null) ? parentSpecifier.id : parentSpecifier.effectiveId;
+                write(ASEmitterTokens.COMMA);
+                write(ASEmitterTokens.SPACE);
+                write(ASEmitterTokens.THIS);
+                if (id != null)
+                {
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(id);
+                }
+                write(ASEmitterTokens.PAREN_CLOSE);
+            }
+        }
+        else
+        {
+            write(specifier.name);
+        }
         writeDelimiter(writeNewline);
 
         if (specifier.isProperty)
@@ -252,13 +284,17 @@
             {
                 write(specifier.propertySpecifiers.size() + 1 + "");
                 writeDelimiter(writeNewline);
-                String idPropName = (specifier.effectiveId != null) ? "_id"
-                        : "id";
-                writeSimpleDescriptor(idPropName, ASEmitterTokens.TRUE.getToken(),
-                        ASEmitterTokens.SINGLE_QUOTE.getToken()
-                                + ((specifier.id != null) ? specifier.id : specifier.effectiveId) + ASEmitterTokens.SINGLE_QUOTE.getToken(),
-                        writeNewline);
-
+                String idPropName = (specifier.effectiveId != null) ? "_id" : "id";
+                String id = (specifier.id != null) ? specifier.id : specifier.effectiveId;
+                write(ASEmitterTokens.SINGLE_QUOTE);
+                write(idPropName);
+                write(ASEmitterTokens.SINGLE_QUOTE);
+                writeDelimiter(writeNewline);
+                write(ASEmitterTokens.TRUE);
+                writeDelimiter(writeNewline);
+                write(ASEmitterTokens.SINGLE_QUOTE);
+                write(id);
+                write(ASEmitterTokens.SINGLE_QUOTE);
                 writeDelimiter(writeNewline);
             }
             else
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
index 05d27c2..8ee0bea 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleDocEmitter.java
@@ -627,7 +627,10 @@
         }
         else
         {
-            boolean warnPublicVars = fjp.config != null && fjp.config.getWarnPublicVars() && !fjp.config.getPreventRenamePublicSymbols();
+            boolean warnPublicVars = fjp.config != null
+                    && fjp.config.getWarnPublicVars()
+                    && !fjp.config.getPreventRenamePublicSymbols()
+                    && !fjp.config.getMxmlReflectObjectProperty();
             IMetaTagsNode meta = node.getMetaTags();
             boolean bindable = false;
             if (meta != null)
@@ -652,12 +655,12 @@
                 }
                 
                 if (!suppressedWarning(node, fjp))
+                {
                 	fjp.getProblems().add(new PublicVarWarningProblem(node.getSourcePath(),
                             node.getStart(), node.getEnd(),
                             warningNode.getLine(), warningNode.getColumn(),
                             node.getEndLine(), node.getEndColumn()));
-               
-
+                }
             }
             boolean avoidExport = (node.getASDocComment() instanceof ASDocComment
                     && ((ASDocComment)node.getASDocComment()).commentNoEnd()
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleEmitter.java
index f211c8f..ff2fc41 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/mxml/royale/MXMLRoyaleEmitter.java
@@ -1510,6 +1510,7 @@
         IASEmitter asEmitter = ((IMXMLBlockWalker) getMXMLWalker())
                 .getASEmitter();
         boolean allowDynamicBindings = project.config != null && project.config.getAllowDynamicBindings();
+        boolean useMxmlReflectObjectProperty = project.config != null && project.config.getMxmlReflectObjectProperty();
         
         writeNewline("/**");
         writeNewline(" * @export"); // must export or else GCC will remove it
@@ -1528,7 +1529,10 @@
         boolean hadOutput = false;
         for (BindingInfo bi : bindingInfo)
         {
-            if (hadOutput) writeNewline(ASEmitterTokens.COMMA.getToken());
+            if (hadOutput)
+            {
+                writeNewline(ASEmitterTokens.COMMA);
+            }
             hadOutput = true;
             String s;
             IMXMLNode node = bi.node;
@@ -1559,7 +1563,11 @@
                 	IExpressionNode getterNode = getterNodes.get(i);
                     sb.append(asEmitter.stringifyNode(getterNode));
                     if (i < n - 1)
-                    	sb.append(ASEmitterTokens.SPACE.getToken() + ASEmitterTokens.PLUS.getToken() + ASEmitterTokens.SPACE.getToken());
+                    {
+                        sb.append(ASEmitterTokens.SPACE.getToken());
+                        sb.append(ASEmitterTokens.PLUS.getToken());
+                        sb.append(ASEmitterTokens.SPACE.getToken());
+                    }
                 }
                 sb.append("; },");
                 writeNewline(sb.toString());
@@ -1568,39 +1576,107 @@
             {
             	if (bi.classDef != null)
             	{
-	                String[] parts = s.split("\\.");
-	                write(ASEmitterTokens.SQUARE_OPEN.getToken() + ASEmitterTokens.DOUBLE_QUOTE.getToken() +
-	                        bi.classDef.getQualifiedName() + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+                    String[] parts = s.split("\\.");
 	                String qname = bi.classDef.getQualifiedName();
+                    write(ASEmitterTokens.SQUARE_OPEN);
+                    write(ASEmitterTokens.DOUBLE_QUOTE);
+                    write(qname);
+                    write(ASEmitterTokens.DOUBLE_QUOTE);
 	                if (!usedNames.contains(qname))
 	                	usedNames.add(qname);
 	                if (!staticUsedNames.contains(qname))
 	                	staticUsedNames.add(qname);
+                    StringBuilder objString = null;
+                    if (useMxmlReflectObjectProperty)
+                    {
+                        objString = new StringBuilder();
+                        objString.append(qname);
+                    }
 	                int n = parts.length;
 	                for (int i = 1; i < n; i++)
 	                {
 	                    String part = parts[i];
-	                    write(", " +  ASEmitterTokens.DOUBLE_QUOTE.getToken() + part + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+                        write(", ");
+                        if(useMxmlReflectObjectProperty)
+                        {
+                            write(JSGoogEmitterTokens.GOOG_REFLECT_OBJECTPROPERTY);
+                            write(ASEmitterTokens.PAREN_OPEN);
+                        }
+                        write(ASEmitterTokens.DOUBLE_QUOTE);
+                        write(part);
+                        write(ASEmitterTokens.DOUBLE_QUOTE);
+                        if(useMxmlReflectObjectProperty)
+                        {
+                            write(ASEmitterTokens.COMMA);
+                            write(ASEmitterTokens.SPACE);
+                            write(objString.toString());
+                            write(ASEmitterTokens.PAREN_CLOSE);
+                            objString.append(".");
+                            objString.append(part);
+                        }
 	                }
-	                writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + ASEmitterTokens.COMMA.getToken());
+                    write(ASEmitterTokens.SQUARE_CLOSE);
+                    writeNewline(ASEmitterTokens.COMMA);
             	}
             	else
             	{
 	                String[] parts = s.split("\\.");
-	                write(ASEmitterTokens.SQUARE_OPEN.getToken() + ASEmitterTokens.DOUBLE_QUOTE.getToken() +
-	                        parts[0] + ASEmitterTokens.DOUBLE_QUOTE.getToken());
-	                int n = parts.length;
-	                for (int i = 1; i < n; i++)
+                    write(ASEmitterTokens.SQUARE_OPEN);
+                    StringBuilder objString = null;
+                    if (useMxmlReflectObjectProperty)
+                    {
+                        objString = new StringBuilder();
+                        objString.append("this");
+                    }
+                    int n = parts.length;
+	                for (int i = 0; i < n; i++)
 	                {
-	                    String part = parts[i];
-	                    write(", " +  ASEmitterTokens.DOUBLE_QUOTE.getToken() + part + ASEmitterTokens.DOUBLE_QUOTE.getToken());
-	                }
-	                writeNewline(ASEmitterTokens.SQUARE_CLOSE.getToken() + ASEmitterTokens.COMMA.getToken());
+                        String part = parts[i];
+                        if (i > 0)
+                        {
+                            write(", ");
+                        }
+                        if(useMxmlReflectObjectProperty)
+                        {
+                            write(JSGoogEmitterTokens.GOOG_REFLECT_OBJECTPROPERTY);
+                            write(ASEmitterTokens.PAREN_OPEN);
+                        }
+                        write(ASEmitterTokens.DOUBLE_QUOTE);
+                        write(part);
+                        write(ASEmitterTokens.DOUBLE_QUOTE);
+                        if(useMxmlReflectObjectProperty)
+                        {
+                            write(ASEmitterTokens.COMMA);
+                            write(ASEmitterTokens.SPACE);
+                            write(objString.toString());
+                            write(ASEmitterTokens.PAREN_CLOSE);
+                            objString.append(".");
+                            objString.append(part);
+                        }
+                    }
+                    write(ASEmitterTokens.SQUARE_CLOSE);
+	                writeNewline(ASEmitterTokens.COMMA);
             	}
             }
             else
-                writeNewline(ASEmitterTokens.DOUBLE_QUOTE.getToken() + s +
-                        ASEmitterTokens.DOUBLE_QUOTE.getToken() + ASEmitterTokens.COMMA.getToken());
+            {
+                if(useMxmlReflectObjectProperty)
+                {
+                    write(JSGoogEmitterTokens.GOOG_REFLECT_OBJECTPROPERTY);
+                    write(ASEmitterTokens.PAREN_OPEN);
+                }
+                write(ASEmitterTokens.DOUBLE_QUOTE);
+                write(s);
+                write(ASEmitterTokens.DOUBLE_QUOTE);
+                if(useMxmlReflectObjectProperty)
+                {
+                    write(ASEmitterTokens.COMMA);
+                    write(ASEmitterTokens.SPACE);
+                    write(ASEmitterTokens.THIS);
+                    write(ASEmitterTokens.PAREN_CLOSE);
+                }
+                writeNewline(ASEmitterTokens.COMMA);
+            }
 
             IExpressionNode destNode = bi.getExpressionNodeForDestination();
             s = bi.getDestinationString();
@@ -1621,32 +1697,75 @@
             {
                 StringBuilder sb = new StringBuilder();
                 sb.append(generateSetterFunction(bi, destNode));
-                writeNewline(sb.toString() + ASEmitterTokens.COMMA.getToken());
+                write(sb.toString());
+                writeNewline(ASEmitterTokens.COMMA);
             }
             else
-                writeNewline(ASEmitterTokens.NULL.getToken() + ASEmitterTokens.COMMA.getToken());
+            {
+                write(ASEmitterTokens.NULL);
+                writeNewline(ASEmitterTokens.COMMA);
+            }
 
             if (s == null)
             {
-                write(ASEmitterTokens.NULL.getToken());
+                write(ASEmitterTokens.NULL);
             }
             else if (s.contains("."))
             {
                 String[] parts = s.split("\\.");
-                write(ASEmitterTokens.SQUARE_OPEN.getToken() + ASEmitterTokens.DOUBLE_QUOTE.getToken() +
-                        parts[0] + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+                write(ASEmitterTokens.SQUARE_OPEN);
+                StringBuilder objString = null;
+                if (useMxmlReflectObjectProperty)
+                {
+                    objString = new StringBuilder();
+                    objString.append("this");
+                }
                 int n = parts.length;
-                for (int i = 1; i < n; i++)
+                for (int i = 0; i < n; i++)
                 {
                     String part = parts[i];
-                    write(", " + ASEmitterTokens.DOUBLE_QUOTE.getToken() + part + ASEmitterTokens.DOUBLE_QUOTE.getToken());
+                    if (i > 0)
+                    {
+                        write(", ");
+                    }
+                    if(useMxmlReflectObjectProperty)
+                    {
+                        write(JSGoogEmitterTokens.GOOG_REFLECT_OBJECTPROPERTY);
+                        write(ASEmitterTokens.PAREN_OPEN);
+                    }
+                    write(ASEmitterTokens.DOUBLE_QUOTE);
+                    write(part);
+                    write(ASEmitterTokens.DOUBLE_QUOTE);
+                    if(useMxmlReflectObjectProperty)
+                    {
+                        write(ASEmitterTokens.COMMA);
+                        write(ASEmitterTokens.SPACE);
+                        write(objString.toString());
+                        write(ASEmitterTokens.PAREN_CLOSE);
+                        objString.append(".");
+                        objString.append(part);
+                    }
                 }
-                write(ASEmitterTokens.SQUARE_CLOSE.getToken());
+                write(ASEmitterTokens.SQUARE_CLOSE);
             }
             else
             {
-                write(ASEmitterTokens.DOUBLE_QUOTE.getToken() + s +
-                        ASEmitterTokens.DOUBLE_QUOTE.getToken());
+                if(useMxmlReflectObjectProperty)
+                {
+                    write(JSGoogEmitterTokens.GOOG_REFLECT_OBJECTPROPERTY);
+                    write(ASEmitterTokens.PAREN_OPEN);
+                }
+                write(ASEmitterTokens.DOUBLE_QUOTE);
+                write(s);
+                write(ASEmitterTokens.DOUBLE_QUOTE);
+                if(useMxmlReflectObjectProperty)
+                {
+                    write(ASEmitterTokens.COMMA);
+                    write(ASEmitterTokens.SPACE);
+                    write(ASEmitterTokens.THIS);
+                    write(ASEmitterTokens.PAREN_CLOSE);
+                }
+                writeNewline(ASEmitterTokens.COMMA);
             }
             
         }
@@ -1670,7 +1789,8 @@
             if (hadOutput) writeNewline();
         }
 
-        writeNewline( ASEmitterTokens.SQUARE_CLOSE.getToken() + ASEmitterTokens.SEMICOLON.getToken());
+        write(ASEmitterTokens.SQUARE_CLOSE);
+        writeNewline(ASEmitterTokens.SEMICOLON);
     }
 
     private String generateSetterFunction(BindingInfo bi, IExpressionNode destNode) {
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/goog/JSGoogConfiguration.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/goog/JSGoogConfiguration.java
index 892cced..1f54cbc 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/goog/JSGoogConfiguration.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/goog/JSGoogConfiguration.java
@@ -883,6 +883,25 @@
     	allowDynamicBindings = value;
     }
 
+    //
+    // 'mxml-reflect-object-property'
+    //
+
+    private boolean mxmlReflectObjectProperty = false;
+
+    public boolean getMxmlReflectObjectProperty()
+    {
+        return mxmlReflectObjectProperty;
+    }
+
+    @Config
+    @Mapping("mxml-reflect-object-property")
+    public void setMxmlReflectObjectProperty(ConfigurationValue cv, boolean value)
+            throws ConfigurationException
+    {
+    	mxmlReflectObjectProperty = value;
+    }
+
     
     //
     // 'warn-public-vars'