[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog server/StreamProvider.cpp serve...
From: |
Chad Musick |
Subject: |
[Gnash-commit] gnash ChangeLog server/StreamProvider.cpp serve... |
Date: |
Mon, 29 Oct 2007 21:07:35 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Chad Musick <cmusick> 07/10/29 21:07:34
Modified files:
. : ChangeLog
server : StreamProvider.cpp as_object.h as_object.cpp
namedStrings.h namedStrings.cpp
server/asobj : ClassHierarchy.cpp
server/vm : ASHandlers.cpp Machine.h Machine.cpp
SafeStack.h CodeStream.h
testsuite/actionscript.all: Date.as
Log message:
Various updates to AS3 support, fix a compile error in StreamProvider,
and a
faulty assumption in testsuite/actionscript.all/Date.as
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4736&r2=1.4737
http://cvs.savannah.gnu.org/viewcvs/gnash/server/StreamProvider.cpp?cvsroot=gnash&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_object.h?cvsroot=gnash&r1=1.80&r2=1.81
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_object.cpp?cvsroot=gnash&r1=1.77&r2=1.78
http://cvs.savannah.gnu.org/viewcvs/gnash/server/namedStrings.h?cvsroot=gnash&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/gnash/server/namedStrings.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/ClassHierarchy.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/ASHandlers.cpp?cvsroot=gnash&r1=1.145&r2=1.146
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/Machine.h?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/Machine.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/SafeStack.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/CodeStream.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/Date.as?cvsroot=gnash&r1=1.32&r2=1.33
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.4736
retrieving revision 1.4737
diff -u -b -r1.4736 -r1.4737
--- ChangeLog 29 Oct 2007 20:09:38 -0000 1.4736
+++ ChangeLog 29 Oct 2007 21:07:32 -0000 1.4737
@@ -1,3 +1,20 @@
+2007-10-30 Chad Musick <address@hidden>
+
+ * server/StreamProvider.cpp: Even if LIBCURL is not being used,
+ URLAccessManager.h must be included.
+ * server/as_object.h,.cpp: Make instanceOf a recursive function
+ so that non-proper properties, like interfaces, will be correctly
+ searched. Add get_super() and get_constructor() functions, not yet
+ implemented.
+ * server/namedStrings.h,.cpp: Add another anonymous string.
+ * server/asobj/ClassHierarchy.cpp: Add prototypes to loaded objects if
+ they don't do so themselves.
+ * server/vm/ASHandlers.cpp: ImplementsOp -- not quite working, yet.
+ * server/vm/Machine.h,.cpp: More work toward AS3 ability.
+ * testsuite/actionscript.all/Date.as: Fix bogus test -- the time
+ returned depends on local timezone, so you can't check to the second.
+ * server/vm/SafeStack.h, server/vm/CodeStream.h -- Comment updates.
+
2007-10-27 Sandro Santilli <address@hidden>
* testsuite/MovieTester.cpp (checkPixel): multiply tolerance by
Index: server/StreamProvider.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/StreamProvider.cpp,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- server/StreamProvider.cpp 20 Oct 2007 07:06:16 -0000 1.21
+++ server/StreamProvider.cpp 29 Oct 2007 21:07:33 -0000 1.22
@@ -27,8 +27,8 @@
#ifdef USE_CURL
//# include <curl/curl.h>
# include "curl_adapter.h"
-#include "URLAccessManager.h"
#endif
+#include "URLAccessManager.h"
#include "log.h"
#include "rc.h" // for rcfile
Index: server/as_object.h
===================================================================
RCS file: /sources/gnash/gnash/server/as_object.h,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -b -r1.80 -r1.81
--- server/as_object.h 29 Oct 2007 10:53:12 -0000 1.80
+++ server/as_object.h 29 Oct 2007 21:07:33 -0000 1.81
@@ -472,6 +472,20 @@
bool isXML() const { return false; /* TODO */ }
bool isDictionary() const { return false; /* TODO */ }
+ /// Get the super object of this object.
+ ///
+ /// The super should be __proto__ if this is a prototype object
+ /// itself, or __proto__.__proto__ if this is not a prototype
+ /// object. This is only conceptual however, and may be more
+ /// convoluted to obtain the actual super.
+ as_object* get_super();
+
+ /// Get the constructor for this object.
+ ///
+ /// This is the AS constructor for this object. When invoked, it
+ /// should initialize the object passed as 'this'
+ as_function* get_constructor();
+
/// Get a member as_value by name in an AS-compatible way
//
/// NOTE that this method is non-const becase a property
Index: server/as_object.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/as_object.cpp,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -b -r1.77 -r1.78
--- server/as_object.cpp 29 Oct 2007 10:53:12 -0000 1.77
+++ server/as_object.cpp 29 Oct 2007 21:07:33 -0000 1.78
@@ -135,6 +135,20 @@
return const_cast<Property *>(obj->_members.getPropertyByOrder(index));
}
+as_object*
+as_object::get_super()
+{
+ // TODO: Implement
+ return NULL;
+}
+
+as_function*
+as_object::get_constructor()
+{
+ // TODO: Implement
+ return NULL;
+}
+
int
as_object::nextIndex(int index, as_object **owner)
{
@@ -483,6 +497,8 @@
void
as_object::add_interface(as_object* obj)
{
+ assert(obj);
+
if (std::find(mInterfaces.begin(), mInterfaces.end(), obj) ==
mInterfaces.end())
mInterfaces.push_back(obj);
else
@@ -492,26 +508,22 @@
bool
as_object::instanceOf(as_function* ctor)
{
- boost::intrusive_ptr<as_object> obj = this;
-
- std::set< as_object* > visited;
+ if (this == ctor->getPrototype())
+ return true;
- if (this == ctor)
- { assert(0); }
- while (obj && visited.insert(obj.get()).second )
+ if (!mInterfaces.empty())
+ {
+ // TODO: Make this work.
+ if (std::find(mInterfaces.begin(), mInterfaces.end(),
ctor->getPrototype()) != mInterfaces.end())
{
- if (!mInterfaces.empty() &&
- std::find(mInterfaces.begin(), mInterfaces.end(), obj)
!= mInterfaces.end())
return true;
- if ( obj->get_prototype() == ctor->getPrototype() ) return true;
- obj = obj->get_prototype();
+ }
}
- // See actionscript.all/Inheritance.as for a way to trigger this
- IF_VERBOSE_ASCODING_ERRORS(
- if ( obj ) log_aserror(_("Circular inheritance chain detected during
instanceOf call"));
- );
-
+ as_object *proto = this->get_prototype().get();
+ if (proto)
+ return proto->instanceOf(ctor);
+ else
return false;
}
Index: server/namedStrings.h
===================================================================
RCS file: /sources/gnash/gnash/server/namedStrings.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- server/namedStrings.h 18 Oct 2007 11:47:55 -0000 1.6
+++ server/namedStrings.h 29 Oct 2007 21:07:33 -0000 1.7
@@ -160,7 +160,8 @@
NS_FLASH_UI,
NS_ADOBE_UTILS,
INTERNAL_TYPE, // The type name
- INTERNAL_STACK_PARENT // Any public property is unsafe
+ INTERNAL_STACK_PARENT, // Any public property is unsafe
+ INTERNAL_INTERFACES
} named_strings;
/// Load the prenamed strings.
Index: server/namedStrings.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/namedStrings.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/namedStrings.cpp 18 Oct 2007 11:47:54 -0000 1.4
+++ server/namedStrings.cpp 29 Oct 2007 21:07:34 -0000 1.5
@@ -138,7 +138,8 @@
{ "flash.ui", NSV::NS_FLASH_UI },
{ "adobe.utils", NSV::NS_ADOBE_UTILS },
{ "", NSV::INTERNAL_TYPE },
- { "", NSV::INTERNAL_STACK_PARENT }
+ { "", NSV::INTERNAL_STACK_PARENT },
+ { "", NSV::INTERNAL_INTERFACES }
};
void load_strings(string_table *table, int version)
Index: server/asobj/ClassHierarchy.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/ClassHierarchy.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/asobj/ClassHierarchy.cpp 18 Oct 2007 11:47:55 -0000 1.4
+++ server/asobj/ClassHierarchy.cpp 29 Oct 2007 21:07:34 -0000 1.5
@@ -101,7 +101,7 @@
super.set_undefined();
return super;
}
- if (!super.is_object())
+ if (!super.is_as_function())
{
// Error here -- not an object.
// TODO: Log the error.
@@ -115,8 +115,8 @@
// Successfully loaded it, now find it, set its proto,
and return.
as_value us;
mTarget->get_member(mDeclaration.name, &us);
- if (0 && mDeclaration.super_name)
-
us.to_object()->set_prototype(boost::intrusive_ptr<as_object>(super.to_object()));
+ if (mDeclaration.super_name &&
!us.to_object()->get_prototype())
+
us.to_object()->set_prototype(super.to_as_function()->getPrototype());
fprintf(stderr, "Loaded ourselves.\n");
return us;
}
@@ -158,7 +158,7 @@
super.set_undefined();
return super;
}
- if (!super.is_object())
+ if (!super.is_as_function())
{
// Error here -- not an object.
// TODO: Log the error.
@@ -170,8 +170,8 @@
// Successfully loaded it, now find it, set its proto, and
return.
as_value us;
mTarget->get_member(mDeclaration.name, &us);
- if (0 && mDeclaration.super_name)
-
us.to_object()->set_prototype(boost::intrusive_ptr<as_object>(super.to_object()));
+ if (mDeclaration.super_name && !us.to_object()->get_prototype())
+
us.to_object()->set_prototype(super.to_as_function()->getPrototype());
return us;
}
};
Index: server/vm/ASHandlers.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/vm/ASHandlers.cpp,v
retrieving revision 1.145
retrieving revision 1.146
diff -u -b -r1.145 -r1.146
--- server/vm/ASHandlers.cpp 25 Oct 2007 09:37:35 -0000 1.145
+++ server/vm/ASHandlers.cpp 29 Oct 2007 21:07:34 -0000 1.146
@@ -17,7 +17,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-/* $Id: ASHandlers.cpp,v 1.145 2007/10/25 09:37:35 strk Exp $ */
+/* $Id: ASHandlers.cpp,v 1.146 2007/10/29 21:07:34 cmusick Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -1358,27 +1358,51 @@
}
env.drop(1);
- if ( instance->instanceOf(super) )
+ if (instance->instanceOf(super))
{
+ fprintf(stderr, "Cast succeeded.\n");
env.top(0) = as_value(instance);
}
else
{
- env.top(0) = as_value();
+ fprintf(stderr, "Cast failed.\n");
+ env.top(0).set_null(); // null, not undefined.
}
log_msg(_("ActionCastOp TESTING"));
}
void
-SWFHandlers::ActionImplementsOp(ActionExec& /*thread*/)
+SWFHandlers::ActionImplementsOp(ActionExec& thread)
{
// GNASH_REPORT_FUNCTION;
+// TODO: This doesn't work quite right, yet.
+ as_environment& env = thread.env;
- // assert(thread.code[thread.pc] == SWF::ACTION_IMPLEMENTSOP);
+ thread.ensureStack(2);
- //as_environment& env = thread.env;
- log_unimpl (__PRETTY_FUNCTION__);
+ as_object *obj = env.pop().to_object().get();
+ int count = static_cast<int>(env.pop().to_number(&env));
+ as_value a(1);
+
+ if (!obj)
+ {
+ log_msg(_("In ImplementsOp, not an object.\n"));
+ return;
+ }
+ obj = obj->get_prototype().get();
+ if (!obj)
+ {
+ log_msg(_("In ImplementsOp, object had no prototype.\n"));
+ return;
+ }
+
+ thread.ensureStack(count);
+ while (count--)
+ {
+ as_object *inter =
env.pop().to_as_function()->getPrototype().get();
+ obj->add_interface(inter);
+ }
}
void
@@ -3492,6 +3516,7 @@
}
env.drop(2);
+ fprintf(stderr, "Extending.\n");
sub->extends(*super);
//log_msg(_("%s: testing"), __PRETTY_FUNCTION__);
Index: server/vm/Machine.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/Machine.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- server/vm/Machine.h 18 Oct 2007 11:47:56 -0000 1.5
+++ server/vm/Machine.h 29 Oct 2007 21:07:34 -0000 1.6
@@ -1,3 +1,5 @@
+// Machine.h A VM to run AS3 code, and AS2 code in the future.
+//
// Copyright (C) 2007 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or modify
@@ -127,36 +129,77 @@
void execute();
- /// push a function call to be executed next.
+ /// push a get call to be executed next.
///
- /// Any asBinding can be pushed, and it will appropriate value
- /// into return_slot. This ensures that getter/setter properties
+ /// Any Property can be pushed, and it will put an appropriate value
+ /// into return_slot. This ensures that getter properties
/// can be accessed in the same way as other properties, and hides
/// the difference between ActionScript methods and native C++ methods.
///
- /// @param stack_in
- /// The initial stack size when the function is entered. This can be
used
- /// to pass 'this' and other parameters to the call.
- ///
- /// @param stack_out
- /// The maximum number of values to leave on the stack when the function
- /// returns.
+ /// @param this_obj
+ /// The 'this' to use for a getter/setter if it exists.
///
/// @param return_slot
/// A space for the return value. An assignment will always be made
here,
/// but mVoidSlot can be used for values that will be discarded.
///
- /// @param pBind
- /// The binding. If this is only a partial binding, then
- /// the 'this' value will be used to complete it, when possible.
- /// Sending a null binding will result in a no-op, not an error.
- void pushCall(unsigned int stack_in, as_value *return_slot,
- Property *pBind);
-
- void immediateFunction(as_function *to_call, as_value& storage,
- as_object *pThis);
- void immediateProcedure(as_function *to_call, as_object *pthis,
- const as_value *stackAdditions, unsigned int
stackAdditionsCount);
+ /// @param prop
+ /// The property. If this is a value, it simply returns that value in
+ /// the return_slot immediately. Otherwise, it may immediately call
+ /// the gettter or it may push that onto the call stack and transfer
+ /// control. Callers can be agnostic as to which happens.
+ void pushGet(as_object *this_obj, as_value& return_slot, Property
*prop);
+
+ /// push a set call to be executed next.
+ ///
+ /// Any Property can be pushed, and it will set the property, if
possible.
+ /// setter properties and simple properties alike will be handled by
this.
+ ///
+ /// @param this_obj
+ /// The 'this' to use for a getter/setter if it exists.
+ ///
+ /// @param value
+ /// The value which should be set
+ ///
+ /// @param prop
+ /// The property desired to be set.
+ ///
+ void pushSet(as_object *this_obj, as_value& value, Property *prop);
+
+ /// push a call to be executed next
+ ///
+ /// Push a call to be executed as soon as execution of the current
opcode
+ /// finishes. At the end, transfer will return to the previous context.
+ ///
+ /// @param func
+ /// The function to call
+ ///
+ /// @param pThis
+ /// The object to act as the 'this' pointer.
+ ///
+ /// @param return_slot
+ /// The slot to use for returns. Use mIgnoreReturn if you don't care
+ /// what happens here.
+ ///
+ /// @param stack_in
+ /// How many of the values on the stack are for the new context
+ ///
+ /// @param stack_out
+ /// How much of the stack should be left behind when the function exits.
+ /// For example: 0 will leave a stack which is stack_in shorter than it
+ /// was on call. 1 will leave a stack which is 1 taller than it was on
+ /// call.
+ ///
+ /// RESTRICTION: stack_in - stack_out must not be negative
+ void pushCall(as_function *func, as_object *pThis, as_value&
return_slot,
+ unsigned char stack_in, short stack_out);
+
+ void immediateFunction(const as_function *to_call, as_object* pThis,
+ as_value& storage, unsigned char stack_in, short stack_out);
+
+ void immediateProcedure(const as_function *to_call, as_object *pthis,
+ unsigned char stack_in, short stack_out)
+ { immediateFunction(to_call, pthis, mIgnoreReturn, stack_in,
stack_out); }
Machine(string_table &ST, ClassHierarchy *CH);
Index: server/vm/Machine.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/vm/Machine.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/vm/Machine.cpp 18 Oct 2007 11:47:56 -0000 1.2
+++ server/vm/Machine.cpp 29 Oct 2007 21:07:34 -0000 1.3
@@ -1,3 +1,4 @@
+// Machine.cpp A machine to run AS3 code, with AS2 code in the future
//
// Copyright (C) 2007 Free Software Foundation, Inc.
//
@@ -22,6 +23,7 @@
#include "namedStrings.h"
#include "array.h"
#include "abc_block.h"
+#include "fn_call.h"
namespace gnash {
@@ -120,8 +122,7 @@
if (b)
\
{
\
mStream->seekTo(opStart);
\
- mStack.push(*e);
\
- pushCall(1, e, b);
\
+ pushGet(e->to_object().get(), *e, b);
\
break;
\
}
\
}
\
@@ -148,8 +149,7 @@
if (d)
\
{
\
mStream->seekTo(opStart);
\
- mStack.push(*c);
\
- pushCall(1, c, d);
\
+ pushGet(c->to_object().get(), *c, d);
\
break;
\
}
\
}
\
@@ -323,7 +323,7 @@
Property *b = super->findProperty(a.getName(),
a.getNamespace()->getURI());
// The object is on the top already.
- pushCall(1, &mStack.top(0), b);
+ pushGet(super, mStack.top(0), b);
break;
}
/// 0x05 ABC_ACTION_SETSUPER
@@ -349,8 +349,8 @@
throw ASReferenceError();
Property* b = super->findProperty(a.getName(),
a.getNamespace()->getURI());
- // The object is on the top already.
- pushCall(1, &mStack.top(0), b);
+ mStack.push(vobj);
+ pushSet(super, vobj, b);
break;
}
/// 0x06 ABC_ACTION_DXNS
@@ -780,8 +780,11 @@
mStack.drop(1);
if (!b)
mStack.top(0).set_undefined();
- else // The top of the stack is obj, as it should be.
- pushCall(1, &mStack.top(0), const_cast<Property*>(b));
+ else
+ {
+ mStack.drop(1);
+ pushGet(obj, mStack.top(0), const_cast<Property*>(b));
+ }
break;
}
/// 0x24 ABC_ACTION_PUSHBYTE
@@ -984,13 +987,19 @@
case SWF::ABC_ACTION_CALL:
{
uint32_t argc = mStream->read_V32();
- ENSURE_OBJECT(mStack.top(argc + 1));
+ ENSURE_OBJECT(mStack.top(argc + 1)); // The func
+ ENSURE_OBJECT(mStack.top(argc)); // The 'this'
as_function *f = mStack.top(argc + 1).to_as_function();
- // argc + 1 will be dropped, and mStack.top(argc + 1)
- // will be the top of the stack, so that is where the
- // return value should go. (Currently it is the func)
- Property b(0, 0, f, NULL);
- pushCall(argc + 1, &mStack.top(argc + 1), &b);
+ as_object *obj = mStack.top(argc).to_object().get();
+ // We start with argc + 2 values related to this call
+ // on the stack. We want to end with 1 value. We pass
+ // argc values (the parameters), so we need to drop
+ // one more than we pass and store the return just
+ // below that one. Thus:
+ // return is mStack.top(argc + 1)
+ // bottom of arguments is argc deep
+ // drop 1 more value than is passed, on return
+ pushCall(f, obj, mStack.top(argc + 1), argc, -1);
break;
}
/// 0x42 ABC_ACTION_CONSTRUCT
@@ -1005,7 +1014,7 @@
uint32_t argc = mStream->read_V32();
as_function *f = mStack.top(argc).to_as_function();
Property b(0, 0, f, NULL);
- pushCall(argc, &mStack.top(argc), &b);
+ pushCall(f, NULL, mStack.top(argc), argc, 0);
break;
}
/// 0x43 ABC_ACTION_CALLMETHOD
@@ -1021,14 +1030,21 @@
uint32_t argc = mStream->read_V32();
ENSURE_OBJECT(mStack.top(argc));
as_object *obj = mStack.top(argc).to_object().get();
- Property *b = NULL; // TODO: obj->findProperty(dispatch_id);
- if (!b)
+ Property *f = obj->getByIndex(dispatch_id);
+ as_function* func;
+ if (f->isGetterSetter())
{
- mStack.drop(argc);
- mStack.top(0).set_undefined();
- break;
+ // Likely an error, but try to handle it.
+ func = f->getGetter();
+ }
+ else if (f->getValue(*obj).is_function())
+ func = f->getValue(*obj).to_as_function();
+ else
+ {
+ // Definitely an error, and not the kind we can handle.
+ throw ASException();
}
- pushCall(argc + 1, &mStack.top(argc), b);
+ pushCall(func, obj, mStack.top(argc), argc, 0);
break;
}
/// 0x44 ABC_ACTION_CALLSTATIC
@@ -1042,8 +1058,10 @@
{
asMethod *m = pool_method(mStream->read_V32(), mPoolObject);
uint32_t argc = mStream->read_V32();
- Property b; //TODO: asBinding b(m);
- pushCall(argc + 1, &mStack.top(argc), &b);
+ as_function *func = m->getPrototype();
+ ENSURE_OBJECT(mStack.top(argc));
+ as_object *obj = mStack.top(argc).to_object().get();
+ pushCall(func, obj, mStack.top(argc), argc, 0);
break;
}
/// 0x45 ABC_ACTION_CALLSUPER
@@ -1065,16 +1083,20 @@
int dropsize = completeName(a);
ENSURE_OBJECT(mStack.top(argc + dropsize));
mStack.drop(dropsize);
- ENSURE_OBJECT(mStack.top(argc));
- as_object *super =
mStack.top(argc).to_object()->get_prototype().get();
+ as_object *super = mStack.top(argc).to_object()->get_super();
if (!super)
throw ASReferenceError();
Property *b = super->findProperty(a.getName(),
a.getNamespace()->getURI());
+ if (!b)
+ throw ASReferenceError();
+ as_function *f = b->isGetterSetter() ? b->getGetter() :
+ b->getValue(super).to_as_function();
+
if (opcode == SWF::ABC_ACTION_CALLSUPER)
- pushCall(argc + 1, &mStack.top(argc), b);
- else
- pushCall(argc + 1, &mIgnoreReturn, b);
+ pushCall(f, super, mStack.top(argc), argc, 0);
+ else // Void call
+ pushCall(f, super, mIgnoreReturn, argc, -1); // drop
obj too.
break;
}
/// 0x46 ABC_ACTION_CALLPROPERTY
@@ -1099,21 +1121,33 @@
uint32_t argc = mStream->read_V32();
int shift = completeName(a, argc);
ENSURE_OBJECT(mStack.top(shift + argc));
- // Ugly setup. Any name stuff is between the args and the
object.
- if (shift)
+ as_object *obj = mStack.top(argc + shift).to_object().get();
+ Property *b = obj->findProperty(a.getName(),
+ a.getNamespace()->getURI());
+ if (!b)
+ throw ASReferenceError();
+
+ as_function *func;
+ if (b->isGetterSetter())
{
- uint32_t i = argc;
- while (i--)
- mStack.top(i + shift) = mStack.top(i);
- mStack.drop(shift);
+ if (lex_only)
+ {
+ mStack.top(argc + shift).set_undefined();
+ mStack.drop(argc + shift);
+ break;
+ }
+ else
+ {
+ func = b->getGetter();
+ }
}
- Property *b = mStack.top(argc).to_object()->
- findProperty(a.getName(), a.getNamespace()->getURI());
- //TODO: b->setLexOnly(lex_only);
+ else
+ func = b->getValue(obj).to_as_function();
+
if (opcode == SWF::ABC_ACTION_CALLPROPVOID)
- pushCall(argc + 1, &mIgnoreReturn, b);
+ pushCall(func, obj, mIgnoreReturn, argc, -shift - 1);
else
- pushCall(argc + 1, &mStack.top(argc), b);
+ pushCall(func, obj, mStack.top(argc + shift), argc,
-shift);
break;
}
/// 0x47 ABC_ACTION_RETURNVOID
@@ -1135,6 +1169,7 @@
case SWF::ABC_ACTION_RETURNVALUE:
{
// Slot the return.
+ if (mGlobalReturn != &mStack.top(0));
*mGlobalReturn = mStack.top(0);
// And restore the previous state.
restoreState();
@@ -1143,17 +1178,27 @@
/// 0x49 ABC_ACTION_CONSTRUCTSUPER
/// Stream: V32 'arg_count'
/// Stack In:
+/// argN ... arg1 -- the arg_count arguments
/// obj -- the object whose super's constructor should be invoked
-/// arg1 ... argN -- the arg_count arguments
/// Stack Out:
/// .
case SWF::ABC_ACTION_CONSTRUCTSUPER:
{
+ // TODO
uint32_t argc = mStream->read_V32();
ENSURE_OBJECT(mStack.top(argc));
- asMethod *m = findSuper(mStack.top(argc),
true)->getConstructor();
- Property b; //TODO: asBinding b(m);
- pushCall(argc + 1, &mIgnoreReturn, &b);
+ as_object *obj = mStack.top(argc).to_object().get();
+ as_object *super = mStack.top(argc).to_object()->get_super();
+ if (!super)
+ {
+ throw ASException();
+ break;
+ }
+ as_function *func = super->get_constructor();
+ // 'obj' is the 'this' for the call, we ignore the return,
there are
+ // argc arguments, and we drop all of the arguments plus 'obj'
from
+ // the stack.
+ pushCall(func, obj, mIgnoreReturn, argc, -1);
break;
}
/// 0x4A ABC_ACTION_CONSTRUCTPROP
@@ -1167,6 +1212,7 @@
/// 'name_offset'(arg1, ..., argN)
case SWF::ABC_ACTION_CONSTRUCTPROP:
{
+ // TODO
asName a = pool_name(mStream->read_V32(), mPoolObject);
uint32_t argc = mStream->read_V32();
int shift = completeName(a, argc);
@@ -1197,7 +1243,7 @@
/// NB: This builds an object from its properties, it's not a constructor.
case SWF::ABC_ACTION_NEWOBJECT:
{
- as_object *obj = mCH->newOfType(NSV::CLASS_OBJECT);
+ as_object *obj = new as_object;
uint32_t argc = mStream->read_V32();
int i = argc;
while (i--)
@@ -1222,14 +1268,13 @@
case SWF::ABC_ACTION_NEWARRAY:
{
uint32_t asize = mStream->read_V32();
- as_object *obj = mCH->newOfType(NSV::CLASS_ARRAY);
- as_array_object *array = dynamic_cast<as_array_object*> (obj);
- array->resize(asize);
+ as_array_object *arr = new as_array_object;
+ arr->resize(asize);
uint32_t i = asize;
while (i--)
- array->set_indexed(i, mStack.value(i));
+ arr->set_indexed(i, mStack.value(i));
mStack.drop(asize - 1);
- mStack.top(0) = array;
+ mStack.top(0) = arr;
break;
}
/// 0x57 ABC_ACTION_NEWACTIVATION
@@ -1252,9 +1297,12 @@
{
uint32_t cid = mStream->read_V32();
asClass *c = pool_class(cid, mPoolObject);
- asMethod *m = c->getConstructor();
- Property b; //TODO: asBinding b(m);
- pushCall(1, &mStack.top(0), &b);
+ ENSURE_OBJECT(mStack.top(0));
+ as_object *obj = mStack.top(0).to_object().get();
+ as_function *func = c->getConstructor()->getPrototype();
+ // func is the constructor, obj is 'this' and also the return
+ // value, no arguments, no change in stack.
+ pushCall(func, obj, mStack.top(0), 0, 0);
break;
}
/// 0x59 ABC_ACTION_GETDESCENDANTS
@@ -1301,16 +1349,19 @@
{
asName a = pool_name(mStream->read_V32(), mPoolObject);
mStack.drop(completeName(a));
- Property *b = NULL; //TODO: asBinding *b = findProperty(a);
- if (0)//!b)
+ as_object *owner;
+ Property *b = mCurrentScope->findProperty(a.getName(),
+ a.getNamespace()->getURI(), &owner);
+ if (!b)
+ {
if (opcode == SWF::ABC_ACTION_FINDPROPSTRICT)
throw ASReferenceError();
else
mStack.push(as_value());
+ }
else
{
- mStack.push(as_value());
- pushCall(0, &mStack.top(0), b);
+ mStack.push(owner);
}
break;
}
@@ -1333,13 +1384,14 @@
case SWF::ABC_ACTION_GETLEX:
{
asName a = pool_name(mStream->read_V32(), mPoolObject);
- // The name is expected to be complete.
- Property *b = NULL; //TODO: asBinding *b = findProperty(a);
- if (0)//!b)
- throw ASReferenceError();
- //TODO: b->setLexOnly(b);
+ as_object *owner;
+ Property *b = mCurrentScope->findProperty(a.getName(),
+ a.getNamespace()->getURI(), &owner);
+ if (!b)
+ throw ASException();
+
mStack.grow(1);
- pushCall(0, &mStack.top(0), b);
+ pushGet(owner, mStack.top(0), b);
break;
}
/// 0x61 ABC_ACTION_SETPROPERTY
@@ -2242,13 +2294,7 @@
{
if (!instance.is_object())
throw ASTypeError();
-
- return; // TODO:
#if 0
- asBinding *pBinding = pDefinition->getBinding(name.getName());
- if (pBinding->isWriteOnly())
- throw ASReferenceError();
-
if (!pBinding->isGetSet())
{
//TODO: mStack.push(pBinding->getFromInstance(instance));
@@ -2340,89 +2386,76 @@
}
void
-Machine::immediateFunction(as_function *to_call, as_value& storage,
- as_object *pThis)
+Machine::immediateFunction(const as_function *to_call, as_object *pThis,
+ as_value& storage, unsigned char stack_in, short stack_out)
{
- // TODO: Implement
+ // TODO: Set up the fn, or remove the need.
+ fn_call fn(NULL, NULL, 0, 0);
+ mStack.drop(stack_in - stack_out);
+ saveState();
+ mThis = pThis;
+ mStack.grow(stack_in - stack_out);
+ mStack.setDownstop(stack_in);
+ storage = const_cast<as_function*>(to_call)->call(fn);
+ restoreState();
}
void
-Machine::immediateProcedure(as_function *to_call, as_object *pthis,
- const as_value *stackAdditions, unsigned int stackAdditionsCount)
+Machine::pushGet(as_object *this_obj, as_value &return_slot, Property *prop)
{
- // TODO: Implement
+ if (!prop)
+ return;
+
+ if (prop->isGetterSetter())
+ {
+ //TODO pushCall(prop->getGetter(), this_obj, return_slot, 0);
+ return;
+ }
+
+ return_slot = prop->getValue(*this_obj);
}
void
-Machine::pushCall(unsigned int stack_in, as_value *return_slot,
- Property *pBind)
+Machine::pushSet(as_object *this_obj, as_value &value, Property *prop)
{
- if (!pBind)
+ if (!prop)
return;
- //TODO
-#if 0
- switch (pBind->mType)
+
+ if (prop->isGetterSetter())
{
- default:
- case asBinding::T_ACCESS:
- case asBinding::T_CLASS:
- throw ASException();
- return;
- case asBinding::T_VALUE:
- *return_slot = pBind->getValue()->getCurrentValue();
+ mStack.push(value);
+ //TODO pushCall(prop->getSetter(), this_obj, mIgnoreReturn, 1);
return;
- case asBinding::T_METHOD:
- break;
}
- asMethod *m = pBind->getMethod();
+ prop->setValue(*this_obj, value);
+}
- if (!(m->isNative() || m->hasBody()))
- throw ASException();
+void
+Machine::pushCall(as_function *func, as_object *pthis, as_value& return_slot,
+ unsigned char stack_in, short stack_out)
+{
+ if (1 || func->isBuiltin())
+ {
+ immediateFunction(func, pthis, return_slot, stack_in,
stack_out);
+ return;
+ }
+ // TODO: Make this work for stackless.
// Here is where the SafeStack shines:
// We set the stack the way it should be on return.
- // If the return slot is the deepest parameter, leave room for it.
- if (stack_in && (return_slot == &mStack.top(stack_in - 1)))
- mStack.drop(stack_in - 1);
- else // The return slot is somewhere else.
- mStack.drop(stack_in);
+ mStack.drop(stack_in - stack_out);
// We save that state.
saveState();
- // Set the 'this' object for the new call.
- if (stack_in == 0)
- mThis = mDefaultThis;
- else
- mThis = mStack.value(0).to_object().get(); // Checked in caller.
- // We make the stack appear empty.
- mStack.fixDownstop();
- // We grow to reclaim the parameters. Since this is a SafeStack, they
- // were not lost.
- mStack.grow(stack_in);
-
- // Native functions have to be called now.
- if (m->isNative())
- {
- //TODO: return_slot = m->CallNative(mStack, mGlobalScope);
- restoreState();
- return;
- }
-
- // The scope stack should be fixed for non-native calls.
- mScopeStack.fixDownstop();
- //TODO: mScopeStack.push(m->getActivation());
- if (!mScopeStack.empty())
- mCurrentScope = mScopeStack.top(0).mScope;
- else
- mCurrentScope = NULL;
-
- // We set the stream and return as given in the method and call.
- //TODO: mStream = m->getBody();
- mGlobalReturn = return_slot;
+ // Set the 'this' for the new call
+ mThis = pthis;
+ // Retrieve the stack. (It wasn't lost)
+ mStack.grow(stack_in - stack_out);
+ // And then we set the downstop
+ mStack.setDownstop(stack_in);
// When control goes to the main loop of the interpreter, it will
// automatically start executing the method.
-#endif
}
void
Index: server/vm/SafeStack.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/SafeStack.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/vm/SafeStack.h 18 Oct 2007 11:47:56 -0000 1.4
+++ server/vm/SafeStack.h 29 Oct 2007 21:07:34 -0000 1.5
@@ -1,3 +1,7 @@
+// SafeStack.h A stack which doesn't drop or free references until explicitly
+// asked to do so, so that values outside of the stack are guaranteed good
+// in an appropriate scope.
+//
// Copyright (C) 2007 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or modify
Index: server/vm/CodeStream.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/CodeStream.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/vm/CodeStream.h 8 Oct 2007 06:55:11 -0000 1.2
+++ server/vm/CodeStream.h 29 Oct 2007 21:07:34 -0000 1.3
@@ -1,3 +1,5 @@
+// CodeStream.h A class which allows bounds-checked reading from a char array
+//
// Copyright (C) 2007 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or modify
Index: testsuite/actionscript.all/Date.as
===================================================================
RCS file: /sources/gnash/gnash/testsuite/actionscript.all/Date.as,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -b -r1.32 -r1.33
--- testsuite/actionscript.all/Date.as 26 Oct 2007 08:26:54 -0000 1.32
+++ testsuite/actionscript.all/Date.as 29 Oct 2007 21:07:34 -0000 1.33
@@ -21,7 +21,7 @@
// compile this test case with Ming makeswf, and then
// execute it like this gnash -1 -r 0 -v out.swf
-rcsid="$Id: Date.as,v 1.32 2007/10/26 08:26:54 strk Exp $";
+rcsid="$Id: Date.as,v 1.33 2007/10/29 21:07:34 cmusick Exp $";
#include "check.as"
@@ -532,8 +532,9 @@
check_equals(foo.indexOf("Feb"), 8);
#else
check_equals(typeof(bar), 'number');
- // correct: "foo 950569200000"
- check_equals(foo.substring(0, 10), 'foo 950569');
+ // correct: "foo 950569200000", but only for the timezone
+ // of the original author
+ check_equals(foo.substring(0, 7), 'foo 950');
#endif
totals();
- [Gnash-commit] gnash ChangeLog server/StreamProvider.cpp serve...,
Chad Musick <=