avm2: Implement `in`

This commit is contained in:
David Wendt 2020-09-03 21:47:26 -04:00 committed by Mike Welsh
parent 11b8354905
commit 3b5411547a
6 changed files with 299 additions and 0 deletions

View File

@ -450,6 +450,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
Op::DeleteProperty { index } => self.op_delete_property(method, index),
Op::GetSuper { index } => self.op_get_super(method, index),
Op::SetSuper { index } => self.op_set_super(method, index),
Op::In => self.op_in(),
Op::PushScope => self.op_push_scope(),
Op::PushWith => self.op_push_with(),
Op::PopScope => self.op_pop_scope(),
@ -1033,6 +1034,24 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
Ok(FrameControl::Continue)
}
fn op_in(&mut self) -> Result<FrameControl<'gc>, Error> {
let obj = self.context.avm2.pop().coerce_to_object(self)?;
let name = self.context.avm2.pop().coerce_to_string(self)?;
let mut has_prop = false;
if let Some(ns) = obj.resolve_any(name)? {
if !ns.is_private() {
let qname = QName::new(ns, name);
has_prop = obj.has_property(&qname)?;
}
}
self.context.avm2.push(has_prop);
Ok(FrameControl::Continue)
}
fn op_push_scope(&mut self) -> Result<FrameControl<'gc>, Error> {
let object = self.context.avm2.pop().coerce_to_object(self)?;
let scope_stack = self.scope();

View File

@ -351,6 +351,7 @@ swf_tests! {
(as3_rshift, "avm2/rshift", 1),
(as3_subtract, "avm2/subtract", 1),
(as3_urshift, "avm2/urshift", 1),
(as3_in, "avm2/in", 1),
}
// TODO: These tests have some inaccuracies currently, so we use approx_eq to test that numeric values are close enough.

View File

@ -0,0 +1,177 @@
package {
public class Test {}
}
class ES4Class extends Object {
public var test_var = "var";
public const test_const = "const";
public function test_function() {
trace("test_function");
}
public function get test_virt() {
return "test_virt";
}
public function set test_virt(val) {
trace("test_virt");
}
public static var test_static_var = "var";
public static const test_static_const = "const";
public static function test_static_function() {
trace("test_static_function");
}
public static function get test_static_virt() {
return "test_static_virt";
}
public static function set test_static_virt(val) {
trace("test_static_virt");
}
private var test_private_var = "private_var";
private const test_private_const = "private_const";
private function test_private_function() {
trace("test_private_function");
}
private function get test_private_virt() {
return "test_private_virt";
}
private function set test_private_virt(val) {
trace("test_private_virt");
}
}
function ES3Class() {
this.test_var = "var";
}
ES3Class.test_static_var = "var";
ES3Class.test_static_function = function () {
trace("test_static_function");
}
ES3Class.prototype.test_function = function() {
trace("test_function");
}
ES3Class.prototype.test_proto = "proto_var";
var es4inst = new ES4Class();
var es3inst = new ES3Class();
trace("//'test_var' in es4inst");
trace('test_var' in es4inst);
trace("//'test_const' in es4inst");
trace('test_const' in es4inst);
trace("//'test_function' in es4inst");
trace('test_function' in es4inst);
trace("//'test_virt' in es4inst");
trace('test_virt' in es4inst);
trace("//'test_static_var' in es4inst");
trace('test_static_var' in es4inst);
trace("//'test_static_const' in es4inst");
trace('test_static_const' in es4inst);
trace("//'test_static_function' in es4inst");
trace('test_static_function' in es4inst);
trace("//'test_static_virt' in es4inst");
trace('test_static_virt' in es4inst);
trace("//'test_private_var' in es4inst");
trace('test_private_var' in es4inst);
trace("//'test_private_const' in es4inst");
trace('test_private_const' in es4inst);
trace("//'test_private_function' in es4inst");
trace('test_private_function' in es4inst);
trace("//'test_private_virt' in es4inst");
trace('test_private_virt' in es4inst);
trace("//'test_var' in ES4Class");
trace('test_var' in ES4Class);
trace("//'test_const' in ES4Class");
trace('test_const' in ES4Class);
trace("//'test_function' in ES4Class");
trace('test_function' in ES4Class);
trace("//'test_virt' in ES4Class");
trace('test_virt' in ES4Class);
trace("//'test_static_var' in ES4Class");
trace('test_static_var' in ES4Class);
trace("//'test_static_const' in ES4Class");
trace('test_static_const' in ES4Class);
trace("//'test_static_function' in ES4Class");
trace('test_static_function' in ES4Class);
trace("//'test_static_virt' in ES4Class");
trace('test_static_virt' in ES4Class);
trace("//'test_private_var' in ES4Class");
trace('test_private_var' in ES4Class);
trace("//'test_private_const' in ES4Class");
trace('test_private_const' in ES4Class);
trace("//'test_private_function' in ES4Class");
trace('test_private_function' in ES4Class);
trace("//'test_private_virt' in ES4Class");
trace('test_private_virt' in ES4Class);
trace("//'test_var' in ES4Class.prototype");
trace('test_var' in ES4Class.prototype);
trace("//'test_const' in ES4Class.prototype");
trace('test_const' in ES4Class.prototype);
trace("//'test_function' in ES4Class.prototype");
trace('test_function' in ES4Class.prototype);
trace("//'test_virt' in ES4Class.prototype");
trace('test_virt' in ES4Class.prototype);
trace("//'test_static_var' in ES4Class.prototype");
trace('test_static_var' in ES4Class.prototype);
trace("//'test_static_const' in ES4Class.prototype");
trace('test_static_const' in ES4Class.prototype);
trace("//'test_static_function' in ES4Class.prototype");
trace('test_static_function' in ES4Class.prototype);
trace("//'test_static_virt' in ES4Class.prototype");
trace('test_static_virt' in ES4Class.prototype);
trace("//'test_private_var' in ES4Class.prototype");
trace('test_private_var' in ES4Class.prototype);
trace("//'test_private_const' in ES4Class.prototype");
trace('test_private_const' in ES4Class.prototype);
trace("//'test_private_function' in ES4Class.prototype");
trace('test_private_function' in ES4Class.prototype);
trace("//'test_private_virt' in ES4Class.prototype");
trace('test_private_virt' in ES4Class.prototype);
trace("//'test_var' in es3inst");
trace('test_var' in es3inst);
trace("//'test_function' in es3inst");
trace('test_function' in es3inst);
trace("//'test_proto' in es3inst");
trace('test_proto' in es3inst);
trace("//'test_static_var' in es3inst");
trace('test_static_var' in es3inst);
trace("//'test_static_function' in es3inst");
trace('test_static_function' in es3inst);
trace("//'test_var' in ES3Class");
trace('test_var' in ES3Class);
trace("//'test_function' in ES3Class");
trace('test_function' in ES3Class);
trace("//'test_proto' in ES3Class");
trace('test_proto' in ES3Class);
trace("//'test_static_var' in ES3Class");
trace('test_static_var' in ES3Class);
trace("//'test_static_function' in ES3Class");
trace('test_static_function' in ES3Class);
trace("//'test_var' in ES3Class.prototype");
trace('test_var' in ES3Class.prototype);
trace("//'test_function' in ES3Class.prototype");
trace('test_function' in ES3Class.prototype);
trace("//'test_proto' in ES3Class.prototype");
trace('test_proto' in ES3Class.prototype);
trace("//'test_static_var' in ES3Class.prototype");
trace('test_static_var' in ES3Class.prototype);
trace("//'test_static_function' in ES3Class.prototype");
trace('test_static_function' in ES3Class.prototype);

View File

@ -0,0 +1,102 @@
//'test_var' in es4inst
true
//'test_const' in es4inst
true
//'test_function' in es4inst
true
//'test_virt' in es4inst
true
//'test_static_var' in es4inst
false
//'test_static_const' in es4inst
false
//'test_static_function' in es4inst
false
//'test_static_virt' in es4inst
false
//'test_private_var' in es4inst
false
//'test_private_const' in es4inst
false
//'test_private_function' in es4inst
false
//'test_private_virt' in es4inst
false
//'test_var' in ES4Class
false
//'test_const' in ES4Class
false
//'test_function' in ES4Class
false
//'test_virt' in ES4Class
false
//'test_static_var' in ES4Class
true
//'test_static_const' in ES4Class
true
//'test_static_function' in ES4Class
true
//'test_static_virt' in ES4Class
true
//'test_private_var' in ES4Class
false
//'test_private_const' in ES4Class
false
//'test_private_function' in ES4Class
false
//'test_private_virt' in ES4Class
false
//'test_var' in ES4Class.prototype
false
//'test_const' in ES4Class.prototype
false
//'test_function' in ES4Class.prototype
false
//'test_virt' in ES4Class.prototype
false
//'test_static_var' in ES4Class.prototype
false
//'test_static_const' in ES4Class.prototype
false
//'test_static_function' in ES4Class.prototype
false
//'test_static_virt' in ES4Class.prototype
false
//'test_private_var' in ES4Class.prototype
false
//'test_private_const' in ES4Class.prototype
false
//'test_private_function' in ES4Class.prototype
false
//'test_private_virt' in ES4Class.prototype
false
//'test_var' in es3inst
true
//'test_function' in es3inst
true
//'test_proto' in es3inst
true
//'test_static_var' in es3inst
false
//'test_static_function' in es3inst
false
//'test_var' in ES3Class
false
//'test_function' in ES3Class
false
//'test_proto' in ES3Class
false
//'test_static_var' in ES3Class
true
//'test_static_function' in ES3Class
true
//'test_var' in ES3Class.prototype
false
//'test_function' in ES3Class.prototype
true
//'test_proto' in ES3Class.prototype
true
//'test_static_var' in ES3Class.prototype
false
//'test_static_function' in ES3Class.prototype
false

Binary file not shown.

Binary file not shown.