Skip to content

Commit

Permalink
avm2: Implement XMLList.contains
Browse files Browse the repository at this point in the history
  • Loading branch information
sleepycatcoding committed May 29, 2024
1 parent 1fe1b8d commit 007a532
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 2 deletions.
6 changes: 6 additions & 0 deletions core/src/avm2/globals/XMLList.as
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ package {
AS3 native function length():int;
AS3 native function child(name:Object):XMLList;
AS3 native function children():XMLList;
AS3 native function contains(value:*):Boolean;
AS3 native function copy():XMLList;
AS3 native function attribute(name:*):XMLList;
AS3 native function attributes():XMLList;
Expand Down Expand Up @@ -87,6 +88,11 @@ package {
return self.AS3::children();
}

prototype.contains = function(value:*):Boolean {
var self:XMLList = this;
return self.AS3::contains(value);
}

prototype.copy = function():XMLList {
var self:XMLList = this;
return self.AS3::copy();
Expand Down
27 changes: 27 additions & 0 deletions core/src/avm2/globals/xml_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,33 @@ pub fn children<'gc>(
.into())
}

/// 13.5.4.8 XMLList.prototype.contains (value)
pub fn contains<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let list = this.as_xml_list_object().unwrap();
let value = args.get_value(0);
let length = list.length();

// 1. For i = 0 to list.[[Length]]-1
// NOTE: cannot use children_mut here since the value can be this same list, which causes a panic.
for index in 0..length {
let child = list
.xml_object_child(index, activation)
.expect("index should be in between 0 and length");

// 2.a. If the result of the comparison list[i] == value is true, return true
if child.abstract_eq(&value, activation)? {
return Ok(true.into());
}
}

// 2. Return false
Ok(false.into())
}

pub fn copy<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
Expand Down
85 changes: 85 additions & 0 deletions tests/tests/swfs/avm2/xml_contains/Test.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package {
import flash.display.Sprite;
public class Test extends Sprite {}
}

var list1 = new XMLList("<item>A</item><item>B</item>");
var list2 = new XMLList("<item>A</item>");
var list3 = new XMLList("<item>B</item>");

var x = new XML("<item>A</item>");
var x1 = <item>A</item>;
var x2 = new XML("<item>B</item>");

var values = [null, undefined, "A", "B", "C", list1, list2, list3, x, x1, x2];

for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values.length; j++) {
test(values[i], values[j]);
}
}

function test(self, a) {
if (!(self is XMLList) && !(self is XML)) {
return;
}

trace(repr(self) + ".contains(" + repr(a) + ")");
try {
trace(self.contains(a));
} catch (ex) {
trace("! " + ex);
}
trace();
}

function repr(value: *) {
if (value === undefined) {
return "undefined";
} else if (value === null) {
return "null";
} else if (value === list1) {
return "list1";
} else if (value === list2) {
return "list2";
} else if (value === list3) {
return "list3";
} else if (value === x) {
return "x";
} else if (value === x1) {
return "x1";
} else if (value === x2) {
return "x2";
} else if (value is String) {
return escapeString(value);
} else {
return typeof(value) + " " + value;
}
}

function escapeString(input: String): String {
var output:String = "\"";
for (var i:int = 0; i < input.length; i++) {
var char:String = input.charAt(i);
switch (char) {
case "\\":
output += "\\\\";
break;
case "\"":
output += "\\\"";
break;
case "\n":
output += "\\n";
break;
case "\r":
output += "\\r";
break;
case "\t":
output += "\\t";
break;
default:
output += char;
}
}
return output + "\"";
}
198 changes: 198 additions & 0 deletions tests/tests/swfs/avm2/xml_contains/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
list1.contains(null)
false

list1.contains(undefined)
false

list1.contains("A")
true

list1.contains("B")
true

list1.contains("C")
false

list1.contains(list1)
false

list1.contains(list2)
true

list1.contains(list3)
true

list1.contains(x)
true

list1.contains(x1)
true

list1.contains(x2)
true

list2.contains(null)
false

list2.contains(undefined)
false

list2.contains("A")
true

list2.contains("B")
false

list2.contains("C")
false

list2.contains(list1)
false

list2.contains(list2)
true

list2.contains(list3)
false

list2.contains(x)
true

list2.contains(x1)
true

list2.contains(x2)
false

list3.contains(null)
false

list3.contains(undefined)
false

list3.contains("A")
false

list3.contains("B")
true

list3.contains("C")
false

list3.contains(list1)
false

list3.contains(list2)
false

list3.contains(list3)
true

list3.contains(x)
false

list3.contains(x1)
false

list3.contains(x2)
true

x.contains(null)
false

x.contains(undefined)
false

x.contains("A")
false

x.contains("B")
false

x.contains("C")
false

x.contains(list1)
false

x.contains(list2)
false

x.contains(list3)
false

x.contains(x)
true

x.contains(x1)
true

x.contains(x2)
false

x1.contains(null)
false

x1.contains(undefined)
false

x1.contains("A")
false

x1.contains("B")
false

x1.contains("C")
false

x1.contains(list1)
false

x1.contains(list2)
false

x1.contains(list3)
false

x1.contains(x)
true

x1.contains(x1)
true

x1.contains(x2)
false

x2.contains(null)
false

x2.contains(undefined)
false

x2.contains("A")
false

x2.contains("B")
false

x2.contains("C")
false

x2.contains(list1)
false

x2.contains(list2)
false

x2.contains(list3)
false

x2.contains(x)
false

x2.contains(x1)
false

x2.contains(x2)
true

Binary file added tests/tests/swfs/avm2/xml_contains/test.swf
Binary file not shown.
1 change: 1 addition & 0 deletions tests/tests/swfs/avm2/xml_contains/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
num_ticks = 1
1 change: 0 additions & 1 deletion tests/tests/swfs/from_avmplus/e4x/XML/e13_4_4_10/test.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
num_ticks = 1
known_failure = true
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
num_ticks = 1
known_failure = true

0 comments on commit 007a532

Please sign in to comment.