CVSROOT: /sources/gnash Module name: gnash Changes by: Chad Musick <cmusick> 07/10/05 17:48:17
Modified files: . : ChangeLog server/vm : Machine.h AbcHandlers.cpp Log message: More work on AS3. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4540&r2=1.4541 http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/Machine.h?cvsroot=gnash&r1=1.1&r2=1.2 http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/AbcHandlers.cpp?cvsroot=gnash&r1=1.3&r2=1.4 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.4540 retrieving revision 1.4541 diff -u -b -r1.4540 -r1.4541 --- ChangeLog 5 Oct 2007 15:08:12 -0000 1.4540 +++ ChangeLog 5 Oct 2007 17:48:16 -0000 1.4541 @@ -1,4 +1,10 @@ 2007-10-06 Chad Musick <[EMAIL PROTECTED]> + * server/vm/Machine.h: More comments about functions, some + signature corrections. + * server/vm/AbcHandlers.cpp: Definition of some of the necessary + support functions. + +2007-10-06 Chad Musick <[EMAIL PROTECTED]> * server/vm/Machine.h: New File. First iteration (not documented, not compilable) of class definition for VM for ActionScript3 Index: server/vm/Machine.h =================================================================== RCS file: /sources/gnash/gnash/server/vm/Machine.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -b -r1.1 -r1.2 --- server/vm/Machine.h 5 Oct 2007 15:08:12 -0000 1.1 +++ server/vm/Machine.h 5 Oct 2007 17:48:16 -0000 1.2 @@ -131,6 +131,22 @@ Stack<as_value> *mStack; }; +/// This machine is intended to work without relying on the C++ call stack, +/// by resetting its Stream and Stack members (actually, by limiting the stack) +/// to make function calls, rather than calling them directly in C++. +/// As a result, many of the internal calls are void functions even though they +/// will be returning some value. +/// The exception to this is that C++ native functions defined in ActionScript +/// objects will be called in the typical way. +/// +/// The C++ exceptions mechanism is used for exception handling, since this +/// allows both ActionScript code and C++ code to use the exception handling +/// with a minimum of hassle, and it helps with correctness. +/// +/// The intent is that the machine will run both AS2 and AS3 code. Despite the +/// difference in presentation between the two, they should be compatible (or +/// able to become so), so that extensions written for AS2 will work in AS3 +/// (and vice versa). class Machine { public: @@ -142,21 +158,78 @@ /// Not null. void setTarget(character* target); - void completeName(asBindingName&); + /// This will complete a name in AS3, where a part of the name + /// is stored in the stream and another part may be stored on + /// the stack. + /// + /// @param name + /// A partially filled asBoundName, this should be the id + /// from the stream. + /// + /// @param initial + /// The depth in the stack where the stack objects may be found. + /// + /// @return + /// The number of stack elements used by the name. + /// At present, always 0, 1, or 2. These are not dropped. + int completeName(asBoundName& name, int initial = 0); + + /// Given a value v, find the class object of the superclass of v. + /// + /// @param obj + /// The object whose superclass is desired. + /// + /// @param find_primitive + /// If true, the ActionScript prototype will be find for primitive values. + /// + /// @return + /// Null if the superclass was not found, or the superclass. + asClass* findSuper(as_value& obj, bool find_primitive); + + /// Get a member from an object. + /// + /// @param pDefinition + /// The definition of the class which is to be used. This should be the + /// one which has the property. + /// + /// @param name + /// The bound name of the member + /// + /// @param source + /// The source object -- the specific instance of the pDefinition class. + /// + /// @return + /// This returns the value, but on the stack. + /// (Since the return value is not known until after control has left + /// the caller of this, it's impossible to return a meaningful value. + void getMember(asClass* pDefinition, asBoundName& name, as_value& source); + + /// Set a member in an object. + /// + /// @param pDefinition + /// The definition of the class which is to be used. + /// + /// @param name + /// The bound name of the member + /// + /// @param source + /// The source object -- where the instance should be set + /// + /// @param newvalue + /// The new value + /// + /// @return + /// Nothing. + void setMember(asClass*, asBoundName&, as_value& target, as_value& val); - asClass* findSuper(as_value&, bool); - - as_value getMember(asClass*, asBindingName&, as_value&); - bool setMember(asClass*, asBindingName&, as_value& target, as_value& val); - - std::string pool_string(uint32_t); + std::string& pool_string(uint32_t); int pool_int(uint32_t); unsigned int pool_uint(uint32_t); double pool_double(uint32_t); asNamespace* pool_namespace(uint32_t); asMethod* pool_method(uint32_t); - as_value(v) findProperty(asBindingName&); + as_value findProperty(asBoundName&); void pushScope(asScope*); asScope* popScope(); @@ -165,6 +238,8 @@ void execute_as2(); + void pushCall(int param_count, int return_count, asMethod *pMethod); + private: Stack<as_value> mStack; Stack<FunctionEntry> mCallStack; Index: server/vm/AbcHandlers.cpp =================================================================== RCS file: /sources/gnash/gnash/server/vm/AbcHandlers.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -b -r1.3 -r1.4 --- server/vm/AbcHandlers.cpp 5 Oct 2007 15:08:12 -0000 1.3 +++ server/vm/AbcHandlers.cpp 5 Oct 2007 17:48:16 -0000 1.4 @@ -61,15 +61,15 @@ // Get the name. asName a = mStream.read_V32(); // Finish it, if necessary. - completeName(a); + mStack.drop(completeName(a)); // Get the target object. as_value vobj& = mStack.top(0); asClass *pClass = findSuper(vobj, true); // If we don't have a class yet, throw. if (!pClass) throw ASReferenceError(); - // getMember will throw any necessary exceptions. - mStack.top(0) = getMember(pClass, a, vobj); + // getMember will throw any necessary exceptions and do the push. + getMember(pClass, a, vobj); break; } /// 0x05 ABC_ACTION_SETSUPER @@ -87,7 +87,7 @@ asName a = mStream.read_V32(); as_value vobj = mStack.pop(); // The value - completeName(a); + mStack.drop(completeName(a)); as_value target = mStack.pop(); asClass *pClass = findSuper(target, true); @@ -760,7 +760,7 @@ case SWF::ABC_ACTION_CALLSUPERVOID: { asName a = mStream.read_V32(); - completeName(a); + mStack.drop(completeName(a)); mStack.top(argc) = mStack.top(argc).get_named_super(a) .call_function(mStack.top(argc - 1)); @@ -956,7 +956,7 @@ case SWF::ABC_ACTION_FINDPROPERTY: { asName a = mStream.read_V32(); - completeName(a); + mStack.drop(completeName(a)); as_value v = findProperty(a); if ((opcode == SWF::ABC_ACTION_FINDPROPSTRICT) && v.is_undefined()) throw ASReferenceException(); @@ -1016,7 +1016,7 @@ if (a.isRtns() || !(mStack.top(0).is_object() && mStack.top(1).is_dictionary())) { - completeName(a); + mStack.drop(completeName(a)); mStack.top(0).setProperty(a, v); mStack.drop(1); } @@ -1094,7 +1094,7 @@ if (a.isRtns() || !(mStack.top(0).is_object() && mStack.top(1).is_dictionary())) { - completeName(a); + mStack.drop(completeName(a)); mStack.top(0) = mStack.top(0).getProperty(a); } else @@ -1119,7 +1119,7 @@ { asName a = mStream.read_V32(); as_value& v = mStack.pop(); - completeName(a); + mStack.drop(completeName(a)); mStack.pop().to_object().setProperty(a, v, true); // true for init break; } @@ -1133,7 +1133,7 @@ case SWF::ABC_ACTION_DELETEPROPERTY: { asName a = mStream.read_V32(); - completeName(a); + mStack.drop(completeName(a)); mStack.top(0) = mStack.top(0).deleteProperty(a); break; } @@ -1317,7 +1317,7 @@ case SWF::ABC_ACTION_COERCE: { asName a = mStream.read_V32(); - completeName(a); + mStack.drop(completeName(a)); mStack.top(0) = mStack.top(0).coerce(a); break; } @@ -1354,7 +1354,7 @@ case SWF::ABC_ACTION_ASTYPE: { asName a = mStream.read_V32(); - completeName(a); + mStack.drop(completeName(a)); if (!mStack.top(0).conforms_to(a) mStack.top(0).set_null(); break; @@ -1696,7 +1696,7 @@ case SWF::ABC_ACTION_ISTYPE: { asName a = mStream.read_V32(); - completeName(a); + mStack.drop(completeName(a)); mStack.top(0).set_bool(mStack.top(0).conforms_to(a)); } /// 0xB3 ABC_ACTION_ISTYPELATE @@ -1859,9 +1859,77 @@ } // end of main loop } // end of execute function -/// Given a value v, find the class object of the superclass of v. -/// If find_for_primitive is true, then, for example, The value -/// 1 (a number) will return the Number class object. +void +ActionMachine::getMember(asClass* pDefinition, asBoundName& name, + as_value& instance) +{ + if (!instance.is_object()) + throw ASTypeError(); + + asBinding *pBinding = pDefinition->findMember(name); + if (pBinding->isWriteOnly()) + throw ASReferenceError(); + + if (!pBinding->isGetSet()) + { + mStack.push(pBinding->getFromInstance(instance)); + return; + } + + // This is a getter, so we need to execute it. Even those + // written in C++ get called like this, with pushCall handling. + // 1 parameter (the source), 1 value expected back. + mStack.push(instance); + pushCall(1, 1, pBinding->getGetter()); +} + +void +ActionMachine::setMember(asClass *pDefinition, asBoundName& name, + as_value& instance, as_value& newvalue) +{ + if (!instance.is_object()) + throw ReferenceError(); + + asBinding *pBinding = pDefinition->findMember(name); + if (pBinding->isReadOnly()) + throw ASReferenceError(); + + if (!pBinding->isGetSet()) + { + pBinding->setInInstance(instance, newvalue); + return; + } + + // Two parameters -- the target object, the value to set. + mStack.push(instance); + mStack.push(newvalue); + pushCall(2, 0, pBinding->getSetter()); +} + +int +ActionMachine::completeName(asBoundName &name, int offset) +{ + int size = 0; + + asUnboundName* uname = mNamePool.at(name.id); + if (uname->isRuntime()) + { + as_value obj = mStack.top(offset); + if (obj.is_object() && obj.to_object()->isQName()) + name.fill(obj.to_object()); + ++size; + + if (uname->isRuntimeNamespace()) + ++size; // Ignore the Namespace. + } + else if (uname->isRuntimeNamespace()) + { + uname->setNamespace(mStack.top(offset); + ++size; + } + return size; +} + asClass * ActionMachine::findSuper(as_value &v, bool find_for_primitive) { @@ -1880,6 +1948,7 @@ } // And so on... + // TODO: Other primitives return NULL; } _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit