1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h" 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochv8::base::Semaphore* semaphore = NULL; 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Signal(const v8::FunctionCallbackInfo<v8::Value>& args) { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block semaphore->Signal(); 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid TerminateCurrentThread(const v8::FunctionCallbackInfo<v8::Value>& args) { 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::V8::TerminateExecution(args.GetIsolate()); 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Fail(const v8::FunctionCallbackInfo<v8::Value>& args) { 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(false); 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Loop(const v8::FunctionCallbackInfo<v8::Value>& args) { 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::String> source = v8::String::NewFromUtf8( 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch args.GetIsolate(), "try { doloop(); fail(); } catch(e) { fail(); }"); 576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block v8::Handle<v8::Value> result = v8::Script::Compile(source)->Run(); 586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CHECK(result.IsEmpty()); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate())); 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DoLoop(const v8::FunctionCallbackInfo<v8::Value>& args) { 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::TryCatch try_catch; 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(), 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "function f() {" 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " var term = true;" 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " try {" 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " while(true) {" 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " if (term) terminate();" 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " term = false;" 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " }" 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " fail();" 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " } catch(e) {" 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " fail();" 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " }" 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "}" 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "f()"))->Run(); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(try_catch.HasCaught()); 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(try_catch.Exception()->IsNull()); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(try_catch.Message().IsEmpty()); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(!try_catch.CanContinue()); 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate())); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DoLoopNoCall(const v8::FunctionCallbackInfo<v8::Value>& args) { 89d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block v8::TryCatch try_catch; 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(), 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "var term = true;" 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "while(true) {" 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " if (term) terminate();" 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " term = false;" 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "}"))->Run(); 97d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK(try_catch.HasCaught()); 98d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK(try_catch.Exception()->IsNull()); 99d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK(try_catch.Message().IsEmpty()); 100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK(!try_catch.CanContinue()); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate())); 102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::ObjectTemplate> CreateGlobalTemplate( 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Isolate* isolate, 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::FunctionCallback terminate, 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::FunctionCallback doloop) { 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global->Set(v8::String::NewFromUtf8(isolate, "terminate"), 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::FunctionTemplate::New(isolate, terminate)); 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global->Set(v8::String::NewFromUtf8(isolate, "fail"), 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::FunctionTemplate::New(isolate, Fail)); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global->Set(v8::String::NewFromUtf8(isolate, "loop"), 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::FunctionTemplate::New(isolate, Loop)); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global->Set(v8::String::NewFromUtf8(isolate, "doloop"), 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::FunctionTemplate::New(isolate, doloop)); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return global; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that a single thread of JavaScript execution can terminate 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// itself. 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(TerminateOnlyV8ThreadFromThreadItself) { 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(CcTest::isolate()); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::ObjectTemplate> global = 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateGlobalTemplate(CcTest::isolate(), TerminateCurrentThread, DoLoop); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::Context> context = 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::New(CcTest::isolate(), NULL, global); 130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block v8::Context::Scope context_scope(context); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate())); 132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Run a loop that will be infinite if thread termination does not work. 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::String> source = v8::String::NewFromUtf8( 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::isolate(), "try { loop(); fail(); } catch(e) { fail(); }"); 135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block v8::Script::Compile(source)->Run(); 136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Test that we can run the code again after thread termination. 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate())); 138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block v8::Script::Compile(source)->Run(); 139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Test that a single thread of JavaScript execution can terminate 143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// itself in a loop that performs no calls. 144d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockTEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) { 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(CcTest::isolate()); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate( 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::isolate(), TerminateCurrentThread, DoLoopNoCall); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::Context> context = 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::New(CcTest::isolate(), NULL, global); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Context::Scope context_scope(context); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate())); 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run a loop that will be infinite if thread termination does not work. 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::String> source = v8::String::NewFromUtf8( 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::isolate(), "try { loop(); fail(); } catch(e) { fail(); }"); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Script::Compile(source)->Run(); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate())); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Test that we can run the code again after thread termination. 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Script::Compile(source)->Run(); 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass TerminatorThread : public v8::base::Thread { 16344f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 16444f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit TerminatorThread(i::Isolate* isolate) 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Thread(Options("TerminatorThread")), 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate_(reinterpret_cast<v8::Isolate*>(isolate)) {} 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Run() { 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block semaphore->Wait(); 1693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK(!v8::V8::IsExecutionTerminating(isolate_)); 1703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch v8::V8::TerminateExecution(isolate_); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch v8::Isolate* isolate_; 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that a single thread of JavaScript execution can be terminated 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from the side by another thread. 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(TerminateOnlyV8ThreadFromOtherThread) { 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore = new v8::base::Semaphore(0); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TerminatorThread thread(CcTest::i_isolate()); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block thread.Start(); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(CcTest::isolate()); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::ObjectTemplate> global = 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateGlobalTemplate(CcTest::isolate(), Signal, DoLoop); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::Context> context = 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::New(CcTest::isolate(), NULL, global); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Context::Scope context_scope(context); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate())); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run a loop that will be infinite if thread termination does not work. 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::String> source = v8::String::NewFromUtf8( 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::isolate(), "try { loop(); fail(); } catch(e) { fail(); }"); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Script::Compile(source)->Run(); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block thread.Join(); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete semaphore; 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block semaphore = NULL; 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint call_count = 0; 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid TerminateOrReturnObject(const v8::FunctionCallbackInfo<v8::Value>& args) { 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (++call_count == 10) { 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::V8::TerminateExecution(args.GetIsolate()); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Local<v8::Object> result = v8::Object::New(args.GetIsolate()); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result->Set(v8::String::NewFromUtf8(args.GetIsolate(), "x"), 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Integer::New(args.GetIsolate(), 42)); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch args.GetReturnValue().Set(result); 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LoopGetProperty(const v8::FunctionCallbackInfo<v8::Value>& args) { 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::TryCatch try_catch; 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Script::Compile( 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::String::NewFromUtf8(args.GetIsolate(), 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "function f() {" 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " try {" 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " while(true) {" 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " terminate_or_return_object().x;" 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " }" 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " fail();" 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " } catch(e) {" 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " fail();" 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " }" 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "}" 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "f()"))->Run(); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(try_catch.HasCaught()); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(try_catch.Exception()->IsNull()); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(try_catch.Message().IsEmpty()); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(!try_catch.CanContinue()); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate())); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that we correctly handle termination exceptions if they are 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// triggered by the creation of error objects in connection with ICs. 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(TerminateLoadICException) { 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Isolate* isolate = CcTest::isolate(); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(isolate); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global->Set( 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::String::NewFromUtf8(isolate, "terminate_or_return_object"), 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::FunctionTemplate::New(isolate, TerminateOrReturnObject)); 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global->Set(v8::String::NewFromUtf8(isolate, "fail"), 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::FunctionTemplate::New(isolate, Fail)); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global->Set(v8::String::NewFromUtf8(isolate, "loop"), 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::FunctionTemplate::New(isolate, LoopGetProperty)); 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::Context> context = 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::New(isolate, NULL, global); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Context::Scope context_scope(context); 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(isolate)); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run a loop that will be infinite if thread termination does not work. 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::String> source = v8::String::NewFromUtf8( 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate, "try { loop(); fail(); } catch(e) { fail(); }"); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_count = 0; 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Script::Compile(source)->Run(); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Test that we can run the code again after thread termination. 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(isolate)); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block call_count = 0; 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Script::Compile(source)->Run(); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ReenterAfterTermination(const v8::FunctionCallbackInfo<v8::Value>& args) { 274f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke v8::TryCatch try_catch; 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(), 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "function f() {" 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " var term = true;" 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " try {" 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " while(true) {" 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " if (term) terminate();" 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " term = false;" 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " }" 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " fail();" 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " } catch(e) {" 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " fail();" 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " }" 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "}" 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "f()"))->Run(); 290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CHECK(try_catch.HasCaught()); 291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CHECK(try_catch.Exception()->IsNull()); 292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CHECK(try_catch.Message().IsEmpty()); 293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CHECK(!try_catch.CanContinue()); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(v8::V8::IsExecutionTerminating(args.GetIsolate())); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(), 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "function f() { fail(); } f()")) 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->Run(); 298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Test that reentry into V8 while the termination exception is still pending 302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// (has not yet unwound the 0-level JS frame) does not crash. 303f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeTEST(TerminateAndReenterFromThreadItself) { 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Isolate* isolate = CcTest::isolate(); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(isolate); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate( 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate, TerminateCurrentThread, ReenterAfterTermination); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::Context> context = 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::New(isolate, NULL, global); 310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke v8::Context::Scope context_scope(context); 311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CHECK(!v8::V8::IsExecutionTerminating()); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::String> source = v8::String::NewFromUtf8( 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate, "try { loop(); fail(); } catch(e) { fail(); }"); 314f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke v8::Script::Compile(source)->Run(); 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(isolate)); 316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check we can run JS again after termination. 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(v8::Script::Compile( 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::String::NewFromUtf8(isolate, 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "function f() { return true; }" 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "f()")) 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->Run() 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ->IsTrue()); 323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DoLoopCancelTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::TryCatch try_catch; 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating()); 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(), 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "var term = true;" 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "while(true) {" 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " if (term) terminate();" 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " term = false;" 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "}" 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "fail();"))->Run(); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(try_catch.HasCaught()); 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(try_catch.Exception()->IsNull()); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(try_catch.Message().IsEmpty()); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!try_catch.CanContinue()); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(v8::V8::IsExecutionTerminating()); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(try_catch.HasTerminated()); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::V8::CancelTerminateExecution(CcTest::isolate()); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating()); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that a single thread of JavaScript execution can terminate 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// itself and then resume execution. 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TerminateCancelTerminateFromThreadItself) { 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Isolate* isolate = CcTest::isolate(); 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(isolate); 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate( 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate, TerminateCurrentThread, DoLoopCancelTerminate); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::Context> context = v8::Context::New(isolate, NULL, global); 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::Scope context_scope(context); 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!v8::V8::IsExecutionTerminating(CcTest::isolate())); 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::String> source = v8::String::NewFromUtf8( 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate, "try { doloop(); } catch(e) { fail(); } 'completed';"); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that execution completed with correct return value. 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(v8::Script::Compile(source)->Run()->Equals(v8_str("completed"))); 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MicrotaskShouldNotRun(const v8::FunctionCallbackInfo<v8::Value>& info) { 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(false); 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MicrotaskLoopForever(const v8::FunctionCallbackInfo<v8::Value>& info) { 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Isolate* isolate = info.GetIsolate(); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(isolate); 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enqueue another should-not-run task to ensure we clean out the queue 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // when we terminate. 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->EnqueueMicrotask(v8::Function::New(isolate, MicrotaskShouldNotRun)); 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileRun("terminate(); while (true) { }"); 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(v8::V8::IsExecutionTerminating()); 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(TerminateFromOtherThreadWhileMicrotaskRunning) { 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore = new v8::base::Semaphore(0); 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TerminatorThread thread(CcTest::i_isolate()); 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch thread.Start(); 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Isolate* isolate = CcTest::isolate(); 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->SetAutorunMicrotasks(false); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(isolate); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::ObjectTemplate> global = 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateGlobalTemplate(CcTest::isolate(), Signal, DoLoop); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::Context> context = 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::New(CcTest::isolate(), NULL, global); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::Scope context_scope(context); 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->EnqueueMicrotask(v8::Function::New(isolate, MicrotaskLoopForever)); 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The second task should never be run because we bail out if we're 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // terminating. 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->EnqueueMicrotask(v8::Function::New(isolate, MicrotaskShouldNotRun)); 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->RunMicrotasks(); 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::V8::CancelTerminateExecution(isolate); 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->RunMicrotasks(); // should not run MicrotaskShouldNotRun 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch thread.Join(); 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete semaphore; 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore = NULL; 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int callback_counter = 0; 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CounterCallback(v8::Isolate* isolate, void* data) { 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch callback_counter++; 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(PostponeTerminateException) { 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Isolate* isolate = CcTest::isolate(); 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(isolate); 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::ObjectTemplate> global = 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CreateGlobalTemplate(CcTest::isolate(), TerminateCurrentThread, DoLoop); 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::Context> context = 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::New(CcTest::isolate(), NULL, global); 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::Scope context_scope(context); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::TryCatch try_catch; 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const char* terminate_and_loop = 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "terminate(); for (var i = 0; i < 10000; i++);"; 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { // Postpone terminate execution interrupts. 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i::PostponeInterruptsScope p1(CcTest::i_isolate(), 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i::StackGuard::TERMINATE_EXECUTION) ; 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // API interrupts should still be triggered. 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::isolate()->RequestInterrupt(&CounterCallback, NULL); 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(0, callback_counter); 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileRun(terminate_and_loop); 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!try_catch.HasTerminated()); 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(1, callback_counter); 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { // Postpone API interrupts as well. 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i::PostponeInterruptsScope p2(CcTest::i_isolate(), 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i::StackGuard::API_INTERRUPT); 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // None of the two interrupts should trigger. 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::isolate()->RequestInterrupt(&CounterCallback, NULL); 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileRun(terminate_and_loop); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!try_catch.HasTerminated()); 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(1, callback_counter); 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now the previously requested API interrupt should trigger. 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileRun(terminate_and_loop); 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!try_catch.HasTerminated()); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(2, callback_counter); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now the previously requested terminate execution interrupt should trigger. 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompileRun("for (var i = 0; i < 10000; i++);"); 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(try_catch.HasTerminated()); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(2, callback_counter); 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ErrorObjectAfterTermination) { 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Isolate* isolate = CcTest::isolate(); 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope scope(isolate); 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate()); 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Context::Scope context_scope(context); 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::V8::TerminateExecution(isolate); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Local<v8::Value> error = v8::Exception::Error(v8_str("error")); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(yangguo): crbug/403509. Check for empty handle instead. 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(error->IsUndefined()); 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 474