This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit 5dde356731d622fecf61720c3b9d321b5bac743f
Author: Josh Tynjala <[email protected]>
AuthorDate: Tue Dec 12 16:00:34 2023 -0800

    MXMLRoyaleEmitter: When writing MXML properties to JS, escape all backslash 
characters
    
    For instance, \n is not a new line in MXML strings. It becomes \\n instead. 
To insert a real \n new line that won't be modified, use &#xA; in MXML instead. 
This is how the Flex SDK compiler behaves, so the Royale compiler now more 
closely matches Flex.
    
    Also cleaned up handling of carriage return and tab characters to match the 
Flex SDK compiler.
---
 .../royale/JSRoyaleBasicMXMLDescriptorEmitter.java |    8 +-
 .../codegen/mxml/royale/MXMLRoyaleEmitter.java     |   12 +-
 .../mxml/royale/TestRoyaleMXMLApplication.java     | 1243 ++++++++++++++++++++
 .../tree/mxml/MXMLPropertySpecifierNode.java       |   11 +-
 .../internal/tree/mxml/MXMLTreeBuilder.java        |  130 +-
 5 files changed, 1345 insertions(+), 59 deletions(-)

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 934569b89..71698baac 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
@@ -19,6 +19,8 @@
 
 package org.apache.royale.compiler.internal.codegen.js.royale;
 
+import java.util.regex.Matcher;
+
 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;
@@ -244,12 +246,6 @@ public class JSRoyaleBasicMXMLDescriptorEmitter extends 
MXMLSubEmitter implement
             {
                 write(ASEmitterTokens.TRUE);
                 writeDelimiter(writeNewline);
-                // need to do other escaping here?
-                // restrict="0-9.\"
-                if (specifier.value.endsWith("\\'") && 
!specifier.value.endsWith("\\\\'"))
-                {
-                       specifier.value = specifier.value.substring(0, 
specifier.value.length() - 1) + "\\'";
-                }
                 write(specifier.value);
             }
             else
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 a64f70bfb..2456933d7 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
@@ -3302,11 +3302,19 @@ public class MXMLRoyaleEmitter extends MXMLEmitter 
implements
         String s = node.getValue().toString();
         if (ps.valueNeedsQuotes)
         {
-            // escape all single quotes found within the string
+            // all backslashes in the value need to be be escaped
+            // for example: we don't want "\" + "n" to be treated as a new 
line,
+            // so it should become "\" + "\" + "n" instead. to insert a new 
line
+            // in MXML, use &#xA; instead.
+            s = s.replace("\\", "\\\\");
+
+            // the string will be wrapped with single quotes, so escape all
+            // existing single quotes found within the string
             s = s.replace(ASEmitterTokens.SINGLE_QUOTE.getToken(),
                     "\\" + ASEmitterTokens.SINGLE_QUOTE.getToken());
         }
-        s = s.replace("\r\n", "\\n");
+        s = s.replace("\t", "\\t");
+        s = s.replace("\r", "\\r");
         s = s.replace("\n", "\\n");
         ps.value += s;
 
diff --git 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLApplication.java
 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLApplication.java
index 03b339375..13442c7be 100644
--- 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLApplication.java
+++ 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLApplication.java
@@ -348,6 +348,1249 @@ public class TestRoyaleMXMLApplication extends 
RoyaleTestBase
         assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
     }
 
+    @Test
+    public void testBackslashTStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"\\t\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '\\\\t',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testBackslashNStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"\\n\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '\\\\n',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testBackslashRStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"\\r\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '\\\\r',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testQuoteEntityStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"&quot;\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '\"',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testApostropheEntityStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"&apos;\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '\\'',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testLessThanEntityStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"&lt;\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '<',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testGreaterThanEntityStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"&gt;\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '>',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testAmpersandEntityStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"&amp;\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '&',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testNewLineEntityStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"&#xA;\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '\\n',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testCarriageReturnEntityStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"&#13;\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '\\r',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
+    @Test
+    public void testTabEntityStringAttribute()
+    {
+        String code = "<basic:Application 
xmlns:fx=\"http://ns.adobe.com/mxml/2009\"; 
xmlns:basic=\"library://ns.apache.org/royale/basic\">"
+                + "<basic:beads><basic:TextPromptBead 
prompt=\"&#09;\"/></basic:beads></basic:Application>";
+
+        IMXMLDocumentNode dnode = (IMXMLDocumentNode) getNode(code,
+                       IMXMLDocumentNode.class, 
RoyaleTestBase.WRAP_LEVEL_NONE);
+
+        
((JSRoyaleEmitter)(mxmlBlockWalker.getASEmitter())).getModel().setCurrentClass(dnode.getDefinition());
+        mxmlBlockWalker.visitDocument(dnode);
+        String appName = dnode.getQualifiedName();
+        String outTemplate = "/**\n" +
+                       " * AppName\n" +
+                       " *\n" +
+                       " * @fileoverview\n" +
+                       " *\n" +
+                       " * @suppress {checkTypes|accessControls}\n" +
+                       " */\n" +
+                       "\n" +
+                       "goog.provide('AppName');\n" +
+                       "\n" +
+                       "goog.require('org.apache.royale.core.Application');\n" 
+
+                       
"goog.require('org.apache.royale.html.accessories.TextPromptBead');\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * @constructor\n" +
+                       " * @extends {org.apache.royale.core.Application}\n" +
+                       " */\n" +
+                       "AppName = function() {\n" +
+                       "  AppName.base(this, 'constructor');\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type 
{org.apache.royale.html.accessories.TextPromptBead}\n" +
+                       "   */\n" +
+                       "  this.$ID_8_0;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldd;\n" +
+                       "  \n" +
+                       "  /**\n" +
+                       "   * @private\n" +
+                       "   * @type {Array}\n" +
+                       "   */\n" +
+                       "  this.mxmldp;\n" +
+                       "\n" +
+                       "  this.generateMXMLAttributes([\n" +
+                       "    1,\n" +
+                       "    'beads',\n" +
+                       "    null,\n" +
+                       "    [\n" +
+                       "      
org.apache.royale.html.accessories.TextPromptBead,\n" +
+                       "      2,\n" +
+                       "      '_id',\n" +
+                       "      true,\n" +
+                       "      '$ID_8_0',\n" +
+                       "      'prompt',\n" +
+                       "      true,\n" +
+                       "      '\\t',\n" +
+                       "      0,\n" +
+                       "      0,\n" +
+                       "      null\n" +
+                       "    ],\n" +
+                       "    0,\n" +
+                       "    0\n" +
+                       "  ]);\n" +
+                       "  \n" +
+                       "};\n" +
+                       "goog.inherits(AppName, 
org.apache.royale.core.Application);\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                               "\n" +
+                       "/**\n" +
+                       " * Metadata\n" +
+                       " *\n" +
+                       " * @type {Object.<string, Array.<Object>>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_CLASS_INFO = { names: [{ 
name: 'AppName', qName: 'AppName', kind: 'class'  }] };\n" +
+                       "\n" +
+                       "\n" +
+                       "\n" +
+                       "/**\n" +
+                       " * Reflection\n" +
+                       " *\n" +
+                       " * @return {Object.<string, Function>}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_REFLECTION_INFO = function () 
{\n" +
+                       "  return {\n" +
+                       "    methods: function () {\n" +
+                       "      return {\n" +
+                               "        'AppName': { type: '', declaredBy: 
'AppName'}\n"+
+                       "      };\n" +
+                       "    }\n" +
+                       "  };\n" +
+                       "};\n" +
+                       "/**\n" +
+                       " * @const\n" +
+                       " * @type {number}\n" +
+                       " */\n" +
+                       "AppName.prototype.ROYALE_COMPILE_FLAGS = 9;\n" +
+                       "\n" +
+                       "\n";
+
+        assertOutWithMetadata(outTemplate.replaceAll("AppName", appName));
+    }
+
     @Test
     public void testInterfaceAttribute()
     {
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLPropertySpecifierNode.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLPropertySpecifierNode.java
index 64867178c..b6a096b11 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLPropertySpecifierNode.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLPropertySpecifierNode.java
@@ -221,7 +221,7 @@ class MXMLPropertySpecifierNode extends 
MXMLSpecifierNodeBase implements IMXMLPr
         info.addSourceFragments(attribute.getSourcePath(), fragments);
 
         // parse out text and make correct kind of child node
-        processFragments(builder, attribute, info);
+        processFragments(builder, attribute, info, true);
 
         info.clearFragments();
 
@@ -230,7 +230,8 @@ class MXMLPropertySpecifierNode extends 
MXMLSpecifierNodeBase implements IMXMLPr
 
     private void processFragments(MXMLTreeBuilder builder,
                                   ISourceLocation sourceLocation,
-                                  MXMLNodeInfo info)
+                                  MXMLNodeInfo info,
+                                  boolean isAttribute)
     {
         ITypeDefinition propertyType = getPropertyType(builder);
 
@@ -256,7 +257,7 @@ class MXMLPropertySpecifierNode extends 
MXMLSpecifierNodeBase implements IMXMLPr
         }
 
         instanceNode = builder.createInstanceNode(
-                this, propertyType, fragments, location, flags, classNode);
+                this, propertyType, fragments, location, flags, classNode, 
isAttribute);
 
         // If we don't have a value, we can't do codegen.
         if (instanceNode == null)
@@ -350,7 +351,7 @@ class MXMLPropertySpecifierNode extends 
MXMLSpecifierNodeBase implements IMXMLPr
         // use helpers to set offsets on fragments and create child node of 
correct type
         accumulateTextFragments(builder, text, info);
 
-        processFragments(builder, text, info);
+        processFragments(builder, text, info, false);
     }
 
     void initializeDefaultProperty(MXMLTreeBuilder builder, 
IVariableDefinition defaultPropertyDefinition,
@@ -623,7 +624,7 @@ class MXMLPropertySpecifierNode extends 
MXMLSpecifierNodeBase implements IMXMLPr
         if (instanceNode == null)
         {
             // use helpers for parse for bindings, @functions, create correct 
child node
-            processFragments(builder, tag, info);
+            processFragments(builder, tag, info, false);
         }
 
         validateProperty(builder, tag);
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLTreeBuilder.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLTreeBuilder.java
index 2672b8b8e..6916a3716 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLTreeBuilder.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLTreeBuilder.java
@@ -350,7 +350,8 @@ public class MXMLTreeBuilder
      * <code>null</code>.
      */
     private Object parseValue(IMXMLNode propertyNode, ITypeDefinition type,
-                              String text, EnumSet<TextParsingFlags> flags)
+                              String text, EnumSet<TextParsingFlags> flags,
+                              Object defaultValue, boolean isAttribute)
     {
         Object result = null;
 
@@ -359,51 +360,67 @@ public class MXMLTreeBuilder
             typeName = type.getQualifiedName();
         }
 
-        if (typeName.equals(IASLanguageConstants.Boolean))
-        {
-            result = mxmlDialect.parseBoolean(project, text, flags);
-        }
-        else if (typeName.equals(IASLanguageConstants._int))
-        {
-            result = mxmlDialect.parseInt(project, text, flags);
-            if (result == null)
-                result = parsePercent(project, propertyNode, text, flags);
-        }
-        else if (typeName.equals(IASLanguageConstants.uint))
-        {
-            result = mxmlDialect.parseUint(project, text, flags);
-            if (result == null)
-                result = parsePercent(project, propertyNode, text, flags);
-        }
-        else if (typeName.equals(IASLanguageConstants.Number))
-
-        {
-            result = mxmlDialect.parseNumber(project, text, flags);
-            if (result == null)
-                result = parsePercent(project, propertyNode, text, flags);
-        }
-        else if (typeName.equals(IASLanguageConstants.String))
+        if (typeName.equals(IASLanguageConstants.String))
         {
+            // for other types below, we always return the default value if the
+            // text is entirely whitespace, but we preserve the whitespace for
+            // strings specified with attributes
+            if (!isAttribute && mxmlDialect.isWhitespace(text))
+            {
+                return defaultValue;
+            }
             result = mxmlDialect.parseString(project, text, flags);
         }
-        else if (typeName.equals(IASLanguageConstants.Array))
+        else
         {
-            result = mxmlDialect.parseArray(project, text, flags);
-            if (result == null && 
flags.contains(TextParsingFlags.RICH_TEXT_CONTENT))
+            // if a non-string value is only whitespace, return the default 
value
+            if (mxmlDialect.isWhitespace(text))
             {
-                result = mxmlDialect.parseString(project, text, flags);
-                if (result != null)
+                return defaultValue;
+            }
+
+            if (typeName.equals(IASLanguageConstants.Boolean))
+            {
+                result = mxmlDialect.parseBoolean(project, text, flags);
+            }
+            else if (typeName.equals(IASLanguageConstants._int))
+            {
+                result = mxmlDialect.parseInt(project, text, flags);
+                if (result == null)
+                    result = parsePercent(project, propertyNode, text, flags);
+            }
+            else if (typeName.equals(IASLanguageConstants.uint))
+            {
+                result = mxmlDialect.parseUint(project, text, flags);
+                if (result == null)
+                    result = parsePercent(project, propertyNode, text, flags);
+            }
+            else if (typeName.equals(IASLanguageConstants.Number))
+
+            {
+                result = mxmlDialect.parseNumber(project, text, flags);
+                if (result == null)
+                    result = parsePercent(project, propertyNode, text, flags);
+            }
+            else if (typeName.equals(IASLanguageConstants.Array))
+            {
+                result = mxmlDialect.parseArray(project, text, flags);
+                if (result == null && 
flags.contains(TextParsingFlags.RICH_TEXT_CONTENT))
                 {
-                       ArrayList<Object> arr = new ArrayList<Object>();
-                       arr.add(result);
-                       result = arr;
+                    result = mxmlDialect.parseString(project, text, flags);
+                    if (result != null)
+                    {
+                        ArrayList<Object> arr = new ArrayList<Object>();
+                        arr.add(result);
+                        result = arr;
+                    }
                 }
             }
-        }
-        else if (typeName.equals(IASLanguageConstants.Object) ||
-                 typeName.equals(IASLanguageConstants.ANY_TYPE))
-        {
-            result = mxmlDialect.parseObject(project, text, flags);
+            else if (typeName.equals(IASLanguageConstants.Object) ||
+                    typeName.equals(IASLanguageConstants.ANY_TYPE))
+            {
+                result = mxmlDialect.parseObject(project, text, flags);
+            }
         }
 
         return result;
@@ -473,7 +490,8 @@ public class MXMLTreeBuilder
                                               ISourceFragment[] fragments,
                                               ISourceLocation location,
                                               EnumSet<TextParsingFlags> flags,
-                                              Object defaultValue)
+                                              Object defaultValue,
+                                              boolean isAttribute)
     {
         Object value = null;
         if (type.getQualifiedName().equals(IASLanguageConstants.String)
@@ -520,9 +538,7 @@ public class MXMLTreeBuilder
                 text = SourceFragmentsReader.concatPhysicalText(fragments);
             }
 
-            value = mxmlDialect.isWhitespace(text) ?
-                        defaultValue :
-                        parseValue(propertyNode, type, text, flags);
+            value = parseValue(propertyNode, type, text, flags, defaultValue, 
isAttribute);
 
             if (value == null)
             {
@@ -600,6 +616,16 @@ public class MXMLTreeBuilder
         node.runPostProcess(postProcessSteps, classScope);
     }
 
+    public NodeBase createExpressionNode(IMXMLNode propertyNode, 
ITypeDefinition type,
+                                         ISourceFragment[] fragments,
+                                         ISourceLocation location,
+                                         EnumSet<TextParsingFlags> flags,
+                                         Object defaultValue,
+                                         MXMLClassDefinitionNode classNode)
+    {
+        return createExpressionNode(propertyNode, type, fragments, location, 
flags, defaultValue, classNode, false);
+    }
+
     /**
      * Creates a databinding node, a class directive node, or a literal node.
      */
@@ -608,7 +634,8 @@ public class MXMLTreeBuilder
                                          ISourceLocation location,
                                          EnumSet<TextParsingFlags> flags,
                                          Object defaultValue,
-                                         MXMLClassDefinitionNode classNode)
+                                         MXMLClassDefinitionNode classNode,
+                                         boolean isAttribute)
     {
         NodeBase expressionNode = null;
 
@@ -659,7 +686,7 @@ public class MXMLTreeBuilder
 
         // Look for other primitive values.
         if (expressionNode == null)
-            expressionNode = createLiteralNode(propertyNode, type, fragments, 
location, flags, defaultValue);
+            expressionNode = createLiteralNode(propertyNode, type, fragments, 
location, flags, defaultValue, isAttribute);
 
         if (expressionNode == null)
         {
@@ -671,6 +698,16 @@ public class MXMLTreeBuilder
         return expressionNode;
     }
 
+
+    public MXMLInstanceNode createInstanceNode(NodeBase parent, 
ITypeDefinition type,
+                                               ISourceFragment[] fragments,
+                                               ISourceLocation location,
+                                               EnumSet<TextParsingFlags> flags,
+                                               MXMLClassDefinitionNode 
classNode)
+    {
+        return createInstanceNode(parent, type, fragments, location, flags, 
classNode, false);
+    }
+
     /**
      * Parses the specified source fragments as a databinding, or a compiler
      * directive, or a textual value of the specified type and returns an MXML
@@ -707,7 +744,8 @@ public class MXMLTreeBuilder
                                                ISourceFragment[] fragments,
                                                ISourceLocation location,
                                                EnumSet<TextParsingFlags> flags,
-                                               MXMLClassDefinitionNode 
classNode)
+                                               MXMLClassDefinitionNode 
classNode,
+                                               boolean isAttribute)
     {
         MXMLInstanceNode instanceNode = null;
 
@@ -761,7 +799,7 @@ public class MXMLTreeBuilder
         else
         {
             NodeBase expressionNode = createExpressionNode(
-                    (IMXMLNode)parent, type, fragments, location, flags, null, 
classNode);
+                    (IMXMLNode)parent, type, fragments, location, flags, null, 
classNode, isAttribute);
 
             // If we produced a databinding node or a class directive node,
             // those are already instance nodes.

Reply via email to