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 
 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; }
