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 1c92c95f79af8d102aa5bcb2e5e8b3dd6b0c4c97
Author: Josh Tynjala <[email protected]>
AuthorDate: Thu Mar 13 14:54:56 2025 -0700

    MXMLRoyaleEmitter: make <fx:String> generated JS more consistent with 
string properties
    
    Chars such as \t and \n should be escaped with an extra \, but unicode 
escapes should be allowed.
    
    Confirmed that the Flex SDK compiler has this consistency
---
 .../codegen/mxml/royale/MXMLRoyaleEmitter.java     |  14 +-
 .../codegen/mxml/royale/TestRoyaleMXMLString.java  | 783 +++++++++++++++++++++
 .../royale/compiler/internal/test/TestBase.java    |   6 +
 3 files changed, 802 insertions(+), 1 deletion(-)

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 c593c1031..59057960a 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
@@ -3888,7 +3888,19 @@ public class MXMLRoyaleEmitter extends MXMLEmitter 
implements
        if (value instanceof String)
        {
                String s = (String)value;
-               s = StringEscapeUtils.escapeJavaScript(s);
+
+            // most 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.
+            // Unicode escape sequences are allowed, though.
+            s = s.replaceAll("\\\\(?!u)", Matcher.quoteReplacement("\\\\"));
+
+            // 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());
+
                return "'" + s + "'";
        }
        return "";
diff --git 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLString.java
 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLString.java
new file mode 100644
index 000000000..58146c599
--- /dev/null
+++ 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/mxml/royale/TestRoyaleMXMLString.java
@@ -0,0 +1,783 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.royale.compiler.internal.codegen.mxml.royale;
+
+import org.apache.royale.compiler.internal.test.RoyaleTestBase;
+import org.apache.royale.compiler.tree.mxml.IMXMLDeclarationsNode;
+import org.apache.royale.compiler.tree.mxml.IMXMLDocumentNode;
+import org.junit.Test;
+
+public class TestRoyaleMXMLString extends RoyaleTestBase
+{
+    @Test
+    public void testStringTag()
+    {
+        String code = "<fx:Declarations>\n"
+                               + "\t<fx:String id=\"string\"> abc 123 
</fx:String>\n"
+                               + "</fx:Declarations>";
+
+        IMXMLDeclarationsNode declNode = (IMXMLDeclarationsNode) getNode(code,
+            IMXMLDeclarationsNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT);
+        IMXMLDocumentNode docNode = (IMXMLDocumentNode) 
declNode.getAncestorOfType(IMXMLDocumentNode.class);
+               mxmlBlockWalker.visitDocument(docNode);
+        
+        String appName = docNode.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" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "/**\n" +
+            " * @constructor\n" +
+            " * @extends {org.apache.royale.core.Application}\n" +
+            " */\n" +
+            "AppName = function() {\n" +
+            "  AppName.base(this, 'constructor');\n" +
+            "  \n" +
+            "  this.string = ' abc 123 ';\n" +
+            "  /**\n" +
+            "   * @private\n" +
+            "   * @type {Array}\n" +
+            "   */\n" +
+            "  this.mxmldd;\n" +
+            "  \n" +
+            "  /**\n" +
+            "   * @private\n" +
+            "   * @type {Array}\n" +
+            "   */\n" +
+            "  this.mxmldp;\n" +
+            "};\n" +
+            "goog.inherits(AppName, org.apache.royale.core.Application);\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "/**\n" +
+            " * @export\n" +
+            " * @type {string}\n" +
+            " */\n" +
+            "AppName.prototype.string;";
+               
+        assertOut(outTemplate.replaceAll("AppName", appName), false);
+    }
+
+    @Test
+    public void testStringTagWithCharsThatShouldNotBeEscaped()
+    {
+        String code = "<fx:Declarations>\n"
+                               + "\t<fx:String 
id=\"string\">\\t\\n\\r\\f\\b</fx:String>\n"
+                               + "</fx:Declarations>";
+
+        IMXMLDeclarationsNode declNode = (IMXMLDeclarationsNode) getNode(code,
+            IMXMLDeclarationsNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT);
+        IMXMLDocumentNode docNode = (IMXMLDocumentNode) 
declNode.getAncestorOfType(IMXMLDocumentNode.class);
+               mxmlBlockWalker.visitDocument(docNode);
+        
+        String appName = docNode.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" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "/**\n" +
+            " * @constructor\n" +
+            " * @extends {org.apache.royale.core.Application}\n" +
+            " */\n" +
+            "AppName = function() {\n" +
+            "  AppName.base(this, 'constructor');\n" +
+            "  \n" +
+            "  this.string = '\\\\t\\\\n\\\\r\\\\f\\\\b';\n" +
+            "  /**\n" +
+            "   * @private\n" +
+            "   * @type {Array}\n" +
+            "   */\n" +
+            "  this.mxmldd;\n" +
+            "  \n" +
+            "  /**\n" +
+            "   * @private\n" +
+            "   * @type {Array}\n" +
+            "   */\n" +
+            "  this.mxmldp;\n" +
+            "};\n" +
+            "goog.inherits(AppName, org.apache.royale.core.Application);\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "/**\n" +
+            " * @export\n" +
+            " * @type {string}\n" +
+            " */\n" +
+            "AppName.prototype.string;";
+               
+        assertOut(outTemplate.replaceAll("AppName", appName), false);
+    }
+
+    @Test
+    public void testStringTagWithUnicodeEscape()
+    {
+        String code = "<fx:Declarations>\n"
+                               + "\t<fx:String 
id=\"string\">\\u00B0</fx:String>\n"
+                               + "</fx:Declarations>";
+
+        IMXMLDeclarationsNode declNode = (IMXMLDeclarationsNode) getNode(code,
+            IMXMLDeclarationsNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT);
+        IMXMLDocumentNode docNode = (IMXMLDocumentNode) 
declNode.getAncestorOfType(IMXMLDocumentNode.class);
+               mxmlBlockWalker.visitDocument(docNode);
+        
+        String appName = docNode.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" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "/**\n" +
+            " * @constructor\n" +
+            " * @extends {org.apache.royale.core.Application}\n" +
+            " */\n" +
+            "AppName = function() {\n" +
+            "  AppName.base(this, 'constructor');\n" +
+            "  \n" +
+            "  this.string = '\\u00B0';\n" +
+            "  /**\n" +
+            "   * @private\n" +
+            "   * @type {Array}\n" +
+            "   */\n" +
+            "  this.mxmldd;\n" +
+            "  \n" +
+            "  /**\n" +
+            "   * @private\n" +
+            "   * @type {Array}\n" +
+            "   */\n" +
+            "  this.mxmldp;\n" +
+            "};\n" +
+            "goog.inherits(AppName, org.apache.royale.core.Application);\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "/**\n" +
+            " * @export\n" +
+            " * @type {string}\n" +
+            " */\n" +
+            "AppName.prototype.string;";
+               
+        assertOut(outTemplate.replaceAll("AppName", appName), false);
+    }
+
+    @Test
+    public void testStringPropertyAttribute()
+    {
+        String code = "<fx:Declarations>\n"
+                               + "\t<basic:Label text=\" abc 123 \"/>\n"
+                               + "</fx:Declarations>";
+
+        IMXMLDeclarationsNode declNode = (IMXMLDeclarationsNode) getNode(code,
+            IMXMLDeclarationsNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT);
+        IMXMLDocumentNode docNode = (IMXMLDocumentNode) 
declNode.getAncestorOfType(IMXMLDocumentNode.class);
+               mxmlBlockWalker.visitDocument(docNode);
+        
+        String appName = docNode.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.Label');\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.Label}\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" +
+            "goog.inherits(AppName, org.apache.royale.core.Application);\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "Object.defineProperties(AppName.prototype, /** @lends 
{AppName.prototype} */ {\n" +
+            "  'MXMLDescriptor': {\n" +
+            "    /** @this {AppName} */\n" +
+            "    get: function() {\n" +
+            "      if (this.mxmldd == undefined)\n" +
+            "      {\n" +
+            "        /** @type {Array} */\n" +
+            "        var arr = 
AppName.superClass_.get__MXMLDescriptor.apply(this);\n" +
+            "        /** @type {Array} */\n" +
+            "        var mxmldd = [\n" +
+            "          org.apache.royale.html.Label,\n" +
+            "          2,\n" +
+            "          '_id',\n" +
+            "          true,\n" +
+            "          '$ID_8_0',\n" +
+            "          'text',\n" +
+            "          true,\n" +
+            "          ' abc 123 ',\n" +
+            "          0,\n" +
+            "          0,\n" +
+            "          null\n" +
+            "        ];\n" +
+            "        if (arr)\n" +
+            "          this.mxmldd = arr.concat(mxmldd);\n" +
+            "        else\n" +
+            "          this.mxmldd = mxmldd;\n" +
+            "      }\n" +
+            "      return this.mxmldd;\n" +
+            "    }\n" +
+            "  }\n" +
+            "});";
+               
+        assertOut(outTemplate.replaceAll("AppName", appName), false);
+    }
+
+    @Test
+    public void testStringPropertyAttributeWithCharsThatShouldNotBeEscaped()
+    {
+        String code = "<fx:Declarations>\n"
+                               + "\t<basic:Label text=\"\\t\\n\\r\\f\\b\"/>\n"
+                               + "</fx:Declarations>";
+
+        IMXMLDeclarationsNode declNode = (IMXMLDeclarationsNode) getNode(code,
+            IMXMLDeclarationsNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT);
+        IMXMLDocumentNode docNode = (IMXMLDocumentNode) 
declNode.getAncestorOfType(IMXMLDocumentNode.class);
+               mxmlBlockWalker.visitDocument(docNode);
+        
+        String appName = docNode.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.Label');\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.Label}\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" +
+            "goog.inherits(AppName, org.apache.royale.core.Application);\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "Object.defineProperties(AppName.prototype, /** @lends 
{AppName.prototype} */ {\n" +
+            "  'MXMLDescriptor': {\n" +
+            "    /** @this {AppName} */\n" +
+            "    get: function() {\n" +
+            "      if (this.mxmldd == undefined)\n" +
+            "      {\n" +
+            "        /** @type {Array} */\n" +
+            "        var arr = 
AppName.superClass_.get__MXMLDescriptor.apply(this);\n" +
+            "        /** @type {Array} */\n" +
+            "        var mxmldd = [\n" +
+            "          org.apache.royale.html.Label,\n" +
+            "          2,\n" +
+            "          '_id',\n" +
+            "          true,\n" +
+            "          '$ID_8_0',\n" +
+            "          'text',\n" +
+            "          true,\n" +
+            "          '\\\\t\\\\n\\\\r\\\\f\\\\b',\n" +
+            "          0,\n" +
+            "          0,\n" +
+            "          null\n" +
+            "        ];\n" +
+            "        if (arr)\n" +
+            "          this.mxmldd = arr.concat(mxmldd);\n" +
+            "        else\n" +
+            "          this.mxmldd = mxmldd;\n" +
+            "      }\n" +
+            "      return this.mxmldd;\n" +
+            "    }\n" +
+            "  }\n" +
+            "});";
+               
+        assertOut(outTemplate.replaceAll("AppName", appName), false);
+    }
+
+    @Test
+    public void testStringPropertyAttributeWithUnicodeEscape()
+    {
+        String code = "<fx:Declarations>\n"
+                               + "\t<basic:Label text=\"\\u00B0\"/>\n"
+                               + "</fx:Declarations>";
+
+        IMXMLDeclarationsNode declNode = (IMXMLDeclarationsNode) getNode(code,
+            IMXMLDeclarationsNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT);
+        IMXMLDocumentNode docNode = (IMXMLDocumentNode) 
declNode.getAncestorOfType(IMXMLDocumentNode.class);
+               mxmlBlockWalker.visitDocument(docNode);
+        
+        String appName = docNode.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.Label');\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.Label}\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" +
+            "goog.inherits(AppName, org.apache.royale.core.Application);\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "Object.defineProperties(AppName.prototype, /** @lends 
{AppName.prototype} */ {\n" +
+            "  'MXMLDescriptor': {\n" +
+            "    /** @this {AppName} */\n" +
+            "    get: function() {\n" +
+            "      if (this.mxmldd == undefined)\n" +
+            "      {\n" +
+            "        /** @type {Array} */\n" +
+            "        var arr = 
AppName.superClass_.get__MXMLDescriptor.apply(this);\n" +
+            "        /** @type {Array} */\n" +
+            "        var mxmldd = [\n" +
+            "          org.apache.royale.html.Label,\n" +
+            "          2,\n" +
+            "          '_id',\n" +
+            "          true,\n" +
+            "          '$ID_8_0',\n" +
+            "          'text',\n" +
+            "          true,\n" +
+            "          '\\u00B0',\n" +
+            "          0,\n" +
+            "          0,\n" +
+            "          null\n" +
+            "        ];\n" +
+            "        if (arr)\n" +
+            "          this.mxmldd = arr.concat(mxmldd);\n" +
+            "        else\n" +
+            "          this.mxmldd = mxmldd;\n" +
+            "      }\n" +
+            "      return this.mxmldd;\n" +
+            "    }\n" +
+            "  }\n" +
+            "});";
+               
+        assertOut(outTemplate.replaceAll("AppName", appName), false);
+    }
+
+    @Test
+    public void testStringPropertyChildTag()
+    {
+        String code = "<fx:Declarations>\n"
+                               + "\t<basic:Label>\n"
+                + "\t\t<basic:text> abc 123 </basic:text>\n"
+                + "\t</basic:Label>"
+                               + "</fx:Declarations>";
+
+        IMXMLDeclarationsNode declNode = (IMXMLDeclarationsNode) getNode(code,
+            IMXMLDeclarationsNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT);
+        IMXMLDocumentNode docNode = (IMXMLDocumentNode) 
declNode.getAncestorOfType(IMXMLDocumentNode.class);
+               mxmlBlockWalker.visitDocument(docNode);
+        
+        String appName = docNode.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.Label');\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.Label}\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" +
+            "goog.inherits(AppName, org.apache.royale.core.Application);\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "Object.defineProperties(AppName.prototype, /** @lends 
{AppName.prototype} */ {\n" +
+            "  'MXMLDescriptor': {\n" +
+            "    /** @this {AppName} */\n" +
+            "    get: function() {\n" +
+            "      if (this.mxmldd == undefined)\n" +
+            "      {\n" +
+            "        /** @type {Array} */\n" +
+            "        var arr = 
AppName.superClass_.get__MXMLDescriptor.apply(this);\n" +
+            "        /** @type {Array} */\n" +
+            "        var mxmldd = [\n" +
+            "          org.apache.royale.html.Label,\n" +
+            "          2,\n" +
+            "          '_id',\n" +
+            "          true,\n" +
+            "          '$ID_8_0',\n" +
+            "          'text',\n" +
+            "          true,\n" +
+            "          ' abc 123 ',\n" +
+            "          0,\n" +
+            "          0,\n" +
+            "          null\n" +
+            "        ];\n" +
+            "        if (arr)\n" +
+            "          this.mxmldd = arr.concat(mxmldd);\n" +
+            "        else\n" +
+            "          this.mxmldd = mxmldd;\n" +
+            "      }\n" +
+            "      return this.mxmldd;\n" +
+            "    }\n" +
+            "  }\n" +
+            "});";
+               
+        assertOut(outTemplate.replaceAll("AppName", appName), false);
+    }
+
+    @Test
+    public void testStringPropertyChildTagWithCharsThatShouldNotBeEscaped()
+    {
+        String code = "<fx:Declarations>\n"
+                               + "\t<basic:Label>\n"
+                + "\t\t<basic:text>\\t\\n\\r\\f\\b</basic:text>\n"
+                + "\t</basic:Label>"
+                               + "</fx:Declarations>";
+
+        IMXMLDeclarationsNode declNode = (IMXMLDeclarationsNode) getNode(code,
+            IMXMLDeclarationsNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT);
+        IMXMLDocumentNode docNode = (IMXMLDocumentNode) 
declNode.getAncestorOfType(IMXMLDocumentNode.class);
+               mxmlBlockWalker.visitDocument(docNode);
+        
+        String appName = docNode.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.Label');\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.Label}\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" +
+            "goog.inherits(AppName, org.apache.royale.core.Application);\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "Object.defineProperties(AppName.prototype, /** @lends 
{AppName.prototype} */ {\n" +
+            "  'MXMLDescriptor': {\n" +
+            "    /** @this {AppName} */\n" +
+            "    get: function() {\n" +
+            "      if (this.mxmldd == undefined)\n" +
+            "      {\n" +
+            "        /** @type {Array} */\n" +
+            "        var arr = 
AppName.superClass_.get__MXMLDescriptor.apply(this);\n" +
+            "        /** @type {Array} */\n" +
+            "        var mxmldd = [\n" +
+            "          org.apache.royale.html.Label,\n" +
+            "          2,\n" +
+            "          '_id',\n" +
+            "          true,\n" +
+            "          '$ID_8_0',\n" +
+            "          'text',\n" +
+            "          true,\n" +
+            "          '\\\\t\\\\n\\\\r\\\\f\\\\b',\n" +
+            "          0,\n" +
+            "          0,\n" +
+            "          null\n" +
+            "        ];\n" +
+            "        if (arr)\n" +
+            "          this.mxmldd = arr.concat(mxmldd);\n" +
+            "        else\n" +
+            "          this.mxmldd = mxmldd;\n" +
+            "      }\n" +
+            "      return this.mxmldd;\n" +
+            "    }\n" +
+            "  }\n" +
+            "});";
+               
+        assertOut(outTemplate.replaceAll("AppName", appName), false);
+    }
+
+    @Test
+    public void testStringPropertyChildTagWithUnicodeEscape()
+    {
+        String code = "<fx:Declarations>\n"
+                               + "\t<basic:Label>\n"
+                + "\t\t<basic:text>\\u00B0</basic:text>\n"
+                               + "\t</basic:Label>\n"
+                               + "</fx:Declarations>";
+
+        IMXMLDeclarationsNode declNode = (IMXMLDeclarationsNode) getNode(code,
+            IMXMLDeclarationsNode.class, RoyaleTestBase.WRAP_LEVEL_DOCUMENT);
+        IMXMLDocumentNode docNode = (IMXMLDocumentNode) 
declNode.getAncestorOfType(IMXMLDocumentNode.class);
+               mxmlBlockWalker.visitDocument(docNode);
+        
+        String appName = docNode.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.Label');\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.Label}\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" +
+            "goog.inherits(AppName, org.apache.royale.core.Application);\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "\n" +
+            "Object.defineProperties(AppName.prototype, /** @lends 
{AppName.prototype} */ {\n" +
+            "  'MXMLDescriptor': {\n" +
+            "    /** @this {AppName} */\n" +
+            "    get: function() {\n" +
+            "      if (this.mxmldd == undefined)\n" +
+            "      {\n" +
+            "        /** @type {Array} */\n" +
+            "        var arr = 
AppName.superClass_.get__MXMLDescriptor.apply(this);\n" +
+            "        /** @type {Array} */\n" +
+            "        var mxmldd = [\n" +
+            "          org.apache.royale.html.Label,\n" +
+            "          2,\n" +
+            "          '_id',\n" +
+            "          true,\n" +
+            "          '$ID_8_0',\n" +
+            "          'text',\n" +
+            "          true,\n" +
+            "          '\\u00B0',\n" +
+            "          0,\n" +
+            "          0,\n" +
+            "          null\n" +
+            "        ];\n" +
+            "        if (arr)\n" +
+            "          this.mxmldd = arr.concat(mxmldd);\n" +
+            "        else\n" +
+            "          this.mxmldd = mxmldd;\n" +
+            "      }\n" +
+            "      return this.mxmldd;\n" +
+            "    }\n" +
+            "  }\n" +
+            "});";
+               
+        assertOut(outTemplate.replaceAll("AppName", appName), false);
+    }
+}
diff --git 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/test/TestBase.java
 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/test/TestBase.java
index 91bd3009a..22d3b45ef 100644
--- 
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/test/TestBase.java
+++ 
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/test/TestBase.java
@@ -283,6 +283,12 @@ public class TestBase implements ITestBase
        int c = code.indexOf("\n\n\n/**\n * Metadata");
        if (c != -1)
                return code.substring(0, c);
+        c = code.indexOf("\n\n/**\n * Metadata");
+        if (c != -1)
+            return code.substring(0, c);
+        c = code.indexOf("\n/**\n * Metadata");
+        if (c != -1)
+            return code.substring(0, c);
        return code;
     }
 

Reply via email to