// Generate code and return it.
Handle<Code> result = CodeGenerator::MakeCode(literal, script, is_eval);
+ // Check for stack-overflow exception.
+ if (result.is_null()) {
+ Top::StackOverflow();
+ Top::ReportPendingMessages();
+ }
return result;
}
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
+ Top::ReportPendingMessages();
return Handle<JSFunction>::null();
}
// Check for stack-overflow exceptions.
if (code.is_null()) {
- Top::StackOverflow();
return Handle<JSFunction>::null();
}
}
}
+ if (result.is_null()) Top::ReportPendingMessages();
+
return result;
}
CompilationCache::PutFunction(source, entry, result);
}
}
+
+ if (result.is_null()) Top::ReportPendingMessages();
+
return result;
}
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
+ Top::ReportPendingMessages();
return false;
}
// Compile the code.
Handle<Code> code = MakeCode(lit, script, false);
- // Check for stack-overflow exception.
if (code.is_null()) {
- Top::StackOverflow();
return false;
}
*has_pending_exception = value->IsException();
ASSERT(*has_pending_exception == Top::has_pending_exception());
if (*has_pending_exception) {
- Top::setup_external_caught();
- // If the pending exception is OutOfMemoryException set out_of_memory in
- // the global context. Note: We have to mark the global context here
- // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
- // set it.
- if (Top::pending_exception() == Failure::OutOfMemoryException()) {
- Top::context()->mark_out_of_memory();
- }
+ Top::ReportPendingMessages();
return Handle<Object>();
+ } else {
+ Top::clear_pending_message();
}
return Handle<Object>(value);
void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
v->VisitPointer(&(thread->pending_exception_));
+ v->VisitPointer(&(thread->pending_message_obj_));
+ v->VisitPointer(
+ bit_cast<Object**, Script**>(&(thread->pending_message_script_)));
v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_)));
v->VisitPointer(&(thread->scheduled_exception_));
thread_local_.external_caught_exception_ = false;
thread_local_.failed_access_check_callback_ = NULL;
clear_pending_exception();
+ clear_pending_message();
clear_scheduled_exception();
thread_local_.save_context_ = NULL;
thread_local_.catcher_ = NULL;
// Determine reporting and whether the exception is caught externally.
bool is_caught_externally = false;
- bool report_exception = (exception != Failure::OutOfMemoryException()) &&
- ShouldReportException(&is_caught_externally);
+ bool is_out_of_memory = exception == Failure::OutOfMemoryException();
+ bool should_return_exception = ShouldReportException(&is_caught_externally);
+ bool report_exception = !is_out_of_memory && should_return_exception;
+
+
+ // Notify debugger of exception.
+ Debugger::OnException(exception_handle, report_exception);
// Generate the message.
Handle<Object> message_obj;
location, HandleVector<Object>(&exception_handle, 1), stack_trace);
}
- // If the exception is caught externally, we store it in the
- // try/catch handler. The C code can find it later and process it if
- // necessary.
- thread_local_.catcher_ = NULL;
+ // Save the message for reporting if the the exception remains uncaught.
+ thread_local_.pending_message_ = message;
+ if (!message_obj.is_null()) {
+ thread_local_.pending_message_obj_ = *message_obj;
+ if (location != NULL) {
+ thread_local_.pending_message_script_ = *location->script();
+ thread_local_.pending_message_start_pos_ = location->start_pos();
+ thread_local_.pending_message_end_pos_ = location->end_pos();
+ }
+ }
+
if (is_caught_externally) {
thread_local_.catcher_ = thread_local_.try_catch_handler_;
- thread_local_.try_catch_handler_->exception_ =
- reinterpret_cast<void*>(*exception_handle);
- if (!message_obj.is_null()) {
- thread_local_.try_catch_handler_->message_ =
- reinterpret_cast<void*>(*message_obj);
- }
}
- // Notify debugger of exception.
- Debugger::OnException(exception_handle, report_exception);
+ // NOTE: Notifying the debugger or generating the message
+ // may have caused new exceptions. For now, we just ignore
+ // that and set the pending exception to the original one.
+ set_pending_exception(*exception_handle);
+}
- if (report_exception) {
- if (message != NULL) {
- MessageHandler::ReportMessage(message);
- } else if (!message_obj.is_null()) {
- MessageHandler::ReportMessage(location, message_obj);
+
+void Top::ReportPendingMessages() {
+ ASSERT(has_pending_exception());
+ setup_external_caught();
+ // If the pending exception is OutOfMemoryException set out_of_memory in
+ // the global context. Note: We have to mark the global context here
+ // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
+ // set it.
+ HandleScope scope;
+ if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) {
+ context()->mark_out_of_memory();
+ } else {
+ Handle<Object> exception(pending_exception());
+ if (thread_local_.external_caught_exception_) {
+ thread_local_.try_catch_handler_->exception_ =
+ thread_local_.pending_exception_;
+ if (!thread_local_.pending_message_obj_->IsTheHole()) {
+ try_catch_handler()->message_ = thread_local_.pending_message_obj_;
+ }
+ } else if (thread_local_.pending_message_ != NULL) {
+ MessageHandler::ReportMessage(thread_local_.pending_message_);
+ } else if (!thread_local_.pending_message_obj_->IsTheHole()) {
+ Handle<Object> message_obj(thread_local_.pending_message_obj_);
+ if (thread_local_.pending_message_script_ != NULL) {
+ Handle<Script> script(thread_local_.pending_message_script_);
+ int start_pos = thread_local_.pending_message_start_pos_;
+ int end_pos = thread_local_.pending_message_end_pos_;
+ MessageLocation location(script, start_pos, end_pos);
+ MessageHandler::ReportMessage(&location, message_obj);
+ } else {
+ MessageHandler::ReportMessage(NULL, message_obj);
+ }
}
+ set_pending_exception(*exception);
}
-
- // NOTE: Notifying the debugger or reporting the exception may have caused
- // new exceptions. For now, we just ignore that and set the pending exception
- // to the original one.
- set_pending_exception(*exception_handle);
+ clear_pending_message();
}
// lookups.
Context* context_;
Object* pending_exception_;
+ const char* pending_message_;
+ Object* pending_message_obj_;
+ Script* pending_message_script_;
+ int pending_message_start_pos_;
+ int pending_message_end_pos_;
// Use a separate value for scheduled exceptions to preserve the
// invariants that hold about pending_exception. We may want to
// unify them later.
static bool has_pending_exception() {
return !thread_local_.pending_exception_->IsTheHole();
}
+ static void clear_pending_message() {
+ thread_local_.catcher_ = NULL;
+ thread_local_.pending_message_ = NULL;
+ thread_local_.pending_message_obj_ = Heap::the_hole_value();
+ thread_local_.pending_message_script_ = NULL;
+ }
static v8::TryCatch* try_catch_handler() {
return thread_local_.try_catch_handler_;
}
static void setup_external_caught() {
thread_local_.external_caught_exception_ =
+ (!thread_local_.pending_exception_->IsTheHole()) &&
(thread_local_.catcher_ != NULL) &&
(Top::thread_local_.try_catch_handler_ == Top::thread_local_.catcher_);
}
// originally.
static Failure* ReThrow(Object* exception, MessageLocation* location = NULL);
static void ScheduleThrow(Object* exception);
+ static void ReportPendingMessages();
// Promote a scheduled exception to pending. Asserts has_scheduled_exception.
static Object* PromoteScheduledException();
// Counts uncaught exceptions, but other tests running in parallel
// also have uncaught exceptions.
TEST(ApiUncaughtException) {
+ report_count = 0;
v8::HandleScope scope;
LocalContext env;
v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
CHECK(trouble_caller->IsFunction());
Function::Cast(*trouble_caller)->Call(global, 0, NULL);
CHECK_EQ(1, report_count);
+ v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
+}
+
+
+TEST(CompilationErrorUsingTryCatchHandler) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::TryCatch try_catch;
+ Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
+ CHECK_NE(NULL, *try_catch.Exception());
+ CHECK(try_catch.HasCaught());
+}
+
+
+TEST(TryCatchFinallyUsingTryCatchHandler) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::TryCatch try_catch;
+ Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
+ CHECK(!try_catch.HasCaught());
+ Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
+ CHECK(try_catch.HasCaught());
+ try_catch.Reset();
+ Script::Compile(v8_str("(function() {"
+ "try { throw ''; } finally { return; }"
+ "})()"))->Run();
+ CHECK(!try_catch.HasCaught());
+ Script::Compile(v8_str("(function()"
+ " { try { throw ''; } finally { throw 0; }"
+ "})()"))->Run();
+ CHECK(try_catch.HasCaught());
}
--- /dev/null
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function f() {
+ try {
+ throw "foo";
+ return 7;
+ } catch (e) {
+ "bar"
+ } finally {
+ return 42;
+ }
+}
+
+print(f());
--- /dev/null
+# Copyright 2008 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+42
--- /dev/null
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function f() {
+ try {
+ throw "foo";
+ return 7;
+ } finally {
+ return 42;
+ }
+}
+
+print(f());
--- /dev/null
+# Copyright 2008 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+42