gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash ChangeLog server/as_value.cpp server/as_v...


From: Chad Musick
Subject: [Gnash-commit] gnash ChangeLog server/as_value.cpp server/as_v...
Date: Tue, 11 Sep 2007 22:03:06 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Chad Musick <cmusick>   07/09/11 22:03:06

Modified files:
        .              : ChangeLog 
        server         : as_value.cpp as_value.h 
        server/vm      : ASHandlers.cpp ActionExec.cpp ActionExec.h 
        testsuite/misc-mtasc.all: exception.as 

Log message:
        Exceptions now work.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4275&r2=1.4276
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_value.cpp?cvsroot=gnash&r1=1.70&r2=1.71
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_value.h?cvsroot=gnash&r1=1.64&r2=1.65
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/ASHandlers.cpp?cvsroot=gnash&r1=1.128&r2=1.129
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/ActionExec.cpp?cvsroot=gnash&r1=1.42&r2=1.43
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/ActionExec.h?cvsroot=gnash&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-mtasc.all/exception.as?cvsroot=gnash&r1=1.3&r2=1.4

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.4275
retrieving revision 1.4276
diff -u -b -r1.4275 -r1.4276
--- ChangeLog   11 Sep 2007 19:31:49 -0000      1.4275
+++ ChangeLog   11 Sep 2007 22:03:05 -0000      1.4276
@@ -1,3 +1,10 @@
+2007-09-12 Chad Musick <address@hidden>
+
+       * server/as_value.cpp,h: Add exception types to as_value.
+       * server/vm/ASHandlers.cpp: Implement try and throw
+       * server/vm/ActionExec.cpp,h: Support for try and throw
+       * testsuite/misc-mtasc.all/exception.as: Exceptions now work.
+
 2007-09-11 Sandro Santilli <address@hidden>
 
        * server/as_object.{cpp,h} (copyProperties): don't copy __proto__.

Index: server/as_value.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/as_value.cpp,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -b -r1.70 -r1.71
--- server/as_value.cpp 11 Sep 2007 17:26:48 -0000      1.70
+++ server/as_value.cpp 11 Sep 2007 22:03:05 -0000      1.71
@@ -935,14 +935,18 @@
 void
 as_value::operator=(const as_value& v)
 {
-       if (v.m_type == UNDEFINED) set_undefined();
-       else if (v.m_type == NULLTYPE) set_null();
-       else if (v.m_type == BOOLEAN) set_bool(v.m_boolean_value);
-       else if (v.m_type == STRING) set_string(v.m_string_value);
-       else if (v.m_type == NUMBER) set_double(v.m_number_value);
-       else if (v.m_type == OBJECT) set_as_object(v.m_object_value);
+       type the_type = v.m_type;
+       if (v.is_exception())
+               the_type = (type) ((int) the_type - 1);
+
+       if (the_type == UNDEFINED) set_undefined();
+       else if (the_type == NULLTYPE) set_null();
+       else if (the_type == BOOLEAN) set_bool(v.m_boolean_value);
+       else if (the_type == STRING) set_string(v.m_string_value);
+       else if (the_type == NUMBER) set_double(v.m_number_value);
+       else if (the_type == OBJECT) set_as_object(v.m_object_value);
 
-       else if (v.m_type == MOVIECLIP)
+       else if (the_type == MOVIECLIP)
        {
 #ifndef MOVIECLIP_AS_SOFTREF
                sprite_instance* sp = 
dynamic_cast<sprite_instance*>(v.m_object_value);
@@ -953,8 +957,12 @@
 #endif
        }
 
-       else if (v.m_type == AS_FUNCTION) 
set_as_function(v.m_object_value->to_function());
-       else assert(0);
+       else if (the_type == AS_FUNCTION) 
set_as_function(v.m_object_value->to_function());
+       else 
+               assert(0);
+
+       if (v.is_exception())
+               flag_exception();
 }
 
 as_value::as_value(boost::intrusive_ptr<as_object> obj)

Index: server/as_value.h
===================================================================
RCS file: /sources/gnash/gnash/server/as_value.h,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -b -r1.64 -r1.65
--- server/as_value.h   25 Aug 2007 14:15:51 -0000      1.64
+++ server/as_value.h   11 Sep 2007 22:03:05 -0000      1.65
@@ -15,7 +15,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: as_value.h,v 1.64 2007/08/25 14:15:51 strk Exp $ */
+/* $Id: as_value.h,v 1.65 2007/09/11 22:03:05 cmusick Exp $ */
 
 #ifndef GNASH_AS_VALUE_H
 #define GNASH_AS_VALUE_H
@@ -94,29 +94,39 @@
 public:
        enum type
        {
+               // Always make the exception type one greater than the normal 
type.
+               
                /// Undefined value
                UNDEFINED,
+               UNDEFINED_EXCEPT,
 
                /// NULL value
                NULLTYPE,
+               NULLTYPE_EXCEPT,
 
                /// Boolean value
                BOOLEAN,
+               BOOLEAN_EXCEPT,
 
                /// String value
                STRING,
+               STRING_EXCEPT,
 
                /// Number value
                NUMBER, 
+               NUMBER_EXCEPT,
 
                /// Object reference
                OBJECT,
+               OBJECT_EXCEPT,
 
                /// ActionScript function reference
                AS_FUNCTION,
+               AS_FUNCTION_EXCEPT,
 
                /// MovieClip reference
-               MOVIECLIP
+               MOVIECLIP,
+               MOVIECLIP_EXCEPT
        };
 
        /// Construct an UNDEFINED value
@@ -544,6 +554,20 @@
 
        bool    is_bool() const { return (m_type == BOOLEAN); }
 
+       bool    is_exception() const
+       { return (m_type == UNDEFINED_EXCEPT || m_type == NULLTYPE_EXCEPT
+               || m_type == BOOLEAN_EXCEPT || m_type == NUMBER_EXCEPT
+               || m_type == OBJECT_EXCEPT || m_type == AS_FUNCTION_EXCEPT
+               || m_type == MOVIECLIP_EXCEPT || m_type == STRING_EXCEPT);
+       }
+
+       // Flag or unflag an as_value as an exception -- this gets flagged
+       // when an as_value is 'thrown'.
+       void    flag_exception() 
+       { if (!is_exception()) m_type = (type) ((int) m_type + 1); }
+       void    unflag_exception()
+       { if (is_exception()) m_type = (type) ((int) m_type - 1); }
+
        /// Return true if this value is strictly equal to the given one
        //
        /// Strict equality is defined as the two values being of the

Index: server/vm/ASHandlers.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/vm/ASHandlers.cpp,v
retrieving revision 1.128
retrieving revision 1.129
diff -u -b -r1.128 -r1.129
--- server/vm/ASHandlers.cpp    27 Aug 2007 03:06:42 -0000      1.128
+++ server/vm/ASHandlers.cpp    11 Sep 2007 22:03:05 -0000      1.129
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-/* $Id: ASHandlers.cpp,v 1.128 2007/08/27 03:06:42 cmusick Exp $ */
+/* $Id: ASHandlers.cpp,v 1.129 2007/09/11 22:03:05 cmusick Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -1312,11 +1312,16 @@
 }
 
 void
-SWFHandlers::ActionThrow(ActionExec& /*thread*/)
+SWFHandlers::ActionThrow(ActionExec& thread)
 {
 //    GNASH_REPORT_FUNCTION;
-    //as_environment& env = thread.env;
-    log_unimpl (__PRETTY_FUNCTION__);
+    as_environment& env = thread.env;
+
+       // Throw the value on the top of the stack.
+       env.top(0).flag_exception();
+
+       // Proceed to the end of the code block to throw.
+       thread.next_pc = thread.stop_pc;
 }
 
 void
@@ -2469,6 +2474,11 @@
        env.drop(nargs + 1);
        env.top(0) = result;
 
+       // If the function threw an exception, do so here.
+       if (result.is_exception())
+       {
+               thread.next_pc = thread.stop_pc;
+       }
 
        //cerr << "After ActionCallFunction:"<<endl;
        //env.dump_stack();
@@ -2479,7 +2489,6 @@
 {
 //        GNASH_REPORT_FUNCTION;
        as_environment& env = thread.env;
-       as_value* retval = thread.retval;
 
        //log_msg(_("Before top/drop (retval=%p)"), (void*)retval);
        //env.dump_stack();
@@ -2488,9 +2497,7 @@
 
        // Put top of stack in the provided return slot, if
        // it's not NULL.
-       if (retval) {
-               *retval = env.top(0);
-       }
+       thread.pushReturn(env.top(0));
        env.drop(1);
 
 #ifdef USE_DEBUGGER
@@ -3140,6 +3147,11 @@
        env.drop(nargs + 2);
        env.top(0) = result;
 
+       // Now, if there was an exception, proceed to the end of the block.
+       if (result.is_exception())
+       {
+               thread.next_pc = thread.stop_pc;
+       }
        // This is to check stack status after call method
        //log_msg(_("at doActionCallMethod() end, stack: ")); env.dump_stack();
 
@@ -3603,7 +3615,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
 
-       //as_environment& env = thread.env;
+       as_environment& env = thread.env;
        const action_buffer& code = thread.code;
        size_t pc = thread.pc;
 
@@ -3626,21 +3638,34 @@
        const char* catchName = NULL;
        uint8_t catchRegister = 0;
 
-       if ( catchInRegister )
+       if (!doFinally)
+               finallySize = 0;
+       if (!doCatch)
+               catchSize = 0;
+
+       if (!catchInRegister)
        {
                catchName = code.read_string(i);
+               i += strlen(catchName) + 1;
+               tryBlock t(i, trySize, catchSize, finallySize, catchName, 
+                       env.stack_size());
+               thread.pushTryBlock(t);
        }
        else
        {
                catchRegister = code[i];
+               ++i;
+               tryBlock t(i, trySize, catchSize, finallySize, catchRegister,
+                       env.stack_size());
+               thread.pushTryBlock(t);
        }
 
+       thread.next_pc = i; // Proceed into the try block.
+
        IF_VERBOSE_ACTION(
        log_action(_("ActionTry: reserved:%x doFinally:%d doCatch:%d trySize:%u 
catchSize:%u finallySize:%u catchName:%s catchRegister:%u"),
                reserved, doFinally, doCatch, trySize, catchSize, finallySize, 
catchName ? catchName : "(null)", catchRegister);
        );
-
-       log_unimpl (__PRETTY_FUNCTION__);
 }
 
 /// See: http://sswf.sourceforge.net/SWFalexref.html#action_with

Index: server/vm/ActionExec.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/vm/ActionExec.cpp,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -b -r1.42 -r1.43
--- server/vm/ActionExec.cpp    4 Sep 2007 10:19:01 -0000       1.42
+++ server/vm/ActionExec.cpp    11 Sep 2007 22:03:06 -0000      1.43
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-/* $Id: ActionExec.cpp,v 1.42 2007/09/04 10:19:01 strk Exp $ */
+/* $Id: ActionExec.cpp,v 1.43 2007/09/11 22:03:06 cmusick Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -86,6 +86,7 @@
        next_pc(pc),
        env(newEnv),
        retval(nRetVal),
+       mReturning(false),
        _abortOnUnload(false)
 {
        //GNASH_REPORT_FUNCTION;
@@ -120,6 +121,7 @@
        next_pc(0),
        env(newEnv),
        retval(0),
+       mReturning(false),
        _abortOnUnload(abortOnUnloaded)
 {
        //GNASH_REPORT_FUNCTION;
@@ -166,8 +168,111 @@
 
        size_t branchCount = 0;
        try {
-       while (pc<stop_pc)
+       while (1) // We might not stop at stop_pc, if we are trying.
        {
+               if (!(pc < stop_pc))
+               {
+                       // Handle try/catch/finally blocks.
+                       if (mTryList.empty())
+                               break; // No try block.
+                       // If we are in a try block, check to see if we have 
thrown.
+                       tryBlock& t = mTryList.back();
+                       if (t.mState == tryBlock::TRY_TRY)
+                       {
+                               if (env.top(0).is_exception()) // We have an 
exception. Catch.
+                               {
+                                       as_value exc = env.pop();
+                                       pc = t.mCatchOffset;
+                                       // Save the exception to the requested 
place.
+                                       exc.unflag_exception();
+                                       if (t.mNamed)
+                                               setLocalVariable(t.mName, exc);
+                                       else
+                                       {
+                                               if (isFunction2() && t.mReg < 
env.num_local_registers())
+                                               {
+                                                       
env.local_register(t.mReg) = exc;
+                                               }
+                                               else if (t.mReg < 4)
+                                               {
+                                                       
env.global_register(t.mReg) = exc;
+                                               }
+                                       }
+
+                                       // Set a new stop.
+                                       stop_pc = t.mFinallyOffset;
+                                       t.mState = tryBlock::TRY_CATCH;
+                               }
+                               else // No exception. Finally.
+                               {
+                                       pc = t.mFinallyOffset;
+                                       stop_pc = t.mAfterTriedOffset;
+                                       t.mState = tryBlock::TRY_FINALLY;
+                               }
+                       }
+                       else if (t.mState == tryBlock::TRY_CATCH) // We've 
caught. Finally.
+                       {
+                               // Here's a fine mess. We've thrown, but we 
still need to
+                               // go to finally.
+
+                               if (env.top(0).is_exception())
+                               {
+                                       // If we set a variable, erase it.
+                                       if (t.mNamed)
+                                               delVariable(t.mName);
+                                       // Save this for 'finally'.
+                                       t.mThrownFromCatch = env.pop();
+                                       pc = t.mFinallyOffset;
+                                       stop_pc = t.mAfterTriedOffset;
+                                       t.mState = tryBlock::TRY_FINALLY;
+                               }
+                               else // No exception. Finally.
+                               {
+                                       pc = t.mFinallyOffset;
+                                       stop_pc = t.mAfterTriedOffset;
+                                       t.mState = tryBlock::TRY_FINALLY;
+                               }
+                       }
+                       else // TRY_FINALLY
+                       {
+                               // No matter how we reached this, this try 
block is done.
+                               tryBlock ts = t;
+                               mTryList.pop_back();
+
+                               // If there is an exception, we're throwing 
from finally.
+                               if (env.top(0).is_exception())
+                               {
+                                       continue; // Leaving it does right.
+                               }
+                               else
+                               {
+                                       // If we have an exception from catch 
and no finally
+                                       // block, throw it.
+                                       if (ts.mThrownFromCatch.is_exception() 
&&
+                                               ts.mFinallyOffset == 
ts.mSavedEndOffset)
+                                       {
+                                               env.push(ts.mThrownFromCatch);
+                                               if (retval)
+                                               {
+                                                       *retval = 
ts.mThrownFromCatch;
+                                               }
+                                               continue;
+                                       }
+                                       else
+                                       {
+                                               pc = ts.mAfterTriedOffset;
+                                               stop_pc = ts.mSavedEndOffset;
+                                               if (mReturning)
+                                               {
+                                                       mReturning = false;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       continue; // Walk up the try chain if necessary.
+               } // end of try checking.
+
                if ( _abortOnUnload && _original_target->isUnloaded() )
                {
                        log_debug("Target of action_buffer unloaded during 
execution, discarding %d remaining opcodes", stop_pc-pc);
@@ -552,6 +657,26 @@
        }
 }
 
+void
+ActionExec::pushTryBlock(tryBlock& t)
+{
+       // The current block should end at the end of the try block.
+       t.mSavedEndOffset = stop_pc;
+       stop_pc = t.mCatchOffset;
+
+       mTryList.push_back(t);
+}
+
+void
+ActionExec::pushReturn(const as_value& t)
+{
+       if (retval)
+       {
+       *retval = t;
+       }
+    mReturning = true;
+}
+
 } // end of namespace gnash
 
 

Index: server/vm/ActionExec.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/ActionExec.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- server/vm/ActionExec.h      4 Sep 2007 10:19:01 -0000       1.21
+++ server/vm/ActionExec.h      11 Sep 2007 22:03:06 -0000      1.22
@@ -35,10 +35,55 @@
        class action_buffer;
        class as_value;
        class swf_function;
+       class ActionExec;
 }
 
 namespace gnash {
 
+class tryBlock
+{
+public:
+       friend class ActionExec;
+
+       enum tryState
+       {
+               TRY_TRY, // In a try block.
+               TRY_CATCH, // In a catch block.
+               TRY_FINALLY // In a finally block.
+       };
+
+    tryBlock(size_t cur_off, size_t try_size, size_t catch_size,
+               size_t finally_size, std::string catchName, int stack_depth)
+               : mCatchOffset(cur_off + try_size),
+               mFinallyOffset(cur_off + try_size + catch_size),
+               mAfterTriedOffset(cur_off + try_size + catch_size + 
finally_size),
+               mNamed(true), mName(catchName), mReg(), 
mState(tryBlock::TRY_TRY),
+               mThrownFromCatch(), mStackDepth(stack_depth)
+       {/**/}
+
+       tryBlock(size_t cur_off, size_t try_size, size_t catch_size,
+               size_t finally_size, uint8_t register_index, int stack_depth)
+               : mCatchOffset(cur_off + try_size),
+               mFinallyOffset(cur_off + try_size + catch_size),
+               mAfterTriedOffset(cur_off + try_size + catch_size + 
finally_size),
+               mNamed(false), mName(), mReg(register_index),
+               mState(tryBlock::TRY_TRY), mThrownFromCatch(),
+               mStackDepth(stack_depth)
+       {/**/}
+
+private:
+       size_t mCatchOffset;
+       size_t mFinallyOffset;
+       size_t mAfterTriedOffset;
+       size_t mSavedEndOffset;
+       bool mNamed;
+       std::string mName;
+       uint8_t mReg;
+       tryState mState;
+       as_value mThrownFromCatch;
+       uint32_t mStackDepth;
+};
+
 /// Executor of an action_buffer 
 class ActionExec {
 
@@ -108,6 +153,10 @@
 
        character* _original_target;
 
+       std::list<tryBlock> mTryList;
+
+       bool mReturning;
+
        /// Warn about a stack underrun and fix it 
        //
        /// The fix is padding the stack with undefined
@@ -143,6 +192,15 @@
                }
        }
 
+       /// \brief
+       /// Use this to push a try block.
+       /// t will be copied
+       void pushTryBlock(tryBlock& t);
+
+       /// \brief
+       /// Set the return value.
+       void pushReturn(const as_value& t);
+
        /// The actual action buffer
        //
        /// TODO: provide a getter and make private
@@ -157,7 +215,7 @@
 
        /// End of current function execution
        //
-       /// TODO: make private
+       /// Used for try/throw/catch blocks.
        ///
        size_t stop_pc;
 

Index: testsuite/misc-mtasc.all/exception.as
===================================================================
RCS file: /sources/gnash/gnash/testsuite/misc-mtasc.all/exception.as,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- testsuite/misc-mtasc.all/exception.as       22 Aug 2007 17:50:25 -0000      
1.3
+++ testsuite/misc-mtasc.all/exception.as       11 Sep 2007 22:03:06 -0000      
1.4
@@ -95,7 +95,7 @@
                        res = e;
                }
                check_equals(typeof(res), 'number');
-               xcheck_equals(res, 1);
+               check_equals(res, 1);
 
                res = 'string';
                try {
@@ -108,7 +108,7 @@
                        res += '_finally';
                }
                check_equals(typeof(res), 'string');
-               xcheck_equals(res, 'thrown_finally');
+               check_equals(res, 'thrown_finally');
 
                res = 'string';
                try {
@@ -125,20 +125,20 @@
                var o = new Object();
                o.num = 1;
                var ret = addOneOnFinal(o);
-               xcheck_equals(ret, 'finally');
-               xcheck_equals(o.num, 2);
+               check_equals(ret, 'finally');
+               check_equals(o.num, 2);
 
                ret = throwAndCatchAddingOne(o);
-               xcheck_equals(ret, 'catch');
-               xcheck_equals(o.num, 3);
+               check_equals(ret, 'catch');
+               check_equals(o.num, 3);
 
                try {
                        ret = throwAndCatchAddingOne(o);
                } catch (e) {
                        ret = 'catch_outside';
                }
-               xcheck_equals(ret, 'catch');
-               xcheck_equals(o.num, 4);
+               check_equals(ret, 'catch');
+               check_equals(o.num, 4);
 
                try {
                        ret = throwFromCatchAddingOne(o);
@@ -147,8 +147,8 @@
                        o.num += 1;
                        ret += e+'_outside';
                }
-               xcheck_equals(ret, 'finally');
-               xcheck_equals(o.num, 5);
+               check_equals(ret, 'finally');
+               check_equals(o.num, 5);
 
                try {
                        throwNested();
@@ -156,7 +156,7 @@
                        note("Catch outside");
                        o.num = e;
                }
-               xcheck_equals(o.num, 'throw');
+               check_equals(o.num, 'throw');
        }
 
        static function main(mc)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]