From 3b5411547a6d4d441a10b5f722cbf3da363869f5 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Thu, 3 Sep 2020 21:47:26 -0400 Subject: [PATCH] avm2: Implement `in` --- core/src/avm2/activation.rs | 19 ++++ core/tests/regression_tests.rs | 1 + core/tests/swfs/avm2/in/Test.as | 177 +++++++++++++++++++++++++++++ core/tests/swfs/avm2/in/output.txt | 102 +++++++++++++++++ core/tests/swfs/avm2/in/test.fla | Bin 0 -> 3983 bytes core/tests/swfs/avm2/in/test.swf | Bin 0 -> 2358 bytes 6 files changed, 299 insertions(+) create mode 100644 core/tests/swfs/avm2/in/Test.as create mode 100644 core/tests/swfs/avm2/in/output.txt create mode 100644 core/tests/swfs/avm2/in/test.fla create mode 100644 core/tests/swfs/avm2/in/test.swf diff --git a/core/src/avm2/activation.rs b/core/src/avm2/activation.rs index 216e8e814..9bee056e8 100644 --- a/core/src/avm2/activation.rs +++ b/core/src/avm2/activation.rs @@ -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, 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, Error> { let object = self.context.avm2.pop().coerce_to_object(self)?; let scope_stack = self.scope(); diff --git a/core/tests/regression_tests.rs b/core/tests/regression_tests.rs index 86b7132d4..3f1cfe491 100644 --- a/core/tests/regression_tests.rs +++ b/core/tests/regression_tests.rs @@ -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. diff --git a/core/tests/swfs/avm2/in/Test.as b/core/tests/swfs/avm2/in/Test.as new file mode 100644 index 000000000..8db2bb63c --- /dev/null +++ b/core/tests/swfs/avm2/in/Test.as @@ -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); \ No newline at end of file diff --git a/core/tests/swfs/avm2/in/output.txt b/core/tests/swfs/avm2/in/output.txt new file mode 100644 index 000000000..a643aba1f --- /dev/null +++ b/core/tests/swfs/avm2/in/output.txt @@ -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 diff --git a/core/tests/swfs/avm2/in/test.fla b/core/tests/swfs/avm2/in/test.fla new file mode 100644 index 0000000000000000000000000000000000000000..9117e9f0beb567f07719301e8775ac7b9d90c7dc GIT binary patch literal 3983 zcmbtXc{r5&7oTj|jhzr<>}8FNl#G2zWE--@7)FhC#y0i{V@p}GFHyG8*eZmvFHx3K zT!m&z%6csk`i<+h-RE}y`JMMU&-;Gg@A;hXdEV!o_xXHG3@NEN003G5AfVjBM1aYe zk`4d>>^u1t0E0kdWCC1JCZ@(#*3z10N+!RAlOw*{e)u_k4O6J8we0Vs_7fXvn?t4b z&+Gh07%Mr<%hw6zhDKr#?p`QIav^_*Q_#}>Rcdv>qSq%106?A|0AL}9YZ)79dBT0& z5gz1<-BIw>yVJ}B+Z4g`@Wf)T25XyLAI$~85bmMj@MKffwUB+n~KUKZt zgHKWHG>U3xf1QbbCx`ZP7Jt~th^*;now=0a8kLLU@w;O)6whvLUp?MYf3lclY6&tY z3f|(bC32C50qou2n?hyK1=c90BI?9pxxz=y`nB|~eQbJ`2+7M&ypt5pB_ETd$aHyQ z(kCZcRm|*e#xE)w2ay&Rxl={7&}suiu0ND8cV;zq%WN9)KgWd`6!98w%U-j_#Bd3{ zUIZ2xQA+V^0IR(k0OjR8=~Sz8+|o-|G|TA1tV!}xUCaBHP*VRA~^(n!!k%c;DSGp#a*6i|id%4Pz8J2$G&F+IeQI+MfNh!G zDrD(EOD7K{T~}X+H0QER<|_8Ii#GKg5+>qYU;+RqCk=TiO7rDOdE6|cv@Pz|F_AOE zNUM4C4aNJ_-WNpcsOLBH(?pRv+A(i5dE#7`iW?Z)P|*tVcPXz4a_CpQQxl)TXJDDt zt!UkC^&v#%3Hy<2CNA0KzW4hn^Zb(ZaSVG3dXZOHhnhbA*_ItN4v|In5%}dpvB8*N zt!IsUD>H9D3=U?3Tkl>4x7w$Hv9=4eVqaVRSE~XKi-QFDwT(<|3OaOsVs2b+8!8G? z9WdVc!*63xHOCD{r%Ph=PU>5Q7Fc!hx;)62XXkVK@^GRKX9VeoW-E7uMX6v0lKsTf z`0;Z(>E*Aa#uh?^)K@OQny?6!$G_IU_Yzzyj-N0>Sui|e!MpjhX=*BCrJ|=g!FEf! zsDwtG1#;bdhY|18%892BVzaU9On1LN_Fx$=WckG&SetESvWd}tpT^Z`@boBOZk&?$ z3f3N2RNIq<$e3_+(haRypC4@eay?*!`(WHC{+?m-EPOXk^3(Tmb4OqtogFcb`{VHq zaxhEHDY-&BhXH_6egJ@-3^6$vJu?Ib_?8rF7Re0CpupWeTNqx=Yfr1CR{zdin7jxEOUK4gNL-{-KW%WH z@xc)1UMk*hJclD7*Z}dlPuai^@NuwhBHg|KG7;U0ua#S~ znaUE}j=WeqiX0!BT=%G)bbs(Pro$1!lLI5kA2&Wzy0{ZOotU*=J7IlgtW=5bD021V z;DiLqk7mKLHfR{t0<+UCRb`(Kb|_apR(8erO-YsfeEW`{E3sofwK3gvd@HYU??VLE zrm72;e5yxk#i9HOi+oHo)hza?8u%uyzT@Yhj`XV^G3O~;S9I-m)^{4kj<`l6dE1qv zTxr3de3^#jwI+c&*T)s3hTrlQ zQtJ1`QGrY*BkbKGpadNCMil-e?OGI`D`7KAo;5G;nFPR*fl&!7#b{qm+rW5-e(_cg zN1C^~8S@!fPJuah;}X-76fJv_bsR*k*a@aC>1`3uz6+EzftBsP@aOC=>utlXf|`8X z^G}v3$<+9K4bLLBn>u{O$li1LBPByN(vpGWm?;64aXkGr^2MR?x|O)=OY^CJP zBin2djsQ(Jv8%`P>9c$~KT}nr`58VaR8R{S=a@&?Ga!h3Q9Pm}@8~t8*A^q=&HD6- zu}fDCK0j45pbcZn+BMTGj{t?9L#}B#3x-eQ5DS;YV%^Ru!;cKq--1-)h}Ku_dmwi4 zX{pxm`An?OWO=1+xq@P?L)V>%P7ZY>}E-e7x%+N^a3 zn?&Nnky7RP6FF+ZnL|QG@15~3dSf-Oo=<&txr=rvnN1Ry+DylwW4JbB@4O8LRSTaq zmFe?)RWH*sTjhOE_{}g%Pg#<9uaHAcm{E9@;$b1j9YALao1?YS5{5LA`uQS00bU<*i$@wyB?Mdc&&}qR|0Y zkbGqnras(HZv#2A`ce9ABXIC3ie-vUy@V1>Zg+neAAZ8&*;@Rz`;+EgpOkY#!vy2{ z&6^v1;sryz6Y6iFzV99}2IuoPu`Vb_77kD9jEwzfA`--hj3o4sbIt18VKgXLL^ z3}Er$%^86Qnlo9Wpd_|Vxw?_X%v8z9 zYs6&rR?13s15gJy#rY&vJ&;R(X1b&mTB<9x42yoFaCb9~@+9fwoLlUS6^*^&n&V+b zH=yW8p08)}N;xDTQ+U>Rrvdb zueU$NYi%X1I0Q7E_3H{)O5|RXb_NA^Z>wFne@aDs99p~JdvS`U7%aDa8iy8_n%LM8 zXpv4}y`Ekp%+hB-H9*t9IH{KYxK-rO{DtNgoqj3%XP$Ped$#~k<^s-MY$F2m%rezy zi)3cj{bC?oER_T;dd`;4Xv3U93RRIwnH61XH&0^Z_UXlpG_(H)#>(z`j9}ujQTH4=Eeu zRM9cs38YCBPPFd|j+brn2t>MXy;xEXvl@M~Rd^Am!6iKt4m+0m)VFP;$9OXEIeNWh z=dzHqb7gYTmuv60jhf3_*h0aXXW&f)Pwy2Y!7mB%VRn{PuxGTd7cObljz0+8tTLH? z4o<2d@QZGdf6HfOlLm#_pW6~)N+xT=yz@F}?OC3ZRj2IMLDt5QTz=cf!=PQbnNn$f zz}cKbJuOc!XTv!x#NGw%d{r7G86P@JB(79j>9cyjPa1ihhKmA$o z8(BEe2;a#C`GIYpUwAsXp%6cFg@gESnj*0JxgMEU0QP;KTsXOT$eIPZYazT49?mjw zM>rDUN`6f|ObMU{(2!Fq0#1?F`_@uP<|4l+j;5P4(Y)lHecx9c?rvmO6X=C-^zuTv z!5uMfo*uG(}@uKF8KzEzO@A1dqH*}vnSKfs-o zKb8C|6aDr4e{#_uDK^O|{)L(TR}K69`NKpQ|Gis({p|nj*B^LuGX7t>_gewq8vdU> d`Xj+KIl;G%H8G^7+25fjU&&-0E6B9J`X5A2KimKS literal 0 HcmV?d00001 diff --git a/core/tests/swfs/avm2/in/test.swf b/core/tests/swfs/avm2/in/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..fbdcef2daea7bc3d0e2d654e06963001993e5e8b GIT binary patch literal 2358 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 cqwCS