13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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
289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#include <stdlib.h>
297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/api.h"
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/condition-variable.h"
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h"
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compilation-cache.h"
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h"
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h"
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/frames.h"
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h"
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h"
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::base::Mutex;
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::base::LockGuard;
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::base::ConditionVariable;
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::base::OS;
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::base::Semaphore;
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::EmbeddedVector;
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::Object;
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::Handle;
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::Heap;
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::JSGlobalProxy;
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::Code;
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::Debug;
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::Debugger;
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::CommandMessage;
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::CommandMessageQueue;
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing ::v8::internal::StackFrame;
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::StepAction;
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::StepIn;  // From StepAction enum
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::StepNext;  // From StepAction enum
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::StepOut;  // From StepAction enum
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing ::v8::internal::Vector;
64d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockusing ::v8::internal::StrLength;
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Size of temp buffer for formatting small strings.
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define SMALL_STRING_BUFFER_SIZE 80
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// --- H e l p e r   C l a s s e s
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper class for creating a V8 enviromnent for running tests
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DebugLocalContext {
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline DebugLocalContext(
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Isolate* isolate, v8::ExtensionConfiguration* extensions = 0,
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Handle<v8::ObjectTemplate> global_template =
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::Handle<v8::ObjectTemplate>(),
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : scope_(isolate),
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context_(v8::Context::New(isolate, extensions, global_template,
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  global_object)) {
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context_->Enter();
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline DebugLocalContext(
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::ExtensionConfiguration* extensions = 0,
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::ObjectTemplate> global_template =
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          v8::Handle<v8::ObjectTemplate>(),
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : scope_(CcTest::isolate()),
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context_(v8::Context::New(CcTest::isolate(), extensions,
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  global_template, global_object)) {
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    context_->Enter();
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline ~DebugLocalContext() {
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    context_->Exit();
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline v8::Local<v8::Context> context() { return context_; }
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline v8::Context* operator->() { return *context_; }
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline v8::Context* operator*() { return *context_; }
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline v8::Isolate* GetIsolate() { return context_->GetIsolate(); }
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline bool IsReady() { return !context_.IsEmpty(); }
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ExposeDebug() {
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::internal::Isolate* isolate =
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<v8::internal::Isolate*>(context_->GetIsolate());
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::internal::Factory* factory = isolate->factory();
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Expose the debug context global object in the global object for testing.
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(isolate->debug()->Load());
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<v8::internal::Context> debug_context =
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate->debug()->debug_context();
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    debug_context->set_security_token(
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8::Utils::OpenHandle(*context_)->security_token());
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<JSGlobalProxy> global(Handle<JSGlobalProxy>::cast(
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8::Utils::OpenHandle(*context_->Global())));
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<v8::internal::String> debug_string =
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("debug"));
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::internal::Runtime::DefineObjectProperty(global, debug_string,
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        handle(debug_context->global_proxy(), isolate), DONT_ENUM).Check();
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
121589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope_;
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Context> context_;
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// --- H e l p e r   F u n c t i o n s
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Compile and run the supplied source and return the fequested function.
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic v8::Local<v8::Function> CompileFunction(DebugLocalContext* env,
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                               const char* source,
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                               const char* function_name) {
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), source))
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return v8::Local<v8::Function>::Cast((*env)->Global()->Get(
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), function_name)));
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Compile and run the supplied source and return the requested function.
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic v8::Local<v8::Function> CompileFunction(v8::Isolate* isolate,
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               const char* source,
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                               const char* function_name) {
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate, source))->Run();
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Object> global = isolate->GetCurrentContext()->Global();
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return v8::Local<v8::Function>::Cast(
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      global->Get(v8::String::NewFromUtf8(isolate, function_name)));
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Is there any debug info for the function?
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool HasDebugInfo(v8::Handle<v8::Function> fun) {
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<v8::internal::SharedFunctionInfo> shared(f->shared());
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Debug::HasDebugInfo(shared);
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Set a break point in a function and return the associated break point
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// number.
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int SetBreakPoint(Handle<v8::internal::JSFunction> fun, int position) {
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static int break_point = 0;
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Isolate* isolate = fun->GetIsolate();
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = isolate->debug();
16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  debug->SetBreakPoint(
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fun,
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Object>(v8::internal::Smi::FromInt(++break_point), isolate),
1709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      &position);
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return break_point;
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Set a break point in a function and return the associated break point
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// number.
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int SetBreakPoint(v8::Handle<v8::Function> fun, int position) {
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SetBreakPoint(v8::Utils::OpenHandle(*fun), position);
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Set a break point in a function using the Debug object and return the
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// associated break point number.
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int SetBreakPointFromJS(v8::Isolate* isolate,
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               const char* function_name,
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               int line, int position) {
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SNPrintF(buffer,
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "debug.Debug.setBreakPoint(%s,%d,%d)",
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           function_name, line, position);
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> str = v8::String::NewFromUtf8(isolate, buffer.start());
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return v8::Script::Compile(str)->Run()->Int32Value();
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Set a break point in a script identified by id using the global Debug object.
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int SetScriptBreakPointByIdFromJS(v8::Isolate* isolate, int script_id,
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         int line, int column) {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (column >= 0) {
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Column specified set script break point on precise location.
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SNPrintF(buffer,
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "debug.Debug.setScriptBreakPointById(%d,%d,%d)",
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             script_id, line, column);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Column not specified set script break point on line.
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SNPrintF(buffer,
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "debug.Debug.setScriptBreakPointById(%d,%d)",
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             script_id, line);
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::TryCatch try_catch;
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::String> str =
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(isolate, buffer.start());
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(!try_catch.HasCaught());
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return value->Int32Value();
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Set a break point in a script identified by name using the global Debug
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// object.
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int SetScriptBreakPointByNameFromJS(v8::Isolate* isolate,
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           const char* script_name, int line,
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           int column) {
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (column >= 0) {
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Column specified set script break point on precise location.
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SNPrintF(buffer,
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "debug.Debug.setScriptBreakPointByName(\"%s\",%d,%d)",
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             script_name, line, column);
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Column not specified set script break point on line.
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SNPrintF(buffer,
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "debug.Debug.setScriptBreakPointByName(\"%s\",%d)",
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             script_name, line);
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::TryCatch try_catch;
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::String> str =
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(isolate, buffer.start());
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(!try_catch.HasCaught());
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return value->Int32Value();
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Clear a break point.
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ClearBreakPoint(int break_point) {
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Isolate* isolate = CcTest::i_isolate();
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = isolate->debug();
25744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  debug->ClearBreakPoint(
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Object>(v8::internal::Smi::FromInt(break_point), isolate));
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Clear a break point using the global Debug object.
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ClearBreakPointFromJS(v8::Isolate* isolate,
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  int break_point_number) {
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SNPrintF(buffer,
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "debug.Debug.clearBreakPoint(%d)",
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           break_point_number);
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EnableScriptBreakPointFromJS(v8::Isolate* isolate,
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         int break_point_number) {
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SNPrintF(buffer,
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "debug.Debug.enableScriptBreakPoint(%d)",
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           break_point_number);
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DisableScriptBreakPointFromJS(v8::Isolate* isolate,
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          int break_point_number) {
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SNPrintF(buffer,
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "debug.Debug.disableScriptBreakPoint(%d)",
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           break_point_number);
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ChangeScriptBreakPointConditionFromJS(v8::Isolate* isolate,
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  int break_point_number,
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  const char* condition) {
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SNPrintF(buffer,
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "debug.Debug.changeScriptBreakPointCondition(%d, \"%s\")",
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           break_point_number, condition);
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ChangeScriptBreakPointIgnoreCountFromJS(v8::Isolate* isolate,
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    int break_point_number,
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                    int ignoreCount) {
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SNPrintF(buffer,
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "debug.Debug.changeScriptBreakPointIgnoreCount(%d, %d)",
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           break_point_number, ignoreCount);
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Change break on exception.
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ChangeBreakOnException(bool caught, bool uncaught) {
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  debug->ChangeBreakOnException(v8::internal::BreakException, caught);
32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  debug->ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught);
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Change break on exception using the global Debug object.
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ChangeBreakOnExceptionFromJS(v8::Isolate* isolate, bool caught,
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         bool uncaught) {
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (caught) {
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Script::Compile(
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(isolate, "debug.Debug.setBreakOnException()"))
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->Run();
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Script::Compile(
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(isolate, "debug.Debug.clearBreakOnException()"))
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->Run();
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (uncaught) {
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Script::Compile(
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            isolate, "debug.Debug.setBreakOnUncaughtException()"))->Run();
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Script::Compile(
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            isolate, "debug.Debug.clearBreakOnUncaughtException()"))->Run();
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Prepare to step to next break location.
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void PrepareStep(StepAction step_action) {
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  debug->PrepareStep(step_action, 1, StackFrame::NO_ID);
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is in namespace v8::internal to be friend with class
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// v8::internal::Debug.
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Collect the currently debugged functions.
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<FixedArray> GetDebuggedFunctions() {
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Debug* debug = CcTest::i_isolate()->debug();
36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::DebugInfoListNode* node = debug->debug_info_list_;
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find the number of debugged functions.
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = 0;
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (node) {
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    count++;
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    node = node->next();
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate array for the debugged functions
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<FixedArray> debugged_functions =
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::i_isolate()->factory()->NewFixedArray(count);
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run through the debug info objects and collect all functions.
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  count = 0;
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (node) {
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    debugged_functions->set(count++, *node->debug_info());
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    node = node->next();
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return debugged_functions;
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Check that the debugger has been fully unloaded.
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CheckDebuggerUnloaded(bool check_functions) {
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the debugger context is cleared and that there is no debug
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // information stored for the debugger.
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(CcTest::i_isolate()->debug()->debug_context().is_null());
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(NULL, CcTest::i_isolate()->debug()->debug_info_list_);
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Collect garbage to ensure weak handles are cleared.
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Iterate the head and check that there are no debugger related objects left.
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapIterator iterator(CcTest::heap());
405d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(!obj->IsDebugInfo());
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(!obj->IsBreakPointInfo());
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If deep check of functions is requested check that no debug break code
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // is left in all functions.
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (check_functions) {
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (obj->IsJSFunction()) {
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        JSFunction* fun = JSFunction::cast(obj);
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (RelocIterator it(fun->shared()->code()); !it.done(); it.next()) {
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          RelocInfo::Mode rmode = it.rinfo()->rmode();
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (RelocInfo::IsCodeTarget(rmode)) {
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            CHECK(!Debug::IsDebugBreak(it.rinfo()->target_address()));
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if (RelocInfo::IsJSReturn(rmode)) {
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            CHECK(!Debug::IsDebugBreakAtReturn(it.rinfo()));
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Check that the debugger has been fully unloaded.
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CheckDebuggerUnloaded(bool check_functions = false) {
433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Let debugger to unload itself synchronously
434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::ProcessDebugMessages();
435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::CheckDebuggerUnloaded(check_functions);
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Inherit from BreakLocationIterator to get access to protected parts for
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// testing.
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass TestBreakLocationIterator: public v8::internal::BreakLocationIterator {
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit TestBreakLocationIterator(Handle<v8::internal::DebugInfo> debug_info)
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : BreakLocationIterator(debug_info, v8::internal::SOURCE_BREAK_LOCATIONS) {}
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::RelocIterator* it() { return reloc_iterator_; }
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::RelocIterator* it_original() {
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return reloc_iterator_original_;
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Compile a function, set a break point and check that the call at the break
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// location in the code is the expected debug_break function.
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CheckDebugBreakFunction(DebugLocalContext* env,
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             const char* source, const char* name,
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             int position, v8::internal::RelocInfo::Mode mode,
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             Code* debug_break) {
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
46044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create function and set the break point.
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<v8::internal::JSFunction> fun = v8::Utils::OpenHandle(
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *CompileFunction(env, source, name));
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int bp = SetBreakPoint(fun, position);
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the debug break function is as expected.
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(Debug::HasDebugInfo(shared));
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestBreakLocationIterator it1(Debug::GetDebugInfo(shared));
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  it1.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  v8::internal::RelocInfo::Mode actual_mode = it1.it()->rinfo()->rmode();
472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    actual_mode = v8::internal::RelocInfo::CODE_TARGET;
474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(mode, actual_mode);
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mode != v8::internal::RelocInfo::JS_RETURN) {
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(debug_break,
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Code::GetCodeFromTargetAddress(it1.it()->rinfo()->target_address()));
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(Debug::IsDebugBreakAtReturn(it1.it()->rinfo()));
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the break point and check that the debug break function is no longer
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClearBreakPoint(bp);
48644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(!debug->HasDebugInfo(shared));
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(debug->EnsureDebugInfo(shared, fun));
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  it2.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  actual_mode = it2.it()->rinfo()->rmode();
491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    actual_mode = v8::internal::RelocInfo::CODE_TARGET;
493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(mode, actual_mode);
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mode == v8::internal::RelocInfo::JS_RETURN) {
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(!Debug::IsDebugBreakAtReturn(it2.it()->rinfo()));
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// --- D e b u g   E v e n t   H a n d l e r s
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// --- The different tests uses a number of debug event handlers.
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Source for the JavaScript function which picks out the function
508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// name of a frame.
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* frame_function_name_source =
510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "function frame_function_name(exec_state, frame_number) {"
511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "  return exec_state.frame(frame_number).func().name();"
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}";
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Local<v8::Function> frame_function_name;
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Source for the JavaScript function which pick out the name of the
517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// first argument of a frame.
518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* frame_argument_name_source =
519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "function frame_argument_name(exec_state, frame_number) {"
520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "  return exec_state.frame(frame_number).argumentName(0);"
521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "}";
522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochv8::Local<v8::Function> frame_argument_name;
523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Source for the JavaScript function which pick out the value of the
526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// first argument of a frame.
527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* frame_argument_value_source =
528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "function frame_argument_value(exec_state, frame_number) {"
529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "  return exec_state.frame(frame_number).argumentValue(0).value_;"
530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "}";
531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochv8::Local<v8::Function> frame_argument_value;
532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Source for the JavaScript function which pick out the name of the
535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// first argument of a frame.
536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* frame_local_name_source =
537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "function frame_local_name(exec_state, frame_number) {"
538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "  return exec_state.frame(frame_number).localName(0);"
539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "}";
540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochv8::Local<v8::Function> frame_local_name;
541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Source for the JavaScript function which pick out the value of the
544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// first argument of a frame.
545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* frame_local_value_source =
546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "function frame_local_value(exec_state, frame_number) {"
547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "  return exec_state.frame(frame_number).localValue(0).value_;"
548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "}";
549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochv8::Local<v8::Function> frame_local_value;
550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Source for the JavaScript function which picks out the source line for the
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// top frame.
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* frame_source_line_source =
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function frame_source_line(exec_state) {"
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return exec_state.frame(0).sourceLine();"
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}";
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Local<v8::Function> frame_source_line;
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Source for the JavaScript function which picks out the source column for the
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// top frame.
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* frame_source_column_source =
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function frame_source_column(exec_state) {"
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return exec_state.frame(0).sourceColumn();"
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}";
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Local<v8::Function> frame_source_column;
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Source for the JavaScript function which picks out the script name for the
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// top frame.
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* frame_script_name_source =
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function frame_script_name(exec_state) {"
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return exec_state.frame(0).func().script().name();"
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}";
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Local<v8::Function> frame_script_name;
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Source for the JavaScript function which returns the number of frames.
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* frame_count_source =
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function frame_count(exec_state) {"
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return exec_state.frameCount();"
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}";
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Function> frame_count;
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Global variable to store the last function hit - used by some tests.
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar last_function_hit[80];
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Global variable to store the name for last script hit - used by some tests.
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar last_script_name_hit[80];
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Global variables to store the last source position - used by some tests.
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint last_source_line = -1;
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint last_source_column = -1;
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug event handler which counts the break points which have been hit.
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint break_point_hit_count = 0;
5993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint break_point_hit_count_deoptimize = 0;
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventBreakPointHitCount(
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Isolate* isolate = CcTest::i_isolate();
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Debug* debug = isolate->debug();
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When hitting a debug event listener there must be a break set.
60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(debug->break_id(), 0);
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Count the number of breaks.
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event == v8::Break) {
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!frame_function_name.IsEmpty()) {
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Get the name of the function.
614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      const int argc = 2;
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Handle<v8::Value> argv[argc] = {
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        exec_state, v8::Integer::New(CcTest::isolate(), 0)
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      };
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                               argc, argv);
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (result->IsUndefined()) {
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        last_function_hit[0] = '\0';
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK(result->IsString());
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8::Handle<v8::String> function_name(result->ToString());
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        function_name->WriteUtf8(last_function_hit);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!frame_source_line.IsEmpty()) {
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Get the source line.
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int argc = 1;
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> argv[argc] = { exec_state };
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> result = frame_source_line->Call(exec_state,
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                             argc, argv);
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(result->IsNumber());
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      last_source_line = result->Int32Value();
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!frame_source_column.IsEmpty()) {
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Get the source column.
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int argc = 1;
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> argv[argc] = { exec_state };
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> result = frame_source_column->Call(exec_state,
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                               argc, argv);
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(result->IsNumber());
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      last_source_column = result->Int32Value();
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!frame_script_name.IsEmpty()) {
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Get the script name of the function script.
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int argc = 1;
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> argv[argc] = { exec_state };
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> result = frame_script_name->Call(exec_state,
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                             argc, argv);
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (result->IsUndefined()) {
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        last_script_name_hit[0] = '\0';
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK(result->IsString());
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8::Handle<v8::String> script_name(result->ToString());
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        script_name->WriteUtf8(last_script_name_hit);
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
6633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Perform a full deoptimization when the specified number of
6653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // breaks have been hit.
6663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (break_point_hit_count == break_point_hit_count_deoptimize) {
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Deoptimizer::DeoptimizeAll(isolate);
668402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug event handler which counts a number of events and collects the stack
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// height if there is a function compiled for that.
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint exception_hit_count = 0;
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint uncaught_exception_hit_count = 0;
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint last_js_stack_height = -1;
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochv8::Handle<v8::Function> debug_event_listener_callback;
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint debug_event_listener_callback_result;
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void DebugEventCounterClear() {
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  exception_hit_count = 0;
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uncaught_exception_hit_count = 0;
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventCounter(
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> event_data = event_details.GetEventData();
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
69344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When hitting a debug event listener there must be a break set.
69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(debug->break_id(), 0);
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Count the number of breaks.
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event == v8::Break) {
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (event == v8::Exception) {
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    exception_hit_count++;
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check whether the exception was uncaught.
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::String> fun_name =
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(CcTest::isolate(), "uncaught");
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Local<v8::Function> fun =
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Local<v8::Function>::Cast(event_data->Get(fun_name));
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Value> result = fun->Call(event_data, 0, NULL);
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (result->IsTrue()) {
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uncaught_exception_hit_count++;
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Collect the JavsScript stack height if the function frame_count is
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compiled.
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!frame_count.IsEmpty()) {
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static const int kArgc = 1;
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<v8::Value> argv[kArgc] = { exec_state };
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Using exec_state as receiver is just to have a receiver.
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> result = frame_count->Call(exec_state, kArgc, argv);
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_js_stack_height = result->Int32Value();
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Run callback from DebugEventListener and check the result.
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!debug_event_listener_callback.IsEmpty()) {
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> result =
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        debug_event_listener_callback->Call(event_data, 0, NULL);
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(!result.IsEmpty());
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(debug_event_listener_callback_result, result->Int32Value());
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug event handler which evaluates a number of expressions when a break
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// point is hit. Each evaluated expression is compared with an expected value.
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// For this debug event handler to work the following two global varaibles
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// must be initialized.
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   checks: An array of expressions and expected results
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   evaluate_check_function: A JavaScript function (see below)
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Structure for holding checks to do.
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct EvaluateCheck {
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* expr;  // An expression to evaluate when a break point is hit.
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> expected;  // The expected result.
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Array of checks to do.
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct EvaluateCheck* checks = NULL;
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Source for The JavaScript function which can do the evaluation when a break
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// point is hit.
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* evaluate_check_source =
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function evaluate_check(exec_state, expr, expected) {"
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return exec_state.frame(0).evaluate(expr).value() === expected;"
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}";
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Local<v8::Function> evaluate_check_function;
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The actual debug event described by the longer comment above.
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventEvaluate(
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When hitting a debug event listener there must be a break set.
76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(debug->break_id(), 0);
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event == v8::Break) {
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    break_point_hit_count++;
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; checks[i].expr != NULL; i++) {
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int argc = 3;
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Handle<v8::Value> argv[argc] = {
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          exec_state,
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::String::NewFromUtf8(CcTest::isolate(), checks[i].expr),
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          checks[i].expected};
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> result =
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          evaluate_check_function->Call(exec_state, argc, argv);
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!result->IsTrue()) {
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::Utf8Value utf8(checks[i].expected->ToString());
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        V8_Fatal(__FILE__, __LINE__, "%s != %s", checks[i].expr, *utf8);
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This debug event listener removes a breakpoint in a function
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint debug_event_remove_break_point = 0;
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventRemoveBreakPoint(
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> data = event_details.GetCallbackData();
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When hitting a debug event listener there must be a break set.
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(debug->break_id(), 0);
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event == v8::Break) {
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(data->IsFunction());
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ClearBreakPoint(debug_event_remove_break_point);
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug event handler which counts break points hit and performs a step
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// afterwards.
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStepAction step_action = StepIn;  // Step action to perform when stepping.
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventStep(
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When hitting a debug event listener there must be a break set.
81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(debug->break_id(), 0);
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event == v8::Break) {
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrepareStep(step_action);
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug event handler which counts break points hit and performs a step
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// afterwards. For each call the expected function is checked.
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// For this debug event handler to work the following two global varaibles
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// must be initialized.
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   expected_step_sequence: An array of the expected function call sequence.
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   frame_function_name: A JavaScript function (see below).
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// String containing the expected function call sequence. Note: this only works
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// if functions have name length of one.
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* expected_step_sequence = NULL;
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The actual debug event described by the longer comment above.
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventStepSequence(
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When hitting a debug event listener there must be a break set.
83944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(debug->break_id(), 0);
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event == v8::Break || event == v8::Exception) {
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that the current function is the expected.
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(break_point_hit_count <
844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          StrLength(expected_step_sequence));
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const int argc = 2;
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> argv[argc] = {
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      exec_state, v8::Integer::New(CcTest::isolate(), 0)
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    };
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                             argc, argv);
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(result->IsString());
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::Utf8Value function_name(result->ToString());
853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CHECK_EQ(1, StrLength(*function_name));
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ((*function_name)[0],
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              expected_step_sequence[break_point_hit_count]);
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Perform step.
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrepareStep(step_action);
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug event handler which performs a garbage collection.
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void DebugEventBreakPointCollectGarbage(
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When hitting a debug event listener there must be a break set.
87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(debug->break_id(), 0);
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Perform a garbage collection when break point is hit and continue. Based
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on the number of break points hit either scavenge or mark compact
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // collector is used.
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event == v8::Break) {
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (break_point_hit_count % 2 == 0) {
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Scavenge.
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
88180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // Mark sweep compact.
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug event handler which re-issues a debug break and calls the garbage
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// collector to have the heap verified.
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventBreak(
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When hitting a debug event listener there must be a break set.
89544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(debug->break_id(), 0);
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event == v8::Break) {
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Count the number of breaks.
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Run the garbage collector to enforce heap verification if option
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // --verify-heap is set.
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set the break flag again to come back here as soon as possible.
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Debug::DebugBreak(CcTest::isolate());
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Debug event handler which re-issues a debug break until a limit has been
912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// reached.
913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint max_break_point_hit_count = 0;
9143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhubool terminate_after_max_break_point_hit = false;
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventBreakMax(
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* v8_isolate = CcTest::isolate();
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Isolate* isolate = CcTest::i_isolate();
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = isolate->debug();
922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // When hitting a debug event listener there must be a break set.
92344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(debug->break_id(), 0);
924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
9253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (event == v8::Break) {
9263e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    if (break_point_hit_count < max_break_point_hit_count) {
9273e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Count the number of breaks.
9283e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      break_point_hit_count++;
929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
9303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Collect the JavsScript stack height if the function frame_count is
9313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // compiled.
9323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (!frame_count.IsEmpty()) {
9333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        static const int kArgc = 1;
9343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        v8::Handle<v8::Value> argv[kArgc] = { exec_state };
9353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // Using exec_state as receiver is just to have a receiver.
9363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        v8::Handle<v8::Value> result =
9373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            frame_count->Call(exec_state, kArgc, argv);
9383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        last_js_stack_height = result->Int32Value();
9393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
9403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Set the break flag again to come back here as soon as possible.
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Debug::DebugBreak(v8_isolate);
9433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    } else if (terminate_after_max_break_point_hit) {
9453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      // Terminate execution after the last break if requested.
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::V8::TerminateExecution(v8_isolate);
9473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
9483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Perform a full deoptimization when the specified number of
9503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // breaks have been hit.
9513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (break_point_hit_count == break_point_hit_count_deoptimize) {
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::Deoptimizer::DeoptimizeAll(isolate);
9533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// --- M e s s a g e   C a l l b a c k
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Message callback which counts the number of messages.
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint message_callback_count = 0;
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void MessageCallbackCountClear() {
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_callback_count = 0;
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void MessageCallbackCount(v8::Handle<v8::Message> message,
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 v8::Handle<v8::Value> data) {
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_callback_count++;
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// --- T h e   A c t u a l   T e s t s
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that the debug break function is the expected one for different kinds
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of break locations.
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStub) {
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  using ::v8::internal::Builtins;
98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  using ::v8::internal::Isolate;
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebugBreakFunction(&env,
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          "function f1(){}", "f1",
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          0,
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          v8::internal::RelocInfo::JS_RETURN,
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          NULL);
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebugBreakFunction(&env,
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          "function f2(){x=1;}", "f2",
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          0,
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          v8::internal::RelocInfo::CODE_TARGET,
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          CcTest::i_isolate()->builtins()->builtin(
99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Builtins::kStoreIC_DebugBreak));
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebugBreakFunction(&env,
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          "function f3(){var a=x;}", "f3",
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          0,
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          v8::internal::RelocInfo::CODE_TARGET,
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          CcTest::i_isolate()->builtins()->builtin(
100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Builtins::kLoadIC_DebugBreak));
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// TODO(1240753): Make the test architecture independent or split
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// parts of the debugger into architecture dependent files. This
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// part currently disabled as it is not portable between IA32/ARM.
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Currently on ICs for keyed store/load on ARM.
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if !defined (__arm__) && !defined(__thumb__)
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebugBreakFunction(
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      &env,
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function f4(){var index='propertyName'; var a={}; a[index] = 'x';}",
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "f4",
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      0,
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::internal::RelocInfo::CODE_TARGET,
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::i_isolate()->builtins()->builtin(
101544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Builtins::kKeyedStoreIC_DebugBreak));
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebugBreakFunction(
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      &env,
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function f5(){var index='propertyName'; var a={}; return a[index];}",
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "f5",
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      0,
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::internal::RelocInfo::CODE_TARGET,
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::i_isolate()->builtins()->builtin(
102344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Builtins::kKeyedLoadIC_DebugBreak));
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckDebugBreakFunction(
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      &env,
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f6(a){return a==null;}",
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "f6",
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      0,
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::internal::RelocInfo::CODE_TARGET,
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::i_isolate()->builtins()->builtin(
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Builtins::kCompareNilIC_DebugBreak));
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the debug break code stubs for call ICs with different number of
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // parameters.
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(verwaest): XXX update test.
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Handle<Code> debug_break_0 = v8::internal::ComputeCallDebugBreak(0);
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Handle<Code> debug_break_1 = v8::internal::ComputeCallDebugBreak(1);
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Handle<Code> debug_break_4 = v8::internal::ComputeCallDebugBreak(4);
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // CheckDebugBreakFunction(&env,
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         "function f4_0(){x();}", "f4_0",
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         0,
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         v8::internal::RelocInfo::CODE_TARGET,
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         *debug_break_0);
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // CheckDebugBreakFunction(&env,
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         "function f4_1(){x(1);}", "f4_1",
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         0,
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         v8::internal::RelocInfo::CODE_TARGET,
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         *debug_break_1);
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // CheckDebugBreakFunction(&env,
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         "function f4_4(){x(1,2,3,4);}", "f4_4",
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         0,
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         v8::internal::RelocInfo::CODE_TARGET,
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //                         *debug_break_4);
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that the debug info in the VM is in sync with the functions being
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugged.
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugInfo) {
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a couple of functions for the test.
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo =
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CompileFunction(&env, "function foo(){}", "foo");
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> bar =
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CompileFunction(&env, "function bar(){}", "bar");
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initially no functions are debugged.
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!HasDebugInfo(foo));
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!HasDebugInfo(bar));
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // One function (foo) is debugged.
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int bp1 = SetBreakPoint(foo, 0);
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(HasDebugInfo(foo));
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!HasDebugInfo(bar));
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Two functions are debugged.
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int bp2 = SetBreakPoint(bar, 0);
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, v8::internal::GetDebuggedFunctions()->length());
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(HasDebugInfo(foo));
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(HasDebugInfo(bar));
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // One function (bar) is debugged.
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClearBreakPoint(bp1);
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!HasDebugInfo(foo));
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(HasDebugInfo(bar));
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // No functions are debugged.
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClearBreakPoint(bp2);
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!HasDebugInfo(foo));
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!HasDebugInfo(bar));
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that a break point can be set at an IC store location.
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(BreakPointICStore) {
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "function foo(){bar=0;}"))->Run();
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run with breakpoint
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int bp = SetBreakPoint(foo, 0);
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClearBreakPoint(bp);
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that a break point can be set at an IC load location.
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(BreakPointICLoad) {
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "bar=1"))
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "function foo(){var x=bar;}"))
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Run with breakpoint.
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int bp = SetBreakPoint(foo, 0);
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClearBreakPoint(bp);
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that a break point can be set at an IC call location.
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(BreakPointICCall) {
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){}"))->Run();
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "function foo(){bar();}"))->Run();
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Run with breakpoint
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int bp = SetBreakPoint(foo, 0);
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClearBreakPoint(bp);
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
120180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Test that a break point can be set at an IC call location and survive a GC.
120280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenTEST(BreakPointICCallWithGC) {
120380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  break_point_hit_count = 0;
120480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  DebugLocalContext env;
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage);
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){return 1;}"))
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "function foo(){return bar();}"))
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
121580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
121680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Run without breakpoints.
121780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
121880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(0, break_point_hit_count);
121980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
122080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Run with breakpoint.
122180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int bp = SetBreakPoint(foo, 0);
122280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
122380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(1, break_point_hit_count);
122480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
122580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(2, break_point_hit_count);
122680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
122780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Run without breakpoints.
122880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ClearBreakPoint(bp);
122980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  foo->Call(env->Global(), 0, NULL);
123080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(2, break_point_hit_count);
123180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
123280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  v8::Debug::SetDebugEventListener(NULL);
123380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CheckDebuggerUnloaded();
123480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
123580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
123680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
123780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// Test that a break point can be set at an IC call location and survive a GC.
123880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenTEST(BreakPointConstructCallWithGC) {
123980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  break_point_hit_count = 0;
124080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  DebugLocalContext env;
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage);
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "function bar(){ this.x = 1;}"))
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(),
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "function foo(){return new bar(1).x;}"))->Run();
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
125180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
125280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Run without breakpoints.
125380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
125480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(0, break_point_hit_count);
125580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
125680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Run with breakpoint.
125780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int bp = SetBreakPoint(foo, 0);
125880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
125980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(1, break_point_hit_count);
126080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
126180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(2, break_point_hit_count);
126280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
126380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Run without breakpoints.
126480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ClearBreakPoint(bp);
126580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  foo->Call(env->Global(), 0, NULL);
126680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CHECK_EQ(2, break_point_hit_count);
126780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
126880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  v8::Debug::SetDebugEventListener(NULL);
126980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  CheckDebuggerUnloaded();
127080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
127180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
127280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that a break point can be set at a return store location.
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(BreakPointReturn) {
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a functions for checking the source line and column when hitting
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a break point.
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_source_line = CompileFunction(&env,
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      frame_source_line_source,
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      "frame_source_line");
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_source_column = CompileFunction(&env,
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        frame_source_column_source,
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        "frame_source_column");
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "function foo(){}"))->Run();
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run with breakpoint
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int bp = SetBreakPoint(foo, 0);
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, last_source_line);
1304bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CHECK_EQ(15, last_source_column);
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, last_source_line);
1308bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  CHECK_EQ(15, last_source_column);
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClearBreakPoint(bp);
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CallWithBreakPoints(v8::Local<v8::Object> recv,
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                v8::Local<v8::Function> f,
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                int break_point_count,
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                int call_count) {
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < call_count; i++) {
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(recv, 0, NULL);
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ((i + 1) * break_point_count, break_point_hit_count);
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test GC during break point processing.
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(GCDuringBreakPointProcessing) {
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage);
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo;
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test IC store break point with garbage collection.
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 0);
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallWithBreakPoints(env->Global(), foo, 1, 10);
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test IC load break point with garbage collection.
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 0);
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallWithBreakPoints(env->Global(), foo, 1, 10);
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test IC call break point with garbage collection.
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 0);
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallWithBreakPoints(env->Global(), foo, 1, 10);
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test return break point with garbage collection.
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo = CompileFunction(&env, "function foo(){}", "foo");
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 0);
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallWithBreakPoints(env->Global(), foo, 1, 25);
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Test debug break slot break point with garbage collection.
13627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo = CompileFunction(&env, "function foo(){var a;}", "foo");
13637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 0);
13647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CallWithBreakPoints(env->Global(), foo, 1, 25);
13657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Call the function three times with different garbage collections in between
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and make sure that the break point survives.
1373bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochstatic void CallAndGC(v8::Local<v8::Object> recv,
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      v8::Local<v8::Function> f) {
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 3; i++) {
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Call function.
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(recv, 0, NULL);
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(1 + i * 3, break_point_hit_count);
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Scavenge and call function.
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(recv, 0, NULL);
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(2 + i * 3, break_point_hit_count);
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mark sweep (and perhaps compact) and call function.
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(recv, 0, NULL);
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(3 + i * 3, break_point_hit_count);
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Test that a break point can be set at a return store location.
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(BreakPointSurviveGC) {
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo;
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test IC store break point with garbage collection.
1405bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  {
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileFunction(&env, "function foo(){}", "foo");
1407bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1408bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    SetBreakPoint(foo, 0);
1409bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallAndGC(env->Global(), foo);
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test IC load break point with garbage collection.
1413bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  {
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileFunction(&env, "function foo(){}", "foo");
1415bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1416bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    SetBreakPoint(foo, 0);
1417bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallAndGC(env->Global(), foo);
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test IC call break point with garbage collection.
1421bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  {
14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileFunction(&env, "function foo(){}", "foo");
1423bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    foo = CompileFunction(&env,
1424bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                          "function bar(){};function foo(){bar();}",
1425bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                          "foo");
1426bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    SetBreakPoint(foo, 0);
1427bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallAndGC(env->Global(), foo);
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test return break point with garbage collection.
1431bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  {
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileFunction(&env, "function foo(){}", "foo");
1433bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    foo = CompileFunction(&env, "function foo(){}", "foo");
1434bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    SetBreakPoint(foo, 0);
1435bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallAndGC(env->Global(), foo);
1437bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1438bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Test non IC break point with garbage collection.
1439bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  {
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CompileFunction(&env, "function foo(){}", "foo");
1441bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo");
1442bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    SetBreakPoint(foo, 0);
1443bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallAndGC(env->Global(), foo);
1445bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that break points can be set using the global Debug object.
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(BreakPointThroughJavaScript) {
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){}"))->Run();
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "function foo(){bar();bar();}"))
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //                                               012345678901234567890
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //                                                         1         2
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Break points are set at position 3 and 9
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Script> foo =
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "foo()"));
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Run();
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run with one breakpoint
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bp1 = SetBreakPointFromJS(env->GetIsolate(), "foo", 0, 3);
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Run();
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Run();
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run with two breakpoints
1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bp2 = SetBreakPointFromJS(env->GetIsolate(), "foo", 0, 9);
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Run();
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, break_point_hit_count);
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Run();
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, break_point_hit_count);
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run with one breakpoint
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), bp2);
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Run();
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(7, break_point_hit_count);
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Run();
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(8, break_point_hit_count);
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run without breakpoints.
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), bp1);
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Run();
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(8, break_point_hit_count);
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the break point numbers are consecutive.
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, bp1);
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, bp2);
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that break points on scripts identified by name can be set using the
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// global Debug object.
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ScriptBreakPointByNameThroughJavaScript) {
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script = v8::String::NewFromUtf8(
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->GetIsolate(),
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {\n"
1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  function h() {\n"
1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    a = 0;  // line 2\n"
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }\n"
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  b = 1;  // line 4\n"
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return h();\n"
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}\n"
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "\n"
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function g() {\n"
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  function h() {\n"
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    a = 0;\n"
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }\n"
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  b = 2;  // line 12\n"
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  h();\n"
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  b = 3;  // line 14\n"
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  f();    // line 15\n"
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script and get the two functions.
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ScriptOrigin origin =
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g without break points.
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g with break point on line 12.
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 12, 0);
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove the break point again.
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp1);
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g with break point on line 2.
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp2 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 2, 0);
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g with break point on line 2, 4, 12, 14 and 15.
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp3 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 4, 0);
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp4 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 12, 0);
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp5 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 14, 0);
1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp6 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 15, 0);
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(7, break_point_hit_count);
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove all the break points again.
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp2);
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp3);
1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp4);
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp5);
1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp6);
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the break point numbers are consecutive.
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, sbp1);
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, sbp2);
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, sbp3);
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, sbp4);
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, sbp5);
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, sbp6);
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ScriptBreakPointByIdThroughJavaScript) {
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> source = v8::String::NewFromUtf8(
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->GetIsolate(),
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {\n"
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  function h() {\n"
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    a = 0;  // line 2\n"
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }\n"
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  b = 1;  // line 4\n"
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return h();\n"
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}\n"
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "\n"
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function g() {\n"
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  function h() {\n"
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    a = 0;\n"
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }\n"
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  b = 2;  // line 12\n"
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  h();\n"
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  b = 3;  // line 14\n"
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  f();    // line 15\n"
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script and get the two functions.
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ScriptOrigin origin =
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Script> script = v8::Script::Compile(source, &origin);
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script->Run();
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the script id knowing that internally it is a 32 integer.
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int script_id = script->GetUnboundScript()->GetId();
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g without break points.
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g with break point on line 12.
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp1 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 12, 0);
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove the break point again.
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp1);
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g with break point on line 2.
1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp2 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 2, 0);
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g with break point on line 2, 4, 12, 14 and 15.
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp3 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 4, 0);
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp4 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 12, 0);
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp5 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 14, 0);
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp6 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 15, 0);
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(7, break_point_hit_count);
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove all the break points again.
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp2);
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp3);
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp4);
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp5);
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp6);
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the break point numbers are consecutive.
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, sbp1);
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, sbp2);
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, sbp3);
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, sbp4);
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, sbp5);
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, sbp6);
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test conditional script break points.
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(EnableDisableScriptBreakPoint) {
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script = v8::String::NewFromUtf8(
1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->GetIsolate(),
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {\n"
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  a = 0;  // line 1\n"
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "};");
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script and get function f.
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ScriptOrigin origin =
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set script break point on line 1 (in function f).
1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f while enabeling and disabling the script break point.
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisableScriptBreakPointFromJS(env->GetIsolate(), sbp);
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnableScriptBreakPointFromJS(env->GetIsolate(), sbp);
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisableScriptBreakPointFromJS(env->GetIsolate(), sbp);
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reload the script and get f again checking that the disabeling survives.
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnableScriptBreakPointFromJS(env->GetIsolate(), sbp);
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, break_point_hit_count);
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test conditional script break points.
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ConditionalScriptBreakPoint) {
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script = v8::String::NewFromUtf8(
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->GetIsolate(),
1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "count = 0;\n"
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {\n"
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  g(count++);  // line 2\n"
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "};\n"
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function g(x) {\n"
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  var a=x;  // line 5\n"
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "};");
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script and get function f.
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ScriptOrigin origin =
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set script break point on line 5 (in function g).
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 5, 0);
1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f with different conditions on the script break point.
1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeScriptBreakPointConditionFromJS(env->GetIsolate(), sbp1, "false");
1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeScriptBreakPointConditionFromJS(env->GetIsolate(), sbp1, "true");
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeScriptBreakPointConditionFromJS(env->GetIsolate(), sbp1, "x % 2 == 0");
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(env->Global(), 0, NULL);
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, break_point_hit_count);
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reload the script and get f again checking that the condition survives.
1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(env->Global(), 0, NULL);
1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, break_point_hit_count);
1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test ignore count on script break points.
1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ScriptBreakPointIgnoreCount) {
1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script = v8::String::NewFromUtf8(
1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->GetIsolate(),
1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {\n"
1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  a = 0;  // line 1\n"
1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "};");
1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script and get function f.
1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ScriptOrigin origin =
1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set script break point on line 1 (in function f).
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f with different ignores on the script break point.
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 1);
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 5);
1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(env->Global(), 0, NULL);
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, break_point_hit_count);
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reload the script and get f again checking that the ignore survives.
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(env->Global(), 0, NULL);
1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, break_point_hit_count);
1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that script break points survive when a script is reloaded.
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ScriptBreakPointReload) {
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
1907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f;
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script = v8::String::NewFromUtf8(
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->GetIsolate(),
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f() {\n"
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  function h() {\n"
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    a = 0;  // line 2\n"
1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  }\n"
1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  b = 1;  // line 4\n"
1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return h();\n"
1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}");
1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin_1 =
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "1"));
1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin_2 =
1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "2"));
1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a script break point before the script is loaded.
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetScriptBreakPointByNameFromJS(env->GetIsolate(), "1", 2, 0);
1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script and get the function.
1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin_1)->Run();
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and check that the script break point is active.
1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script again with a different script data and get the
1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function.
1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin_2)->Run();
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and check that no break points are set.
1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script again and get the function.
1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin_1)->Run();
1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and check that the script break point is active.
1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test when several scripts has the same script data
1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ScriptBreakPointMultiple) {
1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f;
1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script_f =
1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(),
1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "function f() {\n"
1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "  a = 0;  // line 1\n"
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "}");
1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> g;
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script_g =
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(),
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "function g() {\n"
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "  b = 0;  // line 1\n"
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "}");
1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ScriptOrigin origin =
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a script break point before the scripts are loaded.
1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
1993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the scripts with same script data and get the functions.
1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script_f, &origin)->Run();
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script_g, &origin)->Run();
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g = v8::Local<v8::Function>::Cast(
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
2001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g and check that the script break point is active.
2003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
2005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
2006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
2007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
2008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the script break point.
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp);
2011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g and check that the script break point is no longer active.
2013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
2015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
2016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
2017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
2018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set script break point with the scripts loaded.
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
2021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and g and check that the script break point is active.
2023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
2025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
2027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
2028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the script origin which has both name and line offset.
2035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ScriptBreakPointLineOffset) {
2036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
2040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f;
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script = v8::String::NewFromUtf8(
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->GetIsolate(),
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function f() {\n"
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  a = 0;  // line 8 as this script has line offset 7\n"
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  b = 0;  // line 9 as this script has line offset 7\n"
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}");
2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create script origin both name and line offset.
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin(
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "test.html"),
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Integer::New(env->GetIsolate(), 7));
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set two script break points before the script is loaded.
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp1 =
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 8, 0);
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp2 =
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 9, 0);
2061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script and get the function.
2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and check that the script break point is active.
2068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
2070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
2071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the script break points.
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp1);
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp2);
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and check that no script break points are active.
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a script break point with the script loaded.
2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 9, 0);
2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and check that the script break point is active.
2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test script break points set on lines.
2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ScriptBreakPointLine) {
2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
2099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for checking the function when hitting a break point.
2101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_function_name = CompileFunction(&env,
2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        frame_function_name_source,
2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        "frame_function_name");
2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f;
2108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> g;
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script =
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(),
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "a = 0                      // line 0\n"
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "function f() {\n"
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "  a = 1;                   // line 2\n"
2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "}\n"
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              " a = 2;                    // line 4\n"
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "  /* xx */ function g() {  // line 5\n"
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "    function h() {         // line 6\n"
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "      a = 3;               // line 7\n"
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "    }\n"
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "    h();                   // line 9\n"
2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "    a = 4;                 // line 10\n"
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "  }\n"
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              " a=5;                      // line 12");
2124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a couple script break point before the script is loaded.
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp1 =
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 0, -1);
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp2 =
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 1, -1);
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp3 =
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 5, -1);
2132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the script and get the function.
2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin(
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "test.html"),
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Integer::New(env->GetIsolate(), 0));
2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  g = v8::Local<v8::Function>::Cast(
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Check that a break point was hit when the script was run.
2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
2146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(0, StrLength(last_function_hit));
2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f and check that the script break point.
2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ("f", last_function_hit);
2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call g and check that the script break point.
2154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, break_point_hit_count);
2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ("g", last_function_hit);
2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the script break point on g and set one on h.
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp3);
2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp4 =
2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 6, -1);
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call g and check that the script break point in h is hit.
2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
2165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, break_point_hit_count);
2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ("h", last_function_hit);
2167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear break points in f and h. Set a new one in the script between
2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // functions f and g and test that there is no break points in f and g any
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // more.
2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp2);
2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp4);
2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp5 =
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 4, -1);
2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reload the script which should hit two break points.
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
2184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(0, StrLength(last_function_hit));
2185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a break point in the code after the last function decleration.
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp6 =
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 12, -1);
2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reload the script which should hit three break points.
2191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
2193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, break_point_hit_count);
2194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(0, StrLength(last_function_hit));
2195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear the last break points, and reload the script which should not hit any
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // break points.
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp1);
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp5);
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp6);
2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin)->Run();
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen// Test top level script break points set on lines.
22119dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(ScriptBreakPointLineTopLevel) {
22129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  DebugLocalContext env;
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
22149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  env.ExposeDebug();
22159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
22179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script =
2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(),
2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "function f() {\n"
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "  a = 1;                   // line 1\n"
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "}\n"
2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "a = 2;                     // line 3\n");
22249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  v8::Local<v8::Function> f;
22259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  {
2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRunWithOrigin(script, "test.html");
22289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
22319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
22339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1);
22359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
22369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Call f and check that there was no break points.
22379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  break_point_hit_count = 0;
22389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  f->Call(env->Global(), 0, NULL);
22399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_EQ(0, break_point_hit_count);
22409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
22419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Recompile and run script and check that break point was hit.
22429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  break_point_hit_count = 0;
2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRunWithOrigin(script, "test.html");
22449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_EQ(1, break_point_hit_count);
22459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
22469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Call f and check that there are still no break points.
22479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  break_point_hit_count = 0;
2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
22509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_EQ(0, break_point_hit_count);
22519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
22529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  v8::Debug::SetDebugEventListener(NULL);
22539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CheckDebuggerUnloaded();
22549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
22559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
22569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
22578defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Test that it is possible to add and remove break points in a top level
22588defd9ff6930b4e24729971a61cf7469daf119beSteve Block// function which has no references but has not been collected yet.
22598defd9ff6930b4e24729971a61cf7469daf119beSteve BlockTEST(ScriptBreakPointTopLevelCrash) {
22608defd9ff6930b4e24729971a61cf7469daf119beSteve Block  DebugLocalContext env;
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
22628defd9ff6930b4e24729971a61cf7469daf119beSteve Block  env.ExposeDebug();
22638defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
22658defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script_source =
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(),
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "function f() {\n"
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "  return 0;\n"
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "}\n"
2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "f()");
22728defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp1 =
2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1);
22758defd9ff6930b4e24729971a61cf7469daf119beSteve Block  {
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
22778defd9ff6930b4e24729971a61cf7469daf119beSteve Block    break_point_hit_count = 0;
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRunWithOrigin(script_source, "test.html");
22798defd9ff6930b4e24729971a61cf7469daf119beSteve Block    CHECK_EQ(1, break_point_hit_count);
22808defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
22818defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp2 =
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1);
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp1);
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp2);
22868defd9ff6930b4e24729971a61cf7469daf119beSteve Block
22878defd9ff6930b4e24729971a61cf7469daf119beSteve Block  v8::Debug::SetDebugEventListener(NULL);
22888defd9ff6930b4e24729971a61cf7469daf119beSteve Block  CheckDebuggerUnloaded();
22898defd9ff6930b4e24729971a61cf7469daf119beSteve Block}
22908defd9ff6930b4e24729971a61cf7469daf119beSteve Block
22918defd9ff6930b4e24729971a61cf7469daf119beSteve Block
2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that it is possible to remove the last break point for a function
2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// inside the break handling of that break point.
2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(RemoveBreakPointInBreak) {
2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo =
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CompileFunction(&env, "function foo(){a=1;}", "foo");
2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  debug_event_remove_break_point = SetBreakPoint(foo, 0);
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register the debug event listener pasing the function
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventRemoveBreakPoint, foo);
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, break_point_hit_count);
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that the debugger statement causes a break.
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebuggerStatement) {
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){debugger}"))
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(),
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              "function foo(){debugger;debugger;}"))->Run();
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "bar")));
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run function with debugger statement
2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bar->Call(env->Global(), 0, NULL);
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run function with two debugger statement
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, break_point_hit_count);
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23488defd9ff6930b4e24729971a61cf7469daf119beSteve Block// Test setting a breakpoint on the debugger statement.
23494515c472dc3e5ed2448a564600976759e569a0a8Leon ClarkeTEST(DebuggerStatementBreakpoint) {
23504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    break_point_hit_count = 0;
23514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    DebugLocalContext env;
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Script::Compile(
2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(env->GetIsolate(), "function foo(){debugger;}"))
2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->Run();
2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
23594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
23604515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // The debugger statement triggers breakpint hit
23614515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    foo->Call(env->Global(), 0, NULL);
23624515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    CHECK_EQ(1, break_point_hit_count);
23634515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
23644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    int bp = SetBreakPoint(foo, 0);
23654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
23664515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Set breakpoint does not duplicate hits
23674515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    foo->Call(env->Global(), 0, NULL);
23684515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    CHECK_EQ(2, break_point_hit_count);
23694515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
23704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    ClearBreakPoint(bp);
23714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    v8::Debug::SetDebugEventListener(NULL);
23724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    CheckDebuggerUnloaded();
23734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
23744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
23754515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that the evaluation of expressions when a break point is hit generates
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the correct results.
2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugEvaluate) {
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for checking the evaluation when hitting a break point.
2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  evaluate_check_function = CompileFunction(&env,
2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            evaluate_check_source,
2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            "evaluate_check");
2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register the debug event listener
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventEvaluate);
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Different expected vaules of x and a when in a break point (u = undefined,
2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // d = Hello, world!).
2393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  struct EvaluateCheck checks_uu[] = {
2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {"x", v8::Undefined(isolate)},
2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {"a", v8::Undefined(isolate)},
2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    {NULL, v8::Handle<v8::Value>()}
2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  struct EvaluateCheck checks_hu[] = {
2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {"x", v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")},
2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {"a", v8::Undefined(isolate)},
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    {NULL, v8::Handle<v8::Value>()}
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  struct EvaluateCheck checks_hh[] = {
2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {"x", v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")},
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {"a", v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")},
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    {NULL, v8::Handle<v8::Value>()}
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Simple test function. The "y=0" is in the function foo to provide a break
2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // location. For "y=0" the "y" is at position 15 in the foo function
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // therefore setting breakpoint at position 15 will break at "y=0" and
2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // setting it higher will break after.
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(&env,
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function foo(x) {"
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  var a;"
24167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  y=0;"  // To ensure break location 1.
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  a=x;"
24187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    "  y=0;"  // To ensure break location 2.
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}",
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "foo");
24217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int foo_break_position_1 = 15;
24227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int foo_break_position_2 = 29;
2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Arguments with one parameter "Hello, world!"
2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_foo[1] = {
2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")};
2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call foo with breakpoint set before a=x and undefined as parameter.
24297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int bp = SetBreakPoint(foo, foo_break_position_1);
2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  checks = checks_uu;
2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call foo with breakpoint set before a=x and parameter "Hello, world!".
2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  checks = checks_hu;
2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 1, argv_foo);
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call foo with breakpoint set after a=x and parameter "Hello, world!".
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClearBreakPoint(bp);
24397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, foo_break_position_2);
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  checks = checks_hh;
2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 1, argv_foo);
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test that overriding Object.prototype will not interfere into evaluation
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // on call frame.
2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> zoo =
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileFunction(&env,
2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "x = undefined;"
2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "function zoo(t) {"
2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "  var a=x;"
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "  Object.prototype.x = 42;"
2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "  x=t;"
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "  y=0;"  // To ensure break location.
2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "  delete Object.prototype.x;"
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "  x=a;"
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "}",
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      "zoo");
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int zoo_break_position = 50;
2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Arguments with one parameter "Hello, world!"
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_zoo[1] = {
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")};
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call zoo with breakpoint set at y=0.
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugEventCounterClear();
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bp = SetBreakPoint(zoo, zoo_break_position);
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  checks = checks_hu;
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  zoo->Call(env->Global(), 1, argv_zoo);
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, break_point_hit_count);
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPoint(bp);
2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test function with an inner function. The "y=0" is in function barbar
2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to provide a break location. For "y=0" the "y" is at position 8 in the
2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // barbar function therefore setting breakpoint at position 8 will break at
2474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // "y=0" and setting it higher will break after.
2475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> bar = CompileFunction(&env,
2476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "y = 0;"
2477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "x = 'Goodbye, world!';"
2478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function bar(x, b) {"
2479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  var a;"
2480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  function barbar() {"
2481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    y=0; /* To ensure break location.*/"
2482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "    a=x;"
2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  };"
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  debug.Debug.clearAllBreakPoints();"
2485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  barbar();"
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  y=0;a=x;"
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}",
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "bar");
2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int barbar_break_position = 8;
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call bar setting breakpoint before a=x in barbar and undefined as
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // parameter.
2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  checks = checks_uu;
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> argv_bar_1[2] = {
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Undefined(isolate),
2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Number::New(isolate, barbar_break_position)
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bar->Call(env->Global(), 2, argv_bar_1);
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call bar setting breakpoint before a=x in barbar and parameter
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // "Hello, world!".
2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  checks = checks_hu;
2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> argv_bar_2[2] = {
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!"),
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Number::New(env->GetIsolate(), barbar_break_position)
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bar->Call(env->Global(), 2, argv_bar_2);
2508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call bar setting breakpoint after a=x in barbar and parameter
2510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // "Hello, world!".
2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  checks = checks_hh;
2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> argv_bar_3[2] = {
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!"),
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Number::New(env->GetIsolate(), barbar_break_position + 1)
2515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
2516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bar->Call(env->Global(), 2, argv_bar_3);
2517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint debugEventCount = 0;
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckDebugEvent(const v8::Debug::EventDetails& eventDetails) {
2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (eventDetails.GetEvent() == v8::Break) ++debugEventCount;
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that the conditional breakpoints work event if code generation from
2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// strings is prohibited in the debugee context.
2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ConditionalBreakpointWithCodeGenerationDisallowed) {
2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env.ExposeDebug();
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(CheckDebugEvent);
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env,
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function foo(x) {\n"
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  var s = 'String value2';\n"
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  return s + x;\n"
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}",
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "foo");
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set conditional breakpoint with condition 'true'.
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("debug.Debug.setBreakPoint(foo, 2, 0, 'true')");
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  debugEventCount = 0;
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->AllowCodeGenerationFromStrings(false);
2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo->Call(env->Global(), 0, NULL);
2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, debugEventCount);
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckDebuggerUnloaded();
2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool checkedDebugEvals = true;
2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochv8::Handle<v8::Function> checkGlobalEvalFunction;
2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochv8::Handle<v8::Function> checkFrameEvalFunction;
2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckDebugEval(const v8::Debug::EventDetails& eventDetails) {
2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (eventDetails.GetEvent() == v8::Break) {
2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ++debugEventCount;
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handleScope(CcTest::isolate());
2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Value> args[] = { eventDetails.GetExecutionState() };
2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(checkGlobalEvalFunction->Call(
2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        eventDetails.GetEventContext()->Global(), 1, args)->IsTrue());
2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(checkFrameEvalFunction->Call(
2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        eventDetails.GetEventContext()->Global(), 1, args)->IsTrue());
2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test that the evaluation of expressions when a break point is hit generates
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the correct results in case code generation from strings is disallowed in the
2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// debugee context.
2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(DebugEvaluateWithCodeGenerationDisallowed) {
2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env.ExposeDebug();
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(CheckDebugEval);
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env,
2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "var global = 'Global';\n"
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function foo(x) {\n"
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  var local = 'Local';\n"
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  debugger;\n"
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  return local + x;\n"
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}",
2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "foo");
2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  checkGlobalEvalFunction = CompileFunction(&env,
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function checkGlobalEval(exec_state) {\n"
2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  return exec_state.evaluateGlobal('global').value() === 'Global';\n"
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}",
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "checkGlobalEval");
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  checkFrameEvalFunction = CompileFunction(&env,
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "function checkFrameEval(exec_state) {\n"
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "  return exec_state.frame(0).evaluate('local').value() === 'Local';\n"
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "}",
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    "checkFrameEval");
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  debugEventCount = 0;
2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->AllowCodeGenerationFromStrings(false);
2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo->Call(env->Global(), 0, NULL);
2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, debugEventCount);
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  checkGlobalEvalFunction.Clear();
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  checkFrameEvalFunction.Clear();
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckDebuggerUnloaded();
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Copies a C string to a 16-bit string.  Does not check for buffer overflow.
2617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Does not use the V8 engine to convert strings, so it can be used
2618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// in any thread.  Returns the length of the string.
2619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeint AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
2620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int i;
2621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  for (i = 0; input_buffer[i] != '\0'; ++i) {
2622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // ASCII does not use chars > 127, but be careful anyway.
2623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
2624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  output_buffer[i] = 0;
2626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return i;
2627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Copies a 16-bit string to a C string by dropping the high byte of
2631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// each character.  Does not check for buffer overflow.
2632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Can be used in any thread.  Requires string length as an input.
2633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeint Utf16ToAscii(const uint16_t* input_buffer, int length,
2634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                 char* output_buffer, int output_len = -1) {
2635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (output_len >= 0) {
2636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (length > output_len - 1) {
2637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      length = output_len - 1;
2638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  for (int i = 0; i < length; ++i) {
2642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    output_buffer[i] = static_cast<char>(input_buffer[i]);
2643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  output_buffer[length] = '\0';
2645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return length;
2646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// We match parts of the message to get evaluate result int value.
2650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkebool GetEvaluateStringResult(char *message, char* buffer, int buffer_size) {
2651d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (strstr(message, "\"command\":\"evaluate\"") == NULL) {
2652d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return false;
2653d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2654d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const char* prefix = "\"text\":\"";
2655d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  char* pos1 = strstr(message, prefix);
2656d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (pos1 == NULL) {
2657d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return false;
2658d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2659d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  pos1 += strlen(prefix);
2660d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  char* pos2 = strchr(pos1, '"');
2661d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (pos2 == NULL) {
2662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return false;
2663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Vector<char> buf(buffer, buffer_size);
2665d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int len = static_cast<int>(pos2 - pos1);
2666d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (len > buffer_size - 1) {
2667d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    len = buffer_size - 1;
2668d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StrNCpy(buf, pos1, len);
2670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  buffer[buffer_size - 1] = '\0';
2671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return true;
2672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestruct EvaluateResult {
2676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static const int kBufferSize = 20;
2677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  char buffer[kBufferSize];
2678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
2679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestruct DebugProcessDebugMessagesData {
2681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static const int kArraySize = 5;
2682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int counter;
2683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  EvaluateResult results[kArraySize];
2684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void reset() {
2686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    counter = 0;
2687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  EvaluateResult* current() {
2689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return &results[counter % kArraySize];
2690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void next() {
2692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    counter++;
2693e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke};
2695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeDebugProcessDebugMessagesData process_debug_messages_data;
2697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void DebugProcessDebugMessagesHandler(
2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::Message& message) {
2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> json = message.GetJSON();
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value utf8(json);
2702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  EvaluateResult* array_item = process_debug_messages_data.current();
2703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool res = GetEvaluateStringResult(*utf8,
2705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     array_item->buffer,
2706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                     EvaluateResult::kBufferSize);
2707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (res) {
2708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    process_debug_messages_data.next();
2709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2713e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Test that the evaluation of expressions works even from ProcessDebugMessages
2714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// i.e. with empty stack.
2715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeTEST(DebugEvaluateWithoutStack) {
2716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::SetMessageHandler(DebugProcessDebugMessagesHandler);
2717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2718e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DebugLocalContext env;
2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2720e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2721e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  const char* source =
2722e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "var v1 = 'Pinguin';\n function getAnimal() { return 'Capy' + 'bara'; }";
2723e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), source))
2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
2726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::ProcessDebugMessages();
2728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2729e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  const int kBufferSize = 1000;
2730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  uint16_t buffer[kBufferSize];
2731e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2732e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  const char* command_111 = "{\"seq\":111,"
2733e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "\"type\":\"request\","
2734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "\"command\":\"evaluate\","
2735e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "\"arguments\":{"
2736e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "    \"global\":true,"
2737e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "    \"expression\":\"v1\",\"disable_break\":true"
2738e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "}}";
2739e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_111, buffer));
2742e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  const char* command_112 = "{\"seq\":112,"
2744e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "\"type\":\"request\","
2745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "\"command\":\"evaluate\","
2746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "\"arguments\":{"
2747e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "    \"global\":true,"
2748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "    \"expression\":\"getAnimal()\",\"disable_break\":true"
2749e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "}}";
2750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_112, buffer));
2752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  const char* command_113 = "{\"seq\":113,"
2754e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     "\"type\":\"request\","
2755e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     "\"command\":\"evaluate\","
2756e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     "\"arguments\":{"
2757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     "    \"global\":true,"
2758e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     "    \"expression\":\"239 + 566\",\"disable_break\":true"
2759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     "}}";
2760e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_113, buffer));
2762e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2763e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::ProcessDebugMessages();
2764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2765e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_EQ(3, process_debug_messages_data.counter);
2766e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2767d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK_EQ(strcmp("Pinguin", process_debug_messages_data.results[0].buffer), 0);
2768d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK_EQ(strcmp("Capybara", process_debug_messages_data.results[1].buffer),
2769d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke           0);
2770d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK_EQ(strcmp("805", process_debug_messages_data.results[2].buffer), 0);
2771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::SetMessageHandler(NULL);
2773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::SetDebugEventListener(NULL);
2774e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CheckDebuggerUnloaded();
2775e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
2776e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Simple test of the stepping mechanism using only store ICs.
2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepLinear) {
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping.
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(&env,
2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                "function foo(){a=1;b=1;c=1;}",
2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                "foo");
2787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Run foo to allow it to get optimized.
2789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("a=0; b=0; c=0; foo();");
2790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 3);
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
2794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStep);
2795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
2797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // With stepping all break locations are hit.
2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, break_point_hit_count);
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which just counts.
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 3);
2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Without stepping only active break points are hit.
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test of the stepping mechanism for keyed load in a loop.
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepKeyedLoadLoop) {
2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
28277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
28287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping of keyed load. The statement 'y=1'
2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is there to have more than one breakable statement in the loop, TODO(315).
2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      &env,
2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function foo(a) {\n"
2834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  var x;\n"
2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  var len = a.length;\n"
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  for (var i = 0; i < len; i++) {\n"
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    y = 1;\n"
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    x = a[i];\n"
2839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  }\n"
2840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "}\n"
2841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "y=0\n",
2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "foo");
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create array [0,1,2,3,4,5,6,7,8,9]
2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    a->Set(v8::Number::New(env->GetIsolate(), i),
2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           v8::Number::New(env->GetIsolate(), i));
2849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call function without any break points to ensure inlining is in place.
2852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kArgc = 1;
2853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> args[kArgc] = { a };
2854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), kArgc, args);
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up break point and step through the function.
2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 3);
2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepNext;
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), kArgc, args);
2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // With stepping all break locations are hit.
2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(35, break_point_hit_count);
2864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test of the stepping mechanism for keyed store in a loop.
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepKeyedStoreLoop) {
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
28767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
28777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping of keyed store. The statement 'y=1'
2879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is there to have more than one breakable statement in the loop, TODO(315).
2880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(
2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      &env,
2882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function foo(a) {\n"
2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  var len = a.length;\n"
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  for (var i = 0; i < len; i++) {\n"
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    y = 1;\n"
2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    a[i] = 42;\n"
2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  }\n"
2888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "}\n"
2889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "y=0\n",
2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "foo");
2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create array [0,1,2,3,4,5,6,7,8,9]
2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 10; i++) {
2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    a->Set(v8::Number::New(env->GetIsolate(), i),
2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           v8::Number::New(env->GetIsolate(), i));
2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call function without any break points to ensure inlining is in place.
2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kArgc = 1;
2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> args[kArgc] = { a };
2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), kArgc, args);
2903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up break point and step through the function.
2905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 3);
2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepNext;
2907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
2908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), kArgc, args);
2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // With stepping all break locations are hit.
2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(34, break_point_hit_count);
2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
2914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
2915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen// Test of the stepping mechanism for named load in a loop.
291925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian MonsenTEST(DebugStepNamedLoadLoop) {
292025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  DebugLocalContext env;
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
292225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
29237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
29247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
29257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
292625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Create a function for testing stepping of named load.
292725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  v8::Local<v8::Function> foo = CompileFunction(
292825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      &env,
292925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      "function foo() {\n"
293025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "  var a = [];\n"
293125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "  var s = \"\";\n"
293225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "  for (var i = 0; i < 10; i++) {\n"
293325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "    var v = new V(i, i + 1);\n"
293425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "    v.y;\n"
293525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "    a.length;\n"  // Special case: array length.
293625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "    s.length;\n"  // Special case: string length.
293725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "  }\n"
293825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "}\n"
293925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "function V(x, y) {\n"
294025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "  this.x = x;\n"
294125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "  this.y = y;\n"
294225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "}\n",
294325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          "foo");
294425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
294525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Call function without any break points to ensure inlining is in place.
294625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  foo->Call(env->Global(), 0, NULL);
294725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
29483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up break point and step through the function.
294925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  SetBreakPoint(foo, 4);
295025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  step_action = StepNext;
295125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  break_point_hit_count = 0;
295225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  foo->Call(env->Global(), 0, NULL);
295325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
295425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // With stepping all break locations are hit.
2955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(55, break_point_hit_count);
295625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
295725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  v8::Debug::SetDebugEventListener(NULL);
295825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  CheckDebuggerUnloaded();
295925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen}
296025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
296125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
2962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void DoDebugStepNamedStoreLoop(int expected) {
2963756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  DebugLocalContext env;
2964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
2965756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Register a debug event listener which steps and counts.
2967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
2968756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2969756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Create a function for testing stepping of named store.
2970756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::Local<v8::Function> foo = CompileFunction(
2971756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      &env,
2972756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "function foo() {\n"
2973756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick          "  var a = {a:1};\n"
2974756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick          "  for (var i = 0; i < 10; i++) {\n"
2975756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick          "    a.a = 2\n"
2976756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick          "  }\n"
2977756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick          "}\n",
2978756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick          "foo");
2979756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2980756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Call function without any break points to ensure inlining is in place.
2981756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  foo->Call(env->Global(), 0, NULL);
2982756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up break point and step through the function.
2984756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  SetBreakPoint(foo, 3);
2985756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  step_action = StepNext;
2986756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  break_point_hit_count = 0;
2987756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  foo->Call(env->Global(), 0, NULL);
2988756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2989756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // With stepping all expected break locations are hit.
2990756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(expected, break_point_hit_count);
2991756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2992756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::Debug::SetDebugEventListener(NULL);
2993756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CheckDebuggerUnloaded();
2994756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
2995756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2996756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2997756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick// Test of the stepping mechanism for named load in a loop.
2998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DebugStepNamedStoreLoop) {
2999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoDebugStepNamedStoreLoop(24);
3000756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
3001756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3002756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test the stepping mechanism with different ICs.
3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepLinearMixedICs) {
3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
30097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
30107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping.
3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(&env,
3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function bar() {};"
3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function foo() {"
3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  var x;"
3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  var index='name';"
3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  var y = {};"
3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  a=1;b=2;x=a;y[index]=3;x=y[index];bar();}", "foo");
3019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Run functions to allow them to get optimized.
3021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("a=0; b=0; bar(); foo();");
3022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 0);
3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
3028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // With stepping all break locations are hit.
30307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(11, break_point_hit_count);
3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which just counts.
3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 0);
3039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
3041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Without stepping only active break points are hit.
3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(DebugStepDeclarations) {
30517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DebugLocalContext env;
3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
30537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
30557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
30567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
30597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src = "function foo() { "
30607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var a;"
30617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var b = 1;"
30627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var c = foo;"
30637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var d = Math.floor;"
30647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var e = b + d(1.2);"
3065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "foo()";
30677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 0);
30707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Stepping through the declarations.
30727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
30737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
30747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), 0, NULL);
30757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(6, break_point_hit_count);
30767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get rid of the debug event listener.
30787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
30797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckDebuggerUnloaded();
30807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
30817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(DebugStepLocals) {
30847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DebugLocalContext env;
3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
30867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
30877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
30887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
30897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
30927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src = "function foo() { "
30937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var a,b;"
30947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  a = 1;"
30957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  b = a + 2;"
30967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  b = 1 + 2 + 3;"
30977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  a = Math.floor(b);"
3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "foo()";
31007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
31027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 0);
31037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Stepping through the declarations.
31057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
31067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
31077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), 0, NULL);
31087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(6, break_point_hit_count);
31097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get rid of the debug event listener.
31117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
31127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckDebuggerUnloaded();
31137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
31147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
31157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepIf) {
3117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
3122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStep);
3123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
3126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = 1;
3127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function foo(x) { "
3128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  a = 1;"
3129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  if (x) {"
3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "    b = 1;"
3131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  } else {"
3132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "    c = 1;"
3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "    d = 1;"
3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  }"
3135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "a=0; b=0; c=0; d=0; foo()";
3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 0);
3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stepping through the true part.
3141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
3144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), argc, argv_true);
31457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(4, break_point_hit_count);
3146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stepping through the false part.
3148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_false[argc] = { v8::False(isolate) };
3151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), argc, argv_false);
31527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(5, break_point_hit_count);
3153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug event listener.
3155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepSwitch) {
3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
3166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStep);
3167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = 1;
3171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function foo(x) { "
3172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  a = 1;"
3173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  switch (x) {"
3174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "    case 1:"
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "      b = 1;"
3176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "    case 2:"
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "      c = 1;"
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "      break;"
3179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "    case 3:"
3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "      d = 1;"
3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "      e = 1;"
31827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "      f = 1;"
3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "      break;"
3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  }"
3185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "a=0; b=0; c=0; d=0; e=0; f=0; foo()";
3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 0);
3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // One case with fall-through.
3191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_1[argc] = { v8::Number::New(isolate, 1) };
3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), argc, argv_1);
31957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(6, break_point_hit_count);
3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Another case.
3198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_2[argc] = { v8::Number::New(isolate, 2) };
3201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), argc, argv_2);
32027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(5, break_point_hit_count);
3203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Last case.
3205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_3[argc] = { v8::Number::New(isolate, 3) };
3208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), argc, argv_3);
32097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(7, break_point_hit_count);
32107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get rid of the debug event listener.
32127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
32137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckDebuggerUnloaded();
32147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
32157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(DebugStepWhile) {
32187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DebugLocalContext env;
3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
32217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
32237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
32247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
32277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = 1;
32287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src = "function foo(x) { "
32297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var a = 0;"
32307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  while (a < x) {"
32317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    a++;"
32327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  }"
3233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "foo()";
32357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
32367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 8);  // "var a = 0;"
32377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Looping 0 times.  We still should break at the while-condition once.
3239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  step_action = StepIn;
3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  break_point_hit_count = 0;
3241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_0[argc] = { v8::Number::New(isolate, 0) };
3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  foo->Call(env->Global(), argc, argv_0);
3243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3, break_point_hit_count);
3244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Looping 10 times.
32467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
32477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
32497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), argc, argv_10);
3250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(23, break_point_hit_count);
32517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Looping 100 times.
32537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
32547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
3255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
32567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), argc, argv_100);
3257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(203, break_point_hit_count);
32587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get rid of the debug event listener.
32607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
32617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckDebuggerUnloaded();
32627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
32637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(DebugStepDoWhile) {
32667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DebugLocalContext env;
3267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
32697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
32717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
32727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
32757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = 1;
32767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src = "function foo(x) { "
32777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var a = 0;"
32787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  do {"
32797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    a++;"
32807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  } while (a < x)"
3281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "foo()";
32837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
32847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 8);  // "var a = 0;"
32857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Looping 10 times.
32877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
32887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
32907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), argc, argv_10);
32917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(22, break_point_hit_count);
32927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
32937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Looping 100 times.
32947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
32957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
32977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), argc, argv_100);
32987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(202, break_point_hit_count);
3299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug event listener.
3301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepFor) {
3307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
3312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStep);
3313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
3316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = 1;
3317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function foo(x) { "
3318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  a = 1;"
3319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  for (i = 0; i < x; i++) {"
3320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "    b = 1;"
3321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "  }"
3322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "a=0; b=0; i=0; foo()";
3324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(foo, 8);  // "a = 1;"
3327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Looping 10 times.
3329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
3332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), argc, argv_10);
3333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(23, break_point_hit_count);
3334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Looping 100 times.
3336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
3339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), argc, argv_100);
3340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(203, break_point_hit_count);
3341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug event listener.
3343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(DebugStepForContinue) {
33497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DebugLocalContext env;
3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
33527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
33537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
33547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
33557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
33587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = 1;
33597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src = "function foo(x) { "
33607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var a = 0;"
33617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var b = 0;"
33627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var c = 0;"
33637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  for (var i = 0; i < x; i++) {"
33647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    a++;"
33657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    if (a % 2 == 0) continue;"
33667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    b++;"
33677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    c++;"
33687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  }"
33697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  return b;"
3370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "foo()";
33727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
33737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Handle<v8::Value> result;
33747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 8);  // "var a = 0;"
33757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
33767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Each loop generates 4 or 5 steps depending on whether a is equal.
33777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
33787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Looping 10 times.
33797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
33807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
3381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
33827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  result = foo->Call(env->Global(), argc, argv_10);
33837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(5, result->Int32Value());
3384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(52, break_point_hit_count);
33857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
33867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Looping 100 times.
33877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
33887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
33907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  result = foo->Call(env->Global(), argc, argv_100);
33917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(50, result->Int32Value());
3392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(457, break_point_hit_count);
33937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
33947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get rid of the debug event listener.
33957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
33967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckDebuggerUnloaded();
33977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
33987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
33997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(DebugStepForBreak) {
34017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DebugLocalContext env;
3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
34047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
34067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
34077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
34107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = 1;
34117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src = "function foo(x) { "
34127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var a = 0;"
34137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var b = 0;"
34147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var c = 0;"
34157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  for (var i = 0; i < 1000; i++) {"
34167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    a++;"
34177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    if (a == x) break;"
34187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    b++;"
34197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "    c++;"
34207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  }"
34217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  return b;"
3422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "foo()";
34247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
34257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Handle<v8::Value> result;
34267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 8);  // "var a = 0;"
34277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Each loop generates 5 steps except for the last (when break is executed)
34297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // which only generates 4.
34307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Looping 10 times.
34327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
34337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
34357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  result = foo->Call(env->Global(), argc, argv_10);
34367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(9, result->Int32Value());
3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(55, break_point_hit_count);
34387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Looping 100 times.
34407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
34417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
34437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  result = foo->Call(env->Global(), argc, argv_100);
34447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(99, result->Int32Value());
3445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(505, break_point_hit_count);
34467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get rid of the debug event listener.
34487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
34497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckDebuggerUnloaded();
34507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
34517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(DebugStepForIn) {
34547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DebugLocalContext env;
3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
34567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
34587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
34597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
34627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Local<v8::Function> foo;
34637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src_1 = "function foo() { "
34647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                      "  var a = [1, 2];"
34657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                      "  for (x in a) {"
34667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                      "    b = 0;"
34677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                      "  }"
3468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      "}"
3469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      "foo()";
34707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo = CompileFunction(&env, src_1, "foo");
34717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 0);  // "var a = ..."
34727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
34747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
34757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), 0, NULL);
34767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(6, break_point_hit_count);
34777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
34807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src_2 = "function foo() { "
34817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                      "  var a = {a:[1, 2, 3]};"
34827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                      "  for (x in a.a) {"
34837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                      "    b = 0;"
34847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                      "  }"
3485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      "}"
3486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      "foo()";
34877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo = CompileFunction(&env, src_2, "foo");
34887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 0);  // "var a = ..."
34897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
34917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
34927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), 0, NULL);
34937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(8, break_point_hit_count);
34947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
34957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get rid of the debug event listener.
34967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
34977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckDebuggerUnloaded();
34987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
34997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(DebugStepWith) {
35027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DebugLocalContext env;
3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
35047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
35067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
35077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
35107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src = "function foo(x) { "
35117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var a = {};"
35127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  with (a) {}"
35137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  with (b) {}"
3514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "foo()";
3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8::String::NewFromUtf8(env->GetIsolate(), "b"),
3517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     v8::Object::New(env->GetIsolate()));
35187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
35197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Handle<v8::Value> result;
35207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 8);  // "var a = {};"
35217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
35237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
35247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), 0, NULL);
35257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(4, break_point_hit_count);
35267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get rid of the debug event listener.
35287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
35297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckDebuggerUnloaded();
35307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
35317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(DebugConditional) {
35347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  DebugLocalContext env;
3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
35377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Register a debug event listener which steps and counts.
35397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStep);
35407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
35437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const char* src = "function foo(x) { "
35447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  var a;"
35457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  a = x ? 1 : 2;"
35467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                    "  return a;"
3547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "}"
3548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "foo()";
35497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
35507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetBreakPoint(foo, 0);  // "var a;"
35517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
35537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
35547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), 0, NULL);
35557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(5, break_point_hit_count);
35567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  step_action = StepIn;
35587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  break_point_hit_count = 0;
35597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  const int argc = 1;
3560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
35617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  foo->Call(env->Global(), argc, argv_true);
35627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(5, break_point_hit_count);
35637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Get rid of the debug event listener.
35657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
35667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CheckDebuggerUnloaded();
35677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
35687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
35697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(StepInOutSimple) {
3571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
3573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for checking the function when hitting a break point.
3575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_function_name = CompileFunction(&env,
3576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        frame_function_name_source,
3577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        "frame_function_name");
3578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
3580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
3581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
3584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function a() {b();c();}; "
3585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function b() {c();}; "
3586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "function c() {}; "
3587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "a(); b(); c()";
3588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(a, 0);
3590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of a with step in.
3592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  expected_step_sequence = "abcbaca";
3595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  a->Call(env->Global(), 0, NULL);
3596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
3597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
3598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of a with step next.
3600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepNext;
3601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  expected_step_sequence = "aaa";
3603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  a->Call(env->Global(), 0, NULL);
3604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
3605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
3606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of a with step out.
3608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepOut;
3609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  expected_step_sequence = "a";
3611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  a->Call(env->Global(), 0, NULL);
3612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
3613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
3614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug event listener.
3616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(StepInOutTree) {
3622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
3624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for checking the function when hitting a break point.
3626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_function_name = CompileFunction(&env,
3627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        frame_function_name_source,
3628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        "frame_function_name");
3629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
3631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
3632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
3635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function a() {b(c(d()),d());c(d());d()}; "
3636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function b(x,y) {c();}; "
3637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function c(x) {}; "
3638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "function d() {}; "
3639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "a(); b(); c(); d()";
3640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(a, 0);
3642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of a with step in.
3644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  expected_step_sequence = "adacadabcbadacada";
3647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  a->Call(env->Global(), 0, NULL);
3648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
3649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
3650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of a with step next.
3652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepNext;
3653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  expected_step_sequence = "aaaa";
3655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  a->Call(env->Global(), 0, NULL);
3656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
3657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
3658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of a with step out.
3660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepOut;
3661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  expected_step_sequence = "a";
3663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  a->Call(env->Global(), 0, NULL);
3664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
3665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
3666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug event listener.
3668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded(true);
3670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(StepInOutBranch) {
3674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
3676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for checking the function when hitting a break point.
3678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_function_name = CompileFunction(&env,
3679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        frame_function_name_source,
3680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        "frame_function_name");
3681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
3683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
3684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for testing stepping. Run it to allow it to get
3686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // optimized.
3687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function a() {b(false);c();}; "
3688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function b(x) {if(x){c();};}; "
3689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "function c() {}; "
3690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    "a(); b(); c()";
3691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(a, 0);
3693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of a.
3695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
36977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  expected_step_sequence = "abbaca";
3698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  a->Call(env->Global(), 0, NULL);
3699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
3700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
3701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug event listener.
3703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that step in does not step into native functions.
3709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepNatives) {
3710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
3712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping.
3714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(
3715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      &env,
3716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function foo(){debugger;Math.sin(1);}",
3717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "foo");
3718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
3720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStep);
3721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
3725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // With stepping all break locations are hit.
3727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, break_point_hit_count);
3728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which just counts.
3733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
3734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
3737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Without stepping only active break points are hit.
3739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
3740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that step in works with function.apply.
3747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepFunctionApply) {
3748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
3750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping.
3752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(
3753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      &env,
3754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
3755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function foo(){ debugger; bar.apply(this, [1,2,3]); }",
3756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "foo");
3757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
3759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStep);
3760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
3764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // With stepping all break locations are hit.
37667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(7, break_point_hit_count);
3767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which just counts.
3772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
3773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
3776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Without stepping only the debugger statement is hit.
3778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
3779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that step in works with function.call.
3786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugStepFunctionCall) {
3787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
3789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
3790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping.
3792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> foo = CompileFunction(
3793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      &env,
3794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
3795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function foo(a){ debugger;"
3796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "                 if (a) {"
3797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "                   bar.call(this, 1, 2, 3);"
3798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "                 } else {"
3799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "                   bar.call(this, 0);"
3800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "                 }"
3801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "}",
3802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "foo");
3803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
3805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStep);
3806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
3807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check stepping where the if condition in bar is false.
3809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
38117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(6, break_point_hit_count);
3812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check stepping where the if condition in bar is true.
3814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = 1;
3816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv[argc] = { v8::True(isolate) };
3817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), argc, argv);
38187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  CHECK_EQ(8, break_point_hit_count);
3819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which just counts.
3824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
3825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
3827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo->Call(env->Global(), 0, NULL);
3828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Without stepping only the debugger statement is hit.
3830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
3831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
3833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
3834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Tests that breakpoint will be hit if it's set in script.
3838d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockTEST(PauseInScript) {
3839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  DebugLocalContext env;
3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
3841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  env.ExposeDebug();
3842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Register a debug event listener which counts.
3844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Debug::SetDebugEventListener(DebugEventCounter);
3845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create a script that returns a function.
3847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* src = "(function (evt) {})";
3848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* script_name = "StepInHandlerTest";
3849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set breakpoint in the script.
3851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetScriptBreakPointByNameFromJS(env->GetIsolate(), script_name, 0, -1);
3852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  break_point_hit_count = 0;
3853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin(
3855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), script_name),
3856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Integer::New(env->GetIsolate(), 0));
3857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script = v8::Script::Compile(
3858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), src), &origin);
3859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Local<v8::Value> r = script->Run();
3860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(r->IsFunction());
3862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(1, break_point_hit_count);
3863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Get rid of the debug event listener.
3865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Debug::SetDebugEventListener(NULL);
3866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CheckDebuggerUnloaded();
3867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
3868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
3870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test break on exceptions. For each exception break combination the number
3871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of debug event exception callbacks and message callbacks are collected. The
3872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// number of debug event exception callbacks are used to check that the
3873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugger is called correctly and the number of message callbacks is used to
3874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// check that uncaught exceptions are still returned even if there is a break
3875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for them.
3876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(BreakOnException) {
3877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
3878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
3879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
3880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create functions for testing break on exception.
38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileFunction(&env, "function throws(){throw 1;}", "throws");
3883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> caught =
3884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CompileFunction(&env,
3885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "function caught(){try {throws();} catch(e) {};}",
3886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      "caught");
3887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> notCaught =
3888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CompileFunction(&env, "function notCaught(){throws();}", "notCaught");
3889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::AddMessageListener(MessageCallbackCount);
3891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventCounter);
3892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3893086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Initial state should be no break on exceptions.
3894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
3895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
3896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  caught->Call(env->Global(), 0, NULL);
3897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, exception_hit_count);
3898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
3900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  notCaught->Call(env->Global(), 0, NULL);
3901086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_EQ(0, exception_hit_count);
3902086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_EQ(0, uncaught_exception_hit_count);
3903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
3904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // No break on exception
3906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
3907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
3908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ChangeBreakOnException(false, false);
3909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  caught->Call(env->Global(), 0, NULL);
3910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, exception_hit_count);
3911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
3913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  notCaught->Call(env->Global(), 0, NULL);
3914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, exception_hit_count);
3915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
3917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Break on uncaught exception
3919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
3920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
3921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ChangeBreakOnException(false, true);
3922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  caught->Call(env->Global(), 0, NULL);
3923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, exception_hit_count);
3924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
3926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  notCaught->Call(env->Global(), 0, NULL);
3927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, exception_hit_count);
3928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, uncaught_exception_hit_count);
3929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
3930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Break on exception and uncaught exception
3932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
3933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
3934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ChangeBreakOnException(true, true);
3935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  caught->Call(env->Global(), 0, NULL);
3936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, exception_hit_count);
3937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
3939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  notCaught->Call(env->Global(), 0, NULL);
3940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, exception_hit_count);
3941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, uncaught_exception_hit_count);
3942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
3943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Break on exception
3945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
3946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
3947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ChangeBreakOnException(true, false);
3948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  caught->Call(env->Global(), 0, NULL);
3949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, exception_hit_count);
3950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
3952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  notCaught->Call(env->Global(), 0, NULL);
3953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, exception_hit_count);
3954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, uncaught_exception_hit_count);
3955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
3956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // No break on exception using JavaScript
3958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
3959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
3960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, false);
3961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  caught->Call(env->Global(), 0, NULL);
3962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, exception_hit_count);
3963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
3965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  notCaught->Call(env->Global(), 0, NULL);
3966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, exception_hit_count);
3967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
3969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Break on uncaught exception using JavaScript
3971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
3972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
3973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, true);
3974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  caught->Call(env->Global(), 0, NULL);
3975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, exception_hit_count);
3976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
3978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  notCaught->Call(env->Global(), 0, NULL);
3979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, exception_hit_count);
3980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, uncaught_exception_hit_count);
3981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
3982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Break on exception and uncaught exception using JavaScript
3984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
3985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
3986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, true);
3987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  caught->Call(env->Global(), 0, NULL);
3988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, exception_hit_count);
3989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
3990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
3991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  notCaught->Call(env->Global(), 0, NULL);
3992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, exception_hit_count);
3993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, uncaught_exception_hit_count);
3994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
3995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Break on exception using JavaScript
3997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
3998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
3999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, false);
4000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  caught->Call(env->Global(), 0, NULL);
4001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, exception_hit_count);
4002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
4003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
4004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  notCaught->Call(env->Global(), 0, NULL);
4005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, exception_hit_count);
4006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, uncaught_exception_hit_count);
4007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
4008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
4010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
4011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::RemoveMessageListeners(MessageCallbackCount);
4012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(EvalJSInDebugEventListenerOnNativeReThrownException) {
4016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
4017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
4018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env.ExposeDebug();
4019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create functions for testing break on exception.
4021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> noThrowJS = CompileFunction(
4022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      &env, "function noThrowJS(){var a=[1]; a.push(2); return a.length;}",
4023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "noThrowJS");
4024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  debug_event_listener_callback = noThrowJS;
4026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  debug_event_listener_callback_result = 2;
4027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::AddMessageListener(MessageCallbackCount);
4029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventCounter);
4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Break on uncaught exception
4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeBreakOnException(false, true);
4032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugEventCounterClear();
4033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MessageCallbackCountClear();
4034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ReThrow native error
4036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::TryCatch tryCatch;
4038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    env->GetIsolate()->ThrowException(v8::Exception::TypeError(
4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(env->GetIsolate(), "Type error")));
4040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(tryCatch.HasCaught());
4041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tryCatch.ReThrow();
4042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, exception_hit_count);
4044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, uncaught_exception_hit_count);
4045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, message_callback_count);  // FIXME: Should it be 1 ?
4046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!debug_event_listener_callback.IsEmpty());
4047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  debug_event_listener_callback.Clear();
4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test break on exception from compiler errors. When compiling using
4053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// v8::Script::Compile there is no JavaScript stack whereas when compiling using
4054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// eval there are JavaScript frames.
4055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(BreakOnCompileException) {
4056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
4057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
4058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4059086aeeaae12517475c22695a200be45495516549Ben Murdoch  // For this test, we want to break on uncaught exceptions:
4060086aeeaae12517475c22695a200be45495516549Ben Murdoch  ChangeBreakOnException(false, true);
4061086aeeaae12517475c22695a200be45495516549Ben Murdoch
4062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for checking the function when hitting a break point.
4063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_count = CompileFunction(&env, frame_count_source, "frame_count");
4064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::AddMessageListener(MessageCallbackCount);
4066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventCounter);
4067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugEventCounterClear();
4069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageCallbackCountClear();
4070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check initial state.
4072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, exception_hit_count);
4073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, uncaught_exception_hit_count);
4074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_callback_count);
4075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, last_js_stack_height);
4076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Throws SyntaxError: Unexpected end of input
4078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "+++"));
4079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, exception_hit_count);
4080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, uncaught_exception_hit_count);
4081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_callback_count);
4082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
4083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Throws SyntaxError: Unexpected identifier
4085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "x x"));
4086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, exception_hit_count);
4087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, uncaught_exception_hit_count);
4088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, message_callback_count);
4089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
4090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Throws SyntaxError: Unexpected end of input
4092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "eval('+++')"))
4093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
4094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, exception_hit_count);
4095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, uncaught_exception_hit_count);
4096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, message_callback_count);
4097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, last_js_stack_height);
4098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Throws SyntaxError: Unexpected identifier
4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "eval('x x')"))
4101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
4102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, exception_hit_count);
4103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, uncaught_exception_hit_count);
4104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(4, message_callback_count);
4105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, last_js_stack_height);
4106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(StepWithException) {
4110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
4112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4113086aeeaae12517475c22695a200be45495516549Ben Murdoch  // For this test, we want to break on uncaught exceptions:
4114086aeeaae12517475c22695a200be45495516549Ben Murdoch  ChangeBreakOnException(false, true);
4115086aeeaae12517475c22695a200be45495516549Ben Murdoch
4116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for checking the function when hitting a break point.
4117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_function_name = CompileFunction(&env,
4118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        frame_function_name_source,
4119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        "frame_function_name");
4120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which steps and counts.
4122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
4123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create functions for testing stepping.
4125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function a() { n(); }; "
4126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function b() { c(); }; "
4127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function c() { n(); }; "
4128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function d() { x = 1; try { e(); } catch(x) { x = 2; } }; "
4129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function e() { n(); }; "
4130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function f() { x = 1; try { g(); } catch(x) { x = 2; } }; "
4131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function g() { h(); }; "
4132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function h() { x = 1; throw 1; }; ";
4133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of a.
4135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
4136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(a, 0);
4137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
4138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
4139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  expected_step_sequence = "aa";
4140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  a->Call(env->Global(), 0, NULL);
4141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
4142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
4143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of b + c.
4145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> b = CompileFunction(&env, src, "b");
4146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(b, 0);
4147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
4148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
4149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  expected_step_sequence = "bcc";
4150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  b->Call(env->Global(), 0, NULL);
4151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
4152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
4153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of d + e.
4154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> d = CompileFunction(&env, src, "d");
4155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(d, 0);
4156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ChangeBreakOnException(false, true);
4157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
4158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
41597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  expected_step_sequence = "ddedd";
4160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  d->Call(env->Global(), 0, NULL);
4161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
4162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
4163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of d + e now with break on caught exceptions.
4165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ChangeBreakOnException(true, true);
4166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
4167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
41687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  expected_step_sequence = "ddeedd";
4169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  d->Call(env->Global(), 0, NULL);
4170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
4171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
4172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of f + g + h.
4174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
4175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetBreakPoint(f, 0);
4176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ChangeBreakOnException(false, true);
4177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
4178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
41797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  expected_step_sequence = "ffghhff";
4180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
4181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
4182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
4183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Step through invocation of f + g + h now with break on caught exceptions.
4185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ChangeBreakOnException(true, true);
4186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  step_action = StepIn;
4187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
41887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  expected_step_sequence = "ffghhhff";
4189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
4190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(StrLength(expected_step_sequence),
4191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           break_point_hit_count);
4192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug event listener.
4194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
4195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
4196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugBreak) {
4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_stress_compaction = false;
4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
4202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::FLAG_verify_heap = true;
4203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which sets the break flag and counts.
4209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventBreak);
4210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping.
4212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function f0() {}"
4213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function f1(x1) {}"
4214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function f2(x1,x2) {}"
4215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    "function f3(x1,x2,x3) {}";
4216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f0 = CompileFunction(&env, src, "f0");
4217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f1 = CompileFunction(&env, src, "f1");
4218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f2 = CompileFunction(&env, src, "f2");
4219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f3 = CompileFunction(&env, src, "f3");
4220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call the function to make sure it is compiled.
4222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv[] = { v8::Number::New(isolate, 1),
4223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   v8::Number::New(isolate, 1),
4224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   v8::Number::New(isolate, 1),
4225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   v8::Number::New(isolate, 1) };
4226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call all functions to make sure that they are compiled.
4228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f0->Call(env->Global(), 0, NULL);
4229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f1->Call(env->Global(), 0, NULL);
4230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f2->Call(env->Global(), 0, NULL);
4231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f3->Call(env->Global(), 0, NULL);
4232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the debug break flag.
4234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
4235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate()));
4236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call all functions with different argument count.
4238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
4239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (unsigned int i = 0; i < arraysize(argv); i++) {
4240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f0->Call(env->Global(), i, argv);
4241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f1->Call(env->Global(), i, argv);
4242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f2->Call(env->Global(), i, argv);
4243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f3->Call(env->Global(), i, argv);
4244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // One break for each function called.
4247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4 * arraysize(argv), break_point_hit_count);
4248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug event listener.
4250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
4251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
4252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test to ensure that JavaScript code keeps running while the debug break
4256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// through the stack limit flag is set but breaks are disabled.
4257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DisableBreak) {
4258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
4260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which sets the break flag and counts.
4262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventCounter);
4263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping.
4265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}";
4266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
4267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set, test and cancel debug break.
4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate()));
4271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::CancelDebugBreak(env->GetIsolate());
4272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(!v8::Debug::CheckDebugBreak(env->GetIsolate()));
4273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the debug break flag.
4275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
4276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call all functions with different argument count.
4278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
4279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
4280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
4281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
4283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Debug::DebugBreak(env->GetIsolate());
4284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
4285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::internal::DisableBreak disable_break(isolate->debug(), true);
4286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(env->Global(), 0, NULL);
4287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(1, break_point_hit_count);
4288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
4291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
4292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug event listener.
4294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
4295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
4296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic const char* kSimpleExtensionSource =
4299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  "(function Foo() {"
4300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  "  return 4;"
4301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  "})() ";
4302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4303e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// http://crbug.com/28933
4304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Test that debug break is disabled when bootstrapper is active.
4305e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeTEST(NoBreakWhenBootstrapping) {
4306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4308e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Register a debug event listener which sets the break flag and counts.
4310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::SetDebugEventListener(DebugEventCounter);
4311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Set the debug break flag.
4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(isolate);
4314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  break_point_hit_count = 0;
4315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  {
4316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Create a context with an extension to make sure that some JavaScript
4317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // code is executed during bootstrapping.
4318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    v8::RegisterExtension(new v8::Extension("simpletest",
4319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                            kSimpleExtensionSource));
4320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    const char* extension_names[] = { "simpletest" };
4321e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    v8::ExtensionConfiguration extensions(1, extension_names);
4322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope handle_scope(isolate);
4323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::New(isolate, &extensions);
4324e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
4325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check that no DebugBreak events occured during the context creation.
4326e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_EQ(0, break_point_hit_count);
4327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
4328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Get rid of the debug event listener.
4329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::SetDebugEventListener(NULL);
4330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CheckDebuggerUnloaded();
4331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
4332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(info.GetIsolate(), 0),
4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::String::NewFromUtf8(info.GetIsolate(), "a"));
4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(info.GetIsolate(), 1),
4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::String::NewFromUtf8(info.GetIsolate(), "b"));
4340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(info.GetIsolate(), 2),
4341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              v8::String::NewFromUtf8(info.GetIsolate(), "c"));
4342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(result);
4343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
4347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = info.GetIsolate();
4348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Array> result = v8::Array::New(isolate, 2);
4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(isolate, 0), v8::Number::New(isolate, 1));
4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->Set(v8::Integer::New(isolate, 1), v8::Number::New(isolate, 10));
4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(result);
4352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NamedGetter(v8::Local<v8::String> name,
4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        const v8::PropertyCallbackInfo<v8::Value>& info) {
4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value n(name);
4358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (strcmp(*n, "a") == 0) {
4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "AA"));
4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
4361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (strcmp(*n, "b") == 0) {
4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "BB"));
4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
4364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (strcmp(*n, "c") == 0) {
4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "CC"));
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
4367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info.GetReturnValue().SetUndefined();
4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
4370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(name);
4372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void IndexedGetter(uint32_t index,
4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const v8::PropertyCallbackInfo<v8::Value>& info) {
4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(static_cast<double>(index + 1));
4378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(InterceptorPropertyMirror) {
4382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a V8 environment with debug access.
4383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
4387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create object with named interceptor.
4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
4390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  named->SetNamedPropertyHandler(NamedGetter, NULL, NULL, NULL, NamedEnum);
4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(
4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "intercepted_named"),
4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      named->NewInstance());
4394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create object with indexed interceptor.
4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> indexed = v8::ObjectTemplate::New(isolate);
4397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  indexed->SetIndexedPropertyHandler(IndexedGetter,
4398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     NULL,
4399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     NULL,
4400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     NULL,
4401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     IndexedEnum);
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "intercepted_indexed"),
4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      indexed->NewInstance());
4405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create object with both named and indexed interceptor.
4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> both = v8::ObjectTemplate::New(isolate);
4408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  both->SetNamedPropertyHandler(NamedGetter, NULL, NULL, NULL, NamedEnum);
4409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  both->SetIndexedPropertyHandler(IndexedGetter, NULL, NULL, NULL, IndexedEnum);
4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(
4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "intercepted_both"),
4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      both->NewInstance());
4413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get mirrors for the three objects with interceptor.
4415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var named_mirror = debug.MakeMirror(intercepted_named);"
44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var indexed_mirror = debug.MakeMirror(intercepted_indexed);"
44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var both_mirror = debug.MakeMirror(intercepted_both)");
4419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(
4420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       "named_mirror instanceof debug.ObjectMirror")->BooleanValue());
4421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(
4422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "indexed_mirror instanceof debug.ObjectMirror")->BooleanValue());
4423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(
4424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        "both_mirror instanceof debug.ObjectMirror")->BooleanValue());
4425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the property names from the interceptors
4427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
4428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "named_names = named_mirror.propertyNames();"
4429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "indexed_names = indexed_mirror.propertyNames();"
4430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "both_names = both_mirror.propertyNames()");
4431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, CompileRun("named_names.length")->Int32Value());
4432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, CompileRun("indexed_names.length")->Int32Value());
4433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, CompileRun("both_names.length")->Int32Value());
4434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the expected number of properties.
4436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source;
4437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "named_mirror.properties().length";
4438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, CompileRun(source)->Int32Value());
4439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "indexed_mirror.properties().length";
4441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, CompileRun(source)->Int32Value());
4442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "both_mirror.properties().length";
4444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, CompileRun(source)->Int32Value());
4445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1 is PropertyKind.Named;
4447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "both_mirror.properties(1).length";
4448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, CompileRun(source)->Int32Value());
4449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 2 is PropertyKind.Indexed;
4451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "both_mirror.properties(2).length";
4452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, CompileRun(source)->Int32Value());
4453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 3 is PropertyKind.Named  | PropertyKind.Indexed;
4455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "both_mirror.properties(3).length";
4456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5, CompileRun(source)->Int32Value());
4457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the interceptor properties for the object with only named interceptor.
44593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var named_values = named_mirror.properties()");
4460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the properties are interceptor properties.
4462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 3; i++) {
4463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
4464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SNPrintF(buffer,
4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "named_values[%d] instanceof debug.PropertyMirror", i);
4466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(CompileRun(buffer.start())->BooleanValue());
4467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SNPrintF(buffer, "named_values[%d].isNative()", i);
4469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(CompileRun(buffer.start())->BooleanValue());
4470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the interceptor properties for the object with only indexed
4473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // interceptor.
44743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var indexed_values = indexed_mirror.properties()");
4475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the properties are interceptor properties.
4477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 2; i++) {
4478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SNPrintF(buffer,
4480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "indexed_values[%d] instanceof debug.PropertyMirror", i);
4481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(CompileRun(buffer.start())->BooleanValue());
4482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the interceptor properties for the object with both types of
4485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // interceptors.
44863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var both_values = both_mirror.properties()");
4487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the properties are interceptor properties.
4489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 5; i++) {
4490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
4491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SNPrintF(buffer, "both_values[%d] instanceof debug.PropertyMirror", i);
4492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK(CompileRun(buffer.start())->BooleanValue());
4493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check the property names.
4496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "both_values[0].name() == 'a'";
4497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(source)->BooleanValue());
4498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "both_values[1].name() == 'b'";
4500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(source)->BooleanValue());
4501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "both_values[2].name() == 'c'";
4503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(source)->BooleanValue());
4504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "both_values[3].name() == 1";
4506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(source)->BooleanValue());
4507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  source = "both_values[4].name() == 10";
4509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(source)->BooleanValue());
4510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(HiddenPrototypePropertyMirror) {
4514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a V8 environment with debug access.
4515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
4519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t0->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "x"),
4522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::Number::New(isolate, 0));
4523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
4524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t1->SetHiddenPrototype(true);
4525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t1->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "y"),
4526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::Number::New(isolate, 1));
4527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
4528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t2->SetHiddenPrototype(true);
4529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t2->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "z"),
4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::Number::New(isolate, 2));
4531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
4532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t3->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "u"),
4533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::Number::New(isolate, 3));
4534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create object and set them on the global object.
4536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> o0 = t0->GetFunction()->NewInstance();
4537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8::String::NewFromUtf8(isolate, "o0"), o0);
4538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> o1 = t1->GetFunction()->NewInstance();
4539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8::String::NewFromUtf8(isolate, "o1"), o1);
4540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> o2 = t2->GetFunction()->NewInstance();
4541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8::String::NewFromUtf8(isolate, "o2"), o2);
4542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Object> o3 = t3->GetFunction()->NewInstance();
4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8::String::NewFromUtf8(isolate, "o3"), o3);
4544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get mirrors for the four objects.
4546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
45473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var o0_mirror = debug.MakeMirror(o0);"
45483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var o1_mirror = debug.MakeMirror(o1);"
45493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var o2_mirror = debug.MakeMirror(o2);"
45503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var o3_mirror = debug.MakeMirror(o3)");
4551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("o0_mirror instanceof debug.ObjectMirror")->BooleanValue());
4552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("o1_mirror instanceof debug.ObjectMirror")->BooleanValue());
4553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("o2_mirror instanceof debug.ObjectMirror")->BooleanValue());
4554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("o3_mirror instanceof debug.ObjectMirror")->BooleanValue());
4555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that each object has one property.
4557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun(
4558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.propertyNames().length")->Int32Value());
4559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun(
4560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o1_mirror.propertyNames().length")->Int32Value());
4561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun(
4562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o2_mirror.propertyNames().length")->Int32Value());
4563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun(
4564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o3_mirror.propertyNames().length")->Int32Value());
4565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set o1 as prototype for o0. o1 has the hidden prototype flag so all
4567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // properties on o1 should be seen on o0.
4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o0->Set(v8::String::NewFromUtf8(isolate, "__proto__"), o1);
4569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, CompileRun(
4570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.propertyNames().length")->Int32Value());
4571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, CompileRun(
4572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.property('x').value().value()")->Int32Value());
4573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun(
4574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.property('y').value().value()")->Int32Value());
4575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set o2 as prototype for o0 (it will end up after o1 as o1 has the hidden
4577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype flag. o2 also has the hidden prototype flag so all properties
4578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on o2 should be seen on o0 as well as properties on o1.
4579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o0->Set(v8::String::NewFromUtf8(isolate, "__proto__"), o2);
4580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, CompileRun(
4581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.propertyNames().length")->Int32Value());
4582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, CompileRun(
4583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.property('x').value().value()")->Int32Value());
4584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun(
4585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.property('y').value().value()")->Int32Value());
4586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, CompileRun(
4587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.property('z').value().value()")->Int32Value());
4588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set o3 as prototype for o0 (it will end up after o1 and o2 as both o1 and
4590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // o2 has the hidden prototype flag. o3 does not have the hidden prototype
4591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // flag so properties on o3 should not be seen on o0 whereas the properties
4592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // from o1 and o2 should still be seen on o0.
4593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Final prototype chain: o0 -> o1 -> o2 -> o3
4594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Hidden prototypes:           ^^    ^^
4595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  o0->Set(v8::String::NewFromUtf8(isolate, "__proto__"), o3);
4596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, CompileRun(
4597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.propertyNames().length")->Int32Value());
4598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun(
4599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o3_mirror.propertyNames().length")->Int32Value());
4600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, CompileRun(
4601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.property('x').value().value()")->Int32Value());
4602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun(
4603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.property('y').value().value()")->Int32Value());
4604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, CompileRun(
4605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "o0_mirror.property('z').value().value()")->Int32Value());
4606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("o0_mirror.property('u').isUndefined()")->BooleanValue());
4607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The prototype (__proto__) for o0 should be o3 as o1 and o2 are hidden.
4609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("o0_mirror.protoObject() == o3_mirror")->BooleanValue());
4610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ProtperyXNativeGetter(
4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::String> property,
4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(10);
4617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(NativeGetterPropertyMirror) {
4621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a V8 environment with debug access.
4622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
4626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> name = v8::String::NewFromUtf8(isolate, "x");
4628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create object with named accessor.
4629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
4630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  named->SetAccessor(name, &ProtperyXNativeGetter, NULL,
4631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value>(), v8::DEFAULT, v8::None);
4632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create object with named property getter.
4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8::String::NewFromUtf8(isolate, "instance"),
4635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     named->NewInstance());
4636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(10, CompileRun("instance.x")->Int32Value());
4637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get mirror for the object with property getter.
46393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var instance_mirror = debug.MakeMirror(instance);");
4640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(
4641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "instance_mirror instanceof debug.ObjectMirror")->BooleanValue());
4642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var named_names = instance_mirror.propertyNames();");
4644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
4645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue());
4646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(
4647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "instance_mirror.property('x').value().isNumber()")->BooleanValue());
4648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(
4649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "instance_mirror.property('x').value().value() == 10")->BooleanValue());
4650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ProtperyXNativeGetterThrowingError(
4654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::String> property,
4655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("throw new Error('Error message');");
4657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(NativeGetterThrowingErrorPropertyMirror) {
4661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a V8 environment with debug access.
4662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
4666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> name = v8::String::NewFromUtf8(isolate, "x");
4668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create object with named accessor.
4669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
4670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  named->SetAccessor(name, &ProtperyXNativeGetterThrowingError, NULL,
4671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value>(), v8::DEFAULT, v8::None);
4672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create object with named property getter.
4674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8::String::NewFromUtf8(isolate, "instance"),
4675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     named->NewInstance());
4676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get mirror for the object with property getter.
46783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var instance_mirror = debug.MakeMirror(instance);");
4679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(
4680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "instance_mirror instanceof debug.ObjectMirror")->BooleanValue());
4681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("named_names = instance_mirror.propertyNames();");
4682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
4683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue());
4684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(
4685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "instance_mirror.property('x').value().isError()")->BooleanValue());
4686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the message is that passed to the Error constructor.
4688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(CompileRun(
4689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "instance_mirror.property('x').value().message() == 'Error message'")->
4690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          BooleanValue());
4691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Test that hidden properties object is not returned as an unnamed property
4695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// among regular properties.
4696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// See http://crbug.com/26491
4697d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockTEST(NoHiddenProperties) {
4698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create a V8 environment with debug access.
4699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  DebugLocalContext env;
4700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
4701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
4702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  env.ExposeDebug();
4703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create an object in the global scope.
4705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* source = "var obj = {a: 1};";
4706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate, source))
4707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
4708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
4709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(isolate, "obj")));
4710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set a hidden property on the object.
4711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->SetHiddenValue(
4712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "v8::test-debug::a"),
4713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Int32::New(isolate, 11));
4714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Get mirror for the object with property getter.
4716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CompileRun("var obj_mirror = debug.MakeMirror(obj);");
4717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(CompileRun(
4718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
4719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CompileRun("var named_names = obj_mirror.propertyNames();");
4720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // There should be exactly one property. But there is also an unnamed
4721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // property whose value is hidden properties dictionary. The latter
4722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // property should not be in the list of reguar properties.
4723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
4724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(CompileRun("named_names[0] == 'a'")->BooleanValue());
4725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(CompileRun(
4726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "obj_mirror.property('a').value().value() == 1")->BooleanValue());
4727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Object created by t0 will become hidden prototype of object 'obj'.
4729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
4730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t0->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "b"),
4731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::Number::New(isolate, 2));
4732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  t0->SetHiddenPrototype(true);
4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
4734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t1->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "c"),
4735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              v8::Number::New(isolate, 3));
4736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create proto objects, add hidden properties to them and set them on
4738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // the global object.
4739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Handle<v8::Object> protoObj = t0->GetFunction()->NewInstance();
4740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  protoObj->SetHiddenValue(
4741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "v8::test-debug::b"),
4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Int32::New(isolate, 12));
4743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8::String::NewFromUtf8(isolate, "protoObj"),
4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     protoObj);
4745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Handle<v8::Object> grandProtoObj = t1->GetFunction()->NewInstance();
4746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  grandProtoObj->SetHiddenValue(
4747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "v8::test-debug::c"),
4748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Int32::New(isolate, 13));
4749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(
4750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "grandProtoObj"),
4751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      grandProtoObj);
4752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Setting prototypes: obj->protoObj->grandProtoObj
4754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  protoObj->Set(v8::String::NewFromUtf8(isolate, "__proto__"),
4755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                grandProtoObj);
4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->Set(v8::String::NewFromUtf8(isolate, "__proto__"), protoObj);
4757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Get mirror for the object with property getter.
4759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CompileRun("var obj_mirror = debug.MakeMirror(obj);");
4760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(CompileRun(
4761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
4762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CompileRun("var named_names = obj_mirror.propertyNames();");
4763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // There should be exactly two properties - one from the object itself and
4764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // another from its hidden prototype.
4765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(2, CompileRun("named_names.length")->Int32Value());
4766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(CompileRun("named_names.sort(); named_names[0] == 'a' &&"
4767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                   "named_names[1] == 'b'")->BooleanValue());
4768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(CompileRun(
4769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "obj_mirror.property('a').value().value() == 1")->BooleanValue());
4770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(CompileRun(
4771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "obj_mirror.property('b').value().value() == 2")->BooleanValue());
4772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
4773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
4774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Multithreaded tests of JSON debugger protocol
4776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Support classes
4778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Provides synchronization between N threads, where N is a template parameter.
4780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The Wait() call blocks a thread until it is called for the Nth time, then all
4781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// calls return.  Each ThreadBarrier object can only be used once.
4782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <int N>
4783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ThreadBarrier FINAL {
4784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
4785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ThreadBarrier() : num_blocked_(0) {}
4786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~ThreadBarrier() {
4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LockGuard<Mutex> lock_guard(&mutex_);
4789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (num_blocked_ != 0) {
4790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(N, num_blocked_);
4791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Wait() {
4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LockGuard<Mutex> lock_guard(&mutex_);
4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_LT(num_blocked_, N);
4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    num_blocked_++;
4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (N == num_blocked_) {
4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Signal and unblock all waiting threads.
4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cv_.NotifyAll();
4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      printf("BARRIER\n\n");
4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fflush(stdout);
4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {  // Wait for the semaphore.
4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      while (num_blocked_ < N) {
4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        cv_.Wait(&mutex_);
4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(N, num_blocked_);
4809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
4812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ConditionVariable cv_;
4813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Mutex mutex_;
4814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int num_blocked_;
4815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(N > 0);
4817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ThreadBarrier);
4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
4820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A set containing enough barriers and semaphores for any of the tests.
4823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Barriers {
4824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
4825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Barriers() : semaphore_1(0), semaphore_2(0) {}
4826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ThreadBarrier<2> barrier_1;
4827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ThreadBarrier<2> barrier_2;
4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ThreadBarrier<2> barrier_3;
4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ThreadBarrier<2> barrier_4;
4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ThreadBarrier<2> barrier_5;
4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::Semaphore semaphore_1;
4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::Semaphore semaphore_2;
4833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
4834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We match parts of the message to decide if it is a break message.
4837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool IsBreakEventMessage(char *message) {
4838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* type_event = "\"type\":\"event\"";
4839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* event_break = "\"event\":\"break\"";
4840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Does the message contain both type:event and event:break?
4841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return strstr(message, type_event) != NULL &&
4842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         strstr(message, event_break) != NULL;
4843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// We match parts of the message to decide if it is a exception message.
48473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockbool IsExceptionEventMessage(char *message) {
48483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* type_event = "\"type\":\"event\"";
48493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* event_exception = "\"event\":\"exception\"";
48503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Does the message contain both type:event and event:exception?
48513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return strstr(message, type_event) != NULL &&
48523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      strstr(message, event_exception) != NULL;
48533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
48543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
48553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
48563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// We match the message wether it is an evaluate response message.
48573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockbool IsEvaluateResponseMessage(char* message) {
48583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* type_response = "\"type\":\"response\"";
48593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* command_evaluate = "\"command\":\"evaluate\"";
48603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Does the message contain both type:response and command:evaluate?
48613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return strstr(message, type_response) != NULL &&
48623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block         strstr(message, command_evaluate) != NULL;
48633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
48643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
48653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4866402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic int StringToInt(const char* s) {
4867402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return atoi(s);  // NOLINT
4868402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
4869402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
4870402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
48713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// We match parts of the message to get evaluate result int value.
48723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint GetEvaluateIntResult(char *message) {
48733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* value = "\"value\":";
48743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  char* pos = strstr(message, value);
48753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (pos == NULL) {
48763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return -1;
48773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
48783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int res = -1;
4879402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  res = StringToInt(pos + strlen(value));
48803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return res;
48813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
48823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
48833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
48843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// We match parts of the message to get hit breakpoint id.
48853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint GetBreakpointIdFromBreakEventMessage(char *message) {
48863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* breakpoints = "\"breakpoints\":[";
48873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  char* pos = strstr(message, breakpoints);
48883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (pos == NULL) {
48893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    return -1;
48903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
48913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int res = -1;
4892402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  res = StringToInt(pos + strlen(breakpoints));
48933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return res;
48943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
48953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
48963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
4897d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// We match parts of the message to get total frames number.
4898d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeint GetTotalFramesInt(char *message) {
4899d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const char* prefix = "\"totalFrames\":";
4900d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  char* pos = strstr(message, prefix);
4901d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (pos == NULL) {
4902d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return -1;
4903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
4904d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  pos += strlen(prefix);
4905402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  int res = StringToInt(pos);
4906d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return res;
4907d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
4908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
49109ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick// We match parts of the message to get source line.
49119ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrickint GetSourceLineFromBreakEventMessage(char *message) {
49129ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  const char* source_line = "\"sourceLine\":";
49139ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  char* pos = strstr(message, source_line);
49149ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  if (pos == NULL) {
49159ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    return -1;
49169ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  }
49179ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  int res = -1;
49189ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  res = StringToInt(pos + strlen(source_line));
49199ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  return res;
49209ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick}
49219ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Test MessageQueues */
4924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Tests the message queues that hold debugger commands and
4925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * response messages to the debugger.  Fills queues and makes
4926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * them grow.
4927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
4928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBarriers message_queue_barriers;
4929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This is the debugger thread, that executes no v8 calls except
4931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// placing JSON debugger commands in the queue.
4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MessageQueueDebuggerThread : public v8::base::Thread {
4933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
49343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  MessageQueueDebuggerThread()
4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Thread(Options("MessageQueueDebuggerThread")) {}
4936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Run();
4937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
4938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void MessageHandler(const v8::Debug::Message& message) {
4941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> json = message.GetJSON();
4942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value utf8(json);
4943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsBreakEventMessage(*utf8)) {
4944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Lets test script wait until break occurs to send commands.
4945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Signals when a break is reported.
4946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    message_queue_barriers.semaphore_2.Signal();
4947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allow message handler to block on a semaphore, to test queueing of
4950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // messages while blocked.
4951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_queue_barriers.semaphore_1.Wait();
4952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid MessageQueueDebuggerThread::Run() {
4956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kBufferSize = 1000;
4957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t buffer_1[kBufferSize];
4958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t buffer_2[kBufferSize];
4959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_1 =
4960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "{\"seq\":117,"
4961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       "\"type\":\"request\","
4962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       "\"command\":\"evaluate\","
4963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       "\"arguments\":{\"expression\":\"1+2\"}}";
4964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_2 =
4965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "{\"seq\":118,"
4966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"type\":\"request\","
4967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"command\":\"evaluate\","
4968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"arguments\":{\"expression\":\"1+a\"}}";
4969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_3 =
4970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "{\"seq\":119,"
4971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"type\":\"request\","
4972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"command\":\"evaluate\","
4973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"arguments\":{\"expression\":\"c.d * b\"}}";
4974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_continue =
4975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "{\"seq\":106,"
4976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"type\":\"request\","
4977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"command\":\"continue\"}";
4978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_single_step =
4979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "{\"seq\":107,"
4980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"type\":\"request\","
4981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"command\":\"continue\","
4982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"arguments\":{\"stepaction\":\"next\"}}";
4983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /* Interleaved sequence of actions by the two threads:*/
4985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Main thread compiles and runs source_1
4986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_queue_barriers.semaphore_1.Signal();
4987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_queue_barriers.barrier_1.Wait();
4988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Post 6 commands, filling the command queue and making it expand.
4989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // These calls return immediately, but the commands stay on the queue
4990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // until the execution of source_2.
4991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: AsciiToUtf16 executes before SendCommand, so command is copied
4992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to buffer before buffer is sent to SendCommand.
4993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
4994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
4996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_queue_barriers.barrier_2.Wait();
5000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Main thread compiles and runs source_2.
5001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Queued commands are executed at the start of compilation of source_2(
5002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // beforeCompile event).
5003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Free the message handler to process all the messages from the queue. 7
5004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // messages are expected: 2 afterCompile events and 5 responses.
5005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All the commands added so far will fail to execute as long as call stack
5006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is empty on beforeCompile event.
5007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 6 ; ++i) {
5008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    message_queue_barriers.semaphore_1.Signal();
5009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_queue_barriers.barrier_3.Wait();
5011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Main thread compiles and runs source_3.
5012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Don't stop in the afterCompile handler.
5013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_queue_barriers.semaphore_1.Signal();
5014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // source_3 includes a debugger statement, which causes a break event.
5015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Wait on break event from hitting "debugger" statement
5016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_queue_barriers.semaphore_2.Wait();
5017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // These should execute after the "debugger" statement in source_2
5018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
5019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
5020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
5021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
5022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, buffer_2, AsciiToUtf16(command_single_step, buffer_2));
5023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run after 2 break events, 4 responses.
5024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 6 ; ++i) {
5025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    message_queue_barriers.semaphore_1.Signal();
5026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Wait on break event after a single step executes.
5028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  message_queue_barriers.semaphore_2.Wait();
5029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_2, buffer_1));
5030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
5031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, buffer_2, AsciiToUtf16(command_continue, buffer_2));
5032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run after 2 responses.
5033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 2 ; ++i) {
5034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    message_queue_barriers.semaphore_1.Signal();
5035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Main thread continues running source_3 to end, waits for this thread.
5037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This thread runs the v8 engine.
5041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MessageQueues) {
50423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  MessageQueueDebuggerThread message_queue_debugger_thread;
504344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a V8 environment
5045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
5046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
5047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetMessageHandler(MessageHandler);
5048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_queue_debugger_thread.Start();
5049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
5051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source_2 = "e = 17;";
5052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source_3 = "a = 4; debugger; a = 5; a = 6; a = 7;";
5053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // See MessageQueueDebuggerThread::Run for interleaved sequence of
5055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // API calls and events in the two threads.
5056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(source_1);
5057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_queue_barriers.barrier_1.Wait();
5058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_queue_barriers.barrier_2.Wait();
5059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(source_2);
5060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_queue_barriers.barrier_3.Wait();
5061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(source_3);
5062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_queue_debugger_thread.Join();
5063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  fflush(stdout);
5064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass TestClientData : public v8::Debug::ClientData {
5068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
5069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestClientData() {
5070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    constructor_call_counter++;
5071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~TestClientData() {
5073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    destructor_call_counter++;
5074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void ResetCounters() {
5077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    constructor_call_counter = 0;
5078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    destructor_call_counter = 0;
5079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static int constructor_call_counter;
5082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static int destructor_call_counter;
5083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
5084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint TestClientData::constructor_call_counter = 0;
5086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint TestClientData::destructor_call_counter = 0;
5087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests that MessageQueue doesn't destroy client data when expands and
5090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// does destroy when it dies.
5091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MessageQueueExpandAndDestroy) {
5092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestClientData::ResetCounters();
5093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { // Create a scope for the queue.
5094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CommandMessageQueue queue(1);
5095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  new TestClientData()));
5097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  new TestClientData()));
5099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  new TestClientData()));
5101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(0, TestClientData::destructor_call_counter);
5102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Get().Dispose();
5103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(1, TestClientData::destructor_call_counter);
5104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  new TestClientData()));
5106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  new TestClientData()));
5108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  new TestClientData()));
5110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  new TestClientData()));
5112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  new TestClientData()));
5114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(1, TestClientData::destructor_call_counter);
5115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    queue.Get().Dispose();
5116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(2, TestClientData::destructor_call_counter);
5117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All the client data should be destroyed when the queue is destroyed.
5119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(TestClientData::destructor_call_counter,
5120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           TestClientData::destructor_call_counter);
5121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int handled_client_data_instances_count = 0;
5125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void MessageHandlerCountingClientData(
5126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const v8::Debug::Message& message) {
5127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (message.GetClientData() != NULL) {
5128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    handled_client_data_instances_count++;
5129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests that all client data passed to the debugger are sent to the handler.
5134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(SendClientDataToHandler) {
5135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a V8 environment
5136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
5137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
5138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestClientData::ResetCounters();
5140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  handled_client_data_instances_count = 0;
5141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(MessageHandlerCountingClientData);
5142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
5143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kBufferSize = 1000;
5144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t buffer[kBufferSize];
5145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_1 =
5146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "{\"seq\":117,"
5147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       "\"type\":\"request\","
5148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       "\"command\":\"evaluate\","
5149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       "\"arguments\":{\"expression\":\"1+2\"}}";
5150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_2 =
5151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "{\"seq\":118,"
5152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"type\":\"request\","
5153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"command\":\"evaluate\","
5154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"arguments\":{\"expression\":\"1+a\"}}";
5155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_continue =
5156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "{\"seq\":106,"
5157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"type\":\"request\","
5158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"command\":\"continue\"}";
5159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer),
5161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         new TestClientData());
5162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
5163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, buffer, AsciiToUtf16(command_2, buffer), NULL);
5164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
5165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         new TestClientData());
5166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
5167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         new TestClientData());
5168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All the messages will be processed on beforeCompile event.
5169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(source_1);
5170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
5171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, buffer, AsciiToUtf16(command_continue, buffer));
5172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, TestClientData::constructor_call_counter);
5173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(TestClientData::constructor_call_counter,
5174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           handled_client_data_instances_count);
5175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(TestClientData::constructor_call_counter,
5176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           TestClientData::destructor_call_counter);
5177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Test ThreadedDebugging */
5181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* This test interrupts a running infinite loop that is
5182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * occupying the v8 thread by a break command from the
5183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * debugger thread.  It then changes the value of a
5184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * global object, to make the loop terminate.
5185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
5186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBarriers threaded_debugging_barriers;
5188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass V8Thread : public v8::base::Thread {
5190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
5191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V8Thread() : Thread(Options("V8Thread")) {}
5192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Run();
5193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate() { return isolate_; }
5194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
5196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate_;
5197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
5198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass DebuggerThread : public v8::base::Thread {
5200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
5201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit DebuggerThread(v8::Isolate* isolate)
5202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Thread(Options("DebuggerThread")), isolate_(isolate) {}
5203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Run();
5204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
5206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate_;
5207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
5208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ThreadedAtBarrier1(
5211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
5212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  threaded_debugging_barriers.barrier_1.Wait();
5213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ThreadedMessageHandler(const v8::Debug::Message& message) {
5217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static char print_buffer[1000];
5218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::String::Value json(message.GetJSON());
5219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Utf16ToAscii(*json, json.length(), print_buffer);
5220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IsBreakEventMessage(print_buffer)) {
52219ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Check that we are inside the while loop.
52229ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    int source_line = GetSourceLineFromBreakEventMessage(print_buffer);
52239ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    CHECK(8 <= source_line && source_line <= 13);
5224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    threaded_debugging_barriers.barrier_2.Wait();
5225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid V8Thread::Run() {
5230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source =
5231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "flag = true;\n"
5232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function bar( new_value ) {\n"
5233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  flag = new_value;\n"
5234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  return \"Return from bar(\" + new_value + \")\";\n"
5235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "}\n"
5236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\n"
5237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "function foo() {\n"
5238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  var x = 1;\n"
5239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  while ( flag == true ) {\n"
5240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    if ( x == 1 ) {\n"
5241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "      ThreadedAtBarrier1();\n"
5242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    }\n"
5243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "    x = x + 1;\n"
5244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  }\n"
5245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "}\n"
5246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\n"
5247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "foo();\n";
5248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_ = v8::Isolate::New();
5250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  threaded_debugging_barriers.barrier_3.Wait();
5251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
5252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate::Scope isolate_scope(isolate_);
5253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DebugLocalContext env(isolate_);
5254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate_);
5255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Debug::SetMessageHandler(&ThreadedMessageHandler);
5256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::ObjectTemplate> global_template =
5257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::ObjectTemplate::New(env->GetIsolate());
5258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    global_template->Set(
5259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::String::NewFromUtf8(env->GetIsolate(), "ThreadedAtBarrier1"),
5260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::FunctionTemplate::New(isolate_, ThreadedAtBarrier1));
5261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Context> context =
5262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Context::New(isolate_, NULL, global_template);
5263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Context::Scope context_scope(context);
5264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun(source);
5266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->Dispose();
5268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerThread::Run() {
5272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kBufSize = 1000;
5273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t buffer[kBufSize];
5274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_1 = "{\"seq\":102,"
5276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"type\":\"request\","
5277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"command\":\"evaluate\","
5278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"arguments\":{\"expression\":\"bar(false)\"}}";
5279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_2 = "{\"seq\":103,"
5280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"type\":\"request\","
5281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"command\":\"continue\"}";
5282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  threaded_debugging_barriers.barrier_1.Wait();
5284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(isolate_);
5285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  threaded_debugging_barriers.barrier_2.Wait();
5286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer));
5287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer));
5288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ThreadedDebugging) {
52923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  V8Thread v8_thread;
529344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a V8 environment
5295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8_thread.Start();
5296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  threaded_debugging_barriers.barrier_3.Wait();
5297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebuggerThread debugger_thread(v8_thread.isolate());
5298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  debugger_thread.Start();
5299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8_thread.Join();
5301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  debugger_thread.Join();
5302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Test RecursiveBreakpoints */
5306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* In this test, the debugger evaluates a function with a breakpoint, after
5307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * hitting a breakpoint in another function.  We do this with both values
5308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * of the flag enabling recursive breakpoints, and verify that the second
5309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * breakpoint is hit when enabled, and missed when disabled.
5310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
5311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass BreakpointsV8Thread : public v8::base::Thread {
5313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
5314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BreakpointsV8Thread() : Thread(Options("BreakpointsV8Thread")) {}
5315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Run();
5316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate() { return isolate_; }
5318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
5320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate_;
5321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
5322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass BreakpointsDebuggerThread : public v8::base::Thread {
5324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
5325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BreakpointsDebuggerThread(bool global_evaluate, v8::Isolate* isolate)
5326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Thread(Options("BreakpointsDebuggerThread")),
5327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        global_evaluate_(global_evaluate),
5328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_(isolate) {}
5329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Run();
5330d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
5331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
5332d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  bool global_evaluate_;
5333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate_;
5334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
5335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBarriers* breakpoints_barriers;
53383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint break_event_breakpoint_id;
53393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint evaluate_int_result;
5340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void BreakpointsMessageHandler(const v8::Debug::Message& message) {
5342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static char print_buffer[1000];
5343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::String::Value json(message.GetJSON());
5344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Utf16ToAscii(*json, json.length(), print_buffer);
5345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IsBreakEventMessage(print_buffer)) {
53473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    break_event_breakpoint_id =
53483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        GetBreakpointIdFromBreakEventMessage(print_buffer);
5349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    breakpoints_barriers->semaphore_1.Signal();
53503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (IsEvaluateResponseMessage(print_buffer)) {
53513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    evaluate_int_result = GetEvaluateIntResult(print_buffer);
5352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    breakpoints_barriers->semaphore_1.Signal();
5353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid BreakpointsV8Thread::Run() {
5358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source_1 = "var y_global = 3;\n"
5359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function cat( new_value ) {\n"
5360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  var x = new_value;\n"
53613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    "  y_global = y_global + 4;\n"
5362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  x = 3 * x + 1;\n"
53633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    "  y_global = y_global + 5;\n"
5364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return x;\n"
5365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}\n"
5366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "\n"
5367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function dog() {\n"
5368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  var x = 1;\n"
5369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  x = y_global;"
5370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  var z = 3;"
5371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  x += 100;\n"
5372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return x;\n"
5373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}\n"
5374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "\n";
5375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source_2 = "cat(17);\n"
5376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "cat(19);\n";
5377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_ = v8::Isolate::New();
5379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  breakpoints_barriers->barrier_3.Wait();
5380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
5381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Isolate::Scope isolate_scope(isolate_);
5382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DebugLocalContext env(isolate_);
5383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(isolate_);
5384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Debug::SetMessageHandler(&BreakpointsMessageHandler);
5385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun(source_1);
5387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    breakpoints_barriers->barrier_1.Wait();
5388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    breakpoints_barriers->barrier_2.Wait();
5389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun(source_2);
5390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->Dispose();
5392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid BreakpointsDebuggerThread::Run() {
5396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kBufSize = 1000;
5397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t buffer[kBufSize];
5398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_1 = "{\"seq\":101,"
5400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"type\":\"request\","
5401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"command\":\"setbreakpoint\","
5402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
5403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_2 = "{\"seq\":102,"
5404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"type\":\"request\","
5405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"command\":\"setbreakpoint\","
5406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"arguments\":{\"type\":\"function\",\"target\":\"dog\",\"line\":3}}";
5407d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const char* command_3;
5408d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (this->global_evaluate_) {
5409d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    command_3 = "{\"seq\":103,"
5410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"type\":\"request\","
5411d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"command\":\"evaluate\","
5412d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false,"
5413d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"global\":true}}";
5414d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else {
5415d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    command_3 = "{\"seq\":103,"
5416d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"type\":\"request\","
5417d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"command\":\"evaluate\","
5418d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false}}";
5419d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
5420d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const char* command_4;
5421d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (this->global_evaluate_) {
5422d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    command_4 = "{\"seq\":104,"
5423d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"type\":\"request\","
5424d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"command\":\"evaluate\","
5425d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"arguments\":{\"expression\":\"100 + 8\",\"disable_break\":true,"
5426d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"global\":true}}";
5427d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else {
5428d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    command_4 = "{\"seq\":104,"
5429d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"type\":\"request\","
5430d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"command\":\"evaluate\","
5431d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"arguments\":{\"expression\":\"x + 1\",\"disable_break\":true}}";
5432d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
54333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* command_5 = "{\"seq\":105,"
5434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"type\":\"request\","
5435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"command\":\"continue\"}";
54363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* command_6 = "{\"seq\":106,"
5437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"type\":\"request\","
5438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"command\":\"continue\"}";
5439d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const char* command_7;
5440d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (this->global_evaluate_) {
5441d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    command_7 = "{\"seq\":107,"
5442d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"type\":\"request\","
5443d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"command\":\"evaluate\","
5444d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true,"
5445d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"global\":true}}";
5446d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else {
5447d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    command_7 = "{\"seq\":107,"
5448d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"type\":\"request\","
5449d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"command\":\"evaluate\","
5450d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true}}";
5451d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
54523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* command_8 = "{\"seq\":108,"
5453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"type\":\"request\","
5454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "\"command\":\"continue\"}";
5455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // v8 thread initializes, runs source_1
5458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  breakpoints_barriers->barrier_1.Wait();
54593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // 1:Set breakpoint in cat() (will get id 1).
5460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer));
54613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // 2:Set breakpoint in dog() (will get id 2).
5462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer));
5463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  breakpoints_barriers->barrier_2.Wait();
54643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // V8 thread starts compiling source_2.
5465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Automatic break happens, to run queued commands
5466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // breakpoints_barriers->semaphore_1.Wait();
5467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Commands 1 through 3 run, thread continues.
5468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // v8 thread runs source_2 to breakpoint in cat().
5469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // message callback receives break event.
5470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  breakpoints_barriers->semaphore_1.Wait();
54713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Must have hit breakpoint #1.
54723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(1, break_event_breakpoint_id);
5473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 4:Evaluate dog() (which has a breakpoint).
5474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_3, buffer));
54753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // V8 thread hits breakpoint in dog().
5476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  breakpoints_barriers->semaphore_1.Wait();  // wait for break event
54773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Must have hit breakpoint #2.
54783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(2, break_event_breakpoint_id);
54793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // 5:Evaluate (x + 1).
5480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_4, buffer));
54813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Evaluate (x + 1) finishes.
5482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  breakpoints_barriers->semaphore_1.Wait();
54833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Must have result 108.
54843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(108, evaluate_int_result);
54853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // 6:Continue evaluation of dog().
5486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_5, buffer));
54873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Evaluate dog() finishes.
5488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  breakpoints_barriers->semaphore_1.Wait();
54893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Must have result 107.
54903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(107, evaluate_int_result);
5491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint
5492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in cat(19).
5493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_6, buffer));
54943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Message callback gets break event.
5495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  breakpoints_barriers->semaphore_1.Wait();  // wait for break event
54963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Must have hit breakpoint #1.
54973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(1, break_event_breakpoint_id);
54983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // 8: Evaluate dog() with breaks disabled.
5499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_7, buffer));
55003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Evaluate dog() finishes.
5501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  breakpoints_barriers->semaphore_1.Wait();
55023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Must have result 116.
55033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK_EQ(116, evaluate_int_result);
5504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 9: Continue evaluation of source2, reach end.
5505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_8, buffer));
5506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5508888f6729be6a6f6fbe246cb5a9f122e2dbe455b7Leon Clarke
5509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid TestRecursiveBreakpointsGeneric(bool global_evaluate) {
55103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BreakpointsV8Thread breakpoints_v8_thread;
5511d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
5512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a V8 environment
5513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Barriers stack_allocated_breakpoints_barriers;
5514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  breakpoints_barriers = &stack_allocated_breakpoints_barriers;
5515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  breakpoints_v8_thread.Start();
5517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  breakpoints_barriers->barrier_3.Wait();
5518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BreakpointsDebuggerThread breakpoints_debugger_thread(
5519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      global_evaluate, breakpoints_v8_thread.isolate());
5520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  breakpoints_debugger_thread.Start();
5521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  breakpoints_v8_thread.Join();
5523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  breakpoints_debugger_thread.Join();
5524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5527d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeTEST(RecursiveBreakpoints) {
5528d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  TestRecursiveBreakpointsGeneric(false);
5529d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
5530d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
5531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5532d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeTEST(RecursiveBreakpointsGlobal) {
5533d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  TestRecursiveBreakpointsGeneric(true);
5534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
5535d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
5536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DummyDebugEventListener(
5538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
5539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(SetDebugEventListenerOnUninitializedVM) {
5543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DummyDebugEventListener);
5544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void DummyMessageHandler(const v8::Debug::Message& message) {
5548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(SetMessageHandlerOnUninitializedVM) {
5552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(DummyMessageHandler);
5553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Source for a JavaScript function which returns the data parameter of a
5557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function called in the context of the debugger. If no data parameter is
5558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// passed it throws an exception.
5559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* debugger_call_with_data_source =
5560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function debugger_call_with_data(exec_state, data) {"
5561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  if (data) return data;"
5562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  throw 'No data!'"
5563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "}";
5564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Function> debugger_call_with_data;
5565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Source for a JavaScript function which returns the data parameter of a
5568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function called in the context of the debugger. If no data parameter is
5569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// passed it throws an exception.
5570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* debugger_call_with_closure_source =
5571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var x = 3;"
5572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "(function (exec_state) {"
5573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  if (exec_state.y) return x - 1;"
5574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  exec_state.y = x;"
5575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "  return exec_state.y"
5576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "})";
5577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockv8::Handle<v8::Function> debugger_call_with_closure;
5578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Function to retrieve the number of JavaScript frames by calling a JavaScript
5580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// in the debugger.
5581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckFrameCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
5582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8::Debug::Call(frame_count)->IsNumber());
5583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(args[0]->Int32Value(),
5584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           v8::Debug::Call(frame_count)->Int32Value());
5585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Function to retrieve the source line of the top JavaScript frame by calling a
5589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// JavaScript function in the debugger.
5590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckSourceLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
5591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8::Debug::Call(frame_source_line)->IsNumber());
5592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(args[0]->Int32Value(),
5593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           v8::Debug::Call(frame_source_line)->Int32Value());
5594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Function to test passing an additional parameter to a JavaScript function
5598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// called in the debugger. It also tests that functions called in the debugger
5599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// can throw exceptions.
5600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckDataParameter(
5601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& args) {
5602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> data =
5603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(args.GetIsolate(), "Test");
5604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8::Debug::Call(debugger_call_with_data, data)->IsString());
5605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 3; i++) {
5607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::TryCatch catcher;
5608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty());
5609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(catcher.HasCaught());
5610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(catcher.Exception()->IsString());
5611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Function to test using a JavaScript with closure in the debugger.
5616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckClosure(const v8::FunctionCallbackInfo<v8::Value>& args) {
5617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(v8::Debug::Call(debugger_call_with_closure)->IsNumber());
5618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, v8::Debug::Call(debugger_call_with_closure)->Int32Value());
5619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test functions called through the debugger.
5623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(CallFunctionInDebugger) {
5624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create and enter a context with the functions CheckFrameCount,
5625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // CheckSourceLine and CheckDataParameter installed.
5626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
5627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
5628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> global_template =
5629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ObjectTemplate::New(isolate);
5630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_template->Set(
5631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "CheckFrameCount"),
5632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, CheckFrameCount));
5633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_template->Set(
5634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "CheckSourceLine"),
5635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, CheckSourceLine));
5636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_template->Set(
5637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "CheckDataParameter"),
5638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, CheckDataParameter));
5639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  global_template->Set(
5640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "CheckClosure"),
5641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, CheckClosure));
5642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Context> context = v8::Context::New(isolate,
5643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     NULL,
5644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     global_template);
5645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Context::Scope context_scope(context);
5646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile a function for checking the number of JavaScript frames.
5648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
5649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, frame_count_source))->Run();
5650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  frame_count = v8::Local<v8::Function>::Cast(context->Global()->Get(
5651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "frame_count")));
5652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile a function for returning the source line for the top frame.
5654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              frame_source_line_source))->Run();
5656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  frame_source_line = v8::Local<v8::Function>::Cast(context->Global()->Get(
5657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "frame_source_line")));
5658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile a function returning the data parameter.
5660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              debugger_call_with_data_source))
5662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
5663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  debugger_call_with_data = v8::Local<v8::Function>::Cast(
5664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      context->Global()->Get(v8::String::NewFromUtf8(
5665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          isolate, "debugger_call_with_data")));
5666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile a function capturing closure.
5668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  debugger_call_with_closure =
5669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Local<v8::Function>::Cast(v8::Script::Compile(
5670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          v8::String::NewFromUtf8(isolate,
5671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  debugger_call_with_closure_source))->Run());
5672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Calling a function through the debugger returns 0 frames if there are
56746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // no JavaScript frames.
5675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(v8::Integer::New(isolate, 0),
5676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           v8::Debug::Call(frame_count));
5677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test that the number of frames can be retrieved.
5679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
5680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "CheckFrameCount(1)"))->Run();
5681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "function f() {"
5683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "  CheckFrameCount(2);"
5684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "}; f()"))->Run();
5685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test that the source line can be retrieved.
5687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
5688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "CheckSourceLine(0)"))->Run();
5689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "function f() {\n"
5691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "  CheckSourceLine(1)\n"
5692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "  CheckSourceLine(2)\n"
5693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "  CheckSourceLine(3)\n"
5694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "}; f()"))->Run();
5695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test that a parameter can be passed to a function called in the debugger.
5697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "CheckDataParameter()"))->Run();
5699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test that a function with closure can be run in the debugger.
5701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
5702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "CheckClosure()"))->Run();
5703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test that the source line is correct when there is a line offset.
5705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin(v8::String::NewFromUtf8(isolate, "test"),
5706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          v8::Integer::New(isolate, 7));
5707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
5708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "CheckSourceLine(7)"), &origin)
5709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
5710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "function f() {\n"
5712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "  CheckSourceLine(8)\n"
5713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "  CheckSourceLine(9)\n"
5714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "  CheckSourceLine(10)\n"
5715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "}; f()"),
5716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      &origin)->Run();
5717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debugger message handler which counts the number of breaks.
5721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void SendContinueCommand();
5722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void MessageHandlerBreakPointHitCount(
5723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const v8::Debug::Message& message) {
5724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (message.IsEvent() && message.GetEvent() == v8::Break) {
5725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Count the number of breaks.
5726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
5727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SendContinueCommand();
5729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that clearing the debug event listener actually clears all break points
5734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and related information.
5735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebuggerUnload) {
5736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
5737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check debugger is unloaded before it is used.
5739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
5740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a debug event listener.
5742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
5743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
5744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
5745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
5746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Create a couple of functions for the test.
5747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Local<v8::Function> foo =
5748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CompileFunction(&env, "function foo(){x=1}", "foo");
5749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Local<v8::Function> bar =
5750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CompileFunction(&env, "function bar(){y=2}", "bar");
5751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set some break points.
5753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetBreakPoint(foo, 0);
5754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetBreakPoint(foo, 4);
5755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetBreakPoint(bar, 0);
5756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetBreakPoint(bar, 4);
5757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Make sure that the break points are there.
5759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count = 0;
5760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    foo->Call(env->Global(), 0, NULL);
5761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(2, break_point_hit_count);
5762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bar->Call(env->Global(), 0, NULL);
5763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(4, break_point_hit_count);
5764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove the debug event listener without clearing breakpoints. Do this
5767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // outside a handle scope.
5768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(NULL);
5769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded(true);
5770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Now set a debug message handler.
5772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_point_hit_count = 0;
5773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(MessageHandlerBreakPointHitCount);
5774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
5775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::HandleScope scope(env->GetIsolate());
5776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the test functions again.
57783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast(
5779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo"))));
5780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    foo->Call(env->Global(), 0, NULL);
5782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(0, break_point_hit_count);
5783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set break points and run again.
5785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetBreakPoint(foo, 0);
5786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SetBreakPoint(foo, 4);
5787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    foo->Call(env->Global(), 0, NULL);
5788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(2, break_point_hit_count);
5789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Remove the debug message handler without clearing breakpoints. Do this
5792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // outside a handle scope.
5793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
5794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded(true);
5795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Sends continue command to the debugger.
5799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void SendContinueCommand() {
5800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kBufferSize = 1000;
5801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint16_t buffer[kBufferSize];
5802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* command_continue =
5803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "{\"seq\":0,"
5804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"type\":\"request\","
5805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     "\"command\":\"continue\"}";
5806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
5808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CcTest::isolate(), buffer, AsciiToUtf16(command_continue, buffer));
5809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debugger message handler which counts the number of times it is called.
5813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int message_handler_hit_count = 0;
5814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void MessageHandlerHitCount(const v8::Debug::Message& message) {
5815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_handler_hit_count++;
5816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static char print_buffer[1000];
58183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  v8::String::Value json(message.GetJSON());
58193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Utf16ToAscii(*json, json.length(), print_buffer);
58203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (IsExceptionEventMessage(print_buffer)) {
58213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    // Send a continue command for exception events.
58223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    SendContinueCommand();
58233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
5824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test clearing the debug message handler.
5828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebuggerClearMessageHandler) {
5829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
5830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
5831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check debugger is unloaded before it is used.
5833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
5834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a debug message handler.
5836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(MessageHandlerHitCount);
5837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run code to throw a unhandled exception. This should end up in the message
5839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handler.
5840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("throw 1");
5841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The message handler should be called.
5843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_GT(message_handler_hit_count, 0);
5844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear debug message handler.
5846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_handler_hit_count = 0;
5847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetMessageHandler(NULL);
5848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run code to throw a unhandled exception. This should end up in the message
5850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handler.
5851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("throw 1");
5852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The message handler should not be called more.
5854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, message_handler_hit_count);
5855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded(true);
5857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debugger message handler which clears the message handler while active.
5861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void MessageHandlerClearingMessageHandler(
5862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const v8::Debug::Message& message) {
5863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_handler_hit_count++;
5864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clear debug message handler.
5866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetMessageHandler(NULL);
5867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test clearing the debug message handler while processing a debug event.
5871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebuggerClearMessageHandlerWhileActive) {
5872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
5873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
5874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check debugger is unloaded before it is used.
5876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
5877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a debug message handler.
5879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(MessageHandlerClearingMessageHandler);
5880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Run code to throw a unhandled exception. This should end up in the message
5882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handler.
5883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun("throw 1");
5884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The message handler should be called.
5886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, message_handler_hit_count);
5887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded(true);
5889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test for issue http://code.google.com/p/v8/issues/detail?id=289.
5893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Make sure that DebugGetLoadedScripts doesn't return scripts
5894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with disposed external source.
5895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EmptyExternalStringResource : public v8::String::ExternalStringResource {
5896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
5897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmptyExternalStringResource() { empty_[0] = 0; }
5898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~EmptyExternalStringResource() {}
5899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual size_t length() const { return empty_.length(); }
5900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual const uint16_t* data() const { return empty_.start(); }
5901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
5902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
5903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
5904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugGetLoadedScripts) {
5907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
5908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
5909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
5910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmptyExternalStringResource source_ext_str;
5912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> source =
5913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewExternal(env->GetIsolate(), &source_ext_str);
59143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::Script> evil_script(v8::Script::Compile(source));
59153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // "use" evil_script to make the compiler happy.
59163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  (void) evil_script;
5917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<i::ExternalTwoByteString> i_source(
5918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
5919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This situation can happen if source was an external string disposed
5920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // by its owner.
5921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i_source->set_resource(0);
5922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
5924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::FLAG_allow_natives_syntax = true;
5925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(
5926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var scripts = %DebugGetLoadedScripts();"
5927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "var count = scripts.length;"
5928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "for (var i = 0; i < count; ++i) {"
5929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "  scripts[i].line_ends;"
5930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "}");
5931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Must not crash while accessing line_ends.
5932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::FLAG_allow_natives_syntax = allow_natives_syntax;
5933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Some scripts are retrieved - at least the number of native scripts.
5935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_GT((*env)
5936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               ->Global()
5937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               ->Get(v8::String::NewFromUtf8(env->GetIsolate(), "count"))
5938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               ->Int32Value(),
5939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           8);
5940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test script break points set on lines.
5944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ScriptNameAndData) {
5945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
5946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
5947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
5948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create functions for retrieving script name and data for the function on
5950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the top frame when hitting a break point.
5951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_script_name = CompileFunction(&env,
5952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      frame_script_name_source,
5953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      "frame_script_name");
5954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
5956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test function source.
5958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> script = v8::String::NewFromUtf8(env->GetIsolate(),
5959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                         "function f() {\n"
5960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                         "  debugger;\n"
5961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                         "}\n");
5962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin1 =
5964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "name"));
5965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Script> script1 = v8::Script::Compile(script, &origin1);
5966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script1->Run();
5967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f;
5968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
5969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
5970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
5972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
5973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ("name", last_script_name_hit);
5974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile the same script again without setting data. As the compilation
5976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // cache is disabled when debugging expect the data to be missing.
5977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Script::Compile(script, &origin1)->Run();
5978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
5979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
5980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
5981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
5982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ("name", last_script_name_hit);
5983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> data_obj_source = v8::String::NewFromUtf8(
5985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->GetIsolate(),
5986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "({ a: 'abc',\n"
5987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  b: 123,\n"
5988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  toString: function() { return this.a + ' ' + this.b; }\n"
5989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "})\n");
5990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(data_obj_source)->Run();
5991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptOrigin origin2 =
5992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "new name"));
5993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Script> script2 = v8::Script::Compile(script, &origin2);
5994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  script2->Run();
5995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
5996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
5997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
5998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, break_point_hit_count);
5999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ("new name", last_script_name_hit);
6000402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script3 = v8::Script::Compile(script, &origin2);
6002402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  script3->Run();
6003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f = v8::Local<v8::Function>::Cast(
6004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
6005402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  f->Call(env->Global(), 0, NULL);
6006402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  CHECK_EQ(4, break_point_hit_count);
6007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic v8::Handle<v8::Context> expected_context;
6011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic v8::Handle<v8::Value> expected_context_data;
6012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Check that the expected context is the one generating the debug event.
6015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ContextCheckMessageHandler(const v8::Debug::Message& message) {
6016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(message.GetEventContext() == expected_context);
6017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals(
6018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      expected_context_data));
6019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_handler_hit_count++;
6020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static char print_buffer[1000];
60223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  v8::String::Value json(message.GetJSON());
60233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Utf16ToAscii(*json, json.length(), print_buffer);
60243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Send a continue command for break events.
60263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (IsBreakEventMessage(print_buffer)) {
6027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SendContinueCommand();
6028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test which creates two contexts and sets different embedder data on each.
6033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Checks that this data is set correctly and that when the debug message
6034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// handler is called the expected context is the one active.
6035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ContextData) {
6036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create two contexts.
6040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Context> context_1;
6041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Context> context_2;
6042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::ObjectTemplate> global_template =
6043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::ObjectTemplate>();
6044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>();
6045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context_1 = v8::Context::New(isolate, NULL, global_template, global_object);
6046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context_2 = v8::Context::New(isolate, NULL, global_template, global_object);
6047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(ContextCheckMessageHandler);
6049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Default data value is undefined.
6051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context_1->GetEmbedderData(0)->IsUndefined());
6052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context_2->GetEmbedderData(0)->IsUndefined());
6053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set and check different data values.
6055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> data_1 = v8::String::NewFromUtf8(isolate, "1");
6056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> data_2 = v8::String::NewFromUtf8(isolate, "2");
6057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context_1->SetEmbedderData(0, data_1);
6058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context_2->SetEmbedderData(0, data_2);
6059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
6060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context_2->GetEmbedderData(0)->StrictEquals(data_2));
6061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Simple test function which causes a break.
6063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source = "function f() { debugger; }";
6064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter and run function in the first context.
6066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
6067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Context::Scope context_scope(context_1);
6068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    expected_context = context_1;
6069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    expected_context_data = data_1;
6070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
6071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(context_1->Global(), 0, NULL);
6072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter and run function in the second context.
6076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
6077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Context::Scope context_scope(context_2);
6078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    expected_context = context_2;
6079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    expected_context_data = data_2;
6080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
6081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(context_2->Global(), 0, NULL);
6082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Two times compile event and two times break event.
6085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_GT(message_handler_hit_count, 4);
6086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
6089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug message handler which issues a debug break when it hits a break event.
6093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int message_handler_break_hit_count = 0;
6094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void DebugBreakMessageHandler(const v8::Debug::Message& message) {
6095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Schedule a debug break for break events.
6096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (message.IsEvent() && message.GetEvent() == v8::Break) {
6097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    message_handler_break_hit_count++;
6098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (message_handler_break_hit_count == 1) {
6099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Debug::DebugBreak(message.GetIsolate());
6100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
6101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Issue a continue command if this event will not cause the VM to start
6104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // running.
6105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!message.WillStartRunning()) {
6106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SendContinueCommand();
6107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that a debug break can be scheduled while in a message handler.
6112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DebugBreakInMessageHandler) {
6113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
6114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(DebugBreakMessageHandler);
6117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test functions.
6119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* script = "function f() { debugger; g(); } function g() { }";
6120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CompileRun(script);
6121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
6122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
6123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
6124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
6125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call f then g. The debugger statement in f will casue a break which will
6127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // cause another break.
6128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
6129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, message_handler_break_hit_count);
6130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calling g will not cause any additional breaks.
6131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  g->Call(env->Global(), 0, NULL);
6132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, message_handler_break_hit_count);
6133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
61366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifndef V8_INTERPRETED_REGEXP
6137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug event handler which gets the function on the top frame and schedules a
6138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// break a number of times.
6139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void DebugEventDebugBreak(
6140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
6141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
6142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
6143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event == v8::Break) {
6145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
6146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the name of the top frame function.
6148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!frame_function_name.IsEmpty()) {
6149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Get the name of the function.
6150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      const int argc = 2;
6151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Handle<v8::Value> argv[argc] = {
6152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        exec_state, v8::Integer::New(CcTest::isolate(), 0)
6153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      };
6154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
6155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                               argc, argv);
6156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (result->IsUndefined()) {
6157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        last_function_hit[0] = '\0';
6158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
6159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK(result->IsString());
6160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        v8::Handle<v8::String> function_name(result->ToString());
6161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        function_name->WriteUtf8(last_function_hit);
6162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
6163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
6164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Keep forcing breaks.
6166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (break_point_hit_count < 20) {
6167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Debug::DebugBreak(CcTest::isolate());
6168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
6169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(RegExpDebugBreak) {
6174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This test only applies to native regexps.
6175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
6176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for checking the function when hitting a break point.
6179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_function_name = CompileFunction(&env,
6180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        frame_function_name_source,
6181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        "frame_function_name");
6182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Test RegExp which matches white spaces and comments at the begining of a
6184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // source line.
6185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* script =
6186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "var sourceLineBeginningSkip = /^(?:[ \\v\\h]*(?:\\/\\*.*?\\*\\/)*)*/;\n"
6187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "function f(s) { return s.match(sourceLineBeginningSkip)[0].length; }";
6188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = CompileFunction(env->GetIsolate(), script, "f");
6190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int argc = 1;
6191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> argv[argc] = {
6192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "  /* xxx */ a=0;")};
6193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Value> result = f->Call(env->Global(), argc, argv);
6194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(12, result->Int32Value());
6195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Debug::SetDebugEventListener(DebugEventDebugBreak);
6197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
6198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = f->Call(env->Global(), argc, argv);
6199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that there was only one break event. Matching RegExp should not
6201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // cause Break events.
6202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
6203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ("f", last_function_hit);
6204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
62056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // V8_INTERPRETED_REGEXP
6206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Common part of EvalContextData and NestedBreakEventContextData tests.
6209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ExecuteScriptForContextCheck(
6210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Debug::MessageHandler message_handler) {
6211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a context.
6212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Context> context_1;
6213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::ObjectTemplate> global_template =
6214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Handle<v8::ObjectTemplate>();
6215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context_1 =
6216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Context::New(CcTest::isolate(), NULL, global_template);
6217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(message_handler);
6219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Default data value is undefined.
6221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context_1->GetEmbedderData(0)->IsUndefined());
6222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set and check a data value.
6224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> data_1 =
6225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(CcTest::isolate(), "1");
6226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context_1->SetEmbedderData(0, data_1);
6227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
6228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Simple test function with eval that causes a break.
6230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* source = "function f() { eval('debugger;'); }";
6231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter and run function in the context.
6233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
6234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Context::Scope context_scope(context_1);
6235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    expected_context = context_1;
6236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    expected_context_data = data_1;
6237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Function> f = CompileFunction(CcTest::isolate(), source, "f");
6238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    f->Call(context_1->Global(), 0, NULL);
6239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test which creates a context and sets embedder data on it. Checks that this
6246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// data is set correctly and that when the debug message handler is called for
6247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// break event in an eval statement the expected context is the one returned by
6248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Message.GetEventContext.
6249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(EvalContextData) {
6250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
6251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExecuteScriptForContextCheck(ContextCheckMessageHandler);
6253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // One time compile event and one time break event.
6255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_GT(message_handler_hit_count, 2);
6256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
6257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool sent_eval = false;
6261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int break_count = 0;
6262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int continue_command_send_count = 0;
6263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Check that the expected context is the one generating the debug event
6264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// including the case of nested break event.
6265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void DebugEvalContextCheckMessageHandler(
6266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const v8::Debug::Message& message) {
6267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(message.GetEventContext() == expected_context);
6268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals(
6269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      expected_context_data));
6270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_handler_hit_count++;
6271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
62723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  static char print_buffer[1000];
62733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  v8::String::Value json(message.GetJSON());
62743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Utf16ToAscii(*json, json.length(), print_buffer);
62753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = message.GetIsolate();
62773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (IsBreakEventMessage(print_buffer)) {
6278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_count++;
6279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!sent_eval) {
6280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sent_eval = true;
6281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int kBufferSize = 1000;
6283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uint16_t buffer[kBufferSize];
6284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const char* eval_command =
6285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          "{\"seq\":0,"
6286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          "\"type\":\"request\","
6287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          "\"command\":\"evaluate\","
6288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          "\"arguments\":{\"expression\":\"debugger;\","
6289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          "\"global\":true,\"disable_break\":false}}";
6290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Send evaluate command.
6292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Debug::SendCommand(
6293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          isolate, buffer, AsciiToUtf16(eval_command, buffer));
6294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
6295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
6296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // It's a break event caused by the evaluation request above.
6297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      SendContinueCommand();
6298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue_command_send_count++;
6299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
63003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  } else if (IsEvaluateResponseMessage(print_buffer) &&
63013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      continue_command_send_count < 2) {
6302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Response to the evaluation request. We're still on the breakpoint so
6303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // send continue.
6304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SendContinueCommand();
6305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    continue_command_send_count++;
6306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests that context returned for break event is correct when the event occurs
6311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// in 'evaluate' debugger request.
6312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(NestedBreakEventContextData) {
6313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
6314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  break_count = 0;
6315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_handler_hit_count = 0;
6316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExecuteScriptForContextCheck(DebugEvalContextCheckMessageHandler);
6318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // One time compile event and two times break event.
6320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_GT(message_handler_hit_count, 3);
6321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // One break from the source and another from the evaluate request.
6323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(break_count, 2);
6324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
6325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debug event listener which counts the after compile events.
6329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint after_compile_message_count = 0;
6330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AfterCompileMessageHandler(const v8::Debug::Message& message) {
6331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Count the number of scripts collected.
6332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (message.IsEvent()) {
6333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (message.GetEvent() == v8::AfterCompile) {
6334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      after_compile_message_count++;
6335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (message.GetEvent() == v8::Break) {
6336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      SendContinueCommand();
6337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
6338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests that after compile event is sent as many times as there are scripts
6343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// compiled.
6344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(AfterCompileMessageWhenMessageHandlerIsReset) {
6345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
6346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  after_compile_message_count = 0;
6348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* script = "var a=1";
6349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
6352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
6353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
6357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
6358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
6359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setting listener to NULL should cause debugger unload.
6361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
6363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compilation cache should be disabled when debugger is active.
6365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, after_compile_message_count);
6366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Syntax error event handler which counts a number of events.
6370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint compile_error_event_count = 0;
6371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CompileErrorEventCounterClear() {
6373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  compile_error_event_count = 0;
6374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CompileErrorEventCounter(
6377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
6378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
6379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (event == v8::CompileError) {
6381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    compile_error_event_count++;
6382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Tests that syntax error event is sent as many times as there are scripts
6387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// with syntax error compiled.
6388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(SyntaxErrorMessageOnSyntaxException) {
6389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
6390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For this test, we want to break on uncaught exceptions:
6393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ChangeBreakOnException(false, true);
6394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(CompileErrorEventCounter);
6396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileErrorEventCounterClear();
6398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check initial state.
6400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, compile_error_event_count);
6401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Throws SyntaxError: Unexpected end of input
6403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "+++"));
6404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, compile_error_event_count);
6405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
6407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::NewFromUtf8(env->GetIsolate(), "/sel\\/: \\"));
6408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, compile_error_event_count);
6409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
6411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::NewFromUtf8(env->GetIsolate(), "JSON.parse('1234:')"));
6412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, compile_error_event_count);
6413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
6415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::String::NewFromUtf8(env->GetIsolate(), "new RegExp('/\\/\\\\');"));
6416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, compile_error_event_count);
6417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "throw 1;"));
6419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, compile_error_event_count);
6420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests that break event is sent when message handler is reset.
6424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(BreakMessageWhenMessageHandlerIsReset) {
6425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
6426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  after_compile_message_count = 0;
6428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* script = "function f() {};";
6429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
6432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
6433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
6437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
6438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
6439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
6440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setting message handler to NULL should cause debugger unload.
6442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
6444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compilation cache should be disabled when debugger is active.
6446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, after_compile_message_count);
6447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int exception_event_count = 0;
6451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ExceptionMessageHandler(const v8::Debug::Message& message) {
6452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (message.IsEvent() && message.GetEvent() == v8::Exception) {
6453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    exception_event_count++;
6454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SendContinueCommand();
6455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests that exception event is sent when message handler is reset.
6460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ExceptionMessageWhenMessageHandlerIsReset) {
6461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
6462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6463086aeeaae12517475c22695a200be45495516549Ben Murdoch
6464086aeeaae12517475c22695a200be45495516549Ben Murdoch  // For this test, we want to break on uncaught exceptions:
6465086aeeaae12517475c22695a200be45495516549Ben Murdoch  ChangeBreakOnException(false, true);
6466086aeeaae12517475c22695a200be45495516549Ben Murdoch
6467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  exception_event_count = 0;
6468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* script = "function f() {throw new Error()};";
6469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
6472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
6473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(ExceptionMessageHandler);
6476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
6477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
6478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
6479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Setting message handler to NULL should cause debugger unload.
6481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
6483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, exception_event_count);
6485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests after compile event is sent when there are some provisional
6489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// breakpoints out of the scripts lines range.
6490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ProvisionalBreakpointOnLineOutOfRange) {
6491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
6492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  env.ExposeDebug();
6494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* script = "function f() {};";
6495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* resource_name = "test_resource";
6496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set a couple of provisional breakpoint on lines out of the script lines
6498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // range.
6499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name,
6500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             3, -1 /* no column */);
6501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int sbp2 =
6502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, 5, 5);
6503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  after_compile_message_count = 0;
6505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::ScriptOrigin origin(
6508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), resource_name),
6509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Integer::New(env->GetIsolate(), 10),
6510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Integer::New(env->GetIsolate(), 1));
6511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compile a script whose first line number is greater than the breakpoints'
6512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // lines.
6513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script),
6514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      &origin)->Run();
6515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the script is compiled successfully there is exactly one after compile
6517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // event. In case of an exception in debugger code after compile event is not
6518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sent.
6519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, after_compile_message_count);
6520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp1);
6522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearBreakPointFromJS(env->GetIsolate(), sbp2);
6523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void BreakMessageHandler(const v8::Debug::Message& message) {
6528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::Isolate* isolate = CcTest::i_isolate();
6529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (message.IsEvent() && message.GetEvent() == v8::Break) {
6530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Count the number of breaks.
6531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    break_point_hit_count++;
6532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::HandleScope scope(isolate);
65343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    message.GetJSON();
6535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SendContinueCommand();
6537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) {
6538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::HandleScope scope(isolate);
6539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int current_count = break_point_hit_count;
6541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Force serialization to trigger some internal JS execution.
65433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    message.GetJSON();
6544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(current_count, break_point_hit_count);
6546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Test that if DebugBreak is forced it is ignored when code from
6551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debug-delay.js is executed.
6552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(NoDebugBreakInAfterCompileMessageHandler) {
6553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
6554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register a debug event listener which sets the break flag and counts.
6557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(BreakMessageHandler);
6558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the debug break flag.
6560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
6561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a function for testing stepping.
6563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* src = "function f() { eval('var x = 10;'); } ";
6564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
6565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // There should be only one break event.
6567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, break_point_hit_count);
6568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the debug break flag again.
6570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
6571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  f->Call(env->Global(), 0, NULL);
6572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // There should be one more break event when the script is evaluated in 'f'.
6573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, break_point_hit_count);
6574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get rid of the debug message handler.
6576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckDebuggerUnloaded();
6578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic int counting_message_handler_counter;
6582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void CountingMessageHandler(const v8::Debug::Message& message) {
6584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (message.IsResponse()) counting_message_handler_counter++;
6585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
6586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Test that debug messages get processed when ProcessDebugMessages is called.
6589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeTEST(ProcessDebugMessages) {
6590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  DebugLocalContext env;
6591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
6592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  counting_message_handler_counter = 0;
6595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(CountingMessageHandler);
6597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  const int kBufferSize = 1000;
6599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  uint16_t buffer[kBufferSize];
6600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  const char* scripts_command =
6601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    "{\"seq\":0,"
6602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     "\"type\":\"request\","
6603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     "\"command\":\"scripts\"}";
6604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Send scripts command.
6606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
6607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_EQ(0, counting_message_handler_counter);
6610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::ProcessDebugMessages();
6611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // At least one message should come
6612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_GE(counting_message_handler_counter, 1);
6613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  counting_message_handler_counter = 0;
6615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
6617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
6619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_EQ(0, counting_message_handler_counter);
6621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::Debug::ProcessDebugMessages();
6622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // At least two messages should come
6623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_GE(counting_message_handler_counter, 2);
6624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Get rid of the debug message handler.
6626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckDebuggerUnloaded();
6628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SendCommandThread;
6632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic SendCommandThread* send_command_thread_ = NULL;
6633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SendCommandThread : public v8::base::Thread {
6636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
6637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit SendCommandThread(v8::Isolate* isolate)
6638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Thread(Options("SendCommandThread")),
6639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        semaphore_(0),
6640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_(isolate) {}
6641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void CountingAndSignallingMessageHandler(
6643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const v8::Debug::Message& message) {
6644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (message.IsResponse()) {
6645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      counting_message_handler_counter++;
6646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      send_command_thread_->semaphore_.Signal();
6647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
6648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void Run() {
6651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    semaphore_.Wait();
6652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const int kBufferSize = 1000;
6653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint16_t buffer[kBufferSize];
6654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const char* scripts_command =
6655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "{\"seq\":0,"
6656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       "\"type\":\"request\","
6657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       "\"command\":\"scripts\"}";
6658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int length = AsciiToUtf16(scripts_command, buffer);
6659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Send scripts command.
6660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < 20; i++) {
6662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::base::ElapsedTimer timer;
6663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      timer.Start();
6664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK_EQ(i, counting_message_handler_counter);
6665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Queue debug message.
6666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Debug::SendCommand(isolate_, buffer, length);
6667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Wait for the message handler to pick up the response.
6668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      semaphore_.Wait();
6669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::PrintF("iteration %d took %f ms\n", i,
6670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                timer.Elapsed().InMillisecondsF());
6671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
6672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::V8::TerminateExecution(isolate_);
6674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void StartSending() { semaphore_.Signal(); }
6677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
6679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::base::Semaphore semaphore_;
6680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate_;
6681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
6682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void StartSendingCommands(
6685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::FunctionCallbackInfo<v8::Value>& info) {
6686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  send_command_thread_->StartSending();
6687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ProcessDebugMessagesThreaded) {
6691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
6692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
6693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counting_message_handler_counter = 0;
6696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(
6698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SendCommandThread::CountingAndSignallingMessageHandler);
6699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  send_command_thread_ = new SendCommandThread(isolate);
6700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  send_command_thread_->Start();
6701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> start =
6703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(isolate, StartSendingCommands);
6704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("start"), start->GetFunction());
6705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("start(); while (true) { }");
6707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(20, counting_message_handler_counter);
6709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CheckDebuggerUnloaded();
6712e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
6713e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6714e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
67156ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstruct BacktraceData {
6716d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static int frame_counter;
6717d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static void MessageHandler(const v8::Debug::Message& message) {
6718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    char print_buffer[1000];
6719d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    v8::String::Value json(message.GetJSON());
6720d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Utf16ToAscii(*json, json.length(), print_buffer, 1000);
6721d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6722d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (strstr(print_buffer, "backtrace") == NULL) {
6723d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      return;
6724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
6725d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    frame_counter = GetTotalFramesInt(print_buffer);
6726d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
6727d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
6728d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
67296ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockint BacktraceData::frame_counter;
6730d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6731d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6732d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Test that debug messages get processed when ProcessDebugMessages is called.
6733d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeTEST(Backtrace) {
6734d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  DebugLocalContext env;
6735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
6736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6737d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(BacktraceData::MessageHandler);
6739d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6740d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const int kBufferSize = 1000;
6741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  uint16_t buffer[kBufferSize];
6742d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const char* scripts_command =
6743d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    "{\"seq\":0,"
6744d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke     "\"type\":\"request\","
6745d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke     "\"command\":\"backtrace\"}";
6746d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6747d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check backtrace from ProcessDebugMessages.
67486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  BacktraceData::frame_counter = -10;
6749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
6750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate,
6751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      buffer,
6752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AsciiToUtf16(scripts_command, buffer),
6753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NULL);
6754d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  v8::Debug::ProcessDebugMessages();
67556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(BacktraceData::frame_counter, 0);
6756d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::String> void0 =
6758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(env->GetIsolate(), "void(0)");
6759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Script> script = CompileWithOrigin(void0, void0);
6760d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6761d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check backtrace from "void(0)" script.
67626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  BacktraceData::frame_counter = -10;
6763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SendCommand(
6764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate,
6765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      buffer,
6766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AsciiToUtf16(scripts_command, buffer),
6767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NULL);
6768d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  script->Run();
67696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CHECK_EQ(BacktraceData::frame_counter, 1);
6770d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6771d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Get rid of the debug message handler.
6772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetMessageHandler(NULL);
6773d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CheckDebuggerUnloaded();
6774d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
6775d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6776d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(GetMirror) {
6778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugLocalContext env;
6779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
6780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Value> obj =
6782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Debug::GetMirror(v8::String::NewFromUtf8(isolate, "hodja"));
6783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::ScriptCompiler::Source source(v8_str(
6784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function runTest(mirror) {"
6785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return mirror.isString() && (mirror.length() == 5);"
6786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}"
6787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ""
6788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "runTest;"));
6789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Function> run_test = v8::Handle<v8::Function>::Cast(
6790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::ScriptCompiler::CompileUnbound(isolate, &source)
6791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ->BindToCurrentContext()
6792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ->Run());
6793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::Value> result = run_test->Call(env->Global(), 1, &obj);
6794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result->IsTrue());
6795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Test that the debug break flag works with function.apply.
6799d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockTEST(DebugBreakFunctionApply) {
6800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  DebugLocalContext env;
6801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
6802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create a function for testing breaking in apply.
6804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Local<v8::Function> foo = CompileFunction(
6805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      &env,
6806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "function baz(x) { }"
6807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "function bar(x) { baz(); }"
6808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "function foo(){ bar.apply(this, [1]); }",
6809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "foo");
6810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Register a debug event listener which steps and counts.
6812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Debug::SetDebugEventListener(DebugEventBreakMax);
6813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Set the debug break flag before calling the code using function.apply.
6815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
6816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Limit the number of debug breaks. This is a regression test for issue 493
6818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // where this test would enter an infinite loop.
6819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  break_point_hit_count = 0;
6820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  max_break_point_hit_count = 10000;  // 10000 => infinite loop.
6821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  foo->Call(env->Global(), 0, NULL);
6822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // When keeping the debug break several break will happen.
68243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_GT(break_point_hit_count, 1);
6825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Debug::SetDebugEventListener(NULL);
6827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CheckDebuggerUnloaded();
6828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
6829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockv8::Handle<v8::Context> debugee_context;
6832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockv8::Handle<v8::Context> debugger_context;
6833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Property getter that checks that current and calling contexts
6836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// are both the debugee contexts.
6837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NamedGetterWithCallingContextCheck(
6838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    v8::Local<v8::String> name,
6839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::PropertyCallbackInfo<v8::Value>& info) {
6840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(name), "a"));
6841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Context> current = info.GetIsolate()->GetCurrentContext();
6842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(current == debugee_context);
6843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(current != debugger_context);
6844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Context> calling = info.GetIsolate()->GetCallingContext();
6845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(calling == debugee_context);
6846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(calling != debugger_context);
6847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info.GetReturnValue().Set(1);
6848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
6849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Debug event listener that checks if the first argument of a function is
6852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// an object with property 'a' == 1. If the property has custom accessor
6853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// this handler will eventually invoke it.
6854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void DebugEventGetAtgumentPropertyValue(
6855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
6856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
6857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
6858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (event == v8::Break) {
6859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    break_point_hit_count++;
6860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(debugger_context == CcTest::isolate()->GetCurrentContext());
6861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(CompileRun(
6862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        "(function(exec_state) {\n"
6863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        "    return (exec_state.frame(0).argumentValue(0).property('a').\n"
6864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        "            value().value() == 1);\n"
6865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "})"));
6866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    const int argc = 1;
6867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    v8::Handle<v8::Value> argv[argc] = { exec_state };
6868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    v8::Handle<v8::Value> result = func->Call(exec_state, argc, argv);
6869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CHECK(result->IsTrue());
6870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
6871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
6872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6874d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockTEST(CallingContextIsNotDebugContext) {
6875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
6876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create and enter a debugee context.
6877d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  DebugLocalContext env;
6878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
6879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  env.ExposeDebug();
6881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Save handles to the debugger and debugee contexts to be used in
6883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // NamedGetterWithCallingContextCheck.
6884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  debugee_context = env.context();
688544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  debugger_context = v8::Utils::ToLocal(debug->debug_context());
6886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create object with 'a' property accessor.
6888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
6889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  named->SetAccessor(v8::String::NewFromUtf8(isolate, "a"),
6890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     NamedGetterWithCallingContextCheck);
6891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"),
6892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     named->NewInstance());
6893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Register the debug event listener
6895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Debug::SetDebugEventListener(DebugEventGetAtgumentPropertyValue);
6896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create a function that invokes debugger.
6898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Local<v8::Function> foo = CompileFunction(
6899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      &env,
6900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "function bar(x) { debugger; }"
6901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "function foo(){ bar(obj); }",
6902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "foo");
6903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  break_point_hit_count = 0;
6905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  foo->Call(env->Global(), 0, NULL);
6906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(1, break_point_hit_count);
6907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
6908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  v8::Debug::SetDebugEventListener(NULL);
6909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  debugee_context = v8::Handle<v8::Context>();
6910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  debugger_context = v8::Handle<v8::Context>();
6911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CheckDebuggerUnloaded();
6912d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
69136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
69146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
69156ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTEST(DebugContextIsPreservedBetweenAccesses) {
6916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
6917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
69186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Local<v8::Context> context1 = v8::Debug::GetDebugContext();
69196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  v8::Local<v8::Context> context2 = v8::Debug::GetDebugContext();
6920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(v8::Utils::OpenHandle(*context1).is_identical_to(
6921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            v8::Utils::OpenHandle(*context2)));
6922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
6923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
6924f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkestatic v8::Handle<v8::Value> expected_callback_data;
6927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkestatic void DebugEventContextChecker(const v8::Debug::EventDetails& details) {
6928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK(details.GetEventContext() == expected_context);
6929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CHECK_EQ(expected_callback_data, details.GetCallbackData());
6930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
6931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
6932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Check that event details contain context where debug event occured.
6934f7060e27768c550ace7ec48ad8c093466db52dfaLeon ClarkeTEST(DebugEventContext) {
6935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = CcTest::isolate();
6936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  expected_context = v8::Context::New(isolate);
6938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  expected_callback_data = v8::Int32::New(isolate, 2010);
6939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventContextChecker,
6940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                    expected_callback_data);
6941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  v8::Context::Scope context_scope(expected_context);
6942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(
6943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::NewFromUtf8(isolate, "(function(){debugger;})();"))->Run();
6944f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  expected_context.Clear();
6945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  v8::Debug::SetDebugEventListener(NULL);
6946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  expected_context_data = v8::Handle<v8::Value>();
69476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CheckDebuggerUnloaded();
69486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
69503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
69513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic void* expected_break_data;
69523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic bool was_debug_break_called;
69533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic bool was_debug_event_called;
69543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic void DebugEventBreakDataChecker(const v8::Debug::EventDetails& details) {
69553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (details.GetEvent() == v8::BreakForCommand) {
69563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    CHECK_EQ(expected_break_data, details.GetClientData());
69573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    was_debug_event_called = true;
69583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  } else if (details.GetEvent() == v8::Break) {
69593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    was_debug_break_called = true;
69603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
69613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
69623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
6963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
69643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Check that event details contain context where debug event occured.
69653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben MurdochTEST(DebugEventBreakData) {
69663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  DebugLocalContext env;
6967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
6968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
6969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakDataChecker);
69703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
69713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  TestClientData::constructor_call_counter = 0;
69723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  TestClientData::destructor_call_counter = 0;
69733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
69743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  expected_break_data = NULL;
69753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  was_debug_event_called = false;
69763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  was_debug_break_called = false;
6977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreakForCommand(isolate, NULL);
6978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
6979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "(function(x){return x;})(1);"))
6980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
69813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK(was_debug_event_called);
69823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK(!was_debug_break_called);
69833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
69843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  TestClientData* data1 = new TestClientData();
69853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  expected_break_data = data1;
69863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  was_debug_event_called = false;
69873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  was_debug_break_called = false;
6988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreakForCommand(isolate, data1);
6989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
6990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "(function(x){return x+1;})(1);"))
6991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
69923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK(was_debug_event_called);
69933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK(!was_debug_break_called);
69943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
69953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  expected_break_data = NULL;
69963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  was_debug_event_called = false;
69973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  was_debug_break_called = false;
6998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(isolate);
6999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
7000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "(function(x){return x+2;})(1);"))
7001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
70023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK(!was_debug_event_called);
70033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK(was_debug_break_called);
70043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
70053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  TestClientData* data2 = new TestClientData();
70063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  expected_break_data = data2;
70073bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  was_debug_event_called = false;
70083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  was_debug_break_called = false;
7009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(isolate);
7010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreakForCommand(isolate, data2);
7011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
7012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              "(function(x){return x+3;})(1);"))
7013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
70143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK(was_debug_event_called);
70153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK(was_debug_break_called);
70163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
70173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ(2, TestClientData::constructor_call_counter);
70183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ(TestClientData::constructor_call_counter,
70193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch           TestClientData::destructor_call_counter);
70203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
70213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  v8::Debug::SetDebugEventListener(NULL);
70223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CheckDebuggerUnloaded();
70233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
70243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
7025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool debug_event_break_deoptimize_done = false;
7026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventBreakDeoptimize(
7028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
7029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
7030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
7031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (event == v8::Break) {
7032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!frame_function_name.IsEmpty()) {
7033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Get the name of the function.
7034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      const int argc = 2;
7035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Handle<v8::Value> argv[argc] = {
7036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        exec_state, v8::Integer::New(CcTest::isolate(), 0)
7037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      };
7038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      v8::Handle<v8::Value> result =
7039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          frame_function_name->Call(exec_state, argc, argv);
7040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!result->IsUndefined()) {
7041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        char fn[80];
7042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK(result->IsString());
7043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        v8::Handle<v8::String> function_name(result->ToString());
7044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        function_name->WriteUtf8(fn);
7045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (strcmp(fn, "bar") == 0) {
7046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          i::Deoptimizer::DeoptimizeAll(CcTest::i_isolate());
7047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          debug_event_break_deoptimize_done = true;
7048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
7049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Debug::DebugBreak(CcTest::isolate());
7053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Test deoptimization when execution is broken using the debug break stack
7058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// check interrupt.
7059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeDuringDebugBreak) {
7060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DebugLocalContext env;
7061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
7062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  env.ExposeDebug();
7063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a function for checking the function when hitting a break point.
7065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  frame_function_name = CompileFunction(&env,
7066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                        frame_function_name_source,
7067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                        "frame_function_name");
7068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set a debug event listener which will keep interrupting execution until
7071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // debug break. When inside function bar it will deoptimize all functions.
7072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // This tests lazy deoptimization bailout for the stack check, as the first
7073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // time in function bar when using debug break and no break points will be at
7074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the initial stack check.
7075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakDeoptimize);
7076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compile and run function bar which will optimize it for some flag settings.
7078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(
7079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          env->GetIsolate(), "function bar(){}; bar()"))->Run();
7080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Set debug break and call bar again.
7082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(env->GetIsolate());
7083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "bar()"))
7084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->Run();
7085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(debug_event_break_deoptimize_done);
7087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::Debug::SetDebugEventListener(NULL);
7089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventBreakWithOptimizedStack(
7093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
7094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = event_details.GetEventContext()->GetIsolate();
7095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
7096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
7097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (event == v8::Break) {
7098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!frame_function_name.IsEmpty()) {
7099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      for (int i = 0; i < 2; i++) {
7100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        const int argc = 2;
7101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Handle<v8::Value> argv[argc] = {
7102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          exec_state, v8::Integer::New(isolate, i)
7103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        };
7104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Get the name of the function in frame i.
7105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        v8::Handle<v8::Value> result =
7106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            frame_function_name->Call(exec_state, argc, argv);
7107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK(result->IsString());
7108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        v8::Handle<v8::String> function_name(result->ToString());
7109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(function_name->Equals(v8::String::NewFromUtf8(isolate, "loop")));
7110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Get the name of the first argument in frame i.
7111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        result = frame_argument_name->Call(exec_state, argc, argv);
7112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK(result->IsString());
7113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        v8::Handle<v8::String> argument_name(result->ToString());
7114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(argument_name->Equals(v8::String::NewFromUtf8(isolate, "count")));
7115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Get the value of the first argument in frame i. If the
7116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // funtion is optimized the value will be undefined, otherwise
7117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // the value will be '1 - i'.
7118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        //
7119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // TODO(3141533): We should be able to get the real value for
7120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // optimized frames.
7121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        result = frame_argument_value->Call(exec_state, argc, argv);
7122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK(result->IsUndefined() || (result->Int32Value() == 1 - i));
7123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Get the name of the first local variable.
7124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        result = frame_local_name->Call(exec_state, argc, argv);
7125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK(result->IsString());
7126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        v8::Handle<v8::String> local_name(result->ToString());
7127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(local_name->Equals(v8::String::NewFromUtf8(isolate, "local")));
7128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Get the value of the first local variable. If the function
7129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // is optimized the value will be undefined, otherwise it will
7130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // be 42.
7131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        //
7132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // TODO(3141533): We should be able to get the real value for
7133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // optimized frames.
7134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        result = frame_local_value->Call(exec_state, argc, argv);
7135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        CHECK(result->IsUndefined() || (result->Int32Value() == 42));
7136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
7137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
7138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
7139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ScheduleBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
7143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventBreakWithOptimizedStack);
7144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(args.GetIsolate());
7145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DebugBreakStackInspection) {
7149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DebugLocalContext env;
7150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
7151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  frame_function_name =
7153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CompileFunction(&env, frame_function_name_source, "frame_function_name");
7154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  frame_argument_name =
7155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CompileFunction(&env, frame_argument_name_source, "frame_argument_name");
7156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  frame_argument_value = CompileFunction(&env,
7157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         frame_argument_value_source,
7158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         "frame_argument_value");
7159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  frame_local_name =
7160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CompileFunction(&env, frame_local_name_source, "frame_local_name");
7161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  frame_local_value =
7162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CompileFunction(&env, frame_local_value_source, "frame_local_value");
7163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::Handle<v8::FunctionTemplate> schedule_break_template =
7165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(env->GetIsolate(), ScheduleBreak);
7166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::Handle<v8::Function> schedule_break =
7167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      schedule_break_template->GetFunction();
7168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  env->Global()->Set(v8_str("scheduleBreak"), schedule_break);
7169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* src =
7171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "function loop(count) {"
7172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "  var local = 42;"
7173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "  if (count < 1) { scheduleBreak(); loop(count + 1); }"
7174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "}"
7175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "loop(0);";
7176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), src))->Run();
7177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
7178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
71793e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
71803e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu// Test that setting the terminate execution flag during debug break processing.
71818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangstatic void TestDebugBreakInLoop(const char* loop_head,
71828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 const char** loop_bodies,
71838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                 const char* loop_tail) {
71848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Receive 100 breaks for each test and then terminate JavaScript execution.
71853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static const int kBreaksPerTest = 100;
71863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
71873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; loop_bodies[i] != NULL; i++) {
71883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Perform a lazy deoptimization after various numbers of breaks
71893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // have been hit.
7190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int j = 0; j < 7; j++) {
71913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break_point_hit_count_deoptimize = j;
7192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (j == 6) {
71933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        break_point_hit_count_deoptimize = kBreaksPerTest;
71943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
71958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
71963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      break_point_hit_count = 0;
71973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      max_break_point_hit_count = kBreaksPerTest;
71983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      terminate_after_max_break_point_hit = true;
71998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
72003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      EmbeddedVector<char, 1024> buffer;
7201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SNPrintF(buffer,
7202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               "function f() {%s%s%s}",
7203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               loop_head, loop_bodies[i], loop_tail);
72048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
72053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Function with infinite loop.
72063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CompileRun(buffer.start());
72078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
72083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Set the debug break to enter the debugger as soon as possible.
7209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Debug::DebugBreak(CcTest::isolate());
72108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
72113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Call function with infinite loop.
72123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CompileRun("f();");
72133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CHECK_EQ(kBreaksPerTest, break_point_hit_count);
72148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
72153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      CHECK(!v8::V8::IsExecutionTerminating());
72163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
72178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
72188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
72198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
72208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
72213e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui ZhuTEST(DebugBreakLoop) {
72223e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  DebugLocalContext env;
7223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
72243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
72253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Register a debug event listener which sets the break flag and counts.
72263e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  v8::Debug::SetDebugEventListener(DebugEventBreakMax);
72273e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
72283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Create a function for getting the frame count when hitting the break.
72293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  frame_count = CompileFunction(&env, frame_count_source, "frame_count");
72303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
72318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CompileRun("var a = 1;");
72328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CompileRun("function g() { }");
72338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CompileRun("function h() { }");
72348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
72358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const char* loop_bodies[] = {
72368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "",
72378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "g()",
72388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "if (a == 0) { g() }",
72398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "if (a == 1) { g() }",
72408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "if (a == 0) { g() } else { h() }",
72418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "if (a == 0) { continue }",
72428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "if (a == 1) { continue }",
72438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "switch (a) { case 1: g(); }",
72448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "switch (a) { case 1: continue; }",
72458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "switch (a) { case 1: g(); break; default: h() }",
72468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "switch (a) { case 1: continue; break; default: h() }",
72478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      NULL
72488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  };
72498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
72508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  TestDebugBreakInLoop("while (true) {", loop_bodies, "}");
72518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  TestDebugBreakInLoop("while (a == 1) {", loop_bodies, "}");
72523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
72538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  TestDebugBreakInLoop("do {", loop_bodies, "} while (true)");
72548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  TestDebugBreakInLoop("do {", loop_bodies, "} while (a == 1)");
72553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
72568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  TestDebugBreakInLoop("for (;;) {", loop_bodies, "}");
72578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}");
72583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
72593e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Get rid of the debug event listener.
72603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  v8::Debug::SetDebugEventListener(NULL);
72613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  CheckDebuggerUnloaded();
72623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu}
72633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
72643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
72653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochv8::Local<v8::Script> inline_script;
72663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugBreakInlineListener(
7268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
7269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
72703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (event != v8::Break) return;
72713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
72723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int expected_frame_count = 4;
72733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int expected_line_number[] = {1, 4, 7, 12};
72743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
72753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::Handle<i::Object> compiled_script = v8::Utils::OpenHandle(*inline_script);
72763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::Handle<i::Script> source_script = i::Handle<i::Script>(i::Script::cast(
72773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      i::JSFunction::cast(*compiled_script)->shared()->script()));
72783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int break_id = CcTest::i_isolate()->debug()->break_id();
72803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  char script[128];
72813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::Vector<char> script_vector(script, sizeof(script));
7282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SNPrintF(script_vector, "%%GetFrameCount(%d)", break_id);
72833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Local<v8::Value> result = CompileRun(script);
72843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
72853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int frame_count = result->Int32Value();
72863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(expected_frame_count, frame_count);
72873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
72883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < frame_count; i++) {
72893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The 5. element in the returned array of GetFrameDetails contains the
72903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // source position of that frame.
7291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SNPrintF(script_vector, "%%GetFrameDetails(%d, %d)[5]", break_id, i);
72923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::Local<v8::Value> result = CompileRun(script);
72933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(expected_line_number[i],
7294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             i::Script::GetLineNumber(source_script, result->Int32Value()));
72953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
72963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
7297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::V8::TerminateExecution(CcTest::isolate());
72983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
72993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
73003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
73013ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(DebugBreakInline) {
73023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i::FLAG_allow_natives_syntax = true;
73033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DebugLocalContext env;
7304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
73053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* source =
73063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function debug(b) {             \n"
73073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  if (b) debugger;              \n"
73083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}                               \n"
73093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function f(b) {                 \n"
73103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  debug(b)                      \n"
73113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "};                              \n"
73123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function g(b) {                 \n"
73133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  f(b);                         \n"
73143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "};                              \n"
73153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "g(false);                       \n"
73163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "g(false);                       \n"
73173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "%OptimizeFunctionOnNextCall(g); \n"
73183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "g(true);";
73193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Debug::SetDebugEventListener(DebugBreakInlineListener);
7320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline_script =
7321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), source));
73223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline_script->Run();
73233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
73243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
73253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugEventStepNext(
7327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
7328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::DebugEvent event = event_details.GetEvent();
7329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (event == v8::Break) {
7330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareStep(StepNext);
7331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
7332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void RunScriptInANewCFrame(const char* source) {
7336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
7337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(source);
7338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasCaught());
7339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Regress131642) {
7343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Bug description:
7344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // When doing StepNext through the first script, the debugger is not reset
7345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // after exiting through exception.  A flawed implementation enabling the
7346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // debugger to step into Array.prototype.forEach breaks inside the callback
7347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for forEach in the second script under the assumption that we are in a
7348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // recursive call.  In an attempt to step out, we crawl the stack using the
7349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // recorded frame pointer from the first script and fail when not finding it
7350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // on the stack.
7351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
7352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
7353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugEventStepNext);
7354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We step through the first script.  It exits through an exception.  We run
7356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this inside a new frame to record a different FP than the second script
7357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // would expect.
7358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* script_1 = "debugger; throw new Error();";
7359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RunScriptInANewCFrame(script_1);
7360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The second script uses forEach.
7362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* script_2 = "[0].forEach(function() { });";
7363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun(script_2);
7364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
7366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Import from test-heap.cc
7370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint CountNativeContexts();
7371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void NopListener(const v8::Debug::EventDetails& event_details) {
7374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(DebuggerCreatesContextIffActive) {
7378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
7379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
7380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CountNativeContexts());
7381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
7383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("debugger;");
7384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1, CountNativeContexts());
7385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(NopListener);
7387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("debugger;");
7388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2, CountNativeContexts());
7389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
7391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(LiveEditEnabled) {
7395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::FLAG_allow_natives_syntax = true;
7396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
7397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
7398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetLiveEditEnabled(env->GetIsolate(), true);
7399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("%LiveEditCompareStrings('', '')");
7400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(LiveEditDisabled) {
7404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::FLAG_allow_natives_syntax = true;
7405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext env;
7406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
7407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetLiveEditEnabled(env->GetIsolate(), false);
7408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("%LiveEditCompareStrings('', '')");
7409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(PrecompiledFunction) {
7413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Regression test for crbug.com/346207. If we have preparse data, parsing the
7414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // function in the presence of the debugger (and breakpoints) should still
7415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // succeed. The bug was that preparsing was done lazily and parsing was done
7416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // eagerly, so, the symbol streams didn't match.
7417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
7418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
7419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env.ExposeDebug();
7420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugBreakInlineListener);
7421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Function> break_here =
7423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CompileFunction(&env, "function break_here(){}", "break_here");
7424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetBreakPoint(break_here, 0);
7425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* source =
7427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "var a = b = c = 1;              \n"
7428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function this_is_lazy() {       \n"
7429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // This symbol won't appear in the preparse data.
7430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  var a;                        \n"
7431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "}                               \n"
7432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "function bar() {                \n"
7433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "  return \"bar\";               \n"
7434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "};                              \n"
7435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "a = b = c = 2;                  \n"
7436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "bar();                          \n";
7437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::Value> result = ParserCacheCompileRun(source);
7438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(result->IsString());
7439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::String::Utf8Value utf8(result);
7440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ("bar", *utf8);
7441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(NULL);
7443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckDebuggerUnloaded();
7444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugBreakStackTraceListener(
7448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
7449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::StackTrace::CurrentStackTrace(CcTest::isolate(), 10);
7450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void AddDebugBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
7454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(args.GetIsolate());
7455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(DebugBreakStackTrace) {
7459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
7460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(env->GetIsolate());
7461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugBreakStackTraceListener);
7462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> add_debug_break_template =
7463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::FunctionTemplate::New(env->GetIsolate(), AddDebugBreak);
7464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::Function> add_debug_break =
7465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      add_debug_break_template->GetFunction();
7466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  env->Global()->Set(v8_str("add_debug_break"), add_debug_break);
7467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("(function loop() {"
7469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "  for (var j = 0; j < 1000; j++) {"
7470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "    for (var i = 0; i < 1000; i++) {"
7471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "      if (i == 999) add_debug_break();"
7472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "    }"
7473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "  }"
7474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             "})()");
7475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochv8::base::Semaphore terminate_requested_semaphore(0);
7479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochv8::base::Semaphore terminate_fired_semaphore(0);
7480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool terminate_already_fired = false;
7481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void DebugBreakTriggerTerminate(
7484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const v8::Debug::EventDetails& event_details) {
7485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (event_details.GetEvent() != v8::Break || terminate_already_fired) return;
7486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  terminate_requested_semaphore.Signal();
7487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Wait for at most 2 seconds for the terminate request.
7488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(terminate_fired_semaphore.WaitFor(v8::base::TimeDelta::FromSeconds(2)));
7489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  terminate_already_fired = true;
7490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass TerminationThread : public v8::base::Thread {
7494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
7495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit TerminationThread(v8::Isolate* isolate)
7496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Thread(Options("terminator")), isolate_(isolate) {}
7497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void Run() {
7499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    terminate_requested_semaphore.Wait();
7500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::V8::TerminateExecution(isolate_);
7501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    terminate_fired_semaphore.Signal();
7502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
7503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
7505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate_;
7506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
7507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(DebugBreakOffThreadTerminate) {
7510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DebugLocalContext env;
7511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate = env->GetIsolate();
7512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(isolate);
7513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::SetDebugEventListener(DebugBreakTriggerTerminate);
7514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TerminationThread terminator(isolate);
7515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  terminator.Start();
7516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::TryCatch try_catch;
7517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Debug::DebugBreak(isolate);
7518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompileRun("while (true);");
7519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(try_catch.HasTerminated());
7520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
7521