From 0e89cb217514d031776c571d44d01d8d63946c24 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Fri, 6 Mar 2020 15:02:19 -0500 Subject: [PATCH] Impl `Object.isPrototypeOf` w/ test --- core/src/avm2/globals/object.rs | 33 ++++++++++++++++-- core/tests/swfs/avm2/is_prototype_of/Test.as | 28 +++++++++++++++ .../swfs/avm2/is_prototype_of/output.txt | 13 +++++++ core/tests/swfs/avm2/is_prototype_of/test.fla | Bin 0 -> 3985 bytes core/tests/swfs/avm2/is_prototype_of/test.swf | Bin 0 -> 896 bytes 5 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 core/tests/swfs/avm2/is_prototype_of/Test.as create mode 100644 core/tests/swfs/avm2/is_prototype_of/output.txt create mode 100644 core/tests/swfs/avm2/is_prototype_of/test.fla create mode 100644 core/tests/swfs/avm2/is_prototype_of/test.swf diff --git a/core/src/avm2/globals/object.rs b/core/src/avm2/globals/object.rs index cdf1e04da..16597ecf5 100644 --- a/core/src/avm2/globals/object.rs +++ b/core/src/avm2/globals/object.rs @@ -12,7 +12,7 @@ use gc_arena::MutationContext; /// Implements `Object` pub fn constructor<'gc>( _avm: &mut Avm2<'gc>, - _action_context: &mut UpdateContext<'_, 'gc, '_>, + _context: &mut UpdateContext<'_, 'gc, '_>, _this: Option>, _args: &[Value<'gc>], ) -> Result, Error> { @@ -22,7 +22,7 @@ pub fn constructor<'gc>( /// `Object.prototype.hasOwnProperty` pub fn has_own_property<'gc>( _avm: &mut Avm2<'gc>, - _action_context: &mut UpdateContext<'_, 'gc, '_>, + _context: &mut UpdateContext<'_, 'gc, '_>, this: Option>, args: &[Value<'gc>], ) -> Result, Error> { @@ -39,6 +39,29 @@ pub fn has_own_property<'gc>( Ok(false.into()) } +/// `Object.prototype.isPrototypeOf` +pub fn is_prototype_of<'gc>( + _avm: &mut Avm2<'gc>, + _context: &mut UpdateContext<'_, 'gc, '_>, + this: Option>, + args: &[Value<'gc>], +) -> Result, Error> { + let search_proto: Result, Error> = + this.ok_or_else(|| "No valid this parameter".into()); + let search_proto = search_proto?; + let mut target_proto = args.get(0).cloned().unwrap_or(Value::Undefined); + + while let Value::Object(proto) = target_proto { + if Object::ptr_eq(search_proto, proto) { + return Ok(true.into()); + } + + target_proto = proto.proto().map(|o| o.into()).unwrap_or(Value::Undefined); + } + + Ok(false.into()) +} + /// Partially construct `Object.prototype`. /// /// `__proto__` and other cross-linked properties of this object will *not* @@ -59,4 +82,10 @@ pub fn fill_proto<'gc>( 0, FunctionObject::from_builtin(gc_context, has_own_property, fn_proto), ); + object_proto.install_method( + gc_context, + QName::new(Namespace::public_namespace(), "isPrototypeOf"), + 0, + FunctionObject::from_builtin(gc_context, is_prototype_of, fn_proto), + ); } diff --git a/core/tests/swfs/avm2/is_prototype_of/Test.as b/core/tests/swfs/avm2/is_prototype_of/Test.as new file mode 100644 index 000000000..c23680bb7 --- /dev/null +++ b/core/tests/swfs/avm2/is_prototype_of/Test.as @@ -0,0 +1,28 @@ +package { + public class Test {} +} + +class ES4Class extends Object { + +} + +function ES3Class() { + +} + +var es4inst = new ES4Class(); +var es3inst = new ES3Class(); + +trace("//ES4Class.prototype.isPrototypeOf(es4inst);"); +trace(ES4Class.prototype.isPrototypeOf(es4inst)); +trace("//Object.prototype.isPrototypeOf(es4inst);"); +trace(Object.prototype.isPrototypeOf(es4inst)); +trace("//ES3Class.prototype.isPrototypeOf(es4inst);"); +trace(ES3Class.prototype.isPrototypeOf(es4inst)); + +trace("//ES4Class.prototype.isPrototypeOf(es3inst);"); +trace(ES4Class.prototype.isPrototypeOf(es3inst)); +trace("//Object.prototype.isPrototypeOf(es3inst);"); +trace(Object.prototype.isPrototypeOf(es3inst)); +trace("//ES3Class.prototype.isPrototypeOf(es3inst);"); +trace(ES3Class.prototype.isPrototypeOf(es3inst)); \ No newline at end of file diff --git a/core/tests/swfs/avm2/is_prototype_of/output.txt b/core/tests/swfs/avm2/is_prototype_of/output.txt new file mode 100644 index 000000000..3d3f2dc80 --- /dev/null +++ b/core/tests/swfs/avm2/is_prototype_of/output.txt @@ -0,0 +1,13 @@ + +//ES4Class.prototype.isPrototypeOf(es4inst); +true +//Object.prototype.isPrototypeOf(es4inst); +true +//ES3Class.prototype.isPrototypeOf(es4inst); +false +//ES4Class.prototype.isPrototypeOf(es3inst); +false +//Object.prototype.isPrototypeOf(es3inst); +true +//ES3Class.prototype.isPrototypeOf(es3inst); +true diff --git a/core/tests/swfs/avm2/is_prototype_of/test.fla b/core/tests/swfs/avm2/is_prototype_of/test.fla new file mode 100644 index 0000000000000000000000000000000000000000..e8422682499736c841d221c3be55563405f47944 GIT binary patch literal 3985 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 literal 0 HcmV?d00001 diff --git a/core/tests/swfs/avm2/is_prototype_of/test.swf b/core/tests/swfs/avm2/is_prototype_of/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..ddbacb6f4813bfacce70ff0385877a91894143af GIT binary patch literal 896 zcmV-`1AqKOS5qsO1^@tfoSjtNa@s}|-XBS;6=1;p+A+-^Y2!G9@;P?|vPx7EC_2>P^~{}ylmH-Ln{aX6-He=Hm=Y+m$W_y z4?<2J+e54I%5vN{&WH^im+1?u?OP+Zz4ZmJWve98DXo*=STEH6ORdf`=B_D6okvP8 zM@n%+FsSvNU_7+W=qqpHu;$Pi7p~2#M5U_p4ygO5ZZC8^m#|>Raf6V{x{yB{HabnO z&pQ68Z4X(e=lQH7LI$1Sy&ZI{$>>SP3696U7kc5@m>qle?rvPQ9Qsy|J=PZutS#JX zPVmbdx9o>;*3DhI@JLORh85kc{CebklOpP0Q$*}snV({9`4k)R#I0EU{=Pu%p6`sq`=4=M){@bxM`%cJq{>R945=B%d zGA$>H$>K^mQ%b70id6|hh%v-;jX*-6O0Y)c6j9Pd%@VvyV2>Qj z5m+K{jjm$??-A_*QNAV0cSLzelua%A8z8=LETveACG(|37(+x62N+R_`$)1%fC?1| z2;^H8fMgl+tylt(C_n{N{9QEhpiq(^5}6>B&x^Cf!6n2Jo*En?2qjsY8q-6-$;yF9 zwIHQWNEsuD|AAA3>&Q%Wkn8D`wgx zM+8{fEMsOKms=S)%bJ-kwzFNjzY2xE%83mDa-2X*M4l5B0ScTTOGJqi-w05SLuoOw z#);bktjD3|#4S$T5nv+@C5ZhD{NwMxe&$_={0O5S5D2wIn!oVf88+b&1e-I7n^nxs z#mm;1x%2xoSOrsCY30xiahCG7(ygh%faplx=oXA_(dd?pZrSL{{C