[Swfdec] Branch 'as' - 7 commits - libswfdec/swfdec_as_context.c libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h libswfdec/swfdec_as_super.c libswfdec/swfdec_as_super.h libswfdec/swfdec_as_with.c test/trace

Benjamin Otte company at kemper.freedesktop.org
Sat Jul 7 09:30:16 PDT 2007


 libswfdec/swfdec_as_context.c               |    7 +-
 libswfdec/swfdec_as_interpret.c             |   35 ++++++-----
 libswfdec/swfdec_as_object.c                |   12 +++
 libswfdec/swfdec_as_object.h                |    5 -
 libswfdec/swfdec_as_super.c                 |   46 +++++++++++++-
 libswfdec/swfdec_as_super.h                 |    2 
 libswfdec/swfdec_as_with.c                  |    2 
 test/trace/Makefile.am                      |   32 ++++++++++
 test/trace/extends-constructors-6.swf       |binary
 test/trace/extends-constructors-6.swf.trace |    8 ++
 test/trace/extends-constructors-7.swf       |binary
 test/trace/extends-constructors-7.swf.trace |    8 ++
 test/trace/extends-constructors-8.swf       |binary
 test/trace/extends-constructors-8.swf.trace |    8 ++
 test/trace/extends-constructors.as          |   72 ++++++++++++++++++++++
 test/trace/super-different-5.swf            |binary
 test/trace/super-different-5.swf.trace      |    4 +
 test/trace/super-different-6.swf            |binary
 test/trace/super-different-6.swf.trace      |   12 +++
 test/trace/super-different-7.swf            |binary
 test/trace/super-different-7.swf.trace      |   12 +++
 test/trace/super-different-8.swf            |binary
 test/trace/super-different-8.swf.trace      |   12 +++
 test/trace/super-different.as               |   66 ++++++++++++++++++++
 test/trace/super-missing-5.swf              |binary
 test/trace/super-missing-5.swf.trace        |    3 
 test/trace/super-missing-6.swf              |binary
 test/trace/super-missing-6.swf.trace        |    9 ++
 test/trace/super-missing-7.swf              |binary
 test/trace/super-missing-7.swf.trace        |    8 ++
 test/trace/super-missing-8.swf              |binary
 test/trace/super-missing-8.swf.trace        |    8 ++
 test/trace/super-missing.as                 |   52 ++++++++++++++++
 test/trace/super-reference-6.swf            |binary
 test/trace/super-reference-6.swf.trace      |   25 +++++++
 test/trace/super-reference-7.swf            |binary
 test/trace/super-reference-7.swf.trace      |   24 +++++++
 test/trace/super-reference-8.swf            |binary
 test/trace/super-reference-8.swf.trace      |   24 +++++++
 test/trace/super-reference.as               |   89 ++++++++++++++++++++++++++++
 40 files changed, 562 insertions(+), 23 deletions(-)

New commits:
diff-tree aab61502175bd018e7de1c01b8ef86b909d932a0 (from a510f23c72c980303c86f869023237bc593fdfe0)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Jul 7 17:30:17 2007 +0100

    add a test for not overwritten functions in subclasses

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index d72d5e2..695cbba 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -779,6 +779,15 @@ EXTRA_DIST = \
 	super-different-7.swf.trace \
 	super-different-8.swf \
 	super-different-8.swf.trace \
+	super-missing.as \
+	super-missing-5.swf \
+	super-missing-5.swf.trace \
+	super-missing-6.swf \
+	super-missing-6.swf.trace \
+	super-missing-7.swf \
+	super-missing-7.swf.trace \
+	super-missing-8.swf \
+	super-missing-8.swf.trace \
 	super-reference.as \
 	super-reference-6.swf \
 	super-reference-6.swf.trace \
diff --git a/test/trace/super-missing-5.swf b/test/trace/super-missing-5.swf
new file mode 100644
index 0000000..7d6b079
Binary files /dev/null and b/test/trace/super-missing-5.swf differ
diff --git a/test/trace/super-missing-5.swf.trace b/test/trace/super-missing-5.swf.trace
new file mode 100644
index 0000000..3db6946
--- /dev/null
+++ b/test/trace/super-missing-5.swf.trace
@@ -0,0 +1,3 @@
+Check how functions that aren't overwritten are handled when called via super
+4
+foo: 4
diff --git a/test/trace/super-missing-6.swf b/test/trace/super-missing-6.swf
new file mode 100644
index 0000000..8e4d85d
Binary files /dev/null and b/test/trace/super-missing-6.swf differ
diff --git a/test/trace/super-missing-6.swf.trace b/test/trace/super-missing-6.swf.trace
new file mode 100644
index 0000000..1f60a12
--- /dev/null
+++ b/test/trace/super-missing-6.swf.trace
@@ -0,0 +1,9 @@
+Check how functions that aren't overwritten are handled when called via super
+1
+2
+3
+4
+foo: 1
+foo: 1
+foo: 1
+foo: 4
diff --git a/test/trace/super-missing-7.swf b/test/trace/super-missing-7.swf
new file mode 100644
index 0000000..6a1bbfd
Binary files /dev/null and b/test/trace/super-missing-7.swf differ
diff --git a/test/trace/super-missing-7.swf.trace b/test/trace/super-missing-7.swf.trace
new file mode 100644
index 0000000..f72f2f9
--- /dev/null
+++ b/test/trace/super-missing-7.swf.trace
@@ -0,0 +1,8 @@
+Check how functions that aren't overwritten are handled when called via super
+1
+2
+3
+4
+foo: 1
+foo: 1
+foo: 4
diff --git a/test/trace/super-missing-8.swf b/test/trace/super-missing-8.swf
new file mode 100644
index 0000000..4172ebe
Binary files /dev/null and b/test/trace/super-missing-8.swf differ
diff --git a/test/trace/super-missing-8.swf.trace b/test/trace/super-missing-8.swf.trace
new file mode 100644
index 0000000..f72f2f9
--- /dev/null
+++ b/test/trace/super-missing-8.swf.trace
@@ -0,0 +1,8 @@
+Check how functions that aren't overwritten are handled when called via super
+1
+2
+3
+4
+foo: 1
+foo: 1
+foo: 4
diff --git a/test/trace/super-missing.as b/test/trace/super-missing.as
new file mode 100644
index 0000000..2bd6fe7
--- /dev/null
+++ b/test/trace/super-missing.as
@@ -0,0 +1,52 @@
+// makeswf -v 7 -s 200x150 -r 1 -o super-missing.swf super-missing.as
+
+trace ("Check how functions that aren't overwritten are handled when called via super");
+
+function One () {
+  trace (1);
+};
+function Two () {
+  super ();
+  trace (2);
+};
+function Three () {
+  super ();
+  trace (3);
+};
+function Four () {
+  super ();
+  trace (4);
+};
+asm {
+  push "Two"
+  getvariable
+  push "One"
+  getvariable
+  extends
+};
+asm {
+  push "Three"
+  getvariable
+  push "Two"
+  getvariable
+  extends
+};
+asm {
+  push "Four"
+  getvariable
+  push "Three"
+  getvariable
+  extends
+};
+One.prototype.foo = function () {
+  super.foo ();
+  trace ("foo: 1");
+};
+Four.prototype.foo = function () {
+  super.foo ();
+  trace ("foo: 4");
+};
+x = new Four ();
+x.foo ();
+
+loadMovie ("FSCommand:quit", "");
diff-tree a510f23c72c980303c86f869023237bc593fdfe0 (from cb0a5b3d2714123e50f45869100e4665c4100379)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Jul 7 17:28:02 2007 +0100

    ad a test for calling different named functions via super

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 9474502..d72d5e2 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -770,6 +770,15 @@ EXTRA_DIST = \
 	super-calls-7.swf.trace \
 	super-calls-8.swf \
 	super-calls-8.swf.trace \
+	super-different.as \
+	super-different-5.swf \
+	super-different-5.swf.trace \
+	super-different-6.swf \
+	super-different-6.swf.trace \
+	super-different-7.swf \
+	super-different-7.swf.trace \
+	super-different-8.swf \
+	super-different-8.swf.trace \
 	super-reference.as \
 	super-reference-6.swf \
 	super-reference-6.swf.trace \
diff --git a/test/trace/super-different-5.swf b/test/trace/super-different-5.swf
new file mode 100644
index 0000000..3cf24ad
Binary files /dev/null and b/test/trace/super-different-5.swf differ
diff --git a/test/trace/super-different-5.swf.trace b/test/trace/super-different-5.swf.trace
new file mode 100644
index 0000000..c89f1d6
--- /dev/null
+++ b/test/trace/super-different-5.swf.trace
@@ -0,0 +1,4 @@
+Check calls to differently named functions on super
+4
+foo: x
+bla: x
diff --git a/test/trace/super-different-6.swf b/test/trace/super-different-6.swf
new file mode 100644
index 0000000..323d467
Binary files /dev/null and b/test/trace/super-different-6.swf differ
diff --git a/test/trace/super-different-6.swf.trace b/test/trace/super-different-6.swf.trace
new file mode 100644
index 0000000..f2db9cf
--- /dev/null
+++ b/test/trace/super-different-6.swf.trace
@@ -0,0 +1,12 @@
+Check calls to differently named functions on super
+1
+2
+3
+4
+bla: 1
+foo: 2
+bla: 3
+foo: x
+bla: 1
+foo: 2
+bla: x
diff --git a/test/trace/super-different-7.swf b/test/trace/super-different-7.swf
new file mode 100644
index 0000000..a3e5912
Binary files /dev/null and b/test/trace/super-different-7.swf differ
diff --git a/test/trace/super-different-7.swf.trace b/test/trace/super-different-7.swf.trace
new file mode 100644
index 0000000..f2db9cf
--- /dev/null
+++ b/test/trace/super-different-7.swf.trace
@@ -0,0 +1,12 @@
+Check calls to differently named functions on super
+1
+2
+3
+4
+bla: 1
+foo: 2
+bla: 3
+foo: x
+bla: 1
+foo: 2
+bla: x
diff --git a/test/trace/super-different-8.swf b/test/trace/super-different-8.swf
new file mode 100644
index 0000000..508e675
Binary files /dev/null and b/test/trace/super-different-8.swf differ
diff --git a/test/trace/super-different-8.swf.trace b/test/trace/super-different-8.swf.trace
new file mode 100644
index 0000000..f2db9cf
--- /dev/null
+++ b/test/trace/super-different-8.swf.trace
@@ -0,0 +1,12 @@
+Check calls to differently named functions on super
+1
+2
+3
+4
+bla: 1
+foo: 2
+bla: 3
+foo: x
+bla: 1
+foo: 2
+bla: x
diff --git a/test/trace/super-different.as b/test/trace/super-different.as
new file mode 100644
index 0000000..155d1fd
--- /dev/null
+++ b/test/trace/super-different.as
@@ -0,0 +1,66 @@
+// makeswf -v 7 -s 200x150 -r 1 -o super-different.swf super-different.as
+
+trace ("Check calls to differently named functions on super");
+function One () {
+  trace (1);
+};
+function Two () {
+  super ();
+  trace (2);
+};
+function Three () {
+  super ();
+  trace (3);
+};
+function Four () {
+  super ();
+  trace (4);
+};
+asm {
+  push "Two"
+  getvariable
+  push "One"
+  getvariable
+  extends
+};
+asm {
+  push "Three"
+  getvariable
+  push "Two"
+  getvariable
+  extends
+};
+asm {
+  push "Four"
+  getvariable
+  push "Three"
+  getvariable
+  extends
+};
+One.prototype.foo = function () {
+  trace ("foo: 1");
+};
+One.prototype.bla = function () {
+  trace ("bla: 1");
+};
+Two.prototype.foo = function () {
+  super.bla ();
+  trace ("foo: 2");
+};
+Three.prototype.bla = function () {
+  super.foo ();
+  trace ("bla: 3");
+};
+x = new Four ();
+x.foo = function () {
+  super.bla ();
+  trace ("foo: x");
+};
+x.bla = function () {
+  super.foo ();
+  trace ("bla: x");
+};
+x.foo ();
+x.bla ();
+
+loadMovie ("FSCommand:quit", "");
diff-tree cb0a5b3d2714123e50f45869100e4665c4100379 (from 96c3f00fcd2a7333f82399b370de89f2e2fc4e48)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Jul 7 17:27:04 2007 +0100

    add a test to see which prototype is referenced by super

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 4115b34..9474502 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -770,6 +770,13 @@ EXTRA_DIST = \
 	super-calls-7.swf.trace \
 	super-calls-8.swf \
 	super-calls-8.swf.trace \
+	super-reference.as \
+	super-reference-6.swf \
+	super-reference-6.swf.trace \
+	super-reference-7.swf \
+	super-reference-7.swf.trace \
+	super-reference-8.swf \
+	super-reference-8.swf.trace \
 	targetpath.as \
 	targetpath-5.swf \
 	targetpath-5.swf.trace \
diff --git a/test/trace/super-reference-6.swf b/test/trace/super-reference-6.swf
new file mode 100644
index 0000000..17aadb4
Binary files /dev/null and b/test/trace/super-reference-6.swf differ
diff --git a/test/trace/super-reference-6.swf.trace b/test/trace/super-reference-6.swf.trace
new file mode 100644
index 0000000..bd485ee
--- /dev/null
+++ b/test/trace/super-reference-6.swf.trace
@@ -0,0 +1,25 @@
+Check which object super refers to
+1
+2
+3
+4
+foo: 1
+foo: 2
+foo: 3
+bla
+3
+foo: 1
+foo: 2
+foo: 3
+bla
+3
+foo: 1
+foo: 2
+foo: 3
+foo: 5
+3
+foo: 1
+foo: 2
+foo: 3
+foo: 5
+3
diff --git a/test/trace/super-reference-7.swf b/test/trace/super-reference-7.swf
new file mode 100644
index 0000000..40c5ed9
Binary files /dev/null and b/test/trace/super-reference-7.swf differ
diff --git a/test/trace/super-reference-7.swf.trace b/test/trace/super-reference-7.swf.trace
new file mode 100644
index 0000000..b7c101e
--- /dev/null
+++ b/test/trace/super-reference-7.swf.trace
@@ -0,0 +1,24 @@
+Check which object super refers to
+1
+2
+3
+4
+foo: 1
+foo: 2
+bla
+2
+foo: 1
+foo: 2
+foo: 3
+bla
+3
+foo: 1
+foo: 2
+foo: 3
+foo: 5
+3
+foo: 1
+foo: 2
+foo: 3
+foo: 5
+3
diff --git a/test/trace/super-reference-8.swf b/test/trace/super-reference-8.swf
new file mode 100644
index 0000000..f7dcd95
Binary files /dev/null and b/test/trace/super-reference-8.swf differ
diff --git a/test/trace/super-reference-8.swf.trace b/test/trace/super-reference-8.swf.trace
new file mode 100644
index 0000000..b7c101e
--- /dev/null
+++ b/test/trace/super-reference-8.swf.trace
@@ -0,0 +1,24 @@
+Check which object super refers to
+1
+2
+3
+4
+foo: 1
+foo: 2
+bla
+2
+foo: 1
+foo: 2
+foo: 3
+bla
+3
+foo: 1
+foo: 2
+foo: 3
+foo: 5
+3
+foo: 1
+foo: 2
+foo: 3
+foo: 5
+3
diff --git a/test/trace/super-reference.as b/test/trace/super-reference.as
new file mode 100644
index 0000000..fef6fe6
--- /dev/null
+++ b/test/trace/super-reference.as
@@ -0,0 +1,89 @@
+// makeswf -v 7 -s 200x150 -r 1 -o super-reference.swf super-reference.as
+
+trace ("Check which object super refers to");
+
+function One () {
+  trace (1);
+};
+function Two () {
+  super ();
+  trace (2);
+};
+function Three () {
+  super ();
+  trace (3);
+};
+function Four () {
+  super ();
+  trace (4);
+};
+asm {
+  push "Two"
+  getvariable
+  push "One"
+  getvariable
+  extends
+};
+asm {
+  push "Three"
+  getvariable
+  push "Two"
+  getvariable
+  extends
+};
+asm {
+  push "Four"
+  getvariable
+  push "Three"
+  getvariable
+  extends
+};
+function check (x) {
+  if (x.foo === One.prototype.foo)
+    trace (1);
+  else if (x.foo === Two.prototype.foo)
+    trace (2);
+  else if (x.foo === Three.prototype.foo)
+    trace (3);
+  else if (x.foo === Four.prototype.foo)
+    trace (4);
+  else
+    trace ("5+");    
+};
+One.prototype.foo = function () {
+  trace ("foo: 1");
+};
+Two.prototype.foo = function () {
+  super.foo ();
+  trace ("foo: 2");
+};
+Three.prototype.foo = function () {
+  super.foo ();
+  trace ("foo: 3");
+};
+Four.prototype.foo = function () {
+  super.foo ();
+  trace ("foo: 4");
+};
+Two.prototype.bla = function () {
+  super.foo ();
+  trace ("blabla");
+  check (super);
+};
+Three.prototype.bla = function () {
+  super.foo ();
+  trace ("bla");
+  check (super);
+};
+x = new Four ();
+x.foo = function () {
+  super.foo ();
+  trace ("foo: 5");
+  check (super);
+};
+x.bla ();
+x.bla.call (x);
+x.foo ();
+x.foo.call (x);
+
+loadMovie ("FSCommand:quit", "");
diff-tree 96c3f00fcd2a7333f82399b370de89f2e2fc4e48 (from a2c9ed6d7a22fa26d5581e9e42e31ffb0b82c3d4)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Jul 7 17:25:27 2007 +0100

    add a test that checks the constructor properties on prototypes after ActionExtends

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index f537b21..4115b34 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -229,6 +229,13 @@ EXTRA_DIST = \
 	export-case-6.swf.trace \
 	export-case-7.swf \
 	export-case-7.swf.trace \
+	extends-constructors.as \
+	extends-constructors-6.swf \
+	extends-constructors-6.swf.trace \
+	extends-constructors-7.swf \
+	extends-constructors-7.swf.trace \
+	extends-constructors-8.swf \
+	extends-constructors-8.swf.trace \
 	extends-simple.swf \
 	extends-simple.swf.trace \
 	extends-super.swf \
diff --git a/test/trace/extends-constructors-6.swf b/test/trace/extends-constructors-6.swf
new file mode 100644
index 0000000..b035036
Binary files /dev/null and b/test/trace/extends-constructors-6.swf differ
diff --git a/test/trace/extends-constructors-6.swf.trace b/test/trace/extends-constructors-6.swf.trace
new file mode 100644
index 0000000..cf826c8
--- /dev/null
+++ b/test/trace/extends-constructors-6.swf.trace
@@ -0,0 +1,8 @@
+One
+undefined
+One
+One
+One
+Two
+One
+Three
diff --git a/test/trace/extends-constructors-7.swf b/test/trace/extends-constructors-7.swf
new file mode 100644
index 0000000..5b80340
Binary files /dev/null and b/test/trace/extends-constructors-7.swf differ
diff --git a/test/trace/extends-constructors-7.swf.trace b/test/trace/extends-constructors-7.swf.trace
new file mode 100644
index 0000000..cf826c8
--- /dev/null
+++ b/test/trace/extends-constructors-7.swf.trace
@@ -0,0 +1,8 @@
+One
+undefined
+One
+One
+One
+Two
+One
+Three
diff --git a/test/trace/extends-constructors-8.swf b/test/trace/extends-constructors-8.swf
new file mode 100644
index 0000000..58d6abe
Binary files /dev/null and b/test/trace/extends-constructors-8.swf differ
diff --git a/test/trace/extends-constructors-8.swf.trace b/test/trace/extends-constructors-8.swf.trace
new file mode 100644
index 0000000..cf826c8
--- /dev/null
+++ b/test/trace/extends-constructors-8.swf.trace
@@ -0,0 +1,8 @@
+One
+undefined
+One
+One
+One
+Two
+One
+Three
diff --git a/test/trace/extends-constructors.as b/test/trace/extends-constructors.as
new file mode 100644
index 0000000..dc6e393
--- /dev/null
+++ b/test/trace/extends-constructors.as
@@ -0,0 +1,72 @@
+// makeswf -v 7 -s 200x150 -r 1 -o extends-constructors.swf extends-constructors.as
+
+function One () {
+  trace (1);
+};
+function Two () {
+  super ();
+  trace (2);
+};
+function Three () {
+  super ();
+  trace (3);
+};
+function Four () {
+  super ();
+  trace (4);
+};
+asm {
+  push "Two"
+  getvariable
+  push "One"
+  getvariable
+  extends
+};
+asm {
+  push "Three"
+  getvariable
+  push "Two"
+  getvariable
+  extends
+};
+asm {
+  push "Four"
+  getvariable
+  push "Three"
+  getvariable
+  extends
+};
+One.prototype.foo = function () {
+  trace (super);
+  trace ("foo: 1");
+};
+Two.prototype.foo = function () {
+  super.foo ();
+  trace ("foo: 2");
+};
+Four.prototype.foo = function () {
+  super.foo ();
+  trace ("foo: 4");
+};
+function check_name (fun) {
+  if (fun === One)
+    trace ("One");
+  else if (fun === Two)
+    trace ("Two");
+  else if (fun === Three)
+    trace ("Three");
+  else if (fun === Four)
+    trace ("Four");
+  else
+    trace (fun);
+};
+check_name (One.prototype.constructor);
+check_name (One.prototype.__constructor__);
+check_name (Two.prototype.constructor);
+check_name (Two.prototype.__constructor__);
+check_name (Three.prototype.constructor);
+check_name (Three.prototype.__constructor__);
+check_name (Four.prototype.constructor);
+check_name (Four.prototype.__constructor__);
+
+loadMovie ("FSCommand:quit", "");
diff-tree a2c9ed6d7a22fa26d5581e9e42e31ffb0b82c3d4 (from f09bcc6abc2629a38f1524d647ec5ee1e6c2b612)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Jul 7 17:18:00 2007 +0100

    skip unknown actions
    
    This may be an interesting patch because Swfdec doesn't abort on weird code
    anymore but just continues running. And it also keeps going for unknown
    actions.

diff --git a/libswfdec/swfdec_as_context.c b/libswfdec/swfdec_as_context.c
index 9257371..0d50224 100644
--- a/libswfdec/swfdec_as_context.c
+++ b/libswfdec/swfdec_as_context.c
@@ -680,10 +680,11 @@ start:
     }
     /* check action is valid */
     if (spec->exec[version] == NULL) {
-      SWFDEC_ERROR ("cannot interpret action %3u 0x%02X %s for version %u", action,
+      SWFDEC_WARNING ("cannot interpret action %3u 0x%02X %s for version %u, skipping it", action,
 	  action, spec->name ? spec->name : "Unknown", script->version);
-      /* FIXME: figure out what flash player does here */
-      goto error;
+      frame->pc = pc = nextpc;
+      check_scope = TRUE;
+      continue;
     }
     if (spec->remove > 0) {
       swfdec_as_stack_ensure_size (stack, spec->remove);
diff-tree f09bcc6abc2629a38f1524d647ec5ee1e6c2b612 (from d4d1998c7e04a7651d89a2c3fb56eb90ba3d474d)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Jul 7 17:14:29 2007 +0100

    rewrite super handling
    
    Super seems to be handled in a way stupid (and buggy) way. This seems to make
    all the testcases (soon to be committed) work.

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 2cabb64..7ade8ca 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -560,7 +560,7 @@ swfdec_action_trace (SwfdecAsContext *cx
 /* stack looks like this: [ function, this, arg1, arg2, ... ] */
 /* stack must be at least 2 elements big */
 static gboolean
-swfdec_action_call (SwfdecAsContext *cx, guint n_args, gboolean use_super)
+swfdec_action_call (SwfdecAsContext *cx, guint n_args)
 {
   SwfdecAsFunction *fun;
   SwfdecAsObject *thisp;
@@ -592,11 +592,9 @@ swfdec_action_call (SwfdecAsContext *cx,
     swfdec_as_stack_pop_n (frame->stack, n_args);
   swfdec_as_function_call (fun, thisp, n_args, swfdec_as_stack_peek (frame->stack, 0), 
       swfdec_as_stack_peek (frame->stack, 1));
-  if (use_super) {
-    if (cx->frame->super && SWFDEC_AS_SUPER (frame->super)->object) {
-      SWFDEC_LOG ("replacing super object on frame");
-      SWFDEC_AS_SUPER (cx->frame->super)->object = SWFDEC_AS_SUPER (frame->super)->object->prototype;
-    }
+  if (SWFDEC_IS_AS_SUPER (fun)) {
+    SWFDEC_LOG ("replacing super object on frame");
+    swfdec_as_super_replace (SWFDEC_AS_SUPER (fun), NULL);
   }
   return TRUE;
 
@@ -631,8 +629,7 @@ swfdec_action_call_function (SwfdecAsCon
     SWFDEC_AS_VALUE_SET_NULL (thisp);
     SWFDEC_AS_VALUE_SET_UNDEFINED (fun);
   }
-  if (!swfdec_action_call (cx, n_args, SWFDEC_AS_VALUE_IS_OBJECT (fun) && 
-	SWFDEC_IS_AS_SUPER (SWFDEC_AS_VALUE_GET_OBJECT (fun)))) {
+  if (!swfdec_action_call (cx, n_args)) {
     SWFDEC_ERROR ("no function named %s", name);
   }
 }
@@ -645,7 +642,6 @@ swfdec_action_call_method (SwfdecAsConte
   SwfdecAsObject *obj;
   guint n_args;
   const char *name = NULL;
-  gboolean use_super = FALSE;
   
   swfdec_as_stack_ensure_size (frame->stack, 3);
   obj = swfdec_as_value_to_object (cx, swfdec_as_stack_peek (frame->stack, 2));
@@ -656,8 +652,6 @@ swfdec_action_call_method (SwfdecAsConte
     SWFDEC_AS_VALUE_SET_STRING (val, SWFDEC_AS_STR_EMPTY);
   }
   if (obj) {
-    if (SWFDEC_IS_AS_SUPER (obj))
-      use_super = TRUE;
     if (SWFDEC_AS_VALUE_IS_STRING (val) && 
 	SWFDEC_AS_VALUE_GET_STRING (val) == SWFDEC_AS_STR_EMPTY) {
       SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (frame->stack, 3));
@@ -674,7 +668,22 @@ swfdec_action_call_method (SwfdecAsConte
     SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (frame->stack, 2));
   }
   swfdec_as_stack_pop (frame->stack);
-  if (!swfdec_action_call (cx, n_args, use_super)) {
+  if (swfdec_action_call (cx, n_args)) {
+    /* setup super to point to the right prototype */
+    frame = cx->frame;
+    if (SWFDEC_IS_AS_SUPER (obj)) {
+      swfdec_as_super_replace (SWFDEC_AS_SUPER (obj), name);
+    } else if (frame->super) {
+      SwfdecAsSuper *super = SWFDEC_AS_SUPER (frame->super);
+      if (name && 
+	  cx->version > 6 && 
+	  swfdec_as_object_get_variable_and_flags (frame->thisp, 
+	    name, NULL, NULL, &super->object) && 
+	  super->object == frame->thisp) {
+	super->object = super->object->prototype;
+      }
+    }
+  } else {
     SWFDEC_ERROR ("no function named %s on object %s", name ? name : "unknown", obj ? G_OBJECT_TYPE_NAME(obj) : "unknown");
   }
 }
@@ -1313,7 +1322,7 @@ swfdec_action_start_drag (SwfdecAsContex
   *swfdec_as_stack_peek (stack, 2) = *swfdec_as_stack_peek (stack, 1);
   swfdec_as_object_get_variable (SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_peek (stack, 2)),
       SWFDEC_AS_STR_startDrag, swfdec_as_stack_peek (stack, 1));
-  swfdec_action_call (cx, n_args, FALSE);
+  swfdec_action_call (cx, n_args);
   /* FIXME: the return value will still be written to this position */
   swfdec_as_stack_pop (stack);
 }
diff --git a/libswfdec/swfdec_as_super.c b/libswfdec/swfdec_as_super.c
index c9994f9..23b5993 100644
--- a/libswfdec/swfdec_as_super.c
+++ b/libswfdec/swfdec_as_super.c
@@ -72,10 +72,14 @@ swfdec_as_super_get (SwfdecAsObject *obj
   SwfdecAsSuper *super = SWFDEC_AS_SUPER (object);
 
   if (super->object == NULL) {
-    SWFDEC_WARNING ("super () called without a this object.");
+    SWFDEC_WARNING ("super.%s () called without an object.", variable);
     return FALSE;
   }
-  if (!swfdec_as_object_get_variable (super->object->prototype, variable, val))
+  if (super->object->prototype == NULL) {
+    SWFDEC_WARNING ("super.%s () called without a prototype.", variable);
+    return FALSE;
+  }
+  if (!swfdec_as_object_get_variable_and_flags (super->object->prototype, variable, val, NULL, NULL))
     return FALSE;
   *flags = 0;
   return TRUE;
@@ -139,3 +143,41 @@ swfdec_as_super_new (SwfdecAsFrame *fram
   return ret;
 }
 
+/**
+ * swfdec_as_super_replace:
+ * @super: the super object to replace from
+ * @function_name: garbage-collected name of the function that was called on 
+ *                 @super or %NULL
+ *
+ * This is an internal function used to replace the current frame's super object
+ * with the next one starting from @super. (FIXME: nice explanation!) So when 
+ * super.foo () has been called, a new frame is constructed and after that this 
+ * function is called with @super and "foo" as @function_name.
+ **/
+void
+swfdec_as_super_replace (SwfdecAsSuper *super, const char *function_name)
+{
+  SwfdecAsSuper *replace;
+  SwfdecAsContext *context;
+
+  g_return_if_fail (SWFDEC_IS_AS_SUPER (super));
+
+  context = SWFDEC_AS_OBJECT (super)->context;
+  replace = SWFDEC_AS_SUPER (context->frame->super);
+  if (replace == NULL)
+    return;
+  if (super->object == NULL || super->object->prototype == NULL) {
+    replace->object = NULL;
+    return;
+  }
+  replace->object = super->object->prototype;
+  if (function_name && context->version > 6) {
+    SwfdecAsObject *res;
+    if (swfdec_as_object_get_variable_and_flags (replace->object, 
+	  function_name, NULL, NULL, &res) &&
+	replace->object != res) {
+      while (replace->object->prototype != res)
+	replace->object = replace->object->prototype;
+    }
+  }
+}
diff --git a/libswfdec/swfdec_as_super.h b/libswfdec/swfdec_as_super.h
index 1870307..117b20a 100644
--- a/libswfdec/swfdec_as_super.h
+++ b/libswfdec/swfdec_as_super.h
@@ -49,6 +49,8 @@ GType		swfdec_as_super_get_type	(void);
 
 SwfdecAsObject *swfdec_as_super_new		(SwfdecAsFrame *	frame);
 
+void		swfdec_as_super_replace		(SwfdecAsSuper *	super,
+						 const char *		function_name);
 
 G_END_DECLS
 #endif
diff-tree d4d1998c7e04a7651d89a2c3fb56eb90ba3d474d (from 08a077a8e233015b32d4aac2742b8374434beaad)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Jul 6 17:00:22 2007 +0100

    change get_variable_and_flags to return the object with the property.

diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 8f51236..96c466c 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -389,12 +389,13 @@ swfdec_as_object_set_variable (SwfdecAsO
 
 gboolean
 swfdec_as_object_get_variable_and_flags (SwfdecAsObject *object, 
-    const char *variable, SwfdecAsValue *value, guint *flags)
+    const char *variable, SwfdecAsValue *value, guint *flags, SwfdecAsObject **pobject)
 {
   SwfdecAsObjectClass *klass;
   guint i;
   SwfdecAsValue tmp_val;
   guint tmp_flags;
+  SwfdecAsObject *tmp_pobject;
 
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), FALSE);
   g_return_val_if_fail (variable != NULL, FALSE);
@@ -403,20 +404,27 @@ swfdec_as_object_get_variable_and_flags 
     value = &tmp_val;
   if (flags == NULL)
     flags = &tmp_flags;
+  if (pobject == NULL)
+    pobject = &tmp_pobject;
 
   for (i = 0; i < 256 && object != NULL; i++) {
     klass = SWFDEC_AS_OBJECT_GET_CLASS (object);
-    if (klass->get (object, variable, value, flags))
+    if (klass->get (object, variable, value, flags)) {
+      *pobject = object;
       return TRUE;
+    }
     object = object->prototype;
   }
   if (i == 256) {
     swfdec_as_context_abort (object->context, "Prototype recursion limit exceeded");
+    *flags = 0;
+    *pobject = NULL;
     return FALSE;
   }
   //SWFDEC_WARNING ("no such variable %s", variable);
   SWFDEC_AS_VALUE_SET_UNDEFINED (value);
   *flags = 0;
+  *pobject = NULL;
   return FALSE;
 }
 
diff --git a/libswfdec/swfdec_as_object.h b/libswfdec/swfdec_as_object.h
index f6e14ed..66e919f 100644
--- a/libswfdec/swfdec_as_object.h
+++ b/libswfdec/swfdec_as_object.h
@@ -117,12 +117,13 @@ void		swfdec_as_object_set_variable	(Swf
 						 const char *		variable,
 						 const SwfdecAsValue *	value);
 #define swfdec_as_object_get_variable(object, variable, value) \
-  swfdec_as_object_get_variable_and_flags (object, variable, value, NULL)
+  swfdec_as_object_get_variable_and_flags (object, variable, value, NULL, NULL)
 gboolean	swfdec_as_object_get_variable_and_flags
 						(SwfdecAsObject *	object,
 						 const char *		variable,
 						 SwfdecAsValue *	value,
-						 guint *		flags);
+						 guint *		flags,
+						 SwfdecAsObject **	pobject);
 gboolean	swfdec_as_object_delete_variable(SwfdecAsObject *	object,
 						 const char *		variable);
 void		swfdec_as_object_set_variable_flags
diff --git a/libswfdec/swfdec_as_with.c b/libswfdec/swfdec_as_with.c
index fa02b0d..9ef6c2e 100644
--- a/libswfdec/swfdec_as_with.c
+++ b/libswfdec/swfdec_as_with.c
@@ -44,7 +44,7 @@ swfdec_as_with_get (SwfdecAsObject *obje
 {
   SwfdecAsWith *with = SWFDEC_AS_WITH (object);
 
-  return swfdec_as_object_get_variable_and_flags (with->object, variable, val, flags);
+  return swfdec_as_object_get_variable_and_flags (with->object, variable, val, flags, NULL);
 }
 
 static void


More information about the Swfdec mailing list