From: yangguo@chromium.org Date: Wed, 19 Mar 2014 13:06:53 +0000 (+0000) Subject: Introduce API to trigger exception on JS execution. X-Git-Tag: upstream/4.7.83~10170 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d8c3c5ef0a83ee3311c93412acf938646738e020;p=platform%2Fupstream%2Fv8.git Introduce API to trigger exception on JS execution. R=jochen@chromium.org, pmarch@chromium.org Review URL: https://codereview.chromium.org/203223013 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20070 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/include/v8.h b/include/v8.h index 942ef4d..4ff5830 100644 --- a/include/v8.h +++ b/include/v8.h @@ -4090,10 +4090,14 @@ class V8_EXPORT Isolate { */ class DisallowJavascriptExecutionScope { public: - explicit DisallowJavascriptExecutionScope(Isolate* isolate); + enum OnFailure { CRASH_ON_FAILURE, THROW_ON_FAILURE }; + + explicit DisallowJavascriptExecutionScope(Isolate* isolate, + OnFailure on_failure); ~DisallowJavascriptExecutionScope(); private: + bool on_failure_; void* internal_; // Prevent copying of Scope objects. @@ -4112,7 +4116,13 @@ class V8_EXPORT Isolate { ~AllowJavascriptExecutionScope(); private: - void* internal_; + void* internal_throws_; + void* internal_assert_; + + // Prevent copying of Scope objects. + AllowJavascriptExecutionScope(const AllowJavascriptExecutionScope&); + AllowJavascriptExecutionScope& operator=( + const AllowJavascriptExecutionScope&); }; /** diff --git a/src/api.cc b/src/api.cc index 381ca00..871da87 100644 --- a/src/api.cc +++ b/src/api.cc @@ -6515,28 +6515,43 @@ void Isolate::Exit() { Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope( - Isolate* isolate) { + Isolate* isolate, + Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure) + : on_failure_(on_failure) { i::Isolate* i_isolate = reinterpret_cast(isolate); - internal_ = reinterpret_cast( - new i::DisallowJavascriptExecution(i_isolate)); + if (on_failure_ == CRASH_ON_FAILURE) { + internal_ = reinterpret_cast( + new i::DisallowJavascriptExecution(i_isolate)); + } else { + ASSERT_EQ(THROW_ON_FAILURE, on_failure); + internal_ = reinterpret_cast( + new i::ThrowOnJavascriptExecution(i_isolate)); + } } Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() { - delete reinterpret_cast(internal_); + if (on_failure_ == CRASH_ON_FAILURE) { + delete reinterpret_cast(internal_); + } else { + delete reinterpret_cast(internal_); + } } Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope( Isolate* isolate) { i::Isolate* i_isolate = reinterpret_cast(isolate); - internal_ = reinterpret_cast( + internal_assert_ = reinterpret_cast( new i::AllowJavascriptExecution(i_isolate)); + internal_throws_ = reinterpret_cast( + new i::NoThrowOnJavascriptExecution(i_isolate)); } Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() { - delete reinterpret_cast(internal_); + delete reinterpret_cast(internal_assert_); + delete reinterpret_cast(internal_throws_); } diff --git a/src/assert-scope.h b/src/assert-scope.h index 4357056..428e6d0 100644 --- a/src/assert-scope.h +++ b/src/assert-scope.h @@ -49,6 +49,7 @@ enum PerThreadAssertType { enum PerIsolateAssertType { JAVASCRIPT_EXECUTION_ASSERT, + JAVASCRIPT_EXECUTION_THROWS, ALLOCATION_FAILURE_ASSERT }; @@ -251,6 +252,14 @@ typedef PerIsolateAssertScope typedef PerIsolateAssertScope AllowJavascriptExecution; +// Scope in which javascript execution leads to exception being thrown. +typedef PerIsolateAssertScope + ThrowOnJavascriptExecution; + +// Scope to introduce an exception to ThrowOnJavascriptExecution. +typedef PerIsolateAssertScope + NoThrowOnJavascriptExecution; + // Scope to document where we do not expect an allocation failure. typedef PerIsolateAssertScopeDebugOnly DisallowAllocationFailure; diff --git a/src/execution.cc b/src/execution.cc index bef01a2..924814c 100644 --- a/src/execution.cc +++ b/src/execution.cc @@ -78,6 +78,12 @@ static Handle Invoke(bool is_construct, // Entering JavaScript. VMState state(isolate); CHECK(AllowJavascriptExecution::IsAllowed(isolate)); + if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) { + isolate->ThrowIllegalOperation(); + *has_pending_exception = true; + isolate->ReportPendingMessages(); + return Handle(); + } // Placeholder for return value. MaybeObject* value = reinterpret_cast(kZapValue); diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 74afab2..d8214e1 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -22399,7 +22399,8 @@ TEST(DisallowJavascriptExecutionScope) { LocalContext context; v8::Isolate* isolate = context->GetIsolate(); v8::HandleScope scope(isolate); - v8::Isolate::DisallowJavascriptExecutionScope no_js(isolate); + v8::Isolate::DisallowJavascriptExecutionScope no_js( + isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE); CompileRun("2+2"); } @@ -22408,8 +22409,23 @@ TEST(AllowJavascriptExecutionScope) { LocalContext context; v8::Isolate* isolate = context->GetIsolate(); v8::HandleScope scope(isolate); - v8::Isolate::DisallowJavascriptExecutionScope no_js(isolate); + v8::Isolate::DisallowJavascriptExecutionScope no_js( + isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE); + v8::Isolate::DisallowJavascriptExecutionScope throw_js( + isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE); { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate); CompileRun("1+1"); } } + + +TEST(ThrowOnJavascriptExecution) { + LocalContext context; + v8::Isolate* isolate = context->GetIsolate(); + v8::HandleScope scope(isolate); + v8::TryCatch try_catch; + v8::Isolate::DisallowJavascriptExecutionScope throw_js( + isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE); + CompileRun("1+1"); + CHECK(try_catch.HasCaught()); +}