| Index: test/cctest/test-thread-termination.cc
|
| diff --git a/test/cctest/test-thread-termination.cc b/test/cctest/test-thread-termination.cc
|
| index d31b4131dfcd2e4cf789469416c187ca7c3739a5..250e9a344ada7b818c635dc2ce78f1c926e92649 100644
|
| --- a/test/cctest/test-thread-termination.cc
|
| +++ b/test/cctest/test-thread-termination.cc
|
| @@ -228,6 +228,7 @@ void LoopGetProperty(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| " }"
|
| " fail();"
|
| " } catch(e) {"
|
| + " (function() {})();" // trigger stack check.
|
| " fail();"
|
| " }"
|
| "}"
|
| @@ -474,3 +475,65 @@ TEST(ErrorObjectAfterTermination) {
|
| // TODO(yangguo): crbug/403509. Check for empty handle instead.
|
| CHECK(error->IsUndefined());
|
| }
|
| +
|
| +
|
| +void InnerTryCallTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| + CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
|
| + v8::Handle<v8::Object> global = CcTest::global();
|
| + v8::Handle<v8::Function> loop =
|
| + v8::Handle<v8::Function>::Cast(global->Get(v8_str("loop")));
|
| + i::MaybeHandle<i::Object> result =
|
| + i::Execution::TryCall(v8::Utils::OpenHandle((*loop)),
|
| + v8::Utils::OpenHandle((*global)), 0, NULL, NULL);
|
| + CHECK(result.is_null());
|
| + // TryCall ignores terminate execution, but rerequests the interrupt.
|
| + CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate()));
|
| + CHECK(CompileRun("1 + 1;").IsEmpty());
|
| +}
|
| +
|
| +
|
| +TEST(TerminationInInnerTryCall) {
|
| + v8::Isolate* isolate = CcTest::isolate();
|
| + v8::HandleScope scope(isolate);
|
| + v8::Handle<v8::ObjectTemplate> global_template = CreateGlobalTemplate(
|
| + CcTest::isolate(), TerminateCurrentThread, DoLoopNoCall);
|
| + global_template->Set(
|
| + v8_str("inner_try_call_terminate"),
|
| + v8::FunctionTemplate::New(isolate, InnerTryCallTerminate));
|
| + v8::Handle<v8::Context> context =
|
| + v8::Context::New(CcTest::isolate(), NULL, global_template);
|
| + v8::Context::Scope context_scope(context);
|
| + {
|
| + v8::TryCatch try_catch;
|
| + CompileRun("inner_try_call_terminate()");
|
| + CHECK(try_catch.HasTerminated());
|
| + }
|
| + CHECK_EQ(4, CompileRun("2 + 2")->ToInt32()->Int32Value());
|
| + CHECK(!v8::V8::IsExecutionTerminating());
|
| +}
|
| +
|
| +
|
| +TEST(TerminateAndTryCall) {
|
| + i::FLAG_allow_natives_syntax = true;
|
| + v8::Isolate* isolate = CcTest::isolate();
|
| + v8::HandleScope scope(isolate);
|
| + v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(
|
| + isolate, TerminateCurrentThread, DoLoopCancelTerminate);
|
| + v8::Handle<v8::Context> context = v8::Context::New(isolate, NULL, global);
|
| + v8::Context::Scope context_scope(context);
|
| + CHECK(!v8::V8::IsExecutionTerminating(isolate));
|
| + v8::TryCatch try_catch;
|
| + CHECK(!v8::V8::IsExecutionTerminating(isolate));
|
| + // Terminate execution has been triggered inside TryCall, but re-requested
|
| + // to trigger later.
|
| + CHECK(CompileRun("terminate(); reference_error();").IsEmpty());
|
| + CHECK(try_catch.HasCaught());
|
| + CHECK(!v8::V8::IsExecutionTerminating(isolate));
|
| + CHECK(CcTest::global()->Get(v8_str("terminate"))->IsFunction());
|
| + // The first stack check after terminate has been re-requested fails.
|
| + CHECK(CompileRun("1 + 1").IsEmpty());
|
| + CHECK(!v8::V8::IsExecutionTerminating(isolate));
|
| + // V8 then recovers.
|
| + CHECK_EQ(4, CompileRun("2 + 2")->ToInt32()->Int32Value());
|
| + CHECK(!v8::V8::IsExecutionTerminating(isolate));
|
| +}
|
|
|