Introduce API to trigger exception on JS execution.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 19 Mar 2014 13:06:53 +0000 (13:06 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 19 Mar 2014 13:06:53 +0000 (13:06 +0000)
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

include/v8.h
src/api.cc
src/assert-scope.h
src/execution.cc
test/cctest/test-api.cc

index 942ef4d..4ff5830 100644 (file)
@@ -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&);
   };
 
   /**
index 381ca00..871da87 100644 (file)
@@ -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<i::Isolate*>(isolate);
-  internal_ = reinterpret_cast<void*>(
-      new i::DisallowJavascriptExecution(i_isolate));
+  if (on_failure_ == CRASH_ON_FAILURE) {
+    internal_ = reinterpret_cast<void*>(
+        new i::DisallowJavascriptExecution(i_isolate));
+  } else {
+    ASSERT_EQ(THROW_ON_FAILURE, on_failure);
+    internal_ = reinterpret_cast<void*>(
+        new i::ThrowOnJavascriptExecution(i_isolate));
+  }
 }
 
 
 Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() {
-  delete reinterpret_cast<i::DisallowJavascriptExecution*>(internal_);
+  if (on_failure_ == CRASH_ON_FAILURE) {
+    delete reinterpret_cast<i::DisallowJavascriptExecution*>(internal_);
+  } else {
+    delete reinterpret_cast<i::ThrowOnJavascriptExecution*>(internal_);
+  }
 }
 
 
 Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope(
     Isolate* isolate) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  internal_ = reinterpret_cast<void*>(
+  internal_assert_ = reinterpret_cast<void*>(
       new i::AllowJavascriptExecution(i_isolate));
+  internal_throws_ = reinterpret_cast<void*>(
+      new i::NoThrowOnJavascriptExecution(i_isolate));
 }
 
 
 Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() {
-  delete reinterpret_cast<i::AllowJavascriptExecution*>(internal_);
+  delete reinterpret_cast<i::AllowJavascriptExecution*>(internal_assert_);
+  delete reinterpret_cast<i::NoThrowOnJavascriptExecution*>(internal_throws_);
 }
 
 
index 4357056..428e6d0 100644 (file)
@@ -49,6 +49,7 @@ enum PerThreadAssertType {
 
 enum PerIsolateAssertType {
   JAVASCRIPT_EXECUTION_ASSERT,
+  JAVASCRIPT_EXECUTION_THROWS,
   ALLOCATION_FAILURE_ASSERT
 };
 
@@ -251,6 +252,14 @@ typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>
 typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>
     AllowJavascriptExecution;
 
+// Scope in which javascript execution leads to exception being thrown.
+typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>
+    ThrowOnJavascriptExecution;
+
+// Scope to introduce an exception to ThrowOnJavascriptExecution.
+typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>
+    NoThrowOnJavascriptExecution;
+
 // Scope to document where we do not expect an allocation failure.
 typedef PerIsolateAssertScopeDebugOnly<ALLOCATION_FAILURE_ASSERT, false>
     DisallowAllocationFailure;
index bef01a2..924814c 100644 (file)
@@ -78,6 +78,12 @@ static Handle<Object> Invoke(bool is_construct,
   // Entering JavaScript.
   VMState<JS> state(isolate);
   CHECK(AllowJavascriptExecution::IsAllowed(isolate));
+  if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
+    isolate->ThrowIllegalOperation();
+    *has_pending_exception = true;
+    isolate->ReportPendingMessages();
+    return Handle<Object>();
+  }
 
   // Placeholder for return value.
   MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
index 74afab2..d8214e1 100644 (file)
@@ -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());
+}