[Top][All Lists]
[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)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash ChangeLog server/as_value.cpp server/as_v...,
Chad Musick <=