From 2efd6aa17970d0ae65cea0e3f8593b497cae9825 Mon Sep 17 00:00:00 2001 From: "dcarney@chromium.org" Date: Thu, 26 Sep 2013 07:37:59 +0000 Subject: [PATCH] add isolate parameter to ThrowException R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/24538002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16955 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 15 +++++--- samples/lineprocessor.cc | 2 +- samples/shell.cc | 18 ++++++--- src/api.cc | 27 ++++++++------ src/d8-posix.cc | 51 +++++++++++++++----------- src/extensions/externalize-string-extension.cc | 11 +++--- test/cctest/test-accessors.cc | 4 +- test/cctest/test-api.cc | 35 +++++++++--------- 8 files changed, 93 insertions(+), 70 deletions(-) diff --git a/include/v8.h b/include/v8.h index 62a1cb3..aa392b7 100644 --- a/include/v8.h +++ b/include/v8.h @@ -3791,12 +3791,7 @@ typedef void (*FatalErrorCallback)(const char* location, const char* message); typedef void (*MessageCallback)(Handle message, Handle error); -/** - * Schedules an exception to be thrown when returning to JavaScript. When an - * exception has been scheduled it is illegal to invoke any JavaScript - * operation; the caller must return immediately and only after the exception - * has been handled does it become legal to invoke JavaScript operations. - */ +// TODO(dcarney): remove. Use Isolate::ThrowException instead. Handle V8_EXPORT ThrowException(Handle exception); /** @@ -4052,6 +4047,14 @@ class V8_EXPORT Isolate { Local GetEnteredContext(); /** + * Schedules an exception to be thrown when returning to JavaScript. When an + * exception has been scheduled it is illegal to invoke any JavaScript + * operation; the caller must return immediately and only after the exception + * has been handled does it become legal to invoke JavaScript operations. + */ + Local V8_EXPORT ThrowException(Local exception); + + /** * Allows the host application to group objects together. If one * object in the group is alive, all objects in the group are alive. * After each garbage collection, object groups are removed. It is diff --git a/samples/lineprocessor.cc b/samples/lineprocessor.cc index b4ffb44..39e5159 100644 --- a/samples/lineprocessor.cc +++ b/samples/lineprocessor.cc @@ -417,7 +417,7 @@ void Print(const v8::FunctionCallbackInfo& args) { // function is called. Reads a string from standard input and returns. void ReadLine(const v8::FunctionCallbackInfo& args) { if (args.Length() > 0) { - v8::ThrowException(v8::String::New("Unexpected arguments")); + args.GetIsolate()->ThrowException(v8::String::New("Unexpected arguments")); return; } args.GetReturnValue().Set(ReadLine()); diff --git a/samples/shell.cc b/samples/shell.cc index 710547c..06bd8f6 100644 --- a/samples/shell.cc +++ b/samples/shell.cc @@ -140,17 +140,20 @@ void Print(const v8::FunctionCallbackInfo& args) { // the argument into a JavaScript string. void Read(const v8::FunctionCallbackInfo& args) { if (args.Length() != 1) { - v8::ThrowException(v8::String::New("Bad parameters")); + args.GetIsolate()->ThrowException( + v8::String::New("Bad parameters")); return; } v8::String::Utf8Value file(args[0]); if (*file == NULL) { - v8::ThrowException(v8::String::New("Error loading file")); + args.GetIsolate()->ThrowException( + v8::String::New("Error loading file")); return; } v8::Handle source = ReadFile(*file); if (source.IsEmpty()) { - v8::ThrowException(v8::String::New("Error loading file")); + args.GetIsolate()->ThrowException( + v8::String::New("Error loading file")); return; } args.GetReturnValue().Set(source); @@ -165,12 +168,14 @@ void Load(const v8::FunctionCallbackInfo& args) { v8::HandleScope handle_scope(args.GetIsolate()); v8::String::Utf8Value file(args[i]); if (*file == NULL) { - v8::ThrowException(v8::String::New("Error loading file")); + args.GetIsolate()->ThrowException( + v8::String::New("Error loading file")); return; } v8::Handle source = ReadFile(*file); if (source.IsEmpty()) { - v8::ThrowException(v8::String::New("Error loading file")); + args.GetIsolate()->ThrowException( + v8::String::New("Error loading file")); return; } if (!ExecuteString(args.GetIsolate(), @@ -178,7 +183,8 @@ void Load(const v8::FunctionCallbackInfo& args) { v8::String::New(*file), false, false)) { - v8::ThrowException(v8::String::New("Error executing file")); + args.GetIsolate()->ThrowException( + v8::String::New("Error executing file")); return; } } diff --git a/src/api.cc b/src/api.cc index 6eb3789..017652a 100644 --- a/src/api.cc +++ b/src/api.cc @@ -473,16 +473,7 @@ void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { v8::Handle ThrowException(v8::Handle value) { - i::Isolate* isolate = i::Isolate::Current(); - ENTER_V8(isolate); - // If we're passed an empty handle, we throw an undefined exception - // to deal more gracefully with out of memory situations. - if (value.IsEmpty()) { - isolate->ScheduleThrow(isolate->heap()->undefined_value()); - } else { - isolate->ScheduleThrow(*Utils::OpenHandle(*value)); - } - return v8::Undefined(); + return v8::Isolate::GetCurrent()->ThrowException(value); } @@ -1926,7 +1917,7 @@ v8::TryCatch::~TryCatch() { isolate_->RestorePendingMessageFromTryCatch(this); } isolate_->UnregisterTryCatchHandler(this); - v8::ThrowException(exc); + reinterpret_cast(isolate_)->ThrowException(exc); ASSERT(!isolate_->thread_local_top()->rethrowing_message_); } else { isolate_->UnregisterTryCatchHandler(this); @@ -6361,6 +6352,20 @@ v8::Local Isolate::GetEnteredContext() { } +v8::Local Isolate::ThrowException(v8::Local value) { + i::Isolate* isolate = reinterpret_cast(this); + ENTER_V8(isolate); + // If we're passed an empty handle, we throw an undefined exception + // to deal more gracefully with out of memory situations. + if (value.IsEmpty()) { + isolate->ScheduleThrow(isolate->heap()->undefined_value()); + } else { + isolate->ScheduleThrow(*Utils::OpenHandle(*value)); + } + return v8::Undefined(); +} + + void Isolate::SetObjectGroupId(const Persistent& object, UniqueId id) { i::Isolate* internal_isolate = reinterpret_cast(this); diff --git a/src/d8-posix.cc b/src/d8-posix.cc index 424dbbb..81c15ae 100644 --- a/src/d8-posix.cc +++ b/src/d8-posix.cc @@ -245,7 +245,8 @@ static bool GetTimeouts(const v8::FunctionCallbackInfo& args, if (args[3]->IsNumber()) { *total_timeout = args[3]->Int32Value(); } else { - ThrowException(String::New("system: Argument 4 must be a number")); + args.GetIsolate()->ThrowException( + String::New("system: Argument 4 must be a number")); return false; } } @@ -253,7 +254,8 @@ static bool GetTimeouts(const v8::FunctionCallbackInfo& args, if (args[2]->IsNumber()) { *read_timeout = args[2]->Int32Value(); } else { - ThrowException(String::New("system: Argument 3 must be a number")); + args.GetIsolate()->ThrowException( + String::New("system: Argument 3 must be a number")); return false; } } @@ -456,7 +458,8 @@ void Shell::System(const v8::FunctionCallbackInfo& args) { Handle command_args; if (args.Length() > 1) { if (!args[1]->IsArray()) { - ThrowException(String::New("system: Argument 2 must be an array")); + args.GetIsolate()->ThrowException( + String::New("system: Argument 2 must be an array")); return; } command_args = Handle::Cast(args[1]); @@ -464,11 +467,13 @@ void Shell::System(const v8::FunctionCallbackInfo& args) { command_args = Array::New(0); } if (command_args->Length() > ExecArgs::kMaxArgs) { - ThrowException(String::New("Too many arguments to system()")); + args.GetIsolate()->ThrowException( + String::New("Too many arguments to system()")); return; } if (args.Length() < 1) { - ThrowException(String::New("Too few arguments to system()")); + args.GetIsolate()->ThrowException( + String::New("Too few arguments to system()")); return; } @@ -483,11 +488,13 @@ void Shell::System(const v8::FunctionCallbackInfo& args) { int stdout_fds[2]; if (pipe(exec_error_fds) != 0) { - ThrowException(String::New("pipe syscall failed.")); + args.GetIsolate()->ThrowException( + String::New("pipe syscall failed.")); return; } if (pipe(stdout_fds) != 0) { - ThrowException(String::New("pipe syscall failed.")); + args.GetIsolate()->ThrowException( + String::New("pipe syscall failed.")); return; } @@ -531,17 +538,17 @@ void Shell::System(const v8::FunctionCallbackInfo& args) { void Shell::ChangeDirectory(const v8::FunctionCallbackInfo& args) { if (args.Length() != 1) { const char* message = "chdir() takes one argument"; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } String::Utf8Value directory(args[0]); if (*directory == NULL) { const char* message = "os.chdir(): String conversion of argument failed."; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } if (chdir(*directory) != 0) { - ThrowException(String::New(strerror(errno))); + args.GetIsolate()->ThrowException(String::New(strerror(errno))); return; } } @@ -550,7 +557,7 @@ void Shell::ChangeDirectory(const v8::FunctionCallbackInfo& args) { void Shell::SetUMask(const v8::FunctionCallbackInfo& args) { if (args.Length() != 1) { const char* message = "umask() takes one argument"; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } if (args[0]->IsNumber()) { @@ -560,7 +567,7 @@ void Shell::SetUMask(const v8::FunctionCallbackInfo& args) { return; } else { const char* message = "umask() argument must be numeric"; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } } @@ -616,18 +623,18 @@ void Shell::MakeDirectory(const v8::FunctionCallbackInfo& args) { mask = args[1]->Int32Value(); } else { const char* message = "mkdirp() second argument must be numeric"; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } } else if (args.Length() != 1) { const char* message = "mkdirp() takes one or two arguments"; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } String::Utf8Value directory(args[0]); if (*directory == NULL) { const char* message = "os.mkdirp(): String conversion of argument failed."; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } mkdirp(*directory, mask); @@ -637,13 +644,13 @@ void Shell::MakeDirectory(const v8::FunctionCallbackInfo& args) { void Shell::RemoveDirectory(const v8::FunctionCallbackInfo& args) { if (args.Length() != 1) { const char* message = "rmdir() takes one or two arguments"; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } String::Utf8Value directory(args[0]); if (*directory == NULL) { const char* message = "os.rmdir(): String conversion of argument failed."; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } rmdir(*directory); @@ -653,7 +660,7 @@ void Shell::RemoveDirectory(const v8::FunctionCallbackInfo& args) { void Shell::SetEnvironment(const v8::FunctionCallbackInfo& args) { if (args.Length() != 2) { const char* message = "setenv() takes two arguments"; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } String::Utf8Value var(args[0]); @@ -661,13 +668,13 @@ void Shell::SetEnvironment(const v8::FunctionCallbackInfo& args) { if (*var == NULL) { const char* message = "os.setenv(): String conversion of variable name failed."; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } if (*value == NULL) { const char* message = "os.setenv(): String conversion of variable contents failed."; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } setenv(*var, *value, 1); @@ -677,14 +684,14 @@ void Shell::SetEnvironment(const v8::FunctionCallbackInfo& args) { void Shell::UnsetEnvironment(const v8::FunctionCallbackInfo& args) { if (args.Length() != 1) { const char* message = "unsetenv() takes one argument"; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } String::Utf8Value var(args[0]); if (*var == NULL) { const char* message = "os.setenv(): String conversion of variable name failed."; - ThrowException(String::New(message)); + args.GetIsolate()->ThrowException(String::New(message)); return; } unsetenv(*var); diff --git a/src/extensions/externalize-string-extension.cc b/src/extensions/externalize-string-extension.cc index 5fd821b..9fdb194 100644 --- a/src/extensions/externalize-string-extension.cc +++ b/src/extensions/externalize-string-extension.cc @@ -75,7 +75,7 @@ v8::Handle ExternalizeStringExtension::GetNativeFunction( void ExternalizeStringExtension::Externalize( const v8::FunctionCallbackInfo& args) { if (args.Length() < 1 || !args[0]->IsString()) { - v8::ThrowException(v8::String::New( + args.GetIsolate()->ThrowException(v8::String::New( "First parameter to externalizeString() must be a string.")); return; } @@ -84,7 +84,7 @@ void ExternalizeStringExtension::Externalize( if (args[1]->IsBoolean()) { force_two_byte = args[1]->BooleanValue(); } else { - v8::ThrowException(v8::String::New( + args.GetIsolate()->ThrowException(v8::String::New( "Second parameter to externalizeString() must be a boolean.")); return; } @@ -92,7 +92,7 @@ void ExternalizeStringExtension::Externalize( bool result = false; Handle string = Utils::OpenHandle(*args[0].As()); if (string->IsExternalString()) { - v8::ThrowException(v8::String::New( + args.GetIsolate()->ThrowException(v8::String::New( "externalizeString() can't externalize twice.")); return; } @@ -120,7 +120,8 @@ void ExternalizeStringExtension::Externalize( if (!result) delete resource; } if (!result) { - v8::ThrowException(v8::String::New("externalizeString() failed.")); + args.GetIsolate()->ThrowException( + v8::String::New("externalizeString() failed.")); return; } } @@ -129,7 +130,7 @@ void ExternalizeStringExtension::Externalize( void ExternalizeStringExtension::IsAscii( const v8::FunctionCallbackInfo& args) { if (args.Length() != 1 || !args[0]->IsString()) { - v8::ThrowException(v8::String::New( + args.GetIsolate()->ThrowException(v8::String::New( "isAsciiString() requires a single string argument.")); return; } diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc index c3148ff..3f3589c 100644 --- a/test/cctest/test-accessors.cc +++ b/test/cctest/test-accessors.cc @@ -405,14 +405,14 @@ static void ThrowingGetAccessor( Local name, const v8::PropertyCallbackInfo& info) { ApiTestFuzzer::Fuzz(); - v8::ThrowException(v8_str("g")); + info.GetIsolate()->ThrowException(v8_str("g")); } static void ThrowingSetAccessor(Local name, Local value, const v8::PropertyCallbackInfo& info) { - v8::ThrowException(value); + info.GetIsolate()->ThrowException(value); } diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index cfebeff..55e0ea3 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -2451,7 +2451,7 @@ static void ThrowingPropertyHandlerGet( Local key, const v8::PropertyCallbackInfo& info) { ApiTestFuzzer::Fuzz(); - info.GetReturnValue().Set(v8::ThrowException(key)); + info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key)); } @@ -2459,7 +2459,7 @@ static void ThrowingPropertyHandlerSet( Local key, Local, const v8::PropertyCallbackInfo& info) { - v8::ThrowException(key); + info.GetIsolate()->ThrowException(key); info.GetReturnValue().SetUndefined(); // not the same as empty handle } @@ -4375,7 +4375,7 @@ THREADED_TEST(ConversionException) { void ThrowFromC(const v8::FunctionCallbackInfo& args) { ApiTestFuzzer::Fuzz(); - v8::ThrowException(v8_str("konto")); + args.GetIsolate()->ThrowException(v8_str("konto")); } @@ -4658,7 +4658,7 @@ void CThrowCountDown(const v8::FunctionCallbackInfo& args) { int count = args[0]->Int32Value(); int cInterval = args[2]->Int32Value(); if (count == 0) { - v8::ThrowException(v8_str("FromC")); + args.GetIsolate()->ThrowException(v8_str("FromC")); return; } else { Local global = @@ -4798,7 +4798,7 @@ TEST(ExceptionOrder) { void ThrowValue(const v8::FunctionCallbackInfo& args) { ApiTestFuzzer::Fuzz(); CHECK_EQ(1, args.Length()); - v8::ThrowException(args[0]); + args.GetIsolate()->ThrowException(args[0]); } @@ -4896,7 +4896,7 @@ static void TryCatchNestedHelper(int depth) { CHECK(try_catch.HasCaught()); try_catch.ReThrow(); } else { - v8::ThrowException(v8_str("back")); + CcTest::isolate()->ThrowException(v8_str("back")); } } @@ -11259,7 +11259,7 @@ THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) { void ThrowingDirectApiCallback( const v8::FunctionCallbackInfo& args) { - v8::ThrowException(v8_str("g")); + args.GetIsolate()->ThrowException(v8_str("g")); } @@ -11327,7 +11327,7 @@ THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) { void ThrowingDirectGetterCallback( Local name, const v8::PropertyCallbackInfo& info) { - v8::ThrowException(v8_str("g")); + info.GetIsolate()->ThrowException(v8_str("g")); } @@ -11938,7 +11938,7 @@ static void InterceptorICExceptionGetter( info.GetReturnValue().Set(call_ic_function3); } if (interceptor_ic_exception_get_count == 20) { - v8::ThrowException(v8_num(42)); + info.GetIsolate()->ThrowException(v8_num(42)); return; } } @@ -11983,7 +11983,7 @@ static void InterceptorICExceptionSetter( const v8::PropertyCallbackInfo& info) { ApiTestFuzzer::Fuzz(); if (++interceptor_ic_exception_set_count > 20) { - v8::ThrowException(v8_num(42)); + info.GetIsolate()->ThrowException(v8_num(42)); } } @@ -12055,7 +12055,7 @@ THREADED_TEST(NamedPropertyHandlerGetterAttributes) { static void ThrowingGetter(Local name, const v8::PropertyCallbackInfo& info) { ApiTestFuzzer::Fuzz(); - ThrowException(Handle()); + info.GetIsolate()->ThrowException(Handle()); info.GetReturnValue().SetUndefined(); } @@ -12140,7 +12140,7 @@ static void ThrowFromJS(Handle message, Handle data) { static void ThrowViaApi(Handle message, Handle data) { - if (--call_depth) ThrowException(v8_str("ThrowViaApi")); + if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi")); } @@ -12499,12 +12499,12 @@ void ApiTestFuzzer::CallTest() { static void ThrowInJS(const v8::FunctionCallbackInfo& args) { - CHECK(v8::Locker::IsLocked(CcTest::isolate())); + CHECK(v8::Locker::IsLocked(args.GetIsolate())); ApiTestFuzzer::Fuzz(); - v8::Unlocker unlocker(CcTest::isolate()); + v8::Unlocker unlocker(args.GetIsolate()); const char* code = "throw 7;"; { - v8::Locker nested_locker(CcTest::isolate()); + v8::Locker nested_locker(args.GetIsolate()); v8::HandleScope scope(args.GetIsolate()); v8::Handle exception; { v8::TryCatch try_catch; @@ -12516,7 +12516,7 @@ static void ThrowInJS(const v8::FunctionCallbackInfo& args) { // when the TryCatch is destroyed. exception = Local::New(try_catch.Exception()); } - v8::ThrowException(exception); + args.GetIsolate()->ThrowException(exception); } } @@ -20341,7 +20341,8 @@ void FailedAccessCheckThrows(Local target, Local data) { access_check_fail_thrown = true; i::PrintF("Access check failed. Error thrown.\n"); - v8::ThrowException(v8::Exception::Error(v8_str("cross context"))); + CcTest::isolate()->ThrowException( + v8::Exception::Error(v8_str("cross context"))); } -- 2.7.4