diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/Test.as
new file mode 100644
index 000000000..90c1c6c55
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/Test.as
@@ -0,0 +1,245 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+import com.adobe.test.Utils;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.1.1 - Attribute Identifiers");
+x1 =
+
+
+
+
+
+
+TEST_XML(1, "value1", x1.bravo.@attr1);
+TEST_XML(2, "value2", x1.bravo.charlie.@attr1);
+
+correct = new XMLList();
+correct += new XML("value1");
+correct += new XML("value2");
+TEST(3, correct, x1..@attr1);
+
+n = new Namespace("http://someuri");
+TEST_XML(4, "value3", x1.bravo.@n::attr1);
+TEST_XML(5, "value4", x1.bravo.charlie.@n::attr1);
+
+correct = new XMLList();
+correct += new XML("value3");
+correct += new XML("value4");
+TEST(6, correct, x1..@n::attr1);
+
+q = new QName("attr1");
+q2 = new QName(q, "attr1");
+
+TEST(7.3, "attr1", q.toString());
+TEST(7.4, "attr1", q2.toString());
+
+q = new QName(n, "attr1");
+q2 = new QName(q, "attr1");
+TEST(7, correct, x1..@[q]);
+TEST(7.1, "http://someuri::attr1", q.toString());
+TEST(7.2, "http://someuri::attr1", q2.toString());
+
+correct = new XMLList();
+correct += new XML("value1");
+correct += new XML("value3");
+correct += new XML("value2");
+correct += new XML("value4");
+TEST(8, correct, x1..@*::attr1);
+
+TEST_XML(9, "value1", x1.bravo.@["attr1"]);
+TEST_XML(10, "value3", x1.bravo.@n::["attr1"]);
+TEST_XML(11, "value3", x1.bravo.@[q]);
+TEST_XML(12, "value3", x1.bravo.@[q2]);
+
+
+y =
+q3 = y.name();
+
+Assert.expectEq("q3 = y.name()", "http://someuri::attr1", q3.toString());
+Assert.expectEq("x1.bravo.@[q3]", "|"+new XML("value3")+"|", "|"+x1.bravo.@[q3]+"|");
+
+
+var xml1 = "pinkpurpleorange";
+var xml2 = "SpotMarcelVirginia";
+var xml3 = "yellow";
+var xml4 = "rainbow";
+
+try {
+ var xml5 = ;
+ var res = "no exception";
+ Assert.expectEq("Attribute with apostrophe in it", "has an apostrophe' in it", xml5.myTag.@myAttrib.toString());
+} catch (e1) {
+ var res = "exception";
+} finally {
+ // Needs to be fixed when bug 133471 is fixed
+ Assert.expectEq("Attribute with apostrophe in it", "no exception", res);
+}
+
+
+var placeHolder = "c";
+
+var ns1 = new Namespace('yo', 'http://yo-raps.tv');
+var ns2 = new Namespace('mo', 'http://maureen.name');
+
+Assert.expectEq("x1.node1[i].@attr", "1",
+ ( x1 = new XML(xml1), x1.color[0].@c.toString()));
+
+Assert.expectEq("x1.node1[i].@attr = \"new value\"", "5",
+ ( x1 = new XML(xml1), x1.color[0].@c = "5", x1.color[0].@c.toString()));
+
+Assert.expectEq("x1.node1[i].@[placeHolder]", "1",
+ ( x1 = new XML(xml1), x1.color[0].@[placeHolder].toString()));
+
+Assert.expectEq("x1.node1[i].@[placeHolder] = \"new value\"", "5",
+ ( x1 = new XML(xml1), x1.color[0].@[placeHolder] = "5", x1.color[0].@[placeHolder].toString()));
+
+Assert.expectEq("x1.node1[i].@attr", "giraffe",
+ ( x1 = new XML(xml2), x1.a[2].@a.toString()));
+
+Assert.expectEq("x1.node1[i].@attr = \"new value\"", "hippopotamus",
+ ( x1 = new XML(xml2), x1.a[2].@a = "hippopotamus", x1.a[2].@a.toString()));
+
+Assert.expectEq("x1.node1.@[attr-with-hyphen]", "got it",
+ ( x1 = new XML(xml3), x1.flower.@["attr-with-hyphen"].toString()));
+
+Assert.expectEq("x1.node1.@[attr-with-hyphen] = \"new value\"", "still got it",
+ ( x1 = new XML(xml3), x1.flower.@["attr-with-hyphen"] = "still got it", x1.flower.@["attr-with-hyphen"].toString()));
+
+Assert.expectEq("x1.namespace1::node1.@attr", "something",
+ ( x1 = new XML(xml4), x1.ns1::b.@attr.toString()));
+
+Assert.expectEq("x1.namespace1::node1.@attr = \"new value\"", "something else",
+ ( x1 = new XML(xml4), x1.ns1::b.@attr = "something else", x1.ns1::b.@attr.toString()));
+
+
+var ns = new Namespace("foo");
+var y1 = ;
+var an = 'a';
+
+Assert.expectEq("y1.@a", "10", y1.@a.toString());
+
+Assert.expectEq("y1.@[an]", "10", y1.@[an].toString());
+
+Assert.expectEq("y1.@*", "10203040", y1.@*.toString()); // Rhino bug: doesn't include qualified attributes
+
+Assert.expectEq("y1.@ns::*", 2, y1.@ns::*.length());
+
+var z = ;
+Assert.expectEq("y1.@b", "200", (z.@b = 200, z.@b.toString()));
+
+Assert.expectEq("y1.@*", "103040", (delete y1.@b, y1.@*.toString()));
+
+// Adding for bug 117159
+var element:XML = new XML();
+Assert.expectEq("Reserved keyword used as attribute name", "foo", element.@["function"].toString());
+
+var xmlObj = new XML ();
+xmlObj = XML ('');
+
+try {
+ e = xmlObj.(@nonExistentAttribute == "nonExistent");
+ result = e;
+} catch (e2) {
+ result = Utils.referenceError(e2.toString());
+}
+Assert.expectEq("Access non-existent attribute", "ReferenceError: Error #1065", result);
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/output.txt
new file mode 100644
index 000000000..199f661aa
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/output.txt
@@ -0,0 +1,38 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+6 PASSED!
+7.3 PASSED!
+7.4 PASSED!
+7 PASSED!
+7.1 PASSED!
+7.2 PASSED!
+8 PASSED!
+9 PASSED!
+10 PASSED!
+11 PASSED!
+12 PASSED!
+q3 = y.name() PASSED!
+x1.bravo.@[q3] PASSED!
+Attribute with apostrophe in it PASSED!
+Attribute with apostrophe in it PASSED!
+x1.node1[i].@attr PASSED!
+x1.node1[i].@attr = "new value" PASSED!
+x1.node1[i].@[placeHolder] PASSED!
+x1.node1[i].@[placeHolder] = "new value" PASSED!
+x1.node1[i].@attr PASSED!
+x1.node1[i].@attr = "new value" PASSED!
+x1.node1.@[attr-with-hyphen] PASSED!
+x1.node1.@[attr-with-hyphen] = "new value" PASSED!
+x1.namespace1::node1.@attr PASSED!
+x1.namespace1::node1.@attr = "new value" PASSED!
+y1.@a PASSED!
+y1.@[an] PASSED!
+y1.@* PASSED!
+y1.@ns::* PASSED!
+y1.@b PASSED!
+y1.@* PASSED!
+Reserved keyword used as attribute name PASSED!
+Access non-existent attribute PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/test.swf
new file mode 100644
index 000000000..4f0a6810f
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_1/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/Test.as
new file mode 100644
index 000000000..d947cf90b
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/Test.as
@@ -0,0 +1,247 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.1.2 - Qualified Identifiers");
+
+x1 =
+
+
+
+ DIS
+
+
+;
+
+soap = new Namespace("http://schemas.xmlsoap.org/soap/envelope/");
+stock = new Namespace("http://mycompany.com/stocks");
+
+encodingStyle = x1.@soap::encodingStyle;
+TEST_XML(1, "http://schemas.xmlsoap.org/soap/encoding/", encodingStyle);
+
+correct =
+
+
+ DIS
+
+;
+
+body = x1.soap::Body;
+TEST_XML(2, correct.toXMLString(), body);
+
+body = x1.soap::["Body"];
+TEST_XML(3, correct.toXMLString(), body);
+
+q = new QName(soap, "Body");
+body = x1[q];
+TEST_XML(4, correct.toXMLString(), body);
+
+correct =
+MYCO;
+
+x1.soap::Body.stock::getLastTradePrice.symbol = "MYCO";
+TEST_XML(5, correct.toXMLString(), x1.soap::Body.stock::getLastTradePrice.symbol);
+
+// SOAP messages
+var msg1 =
+
+
+ DIS
+
+
+
+
+var msg2 =
+
+
+ MACR
+
+
+
+
+var msg3 =
+
+
+ MACR
+
+
+
+
+var msg4 =
+
+
+ box
+ lace
+ soup
+
+
+
+
+var msg5 = "soupboxlacehttp://www.hooping.org";
+
+// declare namespaces
+var ns1 = new Namespace("http://schemas.xmlsoap.org/soap/envelope/");
+var ns2= new Namespace ("http://mycompany.com/stocks/");
+var ns3= new Namespace ("http://macromedia.com/software/central/");
+
+// extract the soap encoding style and body from the soap msg1
+var encodingStyle = msg1.@ns1::encodingStyle;
+var stockURL = msg1.ns1::Body.ns2::GetLastTradePrice.@ns2::blah;
+
+var body = msg1.ns1::Body;
+
+// change the stock symbol
+body.ns2::GetLastTradePrice.symbol = "MACR";
+
+
+Assert.expectEq("body.ns2::GetLastTradePrice.symbol = \"MACR\"", "MACR",
+ ( body.ns2::GetLastTradePrice.symbol.toString()));
+
+
+bodyQ = msg1[QName(ns1, "Body")];
+
+Assert.expectEq("ms1.ns1::Body == msg1[QName(ns1, \"Body\")]", true, (bodyQ == body));
+
+Assert.expectEq("msg1 == msg2", true,
+ ( msg1 == msg2));
+
+Assert.expectEq("msg1.@ns1::encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/",
+ ( msg1.@ns1::encodingStyle.toString()));
+
+Assert.expectEq("msg3.ns1::Body.ns2::GetLastTradePrice.@ns2", "http://www.hooping.org",
+ ( msg3.ns1::Body.ns2::GetLastTradePrice.@ns2::blah.toString()));
+
+
+// Rhino behaves differently:
+
+Assert.expectEq("msg4.bakery.ns3::g.@*", msg5,
+ ( msg4.bakery.ns3::g.@*.toString()));
+
+var x1 = 10;
+var ns = new Namespace("foo");
+
+Assert.expectEq("x1.ns::*", new XMLList("10").toString(), x1.ns::*.toString());
+
+Assert.expectEq("x1.ns::a", "10", x1.ns::a.toString())
+
+Assert.expectEq("x1.*::a", "10", x1.*::a.toString()); // issue: assert
+
+Assert.expectEq("x1.ns::a", "20", (x1.ns::a = 20, x1.ns::a.toString()));
+
+Assert.expectEq("x1.@ns::['v']", "55", x1.@ns::['v'].toString());
+
+Assert.expectEq("x1.@ns::['v']", "555", (x1.@ns::['v'] = '555', x1.@ns::['v'].toString()));
+
+var y1 =
+Assert.expectEq("y1.@ns::*.length()", 2, y1.@ns::*.length());
+
+var z = new XMLList("");
+Assert.expectEq("x1.*", z.toString(), (delete x1.ns::a, x1.*.toString()));
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/output.txt
new file mode 100644
index 000000000..0ac090325
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/output.txt
@@ -0,0 +1,19 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+body.ns2::GetLastTradePrice.symbol = "MACR" PASSED!
+ms1.ns1::Body == msg1[QName(ns1, "Body")] PASSED!
+msg1 == msg2 PASSED!
+msg1.@ns1::encodingStyle PASSED!
+msg3.ns1::Body.ns2::GetLastTradePrice.@ns2 PASSED!
+msg4.bakery.ns3::g.@* PASSED!
+x1.ns::* PASSED!
+x1.ns::a PASSED!
+x1.*::a PASSED!
+x1.ns::a PASSED!
+x1.@ns::['v'] PASSED!
+x1.@ns::['v'] PASSED!
+y1.@ns::*.length() PASSED!
+x1.* PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/test.swf
new file mode 100644
index 000000000..ddc2e756f
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_2/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/Test.as
new file mode 100644
index 000000000..86bf53903
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/Test.as
@@ -0,0 +1,137 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.1.3 - Wildcard Identifiers");
+
+var x1 =
+
+ one
+ two
+
+
+var correct = new XMLList("onetwo");
+TEST(1, correct, x1.*);
+
+XML.ignoreWhitespace = false;
+
+var xml1 = "123
";
+var xml2 = "123";
+var xml3 = "hey there23";
+var xml4 = "hello
";
+
+var ns1 = new Namespace('foobar', 'http://boo.org');
+var ns2 = new Namespace('fooboo', 'http://foo.org');
+var ns3 = new Namespace('booboo', 'http://goo.org');
+
+Assert.expectEq("x.a.*", "123", (x1 = new XML(xml1), x1.a.*.toString()));
+
+Assert.expectEq("xmllist.a.*", "123", (x1 = new XMLList(xml1), x1.a.*.toString()));
+
+Assert.expectEq("xmllist.*", "123", (x1 = new XMLList(xml2), x1.*.toString()));
+
+Assert.expectEq("xmllist[0].*", "1", (x1 = new XMLList(xml2), x1[0].*.toString()));
+
+Assert.expectEq("xmllist[0].e.*", "hey there", (x1 = new XMLList(xml3), x1[0].e.*.toString()));
+
+Assert.expectEq("xml.a.@*", "avm", (x1 = new XML(xml4), x1.a.@*.toString()));
+
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/output.txt
new file mode 100644
index 000000000..44c38184e
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/output.txt
@@ -0,0 +1,7 @@
+1 PASSED!
+x.a.* PASSED!
+xmllist.a.* PASSED!
+xmllist.* PASSED!
+xmllist[0].* PASSED!
+xmllist[0].e.* PASSED!
+xml.a.@* PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/test.swf
new file mode 100644
index 000000000..bfb85abef
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_3/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/Test.as
new file mode 100644
index 000000000..9f9e6021a
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/Test.as
@@ -0,0 +1,295 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.1.4 - XML Initializer");
+
+XML.ignoreWhitespace = true;
+person = John25;
+TEST(1, John25, person);
+
+e =
+ Joe20
+ Sue30
+ ;
+
+TEST_XML(2, 1, e.employee[0].@id);
+
+correct = Sue;
+TEST(3, correct, e.employee[1].name);
+
+names = new Array();
+names[0] = "Alpha";
+names[1] = "Bravo";
+names[2] = "Charlie";
+names[3] = "Delta";
+names[4] = "Echo";
+names[5] = "Golf";
+names[6] = "Hotel";
+names[7] = "India";
+names[8] = "Juliet";
+names[9] = "Kilo";
+
+ages = new Array();
+ages[0] = "20";
+ages[1] = "21";
+ages[2] = "22";
+ages[3] = "23";
+ages[4] = "24";
+ages[5] = "25";
+ages[6] = "26";
+ages[7] = "27";
+ages[8] = "28";
+ages[9] = "29";
+
+for (i = 0; i < 10; i++)
+{
+ e.*[i] =
+ {names[i].toUpperCase()}
+ {ages[i]}
+ ;
+
+ correct = new XML("" + names[i].toUpperCase() + "" + ages[i] + "");
+ TEST(4 + i, correct, e.*[i]);
+}
+
+tagName = "name";
+attributeName = "id";
+attributeValue = 5;
+content = "Fred";
+
+x1 = <{tagName} {attributeName}={attributeValue}>{content}{tagName}>;
+TEST(14, "Fred", x1.toXMLString());
+
+
+
+// Test {} on XML and XMLList types
+x1 =
+
+ 30
+ 50
+;
+
+correct =
+
+ 50
+ 30
+;
+
+x1 = {x1.width}{x1.length};
+
+TEST(15, correct, x1);
+
+var content = "bar";
+
+x1 = {content};
+correct = ;
+correct.a = content;
+TEST(16, correct, x1);
+
+x1 = ;
+correct = ;
+correct.@a = content;
+TEST(17, correct, x1);
+
+a = 5;
+b = 3;
+c = "x";
+x1 = <{c} a={a + " < " + b + " is " + (a < b)}>{a + " < " + b + " is " + (a < b)}{c}>;
+TEST(18, "5 < 3 is false", x1.toXMLString());
+
+x1 = <{c} a={a + " > " + b + " is " + (a > b)}>{a + " > " + b + " is " + (a > b)}{c}>;
+TEST(19, " 3 is true\">5 > 3 is true", x1.toXMLString());
+
+var tagname = "name";
+var attributename = "id";
+var attributevalue = 5;
+content = "Fred";
+
+var xml1 = <{tagname} {attributename}={attributevalue}>{content}{tagname}>;
+
+Assert.expectEq( "x = <{tagname} {attributename}={attributevalue}>{content}{tagname}>", true,
+ ( x1 = new XML('Fred'), (xml1 == x1)));
+
+
+
+names = ["Alfred", "Allie", "Maryann", "Jason", "Amy", "Katja", "Antonio", "Melvin", "Stefan", "Amber"];
+ages = [55, 21, 25, 23, 28, 30, 35, 26, 30, 30];
+
+var xml2;
+var xml2string = "";
+var e = new Array();
+for (i = 0; i < 10; i++) {
+ e[i] =
+ {names[i].toUpperCase()}
+ {ages[i]}
+ ;
+ xml2string += "" + names[i].toUpperCase() + "" + ages[i] + "";
+}
+xml2 = {e[0]}{e[1]}{e[2]}{e[3]}{e[4]}{e[5]}{e[6]}{e[7]}{e[8]}{e[9]};
+xml2string += "";
+
+Assert.expectEq( "Evaluating expressions in a for loop", true,
+ ( x1 = new XML(xml2string), (xml2 == x1)));
+
+
+var xml3 = John25;
+
+Assert.expectEq( "x = John25", true,
+ ( x1 = new XML(xml3.toString()), (xml3 == x1)));
+
+var xml4 = new XML("]]>");
+
+Assert.expectEq( "]]>", true,
+ ( x1 = new XML("]]>"), (xml4 == x1)));
+
+xml5 = heh hey;
+XML.ignoreWhitespace = true;
+
+Assert.expectEq( "heh hey", true,
+ ( x1 = new XML("heh hey"), (xml5 == x1)));
+
+
+Assert.expectEq( "x = new XML(\"\"), xml = \"\", (xml == x)", true,
+ ( x1 = new XML(""), xml = "", (xml == x1)));
+
+
+
+var xx = new XML(" A B ]]>");
+
+Assert.expectEq( " A B ]]>, xml.toXMLString()",
+ "" + NL() + " A B ]]>" + NL() + "",
+ xx.toXMLString());
+
+Assert.expectEq( " A B ]]>, xml.description.text()",
+ "characteristics:",
+ xx.description.text().toString());
+
+Assert.expectEq( " A B ]]>, xml.description.child(0)",
+ "characteristics:",
+ xx.description.child(0).toString());
+
+Assert.expectEq( " A B ]]>, xml.description.child(0).nodeKind()",
+ "text",
+ xx.description.child(0).nodeKind());
+
+var desc = "this is the text";
+
+x1 = {""};
+
+Assert.expectEq("desc = \"this is the text\"; x = {\"\"};",
+ "text]]>", x1.toString());
+
+
+Assert.expectEq("desc = \"this is the text\"; x = {\"\"};",
+ "<![CDATA[this is the <i>text</i>]]>", x1.toXMLString());
+
+// Testing for extra directives. See bug 94230.
+var xx =
+
+;
+
+Assert.expectEq("Testing for extra directives", "", xx.toString());
+
+xx = new XML("");
+
+Assert.expectEq("Testing for extra directives", "", xx.toString());
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/output.txt
new file mode 100644
index 000000000..8ff59d843
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/output.txt
@@ -0,0 +1,33 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+6 PASSED!
+7 PASSED!
+8 PASSED!
+9 PASSED!
+10 PASSED!
+11 PASSED!
+12 PASSED!
+13 PASSED!
+14 PASSED!
+15 PASSED!
+16 PASSED!
+17 PASSED!
+18 PASSED!
+19 PASSED!
+x = <{tagname} {attributename}={attributevalue}>{content}{tagname}> PASSED!
+Evaluating expressions in a for loop PASSED!
+x = John25 PASSED!
+]]> PASSED!
+heh hey PASSED!
+x = new XML(""), xml = "", (xml == x) PASSED!
+ A B ]]>, xml.toXMLString() PASSED!
+ A B ]]>, xml.description.text() PASSED!
+ A B ]]>, xml.description.child(0) PASSED!
+ A B ]]>, xml.description.child(0).nodeKind() PASSED!
+desc = "this is the text"; x = {""}; PASSED!
+desc = "this is the text"; x = {""}; PASSED!
+Testing for extra directives PASSED!
+Testing for extra directives PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/test.swf
new file mode 100644
index 000000000..266d6c554
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_4/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/Test.as
new file mode 100644
index 000000000..e2515b524
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/Test.as
@@ -0,0 +1,180 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.1.5 - XMLList Initializer");
+
+XML.ignoreWhitespace = true;
+
+var docfrag = <>Phil35skiing>;
+TEST(1, "xml", typeof(docfrag));
+
+var correct = Phil;
+TEST(2, correct, docfrag[0]);
+
+var emplist = <>
+ Jim25
+ Joe20
+ Sue30
+ >;
+
+TEST(3, "xml", typeof(emplist));
+TEST_XML(4, 2, emplist[2].@id);
+
+var myVar = "kitty";
+
+var xml1 = <>1>;
+var xml2 = <>a>;
+var xml3 = <>b>;
+var xml4 = <>catwalkdogrun>;
+var xml5 = <>>;
+var xml6 = <><{myVar}>hello{myVar}>>;
+var xml7 = <>"quotes"{curly brackets}>;
+var xml8 = <>5 > 4>;
+var empxml = <>
+ Jim25
+ Joe20
+ Sue30
+>;
+emplist = "Jim25Joe20Sue30";
+
+
+Assert.expectEq( "<>1> == new XMLList(\"1\")", true,
+ ( x1 = new XMLList('1'), (xml1 == x1)));
+
+Assert.expectEq( "<>a> == new XMLList('a')", true,
+ ( x1 = new XMLList('a'), (xml2 == x1)));
+
+Assert.expectEq( "<>b> == new XMLList('b')", true,
+ ( x1 = new XMLList('b'), (xml3 == x1)));
+
+Assert.expectEq( "<>[list]> == new XMLList([list])", true,
+ ( x1 = new XMLList('catwalkdogrun'), (xml4 == x1)));
+
+Assert.expectEq( "<>> == new XMLList()", true,
+ ( x1 = new XMLList(), (xml5 == x1)));
+
+Assert.expectEq( "<>> == new XMLList(\"\")", true,
+ ( x1 = new XMLList(""), (xml5 == x1)));
+
+Assert.expectEq( "<><{myVar}>hello{myVar}>> == new XMLList('hello')", true,
+ ( x1 = new XMLList("hello"), (xml6 == x1)));
+
+Assert.expectEq( "<>{ \\\"\\\" {> == new XMLList({ \"\" })", true,
+ ( x1 = new XMLList("\"quotes\"{curly brackets}"), (xml7 == x1)));
+
+Assert.expectEq( "<>5 > 4> == new XMLList('5 > 4')", true,
+ ( x1 = new XMLList("5 > 4"), (xml8 == x1)));
+
+Assert.expectEq( "Multiline XML", true,
+ ( x1 = new XMLList(emplist), (empxml == x1)));
+
+// Testing for extra directives. See bug 94230.
+var xl = <>
+
+a>;
+
+Assert.expectEq("Testing for extra directives", (<>a>).toString(), xl.toString());
+
+xl = new XMLList("a");
+
+Assert.expectEq("Testing for extra directives", (new XMLList("a")).toString(), xl.toString());
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/output.txt
new file mode 100644
index 000000000..01db1310f
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/output.txt
@@ -0,0 +1,16 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+<>1> == new XMLList("1") PASSED!
+<>a> == new XMLList('a') PASSED!
+<>b> == new XMLList('b') PASSED!
+<>[list]> == new XMLList([list]) PASSED!
+<>> == new XMLList() PASSED!
+<>> == new XMLList("") PASSED!
+<><{myVar}>hello{myVar}>> == new XMLList('hello') PASSED!
+<>{ \"\" {> == new XMLList({ "" }) PASSED!
+<>5 > 4> == new XMLList('5 > 4') PASSED!
+Multiline XML PASSED!
+Testing for extra directives PASSED!
+Testing for extra directives PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/test.swf
new file mode 100644
index 000000000..234c64e59
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/test.toml
new file mode 100644
index 000000000..cf6123969
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_1_5/test.toml
@@ -0,0 +1 @@
+num_ticks = 1
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/Test.as
new file mode 100644
index 000000000..4295405bb
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/Test.as
@@ -0,0 +1,332 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.2.1 - Property Accessors");
+
+
+function convertToString(o:Object){
+ return o.toString();
+}
+
+order =
+
+
+ John
+ Doe
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+;
+
+correct =
+
+ John
+ Doe
+;
+
+TEST(1, correct, order.customer);
+TEST_XML(2, 123456, order.@id);
+
+correct =
+-
+ Big Screen Television
+ 1299.99
+ 1
+
+
+TEST(3, correct, order.children()[1]);
+
+correct =
+
+ John
+ Doe
+ +
+-
+ Big Screen Television
+ 1299.99
+ 1
+
;
+
+
+TEST(4, correct, order.*);
+
+correct = new XMLList();
+correct += new XML("123456");
+correct += new XML("Mon Mar 10 2003 16:03:25 GMT-0800 (PST)");
+TEST(5, correct, order.@*);
+
+order =
+
+ John
+ Doe
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+ ;
+
+correct =
+Big Screen Television +
+DVD Player;
+
+TEST(6, correct, order.item.description);
+
+correct = new XMLList();
+correct += new XML("3456");
+correct += new XML("56789");
+TEST(7, correct, order.item.@id);
+
+correct =
+-
+ DVD Player
+ 399.99
+ 1
+
+
+TEST(8, correct, order.item[1]);
+
+correct =
+Big Screen Television +
+1299.99 +
+1 +
+DVD Player +
+399.99 +
+1;
+
+TEST(9, correct, order.item.*);
+
+correct=
+1299.99;
+
+TEST(10, correct, order.item.*[1]);
+
+// get the first (and only) order [treating single element as a list]
+order =
+
+ John
+ Doe
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+ ;
+
+
+TEST(11, order, order[0]);
+
+// Any other index should return undefined
+TEST(12, undefined, order[1]);
+
+var xml = "JohnDoeB1299.99
1
A12.99
1
";
+
+// XML object test cases
+
+Assert.expectEq("XML.c.f:", "John", (o = new XML(xml), o.c.f.toString()));
+
+Assert.expectEq("XML.c['f']:", "John", (o = new XML(xml), o.c['f'].toString()));
+
+Assert.expectEq("XML.c.f[0]:", "John", (o = new XML(xml), o.c.f[0].toString()));
+
+Assert.expectEq("XML.i[1].p:", "12.99", (o = new XML(xml), o.i[1].p.toString()));
+
+Assert.expectEq("XML.i[1]['p]'", "12.99", (o = new XML(xml), o.i[1]['p'].toString()));
+
+
+// High ASCII test
+var xmlHighASCII = "Sören Lehmenkühler";
+
+Assert.expectEq("High ASCII node value:", "Sören Lehmenkühler", (o = new XML(xmlHighASCII), o.fname.toString()));
+
+
+// XMLList object test cases
+
+Assert.expectEq("XMLList.c.f:", "John", (ol = new XMLList(xml), ol.c.f.toString()));
+
+Assert.expectEq("XMLList.c[\"f\"]:", "John", (ol = new XMLList(xml), ol.c["f"].toString()));
+
+Assert.expectEq("XMLList.c.f[0]:", "John", (o = new XMLList(xml), o.c.f[0].toString()));
+
+Assert.expectEq("XMLList.c.f[0] = \"Peter\":", "Peter", (o = new XMLList(xml), o.c.f[0] = "Peter", o.c.f[0].toString()));
+
+Assert.expectEq("XMLList.i[1].p:", "12.99", (ol = new XMLList(xml), ol.i[1].p.toString()));
+
+Assert.expectEq("XMLList.i[1][\"p\"]:", "12.99", (ol = new XMLList(xml), ol.i[1]["p"].toString()));
+
+Assert.expectEq("XMLList[1] = b", "b", (ol = new XMLList(), ol[1] = b, ol.toString()));
+
+Assert.expectEq("XMLList[1] = b; XMLList[0] = d", "d", (ol = new XMLList(), ol[1] = b, ol[0] = d, ol.toString()));
+
+Assert.expectEq("XMLList[0] = b; XMLList[1] = d", convertToString(new XMLList("bd")), (ol = new XMLList(), ol[0] = b, ol[1] = d, ol).toString());
+
+
+var x1 = new XML("abc");
+var y1 = x1.fname;
+
+Assert.expectEq("x1.f == x1.f[0] + x1.f[1] + x1.f[2]", convertToString(x1.fname[0] + x1.fname[1] + x1.fname[2]),
+x1.fname.toString());
+
+// comparing XML and XMLList equivalents
+
+Assert.expectEq("XML[0].fname[1] == XMLList[1]:", true, (y1 = x1.fname, (x1[0].fname[1] == y1[1])));
+
+Assert.expectEq("XML[0].fname[0] == XMLList.fname[0]:", true, (y1 = new XMLList(x1), (x1[0].fname[0] == y1.fname[0])));
+
+
+var hyphenatedXML = new XML("blueorangeyellow");
+
+Assert.expectEq("hyphenatedXML.[\"b-c\"]:", "orange", (hyphenatedXML["b-c"][1].toString()));
+
+Assert.expectEq("hyphenatedXML.[\"b-c\"][1] = \"new color\":", "pink", (hyphenatedXML["b-c"][1] = "pink", hyphenatedXML["b-c"][1].toString()));
+
+xL = y;
+
+Assert.expectEq("x['*']", "y", xL['*'].toString());
+Assert.expectEq("x['@*']", "aatrbatr", xL['@*'].toString());
+Assert.expectEq("x['@a']", "aatr", xL['@a'].toString());
+
+xL = some text;
+
+Assert.expectEq("x1.@prop", "prop3", xL.@prop.toString());
+
+function setNS1() {
+ use namespace foo;
+ Assert.expectEq("use namespace foo; x1.@prop", "prop1prop3", xL.@prop.toString());
+}
+
+function setNS2() {
+ namespace foo2 = "bar";
+ use namespace foo2;
+ Assert.expectEq("use namespace foo2; x1.@prop", "prop2prop3", xL.@prop.toString());
+}
+
+function setNS3() {
+ use namespace foo;
+ namespace foo2 = "bar";
+ use namespace foo2;
+ Assert.expectEq("use namespace foo2; x1.@prop", "prop1prop2prop3", xL.@prop.toString());
+}
+
+namespace foo = "foo";
+
+setNS1();
+
+setNS2();
+
+setNS3();
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/output.txt
new file mode 100644
index 000000000..d5b5c5c6a
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/output.txt
@@ -0,0 +1,39 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+6 PASSED!
+7 PASSED!
+8 PASSED!
+9 PASSED!
+10 PASSED!
+11 PASSED!
+12 PASSED!
+XML.c.f: PASSED!
+XML.c['f']: PASSED!
+XML.c.f[0]: PASSED!
+XML.i[1].p: PASSED!
+XML.i[1]['p]' PASSED!
+High ASCII node value: PASSED!
+XMLList.c.f: PASSED!
+XMLList.c["f"]: PASSED!
+XMLList.c.f[0]: PASSED!
+XMLList.c.f[0] = "Peter": PASSED!
+XMLList.i[1].p: PASSED!
+XMLList.i[1]["p"]: PASSED!
+XMLList[1] = b PASSED!
+XMLList[1] = b; XMLList[0] = d PASSED!
+XMLList[0] = b; XMLList[1] = d PASSED!
+x1.f == x1.f[0] + x1.f[1] + x1.f[2] PASSED!
+XML[0].fname[1] == XMLList[1]: PASSED!
+XML[0].fname[0] == XMLList.fname[0]: PASSED!
+hyphenatedXML.["b-c"]: PASSED!
+hyphenatedXML.["b-c"][1] = "new color": PASSED!
+x['*'] PASSED!
+x['@*'] PASSED!
+x['@a'] PASSED!
+x1.@prop PASSED!
+use namespace foo; x1.@prop PASSED!
+use namespace foo2; x1.@prop PASSED!
+use namespace foo2; x1.@prop PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/test.swf
new file mode 100644
index 000000000..a538efd21
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_1/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/Test.as
new file mode 100644
index 000000000..9a50d719a
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/Test.as
@@ -0,0 +1,197 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.2.2 - Function Calls");
+
+
+function convertToString(o:Object){
+ return o.toString();
+}
+
+rectangle =
+ 50
+ 75
+ 20
+ 30
+ ;
+
+
+TEST(1, 1, rectangle.length());
+
+TEST(2, 20, rectangle.length);
+
+shipto =
+ Fred Jones
+ 123 Foobar Ave.
+ Redmond, WA, 98008
+ ;
+
+
+upperName = shipto.name.toUpperCase();
+TEST(3, "FRED JONES", upperName);
+
+upperName = shipto.name.toString().toUpperCase();
+TEST(4, "FRED JONES", upperName);
+upperName = shipto.name.toUpperCase();
+TEST(5, "FRED JONES", upperName);
+
+citystatezip = shipto.citystatezip.split(", ");
+state = citystatezip[1];
+TEST(6, "WA", state);
+zip = citystatezip[2];
+TEST(7, "98008", zip);
+
+
+citystatezip = shipto.citystatezip.toString().split(", ");
+state = citystatezip[1];
+TEST(8, "WA", state);
+zip = citystatezip[2];
+TEST(9, "98008", zip);
+
+foo = hello;
+var1 = foo.apple;
+foo.apple = "moi";
+TEST(10, moi, var1);
+
+// Test method name/element name conflicts
+
+x1 =
+
+ Foo
+ Bar
+;
+
+TEST(11, QName("alpha"), x1.name());
+TEST(12, Bar, x1.length);
+TEST(13, 1, x1.length());
+TEST(14, x1, x1.(length == "Bar"));
+
+x1.name = "foobar";
+
+TEST(15, foobar, (x1.name));
+TEST(16, QName("alpha"), (x1.name()));
+
+var xml = "Bubba";
+
+Assert.expectEq("person.name:", "Bubba", (x1 = new XML(xml), x1.name.toString()));
+
+Assert.expectEq("person.name():", "person", (x1 = new XML(xml), x1.name().toString()));
+
+
+xml = "530";
+
+Assert.expectEq("i.length:", "5", (x1 = new XML(xml), x1.length.toString()));
+
+Assert.expectEq("i.length():", 1, (x1 = new XML(xml), x1.length()));
+
+
+xml = "abc";
+var p = new XMLList(xml).parent;
+
+Assert.expectEq("x.parent:", p.toString(), (x1 = new XML(xml), x1.parent).toString());
+
+Assert.expectEq("x.parent():", undefined, (x1 = new XML(xml), x1.parent()));
+
+Assert.expectEq("x.parent.parent():", x1.toString(), (x1 = new XML(xml), x1.parent.parent()).toString());
+
+
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/output.txt
new file mode 100644
index 000000000..b88fb0b68
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/output.txt
@@ -0,0 +1,23 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+6 PASSED!
+7 PASSED!
+8 PASSED!
+9 PASSED!
+10 PASSED!
+11 PASSED!
+12 PASSED!
+13 PASSED!
+14 PASSED!
+15 PASSED!
+16 PASSED!
+person.name: PASSED!
+person.name(): PASSED!
+i.length: PASSED!
+i.length(): PASSED!
+x.parent: PASSED!
+x.parent(): PASSED!
+x.parent.parent(): PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/test.swf
new file mode 100644
index 000000000..3b9e4510d
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_2/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/Test.as
new file mode 100644
index 000000000..63ced7775
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/Test.as
@@ -0,0 +1,165 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.2.3 - XML Descendant Accessor");
+
+function convertToString(o:Object){
+ return o.toString();
+}
+var e =
+
+ Joe20
+ Sue30
+
+
+names = e..name;
+
+correct =
+Joe +
+Sue;
+
+TEST(1, correct, names);
+
+e = "Joe20Sue30";
+
+Assert.expectEq("xml..validnode:", "Joe", (x1 = new XML(e), names = x1..name, names[0].toString()));
+
+Assert.expectEq("xml..validnode length:", 2, (x1 = new XML(e), names = x1..name, names.length()));
+
+Assert.expectEq("xml..invalidnode:", undefined, (x1 = new XML(e), names = x1..hood, names[0]));
+
+Assert.expectEq("xmllist..validnode:", "Joe", (x1 = new XMLList(e), names = x1..name, names[0].toString()));
+
+Assert.expectEq("xmllist..invalidnode:", undefined, (x1 = new XMLList(e), names = x1..hood, names[0]));
+
+Assert.expectEq("xmllist..invalidnode length:", 0, (x1 = new XMLList(e), names = x1..hood, names.length()));
+
+e =
+
+ Joe20
+ Sue30
+
+
+correct =
+Joe +
+Sue;
+
+names = e..first_name;
+
+TEST(2, correct, names);
+
+e =
+
+ Joe20
+ Sue30
+
+
+e =
+
+ heart
+ part
+
+
+es = <>heartheartpartpart>;
+
+Assert.expectEq(3, es.toString(), convertToString(e..bug));
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/output.txt
new file mode 100644
index 000000000..9537b6c65
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/output.txt
@@ -0,0 +1,9 @@
+1 PASSED!
+xml..validnode: PASSED!
+xml..validnode length: PASSED!
+xml..invalidnode: PASSED!
+xmllist..validnode: PASSED!
+xmllist..invalidnode: PASSED!
+xmllist..invalidnode length: PASSED!
+2 PASSED!
+3 PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/test.swf
new file mode 100644
index 000000000..bacbe8003
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_3/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/Test.as
new file mode 100644
index 000000000..7559e5ede
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/Test.as
@@ -0,0 +1,251 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.2.4 - XML Filtering Predicate Operator");
+
+function convertToString(o:Object){
+ return o.toString();
+}
+
+var p;
+
+e =
+ John20
+ Sue30
+ ;
+
+
+correct = John20;
+
+john = e.employee.(fname == "John");
+TEST(1, correct, john);
+
+john = e.employee.(fname == "John");
+TEST(2, correct, john);
+
+correct =
+John20 +
+Sue30;
+
+twoEmployees = e.employee.(@id == 0 || @id == 1);
+TEST(3, correct, twoEmployees);
+
+twoEmployees = e.employee.(@id == 0 || @id == 1);
+TEST(4, correct, twoEmployees);
+
+i = 0;
+twoEmployees = new XMLList();
+for each (p in e..employee)
+{
+ if (p.@id == 0 || p.@id == 1)
+ {
+ twoEmployees += p;
+ }
+}
+TEST(5, correct, twoEmployees);
+
+i = 0;
+twoEmployees = new XMLList();
+for each (p in e..employee)
+{
+ if (p.@id == 0 || p.@id == 1)
+ {
+ twoEmployees[i++] = p;
+ }
+}
+TEST(6, correct, twoEmployees);
+
+// test with syntax
+e =
+ John20
+ Sue30
+ ;
+
+correct =
+John20 +
+Sue30;
+
+i = 0;
+twoEmployees = new XMLList();
+for each (p in e..employee)
+{
+ with (p)
+ {
+ if (@id == 0 || @id == 1)
+ {
+ twoEmployees[i++] = p;
+ }
+ }
+}
+TEST(7, correct, twoEmployees);
+
+var xml = "Joe20SueJoe";
+var e = new XML(xml);
+
+// get employee with fname Joe
+Assert.expectEq("e.employee.(fname == \"Joe\")", 1, (joe = e.employee.(fname == "Joe"), joe.length()));
+
+
+// employees with id's 0 & 1
+Assert.expectEq("employees with id's 1 & 2", 2, (emps = e.employee.(@id == 1 || @id == 2), emps.length()));
+
+
+// name of employee with id 1
+Assert.expectEq("name of employee with id 1", "Joe", (emp = e.employee.(@id == 1).fname, emp.toString()));
+
+
+// get the two employees with ids 0 and 1 using a predicate
+var i = 0;
+var twoEmployees = new XMLList();
+for each (p in e..employee) {
+ with (p) {
+ if (@id == 1 || @id == 2) {
+ twoEmployees[i++] = p;
+ }
+ }
+}
+
+var twoEmployees = e..employee.(@id == 1 || @id == 2);
+
+Assert.expectEq("Compare to equivalent XMLList", true, (emps = e..employee.(@id == 1 || @id == 2), emps == twoEmployees));
+
+ var employees:XML =
+
+
+
+
+11 Main St.
+San Francisco
+CA
+98765
+
+
+
+
+
+99 Broad St.
+Newton
+MA
+01234
+
+
+;
+
+for each (var id:XML in employees.employee.@id) {
+trace(id); // 123-123-1234
+}
+
+correct =
+
+
+
+99 Broad St.
+Newton
+MA
+01234
+
+;
+
+var idToFind:String = "2";
+Assert.expectEq("employees.employee.(@id == idToFind)", correct.toString(), (employees.employee.(@id == idToFind)).toString());
+
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/output.txt
new file mode 100644
index 000000000..e00dc9e59
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/output.txt
@@ -0,0 +1,14 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+6 PASSED!
+7 PASSED!
+e.employee.(fname == "Joe") PASSED!
+employees with id's 1 & 2 PASSED!
+name of employee with id 1 PASSED!
+Compare to equivalent XMLList PASSED!
+1
+2
+employees.employee.(@id == idToFind) PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/test.swf
new file mode 100644
index 000000000..41262f72d
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_2_4/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/Test.as
new file mode 100644
index 000000000..fcefb464d
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/Test.as
@@ -0,0 +1,551 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+import com.adobe.test.Utils;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+
+START("11.3.1 - Delete Operator");
+
+order =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+// Delete the customer address
+correct =
+
+
+ John
+ Doe
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+delete order.customer.address;
+TEST_XML(1, "", order.customer.address);
+TEST(2, correct, order);
+
+order =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+// delete the custmomer ID
+correct =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+delete order.customer.@id;
+TEST_XML(3, "", order.customer.@id);
+TEST(4, correct, order);
+
+order =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+// delete the first item price
+correct =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+delete order.item.price[0];
+TEST_XML(5, "", order.item[0].price);
+TEST(6, 1299.99, order.item.price[0]);
+TEST(7, order, correct);
+
+order =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+// delete all the items
+correct =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+;
+
+delete order.item;
+TEST_XML(8, "", order.item);
+TEST(9, correct, order);
+
+order =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+
+// delete all description tags with descendant operator
+// is not supposed to do anything, see bug 149397
+correct =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+
+delete order..description;
+TEST(10, correct, order);
+
+order =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+
+ Mary
+ Jones
+ 456 Foobar Ave.
+ Bel Air
+ CA
+
+;
+
+try {
+ delete order.customer.(firstname == "John");
+ result = order;
+} catch (e1) {
+ result = Utils.typeError(e1.toString());
+}
+
+Assert.expectEq("Delete an XMLList", "TypeError: Error #1119", result);
+
+order =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+// delete all id attributes
+correct =
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+;
+
+
+delete order.item.@id;
+TEST(11, correct, order);
+
+order =
+
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+
+;
+
+// delete all id attributes, using descendant operator
+correct =
+
+
+
+ John
+ Doe
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ Big Screen Television
+ 1299.99
+ 1
+
+ -
+ DVD Player
+ 399.99
+ 1
+
+
+;
+
+
+delete order..item.@id;
+TEST(12, correct, order);
+
+//default xml namespace = "http://someuri";
+x1 = ;
+x1.a.b = "foo";
+delete x1.a.b;
+TEST_XML(10, "", x1.a.b);
+
+var ns = new Namespace("");
+x1.a.b = foo;
+TEST(11, "foo", x1.a.ns::b.toString());
+
+delete x1.a.b;
+TEST(12, "", x1.a.ns::b.toString());
+
+delete x1.a.ns::b;
+TEST_XML(13, "", x1.a.ns::b);
+
+var y1;
+x1 = new XML("CD");
+y1 = new XML("C");
+
+Assert.expectEq("delete XML:", true, (delete x1.b.d, (x1 == y1)));
+
+
+
+x1 = new XMLList("ABC");
+y1 = new XMLList("AC");
+
+Assert.expectEq("delete XMLList:", true, (delete x1.b, (x1 == y1)));
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/output.txt
new file mode 100644
index 000000000..483d680cc
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/output.txt
@@ -0,0 +1,19 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+6 PASSED!
+7 PASSED!
+8 PASSED!
+9 PASSED!
+10 PASSED!
+Delete an XMLList PASSED!
+11 PASSED!
+12 PASSED!
+10 PASSED!
+11 PASSED!
+12 PASSED!
+13 PASSED!
+delete XML: PASSED!
+delete XMLList: PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/test.swf
new file mode 100644
index 000000000..10fae207a
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_1/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/Test.as
new file mode 100644
index 000000000..7195e6453
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/Test.as
@@ -0,0 +1,124 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.3.2 - Typeof Operator");
+
+x1 = new XML();
+TEST(1, "xml", typeof(x1));
+x1 = new XMLList();
+TEST(2, "xml", typeof(x1));
+
+
+
+x1 = new XML("CD");
+x_ = new XML("E");
+
+Assert.expectEq( "typeof XML :", "xml", typeof(x1) );
+Assert.expectEq( "typeof XML :", "xml", typeof(x1.a.b+x_) );
+
+x1 = new XMLList("ABC");
+x_ = new XMLList("D");
+
+Assert.expectEq( "typeof XMLList :", "xml", typeof(x1) );
+Assert.expectEq( "typeof XMLList :", "xml", typeof(x1+x_) );
+
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/output.txt
new file mode 100644
index 000000000..7d2346170
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/output.txt
@@ -0,0 +1,6 @@
+1 PASSED!
+2 PASSED!
+typeof XML : PASSED!
+typeof XML : PASSED!
+typeof XMLList : PASSED!
+typeof XMLList : PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/test.swf
new file mode 100644
index 000000000..994b6b33d
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_3_2/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/Test.as
new file mode 100644
index 000000000..6a291be57
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/Test.as
@@ -0,0 +1,231 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.4.1 - Addition Operator");
+
+employeeData = Fred + 28 + skiing;
+TEST(1, "xml", typeof(employeeData));
+correct = <>Fred28skiing>;
+TEST(2, correct, employeeData);
+
+order =
+ -
+ Big Screen Television
+
+ -
+ DVD Player
+
+ -
+ CD Player
+
+ -
+ 8-Track Player
+
+ ;
+
+correct =
+- Big Screen Television
+
+- CD Player
+
+- 8-Track Player
;
+
+myItems = order.item[0] + order.item[2] + order.item[3];
+TEST(3, "xml", typeof(myItems));
+TEST(4, correct, myItems);
+
+correct =
+- Big Screen Television
+
+- DVD Player
+
+- CD Player
+
+- 8-Track Player
+
+- New Item
;
+
+newItems = order.item + - New Item
;
+TEST(5, "xml", typeof(newItems));
+TEST(6, correct, newItems);
+
+order =
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+
+totalPrice = +order.item[0].price + +order.item[1].price;
+TEST(7, "number", typeof(totalPrice));
+TEST(8, 1699.98, totalPrice);
+
+totalPrice = +order.item[1].price + +order.item[3].price;
+TEST(9, 469.98, totalPrice);
+
+
+order =
+
+
+
+ 123 Foobar Ave.
+ Bellevue
+ WA
+ 98008
+
+
+;
+
+streetCity = "" + order.customer.address.street + order.customer.address.city;
+TEST(10, "string", typeof(streetCity));
+TEST(11, "123 Foobar Ave.Bellevue", streetCity);
+
+
+statezip = String(order.customer.address.state) + order.customer.address.zip;
+TEST(12, "string", typeof(statezip));
+TEST(13, "WA98008", statezip);
+
+// XML + XML
+
+var x1, y1, z1;
+
+x1 = new XML("AB");
+y1 = new XML("CD");
+z1 = new XMLList("ABCD");
+
+Assert.expectEq( "XML + XML: ", true, ((x1+y1)==z1) );
+
+
+// XML + XMLList
+
+x1 = new XML("AB");
+y1 = new XMLList("CDE");
+z1 = new XMLList("ABCDE");
+
+Assert.expectEq( "XML + XMLList: ", true, ((x1+y1)==z1) );
+
+
+// XMLList + XML
+
+x1 = new XMLList("CDE");
+y1 = new XML("AB");
+z1 = new XMLList("CDEAB");
+
+Assert.expectEq( "XMLList + XML: ", true, ((x1+y1)==z1) );
+
+
+// XMLList + XMLList
+
+x1 = new XMLList("ABC");
+y1 = new XMLList("DEF");
+z1 = new XMLList("ABCDEF");
+
+Assert.expectEq( "XMLList + XMLList: ", true, ((x1+y1)==z1) );
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/output.txt
new file mode 100644
index 000000000..b1431db15
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/output.txt
@@ -0,0 +1,17 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+6 PASSED!
+7 PASSED!
+8 PASSED!
+9 PASSED!
+10 PASSED!
+11 PASSED!
+12 PASSED!
+13 PASSED!
+XML + XML: PASSED!
+XML + XMLList: PASSED!
+XMLList + XML: PASSED!
+XMLList + XMLList: PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/test.swf
new file mode 100644
index 000000000..c0d45a29e
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_4_1/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/Test.as
new file mode 100644
index 000000000..06939269c
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/Test.as
@@ -0,0 +1,259 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.5.1 - Equality Operators");
+
+x1 = one;
+y1 = one;
+TEST(1, true, (x1 == y1) && (y1 == x1));
+
+var myxml:XML = foo;
+var str1:String = "foo";
+TEST(17, true, myxml.hasSimpleContent());
+TEST(18, true, myxml==str1);
+
+
+// Should return false if comparison is not XML
+y1 = "one";
+TEST(2, false, (x1 == y1) || (y1 == x1));
+
+y1 = undefined
+TEST(3, false, (x1 == y1) || (y1 == x1));
+
+y1 = null
+TEST(4, false, (x1 == y1) || (y1 == x1));
+
+// Should check logical equiv.
+x1 = onetwo;
+y1 = onetwo;
+TEST(5, true, (x1 == y1) && (y1 == x1));
+
+y1 = onetwo;
+TEST(6, false, (x1 == y1) || (y1 == x1));
+
+m = new Namespace();
+n = new Namespace();
+TEST(7, true, m == n);
+
+m = new Namespace("uri");
+TEST(8, false, m == n);
+
+n = new Namespace("ns", "uri");
+TEST(9, true, m == n);
+
+m = new Namespace(n);
+TEST(10, true, m == n);
+
+TEST(11, false, m == null);
+TEST(12, false, null == m);
+
+m = new Namespace("ns", "http://anotheruri");
+TEST(13, false, m == n);
+
+p = new QName("a");
+q = new QName("b");
+TEST(14, false, p == q);
+
+q = new QName("a");
+TEST(15, true, p == q);
+
+q = new QName("http://someuri", "a");
+TEST(16, false, p == q);
+
+q = new QName(null, "a");
+TEST(16, false, p == q);
+
+var x1 = new XML("ABC");
+var y0 = new XML("AB");
+var y1 = new XML("ABC");
+var y2 = new XML("ABC");
+var y3 = new XML("DeeEeeFee");
+
+Assert.expectEq( "x=XMLList, y=XML :", false, (x1==y0) );
+Assert.expectEq( "x=XMLList, y=XMLList :", true, (x1==y1) );
+Assert.expectEq( "x=XMLList, y=XMLList :", false, (x1==y2) );
+Assert.expectEq( "x=XMLList, y=XMLList :", false, (x1==y3) );
+
+
+var xt = new XML("text");
+var xa = new XML("attribute");
+var xh = new XML("hasSimpleContent");
+var yt = new XML("text");
+var ya = new XML("attribute");
+var yh = new XML("hasSimpleContent");
+
+Assert.expectEq( "x.[[Class]]='text, y.[[Class]]='text' :", true, (xt==yt) );
+Assert.expectEq( "x.[[Class]]='text, y.[[Class]]='attribute' :", false, (xt==ya.@attr) );
+Assert.expectEq( "x.[[Class]]='text, y.hasSimpleContent() :", false, (xt==yh) );
+
+Assert.expectEq( "x.[[Class]]='attribute, y.[[Class]]='text' :", false, (xa.@attr==yt) );
+Assert.expectEq( "x.[[Class]]='attribute, y.[[Class]]='attribute' :", true, (xa.@attr==ya.@attr) );
+Assert.expectEq( "x.[[Class]]='attribute, y.hasSimpleContent() :", false, (xa.@attr==yh) );
+
+Assert.expectEq( "x.hasSimpleContent(), y.[[Class]]='text' :", false, (xh==yt) );
+Assert.expectEq( "x.hasSimpleContent(), y.[[Class]]='attribute' :", false, (xh==ya.@attr) );
+Assert.expectEq( "x.hasSimpleContent(), y.hasSimpleContent() :", true, (xh==yh) );
+
+
+var xqn0 = new QName("n0");
+var xqn1 = new QName("ns1","n1");
+
+var yqn00 = new QName("n0");
+var yqn01 = new QName("nA");
+var yqn10 = new QName("ns1", "n1" );
+var yqn11 = new QName("ns1", "nB");
+var yqn12 = new QName("nsB","n1" );
+var yqn13 = new QName("nsB","nB");
+
+Assert.expectEq( "QName('n0'), QName('n0') :", true, (xqn0==yqn00) );
+Assert.expectEq( "QName('n0'), QName('nA') :", false, (xqn0==yqn01) );
+Assert.expectEq( "QName('n0'), QName('ns1','n1') :", false, (xqn0==yqn10) );
+Assert.expectEq( "QName('n0'), QName('ns1','nB') :", false, (xqn0==yqn11) );
+Assert.expectEq( "QName('n0'), QName('nsB','n1') :", false, (xqn0==yqn12) );
+Assert.expectEq( "QName('n0'), QName('naB','nB') :", false, (xqn0==yqn13) );
+
+Assert.expectEq( "QName('ns1','n1'), QName('n0') :", false, (xqn1==yqn00) );
+Assert.expectEq( "QName('ns1','n1'), QName('nA') :", false, (xqn1==yqn01) );
+Assert.expectEq( "QName('ns1','n1'), QName('ns1','n1') :", true, (xqn1==yqn10) );
+Assert.expectEq( "QName('ns1','n1'), QName('ns1','nB') :", false, (xqn1==yqn11) );
+Assert.expectEq( "QName('ns1','n1'), QName('nsB','n1') :", false, (xqn1==yqn12) );
+Assert.expectEq( "QName('ns1','n1'), QName('nsB','nB') :", false, (xqn1==yqn13) );
+
+
+var xns0 = new Namespace();
+var xns1 = new Namespace("uri1");
+var xns2 = new Namespace("pre2","uri2");
+
+var yns00 = new Namespace();
+var yns10 = new Namespace("uri1");
+var yns11 = new Namespace("uriB");
+var yns20 = new Namespace("pre2","uri2");
+var yns21 = new Namespace("pre2","uriC");
+var yns22 = new Namespace("preC","uri2");
+var yns23 = new Namespace("preC","uriC");
+
+
+Assert.expectEq( "Namespace(), Namespace() :", true, (xns0==yns00) );
+Assert.expectEq( "Namespace(), Namespace('uri1') :", false, (xns0==yns10) );
+Assert.expectEq( "Namespace(), Namespace('uriB') :", false, (xns0==yns11) );
+Assert.expectEq( "Namespace(), Namespace('pre2','uri2') :", false, (xns0==yns20) );
+Assert.expectEq( "Namespace(), Namespace('pre2','uriC') :", false, (xns0==yns21) );
+Assert.expectEq( "Namespace(), Namespace('preC','uri2') :", false, (xns0==yns22) );
+Assert.expectEq( "Namespace(), Namespace('preC','uriC') :", false, (xns0==yns23) );
+
+Assert.expectEq( "Namespace('uri1'), Namespace() :", false, (xns1==yns00) );
+Assert.expectEq( "Namespace('uri1'), Namespace('uri1') :", true, (xns1==yns10) );
+Assert.expectEq( "Namespace('uri1'), Namespace('uriB') :", false, (xns1==yns11) );
+Assert.expectEq( "Namespace('uri1'), Namespace('pre2','uri2') :", false, (xns1==yns20) );
+Assert.expectEq( "Namespace('uri1'), Namespace('pre2','uriC') :", false, (xns1==yns21) );
+Assert.expectEq( "Namespace('uri1'), Namespace('preC','uri2') :", false, (xns1==yns22) );
+Assert.expectEq( "Namespace('uri1'), Namespace('preC','uriC') :", false, (xns1==yns23) );
+
+Assert.expectEq( "Namespace('pre2','uri2'), Namespace() :", false, (xns2==yns00) );
+Assert.expectEq( "Namespace('pre2','uri2'), Namespace('uri1') :", false, (xns2==yns10) );
+Assert.expectEq( "Namespace('pre2','uri2'), Namespace('uriB') :", false, (xns2==yns11) );
+Assert.expectEq( "Namespace('pre2','uri2'), Namespace('pre2','uri2') :", true, (xns2==yns20) );
+Assert.expectEq( "Namespace('pre2','uri2'), Namespace('pre2','uriC') :", false, (xns2==yns21) );
+Assert.expectEq( "Namespace('pre2','uri2'), Namespace('preC','uri2') :", true, (xns2==yns22) );
+Assert.expectEq( "Namespace('pre2','uri2'), Namespace('preC','uriC') :", false, (xns2==yns23) );
+
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/output.txt
new file mode 100644
index 000000000..ab758feeb
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/output.txt
@@ -0,0 +1,65 @@
+1 PASSED!
+17 PASSED!
+18 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+6 PASSED!
+7 PASSED!
+8 PASSED!
+9 PASSED!
+10 PASSED!
+11 PASSED!
+12 PASSED!
+13 PASSED!
+14 PASSED!
+15 PASSED!
+16 PASSED!
+16 PASSED!
+x=XMLList, y=XML : PASSED!
+x=XMLList, y=XMLList : PASSED!
+x=XMLList, y=XMLList : PASSED!
+x=XMLList, y=XMLList : PASSED!
+x.[[Class]]='text, y.[[Class]]='text' : PASSED!
+x.[[Class]]='text, y.[[Class]]='attribute' : PASSED!
+x.[[Class]]='text, y.hasSimpleContent() : PASSED!
+x.[[Class]]='attribute, y.[[Class]]='text' : PASSED!
+x.[[Class]]='attribute, y.[[Class]]='attribute' : PASSED!
+x.[[Class]]='attribute, y.hasSimpleContent() : PASSED!
+x.hasSimpleContent(), y.[[Class]]='text' : PASSED!
+x.hasSimpleContent(), y.[[Class]]='attribute' : PASSED!
+x.hasSimpleContent(), y.hasSimpleContent() : PASSED!
+QName('n0'), QName('n0') : PASSED!
+QName('n0'), QName('nA') : PASSED!
+QName('n0'), QName('ns1','n1') : PASSED!
+QName('n0'), QName('ns1','nB') : PASSED!
+QName('n0'), QName('nsB','n1') : PASSED!
+QName('n0'), QName('naB','nB') : PASSED!
+QName('ns1','n1'), QName('n0') : PASSED!
+QName('ns1','n1'), QName('nA') : PASSED!
+QName('ns1','n1'), QName('ns1','n1') : PASSED!
+QName('ns1','n1'), QName('ns1','nB') : PASSED!
+QName('ns1','n1'), QName('nsB','n1') : PASSED!
+QName('ns1','n1'), QName('nsB','nB') : PASSED!
+Namespace(), Namespace() : PASSED!
+Namespace(), Namespace('uri1') : PASSED!
+Namespace(), Namespace('uriB') : PASSED!
+Namespace(), Namespace('pre2','uri2') : PASSED!
+Namespace(), Namespace('pre2','uriC') : PASSED!
+Namespace(), Namespace('preC','uri2') : PASSED!
+Namespace(), Namespace('preC','uriC') : PASSED!
+Namespace('uri1'), Namespace() : PASSED!
+Namespace('uri1'), Namespace('uri1') : PASSED!
+Namespace('uri1'), Namespace('uriB') : PASSED!
+Namespace('uri1'), Namespace('pre2','uri2') : PASSED!
+Namespace('uri1'), Namespace('pre2','uriC') : PASSED!
+Namespace('uri1'), Namespace('preC','uri2') : PASSED!
+Namespace('uri1'), Namespace('preC','uriC') : PASSED!
+Namespace('pre2','uri2'), Namespace() : PASSED!
+Namespace('pre2','uri2'), Namespace('uri1') : PASSED!
+Namespace('pre2','uri2'), Namespace('uriB') : PASSED!
+Namespace('pre2','uri2'), Namespace('pre2','uri2') : PASSED!
+Namespace('pre2','uri2'), Namespace('pre2','uriC') : PASSED!
+Namespace('pre2','uri2'), Namespace('preC','uri2') : PASSED!
+Namespace('pre2','uri2'), Namespace('preC','uriC') : PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/test.swf
new file mode 100644
index 000000000..8baab6404
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_5_1/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/Test.as
new file mode 100644
index 000000000..9500c6fc2
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/Test.as
@@ -0,0 +1,556 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.6.1 - XML Assignment");
+
+// Change the value of the id attribute on the second item
+order =
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+correct =
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+order.item[1].@id = 1.23;
+TEST(1, correct, order);
+
+// Add a new attribute to the second item
+order =
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+correct =
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+order.item[1].@newattr = "new value";
+TEST(2, correct, order);
+
+// Construct an attribute list containing all the ids in this order
+order =
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+order.@allids = order.item.@id;
+TEST_XML(3, "1 2 3 4", order.@allids);
+
+// Replace first child of the order element with an XML value
+order =
+
+
+ John
+ 948 Ranier Ave.
+ Portland
+ OR
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+
+order.*[0] =
+
+ Fred
+ 123 Foobar Ave.
+ Bellevue
+ WA
+;
+
+correct =
+
+
+ Fred
+ 123 Foobar Ave.
+ Bellevue
+ WA
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+TEST(4, correct, order);
+
+// Replace the second child of the order element with a list of items
+
+order =
+
+
+ John
+ 948 Ranier Ave.
+ Portland
+ OR
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+correct =
+
+
+ John
+ 948 Ranier Ave.
+ Portland
+ OR
+
+ - item one
+ - item two
+ - item three
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+order.item[0] = - item one
+
+ - item two
+
+ - item three
;
+
+TEST(5, correct, order);
+
+// Replace the third child of the order with a text node
+order =
+
+
+ John
+ 948 Ranier Ave.
+ Portland
+ OR
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+correct =
+
+
+ John
+ 948 Ranier Ave.
+ Portland
+ OR
+
+ -
+ Big Screen Television
+ 1299.99
+
+ - A Text Node
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+order.item[1] = "A Text Node";
+
+TEST(6, correct, order);
+
+// append a new item to the end of the order
+
+order =
+
+
+ John
+ 948 Ranier Ave.
+ Portland
+ OR
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+;
+
+correct =
+
+
+ John
+ 948 Ranier Ave.
+ Portland
+ OR
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+ -
+ CD Player
+ 199.99
+
+ -
+ 8-Track Player
+ 69.99
+
+ - new item
+;
+
+order.*[order.*.length()] = - new item
;
+
+TEST(7, correct, order);
+
+// Change the price of the item
+item =
+-
+ Big Screen Television
+ 1299.99
+
+
+correct =
+-
+ Big Screen Television
+ 99.95
+
+
+item.price = 99.95;
+
+TEST(8, item, correct);
+
+// Change the description of the item
+item =
+-
+ Big Screen Television
+ 1299.99
+
+
+correct =
+-
+ Mobile Phone
+ 1299.99
+
+
+item.description = "Mobile Phone";
+
+TEST(9, item, correct);
+
+// property name begins with "@"
+
+var xx = new XML("");
+var xl = new XMLList("");
+var x_ = new XML("");
+
+xx.@attr = xl.@attr;
+
+Assert.expectEq( "x.@attr=XMLList :", true, (xx==x_) );
+
+xx = new XML("");
+yy = new XML("");
+xx.@attr = "B";
+
+Assert.expectEq( "xx.@attr='B' :", "B", xx.@attr.toString() );
+
+xx.@attr__ = "B";
+
+Assert.expectEq( "xx.@attr__='B' :", true, (xx.@attr__=="B") );
+
+
+// property name does NOT begin with "@" and is NOT array index
+
+var x0 = new XML("BCD");
+var x1 = new XML("Z");
+var x0_ = new XML("ZCD");
+
+x0.b = x1.b;
+
+Assert.expectEq( "Replace XML Obj - XML :", true, (x0==x0_) );
+
+var x2 = new XMLList("YX");
+
+x0.b = x2;
+
+x0_ = new XML("YXCD");
+
+Assert.expectEq( "Replace XML Obj - XMLList :", true, (x0==x0_) );
+
+x0 = new XML("BCD");
+
+x0.e = new XML("E");
+
+x0_ = new XML("BCDE");
+
+Assert.expectEq( "Append new XML property :", true, (x0==x0_) );
+
+x0 = new XML("B0B1B2");
+x1 = new XML("BB");
+x0_ = new XML("BB");
+
+x0 = x1;
+
+Assert.expectEq( "Multiple XML objs with given name - XML :", true, (x0==x0_) );
+
+x0 = new XML("B0B1B2");
+x1 = new XML("BB");
+x0_ = new XML("BB");
+
+x0.b = x1;
+
+Assert.expectEq( "Multiple XML objs with given name - XMLList :", true, (x0==x0_) );
+
+x0 = new XML("BC");
+x0_ = new XML("AC");
+
+x0.b = "A";
+
+Assert.expectEq( "x.b = 'A' :", true, (x0==x0_) );
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/output.txt
new file mode 100644
index 000000000..3e1b3f107
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/output.txt
@@ -0,0 +1,18 @@
+1 PASSED!
+2 PASSED!
+3 PASSED!
+4 PASSED!
+5 PASSED!
+6 PASSED!
+7 PASSED!
+8 PASSED!
+9 PASSED!
+x.@attr=XMLList : PASSED!
+xx.@attr='B' : PASSED!
+xx.@attr__='B' : PASSED!
+Replace XML Obj - XML : PASSED!
+Replace XML Obj - XMLList : PASSED!
+Append new XML property : PASSED!
+Multiple XML objs with given name - XML : PASSED!
+Multiple XML objs with given name - XMLList : PASSED!
+x.b = 'A' : PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/test.swf
new file mode 100644
index 000000000..6ab8bf8ec
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_1/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/Test.as
new file mode 100644
index 000000000..6e8c1c9cf
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/Test.as
@@ -0,0 +1,467 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.6.2 - XMLList Assignment");
+
+// Set the name of the only customer in the order to Fred Jones
+order =
+
+
+ John Smith
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+;
+
+correct =
+
+
+ Fred Jones
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+;
+
+//order.customer.name = "Fred Jones";
+//TEST(1, correct, order);
+
+// Replace all the hobbies for the only customer in the order
+order =
+
+
+ John Smith
+ Biking
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+;
+
+correct =
+
+
+ John Smith
+ shopping
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+;
+
+order.customer.hobby = "shopping"
+TEST(2, correct, order);
+
+// Attempt to set the sale date of the item. Throw an exception if more than 1 item exists.
+order =
+
+
+ John Smith
+
+ -
+ Big Screen Television
+ 1299.99
+ 01-05-2002
+
+;
+
+correct =
+
+
+ John Smith
+
+ -
+ Big Screen Television
+ 1299.99
+ 05-07-2002
+
+;
+
+order.item.saledate = "05-07-2002"
+TEST(3, correct, order);
+
+order =
+
+
+ John Smith
+ Biking
+
+ -
+ Big Screen Television
+ 1299.99
+
+ -
+ DVD Player
+ 399.99
+
+;
+
+try {
+ order.item.saledate = "05-07-2002";
+ SHOULD_THROW(4);
+} catch (ex) {
+ TEST(4, "TypeError", ex.name);
+}
+
+// Replace all the employee's hobbies with their new favorite pastime
+emps =
+
+
+ John
+ 20
+ skiing
+
+
+ Sue
+ 30
+ running
+
+
+ Ted
+ 35
+ Biking
+
+;
+
+correct =
+
+
+ John
+ 20
+ skiing
+
+
+ Sue
+ 30
+ running
+
+
+ Ted
+ 35
+ working
+
+;
+
+//emps.employee.(@id == 3).hobby = "working";
+//TEST(5, correct, emps);
+
+// Replace the first employee with George
+emps =
+
+
+ John
+ 20
+
+
+ Sue
+ 30
+
+
+ Ted
+ 35
+
+;
+
+correct =
+
+
+ George
+ 27
+
+
+ Sue
+ 30
+
+
+ Ted
+ 35
+
+;
+
+emps.employee[0] = George27;
+TEST(6, emps, correct);
+
+// Add a new employee to the end of the employee list
+emps =
+
+
+ John
+ 20
+
+
+ Sue
+ 30
+
+
+ Ted
+ 35
+
+;
+
+correct =
+
+
+ John
+ 20
+
+
+ Sue
+ 30
+
+
+ Ted
+ 35
+
+
+ Frank
+ 39
+
+;
+
+emps.employee += Frank39;
+TEST(7, correct, emps);
+
+// Add a new employee to the end of the employee list
+emps =
+
+
+ John
+ 20
+
+
+ Sue
+ 30
+
+
+ Ted
+ 35
+
+;
+
+correct =
+
+
+ John
+ 20
+
+
+ Sue
+ 30
+
+
+ Ted
+ 35
+
+
+ Frank
+ 39
+
+;
+
+emps.employee[emps.employee.length()] = Frank39;
+TEST(7, correct, emps);
+
+
+// property name is NOT array index
+
+var x1 = new XML("AB");
+
+x1.b.d = "C";
+
+var y1 = new XML("AC");
+
+Assert.expectEq( "property name is not array index :", true, (x1==y1) );
+
+
+x1 = new XML("AB");
+
+x1.v.b.d = "C";
+
+y1 = new XML("ABC");
+
+Assert.expectEq("Adding new nested node at root: " , true, (x1 == y1));
+
+
+// property name is array index
+
+x1 = new XML("A0B0A1B1A2B2");
+
+x1.b[1] = new XML("A3B3");
+
+y1 = new XML("A0B0A3B3A2B2");
+
+Assert.expectEq( "property name exists in XMLList :", true, (x1==y1) );
+
+
+// property name does NOT exist in XMLList
+
+x1.b[3] = new XML("A4B4");
+
+y1 = new XML("A0B0A3B3A2B2A4B4");
+
+Assert.expectEq( "property name does NOT exist in XMLList :", true, (x1==y1) );
+
+
+// property is XML with non-null parent
+
+x1 = new XML("A0B0A1B1A2B2");
+
+x1.b = new XMLList("AB");
+
+y1 = new XML("AB");
+
+Assert.expectEq( "property is XML with non-null parent :", true, (x1==y1) );
+
+
+// AssignmentExpression = XML value
+
+x1 = new XML("A0B0A1B1A2B2");
+
+x1.b[0] = new XML("A3B3");
+
+y1 = new XML("A3B3A1B1A2B2");
+
+Assert.expectEq( "AssignmentExpression = XML value :", true, (x1==y1) );
+
+
+// AssignmentExpression = XMLList object
+
+x1 = new XML("A0B0A1B1A2B2");
+
+x1.b = new XMLList("ABC");
+
+y1 = new XML("ABC");
+
+Assert.expectEq( "AssignmentExpression = XMLList object :", true, (x1==y1) );
+
+
+// AssignmentExpression != XML/XMLList
+
+x1 = new XML("A0B0A1B1A2B2");
+
+x1.b = "Hello World";
+
+y1 = new XML("Hello World");
+
+Assert.expectEq( "AssignmentExpression != XML/XMLList :", true, (x1==y1) );
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/output.txt
new file mode 100644
index 000000000..6dfd31508
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/output.txt
@@ -0,0 +1,14 @@
+2 PASSED!
+3 PASSED!
+4 PASSED!
+6 PASSED!
+7 PASSED!
+7 PASSED!
+property name is not array index : PASSED!
+Adding new nested node at root: PASSED!
+property name exists in XMLList : PASSED!
+property name does NOT exist in XMLList : PASSED!
+property is XML with non-null parent : PASSED!
+AssignmentExpression = XML value : PASSED!
+AssignmentExpression = XMLList object : PASSED!
+AssignmentExpression != XML/XMLList : PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/test.swf
new file mode 100644
index 000000000..5b40c7c29
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_2/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/Test.as
new file mode 100644
index 000000000..4a73212c0
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/Test.as
@@ -0,0 +1,207 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+START("11.6.3 - Compound Assignment");
+
+// Insert employee 3 and 4 after the first employee
+e =
+
+
+ Joe
+ 20
+
+
+ Sue
+ 30
+
+;
+
+correct =
+
+
+ Joe
+ 20
+
+
+ Fred
+
+
+ Carol
+
+
+ Sue
+ 30
+
+;
+
+e.employee[0] += Fred +
+ Carol;
+
+TEST(1, correct, e);
+
+// Append employees 3 and 4 to the end of the employee list
+e =
+
+
+ Joe
+ 20
+
+
+ Sue
+ 30
+
+;
+
+correct =
+
+
+ Joe
+ 20
+
+
+ Sue
+ 30
+
+
+ Fred
+
+
+ Carol
+
+;
+
+e.employee[1] += Fred +
+ Carol;
+TEST(2, correct, e);
+
+// XML +=
+
+var x1 = new XML("A0A1B0B1C0C1");
+
+x1.b[1] += new XML("D0D1");
+
+var y1 = new XML("A0A1B0B1D0D1C0C1");
+
+Assert.expectEq( "XML += :", true, (x1==y1) );
+
+
+// XMLList +=
+
+x1 = new XMLList("A0A1B0B1C0C1");
+
+x1 += new XML("D0D1");
+
+y1 = new XMLList("A0A1B0B1C0C1D0D1");
+
+Assert.expectEq( "XMLList += :", true, (x1==y1) );
+
+
+// XMLList +=, last item in XMLList is XML object with non-null parent
+
+x1 = new XML("A0A1B0B1C0C1");
+
+x1 += new XMLList("D0E0");
+
+y1 = new XMLList("A0A1B0B1C0C1D0E0");
+
+Assert.expectEq( "XMLList += :", true, (x1==y1) );
+
+END();
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/output.txt
new file mode 100644
index 000000000..1598e8a4f
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/output.txt
@@ -0,0 +1,5 @@
+1 PASSED!
+2 PASSED!
+XML += : PASSED!
+XMLList += : PASSED!
+XMLList += : PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/test.swf
new file mode 100644
index 000000000..bd63b06f7
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/e11_6_3/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/Test.as b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/Test.as
new file mode 100644
index 000000000..72bed8903
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/Test.as
@@ -0,0 +1,149 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package {
+public class Test {}
+}
+
+import com.adobe.test.Assert;
+import com.adobe.test.Utils;
+
+function START(summary)
+{
+ // print out bugnumber
+
+ /*if ( BUGNUMBER ) {
+ writeLineToLog ("BUGNUMBER: " + BUGNUMBER );
+ }*/
+ XML.setSettings (null);
+ testcases = new Array();
+
+ // text field for results
+ tc = 0;
+ /*this.addChild ( tf );
+ tf.x = 30;
+ tf.y = 50;
+ tf.width = 200;
+ tf.height = 400;*/
+
+ //_print(summary);
+ var summaryParts = summary.split(" ");
+ //_print("section: " + summaryParts[0] + "!");
+ //fileName = summaryParts[0];
+
+}
+
+function TEST(section, expected, actual)
+{
+ AddTestCase(section, expected, actual);
+}
+
+
+function TEST_XML(section, expected, actual)
+{
+ var actual_t = typeof actual;
+ var expected_t = typeof expected;
+
+ if (actual_t != "xml") {
+ // force error on type mismatch
+ TEST(section, new XML(), actual);
+ return;
+ }
+
+ if (expected_t == "string") {
+
+ TEST(section, expected, actual.toXMLString());
+ } else if (expected_t == "number") {
+
+ TEST(section, String(expected), actual.toXMLString());
+ } else {
+ reportFailure ("", 'Bad TEST_XML usage: type of expected is "+expected_t+", should be number or string');
+ }
+}
+
+function reportFailure (section, msg)
+{
+ trace("~FAILURE: " + section + " | " + msg);
+}
+
+function AddTestCase( description, expect, actual ) {
+ testcases[tc++] = Assert.expectEq(description, "|"+expect+"|", "|"+actual+"|" );
+}
+
+function myGetNamespace (obj, ns) {
+ if (ns != undefined) {
+ return obj.namespace(ns);
+ } else {
+ return obj.namespace();
+ }
+}
+
+
+
+
+function NL()
+{
+ //return java.lang.System.getProperty("line.separator");
+ return "\n";
+}
+
+
+function BUG(arg){
+ // nothing here
+}
+
+function END()
+{
+ //test();
+}
+
+
+START("11.1.2 Qualified Identifiers - XML bad QName error");
+
+var expected, result, expectedStr;
+
+expectedStr = "TypeError: Error #1084: Element or attribute (\":x\") do not match QName production: QName::=(NCName':')?NCName";
+expected = "Error #1084";
+
+result = "error, exception not thrown";
+
+namespace ns="http://www.foo.com";
+var x1 = new XML("foo");
+
+try{
+
+x1 = new XML("<:x>hi");
+throw "kXMLBadQname error not thrown";
+
+} catch( e1 ){
+
+result = Utils.grabError(e1, e1.toString());
+
+}
+
+
+Assert.expectEq("<:x>hi", expected, result);
+
+
+expectedStr = "TypeError: Error #1084: Element or attribute (\":ns\") do not match QName production: QName::=(NCName':')?NCName";
+expected = "Error #1084";
+
+try{
+
+x1 = new XML("hi");
+throw "kXMLBadQname error not thrown";
+
+} catch( e2 ){
+
+result = Utils.grabError(e2, e2.toString());
+
+}
+
+
+Assert.expectEq("hi", expected, result);
+
+END();
+
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/config.xml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/config.xml
new file mode 100644
index 000000000..18d27f9ba
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/config.xml
@@ -0,0 +1,13 @@
+
+
+
+ .
+ ../../../lib
+
+ false
+ false
+ false
+ false
+
+
+
\ No newline at end of file
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/output.txt b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/output.txt
new file mode 100644
index 000000000..dc75a69bf
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/output.txt
@@ -0,0 +1,4 @@
+Asserting for TypeError PASSED!
+<:x>hi PASSED!
+Asserting for TypeError PASSED!
+hi PASSED!
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/test.swf b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/test.swf
new file mode 100644
index 000000000..eb3e87eef
Binary files /dev/null and b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/test.swf differ
diff --git a/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/test.toml b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/test.toml
new file mode 100644
index 000000000..e115772d5
--- /dev/null
+++ b/tests/tests/swfs/avm2/from_avmplus/e4x/Expressions/kXMLBadQNameErr/test.toml
@@ -0,0 +1,2 @@
+num_ticks = 1
+known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12351