blob: 914bda1d4e77e45a13f8f3b5fa174abd5c1d65fd [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010028#include <stdlib.h>
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010029
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "src/api.h"
33#include "src/base/platform/condition-variable.h"
34#include "src/base/platform/platform.h"
35#include "src/compilation-cache.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036#include "src/debug/debug.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037#include "src/deoptimizer.h"
38#include "src/frames.h"
39#include "src/utils.h"
40#include "test/cctest/cctest.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041
42
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043using ::v8::base::Mutex;
44using ::v8::base::LockGuard;
45using ::v8::base::ConditionVariable;
46using ::v8::base::OS;
47using ::v8::base::Semaphore;
Steve Blocka7e24c12009-10-30 11:49:00 +000048using ::v8::internal::EmbeddedVector;
49using ::v8::internal::Object;
Steve Blocka7e24c12009-10-30 11:49:00 +000050using ::v8::internal::Handle;
51using ::v8::internal::Heap;
52using ::v8::internal::JSGlobalProxy;
53using ::v8::internal::Code;
54using ::v8::internal::Debug;
Steve Blocka7e24c12009-10-30 11:49:00 +000055using ::v8::internal::CommandMessage;
56using ::v8::internal::CommandMessageQueue;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057using ::v8::internal::StackFrame;
Steve Blocka7e24c12009-10-30 11:49:00 +000058using ::v8::internal::StepAction;
59using ::v8::internal::StepIn; // From StepAction enum
60using ::v8::internal::StepNext; // From StepAction enum
61using ::v8::internal::StepOut; // From StepAction enum
62using ::v8::internal::Vector;
Steve Blockd0582a62009-12-15 09:54:21 +000063using ::v8::internal::StrLength;
Steve Blocka7e24c12009-10-30 11:49:00 +000064
65// Size of temp buffer for formatting small strings.
66#define SMALL_STRING_BUFFER_SIZE 80
67
Steve Blocka7e24c12009-10-30 11:49:00 +000068// --- H e l p e r C l a s s e s
69
70
71// Helper class for creating a V8 enviromnent for running tests
72class DebugLocalContext {
73 public:
74 inline DebugLocalContext(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 v8::Isolate* isolate, v8::ExtensionConfiguration* extensions = 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 v8::Local<v8::ObjectTemplate> global_template =
77 v8::Local<v8::ObjectTemplate>(),
78 v8::Local<v8::Value> global_object = v8::Local<v8::Value>())
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 : scope_(isolate),
80 context_(v8::Context::New(isolate, extensions, global_template,
81 global_object)) {
82 context_->Enter();
83 }
84 inline DebugLocalContext(
Steve Blocka7e24c12009-10-30 11:49:00 +000085 v8::ExtensionConfiguration* extensions = 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086 v8::Local<v8::ObjectTemplate> global_template =
87 v8::Local<v8::ObjectTemplate>(),
88 v8::Local<v8::Value> global_object = v8::Local<v8::Value>())
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089 : scope_(CcTest::isolate()),
90 context_(v8::Context::New(CcTest::isolate(), extensions,
91 global_template, global_object)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000092 context_->Enter();
93 }
94 inline ~DebugLocalContext() {
95 context_->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000096 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000097 inline v8::Local<v8::Context> context() { return context_; }
Steve Blocka7e24c12009-10-30 11:49:00 +000098 inline v8::Context* operator->() { return *context_; }
99 inline v8::Context* operator*() { return *context_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 inline v8::Isolate* GetIsolate() { return context_->GetIsolate(); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000101 inline bool IsReady() { return !context_.IsEmpty(); }
102 void ExposeDebug() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 v8::internal::Isolate* isolate =
104 reinterpret_cast<v8::internal::Isolate*>(context_->GetIsolate());
105 v8::internal::Factory* factory = isolate->factory();
Steve Blocka7e24c12009-10-30 11:49:00 +0000106 // Expose the debug context global object in the global object for testing.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 CHECK(isolate->debug()->Load());
108 Handle<v8::internal::Context> debug_context =
109 isolate->debug()->debug_context();
110 debug_context->set_security_token(
Steve Blocka7e24c12009-10-30 11:49:00 +0000111 v8::Utils::OpenHandle(*context_)->security_token());
112
113 Handle<JSGlobalProxy> global(Handle<JSGlobalProxy>::cast(
114 v8::Utils::OpenHandle(*context_->Global())));
115 Handle<v8::internal::String> debug_string =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116 factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("debug"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 v8::internal::JSObject::SetOwnPropertyIgnoreAttributes(
118 global, debug_string, handle(debug_context->global_proxy()),
119 v8::internal::DONT_ENUM)
120 .Check();
Steve Blocka7e24c12009-10-30 11:49:00 +0000121 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000122
Steve Blocka7e24c12009-10-30 11:49:00 +0000123 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000124 v8::HandleScope scope_;
125 v8::Local<v8::Context> context_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000126};
127
128
129// --- H e l p e r F u n c t i o n s
130
Steve Blocka7e24c12009-10-30 11:49:00 +0000131// Compile and run the supplied source and return the requested function.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132static v8::Local<v8::Function> CompileFunction(v8::Isolate* isolate,
133 const char* source,
Steve Blocka7e24c12009-10-30 11:49:00 +0000134 const char* function_name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135 CompileRunChecked(isolate, source);
136 v8::Local<v8::String> name = v8_str(isolate, function_name);
137 v8::Local<v8::Context> context = isolate->GetCurrentContext();
138 v8::MaybeLocal<v8::Value> maybe_function =
139 context->Global()->Get(context, name);
140 return v8::Local<v8::Function>::Cast(maybe_function.ToLocalChecked());
141}
142
143
144// Compile and run the supplied source and return the requested function.
145static v8::Local<v8::Function> CompileFunction(DebugLocalContext* env,
146 const char* source,
147 const char* function_name) {
148 return CompileFunction(env->GetIsolate(), source, function_name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000149}
150
151
Steve Blocka7e24c12009-10-30 11:49:00 +0000152// Is there any debug info for the function?
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153static bool HasDebugInfo(v8::Local<v8::Function> fun) {
154 Handle<v8::internal::JSFunction> f =
155 Handle<v8::internal::JSFunction>::cast(v8::Utils::OpenHandle(*fun));
Steve Blocka7e24c12009-10-30 11:49:00 +0000156 Handle<v8::internal::SharedFunctionInfo> shared(f->shared());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 return shared->HasDebugInfo();
Steve Blocka7e24c12009-10-30 11:49:00 +0000158}
159
160
161// Set a break point in a function and return the associated break point
162// number.
163static int SetBreakPoint(Handle<v8::internal::JSFunction> fun, int position) {
164 static int break_point = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165 v8::internal::Isolate* isolate = fun->GetIsolate();
166 v8::internal::Debug* debug = isolate->debug();
Steve Block44f0eee2011-05-26 01:26:41 +0100167 debug->SetBreakPoint(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 fun,
169 Handle<Object>(v8::internal::Smi::FromInt(++break_point), isolate),
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100170 &position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000171 return break_point;
172}
173
174
175// Set a break point in a function and return the associated break point
176// number.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177static int SetBreakPoint(v8::Local<v8::Function> fun, int position) {
178 return SetBreakPoint(
179 i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*fun)), position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000180}
181
182
183// Set a break point in a function using the Debug object and return the
184// associated break point number.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185static int SetBreakPointFromJS(v8::Isolate* isolate,
186 const char* function_name,
Steve Blocka7e24c12009-10-30 11:49:00 +0000187 int line, int position) {
188 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 SNPrintF(buffer,
190 "debug.Debug.setBreakPoint(%s,%d,%d)",
191 function_name, line, position);
Steve Blocka7e24c12009-10-30 11:49:00 +0000192 buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 v8::Local<v8::Value> value = CompileRunChecked(isolate, buffer.start());
194 return value->Int32Value(isolate->GetCurrentContext()).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +0000195}
196
197
198// Set a break point in a script identified by id using the global Debug object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199static int SetScriptBreakPointByIdFromJS(v8::Isolate* isolate, int script_id,
200 int line, int column) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000201 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
202 if (column >= 0) {
203 // Column specified set script break point on precise location.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 SNPrintF(buffer,
205 "debug.Debug.setScriptBreakPointById(%d,%d,%d)",
206 script_id, line, column);
Steve Blocka7e24c12009-10-30 11:49:00 +0000207 } else {
208 // Column not specified set script break point on line.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 SNPrintF(buffer,
210 "debug.Debug.setScriptBreakPointById(%d,%d)",
211 script_id, line);
Steve Blocka7e24c12009-10-30 11:49:00 +0000212 }
213 buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
214 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215 v8::TryCatch try_catch(isolate);
216 v8::Local<v8::Value> value = CompileRunChecked(isolate, buffer.start());
Steve Blocka7e24c12009-10-30 11:49:00 +0000217 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 return value->Int32Value(isolate->GetCurrentContext()).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +0000219 }
220}
221
222
223// Set a break point in a script identified by name using the global Debug
224// object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225static int SetScriptBreakPointByNameFromJS(v8::Isolate* isolate,
226 const char* script_name, int line,
227 int column) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000228 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
229 if (column >= 0) {
230 // Column specified set script break point on precise location.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 SNPrintF(buffer,
232 "debug.Debug.setScriptBreakPointByName(\"%s\",%d,%d)",
233 script_name, line, column);
Steve Blocka7e24c12009-10-30 11:49:00 +0000234 } else {
235 // Column not specified set script break point on line.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 SNPrintF(buffer,
237 "debug.Debug.setScriptBreakPointByName(\"%s\",%d)",
238 script_name, line);
Steve Blocka7e24c12009-10-30 11:49:00 +0000239 }
240 buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
241 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 v8::TryCatch try_catch(isolate);
243 v8::Local<v8::Value> value = CompileRunChecked(isolate, buffer.start());
Steve Blocka7e24c12009-10-30 11:49:00 +0000244 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 return value->Int32Value(isolate->GetCurrentContext()).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +0000246 }
247}
248
249
250// Clear a break point.
251static void ClearBreakPoint(int break_point) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252 v8::internal::Isolate* isolate = CcTest::i_isolate();
253 v8::internal::Debug* debug = isolate->debug();
Steve Block44f0eee2011-05-26 01:26:41 +0100254 debug->ClearBreakPoint(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 Handle<Object>(v8::internal::Smi::FromInt(break_point), isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +0000256}
257
258
259// Clear a break point using the global Debug object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260static void ClearBreakPointFromJS(v8::Isolate* isolate,
261 int break_point_number) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000262 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 SNPrintF(buffer,
264 "debug.Debug.clearBreakPoint(%d)",
265 break_point_number);
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 CompileRunChecked(isolate, buffer.start());
Steve Blocka7e24c12009-10-30 11:49:00 +0000268}
269
270
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271static void EnableScriptBreakPointFromJS(v8::Isolate* isolate,
272 int break_point_number) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 SNPrintF(buffer,
275 "debug.Debug.enableScriptBreakPoint(%d)",
276 break_point_number);
Steve Blocka7e24c12009-10-30 11:49:00 +0000277 buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 CompileRunChecked(isolate, buffer.start());
Steve Blocka7e24c12009-10-30 11:49:00 +0000279}
280
281
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282static void DisableScriptBreakPointFromJS(v8::Isolate* isolate,
283 int break_point_number) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000284 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 SNPrintF(buffer,
286 "debug.Debug.disableScriptBreakPoint(%d)",
287 break_point_number);
Steve Blocka7e24c12009-10-30 11:49:00 +0000288 buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 CompileRunChecked(isolate, buffer.start());
Steve Blocka7e24c12009-10-30 11:49:00 +0000290}
291
292
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293static void ChangeScriptBreakPointConditionFromJS(v8::Isolate* isolate,
294 int break_point_number,
Steve Blocka7e24c12009-10-30 11:49:00 +0000295 const char* condition) {
296 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 SNPrintF(buffer,
298 "debug.Debug.changeScriptBreakPointCondition(%d, \"%s\")",
299 break_point_number, condition);
Steve Blocka7e24c12009-10-30 11:49:00 +0000300 buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 CompileRunChecked(isolate, buffer.start());
Steve Blocka7e24c12009-10-30 11:49:00 +0000302}
303
304
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000305static void ChangeScriptBreakPointIgnoreCountFromJS(v8::Isolate* isolate,
306 int break_point_number,
Steve Blocka7e24c12009-10-30 11:49:00 +0000307 int ignoreCount) {
308 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309 SNPrintF(buffer,
310 "debug.Debug.changeScriptBreakPointIgnoreCount(%d, %d)",
311 break_point_number, ignoreCount);
Steve Blocka7e24c12009-10-30 11:49:00 +0000312 buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 CompileRunChecked(isolate, buffer.start());
Steve Blocka7e24c12009-10-30 11:49:00 +0000314}
315
316
317// Change break on exception.
318static void ChangeBreakOnException(bool caught, bool uncaught) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Steve Block44f0eee2011-05-26 01:26:41 +0100320 debug->ChangeBreakOnException(v8::internal::BreakException, caught);
321 debug->ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught);
Steve Blocka7e24c12009-10-30 11:49:00 +0000322}
323
324
325// Change break on exception using the global Debug object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326static void ChangeBreakOnExceptionFromJS(v8::Isolate* isolate, bool caught,
327 bool uncaught) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000328 if (caught) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 CompileRunChecked(isolate, "debug.Debug.setBreakOnException()");
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 CompileRunChecked(isolate, "debug.Debug.clearBreakOnException()");
Steve Blocka7e24c12009-10-30 11:49:00 +0000332 }
333 if (uncaught) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 CompileRunChecked(isolate, "debug.Debug.setBreakOnUncaughtException()");
Steve Blocka7e24c12009-10-30 11:49:00 +0000335 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 CompileRunChecked(isolate, "debug.Debug.clearBreakOnUncaughtException()");
Steve Blocka7e24c12009-10-30 11:49:00 +0000337 }
338}
339
340
341// Prepare to step to next break location.
342static void PrepareStep(StepAction step_action) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000343 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344 debug->PrepareStep(step_action);
Steve Blocka7e24c12009-10-30 11:49:00 +0000345}
346
347
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348static void ClearStepping() { CcTest::i_isolate()->debug()->ClearStepping(); }
349
350
Steve Blocka7e24c12009-10-30 11:49:00 +0000351// This function is in namespace v8::internal to be friend with class
352// v8::internal::Debug.
353namespace v8 {
354namespace internal {
355
356// Collect the currently debugged functions.
357Handle<FixedArray> GetDebuggedFunctions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358 Debug* debug = CcTest::i_isolate()->debug();
Steve Block44f0eee2011-05-26 01:26:41 +0100359
360 v8::internal::DebugInfoListNode* node = debug->debug_info_list_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000361
362 // Find the number of debugged functions.
363 int count = 0;
364 while (node) {
365 count++;
366 node = node->next();
367 }
368
369 // Allocate array for the debugged functions
370 Handle<FixedArray> debugged_functions =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 CcTest::i_isolate()->factory()->NewFixedArray(count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000372
373 // Run through the debug info objects and collect all functions.
374 count = 0;
375 while (node) {
376 debugged_functions->set(count++, *node->debug_info());
377 node = node->next();
378 }
379
380 return debugged_functions;
381}
382
383
Steve Blocka7e24c12009-10-30 11:49:00 +0000384// Check that the debugger has been fully unloaded.
385void CheckDebuggerUnloaded(bool check_functions) {
386 // Check that the debugger context is cleared and that there is no debug
387 // information stored for the debugger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388 CHECK(CcTest::i_isolate()->debug()->debug_context().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389 CHECK(!CcTest::i_isolate()->debug()->debug_info_list_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000390
391 // Collect garbage to ensure weak handles are cleared.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000393 CcTest::heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
Steve Blocka7e24c12009-10-30 11:49:00 +0000394
395 // Iterate the head and check that there are no debugger related objects left.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000396 HeapIterator iterator(CcTest::heap());
Leon Clarked91b9f72010-01-27 17:25:45 +0000397 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 CHECK(!obj->IsDebugInfo());
399 CHECK(!obj->IsBreakPointInfo());
400
401 // If deep check of functions is requested check that no debug break code
402 // is left in all functions.
403 if (check_functions) {
404 if (obj->IsJSFunction()) {
405 JSFunction* fun = JSFunction::cast(obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 for (RelocIterator it(fun->shared()->code(),
407 RelocInfo::kDebugBreakSlotMask);
408 !it.done(); it.next()) {
409 CHECK(!it.rinfo()->IsPatchedDebugBreakSlotSequence());
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 }
411 }
412 }
413 }
414}
415
416
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000417} // namespace internal
418} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +0000419
420
421// Check that the debugger has been fully unloaded.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422static void CheckDebuggerUnloaded(v8::Isolate* isolate,
423 bool check_functions = false) {
Leon Clarkee46be812010-01-19 14:06:41 +0000424 // Let debugger to unload itself synchronously
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425 v8::Debug::ProcessDebugMessages(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +0000426
Steve Blocka7e24c12009-10-30 11:49:00 +0000427 v8::internal::CheckDebuggerUnloaded(check_functions);
428}
429
430
Steve Blocka7e24c12009-10-30 11:49:00 +0000431// --- D e b u g E v e n t H a n d l e r s
432// ---
433// --- The different tests uses a number of debug event handlers.
434// ---
435
436
Ben Murdochb0fe1622011-05-05 13:52:32 +0100437// Source for the JavaScript function which picks out the function
438// name of a frame.
Steve Blocka7e24c12009-10-30 11:49:00 +0000439const char* frame_function_name_source =
Ben Murdochb0fe1622011-05-05 13:52:32 +0100440 "function frame_function_name(exec_state, frame_number) {"
441 " return exec_state.frame(frame_number).func().name();"
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 "}";
443v8::Local<v8::Function> frame_function_name;
444
445
Ben Murdochb0fe1622011-05-05 13:52:32 +0100446// Source for the JavaScript function which pick out the name of the
447// first argument of a frame.
448const char* frame_argument_name_source =
449 "function frame_argument_name(exec_state, frame_number) {"
450 " return exec_state.frame(frame_number).argumentName(0);"
451 "}";
452v8::Local<v8::Function> frame_argument_name;
453
454
455// Source for the JavaScript function which pick out the value of the
456// first argument of a frame.
457const char* frame_argument_value_source =
458 "function frame_argument_value(exec_state, frame_number) {"
459 " return exec_state.frame(frame_number).argumentValue(0).value_;"
460 "}";
461v8::Local<v8::Function> frame_argument_value;
462
463
464// Source for the JavaScript function which pick out the name of the
465// first argument of a frame.
466const char* frame_local_name_source =
467 "function frame_local_name(exec_state, frame_number) {"
468 " return exec_state.frame(frame_number).localName(0);"
469 "}";
470v8::Local<v8::Function> frame_local_name;
471
472
473// Source for the JavaScript function which pick out the value of the
474// first argument of a frame.
475const char* frame_local_value_source =
476 "function frame_local_value(exec_state, frame_number) {"
477 " return exec_state.frame(frame_number).localValue(0).value_;"
478 "}";
479v8::Local<v8::Function> frame_local_value;
480
481
482// Source for the JavaScript function which picks out the source line for the
Steve Blocka7e24c12009-10-30 11:49:00 +0000483// top frame.
484const char* frame_source_line_source =
485 "function frame_source_line(exec_state) {"
486 " return exec_state.frame(0).sourceLine();"
487 "}";
488v8::Local<v8::Function> frame_source_line;
489
490
Ben Murdochb0fe1622011-05-05 13:52:32 +0100491// Source for the JavaScript function which picks out the source column for the
Steve Blocka7e24c12009-10-30 11:49:00 +0000492// top frame.
493const char* frame_source_column_source =
494 "function frame_source_column(exec_state) {"
495 " return exec_state.frame(0).sourceColumn();"
496 "}";
497v8::Local<v8::Function> frame_source_column;
498
499
Ben Murdochb0fe1622011-05-05 13:52:32 +0100500// Source for the JavaScript function which picks out the script name for the
Steve Blocka7e24c12009-10-30 11:49:00 +0000501// top frame.
502const char* frame_script_name_source =
503 "function frame_script_name(exec_state) {"
504 " return exec_state.frame(0).func().script().name();"
505 "}";
506v8::Local<v8::Function> frame_script_name;
507
508
Ben Murdochb0fe1622011-05-05 13:52:32 +0100509// Source for the JavaScript function which returns the number of frames.
Steve Blocka7e24c12009-10-30 11:49:00 +0000510static const char* frame_count_source =
511 "function frame_count(exec_state) {"
512 " return exec_state.frameCount();"
513 "}";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000514v8::Local<v8::Function> frame_count;
Steve Blocka7e24c12009-10-30 11:49:00 +0000515
516
517// Global variable to store the last function hit - used by some tests.
518char last_function_hit[80];
519
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520// Global variable to store the name for last script hit - used by some tests.
Steve Blocka7e24c12009-10-30 11:49:00 +0000521char last_script_name_hit[80];
Steve Blocka7e24c12009-10-30 11:49:00 +0000522
523// Global variables to store the last source position - used by some tests.
524int last_source_line = -1;
525int last_source_column = -1;
526
527// Debug event handler which counts the break points which have been hit.
528int break_point_hit_count = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000529int break_point_hit_count_deoptimize = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530static void DebugEventBreakPointHitCount(
531 const v8::Debug::EventDetails& event_details) {
532 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 v8::Local<v8::Object> exec_state = event_details.GetExecutionState();
534 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 v8::internal::Isolate* isolate = CcTest::i_isolate();
536 Debug* debug = isolate->debug();
Steve Blocka7e24c12009-10-30 11:49:00 +0000537 // When hitting a debug event listener there must be a break set.
Steve Block44f0eee2011-05-26 01:26:41 +0100538 CHECK_NE(debug->break_id(), 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000539
540 // Count the number of breaks.
541 if (event == v8::Break) {
542 break_point_hit_count++;
543 if (!frame_function_name.IsEmpty()) {
544 // Get the name of the function.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100545 const int argc = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546 v8::Local<v8::Value> argv[argc] = {
547 exec_state, v8::Integer::New(CcTest::isolate(), 0)};
548 v8::Local<v8::Value> result =
549 frame_function_name->Call(context, exec_state, argc, argv)
550 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000551 if (result->IsUndefined()) {
552 last_function_hit[0] = '\0';
553 } else {
554 CHECK(result->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 v8::Local<v8::String> function_name(result.As<v8::String>());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556 function_name->WriteUtf8(last_function_hit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000557 }
558 }
559
560 if (!frame_source_line.IsEmpty()) {
561 // Get the source line.
562 const int argc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 v8::Local<v8::Value> argv[argc] = {exec_state};
564 v8::Local<v8::Value> result =
565 frame_source_line->Call(context, exec_state, argc, argv)
566 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000567 CHECK(result->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 last_source_line = result->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +0000569 }
570
571 if (!frame_source_column.IsEmpty()) {
572 // Get the source column.
573 const int argc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 v8::Local<v8::Value> argv[argc] = {exec_state};
575 v8::Local<v8::Value> result =
576 frame_source_column->Call(context, exec_state, argc, argv)
577 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000578 CHECK(result->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 last_source_column = result->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 }
581
582 if (!frame_script_name.IsEmpty()) {
583 // Get the script name of the function script.
584 const int argc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 v8::Local<v8::Value> argv[argc] = {exec_state};
586 v8::Local<v8::Value> result =
587 frame_script_name->Call(context, exec_state, argc, argv)
588 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000589 if (result->IsUndefined()) {
590 last_script_name_hit[0] = '\0';
591 } else {
592 CHECK(result->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000593 v8::Local<v8::String> script_name(result.As<v8::String>());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000594 script_name->WriteUtf8(last_script_name_hit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000595 }
596 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000597
598 // Perform a full deoptimization when the specified number of
599 // breaks have been hit.
600 if (break_point_hit_count == break_point_hit_count_deoptimize) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601 i::Deoptimizer::DeoptimizeAll(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +0000602 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000603 }
604}
605
606
607// Debug event handler which counts a number of events and collects the stack
608// height if there is a function compiled for that.
609int exception_hit_count = 0;
610int uncaught_exception_hit_count = 0;
611int last_js_stack_height = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612v8::Local<v8::Function> debug_event_listener_callback;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000613int debug_event_listener_callback_result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000614
615static void DebugEventCounterClear() {
616 break_point_hit_count = 0;
617 exception_hit_count = 0;
618 uncaught_exception_hit_count = 0;
619}
620
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000621static void DebugEventCounter(
622 const v8::Debug::EventDetails& event_details) {
623 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624 v8::Local<v8::Object> exec_state = event_details.GetExecutionState();
625 v8::Local<v8::Object> event_data = event_details.GetEventData();
626 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Steve Block44f0eee2011-05-26 01:26:41 +0100628
Steve Blocka7e24c12009-10-30 11:49:00 +0000629 // When hitting a debug event listener there must be a break set.
Steve Block44f0eee2011-05-26 01:26:41 +0100630 CHECK_NE(debug->break_id(), 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000631
632 // Count the number of breaks.
633 if (event == v8::Break) {
634 break_point_hit_count++;
635 } else if (event == v8::Exception) {
636 exception_hit_count++;
637
638 // Check whether the exception was uncaught.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000639 v8::Local<v8::String> fun_name = v8_str(CcTest::isolate(), "uncaught");
640 v8::Local<v8::Function> fun = v8::Local<v8::Function>::Cast(
641 event_data->Get(context, fun_name).ToLocalChecked());
642 v8::Local<v8::Value> result =
643 fun->Call(context, event_data, 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000644 if (result->IsTrue()) {
645 uncaught_exception_hit_count++;
646 }
647 }
648
649 // Collect the JavsScript stack height if the function frame_count is
650 // compiled.
651 if (!frame_count.IsEmpty()) {
652 static const int kArgc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000653 v8::Local<v8::Value> argv[kArgc] = {exec_state};
Steve Blocka7e24c12009-10-30 11:49:00 +0000654 // Using exec_state as receiver is just to have a receiver.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 v8::Local<v8::Value> result =
656 frame_count->Call(context, exec_state, kArgc, argv).ToLocalChecked();
657 last_js_stack_height = result->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +0000658 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000659
660 // Run callback from DebugEventListener and check the result.
661 if (!debug_event_listener_callback.IsEmpty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000662 v8::Local<v8::Value> result =
663 debug_event_listener_callback->Call(context, event_data, 0, NULL)
664 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665 CHECK(!result.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666 CHECK_EQ(debug_event_listener_callback_result,
667 result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000669}
670
671
672// Debug event handler which evaluates a number of expressions when a break
673// point is hit. Each evaluated expression is compared with an expected value.
674// For this debug event handler to work the following two global varaibles
675// must be initialized.
676// checks: An array of expressions and expected results
677// evaluate_check_function: A JavaScript function (see below)
678
679// Structure for holding checks to do.
680struct EvaluateCheck {
681 const char* expr; // An expression to evaluate when a break point is hit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000682 v8::Local<v8::Value> expected; // The expected result.
Steve Blocka7e24c12009-10-30 11:49:00 +0000683};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684
685
Steve Blocka7e24c12009-10-30 11:49:00 +0000686// Array of checks to do.
687struct EvaluateCheck* checks = NULL;
688// Source for The JavaScript function which can do the evaluation when a break
689// point is hit.
690const char* evaluate_check_source =
691 "function evaluate_check(exec_state, expr, expected) {"
692 " return exec_state.frame(0).evaluate(expr).value() === expected;"
693 "}";
694v8::Local<v8::Function> evaluate_check_function;
695
696// The actual debug event described by the longer comment above.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000697static void DebugEventEvaluate(
698 const v8::Debug::EventDetails& event_details) {
699 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000700 v8::Local<v8::Object> exec_state = event_details.GetExecutionState();
701 v8::Isolate* isolate = CcTest::isolate();
702 v8::Local<v8::Context> context = isolate->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000703 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Steve Blocka7e24c12009-10-30 11:49:00 +0000704 // When hitting a debug event listener there must be a break set.
Steve Block44f0eee2011-05-26 01:26:41 +0100705 CHECK_NE(debug->break_id(), 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000706
707 if (event == v8::Break) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000708 break_point_hit_count++;
Steve Blocka7e24c12009-10-30 11:49:00 +0000709 for (int i = 0; checks[i].expr != NULL; i++) {
710 const int argc = 3;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711 v8::Local<v8::String> string = v8_str(isolate, checks[i].expr);
712 v8::Local<v8::Value> argv[argc] = {exec_state, string,
713 checks[i].expected};
714 v8::Local<v8::Value> result =
715 evaluate_check_function->Call(context, exec_state, argc, argv)
716 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000717 if (!result->IsTrue()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400718 v8::String::Utf8Value utf8(checks[i].expected);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000719 V8_Fatal(__FILE__, __LINE__, "%s != %s", checks[i].expr, *utf8);
Steve Blocka7e24c12009-10-30 11:49:00 +0000720 }
721 }
722 }
723}
724
725
726// This debug event listener removes a breakpoint in a function
727int debug_event_remove_break_point = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000728static void DebugEventRemoveBreakPoint(
729 const v8::Debug::EventDetails& event_details) {
730 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000731 v8::Local<v8::Value> data = event_details.GetCallbackData();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000732 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Steve Blocka7e24c12009-10-30 11:49:00 +0000733 // When hitting a debug event listener there must be a break set.
Steve Block44f0eee2011-05-26 01:26:41 +0100734 CHECK_NE(debug->break_id(), 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000735
736 if (event == v8::Break) {
737 break_point_hit_count++;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100738 CHECK(data->IsFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +0000739 ClearBreakPoint(debug_event_remove_break_point);
740 }
741}
742
743
744// Debug event handler which counts break points hit and performs a step
745// afterwards.
746StepAction step_action = StepIn; // Step action to perform when stepping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000747static void DebugEventStep(
748 const v8::Debug::EventDetails& event_details) {
749 v8::DebugEvent event = event_details.GetEvent();
750 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Steve Blocka7e24c12009-10-30 11:49:00 +0000751 // When hitting a debug event listener there must be a break set.
Steve Block44f0eee2011-05-26 01:26:41 +0100752 CHECK_NE(debug->break_id(), 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000753
754 if (event == v8::Break) {
755 break_point_hit_count++;
756 PrepareStep(step_action);
757 }
758}
759
760
761// Debug event handler which counts break points hit and performs a step
762// afterwards. For each call the expected function is checked.
763// For this debug event handler to work the following two global varaibles
764// must be initialized.
765// expected_step_sequence: An array of the expected function call sequence.
766// frame_function_name: A JavaScript function (see below).
767
768// String containing the expected function call sequence. Note: this only works
769// if functions have name length of one.
770const char* expected_step_sequence = NULL;
771
772// The actual debug event described by the longer comment above.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000773static void DebugEventStepSequence(
774 const v8::Debug::EventDetails& event_details) {
775 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000776 v8::Local<v8::Object> exec_state = event_details.GetExecutionState();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000777 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Steve Blocka7e24c12009-10-30 11:49:00 +0000778 // When hitting a debug event listener there must be a break set.
Steve Block44f0eee2011-05-26 01:26:41 +0100779 CHECK_NE(debug->break_id(), 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000780
781 if (event == v8::Break || event == v8::Exception) {
782 // Check that the current function is the expected.
783 CHECK(break_point_hit_count <
Steve Blockd0582a62009-12-15 09:54:21 +0000784 StrLength(expected_step_sequence));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100785 const int argc = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000786 v8::Local<v8::Value> argv[argc] = {exec_state,
787 v8::Integer::New(CcTest::isolate(), 0)};
788 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
789 v8::Local<v8::Value> result =
790 frame_function_name->Call(context, exec_state, argc, argv)
791 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000792 CHECK(result->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793 v8::String::Utf8Value function_name(
794 result->ToString(context).ToLocalChecked());
Steve Blockd0582a62009-12-15 09:54:21 +0000795 CHECK_EQ(1, StrLength(*function_name));
Steve Blocka7e24c12009-10-30 11:49:00 +0000796 CHECK_EQ((*function_name)[0],
797 expected_step_sequence[break_point_hit_count]);
798
799 // Perform step.
800 break_point_hit_count++;
801 PrepareStep(step_action);
802 }
803}
804
805
806// Debug event handler which performs a garbage collection.
807static void DebugEventBreakPointCollectGarbage(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000808 const v8::Debug::EventDetails& event_details) {
809 v8::DebugEvent event = event_details.GetEvent();
810 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Steve Blocka7e24c12009-10-30 11:49:00 +0000811 // When hitting a debug event listener there must be a break set.
Steve Block44f0eee2011-05-26 01:26:41 +0100812 CHECK_NE(debug->break_id(), 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000813
814 // Perform a garbage collection when break point is hit and continue. Based
815 // on the number of break points hit either scavenge or mark compact
816 // collector is used.
817 if (event == v8::Break) {
818 break_point_hit_count++;
819 if (break_point_hit_count % 2 == 0) {
820 // Scavenge.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000821 CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
Steve Blocka7e24c12009-10-30 11:49:00 +0000822 } else {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100823 // Mark sweep compact.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +0000825 }
826 }
827}
828
829
830// Debug event handler which re-issues a debug break and calls the garbage
831// collector to have the heap verified.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832static void DebugEventBreak(
833 const v8::Debug::EventDetails& event_details) {
834 v8::DebugEvent event = event_details.GetEvent();
835 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 // When hitting a debug event listener there must be a break set.
Steve Block44f0eee2011-05-26 01:26:41 +0100837 CHECK_NE(debug->break_id(), 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000838
839 if (event == v8::Break) {
840 // Count the number of breaks.
841 break_point_hit_count++;
842
843 // Run the garbage collector to enforce heap verification if option
844 // --verify-heap is set.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000845 CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
Steve Blocka7e24c12009-10-30 11:49:00 +0000846
847 // Set the break flag again to come back here as soon as possible.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848 v8::Debug::DebugBreak(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000849 }
850}
851
852
Steve Blockd0582a62009-12-15 09:54:21 +0000853// Debug event handler which re-issues a debug break until a limit has been
854// reached.
855int max_break_point_hit_count = 0;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800856bool terminate_after_max_break_point_hit = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857static void DebugEventBreakMax(
858 const v8::Debug::EventDetails& event_details) {
859 v8::DebugEvent event = event_details.GetEvent();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000860 v8::Isolate* v8_isolate = CcTest::isolate();
861 v8::internal::Isolate* isolate = CcTest::i_isolate();
862 v8::internal::Debug* debug = isolate->debug();
Steve Blockd0582a62009-12-15 09:54:21 +0000863 // When hitting a debug event listener there must be a break set.
Steve Block44f0eee2011-05-26 01:26:41 +0100864 CHECK_NE(debug->break_id(), 0);
Steve Blockd0582a62009-12-15 09:54:21 +0000865
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800866 if (event == v8::Break) {
867 if (break_point_hit_count < max_break_point_hit_count) {
868 // Count the number of breaks.
869 break_point_hit_count++;
Steve Blockd0582a62009-12-15 09:54:21 +0000870
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800871 // Set the break flag again to come back here as soon as possible.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000872 v8::Debug::DebugBreak(v8_isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000873
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800874 } else if (terminate_after_max_break_point_hit) {
875 // Terminate execution after the last break if requested.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 v8_isolate->TerminateExecution();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800877 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000878
879 // Perform a full deoptimization when the specified number of
880 // breaks have been hit.
881 if (break_point_hit_count == break_point_hit_count_deoptimize) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882 i::Deoptimizer::DeoptimizeAll(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000883 }
Steve Blockd0582a62009-12-15 09:54:21 +0000884 }
885}
886
887
Steve Blocka7e24c12009-10-30 11:49:00 +0000888// --- M e s s a g e C a l l b a c k
889
890
891// Message callback which counts the number of messages.
892int message_callback_count = 0;
893
894static void MessageCallbackCountClear() {
895 message_callback_count = 0;
896}
897
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000898static void MessageCallbackCount(v8::Local<v8::Message> message,
899 v8::Local<v8::Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000900 message_callback_count++;
901}
902
903
904// --- T h e A c t u a l T e s t s
905
Steve Blocka7e24c12009-10-30 11:49:00 +0000906// Test that the debug info in the VM is in sync with the functions being
907// debugged.
908TEST(DebugInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000909 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000911 // Create a couple of functions for the test.
912 v8::Local<v8::Function> foo =
913 CompileFunction(&env, "function foo(){}", "foo");
914 v8::Local<v8::Function> bar =
915 CompileFunction(&env, "function bar(){}", "bar");
916 // Initially no functions are debugged.
917 CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
918 CHECK(!HasDebugInfo(foo));
919 CHECK(!HasDebugInfo(bar));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 EnableDebugger(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000921 // One function (foo) is debugged.
922 int bp1 = SetBreakPoint(foo, 0);
923 CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
924 CHECK(HasDebugInfo(foo));
925 CHECK(!HasDebugInfo(bar));
926 // Two functions are debugged.
927 int bp2 = SetBreakPoint(bar, 0);
928 CHECK_EQ(2, v8::internal::GetDebuggedFunctions()->length());
929 CHECK(HasDebugInfo(foo));
930 CHECK(HasDebugInfo(bar));
931 // One function (bar) is debugged.
932 ClearBreakPoint(bp1);
933 CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
934 CHECK(!HasDebugInfo(foo));
935 CHECK(HasDebugInfo(bar));
936 // No functions are debugged.
937 ClearBreakPoint(bp2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000938 DisableDebugger(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000939 CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
940 CHECK(!HasDebugInfo(foo));
941 CHECK(!HasDebugInfo(bar));
942}
943
944
945// Test that a break point can be set at an IC store location.
946TEST(BreakPointICStore) {
947 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000948 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000949 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000950
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 v8::Debug::SetDebugEventListener(env->GetIsolate(),
952 DebugEventBreakPointHitCount);
953 v8::Local<v8::Function> foo =
954 CompileFunction(&env, "function foo(){bar=0;}", "foo");
Steve Blocka7e24c12009-10-30 11:49:00 +0000955
956 // Run without breakpoints.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000957 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000958 CHECK_EQ(0, break_point_hit_count);
959
960 // Run with breakpoint
961 int bp = SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000962 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000963 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000964 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000965 CHECK_EQ(2, break_point_hit_count);
966
967 // Run without breakpoints.
968 ClearBreakPoint(bp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000969 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000970 CHECK_EQ(2, break_point_hit_count);
971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
973 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000974}
975
976
977// Test that a break point can be set at an IC load location.
978TEST(BreakPointICLoad) {
979 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000980 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000981 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000982 v8::Debug::SetDebugEventListener(env->GetIsolate(),
983 DebugEventBreakPointHitCount);
984
985 CompileRunChecked(env->GetIsolate(), "bar=1");
986 v8::Local<v8::Function> foo =
987 CompileFunction(&env, "function foo(){var x=bar;}", "foo");
Steve Blocka7e24c12009-10-30 11:49:00 +0000988
989 // Run without breakpoints.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000990 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000991 CHECK_EQ(0, break_point_hit_count);
992
Steve Block44f0eee2011-05-26 01:26:41 +0100993 // Run with breakpoint.
Steve Blocka7e24c12009-10-30 11:49:00 +0000994 int bp = SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000996 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000998 CHECK_EQ(2, break_point_hit_count);
999
1000 // Run without breakpoints.
1001 ClearBreakPoint(bp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001002 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001003 CHECK_EQ(2, break_point_hit_count);
1004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1006 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001007}
1008
1009
1010// Test that a break point can be set at an IC call location.
1011TEST(BreakPointICCall) {
1012 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001013 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001015 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1016 DebugEventBreakPointHitCount);
1017 CompileRunChecked(env->GetIsolate(), "function bar(){}");
1018 v8::Local<v8::Function> foo =
1019 CompileFunction(&env, "function foo(){bar();}", "foo");
Steve Blocka7e24c12009-10-30 11:49:00 +00001020
1021 // Run without breakpoints.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001022 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001023 CHECK_EQ(0, break_point_hit_count);
1024
Steve Block44f0eee2011-05-26 01:26:41 +01001025 // Run with breakpoint
Steve Blocka7e24c12009-10-30 11:49:00 +00001026 int bp = SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001028 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001029 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001030 CHECK_EQ(2, break_point_hit_count);
1031
1032 // Run without breakpoints.
1033 ClearBreakPoint(bp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034 foo->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001035 CHECK_EQ(2, break_point_hit_count);
1036
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001037 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1038 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001039}
1040
1041
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001042// Test that a break point can be set at an IC call location and survive a GC.
1043TEST(BreakPointICCallWithGC) {
1044 break_point_hit_count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001045 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001046 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001047 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1048 DebugEventBreakPointCollectGarbage);
1049 CompileRunChecked(env->GetIsolate(), "function bar(){return 1;}");
1050 v8::Local<v8::Function> foo =
1051 CompileFunction(&env, "function foo(){return bar();}", "foo");
1052 v8::Local<v8::Context> context = env.context();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001053
1054 // Run without breakpoints.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055 CHECK_EQ(1, foo->Call(context, env->Global(), 0, NULL)
1056 .ToLocalChecked()
1057 ->Int32Value(context)
1058 .FromJust());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001059 CHECK_EQ(0, break_point_hit_count);
1060
1061 // Run with breakpoint.
1062 int bp = SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001063 CHECK_EQ(1, foo->Call(context, env->Global(), 0, NULL)
1064 .ToLocalChecked()
1065 ->Int32Value(context)
1066 .FromJust());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001067 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001068 CHECK_EQ(1, foo->Call(context, env->Global(), 0, NULL)
1069 .ToLocalChecked()
1070 ->Int32Value(context)
1071 .FromJust());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001072 CHECK_EQ(2, break_point_hit_count);
1073
1074 // Run without breakpoints.
1075 ClearBreakPoint(bp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001076 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001077 CHECK_EQ(2, break_point_hit_count);
1078
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001079 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1080 CheckDebuggerUnloaded(env->GetIsolate());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001081}
1082
1083
1084// Test that a break point can be set at an IC call location and survive a GC.
1085TEST(BreakPointConstructCallWithGC) {
1086 break_point_hit_count = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001087 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001088 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001089 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1090 DebugEventBreakPointCollectGarbage);
1091 CompileRunChecked(env->GetIsolate(), "function bar(){ this.x = 1;}");
1092 v8::Local<v8::Function> foo =
1093 CompileFunction(&env, "function foo(){return new bar(1).x;}", "foo");
1094 v8::Local<v8::Context> context = env.context();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001095
1096 // Run without breakpoints.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001097 CHECK_EQ(1, foo->Call(context, env->Global(), 0, NULL)
1098 .ToLocalChecked()
1099 ->Int32Value(context)
1100 .FromJust());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001101 CHECK_EQ(0, break_point_hit_count);
1102
1103 // Run with breakpoint.
1104 int bp = SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001105 CHECK_EQ(1, foo->Call(context, env->Global(), 0, NULL)
1106 .ToLocalChecked()
1107 ->Int32Value(context)
1108 .FromJust());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001109 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001110 CHECK_EQ(1, foo->Call(context, env->Global(), 0, NULL)
1111 .ToLocalChecked()
1112 ->Int32Value(context)
1113 .FromJust());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001114 CHECK_EQ(2, break_point_hit_count);
1115
1116 // Run without breakpoints.
1117 ClearBreakPoint(bp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001118 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001119 CHECK_EQ(2, break_point_hit_count);
1120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1122 CheckDebuggerUnloaded(env->GetIsolate());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001123}
1124
1125
Steve Blocka7e24c12009-10-30 11:49:00 +00001126// Test that a break point can be set at a return store location.
1127TEST(BreakPointReturn) {
1128 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001129 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001130 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001131
1132 // Create a functions for checking the source line and column when hitting
1133 // a break point.
1134 frame_source_line = CompileFunction(&env,
1135 frame_source_line_source,
1136 "frame_source_line");
1137 frame_source_column = CompileFunction(&env,
1138 frame_source_column_source,
1139 "frame_source_column");
1140
1141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1143 DebugEventBreakPointHitCount);
1144 v8::Local<v8::Function> foo =
1145 CompileFunction(&env, "function foo(){}", "foo");
1146 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001147
1148 // Run without breakpoints.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001149 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001150 CHECK_EQ(0, break_point_hit_count);
1151
1152 // Run with breakpoint
1153 int bp = SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001154 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001155 CHECK_EQ(1, break_point_hit_count);
1156 CHECK_EQ(0, last_source_line);
Ben Murdochbb769b22010-08-11 14:56:33 +01001157 CHECK_EQ(15, last_source_column);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001158 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001159 CHECK_EQ(2, break_point_hit_count);
1160 CHECK_EQ(0, last_source_line);
Ben Murdochbb769b22010-08-11 14:56:33 +01001161 CHECK_EQ(15, last_source_column);
Steve Blocka7e24c12009-10-30 11:49:00 +00001162
1163 // Run without breakpoints.
1164 ClearBreakPoint(bp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001165 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001166 CHECK_EQ(2, break_point_hit_count);
1167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001168 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1169 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001170}
1171
1172
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173static void CallWithBreakPoints(v8::Local<v8::Context> context,
1174 v8::Local<v8::Object> recv,
Steve Blocka7e24c12009-10-30 11:49:00 +00001175 v8::Local<v8::Function> f,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176 int break_point_count, int call_count) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001177 break_point_hit_count = 0;
1178 for (int i = 0; i < call_count; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179 f->Call(context, recv, 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001180 CHECK_EQ((i + 1) * break_point_count, break_point_hit_count);
1181 }
1182}
1183
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001184
Steve Blocka7e24c12009-10-30 11:49:00 +00001185// Test GC during break point processing.
1186TEST(GCDuringBreakPointProcessing) {
1187 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001188 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001190 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001191
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1193 DebugEventBreakPointCollectGarbage);
Steve Blocka7e24c12009-10-30 11:49:00 +00001194 v8::Local<v8::Function> foo;
1195
1196 // Test IC store break point with garbage collection.
1197 foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1198 SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199 CallWithBreakPoints(context, env->Global(), foo, 1, 10);
Steve Blocka7e24c12009-10-30 11:49:00 +00001200
1201 // Test IC load break point with garbage collection.
1202 foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1203 SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001204 CallWithBreakPoints(context, env->Global(), foo, 1, 10);
Steve Blocka7e24c12009-10-30 11:49:00 +00001205
1206 // Test IC call break point with garbage collection.
1207 foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
1208 SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001209 CallWithBreakPoints(context, env->Global(), foo, 1, 10);
Steve Blocka7e24c12009-10-30 11:49:00 +00001210
1211 // Test return break point with garbage collection.
1212 foo = CompileFunction(&env, "function foo(){}", "foo");
1213 SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001214 CallWithBreakPoints(context, env->Global(), foo, 1, 25);
Steve Blocka7e24c12009-10-30 11:49:00 +00001215
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001216 // Test debug break slot break point with garbage collection.
1217 foo = CompileFunction(&env, "function foo(){var a;}", "foo");
1218 SetBreakPoint(foo, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001219 CallWithBreakPoints(context, env->Global(), foo, 1, 25);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1222 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001223}
1224
1225
1226// Call the function three times with different garbage collections in between
1227// and make sure that the break point survives.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228static void CallAndGC(v8::Local<v8::Context> context,
1229 v8::Local<v8::Object> recv, v8::Local<v8::Function> f) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001230 break_point_hit_count = 0;
1231
1232 for (int i = 0; i < 3; i++) {
1233 // Call function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 f->Call(context, recv, 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001235 CHECK_EQ(1 + i * 3, break_point_hit_count);
1236
1237 // Scavenge and call function.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001238 CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 f->Call(context, recv, 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001240 CHECK_EQ(2 + i * 3, break_point_hit_count);
1241
1242 // Mark sweep (and perhaps compact) and call function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001243 CcTest::heap()->CollectAllGarbage();
1244 f->Call(context, recv, 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001245 CHECK_EQ(3 + i * 3, break_point_hit_count);
1246 }
1247}
1248
1249
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001250// Test that a break point can be set at a return store location.
1251TEST(BreakPointSurviveGC) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001252 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001253 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001254 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001255 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001256
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001257 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1258 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00001259 v8::Local<v8::Function> foo;
1260
1261 // Test IC store break point with garbage collection.
Ben Murdochbb769b22010-08-11 14:56:33 +01001262 {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001263 CompileFunction(&env, "function foo(){}", "foo");
Ben Murdochbb769b22010-08-11 14:56:33 +01001264 foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1265 SetBreakPoint(foo, 0);
1266 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001267 CallAndGC(context, env->Global(), foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001268
1269 // Test IC load break point with garbage collection.
Ben Murdochbb769b22010-08-11 14:56:33 +01001270 {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001271 CompileFunction(&env, "function foo(){}", "foo");
Ben Murdochbb769b22010-08-11 14:56:33 +01001272 foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1273 SetBreakPoint(foo, 0);
1274 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001275 CallAndGC(context, env->Global(), foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001276
1277 // Test IC call break point with garbage collection.
Ben Murdochbb769b22010-08-11 14:56:33 +01001278 {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001279 CompileFunction(&env, "function foo(){}", "foo");
Ben Murdochbb769b22010-08-11 14:56:33 +01001280 foo = CompileFunction(&env,
1281 "function bar(){};function foo(){bar();}",
1282 "foo");
1283 SetBreakPoint(foo, 0);
1284 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001285 CallAndGC(context, env->Global(), foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001286
1287 // Test return break point with garbage collection.
Ben Murdochbb769b22010-08-11 14:56:33 +01001288 {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001289 CompileFunction(&env, "function foo(){}", "foo");
Ben Murdochbb769b22010-08-11 14:56:33 +01001290 foo = CompileFunction(&env, "function foo(){}", "foo");
1291 SetBreakPoint(foo, 0);
1292 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001293 CallAndGC(context, env->Global(), foo);
Ben Murdochbb769b22010-08-11 14:56:33 +01001294
1295 // Test non IC break point with garbage collection.
1296 {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001297 CompileFunction(&env, "function foo(){}", "foo");
Ben Murdochbb769b22010-08-11 14:56:33 +01001298 foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo");
1299 SetBreakPoint(foo, 0);
1300 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001301 CallAndGC(context, env->Global(), foo);
Ben Murdochbb769b22010-08-11 14:56:33 +01001302
Steve Blocka7e24c12009-10-30 11:49:00 +00001303
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1305 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001306}
1307
1308
1309// Test that break points can be set using the global Debug object.
1310TEST(BreakPointThroughJavaScript) {
1311 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001312 DebugLocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001313 v8::Isolate* isolate = env->GetIsolate();
1314 v8::HandleScope scope(isolate);
1315 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001316 env.ExposeDebug();
1317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001318 v8::Debug::SetDebugEventListener(isolate, DebugEventBreakPointHitCount);
1319 CompileRunChecked(isolate, "function bar(){}");
1320 CompileFunction(isolate, "function foo(){bar();bar();}", "foo");
1321 // 012345678901234567890
1322 // 1 2
Steve Blocka7e24c12009-10-30 11:49:00 +00001323 // Break points are set at position 3 and 9
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001324 v8::Local<v8::String> source = v8_str(env->GetIsolate(), "foo()");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001325 v8::Local<v8::Script> foo =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001326 v8::Script::Compile(context, source).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001327
Steve Blocka7e24c12009-10-30 11:49:00 +00001328 CHECK_EQ(0, break_point_hit_count);
1329
1330 // Run with one breakpoint
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001331 int bp1 = SetBreakPointFromJS(env->GetIsolate(), "foo", 0, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001332 foo->Run(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001333 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001334 foo->Run(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001335 CHECK_EQ(2, break_point_hit_count);
1336
1337 // Run with two breakpoints
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 int bp2 = SetBreakPointFromJS(env->GetIsolate(), "foo", 0, 9);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 foo->Run(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001340 CHECK_EQ(4, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001341 foo->Run(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001342 CHECK_EQ(6, break_point_hit_count);
1343
1344 // Run with one breakpoint
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345 ClearBreakPointFromJS(env->GetIsolate(), bp2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001346 foo->Run(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001347 CHECK_EQ(7, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001348 foo->Run(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001349 CHECK_EQ(8, break_point_hit_count);
1350
1351 // Run without breakpoints.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352 ClearBreakPointFromJS(env->GetIsolate(), bp1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001353 foo->Run(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001354 CHECK_EQ(8, break_point_hit_count);
1355
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001356 v8::Debug::SetDebugEventListener(isolate, nullptr);
1357 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001358
1359 // Make sure that the break point numbers are consecutive.
1360 CHECK_EQ(1, bp1);
1361 CHECK_EQ(2, bp2);
1362}
1363
1364
1365// Test that break points on scripts identified by name can be set using the
1366// global Debug object.
1367TEST(ScriptBreakPointByNameThroughJavaScript) {
1368 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001369 DebugLocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001370 v8::Isolate* isolate = env->GetIsolate();
1371 v8::HandleScope scope(isolate);
1372 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001373 env.ExposeDebug();
1374
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001375 v8::Debug::SetDebugEventListener(isolate, DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00001376
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001377 v8::Local<v8::String> script = v8_str(isolate,
1378 "function f() {\n"
1379 " function h() {\n"
1380 " a = 0; // line 2\n"
1381 " }\n"
1382 " b = 1; // line 4\n"
1383 " return h();\n"
1384 "}\n"
1385 "\n"
1386 "function g() {\n"
1387 " function h() {\n"
1388 " a = 0;\n"
1389 " }\n"
1390 " b = 2; // line 12\n"
1391 " h();\n"
1392 " b = 3; // line 14\n"
1393 " f(); // line 15\n"
1394 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00001395
1396 // Compile the script and get the two functions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001397 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str(isolate, "test"));
1398 v8::Script::Compile(context, script, &origin)
1399 .ToLocalChecked()
1400 ->Run(context)
1401 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001402 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001403 env->Global()->Get(context, v8_str(isolate, "f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001404 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001405 env->Global()->Get(context, v8_str(isolate, "g")).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001406
1407 // Call f and g without break points.
1408 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001409 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001410 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001411 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001412 CHECK_EQ(0, break_point_hit_count);
1413
1414 // Call f and g with break point on line 12.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001415 int sbp1 = SetScriptBreakPointByNameFromJS(isolate, "test", 12, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001416 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001417 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001418 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001419 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001420 CHECK_EQ(1, break_point_hit_count);
1421
1422 // Remove the break point again.
1423 break_point_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001424 ClearBreakPointFromJS(env->GetIsolate(), sbp1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001425 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001426 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001427 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001428 CHECK_EQ(0, break_point_hit_count);
1429
1430 // Call f and g with break point on line 2.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431 int sbp2 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 2, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001432 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001433 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001434 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001436 CHECK_EQ(2, break_point_hit_count);
1437
1438 // Call f and g with break point on line 2, 4, 12, 14 and 15.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001439 int sbp3 = SetScriptBreakPointByNameFromJS(isolate, "test", 4, 0);
1440 int sbp4 = SetScriptBreakPointByNameFromJS(isolate, "test", 12, 0);
1441 int sbp5 = SetScriptBreakPointByNameFromJS(isolate, "test", 14, 0);
1442 int sbp6 = SetScriptBreakPointByNameFromJS(isolate, "test", 15, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001443 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001444 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 CHECK_EQ(2, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001446 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001447 CHECK_EQ(7, break_point_hit_count);
1448
1449 // Remove all the break points again.
1450 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001451 ClearBreakPointFromJS(isolate, sbp2);
1452 ClearBreakPointFromJS(isolate, sbp3);
1453 ClearBreakPointFromJS(isolate, sbp4);
1454 ClearBreakPointFromJS(isolate, sbp5);
1455 ClearBreakPointFromJS(isolate, sbp6);
1456 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001457 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001458 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001459 CHECK_EQ(0, break_point_hit_count);
1460
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001461 v8::Debug::SetDebugEventListener(isolate, nullptr);
1462 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001463
1464 // Make sure that the break point numbers are consecutive.
1465 CHECK_EQ(1, sbp1);
1466 CHECK_EQ(2, sbp2);
1467 CHECK_EQ(3, sbp3);
1468 CHECK_EQ(4, sbp4);
1469 CHECK_EQ(5, sbp5);
1470 CHECK_EQ(6, sbp6);
1471}
1472
1473
1474TEST(ScriptBreakPointByIdThroughJavaScript) {
1475 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001476 DebugLocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001477 v8::Isolate* isolate = env->GetIsolate();
1478 v8::HandleScope scope(isolate);
1479 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001480 env.ExposeDebug();
1481
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001482 v8::Debug::SetDebugEventListener(isolate, DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00001483
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001484 v8::Local<v8::String> source = v8_str(isolate,
1485 "function f() {\n"
1486 " function h() {\n"
1487 " a = 0; // line 2\n"
1488 " }\n"
1489 " b = 1; // line 4\n"
1490 " return h();\n"
1491 "}\n"
1492 "\n"
1493 "function g() {\n"
1494 " function h() {\n"
1495 " a = 0;\n"
1496 " }\n"
1497 " b = 2; // line 12\n"
1498 " h();\n"
1499 " b = 3; // line 14\n"
1500 " f(); // line 15\n"
1501 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00001502
1503 // Compile the script and get the two functions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001504 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str(isolate, "test"));
1505 v8::Local<v8::Script> script =
1506 v8::Script::Compile(context, source, &origin).ToLocalChecked();
1507 script->Run(context).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001508 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001509 env->Global()->Get(context, v8_str(isolate, "f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001510 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001511 env->Global()->Get(context, v8_str(isolate, "g")).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001512
1513 // Get the script id knowing that internally it is a 32 integer.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001514 int script_id = script->GetUnboundScript()->GetId();
Steve Blocka7e24c12009-10-30 11:49:00 +00001515
1516 // Call f and g without break points.
1517 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001518 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001519 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001520 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001521 CHECK_EQ(0, break_point_hit_count);
1522
1523 // Call f and g with break point on line 12.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524 int sbp1 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 12, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001525 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001526 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001527 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001528 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001529 CHECK_EQ(1, break_point_hit_count);
1530
1531 // Remove the break point again.
1532 break_point_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001533 ClearBreakPointFromJS(env->GetIsolate(), sbp1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001534 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001535 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001536 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001537 CHECK_EQ(0, break_point_hit_count);
1538
1539 // Call f and g with break point on line 2.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540 int sbp2 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 2, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001541 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001542 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001543 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001544 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001545 CHECK_EQ(2, break_point_hit_count);
1546
1547 // Call f and g with break point on line 2, 4, 12, 14 and 15.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001548 int sbp3 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 4, 0);
1549 int sbp4 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 12, 0);
1550 int sbp5 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 14, 0);
1551 int sbp6 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 15, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001552 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001553 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001554 CHECK_EQ(2, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001555 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001556 CHECK_EQ(7, break_point_hit_count);
1557
1558 // Remove all the break points again.
1559 break_point_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001560 ClearBreakPointFromJS(env->GetIsolate(), sbp2);
1561 ClearBreakPointFromJS(env->GetIsolate(), sbp3);
1562 ClearBreakPointFromJS(env->GetIsolate(), sbp4);
1563 ClearBreakPointFromJS(env->GetIsolate(), sbp5);
1564 ClearBreakPointFromJS(env->GetIsolate(), sbp6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001565 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001566 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001567 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001568 CHECK_EQ(0, break_point_hit_count);
1569
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001570 v8::Debug::SetDebugEventListener(isolate, nullptr);
1571 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001572
1573 // Make sure that the break point numbers are consecutive.
1574 CHECK_EQ(1, sbp1);
1575 CHECK_EQ(2, sbp2);
1576 CHECK_EQ(3, sbp3);
1577 CHECK_EQ(4, sbp4);
1578 CHECK_EQ(5, sbp5);
1579 CHECK_EQ(6, sbp6);
1580}
1581
1582
1583// Test conditional script break points.
1584TEST(EnableDisableScriptBreakPoint) {
1585 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001586 DebugLocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001587 v8::Isolate* isolate = env->GetIsolate();
1588 v8::HandleScope scope(isolate);
1589 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001590 env.ExposeDebug();
1591
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001592 v8::Debug::SetDebugEventListener(isolate, DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00001593
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001594 v8::Local<v8::String> script = v8_str(isolate,
1595 "function f() {\n"
1596 " a = 0; // line 1\n"
1597 "};");
Steve Blocka7e24c12009-10-30 11:49:00 +00001598
1599 // Compile the script and get function f.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001600 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str(isolate, "test"));
1601 v8::Script::Compile(context, script, &origin)
1602 .ToLocalChecked()
1603 ->Run(context)
1604 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001605 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001606 env->Global()->Get(context, v8_str(isolate, "f")).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001607
1608 // Set script break point on line 1 (in function f).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001609 int sbp = SetScriptBreakPointByNameFromJS(isolate, "test", 1, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001610
1611 // Call f while enabeling and disabling the script break point.
1612 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001613 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001614 CHECK_EQ(1, break_point_hit_count);
1615
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616 DisableScriptBreakPointFromJS(isolate, sbp);
1617 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001618 CHECK_EQ(1, break_point_hit_count);
1619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001620 EnableScriptBreakPointFromJS(isolate, sbp);
1621 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001622 CHECK_EQ(2, break_point_hit_count);
1623
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001624 DisableScriptBreakPointFromJS(isolate, sbp);
1625 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001626 CHECK_EQ(2, break_point_hit_count);
1627
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001628 // Reload the script and get f again checking that the disabling survives.
1629 v8::Script::Compile(context, script, &origin)
1630 .ToLocalChecked()
1631 ->Run(context)
1632 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001633 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001634 env->Global()->Get(context, v8_str(isolate, "f")).ToLocalChecked());
1635 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001636 CHECK_EQ(2, break_point_hit_count);
1637
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001638 EnableScriptBreakPointFromJS(isolate, sbp);
1639 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001640 CHECK_EQ(3, break_point_hit_count);
1641
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001642 v8::Debug::SetDebugEventListener(isolate, nullptr);
1643 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001644}
1645
1646
1647// Test conditional script break points.
1648TEST(ConditionalScriptBreakPoint) {
1649 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001650 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001651 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001652 env.ExposeDebug();
1653
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001654 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1655 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00001656
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001657 v8::Local<v8::String> script = v8_str(env->GetIsolate(),
1658 "count = 0;\n"
1659 "function f() {\n"
1660 " g(count++); // line 2\n"
1661 "};\n"
1662 "function g(x) {\n"
1663 " var a=x; // line 5\n"
1664 "};");
Steve Blocka7e24c12009-10-30 11:49:00 +00001665
1666 // Compile the script and get function f.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001667 v8::Local<v8::Context> context = env.context();
1668 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str(env->GetIsolate(), "test"));
1669 v8::Script::Compile(context, script, &origin)
1670 .ToLocalChecked()
1671 ->Run(context)
1672 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001673 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001674 env->Global()
1675 ->Get(context, v8_str(env->GetIsolate(), "f"))
1676 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001677
1678 // Set script break point on line 5 (in function g).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001679 int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 5, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001680
1681 // Call f with different conditions on the script break point.
1682 break_point_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001683 ChangeScriptBreakPointConditionFromJS(env->GetIsolate(), sbp1, "false");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001684 f->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001685 CHECK_EQ(0, break_point_hit_count);
1686
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001687 ChangeScriptBreakPointConditionFromJS(env->GetIsolate(), sbp1, "true");
Steve Blocka7e24c12009-10-30 11:49:00 +00001688 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001689 f->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001690 CHECK_EQ(1, break_point_hit_count);
1691
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001692 ChangeScriptBreakPointConditionFromJS(env->GetIsolate(), sbp1, "x % 2 == 0");
Steve Blocka7e24c12009-10-30 11:49:00 +00001693 break_point_hit_count = 0;
1694 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001695 f->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001696 }
1697 CHECK_EQ(5, break_point_hit_count);
1698
1699 // Reload the script and get f again checking that the condition survives.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001700 v8::Script::Compile(context, script, &origin)
1701 .ToLocalChecked()
1702 ->Run(context)
1703 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001705 env->Global()
1706 ->Get(context, v8_str(env->GetIsolate(), "f"))
1707 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001708
1709 break_point_hit_count = 0;
1710 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001711 f->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001712 }
1713 CHECK_EQ(5, break_point_hit_count);
1714
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001715 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1716 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001717}
1718
1719
1720// Test ignore count on script break points.
1721TEST(ScriptBreakPointIgnoreCount) {
1722 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001723 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001724 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001725 env.ExposeDebug();
1726
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001727 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1728 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00001729
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001730 v8::Local<v8::String> script = v8_str(env->GetIsolate(),
1731 "function f() {\n"
1732 " a = 0; // line 1\n"
1733 "};");
Steve Blocka7e24c12009-10-30 11:49:00 +00001734
1735 // Compile the script and get function f.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001736 v8::Local<v8::Context> context = env.context();
1737 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str(env->GetIsolate(), "test"));
1738 v8::Script::Compile(context, script, &origin)
1739 .ToLocalChecked()
1740 ->Run(context)
1741 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001742 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001743 env->Global()
1744 ->Get(context, v8_str(env->GetIsolate(), "f"))
1745 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001746
1747 // Set script break point on line 1 (in function f).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001748 int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001749
1750 // Call f with different ignores on the script break point.
1751 break_point_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001752 ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001753 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001754 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001755 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001756 CHECK_EQ(1, break_point_hit_count);
1757
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001758 ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 5);
Steve Blocka7e24c12009-10-30 11:49:00 +00001759 break_point_hit_count = 0;
1760 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001761 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001762 }
1763 CHECK_EQ(5, break_point_hit_count);
1764
1765 // Reload the script and get f again checking that the ignore survives.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001766 v8::Script::Compile(context, script, &origin)
1767 .ToLocalChecked()
1768 ->Run(context)
1769 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001770 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001771 env->Global()
1772 ->Get(context, v8_str(env->GetIsolate(), "f"))
1773 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001774
1775 break_point_hit_count = 0;
1776 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001777 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001778 }
1779 CHECK_EQ(5, break_point_hit_count);
1780
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001781 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1782 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001783}
1784
1785
1786// Test that script break points survive when a script is reloaded.
1787TEST(ScriptBreakPointReload) {
1788 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001789 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001790 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001791 env.ExposeDebug();
1792
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001793 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1794 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00001795
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001796 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001797 v8::Local<v8::Function> f;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001798 v8::Local<v8::String> script = v8_str(env->GetIsolate(),
1799 "function f() {\n"
1800 " function h() {\n"
1801 " a = 0; // line 2\n"
1802 " }\n"
1803 " b = 1; // line 4\n"
1804 " return h();\n"
1805 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00001806
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001807 v8::ScriptOrigin origin_1 = v8::ScriptOrigin(v8_str(env->GetIsolate(), "1"));
1808 v8::ScriptOrigin origin_2 = v8::ScriptOrigin(v8_str(env->GetIsolate(), "2"));
Steve Blocka7e24c12009-10-30 11:49:00 +00001809
1810 // Set a script break point before the script is loaded.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001811 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "1", 2, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001812
1813 // Compile the script and get the function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001814 v8::Script::Compile(context, script, &origin_1)
1815 .ToLocalChecked()
1816 ->Run(context)
1817 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001818 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001819 env->Global()
1820 ->Get(context, v8_str(env->GetIsolate(), "f"))
1821 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001822
1823 // Call f and check that the script break point is active.
1824 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001825 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001826 CHECK_EQ(1, break_point_hit_count);
1827
1828 // Compile the script again with a different script data and get the
1829 // function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001830 v8::Script::Compile(context, script, &origin_2)
1831 .ToLocalChecked()
1832 ->Run(context)
1833 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001834 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001835 env->Global()
1836 ->Get(context, v8_str(env->GetIsolate(), "f"))
1837 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001838
1839 // Call f and check that no break points are set.
1840 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001841 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001842 CHECK_EQ(0, break_point_hit_count);
1843
1844 // Compile the script again and get the function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001845 v8::Script::Compile(context, script, &origin_1)
1846 .ToLocalChecked()
1847 ->Run(context)
1848 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001849 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001850 env->Global()
1851 ->Get(context, v8_str(env->GetIsolate(), "f"))
1852 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001853
1854 // Call f and check that the script break point is active.
1855 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001856 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001857 CHECK_EQ(1, break_point_hit_count);
1858
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001859 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1860 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001861}
1862
1863
1864// Test when several scripts has the same script data
1865TEST(ScriptBreakPointMultiple) {
1866 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001867 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001868 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001869 env.ExposeDebug();
1870
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001871 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1872 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00001873
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001874 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001875 v8::Local<v8::Function> f;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001876 v8::Local<v8::String> script_f = v8_str(env->GetIsolate(),
1877 "function f() {\n"
1878 " a = 0; // line 1\n"
1879 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00001880
1881 v8::Local<v8::Function> g;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001882 v8::Local<v8::String> script_g = v8_str(env->GetIsolate(),
1883 "function g() {\n"
1884 " b = 0; // line 1\n"
1885 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00001886
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001887 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str(env->GetIsolate(), "test"));
Steve Blocka7e24c12009-10-30 11:49:00 +00001888
1889 // Set a script break point before the scripts are loaded.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001890 int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001891
1892 // Compile the scripts with same script data and get the functions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001893 v8::Script::Compile(context, script_f, &origin)
1894 .ToLocalChecked()
1895 ->Run(context)
1896 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001897 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001898 env->Global()
1899 ->Get(context, v8_str(env->GetIsolate(), "f"))
1900 .ToLocalChecked());
1901 v8::Script::Compile(context, script_g, &origin)
1902 .ToLocalChecked()
1903 ->Run(context)
1904 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001905 g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001906 env->Global()
1907 ->Get(context, v8_str(env->GetIsolate(), "g"))
1908 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001909
1910 // Call f and g and check that the script break point is active.
1911 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001912 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001913 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001914 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001915 CHECK_EQ(2, break_point_hit_count);
1916
1917 // Clear the script break point.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001918 ClearBreakPointFromJS(env->GetIsolate(), sbp);
Steve Blocka7e24c12009-10-30 11:49:00 +00001919
1920 // Call f and g and check that the script break point is no longer active.
1921 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001922 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001923 CHECK_EQ(0, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001924 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001925 CHECK_EQ(0, break_point_hit_count);
1926
1927 // Set script break point with the scripts loaded.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001928 sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001929
1930 // Call f and g and check that the script break point is active.
1931 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001932 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001933 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001934 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001935 CHECK_EQ(2, break_point_hit_count);
1936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001937 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
1938 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001939}
1940
1941
1942// Test the script origin which has both name and line offset.
1943TEST(ScriptBreakPointLineOffset) {
1944 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00001945 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001946 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001947 env.ExposeDebug();
1948
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001949 v8::Debug::SetDebugEventListener(env->GetIsolate(),
1950 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00001951
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001952 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00001953 v8::Local<v8::Function> f;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001954 v8::Local<v8::String> script =
1955 v8_str(env->GetIsolate(),
1956 "function f() {\n"
1957 " a = 0; // line 8 as this script has line offset 7\n"
1958 " b = 0; // line 9 as this script has line offset 7\n"
1959 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00001960
1961 // Create script origin both name and line offset.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001962 v8::ScriptOrigin origin(v8_str(env->GetIsolate(), "test.html"),
1963 v8::Integer::New(env->GetIsolate(), 7));
Steve Blocka7e24c12009-10-30 11:49:00 +00001964
1965 // Set two script break points before the script is loaded.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001966 int sbp1 =
1967 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 8, 0);
1968 int sbp2 =
1969 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 9, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001970
1971 // Compile the script and get the function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001972 v8::Script::Compile(context, script, &origin)
1973 .ToLocalChecked()
1974 ->Run(context)
1975 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001976 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001977 env->Global()
1978 ->Get(context, v8_str(env->GetIsolate(), "f"))
1979 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001980
1981 // Call f and check that the script break point is active.
1982 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001983 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001984 CHECK_EQ(2, break_point_hit_count);
1985
1986 // Clear the script break points.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001987 ClearBreakPointFromJS(env->GetIsolate(), sbp1);
1988 ClearBreakPointFromJS(env->GetIsolate(), sbp2);
Steve Blocka7e24c12009-10-30 11:49:00 +00001989
1990 // Call f and check that no script break points are active.
1991 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001992 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001993 CHECK_EQ(0, break_point_hit_count);
1994
1995 // Set a script break point with the script loaded.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001996 sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 9, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001997
1998 // Call f and check that the script break point is active.
1999 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002000 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002001 CHECK_EQ(1, break_point_hit_count);
2002
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002003 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2004 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002005}
2006
2007
2008// Test script break points set on lines.
2009TEST(ScriptBreakPointLine) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002010 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002011 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002012 env.ExposeDebug();
2013
2014 // Create a function for checking the function when hitting a break point.
2015 frame_function_name = CompileFunction(&env,
2016 frame_function_name_source,
2017 "frame_function_name");
2018
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002019 v8::Debug::SetDebugEventListener(env->GetIsolate(),
2020 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00002021
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002022 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00002023 v8::Local<v8::Function> f;
2024 v8::Local<v8::Function> g;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002025 v8::Local<v8::String> script =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002026 v8_str(env->GetIsolate(),
2027 "a = 0 // line 0\n"
2028 "function f() {\n"
2029 " a = 1; // line 2\n"
2030 "}\n"
2031 " a = 2; // line 4\n"
2032 " /* xx */ function g() { // line 5\n"
2033 " function h() { // line 6\n"
2034 " a = 3; // line 7\n"
2035 " }\n"
2036 " h(); // line 9\n"
2037 " a = 4; // line 10\n"
2038 " }\n"
2039 " a=5; // line 12");
Steve Blocka7e24c12009-10-30 11:49:00 +00002040
2041 // Set a couple script break point before the script is loaded.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002042 int sbp1 =
2043 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 0, -1);
2044 int sbp2 =
2045 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 1, -1);
2046 int sbp3 =
2047 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 5, -1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002048
2049 // Compile the script and get the function.
2050 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002051 v8::ScriptOrigin origin(v8_str(env->GetIsolate(), "test.html"),
2052 v8::Integer::New(env->GetIsolate(), 0));
2053 v8::Script::Compile(context, script, &origin)
2054 .ToLocalChecked()
2055 ->Run(context)
2056 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002057 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002058 env->Global()
2059 ->Get(context, v8_str(env->GetIsolate(), "f"))
2060 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002061 g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002062 env->Global()
2063 ->Get(context, v8_str(env->GetIsolate(), "g"))
2064 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002065
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002066 // Check that a break point was hit when the script was run.
Steve Blocka7e24c12009-10-30 11:49:00 +00002067 CHECK_EQ(1, break_point_hit_count);
Steve Blockd0582a62009-12-15 09:54:21 +00002068 CHECK_EQ(0, StrLength(last_function_hit));
Steve Blocka7e24c12009-10-30 11:49:00 +00002069
2070 // Call f and check that the script break point.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002071 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002072 CHECK_EQ(2, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002073 CHECK_EQ(0, strcmp("f", last_function_hit));
Steve Blocka7e24c12009-10-30 11:49:00 +00002074
2075 // Call g and check that the script break point.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002076 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002077 CHECK_EQ(3, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002078 CHECK_EQ(0, strcmp("g", last_function_hit));
Steve Blocka7e24c12009-10-30 11:49:00 +00002079
2080 // Clear the script break point on g and set one on h.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002081 ClearBreakPointFromJS(env->GetIsolate(), sbp3);
2082 int sbp4 =
2083 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 6, -1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002084
2085 // Call g and check that the script break point in h is hit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002086 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002087 CHECK_EQ(4, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002088 CHECK_EQ(0, strcmp("h", last_function_hit));
Steve Blocka7e24c12009-10-30 11:49:00 +00002089
2090 // Clear break points in f and h. Set a new one in the script between
2091 // functions f and g and test that there is no break points in f and g any
2092 // more.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002093 ClearBreakPointFromJS(env->GetIsolate(), sbp2);
2094 ClearBreakPointFromJS(env->GetIsolate(), sbp4);
2095 int sbp5 =
2096 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 4, -1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002097 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002098 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
2099 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002100 CHECK_EQ(0, break_point_hit_count);
2101
2102 // Reload the script which should hit two break points.
2103 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002104 v8::Script::Compile(context, script, &origin)
2105 .ToLocalChecked()
2106 ->Run(context)
2107 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002108 CHECK_EQ(2, break_point_hit_count);
Steve Blockd0582a62009-12-15 09:54:21 +00002109 CHECK_EQ(0, StrLength(last_function_hit));
Steve Blocka7e24c12009-10-30 11:49:00 +00002110
2111 // Set a break point in the code after the last function decleration.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002112 int sbp6 =
2113 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 12, -1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002114
2115 // Reload the script which should hit three break points.
2116 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002117 v8::Script::Compile(context, script, &origin)
2118 .ToLocalChecked()
2119 ->Run(context)
2120 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002121 CHECK_EQ(3, break_point_hit_count);
Steve Blockd0582a62009-12-15 09:54:21 +00002122 CHECK_EQ(0, StrLength(last_function_hit));
Steve Blocka7e24c12009-10-30 11:49:00 +00002123
2124 // Clear the last break points, and reload the script which should not hit any
2125 // break points.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002126 ClearBreakPointFromJS(env->GetIsolate(), sbp1);
2127 ClearBreakPointFromJS(env->GetIsolate(), sbp5);
2128 ClearBreakPointFromJS(env->GetIsolate(), sbp6);
Steve Blocka7e24c12009-10-30 11:49:00 +00002129 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002130 v8::Script::Compile(context, script, &origin)
2131 .ToLocalChecked()
2132 ->Run(context)
2133 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002134 CHECK_EQ(0, break_point_hit_count);
2135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002136 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2137 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002138}
2139
2140
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002141// Test top level script break points set on lines.
2142TEST(ScriptBreakPointLineTopLevel) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002143 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002144 v8::HandleScope scope(env->GetIsolate());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002145 env.ExposeDebug();
2146
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002147 v8::Debug::SetDebugEventListener(env->GetIsolate(),
2148 DebugEventBreakPointHitCount);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002149
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002150 v8::Local<v8::Context> context = env.context();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002151 v8::Local<v8::String> script =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002152 v8_str(env->GetIsolate(),
2153 "function f() {\n"
2154 " a = 1; // line 1\n"
2155 "}\n"
2156 "a = 2; // line 3\n");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002157 v8::Local<v8::Function> f;
2158 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002159 v8::HandleScope scope(env->GetIsolate());
2160 CompileRunWithOrigin(script, "test.html");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002161 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002162 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002163 env->Global()
2164 ->Get(context, v8_str(env->GetIsolate(), "f"))
2165 .ToLocalChecked());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002166
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002167 CcTest::heap()->CollectAllGarbage();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002168
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002169 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002170
2171 // Call f and check that there was no break points.
2172 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002173 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002174 CHECK_EQ(0, break_point_hit_count);
2175
2176 // Recompile and run script and check that break point was hit.
2177 break_point_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002178 CompileRunWithOrigin(script, "test.html");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002179 CHECK_EQ(1, break_point_hit_count);
2180
2181 // Call f and check that there are still no break points.
2182 break_point_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002183 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002184 env->Global()
2185 ->Get(context, v8_str(env->GetIsolate(), "f"))
2186 .ToLocalChecked());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002187 CHECK_EQ(0, break_point_hit_count);
2188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002189 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2190 CheckDebuggerUnloaded(env->GetIsolate());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002191}
2192
2193
Steve Block8defd9f2010-07-08 12:39:36 +01002194// Test that it is possible to add and remove break points in a top level
2195// function which has no references but has not been collected yet.
2196TEST(ScriptBreakPointTopLevelCrash) {
Steve Block8defd9f2010-07-08 12:39:36 +01002197 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002198 v8::HandleScope scope(env->GetIsolate());
Steve Block8defd9f2010-07-08 12:39:36 +01002199 env.ExposeDebug();
2200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002201 v8::Debug::SetDebugEventListener(env->GetIsolate(),
2202 DebugEventBreakPointHitCount);
Steve Block8defd9f2010-07-08 12:39:36 +01002203
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002204 v8::Local<v8::String> script_source = v8_str(env->GetIsolate(),
2205 "function f() {\n"
2206 " return 0;\n"
2207 "}\n"
2208 "f()");
Steve Block8defd9f2010-07-08 12:39:36 +01002209
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002210 int sbp1 =
2211 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1);
Steve Block8defd9f2010-07-08 12:39:36 +01002212 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002213 v8::HandleScope scope(env->GetIsolate());
Steve Block8defd9f2010-07-08 12:39:36 +01002214 break_point_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002215 CompileRunWithOrigin(script_source, "test.html");
Steve Block8defd9f2010-07-08 12:39:36 +01002216 CHECK_EQ(1, break_point_hit_count);
2217 }
2218
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002219 int sbp2 =
2220 SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1);
2221 ClearBreakPointFromJS(env->GetIsolate(), sbp1);
2222 ClearBreakPointFromJS(env->GetIsolate(), sbp2);
Steve Block8defd9f2010-07-08 12:39:36 +01002223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002224 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2225 CheckDebuggerUnloaded(env->GetIsolate());
Steve Block8defd9f2010-07-08 12:39:36 +01002226}
2227
2228
Steve Blocka7e24c12009-10-30 11:49:00 +00002229// Test that it is possible to remove the last break point for a function
2230// inside the break handling of that break point.
2231TEST(RemoveBreakPointInBreak) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002232 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002233 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002234
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002235 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00002236 v8::Local<v8::Function> foo =
2237 CompileFunction(&env, "function foo(){a=1;}", "foo");
Steve Blocka7e24c12009-10-30 11:49:00 +00002238
2239 // Register the debug event listener pasing the function
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002240 v8::Debug::SetDebugEventListener(env->GetIsolate(),
2241 DebugEventRemoveBreakPoint, foo);
2242
2243 debug_event_remove_break_point = SetBreakPoint(foo, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002244
2245 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002246 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002247 CHECK_EQ(1, break_point_hit_count);
2248
2249 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002250 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002251 CHECK_EQ(0, break_point_hit_count);
2252
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002253 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2254 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002255}
2256
2257
2258// Test that the debugger statement causes a break.
2259TEST(DebuggerStatement) {
2260 break_point_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002261 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002262 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002263 v8::Debug::SetDebugEventListener(env->GetIsolate(),
2264 DebugEventBreakPointHitCount);
2265 v8::Local<v8::Context> context = env.context();
2266 v8::Script::Compile(context,
2267 v8_str(env->GetIsolate(), "function bar(){debugger}"))
2268 .ToLocalChecked()
2269 ->Run(context)
2270 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002271 v8::Script::Compile(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002272 context, v8_str(env->GetIsolate(), "function foo(){debugger;debugger;}"))
2273 .ToLocalChecked()
2274 ->Run(context)
2275 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002276 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002277 env->Global()
2278 ->Get(context, v8_str(env->GetIsolate(), "foo"))
2279 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002280 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002281 env->Global()
2282 ->Get(context, v8_str(env->GetIsolate(), "bar"))
2283 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002284
2285 // Run function with debugger statement
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002286 bar->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002287 CHECK_EQ(1, break_point_hit_count);
2288
2289 // Run function with two debugger statement
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002290 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002291 CHECK_EQ(3, break_point_hit_count);
2292
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002293 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2294 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002295}
2296
2297
Steve Block8defd9f2010-07-08 12:39:36 +01002298// Test setting a breakpoint on the debugger statement.
Leon Clarke4515c472010-02-03 11:58:03 +00002299TEST(DebuggerStatementBreakpoint) {
2300 break_point_hit_count = 0;
Leon Clarke4515c472010-02-03 11:58:03 +00002301 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002302 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002303 v8::Local<v8::Context> context = env.context();
2304 v8::Debug::SetDebugEventListener(env->GetIsolate(),
2305 DebugEventBreakPointHitCount);
2306 v8::Script::Compile(context,
2307 v8_str(env->GetIsolate(), "function foo(){debugger;}"))
2308 .ToLocalChecked()
2309 ->Run(context)
2310 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002311 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002312 env->Global()
2313 ->Get(context, v8_str(env->GetIsolate(), "foo"))
2314 .ToLocalChecked());
Leon Clarke4515c472010-02-03 11:58:03 +00002315
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002316 // The debugger statement triggers breakpoint hit
2317 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Leon Clarke4515c472010-02-03 11:58:03 +00002318 CHECK_EQ(1, break_point_hit_count);
2319
2320 int bp = SetBreakPoint(foo, 0);
2321
2322 // Set breakpoint does not duplicate hits
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002323 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Leon Clarke4515c472010-02-03 11:58:03 +00002324 CHECK_EQ(2, break_point_hit_count);
2325
2326 ClearBreakPoint(bp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002327 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2328 CheckDebuggerUnloaded(env->GetIsolate());
Leon Clarke4515c472010-02-03 11:58:03 +00002329}
2330
2331
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002332// Test that the evaluation of expressions when a break point is hit generates
Steve Blocka7e24c12009-10-30 11:49:00 +00002333// the correct results.
2334TEST(DebugEvaluate) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002335 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002336 v8::Isolate* isolate = env->GetIsolate();
2337 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002338 env.ExposeDebug();
2339
2340 // Create a function for checking the evaluation when hitting a break point.
2341 evaluate_check_function = CompileFunction(&env,
2342 evaluate_check_source,
2343 "evaluate_check");
2344 // Register the debug event listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002345 v8::Debug::SetDebugEventListener(isolate, DebugEventEvaluate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002346
2347 // Different expected vaules of x and a when in a break point (u = undefined,
2348 // d = Hello, world!).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002349 struct EvaluateCheck checks_uu[] = {{"x", v8::Undefined(isolate)},
2350 {"a", v8::Undefined(isolate)},
2351 {NULL, v8::Local<v8::Value>()}};
Steve Blocka7e24c12009-10-30 11:49:00 +00002352 struct EvaluateCheck checks_hu[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002353 {"x", v8_str(env->GetIsolate(), "Hello, world!")},
2354 {"a", v8::Undefined(isolate)},
2355 {NULL, v8::Local<v8::Value>()}};
Steve Blocka7e24c12009-10-30 11:49:00 +00002356 struct EvaluateCheck checks_hh[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002357 {"x", v8_str(env->GetIsolate(), "Hello, world!")},
2358 {"a", v8_str(env->GetIsolate(), "Hello, world!")},
2359 {NULL, v8::Local<v8::Value>()}};
Steve Blocka7e24c12009-10-30 11:49:00 +00002360
2361 // Simple test function. The "y=0" is in the function foo to provide a break
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002362 // location. For "y=0" the "y" is at position 15 in the foo function
Steve Blocka7e24c12009-10-30 11:49:00 +00002363 // therefore setting breakpoint at position 15 will break at "y=0" and
2364 // setting it higher will break after.
2365 v8::Local<v8::Function> foo = CompileFunction(&env,
2366 "function foo(x) {"
2367 " var a;"
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002368 " y=0;" // To ensure break location 1.
Steve Blocka7e24c12009-10-30 11:49:00 +00002369 " a=x;"
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002370 " y=0;" // To ensure break location 2.
Steve Blocka7e24c12009-10-30 11:49:00 +00002371 "}",
2372 "foo");
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002373 const int foo_break_position_1 = 15;
2374 const int foo_break_position_2 = 29;
Steve Blocka7e24c12009-10-30 11:49:00 +00002375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002376 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00002377 // Arguments with one parameter "Hello, world!"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002378 v8::Local<v8::Value> argv_foo[1] = {
2379 v8_str(env->GetIsolate(), "Hello, world!")};
Steve Blocka7e24c12009-10-30 11:49:00 +00002380
2381 // Call foo with breakpoint set before a=x and undefined as parameter.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002382 int bp = SetBreakPoint(foo, foo_break_position_1);
Steve Blocka7e24c12009-10-30 11:49:00 +00002383 checks = checks_uu;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002384 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002385
2386 // Call foo with breakpoint set before a=x and parameter "Hello, world!".
2387 checks = checks_hu;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002388 foo->Call(context, env->Global(), 1, argv_foo).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002389
2390 // Call foo with breakpoint set after a=x and parameter "Hello, world!".
2391 ClearBreakPoint(bp);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002392 SetBreakPoint(foo, foo_break_position_2);
Steve Blocka7e24c12009-10-30 11:49:00 +00002393 checks = checks_hh;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002394 foo->Call(context, env->Global(), 1, argv_foo).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002395
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002396 // Test that overriding Object.prototype will not interfere into evaluation
2397 // on call frame.
2398 v8::Local<v8::Function> zoo =
2399 CompileFunction(&env,
2400 "x = undefined;"
2401 "function zoo(t) {"
2402 " var a=x;"
2403 " Object.prototype.x = 42;"
2404 " x=t;"
2405 " y=0;" // To ensure break location.
2406 " delete Object.prototype.x;"
2407 " x=a;"
2408 "}",
2409 "zoo");
2410 const int zoo_break_position = 50;
2411
2412 // Arguments with one parameter "Hello, world!"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002413 v8::Local<v8::Value> argv_zoo[1] = {
2414 v8_str(env->GetIsolate(), "Hello, world!")};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002415
2416 // Call zoo with breakpoint set at y=0.
2417 DebugEventCounterClear();
2418 bp = SetBreakPoint(zoo, zoo_break_position);
2419 checks = checks_hu;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002420 zoo->Call(context, env->Global(), 1, argv_zoo).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002421 CHECK_EQ(1, break_point_hit_count);
2422 ClearBreakPoint(bp);
2423
Steve Blocka7e24c12009-10-30 11:49:00 +00002424 // Test function with an inner function. The "y=0" is in function barbar
2425 // to provide a break location. For "y=0" the "y" is at position 8 in the
2426 // barbar function therefore setting breakpoint at position 8 will break at
2427 // "y=0" and setting it higher will break after.
2428 v8::Local<v8::Function> bar = CompileFunction(&env,
2429 "y = 0;"
2430 "x = 'Goodbye, world!';"
2431 "function bar(x, b) {"
2432 " var a;"
2433 " function barbar() {"
2434 " y=0; /* To ensure break location.*/"
2435 " a=x;"
2436 " };"
2437 " debug.Debug.clearAllBreakPoints();"
2438 " barbar();"
2439 " y=0;a=x;"
2440 "}",
2441 "bar");
2442 const int barbar_break_position = 8;
2443
2444 // Call bar setting breakpoint before a=x in barbar and undefined as
2445 // parameter.
2446 checks = checks_uu;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002447 v8::Local<v8::Value> argv_bar_1[2] = {
2448 v8::Undefined(isolate), v8::Number::New(isolate, barbar_break_position)};
2449 bar->Call(context, env->Global(), 2, argv_bar_1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002450
2451 // Call bar setting breakpoint before a=x in barbar and parameter
2452 // "Hello, world!".
2453 checks = checks_hu;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002454 v8::Local<v8::Value> argv_bar_2[2] = {
2455 v8_str(env->GetIsolate(), "Hello, world!"),
2456 v8::Number::New(env->GetIsolate(), barbar_break_position)};
2457 bar->Call(context, env->Global(), 2, argv_bar_2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002458
2459 // Call bar setting breakpoint after a=x in barbar and parameter
2460 // "Hello, world!".
2461 checks = checks_hh;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002462 v8::Local<v8::Value> argv_bar_3[2] = {
2463 v8_str(env->GetIsolate(), "Hello, world!"),
2464 v8::Number::New(env->GetIsolate(), barbar_break_position + 1)};
2465 bar->Call(context, env->Global(), 2, argv_bar_3).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002466
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002467 v8::Debug::SetDebugEventListener(isolate, nullptr);
2468 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002469}
2470
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002471
2472int debugEventCount = 0;
2473static void CheckDebugEvent(const v8::Debug::EventDetails& eventDetails) {
2474 if (eventDetails.GetEvent() == v8::Break) ++debugEventCount;
2475}
2476
2477
2478// Test that the conditional breakpoints work event if code generation from
2479// strings is prohibited in the debugee context.
2480TEST(ConditionalBreakpointWithCodeGenerationDisallowed) {
2481 DebugLocalContext env;
2482 v8::HandleScope scope(env->GetIsolate());
2483 env.ExposeDebug();
2484
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002485 v8::Debug::SetDebugEventListener(env->GetIsolate(), CheckDebugEvent);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002486
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002487 v8::Local<v8::Context> context = env.context();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002488 v8::Local<v8::Function> foo = CompileFunction(&env,
2489 "function foo(x) {\n"
2490 " var s = 'String value2';\n"
2491 " return s + x;\n"
2492 "}",
2493 "foo");
2494
2495 // Set conditional breakpoint with condition 'true'.
2496 CompileRun("debug.Debug.setBreakPoint(foo, 2, 0, 'true')");
2497
2498 debugEventCount = 0;
2499 env->AllowCodeGenerationFromStrings(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002500 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002501 CHECK_EQ(1, debugEventCount);
2502
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002503 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2504 CheckDebuggerUnloaded(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002505}
2506
2507
2508bool checkedDebugEvals = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002509v8::Local<v8::Function> checkGlobalEvalFunction;
2510v8::Local<v8::Function> checkFrameEvalFunction;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002511static void CheckDebugEval(const v8::Debug::EventDetails& eventDetails) {
2512 if (eventDetails.GetEvent() == v8::Break) {
2513 ++debugEventCount;
2514 v8::HandleScope handleScope(CcTest::isolate());
2515
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002516 v8::Local<v8::Value> args[] = {eventDetails.GetExecutionState()};
2517 CHECK(
2518 checkGlobalEvalFunction->Call(eventDetails.GetEventContext(),
2519 eventDetails.GetEventContext()->Global(),
2520 1, args)
2521 .ToLocalChecked()
2522 ->IsTrue());
2523 CHECK(checkFrameEvalFunction->Call(eventDetails.GetEventContext(),
2524 eventDetails.GetEventContext()->Global(),
2525 1, args)
2526 .ToLocalChecked()
2527 ->IsTrue());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002528 }
2529}
2530
2531
2532// Test that the evaluation of expressions when a break point is hit generates
2533// the correct results in case code generation from strings is disallowed in the
2534// debugee context.
2535TEST(DebugEvaluateWithCodeGenerationDisallowed) {
2536 DebugLocalContext env;
2537 v8::HandleScope scope(env->GetIsolate());
2538 env.ExposeDebug();
2539
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002540 v8::Debug::SetDebugEventListener(env->GetIsolate(), CheckDebugEval);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002541
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002542 v8::Local<v8::Context> context = env.context();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002543 v8::Local<v8::Function> foo = CompileFunction(&env,
2544 "var global = 'Global';\n"
2545 "function foo(x) {\n"
2546 " var local = 'Local';\n"
2547 " debugger;\n"
2548 " return local + x;\n"
2549 "}",
2550 "foo");
2551 checkGlobalEvalFunction = CompileFunction(&env,
2552 "function checkGlobalEval(exec_state) {\n"
2553 " return exec_state.evaluateGlobal('global').value() === 'Global';\n"
2554 "}",
2555 "checkGlobalEval");
2556
2557 checkFrameEvalFunction = CompileFunction(&env,
2558 "function checkFrameEval(exec_state) {\n"
2559 " return exec_state.frame(0).evaluate('local').value() === 'Local';\n"
2560 "}",
2561 "checkFrameEval");
2562 debugEventCount = 0;
2563 env->AllowCodeGenerationFromStrings(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002564 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002565 CHECK_EQ(1, debugEventCount);
2566
2567 checkGlobalEvalFunction.Clear();
2568 checkFrameEvalFunction.Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002569 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2570 CheckDebuggerUnloaded(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002571}
2572
2573
Leon Clarkee46be812010-01-19 14:06:41 +00002574// Copies a C string to a 16-bit string. Does not check for buffer overflow.
2575// Does not use the V8 engine to convert strings, so it can be used
2576// in any thread. Returns the length of the string.
2577int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
2578 int i;
2579 for (i = 0; input_buffer[i] != '\0'; ++i) {
2580 // ASCII does not use chars > 127, but be careful anyway.
2581 output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
2582 }
2583 output_buffer[i] = 0;
2584 return i;
2585}
2586
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002587
Leon Clarkee46be812010-01-19 14:06:41 +00002588// Copies a 16-bit string to a C string by dropping the high byte of
2589// each character. Does not check for buffer overflow.
2590// Can be used in any thread. Requires string length as an input.
2591int Utf16ToAscii(const uint16_t* input_buffer, int length,
2592 char* output_buffer, int output_len = -1) {
2593 if (output_len >= 0) {
2594 if (length > output_len - 1) {
2595 length = output_len - 1;
2596 }
2597 }
2598
2599 for (int i = 0; i < length; ++i) {
2600 output_buffer[i] = static_cast<char>(input_buffer[i]);
2601 }
2602 output_buffer[length] = '\0';
2603 return length;
2604}
2605
2606
2607// We match parts of the message to get evaluate result int value.
2608bool GetEvaluateStringResult(char *message, char* buffer, int buffer_size) {
Leon Clarked91b9f72010-01-27 17:25:45 +00002609 if (strstr(message, "\"command\":\"evaluate\"") == NULL) {
2610 return false;
2611 }
2612 const char* prefix = "\"text\":\"";
2613 char* pos1 = strstr(message, prefix);
2614 if (pos1 == NULL) {
2615 return false;
2616 }
2617 pos1 += strlen(prefix);
2618 char* pos2 = strchr(pos1, '"');
2619 if (pos2 == NULL) {
Leon Clarkee46be812010-01-19 14:06:41 +00002620 return false;
2621 }
2622 Vector<char> buf(buffer, buffer_size);
Leon Clarked91b9f72010-01-27 17:25:45 +00002623 int len = static_cast<int>(pos2 - pos1);
2624 if (len > buffer_size - 1) {
2625 len = buffer_size - 1;
2626 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002627 StrNCpy(buf, pos1, len);
Leon Clarkee46be812010-01-19 14:06:41 +00002628 buffer[buffer_size - 1] = '\0';
2629 return true;
2630}
2631
2632
2633struct EvaluateResult {
2634 static const int kBufferSize = 20;
2635 char buffer[kBufferSize];
2636};
2637
2638struct DebugProcessDebugMessagesData {
2639 static const int kArraySize = 5;
2640 int counter;
2641 EvaluateResult results[kArraySize];
2642
2643 void reset() {
2644 counter = 0;
2645 }
2646 EvaluateResult* current() {
2647 return &results[counter % kArraySize];
2648 }
2649 void next() {
2650 counter++;
2651 }
2652};
2653
2654DebugProcessDebugMessagesData process_debug_messages_data;
2655
2656static void DebugProcessDebugMessagesHandler(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002657 const v8::Debug::Message& message) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002658 v8::Local<v8::String> json = message.GetJSON();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002659 v8::String::Utf8Value utf8(json);
Leon Clarkee46be812010-01-19 14:06:41 +00002660 EvaluateResult* array_item = process_debug_messages_data.current();
2661
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002662 bool res = GetEvaluateStringResult(*utf8,
Leon Clarkee46be812010-01-19 14:06:41 +00002663 array_item->buffer,
2664 EvaluateResult::kBufferSize);
2665 if (res) {
2666 process_debug_messages_data.next();
2667 }
2668}
2669
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002670
Leon Clarkee46be812010-01-19 14:06:41 +00002671// Test that the evaluation of expressions works even from ProcessDebugMessages
2672// i.e. with empty stack.
2673TEST(DebugEvaluateWithoutStack) {
Leon Clarkee46be812010-01-19 14:06:41 +00002674 DebugLocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002675 v8::Debug::SetMessageHandler(env->GetIsolate(),
2676 DebugProcessDebugMessagesHandler);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002677 v8::HandleScope scope(env->GetIsolate());
Leon Clarkee46be812010-01-19 14:06:41 +00002678
2679 const char* source =
2680 "var v1 = 'Pinguin';\n function getAnimal() { return 'Capy' + 'bara'; }";
2681
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002682 v8::Local<v8::Context> context = env.context();
2683 v8::Script::Compile(context, v8_str(env->GetIsolate(), source))
2684 .ToLocalChecked()
2685 ->Run(context)
2686 .ToLocalChecked();
Leon Clarkee46be812010-01-19 14:06:41 +00002687
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002688 v8::Debug::ProcessDebugMessages(env->GetIsolate());
Leon Clarkee46be812010-01-19 14:06:41 +00002689
2690 const int kBufferSize = 1000;
2691 uint16_t buffer[kBufferSize];
2692
2693 const char* command_111 = "{\"seq\":111,"
2694 "\"type\":\"request\","
2695 "\"command\":\"evaluate\","
2696 "\"arguments\":{"
2697 " \"global\":true,"
2698 " \"expression\":\"v1\",\"disable_break\":true"
2699 "}}";
2700
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002701 v8::Isolate* isolate = CcTest::isolate();
2702 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_111, buffer));
Leon Clarkee46be812010-01-19 14:06:41 +00002703
2704 const char* command_112 = "{\"seq\":112,"
2705 "\"type\":\"request\","
2706 "\"command\":\"evaluate\","
2707 "\"arguments\":{"
2708 " \"global\":true,"
2709 " \"expression\":\"getAnimal()\",\"disable_break\":true"
2710 "}}";
2711
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002712 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_112, buffer));
Leon Clarkee46be812010-01-19 14:06:41 +00002713
2714 const char* command_113 = "{\"seq\":113,"
2715 "\"type\":\"request\","
2716 "\"command\":\"evaluate\","
2717 "\"arguments\":{"
2718 " \"global\":true,"
2719 " \"expression\":\"239 + 566\",\"disable_break\":true"
2720 "}}";
2721
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002722 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_113, buffer));
Leon Clarkee46be812010-01-19 14:06:41 +00002723
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002724 v8::Debug::ProcessDebugMessages(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00002725
2726 CHECK_EQ(3, process_debug_messages_data.counter);
2727
Leon Clarked91b9f72010-01-27 17:25:45 +00002728 CHECK_EQ(strcmp("Pinguin", process_debug_messages_data.results[0].buffer), 0);
2729 CHECK_EQ(strcmp("Capybara", process_debug_messages_data.results[1].buffer),
2730 0);
2731 CHECK_EQ(strcmp("805", process_debug_messages_data.results[2].buffer), 0);
Leon Clarkee46be812010-01-19 14:06:41 +00002732
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002733 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
2734 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2735 CheckDebuggerUnloaded(env->GetIsolate());
Leon Clarkee46be812010-01-19 14:06:41 +00002736}
2737
Steve Blocka7e24c12009-10-30 11:49:00 +00002738
2739// Simple test of the stepping mechanism using only store ICs.
2740TEST(DebugStepLinear) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002741 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002742 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002743
2744 // Create a function for testing stepping.
2745 v8::Local<v8::Function> foo = CompileFunction(&env,
2746 "function foo(){a=1;b=1;c=1;}",
2747 "foo");
Ben Murdochb0fe1622011-05-05 13:52:32 +01002748
2749 // Run foo to allow it to get optimized.
2750 CompileRun("a=0; b=0; c=0; foo();");
2751
Steve Blocka7e24c12009-10-30 11:49:00 +00002752 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002753 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
2754
2755 SetBreakPoint(foo, 3);
Steve Blocka7e24c12009-10-30 11:49:00 +00002756
2757 step_action = StepIn;
2758 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002759 v8::Local<v8::Context> context = env.context();
2760 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002761
2762 // With stepping all break locations are hit.
2763 CHECK_EQ(4, break_point_hit_count);
2764
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002765 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2766 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002767
2768 // Register a debug event listener which just counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002769 v8::Debug::SetDebugEventListener(env->GetIsolate(),
2770 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00002771
2772 SetBreakPoint(foo, 3);
2773 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002774 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002775
2776 // Without stepping only active break points are hit.
2777 CHECK_EQ(1, break_point_hit_count);
2778
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002779 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2780 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002781}
2782
2783
2784// Test of the stepping mechanism for keyed load in a loop.
2785TEST(DebugStepKeyedLoadLoop) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002786 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002787 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002788
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002789 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002790 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002791
Steve Blocka7e24c12009-10-30 11:49:00 +00002792 // Create a function for testing stepping of keyed load. The statement 'y=1'
2793 // is there to have more than one breakable statement in the loop, TODO(315).
2794 v8::Local<v8::Function> foo = CompileFunction(
2795 &env,
2796 "function foo(a) {\n"
2797 " var x;\n"
2798 " var len = a.length;\n"
2799 " for (var i = 0; i < len; i++) {\n"
2800 " y = 1;\n"
2801 " x = a[i];\n"
2802 " }\n"
Ben Murdochb0fe1622011-05-05 13:52:32 +01002803 "}\n"
2804 "y=0\n",
Steve Blocka7e24c12009-10-30 11:49:00 +00002805 "foo");
2806
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002807 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00002808 // Create array [0,1,2,3,4,5,6,7,8,9]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002809 v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
Steve Blocka7e24c12009-10-30 11:49:00 +00002810 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002811 CHECK(a->Set(context, v8::Number::New(env->GetIsolate(), i),
2812 v8::Number::New(env->GetIsolate(), i))
2813 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002814 }
2815
2816 // Call function without any break points to ensure inlining is in place.
2817 const int kArgc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002818 v8::Local<v8::Value> args[kArgc] = {a};
2819 foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002820
2821 // Set up break point and step through the function.
2822 SetBreakPoint(foo, 3);
2823 step_action = StepNext;
2824 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002825 foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002826
2827 // With stepping all break locations are hit.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002828 CHECK_EQ(45, break_point_hit_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002829
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002830 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2831 CheckDebuggerUnloaded(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002832}
2833
2834
2835// Test of the stepping mechanism for keyed store in a loop.
2836TEST(DebugStepKeyedStoreLoop) {
2837 DebugLocalContext env;
2838 v8::HandleScope scope(env->GetIsolate());
2839
2840 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002841 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002842
2843 // Create a function for testing stepping of keyed store. The statement 'y=1'
2844 // is there to have more than one breakable statement in the loop, TODO(315).
2845 v8::Local<v8::Function> foo = CompileFunction(
2846 &env,
2847 "function foo(a) {\n"
2848 " var len = a.length;\n"
2849 " for (var i = 0; i < len; i++) {\n"
2850 " y = 1;\n"
2851 " a[i] = 42;\n"
2852 " }\n"
2853 "}\n"
2854 "y=0\n",
2855 "foo");
2856
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002857 v8::Local<v8::Context> context = env.context();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002858 // Create array [0,1,2,3,4,5,6,7,8,9]
2859 v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
2860 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002861 CHECK(a->Set(context, v8::Number::New(env->GetIsolate(), i),
2862 v8::Number::New(env->GetIsolate(), i))
2863 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002864 }
2865
2866 // Call function without any break points to ensure inlining is in place.
2867 const int kArgc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002868 v8::Local<v8::Value> args[kArgc] = {a};
2869 foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002870
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002871 // Set up break point and step through the function.
Steve Blocka7e24c12009-10-30 11:49:00 +00002872 SetBreakPoint(foo, 3);
2873 step_action = StepNext;
2874 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002875 foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002876
2877 // With stepping all break locations are hit.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002878 CHECK_EQ(44, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00002879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002880 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2881 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002882}
2883
2884
Kristian Monsen25f61362010-05-21 11:50:48 +01002885// Test of the stepping mechanism for named load in a loop.
2886TEST(DebugStepNamedLoadLoop) {
Kristian Monsen25f61362010-05-21 11:50:48 +01002887 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002888 v8::HandleScope scope(env->GetIsolate());
Kristian Monsen25f61362010-05-21 11:50:48 +01002889
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002890 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002891 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002892
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002893 v8::Local<v8::Context> context = env.context();
Kristian Monsen25f61362010-05-21 11:50:48 +01002894 // Create a function for testing stepping of named load.
2895 v8::Local<v8::Function> foo = CompileFunction(
2896 &env,
2897 "function foo() {\n"
2898 " var a = [];\n"
2899 " var s = \"\";\n"
2900 " for (var i = 0; i < 10; i++) {\n"
2901 " var v = new V(i, i + 1);\n"
2902 " v.y;\n"
2903 " a.length;\n" // Special case: array length.
2904 " s.length;\n" // Special case: string length.
2905 " }\n"
2906 "}\n"
2907 "function V(x, y) {\n"
2908 " this.x = x;\n"
2909 " this.y = y;\n"
2910 "}\n",
2911 "foo");
2912
2913 // Call function without any break points to ensure inlining is in place.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002914 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Kristian Monsen25f61362010-05-21 11:50:48 +01002915
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002916 // Set up break point and step through the function.
Kristian Monsen25f61362010-05-21 11:50:48 +01002917 SetBreakPoint(foo, 4);
2918 step_action = StepNext;
2919 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002920 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Kristian Monsen25f61362010-05-21 11:50:48 +01002921
2922 // With stepping all break locations are hit.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002923 CHECK_EQ(65, break_point_hit_count);
Kristian Monsen25f61362010-05-21 11:50:48 +01002924
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002925 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2926 CheckDebuggerUnloaded(env->GetIsolate());
Kristian Monsen25f61362010-05-21 11:50:48 +01002927}
2928
2929
Ben Murdochb0fe1622011-05-05 13:52:32 +01002930static void DoDebugStepNamedStoreLoop(int expected) {
Iain Merrick75681382010-08-19 15:07:18 +01002931 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002932 v8::HandleScope scope(env->GetIsolate());
Iain Merrick75681382010-08-19 15:07:18 +01002933
Ben Murdochb0fe1622011-05-05 13:52:32 +01002934 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002935 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Iain Merrick75681382010-08-19 15:07:18 +01002936
2937 // Create a function for testing stepping of named store.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002938 v8::Local<v8::Context> context = env.context();
Iain Merrick75681382010-08-19 15:07:18 +01002939 v8::Local<v8::Function> foo = CompileFunction(
2940 &env,
2941 "function foo() {\n"
2942 " var a = {a:1};\n"
2943 " for (var i = 0; i < 10; i++) {\n"
2944 " a.a = 2\n"
2945 " }\n"
2946 "}\n",
2947 "foo");
2948
2949 // Call function without any break points to ensure inlining is in place.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002950 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Iain Merrick75681382010-08-19 15:07:18 +01002951
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002952 // Set up break point and step through the function.
Iain Merrick75681382010-08-19 15:07:18 +01002953 SetBreakPoint(foo, 3);
2954 step_action = StepNext;
2955 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002956 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Iain Merrick75681382010-08-19 15:07:18 +01002957
2958 // With stepping all expected break locations are hit.
2959 CHECK_EQ(expected, break_point_hit_count);
2960
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002961 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2962 CheckDebuggerUnloaded(env->GetIsolate());
Iain Merrick75681382010-08-19 15:07:18 +01002963}
2964
2965
2966// Test of the stepping mechanism for named load in a loop.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002967TEST(DebugStepNamedStoreLoop) { DoDebugStepNamedStoreLoop(34); }
Iain Merrick75681382010-08-19 15:07:18 +01002968
2969
Steve Blocka7e24c12009-10-30 11:49:00 +00002970// Test the stepping mechanism with different ICs.
2971TEST(DebugStepLinearMixedICs) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002972 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002973 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002974
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002975 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002976 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002977
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002978 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00002979 // Create a function for testing stepping.
2980 v8::Local<v8::Function> foo = CompileFunction(&env,
2981 "function bar() {};"
2982 "function foo() {"
2983 " var x;"
2984 " var index='name';"
2985 " var y = {};"
2986 " a=1;b=2;x=a;y[index]=3;x=y[index];bar();}", "foo");
Ben Murdochb0fe1622011-05-05 13:52:32 +01002987
2988 // Run functions to allow them to get optimized.
2989 CompileRun("a=0; b=0; bar(); foo();");
2990
Steve Blocka7e24c12009-10-30 11:49:00 +00002991 SetBreakPoint(foo, 0);
2992
Steve Blocka7e24c12009-10-30 11:49:00 +00002993 step_action = StepIn;
2994 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002995 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002996
2997 // With stepping all break locations are hit.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002998 CHECK_EQ(11, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00002999
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003000 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3001 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003002
3003 // Register a debug event listener which just counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003004 v8::Debug::SetDebugEventListener(env->GetIsolate(),
3005 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00003006
3007 SetBreakPoint(foo, 0);
3008 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003009 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00003010
3011 // Without stepping only active break points are hit.
3012 CHECK_EQ(1, break_point_hit_count);
3013
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003014 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3015 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003016}
3017
3018
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003019TEST(DebugStepDeclarations) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003020 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003021 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003022
3023 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003024 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003025
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003026 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003027 // Create a function for testing stepping. Run it to allow it to get
3028 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003029 const char* src = "function foo() { "
3030 " var a;"
3031 " var b = 1;"
3032 " var c = foo;"
3033 " var d = Math.floor;"
3034 " var e = b + d(1.2);"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003035 "}"
3036 "foo()";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003037 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
Ben Murdochb0fe1622011-05-05 13:52:32 +01003038
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003039 SetBreakPoint(foo, 0);
3040
3041 // Stepping through the declarations.
3042 step_action = StepIn;
3043 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003044 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003045 CHECK_EQ(6, break_point_hit_count);
3046
3047 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003048 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3049 CheckDebuggerUnloaded(env->GetIsolate());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003050}
3051
3052
3053TEST(DebugStepLocals) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003054 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003055 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003056
3057 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003058 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003059
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003060 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003061 // Create a function for testing stepping. Run it to allow it to get
3062 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003063 const char* src = "function foo() { "
3064 " var a,b;"
3065 " a = 1;"
3066 " b = a + 2;"
3067 " b = 1 + 2 + 3;"
3068 " a = Math.floor(b);"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003069 "}"
3070 "foo()";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003071 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
Ben Murdochb0fe1622011-05-05 13:52:32 +01003072
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003073 SetBreakPoint(foo, 0);
3074
3075 // Stepping through the declarations.
3076 step_action = StepIn;
3077 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003078 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003079 CHECK_EQ(6, break_point_hit_count);
3080
3081 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003082 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3083 CheckDebuggerUnloaded(env->GetIsolate());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003084}
3085
3086
Steve Blocka7e24c12009-10-30 11:49:00 +00003087TEST(DebugStepIf) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003088 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003089 v8::Isolate* isolate = env->GetIsolate();
3090 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003091
3092 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003093 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Steve Blocka7e24c12009-10-30 11:49:00 +00003094
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003095 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003096 // Create a function for testing stepping. Run it to allow it to get
3097 // optimized.
Steve Blocka7e24c12009-10-30 11:49:00 +00003098 const int argc = 1;
3099 const char* src = "function foo(x) { "
3100 " a = 1;"
3101 " if (x) {"
3102 " b = 1;"
3103 " } else {"
3104 " c = 1;"
3105 " d = 1;"
3106 " }"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003107 "}"
3108 "a=0; b=0; c=0; d=0; foo()";
Steve Blocka7e24c12009-10-30 11:49:00 +00003109 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3110 SetBreakPoint(foo, 0);
3111
3112 // Stepping through the true part.
3113 step_action = StepIn;
3114 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003115 v8::Local<v8::Value> argv_true[argc] = {v8::True(isolate)};
3116 foo->Call(context, env->Global(), argc, argv_true).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003117 CHECK_EQ(4, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003118
3119 // Stepping through the false part.
3120 step_action = StepIn;
3121 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003122 v8::Local<v8::Value> argv_false[argc] = {v8::False(isolate)};
3123 foo->Call(context, env->Global(), argc, argv_false).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003124 CHECK_EQ(5, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003125
3126 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003127 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3128 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003129}
3130
3131
3132TEST(DebugStepSwitch) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003133 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003134 v8::Isolate* isolate = env->GetIsolate();
3135 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003136
3137 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003138 v8::Debug::SetDebugEventListener(isolate, DebugEventStep);
Steve Blocka7e24c12009-10-30 11:49:00 +00003139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003140 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003141 // Create a function for testing stepping. Run it to allow it to get
3142 // optimized.
Steve Blocka7e24c12009-10-30 11:49:00 +00003143 const int argc = 1;
3144 const char* src = "function foo(x) { "
3145 " a = 1;"
3146 " switch (x) {"
3147 " case 1:"
3148 " b = 1;"
3149 " case 2:"
3150 " c = 1;"
3151 " break;"
3152 " case 3:"
3153 " d = 1;"
3154 " e = 1;"
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003155 " f = 1;"
Steve Blocka7e24c12009-10-30 11:49:00 +00003156 " break;"
3157 " }"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003158 "}"
3159 "a=0; b=0; c=0; d=0; e=0; f=0; foo()";
Steve Blocka7e24c12009-10-30 11:49:00 +00003160 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3161 SetBreakPoint(foo, 0);
3162
3163 // One case with fall-through.
3164 step_action = StepIn;
3165 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003166 v8::Local<v8::Value> argv_1[argc] = {v8::Number::New(isolate, 1)};
3167 foo->Call(context, env->Global(), argc, argv_1).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003168 CHECK_EQ(6, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003169
3170 // Another case.
3171 step_action = StepIn;
3172 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003173 v8::Local<v8::Value> argv_2[argc] = {v8::Number::New(isolate, 2)};
3174 foo->Call(context, env->Global(), argc, argv_2).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003175 CHECK_EQ(5, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003176
3177 // Last case.
3178 step_action = StepIn;
3179 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003180 v8::Local<v8::Value> argv_3[argc] = {v8::Number::New(isolate, 3)};
3181 foo->Call(context, env->Global(), argc, argv_3).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003182 CHECK_EQ(7, break_point_hit_count);
3183
3184 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003185 v8::Debug::SetDebugEventListener(isolate, nullptr);
3186 CheckDebuggerUnloaded(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003187}
3188
3189
3190TEST(DebugStepWhile) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003191 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003192 v8::Isolate* isolate = env->GetIsolate();
3193 v8::HandleScope scope(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003194
3195 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003196 v8::Debug::SetDebugEventListener(isolate, DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003198 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003199 // Create a function for testing stepping. Run it to allow it to get
3200 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003201 const int argc = 1;
3202 const char* src = "function foo(x) { "
3203 " var a = 0;"
3204 " while (a < x) {"
3205 " a++;"
3206 " }"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003207 "}"
3208 "foo()";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003209 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3210 SetBreakPoint(foo, 8); // "var a = 0;"
3211
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003212 // Looping 0 times. We still should break at the while-condition once.
3213 step_action = StepIn;
3214 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003215 v8::Local<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
3216 foo->Call(context, env->Global(), argc, argv_0).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003217 CHECK_EQ(3, break_point_hit_count);
3218
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003219 // Looping 10 times.
3220 step_action = StepIn;
3221 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003222 v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
3223 foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003224 CHECK_EQ(23, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003225
3226 // Looping 100 times.
3227 step_action = StepIn;
3228 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003229 v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
3230 foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003231 CHECK_EQ(203, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003232
3233 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003234 v8::Debug::SetDebugEventListener(isolate, nullptr);
3235 CheckDebuggerUnloaded(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003236}
3237
3238
3239TEST(DebugStepDoWhile) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003240 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003241 v8::Isolate* isolate = env->GetIsolate();
3242 v8::HandleScope scope(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003243
3244 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003245 v8::Debug::SetDebugEventListener(isolate, DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003246
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003247 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003248 // Create a function for testing stepping. Run it to allow it to get
3249 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003250 const int argc = 1;
3251 const char* src = "function foo(x) { "
3252 " var a = 0;"
3253 " do {"
3254 " a++;"
3255 " } while (a < x)"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003256 "}"
3257 "foo()";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003258 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3259 SetBreakPoint(foo, 8); // "var a = 0;"
3260
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003261 // Looping 0 times.
3262 step_action = StepIn;
3263 break_point_hit_count = 0;
3264 v8::Local<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
3265 foo->Call(context, env->Global(), argc, argv_0).ToLocalChecked();
3266 CHECK_EQ(4, break_point_hit_count);
3267
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003268 // Looping 10 times.
3269 step_action = StepIn;
3270 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003271 v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
3272 foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003273 CHECK_EQ(22, break_point_hit_count);
3274
3275 // Looping 100 times.
3276 step_action = StepIn;
3277 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003278 v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
3279 foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003280 CHECK_EQ(202, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003281
3282 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003283 v8::Debug::SetDebugEventListener(isolate, nullptr);
3284 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003285}
3286
3287
3288TEST(DebugStepFor) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003289 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003290 v8::Isolate* isolate = env->GetIsolate();
3291 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003292
3293 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003294 v8::Debug::SetDebugEventListener(isolate, DebugEventStep);
Steve Blocka7e24c12009-10-30 11:49:00 +00003295
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003296 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003297 // Create a function for testing stepping. Run it to allow it to get
3298 // optimized.
Steve Blocka7e24c12009-10-30 11:49:00 +00003299 const int argc = 1;
3300 const char* src = "function foo(x) { "
3301 " a = 1;"
3302 " for (i = 0; i < x; i++) {"
3303 " b = 1;"
3304 " }"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003305 "}"
3306 "a=0; b=0; i=0; foo()";
Steve Blocka7e24c12009-10-30 11:49:00 +00003307 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
Ben Murdochb0fe1622011-05-05 13:52:32 +01003308
Steve Blocka7e24c12009-10-30 11:49:00 +00003309 SetBreakPoint(foo, 8); // "a = 1;"
3310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003311 // Looping 0 times.
3312 step_action = StepIn;
3313 break_point_hit_count = 0;
3314 v8::Local<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
3315 foo->Call(context, env->Global(), argc, argv_0).ToLocalChecked();
3316 CHECK_EQ(4, break_point_hit_count);
3317
Steve Blocka7e24c12009-10-30 11:49:00 +00003318 // Looping 10 times.
3319 step_action = StepIn;
3320 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003321 v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
3322 foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
3323 CHECK_EQ(34, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003324
3325 // Looping 100 times.
3326 step_action = StepIn;
3327 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003328 v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
3329 foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
3330 CHECK_EQ(304, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003331
3332 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003333 v8::Debug::SetDebugEventListener(isolate, nullptr);
3334 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003335}
3336
3337
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003338TEST(DebugStepForContinue) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003339 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003340 v8::Isolate* isolate = env->GetIsolate();
3341 v8::HandleScope scope(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003342
3343 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003344 v8::Debug::SetDebugEventListener(isolate, DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003345
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003346 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003347 // Create a function for testing stepping. Run it to allow it to get
3348 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003349 const int argc = 1;
3350 const char* src = "function foo(x) { "
3351 " var a = 0;"
3352 " var b = 0;"
3353 " var c = 0;"
3354 " for (var i = 0; i < x; i++) {"
3355 " a++;"
3356 " if (a % 2 == 0) continue;"
3357 " b++;"
3358 " c++;"
3359 " }"
3360 " return b;"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003361 "}"
3362 "foo()";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003363 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003364 v8::Local<v8::Value> result;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003365 SetBreakPoint(foo, 8); // "var a = 0;"
3366
3367 // Each loop generates 4 or 5 steps depending on whether a is equal.
3368
3369 // Looping 10 times.
3370 step_action = StepIn;
3371 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003372 v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
3373 result = foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
3374 CHECK_EQ(5, result->Int32Value(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003375 CHECK_EQ(62, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003376
3377 // Looping 100 times.
3378 step_action = StepIn;
3379 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003380 v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
3381 result = foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
3382 CHECK_EQ(50, result->Int32Value(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003383 CHECK_EQ(557, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003384
3385 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003386 v8::Debug::SetDebugEventListener(isolate, nullptr);
3387 CheckDebuggerUnloaded(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003388}
3389
3390
3391TEST(DebugStepForBreak) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003392 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003393 v8::Isolate* isolate = env->GetIsolate();
3394 v8::HandleScope scope(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003395
3396 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003397 v8::Debug::SetDebugEventListener(isolate, DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003398
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003399 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003400 // Create a function for testing stepping. Run it to allow it to get
3401 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003402 const int argc = 1;
3403 const char* src = "function foo(x) { "
3404 " var a = 0;"
3405 " var b = 0;"
3406 " var c = 0;"
3407 " for (var i = 0; i < 1000; i++) {"
3408 " a++;"
3409 " if (a == x) break;"
3410 " b++;"
3411 " c++;"
3412 " }"
3413 " return b;"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003414 "}"
3415 "foo()";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003416 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003417 v8::Local<v8::Value> result;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003418 SetBreakPoint(foo, 8); // "var a = 0;"
3419
3420 // Each loop generates 5 steps except for the last (when break is executed)
3421 // which only generates 4.
3422
3423 // Looping 10 times.
3424 step_action = StepIn;
3425 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003426 v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
3427 result = foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
3428 CHECK_EQ(9, result->Int32Value(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003429 CHECK_EQ(64, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003430
3431 // Looping 100 times.
3432 step_action = StepIn;
3433 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003434 v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
3435 result = foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
3436 CHECK_EQ(99, result->Int32Value(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003437 CHECK_EQ(604, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003438
3439 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003440 v8::Debug::SetDebugEventListener(isolate, nullptr);
3441 CheckDebuggerUnloaded(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003442}
3443
3444
3445TEST(DebugStepForIn) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003446 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003447 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003448
3449 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003450 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003452 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003453 // Create a function for testing stepping. Run it to allow it to get
3454 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003455 v8::Local<v8::Function> foo;
3456 const char* src_1 = "function foo() { "
3457 " var a = [1, 2];"
3458 " for (x in a) {"
3459 " b = 0;"
3460 " }"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003461 "}"
3462 "foo()";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003463 foo = CompileFunction(&env, src_1, "foo");
3464 SetBreakPoint(foo, 0); // "var a = ..."
3465
3466 step_action = StepIn;
3467 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003468 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003469 CHECK_EQ(8, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003470
Ben Murdochb0fe1622011-05-05 13:52:32 +01003471 // Create a function for testing stepping. Run it to allow it to get
3472 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003473 const char* src_2 = "function foo() { "
3474 " var a = {a:[1, 2, 3]};"
3475 " for (x in a.a) {"
3476 " b = 0;"
3477 " }"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003478 "}"
3479 "foo()";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003480 foo = CompileFunction(&env, src_2, "foo");
3481 SetBreakPoint(foo, 0); // "var a = ..."
3482
3483 step_action = StepIn;
3484 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003485 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003486 CHECK_EQ(10, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003487
3488 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003489 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3490 CheckDebuggerUnloaded(env->GetIsolate());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003491}
3492
3493
3494TEST(DebugStepWith) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003495 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003496 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003497
3498 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003499 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003500
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003501 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003502 // Create a function for testing stepping. Run it to allow it to get
3503 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003504 const char* src = "function foo(x) { "
3505 " var a = {};"
3506 " with (a) {}"
3507 " with (b) {}"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003508 "}"
3509 "foo()";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003510 CHECK(env->Global()
3511 ->Set(context, v8_str(env->GetIsolate(), "b"),
3512 v8::Object::New(env->GetIsolate()))
3513 .FromJust());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003514 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003515 v8::Local<v8::Value> result;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003516 SetBreakPoint(foo, 8); // "var a = {};"
3517
3518 step_action = StepIn;
3519 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003520 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003521 CHECK_EQ(4, break_point_hit_count);
3522
3523 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003524 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3525 CheckDebuggerUnloaded(env->GetIsolate());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003526}
3527
3528
3529TEST(DebugConditional) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003530 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003531 v8::Isolate* isolate = env->GetIsolate();
3532 v8::HandleScope scope(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003533
3534 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003535 v8::Debug::SetDebugEventListener(isolate, DebugEventStep);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003536
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003537 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003538 // Create a function for testing stepping. Run it to allow it to get
3539 // optimized.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003540 const char* src = "function foo(x) { "
3541 " var a;"
3542 " a = x ? 1 : 2;"
3543 " return a;"
Ben Murdochb0fe1622011-05-05 13:52:32 +01003544 "}"
3545 "foo()";
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003546 v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3547 SetBreakPoint(foo, 0); // "var a;"
3548
3549 step_action = StepIn;
3550 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003551 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
3552 CHECK_EQ(4, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003553
3554 step_action = StepIn;
3555 break_point_hit_count = 0;
3556 const int argc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003557 v8::Local<v8::Value> argv_true[argc] = {v8::True(isolate)};
3558 foo->Call(context, env->Global(), argc, argv_true).ToLocalChecked();
3559 CHECK_EQ(4, break_point_hit_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003560
3561 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003562 v8::Debug::SetDebugEventListener(isolate, nullptr);
3563 CheckDebuggerUnloaded(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003564}
3565
3566
Steve Blocka7e24c12009-10-30 11:49:00 +00003567TEST(StepInOutSimple) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003568 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003569 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003570
3571 // Create a function for checking the function when hitting a break point.
3572 frame_function_name = CompileFunction(&env,
3573 frame_function_name_source,
3574 "frame_function_name");
3575
3576 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003577 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStepSequence);
Steve Blocka7e24c12009-10-30 11:49:00 +00003578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003579 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003580 // Create a function for testing stepping. Run it to allow it to get
3581 // optimized.
Steve Blocka7e24c12009-10-30 11:49:00 +00003582 const char* src = "function a() {b();c();}; "
3583 "function b() {c();}; "
Ben Murdochb0fe1622011-05-05 13:52:32 +01003584 "function c() {}; "
3585 "a(); b(); c()";
Steve Blocka7e24c12009-10-30 11:49:00 +00003586 v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3587 SetBreakPoint(a, 0);
3588
3589 // Step through invocation of a with step in.
3590 step_action = StepIn;
3591 break_point_hit_count = 0;
3592 expected_step_sequence = "abcbaca";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003593 a->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00003594 CHECK_EQ(StrLength(expected_step_sequence),
3595 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003596
3597 // Step through invocation of a with step next.
3598 step_action = StepNext;
3599 break_point_hit_count = 0;
3600 expected_step_sequence = "aaa";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003601 a->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00003602 CHECK_EQ(StrLength(expected_step_sequence),
3603 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003604
3605 // Step through invocation of a with step out.
3606 step_action = StepOut;
3607 break_point_hit_count = 0;
3608 expected_step_sequence = "a";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003609 a->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00003610 CHECK_EQ(StrLength(expected_step_sequence),
3611 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003612
3613 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003614 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3615 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003616}
3617
3618
3619TEST(StepInOutTree) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003620 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003621 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003622
3623 // Create a function for checking the function when hitting a break point.
3624 frame_function_name = CompileFunction(&env,
3625 frame_function_name_source,
3626 "frame_function_name");
3627
3628 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003629 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStepSequence);
Steve Blocka7e24c12009-10-30 11:49:00 +00003630
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003631 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003632 // Create a function for testing stepping. Run it to allow it to get
3633 // optimized.
Steve Blocka7e24c12009-10-30 11:49:00 +00003634 const char* src = "function a() {b(c(d()),d());c(d());d()}; "
3635 "function b(x,y) {c();}; "
3636 "function c(x) {}; "
Ben Murdochb0fe1622011-05-05 13:52:32 +01003637 "function d() {}; "
3638 "a(); b(); c(); d()";
Steve Blocka7e24c12009-10-30 11:49:00 +00003639 v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3640 SetBreakPoint(a, 0);
3641
3642 // Step through invocation of a with step in.
3643 step_action = StepIn;
3644 break_point_hit_count = 0;
3645 expected_step_sequence = "adacadabcbadacada";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003646 a->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00003647 CHECK_EQ(StrLength(expected_step_sequence),
3648 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003649
3650 // Step through invocation of a with step next.
3651 step_action = StepNext;
3652 break_point_hit_count = 0;
3653 expected_step_sequence = "aaaa";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003654 a->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00003655 CHECK_EQ(StrLength(expected_step_sequence),
3656 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003657
3658 // Step through invocation of a with step out.
3659 step_action = StepOut;
3660 break_point_hit_count = 0;
3661 expected_step_sequence = "a";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003662 a->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00003663 CHECK_EQ(StrLength(expected_step_sequence),
3664 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003665
3666 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003667 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3668 CheckDebuggerUnloaded(env->GetIsolate(), true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003669}
3670
3671
3672TEST(StepInOutBranch) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003673 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003674 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003675
3676 // Create a function for checking the function when hitting a break point.
3677 frame_function_name = CompileFunction(&env,
3678 frame_function_name_source,
3679 "frame_function_name");
3680
3681 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003682 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStepSequence);
Steve Blocka7e24c12009-10-30 11:49:00 +00003683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003684 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01003685 // Create a function for testing stepping. Run it to allow it to get
3686 // optimized.
Steve Blocka7e24c12009-10-30 11:49:00 +00003687 const char* src = "function a() {b(false);c();}; "
3688 "function b(x) {if(x){c();};}; "
Ben Murdochb0fe1622011-05-05 13:52:32 +01003689 "function c() {}; "
3690 "a(); b(); c()";
Steve Blocka7e24c12009-10-30 11:49:00 +00003691 v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3692 SetBreakPoint(a, 0);
3693
3694 // Step through invocation of a.
3695 step_action = StepIn;
3696 break_point_hit_count = 0;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003697 expected_step_sequence = "abbaca";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003698 a->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00003699 CHECK_EQ(StrLength(expected_step_sequence),
3700 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003701
3702 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003703 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3704 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003705}
3706
3707
3708// Test that step in does not step into native functions.
3709TEST(DebugStepNatives) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003710 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003711 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003712
3713 // Create a function for testing stepping.
3714 v8::Local<v8::Function> foo = CompileFunction(
3715 &env,
3716 "function foo(){debugger;Math.sin(1);}",
3717 "foo");
3718
3719 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003720 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Steve Blocka7e24c12009-10-30 11:49:00 +00003721
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003722 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00003723 step_action = StepIn;
3724 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003725 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00003726
3727 // With stepping all break locations are hit.
3728 CHECK_EQ(3, break_point_hit_count);
3729
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003730 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3731 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003732
3733 // Register a debug event listener which just counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003734 v8::Debug::SetDebugEventListener(env->GetIsolate(),
3735 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00003736
3737 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003738 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00003739
3740 // Without stepping only active break points are hit.
3741 CHECK_EQ(1, break_point_hit_count);
3742
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003743 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3744 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003745}
3746
3747
3748// Test that step in works with function.apply.
3749TEST(DebugStepFunctionApply) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003750 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003751 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003752
3753 // Create a function for testing stepping.
3754 v8::Local<v8::Function> foo = CompileFunction(
3755 &env,
3756 "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
3757 "function foo(){ debugger; bar.apply(this, [1,2,3]); }",
3758 "foo");
3759
3760 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003761 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStep);
Steve Blocka7e24c12009-10-30 11:49:00 +00003762
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003763 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00003764 step_action = StepIn;
3765 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003766 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00003767
3768 // With stepping all break locations are hit.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003769 CHECK_EQ(7, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003770
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003771 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3772 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003773
3774 // Register a debug event listener which just counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003775 v8::Debug::SetDebugEventListener(env->GetIsolate(),
3776 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00003777
3778 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003779 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00003780
3781 // Without stepping only the debugger statement is hit.
3782 CHECK_EQ(1, break_point_hit_count);
3783
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003784 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3785 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003786}
3787
3788
3789// Test that step in works with function.call.
3790TEST(DebugStepFunctionCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003791 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003792 v8::Isolate* isolate = env->GetIsolate();
3793 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003794
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003795 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00003796 // Create a function for testing stepping.
3797 v8::Local<v8::Function> foo = CompileFunction(
3798 &env,
3799 "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
3800 "function foo(a){ debugger;"
3801 " if (a) {"
3802 " bar.call(this, 1, 2, 3);"
3803 " } else {"
3804 " bar.call(this, 0);"
3805 " }"
3806 "}",
3807 "foo");
3808
3809 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003810 v8::Debug::SetDebugEventListener(isolate, DebugEventStep);
Steve Blocka7e24c12009-10-30 11:49:00 +00003811 step_action = StepIn;
3812
3813 // Check stepping where the if condition in bar is false.
3814 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003815 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003816 CHECK_EQ(6, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003817
3818 // Check stepping where the if condition in bar is true.
3819 break_point_hit_count = 0;
3820 const int argc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003821 v8::Local<v8::Value> argv[argc] = {v8::True(isolate)};
3822 foo->Call(context, env->Global(), argc, argv).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003823 CHECK_EQ(8, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00003824
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003825 v8::Debug::SetDebugEventListener(isolate, nullptr);
3826 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003827
3828 // Register a debug event listener which just counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003829 v8::Debug::SetDebugEventListener(isolate, DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00003830
3831 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003832 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00003833
3834 // Without stepping only the debugger statement is hit.
3835 CHECK_EQ(1, break_point_hit_count);
3836
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003837 v8::Debug::SetDebugEventListener(isolate, nullptr);
3838 CheckDebuggerUnloaded(isolate);
3839}
3840
3841
3842// Test that step in works with Function.call.apply.
3843TEST(DebugStepFunctionCallApply) {
3844 DebugLocalContext env;
3845 v8::Isolate* isolate = env->GetIsolate();
3846 v8::HandleScope scope(isolate);
3847
3848 v8::Local<v8::Context> context = env.context();
3849 // Create a function for testing stepping.
3850 v8::Local<v8::Function> foo =
3851 CompileFunction(&env,
3852 "function bar() { }"
3853 "function foo(){ debugger;"
3854 " Function.call.apply(bar);"
3855 " Function.call.apply(Function.call, "
3856 "[Function.call, bar]);"
3857 "}",
3858 "foo");
3859
3860 // Register a debug event listener which steps and counts.
3861 v8::Debug::SetDebugEventListener(isolate, DebugEventStep);
3862 step_action = StepIn;
3863
3864 break_point_hit_count = 0;
3865 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
3866 CHECK_EQ(6, break_point_hit_count);
3867
3868 v8::Debug::SetDebugEventListener(isolate, nullptr);
3869 CheckDebuggerUnloaded(isolate);
3870
3871 // Register a debug event listener which just counts.
3872 v8::Debug::SetDebugEventListener(isolate, DebugEventBreakPointHitCount);
3873
3874 break_point_hit_count = 0;
3875 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
3876
3877 // Without stepping only the debugger statement is hit.
3878 CHECK_EQ(1, break_point_hit_count);
3879
3880 v8::Debug::SetDebugEventListener(isolate, nullptr);
3881 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003882}
3883
3884
Steve Blockd0582a62009-12-15 09:54:21 +00003885// Tests that breakpoint will be hit if it's set in script.
3886TEST(PauseInScript) {
Steve Blockd0582a62009-12-15 09:54:21 +00003887 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003888 v8::HandleScope scope(env->GetIsolate());
Steve Blockd0582a62009-12-15 09:54:21 +00003889 env.ExposeDebug();
3890
3891 // Register a debug event listener which counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003892 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventCounter);
Steve Blockd0582a62009-12-15 09:54:21 +00003893
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003894 v8::Local<v8::Context> context = env.context();
Steve Blockd0582a62009-12-15 09:54:21 +00003895 // Create a script that returns a function.
3896 const char* src = "(function (evt) {})";
3897 const char* script_name = "StepInHandlerTest";
3898
3899 // Set breakpoint in the script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003900 SetScriptBreakPointByNameFromJS(env->GetIsolate(), script_name, 0, -1);
Steve Blockd0582a62009-12-15 09:54:21 +00003901 break_point_hit_count = 0;
3902
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003903 v8::ScriptOrigin origin(v8_str(env->GetIsolate(), script_name),
3904 v8::Integer::New(env->GetIsolate(), 0));
3905 v8::Local<v8::Script> script =
3906 v8::Script::Compile(context, v8_str(env->GetIsolate(), src), &origin)
3907 .ToLocalChecked();
3908 v8::Local<v8::Value> r = script->Run(context).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00003909
3910 CHECK(r->IsFunction());
3911 CHECK_EQ(1, break_point_hit_count);
3912
3913 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003914 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
3915 CheckDebuggerUnloaded(env->GetIsolate());
3916}
3917
3918
3919static void DebugEventCounterCheck(int caught, int uncaught, int message) {
3920 CHECK_EQ(caught, exception_hit_count);
3921 CHECK_EQ(uncaught, uncaught_exception_hit_count);
3922 CHECK_EQ(message, message_callback_count);
Steve Blockd0582a62009-12-15 09:54:21 +00003923}
3924
3925
Steve Blocka7e24c12009-10-30 11:49:00 +00003926// Test break on exceptions. For each exception break combination the number
3927// of debug event exception callbacks and message callbacks are collected. The
3928// number of debug event exception callbacks are used to check that the
3929// debugger is called correctly and the number of message callbacks is used to
3930// check that uncaught exceptions are still returned even if there is a break
3931// for them.
3932TEST(BreakOnException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003933 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003934 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003935 env.ExposeDebug();
3936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003937 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00003938 // Create functions for testing break on exception.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003939 CompileFunction(&env, "function throws(){throw 1;}", "throws");
Steve Blocka7e24c12009-10-30 11:49:00 +00003940 v8::Local<v8::Function> caught =
3941 CompileFunction(&env,
3942 "function caught(){try {throws();} catch(e) {};}",
3943 "caught");
3944 v8::Local<v8::Function> notCaught =
3945 CompileFunction(&env, "function notCaught(){throws();}", "notCaught");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003946 v8::Local<v8::Function> notCaughtFinally = CompileFunction(
3947 &env, "function notCaughtFinally(){try{throws();}finally{}}",
3948 "notCaughtFinally");
3949 // In this edge case, even though this finally does not propagate the
3950 // exception, the debugger considers this uncaught, since we want to break
3951 // at the first throw for the general case where finally implicitly rethrows.
3952 v8::Local<v8::Function> edgeCaseFinally = CompileFunction(
3953 &env, "function caughtFinally(){L:try{throws();}finally{break L;}}",
3954 "caughtFinally");
Steve Blocka7e24c12009-10-30 11:49:00 +00003955
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003956 env->GetIsolate()->AddMessageListener(MessageCallbackCount);
3957 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventCounter);
Steve Blocka7e24c12009-10-30 11:49:00 +00003958
Ben Murdoch086aeea2011-05-13 15:57:08 +01003959 // Initial state should be no break on exceptions.
Steve Blocka7e24c12009-10-30 11:49:00 +00003960 DebugEventCounterClear();
3961 MessageCallbackCountClear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003962 caught->Call(context, env->Global(), 0, NULL).ToLocalChecked();
3963 DebugEventCounterCheck(0, 0, 0);
3964 CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty());
3965 DebugEventCounterCheck(0, 0, 1);
3966 CHECK(notCaughtFinally->Call(context, env->Global(), 0, NULL).IsEmpty());
3967 DebugEventCounterCheck(0, 0, 2);
3968 edgeCaseFinally->Call(context, env->Global(), 0, NULL).ToLocalChecked();
3969 DebugEventCounterCheck(0, 0, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +00003970
3971 // No break on exception
3972 DebugEventCounterClear();
3973 MessageCallbackCountClear();
3974 ChangeBreakOnException(false, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003975 caught->Call(context, env->Global(), 0, NULL).ToLocalChecked();
3976 DebugEventCounterCheck(0, 0, 0);
3977 CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty());
3978 DebugEventCounterCheck(0, 0, 1);
3979 CHECK(notCaughtFinally->Call(context, env->Global(), 0, NULL).IsEmpty());
3980 DebugEventCounterCheck(0, 0, 2);
3981 edgeCaseFinally->Call(context, env->Global(), 0, NULL).ToLocalChecked();
3982 DebugEventCounterCheck(0, 0, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +00003983
3984 // Break on uncaught exception
3985 DebugEventCounterClear();
3986 MessageCallbackCountClear();
3987 ChangeBreakOnException(false, true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003988 caught->Call(context, env->Global(), 0, NULL).ToLocalChecked();
3989 DebugEventCounterCheck(0, 0, 0);
3990 CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty());
3991 DebugEventCounterCheck(1, 1, 1);
3992 CHECK(notCaughtFinally->Call(context, env->Global(), 0, NULL).IsEmpty());
3993 DebugEventCounterCheck(2, 2, 2);
3994 edgeCaseFinally->Call(context, env->Global(), 0, NULL).ToLocalChecked();
3995 DebugEventCounterCheck(3, 3, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +00003996
3997 // Break on exception and uncaught exception
3998 DebugEventCounterClear();
3999 MessageCallbackCountClear();
4000 ChangeBreakOnException(true, true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004001 caught->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4002 DebugEventCounterCheck(1, 0, 0);
4003 CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty());
4004 DebugEventCounterCheck(2, 1, 1);
4005 CHECK(notCaughtFinally->Call(context, env->Global(), 0, NULL).IsEmpty());
4006 DebugEventCounterCheck(3, 2, 2);
4007 edgeCaseFinally->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4008 DebugEventCounterCheck(4, 3, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004009
4010 // Break on exception
4011 DebugEventCounterClear();
4012 MessageCallbackCountClear();
4013 ChangeBreakOnException(true, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004014 caught->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4015 DebugEventCounterCheck(1, 0, 0);
4016 CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty());
4017 DebugEventCounterCheck(2, 1, 1);
4018 CHECK(notCaughtFinally->Call(context, env->Global(), 0, NULL).IsEmpty());
4019 DebugEventCounterCheck(3, 2, 2);
4020 edgeCaseFinally->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4021 DebugEventCounterCheck(4, 3, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004022
4023 // No break on exception using JavaScript
4024 DebugEventCounterClear();
4025 MessageCallbackCountClear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004026 ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004027 caught->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4028 DebugEventCounterCheck(0, 0, 0);
4029 CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty());
4030 DebugEventCounterCheck(0, 0, 1);
4031 CHECK(notCaughtFinally->Call(context, env->Global(), 0, NULL).IsEmpty());
4032 DebugEventCounterCheck(0, 0, 2);
4033 edgeCaseFinally->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4034 DebugEventCounterCheck(0, 0, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004035
4036 // Break on uncaught exception using JavaScript
4037 DebugEventCounterClear();
4038 MessageCallbackCountClear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004039 ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004040 caught->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4041 DebugEventCounterCheck(0, 0, 0);
4042 CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty());
4043 DebugEventCounterCheck(1, 1, 1);
4044 CHECK(notCaughtFinally->Call(context, env->Global(), 0, NULL).IsEmpty());
4045 DebugEventCounterCheck(2, 2, 2);
4046 edgeCaseFinally->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4047 DebugEventCounterCheck(3, 3, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004048
4049 // Break on exception and uncaught exception using JavaScript
4050 DebugEventCounterClear();
4051 MessageCallbackCountClear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004052 ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004053 caught->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4054 DebugEventCounterCheck(1, 0, 0);
4055 CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty());
4056 DebugEventCounterCheck(2, 1, 1);
4057 CHECK(notCaughtFinally->Call(context, env->Global(), 0, NULL).IsEmpty());
4058 DebugEventCounterCheck(3, 2, 2);
4059 edgeCaseFinally->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4060 DebugEventCounterCheck(4, 3, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004061
4062 // Break on exception using JavaScript
4063 DebugEventCounterClear();
4064 MessageCallbackCountClear();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004065 ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004066 caught->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4067 DebugEventCounterCheck(1, 0, 0);
4068 CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty());
4069 DebugEventCounterCheck(2, 1, 1);
4070 CHECK(notCaughtFinally->Call(context, env->Global(), 0, NULL).IsEmpty());
4071 DebugEventCounterCheck(3, 2, 2);
4072 edgeCaseFinally->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4073 DebugEventCounterCheck(4, 3, 2);
Steve Blocka7e24c12009-10-30 11:49:00 +00004074
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004075 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
4076 CheckDebuggerUnloaded(env->GetIsolate());
4077 env->GetIsolate()->RemoveMessageListeners(MessageCallbackCount);
4078}
4079
4080
4081static void try_finally_original_message(v8::Local<v8::Message> message,
4082 v8::Local<v8::Value> data) {
4083 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
4084 CHECK_EQ(2, message->GetLineNumber(context).FromJust());
4085 CHECK_EQ(2, message->GetStartColumn(context).FromJust());
4086 message_callback_count++;
4087}
4088
4089
4090TEST(TryFinallyOriginalMessage) {
4091 // Test that the debugger plays nicely with the pending message.
4092 message_callback_count = 0;
4093 DebugEventCounterClear();
4094 DebugLocalContext env;
4095 v8::Isolate* isolate = CcTest::isolate();
4096 isolate->AddMessageListener(try_finally_original_message);
4097 v8::Debug::SetDebugEventListener(isolate, DebugEventCounter);
4098 ChangeBreakOnException(true, true);
4099 v8::HandleScope scope(isolate);
4100 CompileRun(
4101 "try {\n"
4102 " throw 1;\n"
4103 "} finally {\n"
4104 "}\n");
4105 DebugEventCounterCheck(1, 1, 1);
4106 v8::Debug::SetDebugEventListener(isolate, nullptr);
4107 isolate->RemoveMessageListeners(try_finally_original_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00004108}
4109
4110
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004111TEST(EvalJSInDebugEventListenerOnNativeReThrownException) {
4112 DebugLocalContext env;
4113 v8::HandleScope scope(env->GetIsolate());
4114 env.ExposeDebug();
4115
4116 // Create functions for testing break on exception.
4117 v8::Local<v8::Function> noThrowJS = CompileFunction(
4118 &env, "function noThrowJS(){var a=[1]; a.push(2); return a.length;}",
4119 "noThrowJS");
4120
4121 debug_event_listener_callback = noThrowJS;
4122 debug_event_listener_callback_result = 2;
4123
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004124 env->GetIsolate()->AddMessageListener(MessageCallbackCount);
4125 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004126 // Break on uncaught exception
4127 ChangeBreakOnException(false, true);
4128 DebugEventCounterClear();
4129 MessageCallbackCountClear();
4130
4131 // ReThrow native error
4132 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004133 v8::TryCatch tryCatch(env->GetIsolate());
4134 env->GetIsolate()->ThrowException(
4135 v8::Exception::TypeError(v8_str(env->GetIsolate(), "Type error")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004136 CHECK(tryCatch.HasCaught());
4137 tryCatch.ReThrow();
4138 }
4139 CHECK_EQ(1, exception_hit_count);
4140 CHECK_EQ(1, uncaught_exception_hit_count);
4141 CHECK_EQ(0, message_callback_count); // FIXME: Should it be 1 ?
4142 CHECK(!debug_event_listener_callback.IsEmpty());
4143
4144 debug_event_listener_callback.Clear();
4145}
4146
4147
Steve Blocka7e24c12009-10-30 11:49:00 +00004148// Test break on exception from compiler errors. When compiling using
4149// v8::Script::Compile there is no JavaScript stack whereas when compiling using
4150// eval there are JavaScript frames.
4151TEST(BreakOnCompileException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004152 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004153 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004154
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004155 v8::Local<v8::Context> context = env.context();
Ben Murdoch086aeea2011-05-13 15:57:08 +01004156 // For this test, we want to break on uncaught exceptions:
4157 ChangeBreakOnException(false, true);
4158
Steve Blocka7e24c12009-10-30 11:49:00 +00004159 // Create a function for checking the function when hitting a break point.
4160 frame_count = CompileFunction(&env, frame_count_source, "frame_count");
4161
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004162 env->GetIsolate()->AddMessageListener(MessageCallbackCount);
4163 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventCounter);
Steve Blocka7e24c12009-10-30 11:49:00 +00004164
4165 DebugEventCounterClear();
4166 MessageCallbackCountClear();
4167
4168 // Check initial state.
4169 CHECK_EQ(0, exception_hit_count);
4170 CHECK_EQ(0, uncaught_exception_hit_count);
4171 CHECK_EQ(0, message_callback_count);
4172 CHECK_EQ(-1, last_js_stack_height);
4173
4174 // Throws SyntaxError: Unexpected end of input
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004175 CHECK(
4176 v8::Script::Compile(context, v8_str(env->GetIsolate(), "+++")).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00004177 CHECK_EQ(1, exception_hit_count);
4178 CHECK_EQ(1, uncaught_exception_hit_count);
4179 CHECK_EQ(1, message_callback_count);
4180 CHECK_EQ(0, last_js_stack_height); // No JavaScript stack.
4181
4182 // Throws SyntaxError: Unexpected identifier
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004183 CHECK(
4184 v8::Script::Compile(context, v8_str(env->GetIsolate(), "x x")).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00004185 CHECK_EQ(2, exception_hit_count);
4186 CHECK_EQ(2, uncaught_exception_hit_count);
4187 CHECK_EQ(2, message_callback_count);
4188 CHECK_EQ(0, last_js_stack_height); // No JavaScript stack.
4189
4190 // Throws SyntaxError: Unexpected end of input
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004191 CHECK(v8::Script::Compile(context, v8_str(env->GetIsolate(), "eval('+++')"))
4192 .ToLocalChecked()
4193 ->Run(context)
4194 .IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00004195 CHECK_EQ(3, exception_hit_count);
4196 CHECK_EQ(3, uncaught_exception_hit_count);
4197 CHECK_EQ(3, message_callback_count);
4198 CHECK_EQ(1, last_js_stack_height);
4199
4200 // Throws SyntaxError: Unexpected identifier
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004201 CHECK(v8::Script::Compile(context, v8_str(env->GetIsolate(), "eval('x x')"))
4202 .ToLocalChecked()
4203 ->Run(context)
4204 .IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00004205 CHECK_EQ(4, exception_hit_count);
4206 CHECK_EQ(4, uncaught_exception_hit_count);
4207 CHECK_EQ(4, message_callback_count);
4208 CHECK_EQ(1, last_js_stack_height);
4209}
4210
4211
4212TEST(StepWithException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004213 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004214 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004215
Ben Murdoch086aeea2011-05-13 15:57:08 +01004216 // For this test, we want to break on uncaught exceptions:
4217 ChangeBreakOnException(false, true);
4218
Steve Blocka7e24c12009-10-30 11:49:00 +00004219 // Create a function for checking the function when hitting a break point.
4220 frame_function_name = CompileFunction(&env,
4221 frame_function_name_source,
4222 "frame_function_name");
4223
4224 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004225 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStepSequence);
Steve Blocka7e24c12009-10-30 11:49:00 +00004226
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004227 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00004228 // Create functions for testing stepping.
4229 const char* src = "function a() { n(); }; "
4230 "function b() { c(); }; "
4231 "function c() { n(); }; "
4232 "function d() { x = 1; try { e(); } catch(x) { x = 2; } }; "
4233 "function e() { n(); }; "
4234 "function f() { x = 1; try { g(); } catch(x) { x = 2; } }; "
4235 "function g() { h(); }; "
4236 "function h() { x = 1; throw 1; }; ";
4237
4238 // Step through invocation of a.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004239 ClearStepping();
Steve Blocka7e24c12009-10-30 11:49:00 +00004240 v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
4241 SetBreakPoint(a, 0);
4242 step_action = StepIn;
4243 break_point_hit_count = 0;
4244 expected_step_sequence = "aa";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004245 CHECK(a->Call(context, env->Global(), 0, NULL).IsEmpty());
Steve Blockd0582a62009-12-15 09:54:21 +00004246 CHECK_EQ(StrLength(expected_step_sequence),
4247 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00004248
4249 // Step through invocation of b + c.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004250 ClearStepping();
Steve Blocka7e24c12009-10-30 11:49:00 +00004251 v8::Local<v8::Function> b = CompileFunction(&env, src, "b");
4252 SetBreakPoint(b, 0);
4253 step_action = StepIn;
4254 break_point_hit_count = 0;
4255 expected_step_sequence = "bcc";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004256 CHECK(b->Call(context, env->Global(), 0, NULL).IsEmpty());
Steve Blockd0582a62009-12-15 09:54:21 +00004257 CHECK_EQ(StrLength(expected_step_sequence),
4258 break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004259
Steve Blocka7e24c12009-10-30 11:49:00 +00004260 // Step through invocation of d + e.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004261 ClearStepping();
Steve Blocka7e24c12009-10-30 11:49:00 +00004262 v8::Local<v8::Function> d = CompileFunction(&env, src, "d");
4263 SetBreakPoint(d, 0);
4264 ChangeBreakOnException(false, true);
4265 step_action = StepIn;
4266 break_point_hit_count = 0;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004267 expected_step_sequence = "ddedd";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004268 d->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00004269 CHECK_EQ(StrLength(expected_step_sequence),
4270 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00004271
4272 // Step through invocation of d + e now with break on caught exceptions.
4273 ChangeBreakOnException(true, true);
4274 step_action = StepIn;
4275 break_point_hit_count = 0;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004276 expected_step_sequence = "ddeedd";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004277 d->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00004278 CHECK_EQ(StrLength(expected_step_sequence),
4279 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00004280
4281 // Step through invocation of f + g + h.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004282 ClearStepping();
Steve Blocka7e24c12009-10-30 11:49:00 +00004283 v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
4284 SetBreakPoint(f, 0);
4285 ChangeBreakOnException(false, true);
4286 step_action = StepIn;
4287 break_point_hit_count = 0;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004288 expected_step_sequence = "ffghhff";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004289 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00004290 CHECK_EQ(StrLength(expected_step_sequence),
4291 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00004292
4293 // Step through invocation of f + g + h now with break on caught exceptions.
4294 ChangeBreakOnException(true, true);
4295 step_action = StepIn;
4296 break_point_hit_count = 0;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004297 expected_step_sequence = "ffghhhff";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004298 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00004299 CHECK_EQ(StrLength(expected_step_sequence),
4300 break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00004301
4302 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004303 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
4304 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004305}
4306
4307
4308TEST(DebugBreak) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004309 i::FLAG_stress_compaction = false;
4310#ifdef VERIFY_HEAP
4311 i::FLAG_verify_heap = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00004312#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004313 DebugLocalContext env;
4314 v8::Isolate* isolate = env->GetIsolate();
4315 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004316
4317 // Register a debug event listener which sets the break flag and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004318 v8::Debug::SetDebugEventListener(isolate, DebugEventBreak);
Steve Blocka7e24c12009-10-30 11:49:00 +00004319
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004320 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00004321 // Create a function for testing stepping.
4322 const char* src = "function f0() {}"
4323 "function f1(x1) {}"
4324 "function f2(x1,x2) {}"
4325 "function f3(x1,x2,x3) {}";
4326 v8::Local<v8::Function> f0 = CompileFunction(&env, src, "f0");
4327 v8::Local<v8::Function> f1 = CompileFunction(&env, src, "f1");
4328 v8::Local<v8::Function> f2 = CompileFunction(&env, src, "f2");
4329 v8::Local<v8::Function> f3 = CompileFunction(&env, src, "f3");
4330
4331 // Call the function to make sure it is compiled.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004332 v8::Local<v8::Value> argv[] = {
4333 v8::Number::New(isolate, 1), v8::Number::New(isolate, 1),
4334 v8::Number::New(isolate, 1), v8::Number::New(isolate, 1)};
Steve Blocka7e24c12009-10-30 11:49:00 +00004335
4336 // Call all functions to make sure that they are compiled.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004337 f0->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4338 f1->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4339 f2->Call(context, env->Global(), 0, NULL).ToLocalChecked();
4340 f3->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00004341
4342 // Set the debug break flag.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004343 v8::Debug::DebugBreak(env->GetIsolate());
4344 CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +00004345
4346 // Call all functions with different argument count.
4347 break_point_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004348 for (unsigned int i = 0; i < arraysize(argv); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004349 f0->Call(context, env->Global(), i, argv).ToLocalChecked();
4350 f1->Call(context, env->Global(), i, argv).ToLocalChecked();
4351 f2->Call(context, env->Global(), i, argv).ToLocalChecked();
4352 f3->Call(context, env->Global(), i, argv).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00004353 }
4354
4355 // One break for each function called.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004356 CHECK(4 * arraysize(argv) == break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00004357
4358 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004359 v8::Debug::SetDebugEventListener(isolate, nullptr);
4360 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004361}
4362
4363
4364// Test to ensure that JavaScript code keeps running while the debug break
4365// through the stack limit flag is set but breaks are disabled.
4366TEST(DisableBreak) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004367 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004368 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004369
4370 // Register a debug event listener which sets the break flag and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004371 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventCounter);
Steve Blocka7e24c12009-10-30 11:49:00 +00004372
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004373 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00004374 // Create a function for testing stepping.
4375 const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}";
4376 v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
4377
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004378 // Set, test and cancel debug break.
4379 v8::Debug::DebugBreak(env->GetIsolate());
4380 CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate()));
4381 v8::Debug::CancelDebugBreak(env->GetIsolate());
4382 CHECK(!v8::Debug::CheckDebugBreak(env->GetIsolate()));
4383
Steve Blocka7e24c12009-10-30 11:49:00 +00004384 // Set the debug break flag.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004385 v8::Debug::DebugBreak(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004386
4387 // Call all functions with different argument count.
4388 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004389 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00004390 CHECK_EQ(1, break_point_hit_count);
4391
4392 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004393 v8::Debug::DebugBreak(env->GetIsolate());
4394 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
4395 v8::internal::DisableBreak disable_break(isolate->debug(), true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004396 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00004397 CHECK_EQ(1, break_point_hit_count);
4398 }
4399
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004400 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00004401 CHECK_EQ(2, break_point_hit_count);
4402
4403 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004404 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
4405 CheckDebuggerUnloaded(env->GetIsolate());
4406}
4407
4408
4409TEST(DisableDebuggerStatement) {
4410 DebugLocalContext env;
4411 v8::HandleScope scope(env->GetIsolate());
4412
4413 // Register a debug event listener which sets the break flag and counts.
4414 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventCounter);
4415 CompileRun("debugger;");
4416 CHECK_EQ(1, break_point_hit_count);
4417
4418 // Check that we ignore debugger statement when breakpoints aren't active.
4419 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
4420 isolate->debug()->set_break_points_active(false);
4421 CompileRun("debugger;");
4422 CHECK_EQ(1, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00004423}
4424
Leon Clarkee46be812010-01-19 14:06:41 +00004425static const char* kSimpleExtensionSource =
4426 "(function Foo() {"
4427 " return 4;"
4428 "})() ";
4429
4430// http://crbug.com/28933
4431// Test that debug break is disabled when bootstrapper is active.
4432TEST(NoBreakWhenBootstrapping) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004433 v8::Isolate* isolate = CcTest::isolate();
4434 v8::HandleScope scope(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00004435
4436 // Register a debug event listener which sets the break flag and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004437 v8::Debug::SetDebugEventListener(isolate, DebugEventCounter);
Leon Clarkee46be812010-01-19 14:06:41 +00004438
4439 // Set the debug break flag.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004440 v8::Debug::DebugBreak(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00004441 break_point_hit_count = 0;
4442 {
4443 // Create a context with an extension to make sure that some JavaScript
4444 // code is executed during bootstrapping.
4445 v8::RegisterExtension(new v8::Extension("simpletest",
4446 kSimpleExtensionSource));
4447 const char* extension_names[] = { "simpletest" };
4448 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004449 v8::HandleScope handle_scope(isolate);
4450 v8::Context::New(isolate, &extensions);
Leon Clarkee46be812010-01-19 14:06:41 +00004451 }
4452 // Check that no DebugBreak events occured during the context creation.
4453 CHECK_EQ(0, break_point_hit_count);
4454
4455 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004456 v8::Debug::SetDebugEventListener(isolate, nullptr);
4457 CheckDebuggerUnloaded(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00004458}
Steve Blocka7e24c12009-10-30 11:49:00 +00004459
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004460
4461static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004462 v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
4463 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
4464 CHECK(result->Set(context, v8::Integer::New(info.GetIsolate(), 0),
4465 v8_str(info.GetIsolate(), "a"))
4466 .FromJust());
4467 CHECK(result->Set(context, v8::Integer::New(info.GetIsolate(), 1),
4468 v8_str(info.GetIsolate(), "b"))
4469 .FromJust());
4470 CHECK(result->Set(context, v8::Integer::New(info.GetIsolate(), 2),
4471 v8_str(info.GetIsolate(), "c"))
4472 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004473 info.GetReturnValue().Set(result);
Steve Blocka7e24c12009-10-30 11:49:00 +00004474}
4475
4476
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004477static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
4478 v8::Isolate* isolate = info.GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004479 v8::Local<v8::Array> result = v8::Array::New(isolate, 2);
4480 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
4481 CHECK(result->Set(context, v8::Integer::New(isolate, 0),
4482 v8::Number::New(isolate, 1))
4483 .FromJust());
4484 CHECK(result->Set(context, v8::Integer::New(isolate, 1),
4485 v8::Number::New(isolate, 10))
4486 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004487 info.GetReturnValue().Set(result);
Steve Blocka7e24c12009-10-30 11:49:00 +00004488}
4489
4490
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004491static void NamedGetter(v8::Local<v8::Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004492 const v8::PropertyCallbackInfo<v8::Value>& info) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004493 if (name->IsSymbol()) return;
4494 v8::String::Utf8Value n(v8::Local<v8::String>::Cast(name));
Steve Blocka7e24c12009-10-30 11:49:00 +00004495 if (strcmp(*n, "a") == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004496 info.GetReturnValue().Set(v8_str(info.GetIsolate(), "AA"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004497 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00004498 } else if (strcmp(*n, "b") == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004499 info.GetReturnValue().Set(v8_str(info.GetIsolate(), "BB"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004500 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00004501 } else if (strcmp(*n, "c") == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004502 info.GetReturnValue().Set(v8_str(info.GetIsolate(), "CC"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004503 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00004504 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004505 info.GetReturnValue().SetUndefined();
4506 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00004507 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004508 info.GetReturnValue().Set(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00004509}
4510
4511
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004512static void IndexedGetter(uint32_t index,
4513 const v8::PropertyCallbackInfo<v8::Value>& info) {
4514 info.GetReturnValue().Set(static_cast<double>(index + 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00004515}
4516
4517
4518TEST(InterceptorPropertyMirror) {
4519 // Create a V8 environment with debug access.
Steve Blocka7e24c12009-10-30 11:49:00 +00004520 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004521 v8::Isolate* isolate = env->GetIsolate();
4522 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004523 env.ExposeDebug();
4524
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004525 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00004526 // Create object with named interceptor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004527 v8::Local<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004528 named->SetHandler(v8::NamedPropertyHandlerConfiguration(
4529 NamedGetter, NULL, NULL, NULL, NamedEnum));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004530 CHECK(env->Global()
4531 ->Set(context, v8_str(isolate, "intercepted_named"),
4532 named->NewInstance(context).ToLocalChecked())
4533 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004534
4535 // Create object with indexed interceptor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004536 v8::Local<v8::ObjectTemplate> indexed = v8::ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004537 indexed->SetHandler(v8::IndexedPropertyHandlerConfiguration(
4538 IndexedGetter, NULL, NULL, NULL, IndexedEnum));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004539 CHECK(env->Global()
4540 ->Set(context, v8_str(isolate, "intercepted_indexed"),
4541 indexed->NewInstance(context).ToLocalChecked())
4542 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004543
4544 // Create object with both named and indexed interceptor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004545 v8::Local<v8::ObjectTemplate> both = v8::ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004546 both->SetHandler(v8::NamedPropertyHandlerConfiguration(
4547 NamedGetter, NULL, NULL, NULL, NamedEnum));
4548 both->SetHandler(v8::IndexedPropertyHandlerConfiguration(
4549 IndexedGetter, NULL, NULL, NULL, IndexedEnum));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004550 CHECK(env->Global()
4551 ->Set(context, v8_str(isolate, "intercepted_both"),
4552 both->NewInstance(context).ToLocalChecked())
4553 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004554
4555 // Get mirrors for the three objects with interceptor.
4556 CompileRun(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004557 "var named_mirror = debug.MakeMirror(intercepted_named);"
4558 "var indexed_mirror = debug.MakeMirror(intercepted_indexed);"
4559 "var both_mirror = debug.MakeMirror(intercepted_both)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004560 CHECK(CompileRun("named_mirror instanceof debug.ObjectMirror")
4561 ->BooleanValue(context)
4562 .FromJust());
4563 CHECK(CompileRun("indexed_mirror instanceof debug.ObjectMirror")
4564 ->BooleanValue(context)
4565 .FromJust());
4566 CHECK(CompileRun("both_mirror instanceof debug.ObjectMirror")
4567 ->BooleanValue(context)
4568 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004569
4570 // Get the property names from the interceptors
4571 CompileRun(
4572 "named_names = named_mirror.propertyNames();"
4573 "indexed_names = indexed_mirror.propertyNames();"
4574 "both_names = both_mirror.propertyNames()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004575 CHECK_EQ(3, CompileRun("named_names.length")->Int32Value(context).FromJust());
4576 CHECK_EQ(2,
4577 CompileRun("indexed_names.length")->Int32Value(context).FromJust());
4578 CHECK_EQ(5, CompileRun("both_names.length")->Int32Value(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004579
4580 // Check the expected number of properties.
4581 const char* source;
4582 source = "named_mirror.properties().length";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004583 CHECK_EQ(3, CompileRun(source)->Int32Value(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004584
4585 source = "indexed_mirror.properties().length";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004586 CHECK_EQ(2, CompileRun(source)->Int32Value(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004587
4588 source = "both_mirror.properties().length";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004589 CHECK_EQ(5, CompileRun(source)->Int32Value(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004590
4591 // Get the interceptor properties for the object with only named interceptor.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004592 CompileRun("var named_values = named_mirror.properties()");
Steve Blocka7e24c12009-10-30 11:49:00 +00004593
4594 // Check that the properties are interceptor properties.
4595 for (int i = 0; i < 3; i++) {
4596 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004597 SNPrintF(buffer,
4598 "named_values[%d] instanceof debug.PropertyMirror", i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004599 CHECK(CompileRun(buffer.start())->BooleanValue(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004600
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004601 SNPrintF(buffer, "named_values[%d].isNative()", i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004602 CHECK(CompileRun(buffer.start())->BooleanValue(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004603 }
4604
4605 // Get the interceptor properties for the object with only indexed
4606 // interceptor.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004607 CompileRun("var indexed_values = indexed_mirror.properties()");
Steve Blocka7e24c12009-10-30 11:49:00 +00004608
4609 // Check that the properties are interceptor properties.
4610 for (int i = 0; i < 2; i++) {
4611 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004612 SNPrintF(buffer,
4613 "indexed_values[%d] instanceof debug.PropertyMirror", i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004614 CHECK(CompileRun(buffer.start())->BooleanValue(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004615 }
4616
4617 // Get the interceptor properties for the object with both types of
4618 // interceptors.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004619 CompileRun("var both_values = both_mirror.properties()");
Steve Blocka7e24c12009-10-30 11:49:00 +00004620
4621 // Check that the properties are interceptor properties.
4622 for (int i = 0; i < 5; i++) {
4623 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004624 SNPrintF(buffer, "both_values[%d] instanceof debug.PropertyMirror", i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004625 CHECK(CompileRun(buffer.start())->BooleanValue(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004626 }
4627
4628 // Check the property names.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004629 source = "both_values[0].name() == '1'";
4630 CHECK(CompileRun(source)->BooleanValue(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004631
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004632 source = "both_values[1].name() == '10'";
4633 CHECK(CompileRun(source)->BooleanValue(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004635 source = "both_values[2].name() == 'a'";
4636 CHECK(CompileRun(source)->BooleanValue(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004637
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004638 source = "both_values[3].name() == 'b'";
4639 CHECK(CompileRun(source)->BooleanValue(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004640
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004641 source = "both_values[4].name() == 'c'";
4642 CHECK(CompileRun(source)->BooleanValue(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004643}
4644
4645
4646TEST(HiddenPrototypePropertyMirror) {
4647 // Create a V8 environment with debug access.
Steve Blocka7e24c12009-10-30 11:49:00 +00004648 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004649 v8::Isolate* isolate = env->GetIsolate();
4650 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004651 env.ExposeDebug();
4652
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004653 v8::Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
4654 t0->InstanceTemplate()->Set(v8_str(isolate, "x"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004655 v8::Number::New(isolate, 0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004656 v8::Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004657 t1->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004658 t1->InstanceTemplate()->Set(v8_str(isolate, "y"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004659 v8::Number::New(isolate, 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004660 v8::Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004661 t2->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004662 t2->InstanceTemplate()->Set(v8_str(isolate, "z"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004663 v8::Number::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004664 v8::Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
4665 t3->InstanceTemplate()->Set(v8_str(isolate, "u"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004666 v8::Number::New(isolate, 3));
Steve Blocka7e24c12009-10-30 11:49:00 +00004667
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004668 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00004669 // Create object and set them on the global object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004670 v8::Local<v8::Object> o0 = t0->GetFunction(context)
4671 .ToLocalChecked()
4672 ->NewInstance(context)
4673 .ToLocalChecked();
4674 CHECK(env->Global()->Set(context, v8_str(isolate, "o0"), o0).FromJust());
4675 v8::Local<v8::Object> o1 = t1->GetFunction(context)
4676 .ToLocalChecked()
4677 ->NewInstance(context)
4678 .ToLocalChecked();
4679 CHECK(env->Global()->Set(context, v8_str(isolate, "o1"), o1).FromJust());
4680 v8::Local<v8::Object> o2 = t2->GetFunction(context)
4681 .ToLocalChecked()
4682 ->NewInstance(context)
4683 .ToLocalChecked();
4684 CHECK(env->Global()->Set(context, v8_str(isolate, "o2"), o2).FromJust());
4685 v8::Local<v8::Object> o3 = t3->GetFunction(context)
4686 .ToLocalChecked()
4687 ->NewInstance(context)
4688 .ToLocalChecked();
4689 CHECK(env->Global()->Set(context, v8_str(isolate, "o3"), o3).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004690
4691 // Get mirrors for the four objects.
4692 CompileRun(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004693 "var o0_mirror = debug.MakeMirror(o0);"
4694 "var o1_mirror = debug.MakeMirror(o1);"
4695 "var o2_mirror = debug.MakeMirror(o2);"
4696 "var o3_mirror = debug.MakeMirror(o3)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004697 CHECK(CompileRun("o0_mirror instanceof debug.ObjectMirror")
4698 ->BooleanValue(context)
4699 .FromJust());
4700 CHECK(CompileRun("o1_mirror instanceof debug.ObjectMirror")
4701 ->BooleanValue(context)
4702 .FromJust());
4703 CHECK(CompileRun("o2_mirror instanceof debug.ObjectMirror")
4704 ->BooleanValue(context)
4705 .FromJust());
4706 CHECK(CompileRun("o3_mirror instanceof debug.ObjectMirror")
4707 ->BooleanValue(context)
4708 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004709
4710 // Check that each object has one property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004711 CHECK_EQ(1, CompileRun("o0_mirror.propertyNames().length")
4712 ->Int32Value(context)
4713 .FromJust());
4714 CHECK_EQ(1, CompileRun("o1_mirror.propertyNames().length")
4715 ->Int32Value(context)
4716 .FromJust());
4717 CHECK_EQ(1, CompileRun("o2_mirror.propertyNames().length")
4718 ->Int32Value(context)
4719 .FromJust());
4720 CHECK_EQ(1, CompileRun("o3_mirror.propertyNames().length")
4721 ->Int32Value(context)
4722 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004723
4724 // Set o1 as prototype for o0. o1 has the hidden prototype flag so all
4725 // properties on o1 should be seen on o0.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004726 CHECK(o0->Set(context, v8_str(isolate, "__proto__"), o1).FromJust());
4727 CHECK_EQ(2, CompileRun("o0_mirror.propertyNames().length")
4728 ->Int32Value(context)
4729 .FromJust());
4730 CHECK_EQ(0, CompileRun("o0_mirror.property('x').value().value()")
4731 ->Int32Value(context)
4732 .FromJust());
4733 CHECK_EQ(1, CompileRun("o0_mirror.property('y').value().value()")
4734 ->Int32Value(context)
4735 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004736
4737 // Set o2 as prototype for o0 (it will end up after o1 as o1 has the hidden
4738 // prototype flag. o2 also has the hidden prototype flag so all properties
4739 // on o2 should be seen on o0 as well as properties on o1.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004740 CHECK(o0->Set(context, v8_str(isolate, "__proto__"), o2).FromJust());
4741 CHECK_EQ(3, CompileRun("o0_mirror.propertyNames().length")
4742 ->Int32Value(context)
4743 .FromJust());
4744 CHECK_EQ(0, CompileRun("o0_mirror.property('x').value().value()")
4745 ->Int32Value(context)
4746 .FromJust());
4747 CHECK_EQ(1, CompileRun("o0_mirror.property('y').value().value()")
4748 ->Int32Value(context)
4749 .FromJust());
4750 CHECK_EQ(2, CompileRun("o0_mirror.property('z').value().value()")
4751 ->Int32Value(context)
4752 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004753
4754 // Set o3 as prototype for o0 (it will end up after o1 and o2 as both o1 and
4755 // o2 has the hidden prototype flag. o3 does not have the hidden prototype
4756 // flag so properties on o3 should not be seen on o0 whereas the properties
4757 // from o1 and o2 should still be seen on o0.
4758 // Final prototype chain: o0 -> o1 -> o2 -> o3
4759 // Hidden prototypes: ^^ ^^
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004760 CHECK(o0->Set(context, v8_str(isolate, "__proto__"), o3).FromJust());
4761 CHECK_EQ(3, CompileRun("o0_mirror.propertyNames().length")
4762 ->Int32Value(context)
4763 .FromJust());
4764 CHECK_EQ(1, CompileRun("o3_mirror.propertyNames().length")
4765 ->Int32Value(context)
4766 .FromJust());
4767 CHECK_EQ(0, CompileRun("o0_mirror.property('x').value().value()")
4768 ->Int32Value(context)
4769 .FromJust());
4770 CHECK_EQ(1, CompileRun("o0_mirror.property('y').value().value()")
4771 ->Int32Value(context)
4772 .FromJust());
4773 CHECK_EQ(2, CompileRun("o0_mirror.property('z').value().value()")
4774 ->Int32Value(context)
4775 .FromJust());
4776 CHECK(CompileRun("o0_mirror.property('u').isUndefined()")
4777 ->BooleanValue(context)
4778 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004779
4780 // The prototype (__proto__) for o0 should be o3 as o1 and o2 are hidden.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004781 CHECK(CompileRun("o0_mirror.protoObject() == o3_mirror")
4782 ->BooleanValue(context)
4783 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004784}
4785
4786
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004787static void ProtperyXNativeGetter(
4788 v8::Local<v8::String> property,
4789 const v8::PropertyCallbackInfo<v8::Value>& info) {
4790 info.GetReturnValue().Set(10);
Steve Blocka7e24c12009-10-30 11:49:00 +00004791}
4792
4793
4794TEST(NativeGetterPropertyMirror) {
4795 // Create a V8 environment with debug access.
Steve Blocka7e24c12009-10-30 11:49:00 +00004796 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004797 v8::Isolate* isolate = env->GetIsolate();
4798 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004799 env.ExposeDebug();
4800
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004801 v8::Local<v8::Context> context = env.context();
4802 v8::Local<v8::String> name = v8_str(isolate, "x");
Steve Blocka7e24c12009-10-30 11:49:00 +00004803 // Create object with named accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004804 v8::Local<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
4805 named->SetAccessor(name, &ProtperyXNativeGetter, NULL, v8::Local<v8::Value>(),
4806 v8::DEFAULT, v8::None);
Steve Blocka7e24c12009-10-30 11:49:00 +00004807
4808 // Create object with named property getter.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004809 CHECK(env->Global()
4810 ->Set(context, v8_str(isolate, "instance"),
4811 named->NewInstance(context).ToLocalChecked())
4812 .FromJust());
4813 CHECK_EQ(10, CompileRun("instance.x")->Int32Value(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004814
4815 // Get mirror for the object with property getter.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004816 CompileRun("var instance_mirror = debug.MakeMirror(instance);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004817 CHECK(CompileRun("instance_mirror instanceof debug.ObjectMirror")
4818 ->BooleanValue(context)
4819 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004820
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004821 CompileRun("var named_names = instance_mirror.propertyNames();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004822 CHECK_EQ(1, CompileRun("named_names.length")->Int32Value(context).FromJust());
4823 CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue(context).FromJust());
4824 CHECK(CompileRun("instance_mirror.property('x').value().isNumber()")
4825 ->BooleanValue(context)
4826 .FromJust());
4827 CHECK(CompileRun("instance_mirror.property('x').value().value() == 10")
4828 ->BooleanValue(context)
4829 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004830}
4831
4832
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004833static void ProtperyXNativeGetterThrowingError(
4834 v8::Local<v8::String> property,
4835 const v8::PropertyCallbackInfo<v8::Value>& info) {
4836 CompileRun("throw new Error('Error message');");
Steve Blocka7e24c12009-10-30 11:49:00 +00004837}
4838
4839
4840TEST(NativeGetterThrowingErrorPropertyMirror) {
4841 // Create a V8 environment with debug access.
Steve Blocka7e24c12009-10-30 11:49:00 +00004842 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004843 v8::Isolate* isolate = env->GetIsolate();
4844 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004845 env.ExposeDebug();
4846
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004847 v8::Local<v8::Context> context = env.context();
4848 v8::Local<v8::String> name = v8_str(isolate, "x");
Steve Blocka7e24c12009-10-30 11:49:00 +00004849 // Create object with named accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004850 v8::Local<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004851 named->SetAccessor(name, &ProtperyXNativeGetterThrowingError, NULL,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004852 v8::Local<v8::Value>(), v8::DEFAULT, v8::None);
Steve Blocka7e24c12009-10-30 11:49:00 +00004853
4854 // Create object with named property getter.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004855 CHECK(env->Global()
4856 ->Set(context, v8_str(isolate, "instance"),
4857 named->NewInstance(context).ToLocalChecked())
4858 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004859
4860 // Get mirror for the object with property getter.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004861 CompileRun("var instance_mirror = debug.MakeMirror(instance);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004862 CHECK(CompileRun("instance_mirror instanceof debug.ObjectMirror")
4863 ->BooleanValue(context)
4864 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004865 CompileRun("named_names = instance_mirror.propertyNames();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004866 CHECK_EQ(1, CompileRun("named_names.length")->Int32Value(context).FromJust());
4867 CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue(context).FromJust());
4868 CHECK(CompileRun("instance_mirror.property('x').value().isError()")
4869 ->BooleanValue(context)
4870 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004871
4872 // Check that the message is that passed to the Error constructor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004873 CHECK(
4874 CompileRun(
4875 "instance_mirror.property('x').value().message() == 'Error message'")
4876 ->BooleanValue(context)
4877 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00004878}
4879
4880
Steve Blockd0582a62009-12-15 09:54:21 +00004881// Test that hidden properties object is not returned as an unnamed property
4882// among regular properties.
4883// See http://crbug.com/26491
4884TEST(NoHiddenProperties) {
4885 // Create a V8 environment with debug access.
Steve Blockd0582a62009-12-15 09:54:21 +00004886 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004887 v8::Isolate* isolate = env->GetIsolate();
4888 v8::HandleScope scope(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +00004889 env.ExposeDebug();
4890
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004891 v8::Local<v8::Context> context = env.context();
Steve Blockd0582a62009-12-15 09:54:21 +00004892 // Create an object in the global scope.
4893 const char* source = "var obj = {a: 1};";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004894 v8::Script::Compile(context, v8_str(isolate, source))
4895 .ToLocalChecked()
4896 ->Run(context)
4897 .ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00004898 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004899 env->Global()->Get(context, v8_str(isolate, "obj")).ToLocalChecked());
Steve Blockd0582a62009-12-15 09:54:21 +00004900 // Set a hidden property on the object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004901 obj->SetPrivate(
4902 env.context(),
4903 v8::Private::New(isolate, v8_str(isolate, "v8::test-debug::a")),
4904 v8::Int32::New(isolate, 11))
4905 .FromJust();
Steve Blockd0582a62009-12-15 09:54:21 +00004906
4907 // Get mirror for the object with property getter.
4908 CompileRun("var obj_mirror = debug.MakeMirror(obj);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004909 CHECK(CompileRun("obj_mirror instanceof debug.ObjectMirror")
4910 ->BooleanValue(context)
4911 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +00004912 CompileRun("var named_names = obj_mirror.propertyNames();");
4913 // There should be exactly one property. But there is also an unnamed
4914 // property whose value is hidden properties dictionary. The latter
4915 // property should not be in the list of reguar properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004916 CHECK_EQ(1, CompileRun("named_names.length")->Int32Value(context).FromJust());
4917 CHECK(CompileRun("named_names[0] == 'a'")->BooleanValue(context).FromJust());
4918 CHECK(CompileRun("obj_mirror.property('a').value().value() == 1")
4919 ->BooleanValue(context)
4920 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +00004921
4922 // Object created by t0 will become hidden prototype of object 'obj'.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004923 v8::Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
4924 t0->InstanceTemplate()->Set(v8_str(isolate, "b"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004925 v8::Number::New(isolate, 2));
Steve Blockd0582a62009-12-15 09:54:21 +00004926 t0->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004927 v8::Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
4928 t1->InstanceTemplate()->Set(v8_str(isolate, "c"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004929 v8::Number::New(isolate, 3));
Steve Blockd0582a62009-12-15 09:54:21 +00004930
4931 // Create proto objects, add hidden properties to them and set them on
4932 // the global object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004933 v8::Local<v8::Object> protoObj = t0->GetFunction(context)
4934 .ToLocalChecked()
4935 ->NewInstance(context)
4936 .ToLocalChecked();
4937 protoObj->SetPrivate(
4938 env.context(),
4939 v8::Private::New(isolate, v8_str(isolate, "v8::test-debug::b")),
4940 v8::Int32::New(isolate, 12))
4941 .FromJust();
4942 CHECK(env->Global()
4943 ->Set(context, v8_str(isolate, "protoObj"), protoObj)
4944 .FromJust());
4945 v8::Local<v8::Object> grandProtoObj = t1->GetFunction(context)
4946 .ToLocalChecked()
4947 ->NewInstance(context)
4948 .ToLocalChecked();
4949 grandProtoObj->SetPrivate(env.context(),
4950 v8::Private::New(
4951 isolate, v8_str(isolate, "v8::test-debug::c")),
4952 v8::Int32::New(isolate, 13))
4953 .FromJust();
4954 CHECK(env->Global()
4955 ->Set(context, v8_str(isolate, "grandProtoObj"), grandProtoObj)
4956 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +00004957
4958 // Setting prototypes: obj->protoObj->grandProtoObj
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004959 CHECK(protoObj->Set(context, v8_str(isolate, "__proto__"), grandProtoObj)
4960 .FromJust());
4961 CHECK(obj->Set(context, v8_str(isolate, "__proto__"), protoObj).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +00004962
4963 // Get mirror for the object with property getter.
4964 CompileRun("var obj_mirror = debug.MakeMirror(obj);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004965 CHECK(CompileRun("obj_mirror instanceof debug.ObjectMirror")
4966 ->BooleanValue(context)
4967 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +00004968 CompileRun("var named_names = obj_mirror.propertyNames();");
4969 // There should be exactly two properties - one from the object itself and
4970 // another from its hidden prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004971 CHECK_EQ(2, CompileRun("named_names.length")->Int32Value(context).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +00004972 CHECK(CompileRun("named_names.sort(); named_names[0] == 'a' &&"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004973 "named_names[1] == 'b'")
4974 ->BooleanValue(context)
4975 .FromJust());
4976 CHECK(CompileRun("obj_mirror.property('a').value().value() == 1")
4977 ->BooleanValue(context)
4978 .FromJust());
4979 CHECK(CompileRun("obj_mirror.property('b').value().value() == 2")
4980 ->BooleanValue(context)
4981 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +00004982}
4983
Steve Blocka7e24c12009-10-30 11:49:00 +00004984
4985// Multithreaded tests of JSON debugger protocol
4986
4987// Support classes
4988
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004989// Provides synchronization between N threads, where N is a template parameter.
4990// The Wait() call blocks a thread until it is called for the Nth time, then all
4991// calls return. Each ThreadBarrier object can only be used once.
4992template <int N>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004993class ThreadBarrier final {
Steve Blocka7e24c12009-10-30 11:49:00 +00004994 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004995 ThreadBarrier() : num_blocked_(0) {}
4996
4997 ~ThreadBarrier() {
4998 LockGuard<Mutex> lock_guard(&mutex_);
4999 if (num_blocked_ != 0) {
5000 CHECK_EQ(N, num_blocked_);
5001 }
5002 }
5003
5004 void Wait() {
5005 LockGuard<Mutex> lock_guard(&mutex_);
5006 CHECK_LT(num_blocked_, N);
5007 num_blocked_++;
5008 if (N == num_blocked_) {
5009 // Signal and unblock all waiting threads.
5010 cv_.NotifyAll();
5011 printf("BARRIER\n\n");
5012 fflush(stdout);
5013 } else { // Wait for the semaphore.
5014 while (num_blocked_ < N) {
5015 cv_.Wait(&mutex_);
5016 }
5017 }
5018 CHECK_EQ(N, num_blocked_);
5019 }
5020
Steve Blocka7e24c12009-10-30 11:49:00 +00005021 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005022 ConditionVariable cv_;
5023 Mutex mutex_;
Steve Blocka7e24c12009-10-30 11:49:00 +00005024 int num_blocked_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005025
5026 STATIC_ASSERT(N > 0);
5027
5028 DISALLOW_COPY_AND_ASSIGN(ThreadBarrier);
Steve Blocka7e24c12009-10-30 11:49:00 +00005029};
5030
Steve Blocka7e24c12009-10-30 11:49:00 +00005031
5032// A set containing enough barriers and semaphores for any of the tests.
5033class Barriers {
5034 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005035 Barriers() : semaphore_1(0), semaphore_2(0) {}
5036 ThreadBarrier<2> barrier_1;
5037 ThreadBarrier<2> barrier_2;
5038 ThreadBarrier<2> barrier_3;
5039 ThreadBarrier<2> barrier_4;
5040 ThreadBarrier<2> barrier_5;
5041 v8::base::Semaphore semaphore_1;
5042 v8::base::Semaphore semaphore_2;
Steve Blocka7e24c12009-10-30 11:49:00 +00005043};
5044
Steve Blocka7e24c12009-10-30 11:49:00 +00005045
5046// We match parts of the message to decide if it is a break message.
5047bool IsBreakEventMessage(char *message) {
5048 const char* type_event = "\"type\":\"event\"";
5049 const char* event_break = "\"event\":\"break\"";
5050 // Does the message contain both type:event and event:break?
5051 return strstr(message, type_event) != NULL &&
5052 strstr(message, event_break) != NULL;
5053}
5054
5055
Steve Block3ce2e202009-11-05 08:53:23 +00005056// We match parts of the message to decide if it is a exception message.
5057bool IsExceptionEventMessage(char *message) {
5058 const char* type_event = "\"type\":\"event\"";
5059 const char* event_exception = "\"event\":\"exception\"";
5060 // Does the message contain both type:event and event:exception?
5061 return strstr(message, type_event) != NULL &&
5062 strstr(message, event_exception) != NULL;
5063}
5064
5065
5066// We match the message wether it is an evaluate response message.
5067bool IsEvaluateResponseMessage(char* message) {
5068 const char* type_response = "\"type\":\"response\"";
5069 const char* command_evaluate = "\"command\":\"evaluate\"";
5070 // Does the message contain both type:response and command:evaluate?
5071 return strstr(message, type_response) != NULL &&
5072 strstr(message, command_evaluate) != NULL;
5073}
5074
5075
Andrei Popescu402d9372010-02-26 13:31:12 +00005076static int StringToInt(const char* s) {
5077 return atoi(s); // NOLINT
5078}
5079
5080
Steve Block3ce2e202009-11-05 08:53:23 +00005081// We match parts of the message to get evaluate result int value.
5082int GetEvaluateIntResult(char *message) {
5083 const char* value = "\"value\":";
5084 char* pos = strstr(message, value);
5085 if (pos == NULL) {
5086 return -1;
5087 }
5088 int res = -1;
Andrei Popescu402d9372010-02-26 13:31:12 +00005089 res = StringToInt(pos + strlen(value));
Steve Block3ce2e202009-11-05 08:53:23 +00005090 return res;
5091}
5092
5093
5094// We match parts of the message to get hit breakpoint id.
5095int GetBreakpointIdFromBreakEventMessage(char *message) {
5096 const char* breakpoints = "\"breakpoints\":[";
5097 char* pos = strstr(message, breakpoints);
5098 if (pos == NULL) {
5099 return -1;
5100 }
5101 int res = -1;
Andrei Popescu402d9372010-02-26 13:31:12 +00005102 res = StringToInt(pos + strlen(breakpoints));
Steve Block3ce2e202009-11-05 08:53:23 +00005103 return res;
5104}
5105
5106
Leon Clarked91b9f72010-01-27 17:25:45 +00005107// We match parts of the message to get total frames number.
5108int GetTotalFramesInt(char *message) {
5109 const char* prefix = "\"totalFrames\":";
5110 char* pos = strstr(message, prefix);
5111 if (pos == NULL) {
5112 return -1;
5113 }
5114 pos += strlen(prefix);
Andrei Popescu402d9372010-02-26 13:31:12 +00005115 int res = StringToInt(pos);
Leon Clarked91b9f72010-01-27 17:25:45 +00005116 return res;
5117}
5118
5119
Iain Merrick9ac36c92010-09-13 15:29:50 +01005120// We match parts of the message to get source line.
5121int GetSourceLineFromBreakEventMessage(char *message) {
5122 const char* source_line = "\"sourceLine\":";
5123 char* pos = strstr(message, source_line);
5124 if (pos == NULL) {
5125 return -1;
5126 }
5127 int res = -1;
5128 res = StringToInt(pos + strlen(source_line));
5129 return res;
5130}
5131
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005132
Steve Blocka7e24c12009-10-30 11:49:00 +00005133/* Test MessageQueues */
5134/* Tests the message queues that hold debugger commands and
5135 * response messages to the debugger. Fills queues and makes
5136 * them grow.
5137 */
5138Barriers message_queue_barriers;
5139
5140// This is the debugger thread, that executes no v8 calls except
5141// placing JSON debugger commands in the queue.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005142class MessageQueueDebuggerThread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +00005143 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005144 MessageQueueDebuggerThread()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005145 : Thread(Options("MessageQueueDebuggerThread")) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00005146 void Run();
5147};
5148
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005149
5150static void MessageHandler(const v8::Debug::Message& message) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005151 v8::Local<v8::String> json = message.GetJSON();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005152 v8::String::Utf8Value utf8(json);
5153 if (IsBreakEventMessage(*utf8)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005154 // Lets test script wait until break occurs to send commands.
5155 // Signals when a break is reported.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005156 message_queue_barriers.semaphore_2.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +00005157 }
5158
5159 // Allow message handler to block on a semaphore, to test queueing of
5160 // messages while blocked.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005161 message_queue_barriers.semaphore_1.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +00005162}
5163
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005164
Steve Blocka7e24c12009-10-30 11:49:00 +00005165void MessageQueueDebuggerThread::Run() {
5166 const int kBufferSize = 1000;
5167 uint16_t buffer_1[kBufferSize];
5168 uint16_t buffer_2[kBufferSize];
5169 const char* command_1 =
5170 "{\"seq\":117,"
5171 "\"type\":\"request\","
5172 "\"command\":\"evaluate\","
5173 "\"arguments\":{\"expression\":\"1+2\"}}";
5174 const char* command_2 =
5175 "{\"seq\":118,"
5176 "\"type\":\"request\","
5177 "\"command\":\"evaluate\","
5178 "\"arguments\":{\"expression\":\"1+a\"}}";
5179 const char* command_3 =
5180 "{\"seq\":119,"
5181 "\"type\":\"request\","
5182 "\"command\":\"evaluate\","
5183 "\"arguments\":{\"expression\":\"c.d * b\"}}";
5184 const char* command_continue =
5185 "{\"seq\":106,"
5186 "\"type\":\"request\","
5187 "\"command\":\"continue\"}";
5188 const char* command_single_step =
5189 "{\"seq\":107,"
5190 "\"type\":\"request\","
5191 "\"command\":\"continue\","
5192 "\"arguments\":{\"stepaction\":\"next\"}}";
5193
5194 /* Interleaved sequence of actions by the two threads:*/
5195 // Main thread compiles and runs source_1
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005196 message_queue_barriers.semaphore_1.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +00005197 message_queue_barriers.barrier_1.Wait();
5198 // Post 6 commands, filling the command queue and making it expand.
5199 // These calls return immediately, but the commands stay on the queue
5200 // until the execution of source_2.
5201 // Note: AsciiToUtf16 executes before SendCommand, so command is copied
5202 // to buffer before buffer is sent to SendCommand.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005203 v8::Isolate* isolate = CcTest::isolate();
5204 v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
5205 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
5206 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
5207 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
5208 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
Steve Blocka7e24c12009-10-30 11:49:00 +00005209 message_queue_barriers.barrier_2.Wait();
5210 // Main thread compiles and runs source_2.
5211 // Queued commands are executed at the start of compilation of source_2(
5212 // beforeCompile event).
5213 // Free the message handler to process all the messages from the queue. 7
5214 // messages are expected: 2 afterCompile events and 5 responses.
5215 // All the commands added so far will fail to execute as long as call stack
5216 // is empty on beforeCompile event.
5217 for (int i = 0; i < 6 ; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005218 message_queue_barriers.semaphore_1.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +00005219 }
5220 message_queue_barriers.barrier_3.Wait();
5221 // Main thread compiles and runs source_3.
5222 // Don't stop in the afterCompile handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005223 message_queue_barriers.semaphore_1.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +00005224 // source_3 includes a debugger statement, which causes a break event.
5225 // Wait on break event from hitting "debugger" statement
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005226 message_queue_barriers.semaphore_2.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +00005227 // These should execute after the "debugger" statement in source_2
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005228 v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
5229 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
5230 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
5231 v8::Debug::SendCommand(
5232 isolate, buffer_2, AsciiToUtf16(command_single_step, buffer_2));
Steve Blocka7e24c12009-10-30 11:49:00 +00005233 // Run after 2 break events, 4 responses.
5234 for (int i = 0; i < 6 ; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005235 message_queue_barriers.semaphore_1.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +00005236 }
5237 // Wait on break event after a single step executes.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005238 message_queue_barriers.semaphore_2.Wait();
5239 v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_2, buffer_1));
5240 v8::Debug::SendCommand(
5241 isolate, buffer_2, AsciiToUtf16(command_continue, buffer_2));
Steve Blocka7e24c12009-10-30 11:49:00 +00005242 // Run after 2 responses.
5243 for (int i = 0; i < 2 ; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005244 message_queue_barriers.semaphore_1.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +00005245 }
5246 // Main thread continues running source_3 to end, waits for this thread.
5247}
5248
Steve Blocka7e24c12009-10-30 11:49:00 +00005249
5250// This thread runs the v8 engine.
5251TEST(MessageQueues) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005252 MessageQueueDebuggerThread message_queue_debugger_thread;
Steve Block44f0eee2011-05-26 01:26:41 +01005253
Steve Blocka7e24c12009-10-30 11:49:00 +00005254 // Create a V8 environment
Steve Blocka7e24c12009-10-30 11:49:00 +00005255 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005256 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005257 v8::Debug::SetMessageHandler(env->GetIsolate(), MessageHandler);
Steve Blocka7e24c12009-10-30 11:49:00 +00005258 message_queue_debugger_thread.Start();
5259
5260 const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
5261 const char* source_2 = "e = 17;";
5262 const char* source_3 = "a = 4; debugger; a = 5; a = 6; a = 7;";
5263
5264 // See MessageQueueDebuggerThread::Run for interleaved sequence of
5265 // API calls and events in the two threads.
5266 CompileRun(source_1);
5267 message_queue_barriers.barrier_1.Wait();
5268 message_queue_barriers.barrier_2.Wait();
5269 CompileRun(source_2);
5270 message_queue_barriers.barrier_3.Wait();
5271 CompileRun(source_3);
5272 message_queue_debugger_thread.Join();
5273 fflush(stdout);
5274}
5275
5276
5277class TestClientData : public v8::Debug::ClientData {
5278 public:
5279 TestClientData() {
5280 constructor_call_counter++;
5281 }
5282 virtual ~TestClientData() {
5283 destructor_call_counter++;
5284 }
5285
5286 static void ResetCounters() {
5287 constructor_call_counter = 0;
5288 destructor_call_counter = 0;
5289 }
5290
5291 static int constructor_call_counter;
5292 static int destructor_call_counter;
5293};
5294
5295int TestClientData::constructor_call_counter = 0;
5296int TestClientData::destructor_call_counter = 0;
5297
5298
5299// Tests that MessageQueue doesn't destroy client data when expands and
5300// does destroy when it dies.
5301TEST(MessageQueueExpandAndDestroy) {
5302 TestClientData::ResetCounters();
5303 { // Create a scope for the queue.
5304 CommandMessageQueue queue(1);
5305 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5306 new TestClientData()));
5307 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5308 new TestClientData()));
5309 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5310 new TestClientData()));
5311 CHECK_EQ(0, TestClientData::destructor_call_counter);
5312 queue.Get().Dispose();
5313 CHECK_EQ(1, TestClientData::destructor_call_counter);
5314 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5315 new TestClientData()));
5316 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5317 new TestClientData()));
5318 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5319 new TestClientData()));
5320 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5321 new TestClientData()));
5322 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5323 new TestClientData()));
5324 CHECK_EQ(1, TestClientData::destructor_call_counter);
5325 queue.Get().Dispose();
5326 CHECK_EQ(2, TestClientData::destructor_call_counter);
5327 }
5328 // All the client data should be destroyed when the queue is destroyed.
5329 CHECK_EQ(TestClientData::destructor_call_counter,
5330 TestClientData::destructor_call_counter);
5331}
5332
5333
5334static int handled_client_data_instances_count = 0;
5335static void MessageHandlerCountingClientData(
5336 const v8::Debug::Message& message) {
5337 if (message.GetClientData() != NULL) {
5338 handled_client_data_instances_count++;
5339 }
5340}
5341
5342
5343// Tests that all client data passed to the debugger are sent to the handler.
5344TEST(SendClientDataToHandler) {
5345 // Create a V8 environment
Steve Blocka7e24c12009-10-30 11:49:00 +00005346 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005347 v8::Isolate* isolate = env->GetIsolate();
5348 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005349 TestClientData::ResetCounters();
5350 handled_client_data_instances_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005351 v8::Debug::SetMessageHandler(isolate, MessageHandlerCountingClientData);
Steve Blocka7e24c12009-10-30 11:49:00 +00005352 const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
5353 const int kBufferSize = 1000;
5354 uint16_t buffer[kBufferSize];
5355 const char* command_1 =
5356 "{\"seq\":117,"
5357 "\"type\":\"request\","
5358 "\"command\":\"evaluate\","
5359 "\"arguments\":{\"expression\":\"1+2\"}}";
5360 const char* command_2 =
5361 "{\"seq\":118,"
5362 "\"type\":\"request\","
5363 "\"command\":\"evaluate\","
5364 "\"arguments\":{\"expression\":\"1+a\"}}";
5365 const char* command_continue =
5366 "{\"seq\":106,"
5367 "\"type\":\"request\","
5368 "\"command\":\"continue\"}";
5369
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005370 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer),
Steve Blocka7e24c12009-10-30 11:49:00 +00005371 new TestClientData());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005372 v8::Debug::SendCommand(
5373 isolate, buffer, AsciiToUtf16(command_2, buffer), NULL);
5374 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
Steve Blocka7e24c12009-10-30 11:49:00 +00005375 new TestClientData());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005376 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
Steve Blocka7e24c12009-10-30 11:49:00 +00005377 new TestClientData());
5378 // All the messages will be processed on beforeCompile event.
5379 CompileRun(source_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005380 v8::Debug::SendCommand(
5381 isolate, buffer, AsciiToUtf16(command_continue, buffer));
Steve Blocka7e24c12009-10-30 11:49:00 +00005382 CHECK_EQ(3, TestClientData::constructor_call_counter);
5383 CHECK_EQ(TestClientData::constructor_call_counter,
5384 handled_client_data_instances_count);
5385 CHECK_EQ(TestClientData::constructor_call_counter,
5386 TestClientData::destructor_call_counter);
5387}
5388
5389
5390/* Test ThreadedDebugging */
5391/* This test interrupts a running infinite loop that is
5392 * occupying the v8 thread by a break command from the
5393 * debugger thread. It then changes the value of a
5394 * global object, to make the loop terminate.
5395 */
5396
5397Barriers threaded_debugging_barriers;
5398
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005399class V8Thread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +00005400 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005401 V8Thread() : Thread(Options("V8Thread")) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00005402 void Run();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005403 v8::Isolate* isolate() { return isolate_; }
5404
5405 private:
5406 v8::Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00005407};
5408
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005409class DebuggerThread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +00005410 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005411 explicit DebuggerThread(v8::Isolate* isolate)
5412 : Thread(Options("DebuggerThread")), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00005413 void Run();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005414
5415 private:
5416 v8::Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00005417};
5418
5419
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005420static void ThreadedAtBarrier1(
5421 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005422 threaded_debugging_barriers.barrier_1.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +00005423}
5424
5425
5426static void ThreadedMessageHandler(const v8::Debug::Message& message) {
5427 static char print_buffer[1000];
5428 v8::String::Value json(message.GetJSON());
5429 Utf16ToAscii(*json, json.length(), print_buffer);
5430 if (IsBreakEventMessage(print_buffer)) {
Iain Merrick9ac36c92010-09-13 15:29:50 +01005431 // Check that we are inside the while loop.
5432 int source_line = GetSourceLineFromBreakEventMessage(print_buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005433 CHECK(4 <= source_line && source_line <= 10);
Steve Blocka7e24c12009-10-30 11:49:00 +00005434 threaded_debugging_barriers.barrier_2.Wait();
5435 }
Steve Blocka7e24c12009-10-30 11:49:00 +00005436}
5437
5438
5439void V8Thread::Run() {
5440 const char* source =
5441 "flag = true;\n"
Steve Blocka7e24c12009-10-30 11:49:00 +00005442 "\n"
5443 "function foo() {\n"
5444 " var x = 1;\n"
5445 " while ( flag == true ) {\n"
5446 " if ( x == 1 ) {\n"
5447 " ThreadedAtBarrier1();\n"
5448 " }\n"
5449 " x = x + 1;\n"
5450 " }\n"
5451 "}\n"
5452 "\n"
5453 "foo();\n";
5454
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005455 v8::Isolate::CreateParams create_params;
5456 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
5457 isolate_ = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005458 threaded_debugging_barriers.barrier_3.Wait();
5459 {
5460 v8::Isolate::Scope isolate_scope(isolate_);
5461 DebugLocalContext env(isolate_);
5462 v8::HandleScope scope(isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005463 v8::Debug::SetMessageHandler(isolate_, &ThreadedMessageHandler);
5464 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005465 v8::ObjectTemplate::New(env->GetIsolate());
5466 global_template->Set(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005467 v8_str(env->GetIsolate(), "ThreadedAtBarrier1"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005468 v8::FunctionTemplate::New(isolate_, ThreadedAtBarrier1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005469 v8::Local<v8::Context> context =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005470 v8::Context::New(isolate_, NULL, global_template);
5471 v8::Context::Scope context_scope(context);
Steve Blocka7e24c12009-10-30 11:49:00 +00005472
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005473 CompileRun(source);
5474 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005475 threaded_debugging_barriers.barrier_4.Wait();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005476 isolate_->Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00005477}
5478
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005479
Steve Blocka7e24c12009-10-30 11:49:00 +00005480void DebuggerThread::Run() {
5481 const int kBufSize = 1000;
5482 uint16_t buffer[kBufSize];
5483
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005484 const char* command_1 =
5485 "{\"seq\":102,"
Steve Blocka7e24c12009-10-30 11:49:00 +00005486 "\"type\":\"request\","
5487 "\"command\":\"evaluate\","
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005488 "\"arguments\":{\"expression\":\"flag = false\"}}";
Steve Blocka7e24c12009-10-30 11:49:00 +00005489 const char* command_2 = "{\"seq\":103,"
5490 "\"type\":\"request\","
5491 "\"command\":\"continue\"}";
5492
5493 threaded_debugging_barriers.barrier_1.Wait();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005494 v8::Debug::DebugBreak(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +00005495 threaded_debugging_barriers.barrier_2.Wait();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005496 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer));
5497 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005498 threaded_debugging_barriers.barrier_4.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +00005499}
5500
Steve Blocka7e24c12009-10-30 11:49:00 +00005501
5502TEST(ThreadedDebugging) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005503 V8Thread v8_thread;
Steve Block44f0eee2011-05-26 01:26:41 +01005504
Steve Blocka7e24c12009-10-30 11:49:00 +00005505 // Create a V8 environment
Steve Blocka7e24c12009-10-30 11:49:00 +00005506 v8_thread.Start();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005507 threaded_debugging_barriers.barrier_3.Wait();
5508 DebuggerThread debugger_thread(v8_thread.isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00005509 debugger_thread.Start();
5510
5511 v8_thread.Join();
5512 debugger_thread.Join();
5513}
5514
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005515
Steve Blocka7e24c12009-10-30 11:49:00 +00005516/* Test RecursiveBreakpoints */
5517/* In this test, the debugger evaluates a function with a breakpoint, after
5518 * hitting a breakpoint in another function. We do this with both values
5519 * of the flag enabling recursive breakpoints, and verify that the second
5520 * breakpoint is hit when enabled, and missed when disabled.
5521 */
5522
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005523class BreakpointsV8Thread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +00005524 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005525 BreakpointsV8Thread() : Thread(Options("BreakpointsV8Thread")) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00005526 void Run();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005527
5528 v8::Isolate* isolate() { return isolate_; }
5529
5530 private:
5531 v8::Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00005532};
5533
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005534class BreakpointsDebuggerThread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +00005535 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005536 BreakpointsDebuggerThread(bool global_evaluate, v8::Isolate* isolate)
5537 : Thread(Options("BreakpointsDebuggerThread")),
5538 global_evaluate_(global_evaluate),
5539 isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00005540 void Run();
Leon Clarked91b9f72010-01-27 17:25:45 +00005541
5542 private:
5543 bool global_evaluate_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005544 v8::Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00005545};
5546
5547
5548Barriers* breakpoints_barriers;
Steve Block3ce2e202009-11-05 08:53:23 +00005549int break_event_breakpoint_id;
5550int evaluate_int_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00005551
5552static void BreakpointsMessageHandler(const v8::Debug::Message& message) {
5553 static char print_buffer[1000];
5554 v8::String::Value json(message.GetJSON());
5555 Utf16ToAscii(*json, json.length(), print_buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00005556
Steve Blocka7e24c12009-10-30 11:49:00 +00005557 if (IsBreakEventMessage(print_buffer)) {
Steve Block3ce2e202009-11-05 08:53:23 +00005558 break_event_breakpoint_id =
5559 GetBreakpointIdFromBreakEventMessage(print_buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005560 breakpoints_barriers->semaphore_1.Signal();
Steve Block3ce2e202009-11-05 08:53:23 +00005561 } else if (IsEvaluateResponseMessage(print_buffer)) {
5562 evaluate_int_result = GetEvaluateIntResult(print_buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005563 breakpoints_barriers->semaphore_1.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +00005564 }
5565}
5566
5567
5568void BreakpointsV8Thread::Run() {
5569 const char* source_1 = "var y_global = 3;\n"
5570 "function cat( new_value ) {\n"
5571 " var x = new_value;\n"
Steve Block3ce2e202009-11-05 08:53:23 +00005572 " y_global = y_global + 4;\n"
Steve Blocka7e24c12009-10-30 11:49:00 +00005573 " x = 3 * x + 1;\n"
Steve Block3ce2e202009-11-05 08:53:23 +00005574 " y_global = y_global + 5;\n"
Steve Blocka7e24c12009-10-30 11:49:00 +00005575 " return x;\n"
5576 "}\n"
5577 "\n"
5578 "function dog() {\n"
5579 " var x = 1;\n"
5580 " x = y_global;"
5581 " var z = 3;"
5582 " x += 100;\n"
5583 " return x;\n"
5584 "}\n"
5585 "\n";
5586 const char* source_2 = "cat(17);\n"
5587 "cat(19);\n";
5588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005589 v8::Isolate::CreateParams create_params;
5590 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
5591 isolate_ = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005592 breakpoints_barriers->barrier_3.Wait();
5593 {
5594 v8::Isolate::Scope isolate_scope(isolate_);
5595 DebugLocalContext env(isolate_);
5596 v8::HandleScope scope(isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005597 v8::Debug::SetMessageHandler(isolate_, &BreakpointsMessageHandler);
Steve Blocka7e24c12009-10-30 11:49:00 +00005598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005599 CompileRun(source_1);
5600 breakpoints_barriers->barrier_1.Wait();
5601 breakpoints_barriers->barrier_2.Wait();
5602 CompileRun(source_2);
5603 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005604 breakpoints_barriers->barrier_4.Wait();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005605 isolate_->Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00005606}
5607
5608
5609void BreakpointsDebuggerThread::Run() {
5610 const int kBufSize = 1000;
5611 uint16_t buffer[kBufSize];
5612
5613 const char* command_1 = "{\"seq\":101,"
5614 "\"type\":\"request\","
5615 "\"command\":\"setbreakpoint\","
5616 "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
5617 const char* command_2 = "{\"seq\":102,"
5618 "\"type\":\"request\","
5619 "\"command\":\"setbreakpoint\","
5620 "\"arguments\":{\"type\":\"function\",\"target\":\"dog\",\"line\":3}}";
Leon Clarked91b9f72010-01-27 17:25:45 +00005621 const char* command_3;
5622 if (this->global_evaluate_) {
5623 command_3 = "{\"seq\":103,"
5624 "\"type\":\"request\","
5625 "\"command\":\"evaluate\","
5626 "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false,"
5627 "\"global\":true}}";
5628 } else {
5629 command_3 = "{\"seq\":103,"
5630 "\"type\":\"request\","
5631 "\"command\":\"evaluate\","
5632 "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false}}";
5633 }
5634 const char* command_4;
5635 if (this->global_evaluate_) {
5636 command_4 = "{\"seq\":104,"
5637 "\"type\":\"request\","
5638 "\"command\":\"evaluate\","
5639 "\"arguments\":{\"expression\":\"100 + 8\",\"disable_break\":true,"
5640 "\"global\":true}}";
5641 } else {
5642 command_4 = "{\"seq\":104,"
5643 "\"type\":\"request\","
5644 "\"command\":\"evaluate\","
5645 "\"arguments\":{\"expression\":\"x + 1\",\"disable_break\":true}}";
5646 }
Steve Block3ce2e202009-11-05 08:53:23 +00005647 const char* command_5 = "{\"seq\":105,"
Steve Blocka7e24c12009-10-30 11:49:00 +00005648 "\"type\":\"request\","
5649 "\"command\":\"continue\"}";
Steve Block3ce2e202009-11-05 08:53:23 +00005650 const char* command_6 = "{\"seq\":106,"
Steve Blocka7e24c12009-10-30 11:49:00 +00005651 "\"type\":\"request\","
5652 "\"command\":\"continue\"}";
Leon Clarked91b9f72010-01-27 17:25:45 +00005653 const char* command_7;
5654 if (this->global_evaluate_) {
5655 command_7 = "{\"seq\":107,"
5656 "\"type\":\"request\","
5657 "\"command\":\"evaluate\","
5658 "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true,"
5659 "\"global\":true}}";
5660 } else {
5661 command_7 = "{\"seq\":107,"
5662 "\"type\":\"request\","
5663 "\"command\":\"evaluate\","
5664 "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true}}";
5665 }
Steve Block3ce2e202009-11-05 08:53:23 +00005666 const char* command_8 = "{\"seq\":108,"
Steve Blocka7e24c12009-10-30 11:49:00 +00005667 "\"type\":\"request\","
5668 "\"command\":\"continue\"}";
5669
5670
5671 // v8 thread initializes, runs source_1
5672 breakpoints_barriers->barrier_1.Wait();
Steve Block3ce2e202009-11-05 08:53:23 +00005673 // 1:Set breakpoint in cat() (will get id 1).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005674 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer));
Steve Block3ce2e202009-11-05 08:53:23 +00005675 // 2:Set breakpoint in dog() (will get id 2).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005676 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer));
Steve Blocka7e24c12009-10-30 11:49:00 +00005677 breakpoints_barriers->barrier_2.Wait();
Steve Block3ce2e202009-11-05 08:53:23 +00005678 // V8 thread starts compiling source_2.
Steve Blocka7e24c12009-10-30 11:49:00 +00005679 // Automatic break happens, to run queued commands
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005680 // breakpoints_barriers->semaphore_1.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +00005681 // Commands 1 through 3 run, thread continues.
5682 // v8 thread runs source_2 to breakpoint in cat().
5683 // message callback receives break event.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005684 breakpoints_barriers->semaphore_1.Wait();
Steve Block3ce2e202009-11-05 08:53:23 +00005685 // Must have hit breakpoint #1.
5686 CHECK_EQ(1, break_event_breakpoint_id);
Steve Blocka7e24c12009-10-30 11:49:00 +00005687 // 4:Evaluate dog() (which has a breakpoint).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005688 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_3, buffer));
Steve Block3ce2e202009-11-05 08:53:23 +00005689 // V8 thread hits breakpoint in dog().
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005690 breakpoints_barriers->semaphore_1.Wait(); // wait for break event
Steve Block3ce2e202009-11-05 08:53:23 +00005691 // Must have hit breakpoint #2.
5692 CHECK_EQ(2, break_event_breakpoint_id);
5693 // 5:Evaluate (x + 1).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005694 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_4, buffer));
Steve Block3ce2e202009-11-05 08:53:23 +00005695 // Evaluate (x + 1) finishes.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005696 breakpoints_barriers->semaphore_1.Wait();
Steve Block3ce2e202009-11-05 08:53:23 +00005697 // Must have result 108.
5698 CHECK_EQ(108, evaluate_int_result);
5699 // 6:Continue evaluation of dog().
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005700 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_5, buffer));
Steve Block3ce2e202009-11-05 08:53:23 +00005701 // Evaluate dog() finishes.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005702 breakpoints_barriers->semaphore_1.Wait();
Steve Block3ce2e202009-11-05 08:53:23 +00005703 // Must have result 107.
5704 CHECK_EQ(107, evaluate_int_result);
Steve Blocka7e24c12009-10-30 11:49:00 +00005705 // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint
5706 // in cat(19).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005707 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_6, buffer));
Steve Block3ce2e202009-11-05 08:53:23 +00005708 // Message callback gets break event.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005709 breakpoints_barriers->semaphore_1.Wait(); // wait for break event
Steve Block3ce2e202009-11-05 08:53:23 +00005710 // Must have hit breakpoint #1.
5711 CHECK_EQ(1, break_event_breakpoint_id);
5712 // 8: Evaluate dog() with breaks disabled.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005713 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_7, buffer));
Steve Block3ce2e202009-11-05 08:53:23 +00005714 // Evaluate dog() finishes.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005715 breakpoints_barriers->semaphore_1.Wait();
Steve Block3ce2e202009-11-05 08:53:23 +00005716 // Must have result 116.
5717 CHECK_EQ(116, evaluate_int_result);
Steve Blocka7e24c12009-10-30 11:49:00 +00005718 // 9: Continue evaluation of source2, reach end.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005719 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_8, buffer));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005720 breakpoints_barriers->barrier_4.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +00005721}
5722
Leon Clarke888f6722010-01-27 15:57:47 +00005723
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005724void TestRecursiveBreakpointsGeneric(bool global_evaluate) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005725 BreakpointsV8Thread breakpoints_v8_thread;
Leon Clarked91b9f72010-01-27 17:25:45 +00005726
Steve Blocka7e24c12009-10-30 11:49:00 +00005727 // Create a V8 environment
5728 Barriers stack_allocated_breakpoints_barriers;
Steve Blocka7e24c12009-10-30 11:49:00 +00005729 breakpoints_barriers = &stack_allocated_breakpoints_barriers;
5730
5731 breakpoints_v8_thread.Start();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005732 breakpoints_barriers->barrier_3.Wait();
5733 BreakpointsDebuggerThread breakpoints_debugger_thread(
5734 global_evaluate, breakpoints_v8_thread.isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00005735 breakpoints_debugger_thread.Start();
5736
5737 breakpoints_v8_thread.Join();
5738 breakpoints_debugger_thread.Join();
5739}
5740
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005741
Leon Clarked91b9f72010-01-27 17:25:45 +00005742TEST(RecursiveBreakpoints) {
5743 TestRecursiveBreakpointsGeneric(false);
5744}
5745
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005746
Leon Clarked91b9f72010-01-27 17:25:45 +00005747TEST(RecursiveBreakpointsGlobal) {
5748 TestRecursiveBreakpointsGeneric(true);
5749}
5750
Steve Blocka7e24c12009-10-30 11:49:00 +00005751
Steve Blocka7e24c12009-10-30 11:49:00 +00005752TEST(SetDebugEventListenerOnUninitializedVM) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005753 v8::Debug::SetDebugEventListener(CcTest::isolate(), DummyDebugEventListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00005754}
5755
5756
5757static void DummyMessageHandler(const v8::Debug::Message& message) {
5758}
5759
5760
5761TEST(SetMessageHandlerOnUninitializedVM) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005762 v8::Debug::SetMessageHandler(CcTest::isolate(), DummyMessageHandler);
Steve Blocka7e24c12009-10-30 11:49:00 +00005763}
5764
5765
5766// Source for a JavaScript function which returns the data parameter of a
5767// function called in the context of the debugger. If no data parameter is
5768// passed it throws an exception.
5769static const char* debugger_call_with_data_source =
5770 "function debugger_call_with_data(exec_state, data) {"
5771 " if (data) return data;"
5772 " throw 'No data!'"
5773 "}";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005774v8::Local<v8::Function> debugger_call_with_data;
Steve Blocka7e24c12009-10-30 11:49:00 +00005775
5776
5777// Source for a JavaScript function which returns the data parameter of a
5778// function called in the context of the debugger. If no data parameter is
5779// passed it throws an exception.
5780static const char* debugger_call_with_closure_source =
5781 "var x = 3;"
5782 "(function (exec_state) {"
5783 " if (exec_state.y) return x - 1;"
5784 " exec_state.y = x;"
5785 " return exec_state.y"
5786 "})";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005787v8::Local<v8::Function> debugger_call_with_closure;
Steve Blocka7e24c12009-10-30 11:49:00 +00005788
5789// Function to retrieve the number of JavaScript frames by calling a JavaScript
5790// in the debugger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005791static void CheckFrameCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005792 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
5793 CHECK(v8::Debug::Call(context, frame_count).ToLocalChecked()->IsNumber());
5794 CHECK_EQ(args[0]->Int32Value(context).FromJust(),
5795 v8::Debug::Call(context, frame_count)
5796 .ToLocalChecked()
5797 ->Int32Value(context)
5798 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005799}
5800
5801
5802// Function to retrieve the source line of the top JavaScript frame by calling a
5803// JavaScript function in the debugger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005804static void CheckSourceLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005805 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
5806 CHECK(
5807 v8::Debug::Call(context, frame_source_line).ToLocalChecked()->IsNumber());
5808 CHECK_EQ(args[0]->Int32Value(context).FromJust(),
5809 v8::Debug::Call(context, frame_source_line)
5810 .ToLocalChecked()
5811 ->Int32Value(context)
5812 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005813}
5814
5815
5816// Function to test passing an additional parameter to a JavaScript function
5817// called in the debugger. It also tests that functions called in the debugger
5818// can throw exceptions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005819static void CheckDataParameter(
5820 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005821 v8::Local<v8::String> data = v8_str(args.GetIsolate(), "Test");
5822 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
5823 CHECK(v8::Debug::Call(context, debugger_call_with_data, data)
5824 .ToLocalChecked()
5825 ->IsString());
Steve Blocka7e24c12009-10-30 11:49:00 +00005826
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005827 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005828 v8::TryCatch catcher(args.GetIsolate());
5829 CHECK(v8::Debug::Call(context, debugger_call_with_data).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005830 CHECK(catcher.HasCaught());
5831 CHECK(catcher.Exception()->IsString());
5832 }
Steve Blocka7e24c12009-10-30 11:49:00 +00005833}
5834
5835
5836// Function to test using a JavaScript with closure in the debugger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005837static void CheckClosure(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005838 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
5839 CHECK(v8::Debug::Call(context, debugger_call_with_closure)
5840 .ToLocalChecked()
5841 ->IsNumber());
5842 CHECK_EQ(3, v8::Debug::Call(context, debugger_call_with_closure)
5843 .ToLocalChecked()
5844 ->Int32Value(context)
5845 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005846}
5847
5848
5849// Test functions called through the debugger.
5850TEST(CallFunctionInDebugger) {
5851 // Create and enter a context with the functions CheckFrameCount,
5852 // CheckSourceLine and CheckDataParameter installed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005853 v8::Isolate* isolate = CcTest::isolate();
5854 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005855 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005856 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005857 global_template->Set(v8_str(isolate, "CheckFrameCount"),
5858 v8::FunctionTemplate::New(isolate, CheckFrameCount));
5859 global_template->Set(v8_str(isolate, "CheckSourceLine"),
5860 v8::FunctionTemplate::New(isolate, CheckSourceLine));
5861 global_template->Set(v8_str(isolate, "CheckDataParameter"),
5862 v8::FunctionTemplate::New(isolate, CheckDataParameter));
5863 global_template->Set(v8_str(isolate, "CheckClosure"),
5864 v8::FunctionTemplate::New(isolate, CheckClosure));
5865 v8::Local<v8::Context> context =
5866 v8::Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00005867 v8::Context::Scope context_scope(context);
5868
5869 // Compile a function for checking the number of JavaScript frames.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005870 v8::Script::Compile(context, v8_str(isolate, frame_count_source))
5871 .ToLocalChecked()
5872 ->Run(context)
5873 .ToLocalChecked();
5874 frame_count = v8::Local<v8::Function>::Cast(
5875 context->Global()
5876 ->Get(context, v8_str(isolate, "frame_count"))
5877 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005878
5879 // Compile a function for returning the source line for the top frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005880 v8::Script::Compile(context, v8_str(isolate, frame_source_line_source))
5881 .ToLocalChecked()
5882 ->Run(context)
5883 .ToLocalChecked();
5884 frame_source_line = v8::Local<v8::Function>::Cast(
5885 context->Global()
5886 ->Get(context, v8_str(isolate, "frame_source_line"))
5887 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005888
5889 // Compile a function returning the data parameter.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005890 v8::Script::Compile(context, v8_str(isolate, debugger_call_with_data_source))
5891 .ToLocalChecked()
5892 ->Run(context)
5893 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005894 debugger_call_with_data = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005895 context->Global()
5896 ->Get(context, v8_str(isolate, "debugger_call_with_data"))
5897 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005898
5899 // Compile a function capturing closure.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005900 debugger_call_with_closure = v8::Local<v8::Function>::Cast(
5901 v8::Script::Compile(context,
5902 v8_str(isolate, debugger_call_with_closure_source))
5903 .ToLocalChecked()
5904 ->Run(context)
5905 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005906
Steve Block6ded16b2010-05-10 14:33:55 +01005907 // Calling a function through the debugger returns 0 frames if there are
5908 // no JavaScript frames.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005909 CHECK(v8::Integer::New(isolate, 0)
5910 ->Equals(context,
5911 v8::Debug::Call(context, frame_count).ToLocalChecked())
5912 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005913
5914 // Test that the number of frames can be retrieved.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005915 v8::Script::Compile(context, v8_str(isolate, "CheckFrameCount(1)"))
5916 .ToLocalChecked()
5917 ->Run(context)
5918 .ToLocalChecked();
5919 v8::Script::Compile(context, v8_str(isolate,
5920 "function f() {"
5921 " CheckFrameCount(2);"
5922 "}; f()"))
5923 .ToLocalChecked()
5924 ->Run(context)
5925 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005926
5927 // Test that the source line can be retrieved.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005928 v8::Script::Compile(context, v8_str(isolate, "CheckSourceLine(0)"))
5929 .ToLocalChecked()
5930 ->Run(context)
5931 .ToLocalChecked();
5932 v8::Script::Compile(context, v8_str(isolate,
5933 "function f() {\n"
5934 " CheckSourceLine(1)\n"
5935 " CheckSourceLine(2)\n"
5936 " CheckSourceLine(3)\n"
5937 "}; f()"))
5938 .ToLocalChecked()
5939 ->Run(context)
5940 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005941
5942 // Test that a parameter can be passed to a function called in the debugger.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005943 v8::Script::Compile(context, v8_str(isolate, "CheckDataParameter()"))
5944 .ToLocalChecked()
5945 ->Run(context)
5946 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005947
5948 // Test that a function with closure can be run in the debugger.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005949 v8::Script::Compile(context, v8_str(isolate, "CheckClosure()"))
5950 .ToLocalChecked()
5951 ->Run(context)
5952 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005953
5954 // Test that the source line is correct when there is a line offset.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005955 v8::ScriptOrigin origin(v8_str(isolate, "test"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005956 v8::Integer::New(isolate, 7));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005957 v8::Script::Compile(context, v8_str(isolate, "CheckSourceLine(7)"), &origin)
5958 .ToLocalChecked()
5959 ->Run(context)
5960 .ToLocalChecked();
5961 v8::Script::Compile(context, v8_str(isolate,
5962 "function f() {\n"
5963 " CheckSourceLine(8)\n"
5964 " CheckSourceLine(9)\n"
5965 " CheckSourceLine(10)\n"
5966 "}; f()"),
5967 &origin)
5968 .ToLocalChecked()
5969 ->Run(context)
5970 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005971}
5972
5973
5974// Debugger message handler which counts the number of breaks.
5975static void SendContinueCommand();
5976static void MessageHandlerBreakPointHitCount(
5977 const v8::Debug::Message& message) {
5978 if (message.IsEvent() && message.GetEvent() == v8::Break) {
5979 // Count the number of breaks.
5980 break_point_hit_count++;
5981
5982 SendContinueCommand();
5983 }
5984}
5985
5986
5987// Test that clearing the debug event listener actually clears all break points
5988// and related information.
5989TEST(DebuggerUnload) {
5990 DebugLocalContext env;
5991
5992 // Check debugger is unloaded before it is used.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005993 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00005994
5995 // Set a debug event listener.
5996 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005997 v8::Debug::SetDebugEventListener(env->GetIsolate(),
5998 DebugEventBreakPointHitCount);
5999 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00006000 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006001 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006002 // Create a couple of functions for the test.
6003 v8::Local<v8::Function> foo =
6004 CompileFunction(&env, "function foo(){x=1}", "foo");
6005 v8::Local<v8::Function> bar =
6006 CompileFunction(&env, "function bar(){y=2}", "bar");
6007
6008 // Set some break points.
6009 SetBreakPoint(foo, 0);
6010 SetBreakPoint(foo, 4);
6011 SetBreakPoint(bar, 0);
6012 SetBreakPoint(bar, 4);
6013
6014 // Make sure that the break points are there.
6015 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006016 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006017 CHECK_EQ(2, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006018 bar->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006019 CHECK_EQ(4, break_point_hit_count);
6020 }
6021
6022 // Remove the debug event listener without clearing breakpoints. Do this
6023 // outside a handle scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006024 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
6025 CheckDebuggerUnloaded(env->GetIsolate(), true);
Steve Blocka7e24c12009-10-30 11:49:00 +00006026
6027 // Now set a debug message handler.
6028 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006029 v8::Debug::SetMessageHandler(env->GetIsolate(),
6030 MessageHandlerBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00006031 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006032 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006033
6034 // Get the test functions again.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006035 v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006036 env->Global()
6037 ->Get(context, v8_str(env->GetIsolate(), "foo"))
6038 .ToLocalChecked()));
Steve Blocka7e24c12009-10-30 11:49:00 +00006039
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006040 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006041 CHECK_EQ(0, break_point_hit_count);
6042
6043 // Set break points and run again.
6044 SetBreakPoint(foo, 0);
6045 SetBreakPoint(foo, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006046 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006047 CHECK_EQ(2, break_point_hit_count);
6048 }
6049
6050 // Remove the debug message handler without clearing breakpoints. Do this
6051 // outside a handle scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006052 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
6053 CheckDebuggerUnloaded(env->GetIsolate(), true);
Steve Blocka7e24c12009-10-30 11:49:00 +00006054}
6055
6056
6057// Sends continue command to the debugger.
6058static void SendContinueCommand() {
6059 const int kBufferSize = 1000;
6060 uint16_t buffer[kBufferSize];
6061 const char* command_continue =
6062 "{\"seq\":0,"
6063 "\"type\":\"request\","
6064 "\"command\":\"continue\"}";
6065
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006066 v8::Debug::SendCommand(
6067 CcTest::isolate(), buffer, AsciiToUtf16(command_continue, buffer));
Steve Blocka7e24c12009-10-30 11:49:00 +00006068}
6069
6070
6071// Debugger message handler which counts the number of times it is called.
6072static int message_handler_hit_count = 0;
6073static void MessageHandlerHitCount(const v8::Debug::Message& message) {
6074 message_handler_hit_count++;
6075
Steve Block3ce2e202009-11-05 08:53:23 +00006076 static char print_buffer[1000];
6077 v8::String::Value json(message.GetJSON());
6078 Utf16ToAscii(*json, json.length(), print_buffer);
6079 if (IsExceptionEventMessage(print_buffer)) {
6080 // Send a continue command for exception events.
6081 SendContinueCommand();
6082 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006083}
6084
6085
6086// Test clearing the debug message handler.
6087TEST(DebuggerClearMessageHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006088 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006089 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006090
6091 // Check debugger is unloaded before it is used.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006092 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006093
6094 // Set a debug message handler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006095 v8::Debug::SetMessageHandler(env->GetIsolate(), MessageHandlerHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00006096
6097 // Run code to throw a unhandled exception. This should end up in the message
6098 // handler.
6099 CompileRun("throw 1");
6100
6101 // The message handler should be called.
6102 CHECK_GT(message_handler_hit_count, 0);
6103
6104 // Clear debug message handler.
6105 message_handler_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006106 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
Steve Blocka7e24c12009-10-30 11:49:00 +00006107
6108 // Run code to throw a unhandled exception. This should end up in the message
6109 // handler.
6110 CompileRun("throw 1");
6111
6112 // The message handler should not be called more.
6113 CHECK_EQ(0, message_handler_hit_count);
6114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006115 CheckDebuggerUnloaded(env->GetIsolate(), true);
Steve Blocka7e24c12009-10-30 11:49:00 +00006116}
6117
6118
6119// Debugger message handler which clears the message handler while active.
6120static void MessageHandlerClearingMessageHandler(
6121 const v8::Debug::Message& message) {
6122 message_handler_hit_count++;
6123
6124 // Clear debug message handler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006125 v8::Debug::SetMessageHandler(message.GetIsolate(), nullptr);
Steve Blocka7e24c12009-10-30 11:49:00 +00006126}
6127
6128
6129// Test clearing the debug message handler while processing a debug event.
6130TEST(DebuggerClearMessageHandlerWhileActive) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006131 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006132 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006133
6134 // Check debugger is unloaded before it is used.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006135 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006136
6137 // Set a debug message handler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006138 v8::Debug::SetMessageHandler(env->GetIsolate(),
6139 MessageHandlerClearingMessageHandler);
Steve Blocka7e24c12009-10-30 11:49:00 +00006140
6141 // Run code to throw a unhandled exception. This should end up in the message
6142 // handler.
6143 CompileRun("throw 1");
6144
6145 // The message handler should be called.
6146 CHECK_EQ(1, message_handler_hit_count);
6147
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006148 CheckDebuggerUnloaded(env->GetIsolate(), true);
Steve Blocka7e24c12009-10-30 11:49:00 +00006149}
6150
6151
Steve Blocka7e24c12009-10-30 11:49:00 +00006152// Test for issue http://code.google.com/p/v8/issues/detail?id=289.
6153// Make sure that DebugGetLoadedScripts doesn't return scripts
6154// with disposed external source.
6155class EmptyExternalStringResource : public v8::String::ExternalStringResource {
6156 public:
6157 EmptyExternalStringResource() { empty_[0] = 0; }
6158 virtual ~EmptyExternalStringResource() {}
6159 virtual size_t length() const { return empty_.length(); }
6160 virtual const uint16_t* data() const { return empty_.start(); }
6161 private:
6162 ::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
6163};
6164
6165
6166TEST(DebugGetLoadedScripts) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006167 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006168 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006169 env.ExposeDebug();
6170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006171 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00006172 EmptyExternalStringResource source_ext_str;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006173 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006174 v8::String::NewExternalTwoByte(env->GetIsolate(), &source_ext_str)
6175 .ToLocalChecked();
6176 CHECK(v8::Script::Compile(context, source).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00006177 Handle<i::ExternalTwoByteString> i_source(
6178 i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
6179 // This situation can happen if source was an external string disposed
6180 // by its owner.
6181 i_source->set_resource(0);
6182
6183 bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
6184 i::FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006185 EnableDebugger(env->GetIsolate());
6186 v8::MaybeLocal<v8::Value> result =
6187 CompileRun(env.context(),
6188 "var scripts = %DebugGetLoadedScripts();"
6189 "var count = scripts.length;"
6190 "for (var i = 0; i < count; ++i) {"
6191 " var lines = scripts[i].lineCount();"
6192 " if (lines < 1) throw 'lineCount';"
6193 " var last = -1;"
6194 " for (var j = 0; j < lines; ++j) {"
6195 " var end = scripts[i].lineEnd(j);"
6196 " if (last >= end) throw 'lineEnd';"
6197 " last = end;"
6198 " }"
6199 "}");
6200 CHECK(!result.IsEmpty());
6201 DisableDebugger(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006202 // Must not crash while accessing line_ends.
6203 i::FLAG_allow_natives_syntax = allow_natives_syntax;
6204
6205 // Some scripts are retrieved - at least the number of native scripts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006206 CHECK_GT(env->Global()
6207 ->Get(context, v8_str(env->GetIsolate(), "count"))
6208 .ToLocalChecked()
6209 ->Int32Value(context)
6210 .FromJust(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006211 8);
Steve Blocka7e24c12009-10-30 11:49:00 +00006212}
6213
6214
6215// Test script break points set on lines.
6216TEST(ScriptNameAndData) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006217 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006218 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006219 env.ExposeDebug();
6220
6221 // Create functions for retrieving script name and data for the function on
6222 // the top frame when hitting a break point.
6223 frame_script_name = CompileFunction(&env,
6224 frame_script_name_source,
6225 "frame_script_name");
Steve Blocka7e24c12009-10-30 11:49:00 +00006226
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006227 v8::Debug::SetDebugEventListener(env->GetIsolate(),
6228 DebugEventBreakPointHitCount);
Steve Blocka7e24c12009-10-30 11:49:00 +00006229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006230 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00006231 // Test function source.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006232 v8::Local<v8::String> script = v8_str(env->GetIsolate(),
6233 "function f() {\n"
6234 " debugger;\n"
6235 "}\n");
Steve Blocka7e24c12009-10-30 11:49:00 +00006236
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006237 v8::ScriptOrigin origin1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006238 v8::ScriptOrigin(v8_str(env->GetIsolate(), "name"));
6239 v8::Local<v8::Script> script1 =
6240 v8::Script::Compile(context, script, &origin1).ToLocalChecked();
6241 script1->Run(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006242 v8::Local<v8::Function> f;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006243 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006244 env->Global()
6245 ->Get(context, v8_str(env->GetIsolate(), "f"))
6246 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00006247
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006248 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006249 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006250 CHECK_EQ(0, strcmp("name", last_script_name_hit));
Steve Blocka7e24c12009-10-30 11:49:00 +00006251
6252 // Compile the same script again without setting data. As the compilation
6253 // cache is disabled when debugging expect the data to be missing.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006254 v8::Script::Compile(context, script, &origin1)
6255 .ToLocalChecked()
6256 ->Run(context)
6257 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006258 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006259 env->Global()
6260 ->Get(context, v8_str(env->GetIsolate(), "f"))
6261 .ToLocalChecked());
6262 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006263 CHECK_EQ(2, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006264 CHECK_EQ(0, strcmp("name", last_script_name_hit));
Steve Blocka7e24c12009-10-30 11:49:00 +00006265
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006266 v8::Local<v8::String> data_obj_source =
6267 v8_str(env->GetIsolate(),
6268 "({ a: 'abc',\n"
6269 " b: 123,\n"
6270 " toString: function() { return this.a + ' ' + this.b; }\n"
6271 "})\n");
6272 v8::Script::Compile(context, data_obj_source)
6273 .ToLocalChecked()
6274 ->Run(context)
6275 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006276 v8::ScriptOrigin origin2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006277 v8::ScriptOrigin(v8_str(env->GetIsolate(), "new name"));
6278 v8::Local<v8::Script> script2 =
6279 v8::Script::Compile(context, script, &origin2).ToLocalChecked();
6280 script2->Run(context).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006281 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006282 env->Global()
6283 ->Get(context, v8_str(env->GetIsolate(), "f"))
6284 .ToLocalChecked());
6285 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006286 CHECK_EQ(3, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006287 CHECK_EQ(0, strcmp("new name", last_script_name_hit));
Andrei Popescu402d9372010-02-26 13:31:12 +00006288
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006289 v8::Local<v8::Script> script3 =
6290 v8::Script::Compile(context, script, &origin2).ToLocalChecked();
6291 script3->Run(context).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006292 f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006293 env->Global()
6294 ->Get(context, v8_str(env->GetIsolate(), "f"))
6295 .ToLocalChecked());
6296 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +00006297 CHECK_EQ(4, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00006298}
6299
6300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006301static v8::Local<v8::Context> expected_context;
6302static v8::Local<v8::Value> expected_context_data;
Steve Blocka7e24c12009-10-30 11:49:00 +00006303
6304
6305// Check that the expected context is the one generating the debug event.
6306static void ContextCheckMessageHandler(const v8::Debug::Message& message) {
6307 CHECK(message.GetEventContext() == expected_context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006308 CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals(
Steve Blocka7e24c12009-10-30 11:49:00 +00006309 expected_context_data));
6310 message_handler_hit_count++;
6311
Steve Block3ce2e202009-11-05 08:53:23 +00006312 static char print_buffer[1000];
6313 v8::String::Value json(message.GetJSON());
6314 Utf16ToAscii(*json, json.length(), print_buffer);
6315
Steve Blocka7e24c12009-10-30 11:49:00 +00006316 // Send a continue command for break events.
Steve Block3ce2e202009-11-05 08:53:23 +00006317 if (IsBreakEventMessage(print_buffer)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006318 SendContinueCommand();
6319 }
6320}
6321
6322
6323// Test which creates two contexts and sets different embedder data on each.
6324// Checks that this data is set correctly and that when the debug message
6325// handler is called the expected context is the one active.
6326TEST(ContextData) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006327 v8::Isolate* isolate = CcTest::isolate();
6328 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006329
6330 // Create two contexts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006331 v8::Local<v8::Context> context_1;
6332 v8::Local<v8::Context> context_2;
6333 v8::Local<v8::ObjectTemplate> global_template =
6334 v8::Local<v8::ObjectTemplate>();
6335 v8::Local<v8::Value> global_object = v8::Local<v8::Value>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006336 context_1 = v8::Context::New(isolate, NULL, global_template, global_object);
6337 context_2 = v8::Context::New(isolate, NULL, global_template, global_object);
6338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006339 v8::Debug::SetMessageHandler(isolate, ContextCheckMessageHandler);
Steve Blocka7e24c12009-10-30 11:49:00 +00006340
6341 // Default data value is undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006342 CHECK(context_1->GetEmbedderData(0)->IsUndefined());
6343 CHECK(context_2->GetEmbedderData(0)->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00006344
6345 // Set and check different data values.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006346 v8::Local<v8::String> data_1 = v8_str(isolate, "1");
6347 v8::Local<v8::String> data_2 = v8_str(isolate, "2");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006348 context_1->SetEmbedderData(0, data_1);
6349 context_2->SetEmbedderData(0, data_2);
6350 CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
6351 CHECK(context_2->GetEmbedderData(0)->StrictEquals(data_2));
Steve Blocka7e24c12009-10-30 11:49:00 +00006352
6353 // Simple test function which causes a break.
6354 const char* source = "function f() { debugger; }";
6355
6356 // Enter and run function in the first context.
6357 {
6358 v8::Context::Scope context_scope(context_1);
6359 expected_context = context_1;
6360 expected_context_data = data_1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006361 v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006362 f->Call(context_1, context_1->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006363 }
6364
6365
6366 // Enter and run function in the second context.
6367 {
6368 v8::Context::Scope context_scope(context_2);
6369 expected_context = context_2;
6370 expected_context_data = data_2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006371 v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006372 f->Call(context_2, context_2->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006373 }
6374
6375 // Two times compile event and two times break event.
6376 CHECK_GT(message_handler_hit_count, 4);
6377
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006378 v8::Debug::SetMessageHandler(isolate, nullptr);
6379 CheckDebuggerUnloaded(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006380}
6381
6382
6383// Debug message handler which issues a debug break when it hits a break event.
6384static int message_handler_break_hit_count = 0;
6385static void DebugBreakMessageHandler(const v8::Debug::Message& message) {
6386 // Schedule a debug break for break events.
6387 if (message.IsEvent() && message.GetEvent() == v8::Break) {
6388 message_handler_break_hit_count++;
6389 if (message_handler_break_hit_count == 1) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006390 v8::Debug::DebugBreak(message.GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006391 }
6392 }
6393
6394 // Issue a continue command if this event will not cause the VM to start
6395 // running.
6396 if (!message.WillStartRunning()) {
6397 SendContinueCommand();
6398 }
6399}
6400
6401
6402// Test that a debug break can be scheduled while in a message handler.
6403TEST(DebugBreakInMessageHandler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006404 i::FLAG_turbo_inlining = false; // Make sure g is not inlined into f.
Steve Blocka7e24c12009-10-30 11:49:00 +00006405 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006406 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006407
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006408 v8::Debug::SetMessageHandler(env->GetIsolate(), DebugBreakMessageHandler);
Steve Blocka7e24c12009-10-30 11:49:00 +00006409
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006410 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00006411 // Test functions.
6412 const char* script = "function f() { debugger; g(); } function g() { }";
6413 CompileRun(script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006414 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006415 env->Global()
6416 ->Get(context, v8_str(env->GetIsolate(), "f"))
6417 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006418 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006419 env->Global()
6420 ->Get(context, v8_str(env->GetIsolate(), "g"))
6421 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00006422
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006423 // Call f then g. The debugger statement in f will cause a break which will
Steve Blocka7e24c12009-10-30 11:49:00 +00006424 // cause another break.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006425 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006426 CHECK_EQ(2, message_handler_break_hit_count);
6427 // Calling g will not cause any additional breaks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006428 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006429 CHECK_EQ(2, message_handler_break_hit_count);
6430}
6431
6432
Steve Block6ded16b2010-05-10 14:33:55 +01006433#ifndef V8_INTERPRETED_REGEXP
Steve Blocka7e24c12009-10-30 11:49:00 +00006434// Debug event handler which gets the function on the top frame and schedules a
6435// break a number of times.
6436static void DebugEventDebugBreak(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006437 const v8::Debug::EventDetails& event_details) {
6438 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006439 v8::Local<v8::Object> exec_state = event_details.GetExecutionState();
6440 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
Steve Blocka7e24c12009-10-30 11:49:00 +00006441 if (event == v8::Break) {
6442 break_point_hit_count++;
6443
6444 // Get the name of the top frame function.
6445 if (!frame_function_name.IsEmpty()) {
6446 // Get the name of the function.
Ben Murdochb0fe1622011-05-05 13:52:32 +01006447 const int argc = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006448 v8::Local<v8::Value> argv[argc] = {
6449 exec_state, v8::Integer::New(CcTest::isolate(), 0)};
6450 v8::Local<v8::Value> result =
6451 frame_function_name->Call(context, exec_state, argc, argv)
6452 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006453 if (result->IsUndefined()) {
6454 last_function_hit[0] = '\0';
6455 } else {
6456 CHECK(result->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006457 v8::Local<v8::String> function_name(
6458 result->ToString(context).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006459 function_name->WriteUtf8(last_function_hit);
Steve Blocka7e24c12009-10-30 11:49:00 +00006460 }
6461 }
6462
6463 // Keep forcing breaks.
6464 if (break_point_hit_count < 20) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006465 v8::Debug::DebugBreak(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006466 }
6467 }
6468}
6469
6470
6471TEST(RegExpDebugBreak) {
6472 // This test only applies to native regexps.
Steve Blocka7e24c12009-10-30 11:49:00 +00006473 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006474 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006475 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00006476 // Create a function for checking the function when hitting a break point.
6477 frame_function_name = CompileFunction(&env,
6478 frame_function_name_source,
6479 "frame_function_name");
6480
6481 // Test RegExp which matches white spaces and comments at the begining of a
6482 // source line.
6483 const char* script =
6484 "var sourceLineBeginningSkip = /^(?:[ \\v\\h]*(?:\\/\\*.*?\\*\\/)*)*/;\n"
6485 "function f(s) { return s.match(sourceLineBeginningSkip)[0].length; }";
6486
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006487 v8::Local<v8::Function> f = CompileFunction(env->GetIsolate(), script, "f");
Steve Blocka7e24c12009-10-30 11:49:00 +00006488 const int argc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006489 v8::Local<v8::Value> argv[argc] = {
6490 v8_str(env->GetIsolate(), " /* xxx */ a=0;")};
6491 v8::Local<v8::Value> result =
6492 f->Call(context, env->Global(), argc, argv).ToLocalChecked();
6493 CHECK_EQ(12, result->Int32Value(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006495 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventDebugBreak);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006496 v8::Debug::DebugBreak(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006497 result = f->Call(context, env->Global(), argc, argv).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006498
6499 // Check that there was only one break event. Matching RegExp should not
6500 // cause Break events.
6501 CHECK_EQ(1, break_point_hit_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006502 CHECK_EQ(0, strcmp("f", last_function_hit));
Steve Blocka7e24c12009-10-30 11:49:00 +00006503}
Steve Block6ded16b2010-05-10 14:33:55 +01006504#endif // V8_INTERPRETED_REGEXP
Steve Blocka7e24c12009-10-30 11:49:00 +00006505
6506
6507// Common part of EvalContextData and NestedBreakEventContextData tests.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006508static void ExecuteScriptForContextCheck(
6509 v8::Debug::MessageHandler message_handler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006510 // Create a context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006511 v8::Local<v8::Context> context_1;
6512 v8::Local<v8::ObjectTemplate> global_template =
6513 v8::Local<v8::ObjectTemplate>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006514 context_1 =
6515 v8::Context::New(CcTest::isolate(), NULL, global_template);
6516
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006517 v8::Debug::SetMessageHandler(CcTest::isolate(), message_handler);
Steve Blocka7e24c12009-10-30 11:49:00 +00006518
6519 // Default data value is undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006520 CHECK(context_1->GetEmbedderData(0)->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00006521
6522 // Set and check a data value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006523 v8::Local<v8::String> data_1 = v8_str(CcTest::isolate(), "1");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006524 context_1->SetEmbedderData(0, data_1);
6525 CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
Steve Blocka7e24c12009-10-30 11:49:00 +00006526
6527 // Simple test function with eval that causes a break.
6528 const char* source = "function f() { eval('debugger;'); }";
6529
6530 // Enter and run function in the context.
6531 {
6532 v8::Context::Scope context_scope(context_1);
6533 expected_context = context_1;
6534 expected_context_data = data_1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006535 v8::Local<v8::Function> f = CompileFunction(CcTest::isolate(), source, "f");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006536 f->Call(context_1, context_1->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006537 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006538
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006539 v8::Debug::SetMessageHandler(CcTest::isolate(), nullptr);
Steve Blocka7e24c12009-10-30 11:49:00 +00006540}
6541
6542
6543// Test which creates a context and sets embedder data on it. Checks that this
6544// data is set correctly and that when the debug message handler is called for
6545// break event in an eval statement the expected context is the one returned by
6546// Message.GetEventContext.
6547TEST(EvalContextData) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006548 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006549
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006550 ExecuteScriptForContextCheck(ContextCheckMessageHandler);
Steve Blocka7e24c12009-10-30 11:49:00 +00006551
6552 // One time compile event and one time break event.
6553 CHECK_GT(message_handler_hit_count, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006554 CheckDebuggerUnloaded(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006555}
6556
6557
6558static bool sent_eval = false;
6559static int break_count = 0;
6560static int continue_command_send_count = 0;
6561// Check that the expected context is the one generating the debug event
6562// including the case of nested break event.
6563static void DebugEvalContextCheckMessageHandler(
6564 const v8::Debug::Message& message) {
6565 CHECK(message.GetEventContext() == expected_context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006566 CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals(
Steve Blocka7e24c12009-10-30 11:49:00 +00006567 expected_context_data));
6568 message_handler_hit_count++;
6569
Steve Block3ce2e202009-11-05 08:53:23 +00006570 static char print_buffer[1000];
6571 v8::String::Value json(message.GetJSON());
6572 Utf16ToAscii(*json, json.length(), print_buffer);
6573
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006574 v8::Isolate* isolate = message.GetIsolate();
Steve Block3ce2e202009-11-05 08:53:23 +00006575 if (IsBreakEventMessage(print_buffer)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006576 break_count++;
6577 if (!sent_eval) {
6578 sent_eval = true;
6579
6580 const int kBufferSize = 1000;
6581 uint16_t buffer[kBufferSize];
6582 const char* eval_command =
Ben Murdoch257744e2011-11-30 15:57:28 +00006583 "{\"seq\":0,"
6584 "\"type\":\"request\","
6585 "\"command\":\"evaluate\","
6586 "\"arguments\":{\"expression\":\"debugger;\","
6587 "\"global\":true,\"disable_break\":false}}";
Steve Blocka7e24c12009-10-30 11:49:00 +00006588
6589 // Send evaluate command.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006590 v8::Debug::SendCommand(
6591 isolate, buffer, AsciiToUtf16(eval_command, buffer));
Steve Blocka7e24c12009-10-30 11:49:00 +00006592 return;
6593 } else {
6594 // It's a break event caused by the evaluation request above.
6595 SendContinueCommand();
6596 continue_command_send_count++;
6597 }
Steve Block3ce2e202009-11-05 08:53:23 +00006598 } else if (IsEvaluateResponseMessage(print_buffer) &&
6599 continue_command_send_count < 2) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006600 // Response to the evaluation request. We're still on the breakpoint so
6601 // send continue.
6602 SendContinueCommand();
6603 continue_command_send_count++;
6604 }
6605}
6606
6607
6608// Tests that context returned for break event is correct when the event occurs
6609// in 'evaluate' debugger request.
6610TEST(NestedBreakEventContextData) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006611 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006612 break_count = 0;
6613 message_handler_hit_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00006614
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006615 ExecuteScriptForContextCheck(DebugEvalContextCheckMessageHandler);
Steve Blocka7e24c12009-10-30 11:49:00 +00006616
6617 // One time compile event and two times break event.
6618 CHECK_GT(message_handler_hit_count, 3);
6619
6620 // One break from the source and another from the evaluate request.
6621 CHECK_EQ(break_count, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006622 CheckDebuggerUnloaded(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006623}
6624
6625
Steve Blocka7e24c12009-10-30 11:49:00 +00006626// Debug event listener which counts the after compile events.
6627int after_compile_message_count = 0;
6628static void AfterCompileMessageHandler(const v8::Debug::Message& message) {
6629 // Count the number of scripts collected.
6630 if (message.IsEvent()) {
6631 if (message.GetEvent() == v8::AfterCompile) {
6632 after_compile_message_count++;
6633 } else if (message.GetEvent() == v8::Break) {
6634 SendContinueCommand();
6635 }
6636 }
6637}
6638
6639
6640// Tests that after compile event is sent as many times as there are scripts
6641// compiled.
6642TEST(AfterCompileMessageWhenMessageHandlerIsReset) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006643 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006644 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006645 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00006646 after_compile_message_count = 0;
6647 const char* script = "var a=1";
6648
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006649 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler);
6650 v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
6651 .ToLocalChecked()
6652 ->Run(context)
6653 .ToLocalChecked();
6654 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
Steve Blocka7e24c12009-10-30 11:49:00 +00006655
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006656 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006657 v8::Debug::DebugBreak(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006658 v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
6659 .ToLocalChecked()
6660 ->Run(context)
6661 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006662
6663 // Setting listener to NULL should cause debugger unload.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006664 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
6665 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006666
6667 // Compilation cache should be disabled when debugger is active.
6668 CHECK_EQ(2, after_compile_message_count);
6669}
6670
6671
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006672// Syntax error event handler which counts a number of events.
6673int compile_error_event_count = 0;
6674
6675static void CompileErrorEventCounterClear() {
6676 compile_error_event_count = 0;
6677}
6678
6679static void CompileErrorEventCounter(
6680 const v8::Debug::EventDetails& event_details) {
6681 v8::DebugEvent event = event_details.GetEvent();
6682
6683 if (event == v8::CompileError) {
6684 compile_error_event_count++;
6685 }
6686}
6687
6688
6689// Tests that syntax error event is sent as many times as there are scripts
6690// with syntax error compiled.
6691TEST(SyntaxErrorMessageOnSyntaxException) {
6692 DebugLocalContext env;
6693 v8::HandleScope scope(env->GetIsolate());
6694
6695 // For this test, we want to break on uncaught exceptions:
6696 ChangeBreakOnException(false, true);
6697
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006698 v8::Debug::SetDebugEventListener(env->GetIsolate(), CompileErrorEventCounter);
6699 v8::Local<v8::Context> context = env.context();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006700
6701 CompileErrorEventCounterClear();
6702
6703 // Check initial state.
6704 CHECK_EQ(0, compile_error_event_count);
6705
6706 // Throws SyntaxError: Unexpected end of input
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006707 CHECK(
6708 v8::Script::Compile(context, v8_str(env->GetIsolate(), "+++")).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006709 CHECK_EQ(1, compile_error_event_count);
6710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006711 CHECK(v8::Script::Compile(context, v8_str(env->GetIsolate(), "/sel\\/: \\"))
6712 .IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006713 CHECK_EQ(2, compile_error_event_count);
6714
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006715 v8::Local<v8::Script> script =
6716 v8::Script::Compile(context,
6717 v8_str(env->GetIsolate(), "JSON.parse('1234:')"))
6718 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006719 CHECK_EQ(2, compile_error_event_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006720 CHECK(script->Run(context).IsEmpty());
6721 CHECK_EQ(3, compile_error_event_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006723 v8::Script::Compile(context,
6724 v8_str(env->GetIsolate(), "new RegExp('/\\/\\\\');"))
6725 .ToLocalChecked();
6726 CHECK_EQ(3, compile_error_event_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006727
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006728 v8::Script::Compile(context, v8_str(env->GetIsolate(), "throw 1;"))
6729 .ToLocalChecked();
6730 CHECK_EQ(3, compile_error_event_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006731}
6732
6733
Steve Blocka7e24c12009-10-30 11:49:00 +00006734// Tests that break event is sent when message handler is reset.
6735TEST(BreakMessageWhenMessageHandlerIsReset) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006736 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006737 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006738 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00006739 after_compile_message_count = 0;
6740 const char* script = "function f() {};";
6741
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006742 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler);
6743 v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
6744 .ToLocalChecked()
6745 ->Run(context)
6746 .ToLocalChecked();
6747 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
Steve Blocka7e24c12009-10-30 11:49:00 +00006748
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006749 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006750 v8::Debug::DebugBreak(env->GetIsolate());
6751 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006752 env->Global()
6753 ->Get(context, v8_str(env->GetIsolate(), "f"))
6754 .ToLocalChecked());
6755 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006756
6757 // Setting message handler to NULL should cause debugger unload.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006758 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
6759 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006760
6761 // Compilation cache should be disabled when debugger is active.
6762 CHECK_EQ(1, after_compile_message_count);
6763}
6764
6765
6766static int exception_event_count = 0;
6767static void ExceptionMessageHandler(const v8::Debug::Message& message) {
6768 if (message.IsEvent() && message.GetEvent() == v8::Exception) {
6769 exception_event_count++;
6770 SendContinueCommand();
6771 }
6772}
6773
6774
6775// Tests that exception event is sent when message handler is reset.
6776TEST(ExceptionMessageWhenMessageHandlerIsReset) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006777 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006778 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch086aeea2011-05-13 15:57:08 +01006779
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006780 v8::Local<v8::Context> context = env.context();
Ben Murdoch086aeea2011-05-13 15:57:08 +01006781 // For this test, we want to break on uncaught exceptions:
6782 ChangeBreakOnException(false, true);
6783
Steve Blocka7e24c12009-10-30 11:49:00 +00006784 exception_event_count = 0;
6785 const char* script = "function f() {throw new Error()};";
6786
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006787 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler);
6788 v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
6789 .ToLocalChecked()
6790 ->Run(context)
6791 .ToLocalChecked();
6792 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
Steve Blocka7e24c12009-10-30 11:49:00 +00006793
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006794 v8::Debug::SetMessageHandler(env->GetIsolate(), ExceptionMessageHandler);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006795 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006796 env->Global()
6797 ->Get(context, v8_str(env->GetIsolate(), "f"))
6798 .ToLocalChecked());
6799 CHECK(f->Call(context, env->Global(), 0, NULL).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00006800
6801 // Setting message handler to NULL should cause debugger unload.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006802 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
6803 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006804
6805 CHECK_EQ(1, exception_event_count);
6806}
6807
6808
6809// Tests after compile event is sent when there are some provisional
6810// breakpoints out of the scripts lines range.
6811TEST(ProvisionalBreakpointOnLineOutOfRange) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006812 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006813 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006814 env.ExposeDebug();
6815 const char* script = "function f() {};";
6816 const char* resource_name = "test_resource";
6817
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006818 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler);
6819 v8::Local<v8::Context> context = env.context();
6820
Steve Blocka7e24c12009-10-30 11:49:00 +00006821 // Set a couple of provisional breakpoint on lines out of the script lines
6822 // range.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006823 int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name,
6824 3, -1 /* no column */);
6825 int sbp2 =
6826 SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, 5, 5);
Steve Blocka7e24c12009-10-30 11:49:00 +00006827
6828 after_compile_message_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00006829
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006830 v8::ScriptOrigin origin(v8_str(env->GetIsolate(), resource_name),
6831 v8::Integer::New(env->GetIsolate(), 10),
6832 v8::Integer::New(env->GetIsolate(), 1));
Steve Blocka7e24c12009-10-30 11:49:00 +00006833 // Compile a script whose first line number is greater than the breakpoints'
6834 // lines.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006835 v8::Script::Compile(context, v8_str(env->GetIsolate(), script), &origin)
6836 .ToLocalChecked()
6837 ->Run(context)
6838 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006839
6840 // If the script is compiled successfully there is exactly one after compile
6841 // event. In case of an exception in debugger code after compile event is not
6842 // sent.
6843 CHECK_EQ(1, after_compile_message_count);
6844
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006845 ClearBreakPointFromJS(env->GetIsolate(), sbp1);
6846 ClearBreakPointFromJS(env->GetIsolate(), sbp2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006847 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
Steve Blocka7e24c12009-10-30 11:49:00 +00006848}
6849
6850
6851static void BreakMessageHandler(const v8::Debug::Message& message) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006852 i::Isolate* isolate = CcTest::i_isolate();
Steve Blocka7e24c12009-10-30 11:49:00 +00006853 if (message.IsEvent() && message.GetEvent() == v8::Break) {
6854 // Count the number of breaks.
6855 break_point_hit_count++;
6856
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006857 i::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006858 message.GetJSON();
Steve Blocka7e24c12009-10-30 11:49:00 +00006859
6860 SendContinueCommand();
6861 } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006862 i::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006863
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006864 int current_count = break_point_hit_count;
Steve Blocka7e24c12009-10-30 11:49:00 +00006865
6866 // Force serialization to trigger some internal JS execution.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006867 message.GetJSON();
Steve Blocka7e24c12009-10-30 11:49:00 +00006868
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006869 CHECK_EQ(current_count, break_point_hit_count);
Steve Blocka7e24c12009-10-30 11:49:00 +00006870 }
6871}
6872
6873
6874// Test that if DebugBreak is forced it is ignored when code from
6875// debug-delay.js is executed.
6876TEST(NoDebugBreakInAfterCompileMessageHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006877 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006878 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006879 v8::Local<v8::Context> context = env.context();
Steve Blocka7e24c12009-10-30 11:49:00 +00006880
6881 // Register a debug event listener which sets the break flag and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006882 v8::Debug::SetMessageHandler(env->GetIsolate(), BreakMessageHandler);
Steve Blocka7e24c12009-10-30 11:49:00 +00006883
6884 // Set the debug break flag.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006885 v8::Debug::DebugBreak(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006886
6887 // Create a function for testing stepping.
6888 const char* src = "function f() { eval('var x = 10;'); } ";
6889 v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
6890
6891 // There should be only one break event.
6892 CHECK_EQ(1, break_point_hit_count);
6893
6894 // Set the debug break flag again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006895 v8::Debug::DebugBreak(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006896 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006897 // There should be one more break event when the script is evaluated in 'f'.
6898 CHECK_EQ(2, break_point_hit_count);
6899
6900 // Get rid of the debug message handler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006901 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
6902 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006903}
6904
6905
Leon Clarkee46be812010-01-19 14:06:41 +00006906static int counting_message_handler_counter;
6907
6908static void CountingMessageHandler(const v8::Debug::Message& message) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006909 if (message.IsResponse()) counting_message_handler_counter++;
Leon Clarkee46be812010-01-19 14:06:41 +00006910}
6911
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006912
Leon Clarkee46be812010-01-19 14:06:41 +00006913// Test that debug messages get processed when ProcessDebugMessages is called.
6914TEST(ProcessDebugMessages) {
Leon Clarkee46be812010-01-19 14:06:41 +00006915 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006916 v8::Isolate* isolate = env->GetIsolate();
6917 v8::HandleScope scope(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00006918
6919 counting_message_handler_counter = 0;
6920
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006921 v8::Debug::SetMessageHandler(isolate, CountingMessageHandler);
Leon Clarkee46be812010-01-19 14:06:41 +00006922
6923 const int kBufferSize = 1000;
6924 uint16_t buffer[kBufferSize];
6925 const char* scripts_command =
6926 "{\"seq\":0,"
6927 "\"type\":\"request\","
6928 "\"command\":\"scripts\"}";
6929
6930 // Send scripts command.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006931 v8::Debug::SendCommand(
6932 isolate, buffer, AsciiToUtf16(scripts_command, buffer));
Leon Clarkee46be812010-01-19 14:06:41 +00006933
6934 CHECK_EQ(0, counting_message_handler_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006935 v8::Debug::ProcessDebugMessages(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00006936 // At least one message should come
6937 CHECK_GE(counting_message_handler_counter, 1);
6938
6939 counting_message_handler_counter = 0;
6940
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006941 v8::Debug::SendCommand(
6942 isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6943 v8::Debug::SendCommand(
6944 isolate, buffer, AsciiToUtf16(scripts_command, buffer));
Leon Clarkee46be812010-01-19 14:06:41 +00006945 CHECK_EQ(0, counting_message_handler_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006946 v8::Debug::ProcessDebugMessages(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00006947 // At least two messages should come
6948 CHECK_GE(counting_message_handler_counter, 2);
6949
6950 // Get rid of the debug message handler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006951 v8::Debug::SetMessageHandler(isolate, nullptr);
6952 CheckDebuggerUnloaded(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006953}
6954
6955
6956class SendCommandThread;
6957static SendCommandThread* send_command_thread_ = NULL;
6958
6959
6960class SendCommandThread : public v8::base::Thread {
6961 public:
6962 explicit SendCommandThread(v8::Isolate* isolate)
6963 : Thread(Options("SendCommandThread")),
6964 semaphore_(0),
6965 isolate_(isolate) {}
6966
6967 static void CountingAndSignallingMessageHandler(
6968 const v8::Debug::Message& message) {
6969 if (message.IsResponse()) {
6970 counting_message_handler_counter++;
6971 send_command_thread_->semaphore_.Signal();
6972 }
6973 }
6974
6975 virtual void Run() {
6976 semaphore_.Wait();
6977 const int kBufferSize = 1000;
6978 uint16_t buffer[kBufferSize];
6979 const char* scripts_command =
6980 "{\"seq\":0,"
6981 "\"type\":\"request\","
6982 "\"command\":\"scripts\"}";
6983 int length = AsciiToUtf16(scripts_command, buffer);
6984 // Send scripts command.
6985
6986 for (int i = 0; i < 20; i++) {
6987 v8::base::ElapsedTimer timer;
6988 timer.Start();
6989 CHECK_EQ(i, counting_message_handler_counter);
6990 // Queue debug message.
6991 v8::Debug::SendCommand(isolate_, buffer, length);
6992 // Wait for the message handler to pick up the response.
6993 semaphore_.Wait();
6994 i::PrintF("iteration %d took %f ms\n", i,
6995 timer.Elapsed().InMillisecondsF());
6996 }
6997
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006998 isolate_->TerminateExecution();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006999 }
7000
7001 void StartSending() { semaphore_.Signal(); }
7002
7003 private:
7004 v8::base::Semaphore semaphore_;
7005 v8::Isolate* isolate_;
7006};
7007
7008
7009static void StartSendingCommands(
7010 const v8::FunctionCallbackInfo<v8::Value>& info) {
7011 send_command_thread_->StartSending();
7012}
7013
7014
7015TEST(ProcessDebugMessagesThreaded) {
7016 DebugLocalContext env;
7017 v8::Isolate* isolate = env->GetIsolate();
7018 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007019 v8::Local<v8::Context> context = env.context();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007020
7021 counting_message_handler_counter = 0;
7022
7023 v8::Debug::SetMessageHandler(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007024 isolate, SendCommandThread::CountingAndSignallingMessageHandler);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007025 send_command_thread_ = new SendCommandThread(isolate);
7026 send_command_thread_->Start();
7027
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007028 v8::Local<v8::FunctionTemplate> start =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007029 v8::FunctionTemplate::New(isolate, StartSendingCommands);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007030 CHECK(env->Global()
7031 ->Set(context, v8_str("start"),
7032 start->GetFunction(context).ToLocalChecked())
7033 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007034
7035 CompileRun("start(); while (true) { }");
7036
7037 CHECK_EQ(20, counting_message_handler_counter);
7038
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007039 v8::Debug::SetMessageHandler(isolate, nullptr);
7040 CheckDebuggerUnloaded(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00007041}
7042
7043
Steve Block6ded16b2010-05-10 14:33:55 +01007044struct BacktraceData {
Leon Clarked91b9f72010-01-27 17:25:45 +00007045 static int frame_counter;
7046 static void MessageHandler(const v8::Debug::Message& message) {
7047 char print_buffer[1000];
7048 v8::String::Value json(message.GetJSON());
7049 Utf16ToAscii(*json, json.length(), print_buffer, 1000);
7050
7051 if (strstr(print_buffer, "backtrace") == NULL) {
7052 return;
7053 }
7054 frame_counter = GetTotalFramesInt(print_buffer);
7055 }
7056};
7057
Steve Block6ded16b2010-05-10 14:33:55 +01007058int BacktraceData::frame_counter;
Leon Clarked91b9f72010-01-27 17:25:45 +00007059
7060
7061// Test that debug messages get processed when ProcessDebugMessages is called.
7062TEST(Backtrace) {
Leon Clarked91b9f72010-01-27 17:25:45 +00007063 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007064 v8::Isolate* isolate = env->GetIsolate();
7065 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007066 v8::Local<v8::Context> context = env.context();
Leon Clarked91b9f72010-01-27 17:25:45 +00007067
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007068 v8::Debug::SetMessageHandler(isolate, BacktraceData::MessageHandler);
Leon Clarked91b9f72010-01-27 17:25:45 +00007069
7070 const int kBufferSize = 1000;
7071 uint16_t buffer[kBufferSize];
7072 const char* scripts_command =
7073 "{\"seq\":0,"
7074 "\"type\":\"request\","
7075 "\"command\":\"backtrace\"}";
7076
7077 // Check backtrace from ProcessDebugMessages.
Steve Block6ded16b2010-05-10 14:33:55 +01007078 BacktraceData::frame_counter = -10;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007079 v8::Debug::SendCommand(
7080 isolate,
7081 buffer,
7082 AsciiToUtf16(scripts_command, buffer),
7083 NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007084 v8::Debug::ProcessDebugMessages(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01007085 CHECK_EQ(BacktraceData::frame_counter, 0);
Leon Clarked91b9f72010-01-27 17:25:45 +00007086
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007087 v8::Local<v8::String> void0 = v8_str(env->GetIsolate(), "void(0)");
7088 v8::Local<v8::Script> script = CompileWithOrigin(void0, void0);
Leon Clarked91b9f72010-01-27 17:25:45 +00007089
7090 // Check backtrace from "void(0)" script.
Steve Block6ded16b2010-05-10 14:33:55 +01007091 BacktraceData::frame_counter = -10;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007092 v8::Debug::SendCommand(
7093 isolate,
7094 buffer,
7095 AsciiToUtf16(scripts_command, buffer),
7096 NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007097 script->Run(context).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01007098 CHECK_EQ(BacktraceData::frame_counter, 1);
Leon Clarked91b9f72010-01-27 17:25:45 +00007099
7100 // Get rid of the debug message handler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007101 v8::Debug::SetMessageHandler(isolate, nullptr);
7102 CheckDebuggerUnloaded(isolate);
Leon Clarked91b9f72010-01-27 17:25:45 +00007103}
7104
7105
Steve Blocka7e24c12009-10-30 11:49:00 +00007106TEST(GetMirror) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007107 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007108 v8::Isolate* isolate = env->GetIsolate();
7109 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007110 v8::Local<v8::Context> context = env.context();
7111 v8::Local<v8::Value> obj =
7112 v8::Debug::GetMirror(context, v8_str(isolate, "hodja")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007113 v8::ScriptCompiler::Source source(v8_str(
7114 "function runTest(mirror) {"
7115 " return mirror.isString() && (mirror.length() == 5);"
7116 "}"
7117 ""
7118 "runTest;"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007119 v8::Local<v8::Function> run_test = v8::Local<v8::Function>::Cast(
7120 v8::ScriptCompiler::CompileUnboundScript(isolate, &source)
7121 .ToLocalChecked()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007122 ->BindToCurrentContext()
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007123 ->Run(context)
7124 .ToLocalChecked());
7125 v8::Local<v8::Value> result =
7126 run_test->Call(context, env->Global(), 1, &obj).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00007127 CHECK(result->IsTrue());
7128}
Steve Blockd0582a62009-12-15 09:54:21 +00007129
7130
7131// Test that the debug break flag works with function.apply.
7132TEST(DebugBreakFunctionApply) {
Steve Blockd0582a62009-12-15 09:54:21 +00007133 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007134 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007135 v8::Local<v8::Context> context = env.context();
Steve Blockd0582a62009-12-15 09:54:21 +00007136
7137 // Create a function for testing breaking in apply.
7138 v8::Local<v8::Function> foo = CompileFunction(
7139 &env,
7140 "function baz(x) { }"
7141 "function bar(x) { baz(); }"
7142 "function foo(){ bar.apply(this, [1]); }",
7143 "foo");
7144
7145 // Register a debug event listener which steps and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007146 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventBreakMax);
Steve Blockd0582a62009-12-15 09:54:21 +00007147
7148 // Set the debug break flag before calling the code using function.apply.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007149 v8::Debug::DebugBreak(env->GetIsolate());
Steve Blockd0582a62009-12-15 09:54:21 +00007150
7151 // Limit the number of debug breaks. This is a regression test for issue 493
7152 // where this test would enter an infinite loop.
7153 break_point_hit_count = 0;
7154 max_break_point_hit_count = 10000; // 10000 => infinite loop.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007155 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00007156
7157 // When keeping the debug break several break will happen.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007158 CHECK_GT(break_point_hit_count, 1);
Steve Blockd0582a62009-12-15 09:54:21 +00007159
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007160 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
7161 CheckDebuggerUnloaded(env->GetIsolate());
Steve Blockd0582a62009-12-15 09:54:21 +00007162}
7163
7164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007165v8::Local<v8::Context> debugee_context;
7166v8::Local<v8::Context> debugger_context;
Steve Blockd0582a62009-12-15 09:54:21 +00007167
7168
7169// Property getter that checks that current and calling contexts
7170// are both the debugee contexts.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007171static void NamedGetterWithCallingContextCheck(
Steve Blockd0582a62009-12-15 09:54:21 +00007172 v8::Local<v8::String> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007173 const v8::PropertyCallbackInfo<v8::Value>& info) {
7174 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(name), "a"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007175 v8::Local<v8::Context> current = info.GetIsolate()->GetCurrentContext();
Steve Blockd0582a62009-12-15 09:54:21 +00007176 CHECK(current == debugee_context);
7177 CHECK(current != debugger_context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007178 info.GetReturnValue().Set(1);
Steve Blockd0582a62009-12-15 09:54:21 +00007179}
7180
7181
7182// Debug event listener that checks if the first argument of a function is
7183// an object with property 'a' == 1. If the property has custom accessor
7184// this handler will eventually invoke it.
7185static void DebugEventGetAtgumentPropertyValue(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007186 const v8::Debug::EventDetails& event_details) {
7187 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007188 v8::Local<v8::Object> exec_state = event_details.GetExecutionState();
Steve Blockd0582a62009-12-15 09:54:21 +00007189 if (event == v8::Break) {
7190 break_point_hit_count++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007191 CHECK(debugger_context == CcTest::isolate()->GetCurrentContext());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007192 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(CompileRun(
Steve Blockd0582a62009-12-15 09:54:21 +00007193 "(function(exec_state) {\n"
7194 " return (exec_state.frame(0).argumentValue(0).property('a').\n"
7195 " value().value() == 1);\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007196 "})"));
Steve Blockd0582a62009-12-15 09:54:21 +00007197 const int argc = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007198 v8::Local<v8::Value> argv[argc] = {exec_state};
7199 v8::Local<v8::Value> result =
7200 func->Call(debugger_context, exec_state, argc, argv).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00007201 CHECK(result->IsTrue());
7202 }
7203}
7204
7205
7206TEST(CallingContextIsNotDebugContext) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007207 v8::internal::Debug* debug = CcTest::i_isolate()->debug();
Steve Blockd0582a62009-12-15 09:54:21 +00007208 // Create and enter a debugee context.
Steve Blockd0582a62009-12-15 09:54:21 +00007209 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007210 v8::Isolate* isolate = env->GetIsolate();
7211 v8::HandleScope scope(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +00007212 env.ExposeDebug();
7213
7214 // Save handles to the debugger and debugee contexts to be used in
7215 // NamedGetterWithCallingContextCheck.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007216 debugee_context = env.context();
Steve Block44f0eee2011-05-26 01:26:41 +01007217 debugger_context = v8::Utils::ToLocal(debug->debug_context());
Steve Blockd0582a62009-12-15 09:54:21 +00007218
7219 // Create object with 'a' property accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007220 v8::Local<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
7221 named->SetAccessor(v8_str(isolate, "a"), NamedGetterWithCallingContextCheck);
7222 CHECK(env->Global()
7223 ->Set(debugee_context, v8_str(isolate, "obj"),
7224 named->NewInstance(debugee_context).ToLocalChecked())
7225 .FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +00007226
7227 // Register the debug event listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007228 v8::Debug::SetDebugEventListener(isolate, DebugEventGetAtgumentPropertyValue);
Steve Blockd0582a62009-12-15 09:54:21 +00007229
7230 // Create a function that invokes debugger.
7231 v8::Local<v8::Function> foo = CompileFunction(
7232 &env,
7233 "function bar(x) { debugger; }"
7234 "function foo(){ bar(obj); }",
7235 "foo");
7236
7237 break_point_hit_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007238 foo->Call(debugee_context, env->Global(), 0, NULL).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +00007239 CHECK_EQ(1, break_point_hit_count);
7240
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007241 v8::Debug::SetDebugEventListener(isolate, nullptr);
7242 debugee_context = v8::Local<v8::Context>();
7243 debugger_context = v8::Local<v8::Context>();
7244 CheckDebuggerUnloaded(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +00007245}
Steve Block6ded16b2010-05-10 14:33:55 +01007246
7247
7248TEST(DebugContextIsPreservedBetweenAccesses) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007249 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007250 v8::Debug::SetDebugEventListener(CcTest::isolate(),
7251 DebugEventBreakPointHitCount);
7252 v8::Local<v8::Context> context1 =
7253 v8::Debug::GetDebugContext(CcTest::isolate());
7254 v8::Local<v8::Context> context2 =
7255 v8::Debug::GetDebugContext(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007256 CHECK(v8::Utils::OpenHandle(*context1).is_identical_to(
7257 v8::Utils::OpenHandle(*context2)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007258 v8::Debug::SetDebugEventListener(CcTest::isolate(), nullptr);
Leon Clarkef7060e22010-06-03 12:02:55 +01007259}
7260
7261
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007262TEST(NoDebugContextWhenDebuggerDisabled) {
7263 v8::HandleScope scope(CcTest::isolate());
7264 v8::Local<v8::Context> context =
7265 v8::Debug::GetDebugContext(CcTest::isolate());
7266 CHECK(context.IsEmpty());
7267}
7268
7269
7270static v8::Local<v8::Value> expected_callback_data;
Leon Clarkef7060e22010-06-03 12:02:55 +01007271static void DebugEventContextChecker(const v8::Debug::EventDetails& details) {
7272 CHECK(details.GetEventContext() == expected_context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007273 CHECK(expected_callback_data->Equals(details.GetEventContext(),
7274 details.GetCallbackData())
7275 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01007276}
7277
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007278
Leon Clarkef7060e22010-06-03 12:02:55 +01007279// Check that event details contain context where debug event occured.
7280TEST(DebugEventContext) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007281 v8::Isolate* isolate = CcTest::isolate();
7282 v8::HandleScope scope(isolate);
7283 expected_context = v8::Context::New(isolate);
7284 expected_callback_data = v8::Int32::New(isolate, 2010);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007285 v8::Debug::SetDebugEventListener(isolate, DebugEventContextChecker,
7286 expected_callback_data);
Leon Clarkef7060e22010-06-03 12:02:55 +01007287 v8::Context::Scope context_scope(expected_context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007288 v8::Script::Compile(expected_context,
7289 v8_str(isolate, "(function(){debugger;})();"))
7290 .ToLocalChecked()
7291 ->Run(expected_context)
7292 .ToLocalChecked();
Leon Clarkef7060e22010-06-03 12:02:55 +01007293 expected_context.Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007294 v8::Debug::SetDebugEventListener(isolate, nullptr);
7295 expected_context_data = v8::Local<v8::Value>();
7296 CheckDebuggerUnloaded(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01007297}
Leon Clarkef7060e22010-06-03 12:02:55 +01007298
Ben Murdoch3bec4d22010-07-22 14:51:16 +01007299
Ben Murdochb0fe1622011-05-05 13:52:32 +01007300static bool debug_event_break_deoptimize_done = false;
7301
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007302static void DebugEventBreakDeoptimize(
7303 const v8::Debug::EventDetails& event_details) {
7304 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007305 v8::Local<v8::Object> exec_state = event_details.GetExecutionState();
7306 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007307 if (event == v8::Break) {
7308 if (!frame_function_name.IsEmpty()) {
7309 // Get the name of the function.
7310 const int argc = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007311 v8::Local<v8::Value> argv[argc] = {
7312 exec_state, v8::Integer::New(CcTest::isolate(), 0)};
7313 v8::Local<v8::Value> result =
7314 frame_function_name->Call(context, exec_state, argc, argv)
7315 .ToLocalChecked();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007316 if (!result->IsUndefined()) {
7317 char fn[80];
7318 CHECK(result->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007319 v8::Local<v8::String> function_name(
7320 result->ToString(context).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007321 function_name->WriteUtf8(fn);
Ben Murdochb0fe1622011-05-05 13:52:32 +01007322 if (strcmp(fn, "bar") == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007323 i::Deoptimizer::DeoptimizeAll(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +01007324 debug_event_break_deoptimize_done = true;
7325 }
7326 }
7327 }
7328
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007329 v8::Debug::DebugBreak(CcTest::isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +01007330 }
7331}
7332
7333
7334// Test deoptimization when execution is broken using the debug break stack
7335// check interrupt.
7336TEST(DeoptimizeDuringDebugBreak) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01007337 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007338 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +01007339 env.ExposeDebug();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007340 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007341
7342 // Create a function for checking the function when hitting a break point.
7343 frame_function_name = CompileFunction(&env,
7344 frame_function_name_source,
7345 "frame_function_name");
7346
Ben Murdochb0fe1622011-05-05 13:52:32 +01007347 // Set a debug event listener which will keep interrupting execution until
7348 // debug break. When inside function bar it will deoptimize all functions.
7349 // This tests lazy deoptimization bailout for the stack check, as the first
7350 // time in function bar when using debug break and no break points will be at
7351 // the initial stack check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007352 v8::Debug::SetDebugEventListener(env->GetIsolate(),
7353 DebugEventBreakDeoptimize);
Ben Murdochb0fe1622011-05-05 13:52:32 +01007354
7355 // Compile and run function bar which will optimize it for some flag settings.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007356 v8::Local<v8::Function> f = CompileFunction(&env, "function bar(){}", "bar");
7357 f->Call(context, v8::Undefined(env->GetIsolate()), 0, NULL).ToLocalChecked();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007358
7359 // Set debug break and call bar again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007360 v8::Debug::DebugBreak(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007361 f->Call(context, v8::Undefined(env->GetIsolate()), 0, NULL).ToLocalChecked();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007362
7363 CHECK(debug_event_break_deoptimize_done);
7364
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007365 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01007366}
7367
7368
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007369static void DebugEventBreakWithOptimizedStack(
7370 const v8::Debug::EventDetails& event_details) {
7371 v8::Isolate* isolate = event_details.GetEventContext()->GetIsolate();
7372 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007373 v8::Local<v8::Object> exec_state = event_details.GetExecutionState();
7374 v8::Local<v8::Context> context = isolate->GetCurrentContext();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007375 if (event == v8::Break) {
7376 if (!frame_function_name.IsEmpty()) {
7377 for (int i = 0; i < 2; i++) {
7378 const int argc = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007379 v8::Local<v8::Value> argv[argc] = {exec_state,
7380 v8::Integer::New(isolate, i)};
Ben Murdochb0fe1622011-05-05 13:52:32 +01007381 // Get the name of the function in frame i.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007382 v8::Local<v8::Value> result =
7383 frame_function_name->Call(context, exec_state, argc, argv)
7384 .ToLocalChecked();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007385 CHECK(result->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007386 v8::Local<v8::String> function_name(
7387 result->ToString(context).ToLocalChecked());
7388 CHECK(
7389 function_name->Equals(context, v8_str(isolate, "loop")).FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +01007390 // Get the name of the first argument in frame i.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007391 result = frame_argument_name->Call(context, exec_state, argc, argv)
7392 .ToLocalChecked();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007393 CHECK(result->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007394 v8::Local<v8::String> argument_name(
7395 result->ToString(context).ToLocalChecked());
7396 CHECK(argument_name->Equals(context, v8_str(isolate, "count"))
7397 .FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +01007398 // Get the value of the first argument in frame i. If the
7399 // funtion is optimized the value will be undefined, otherwise
7400 // the value will be '1 - i'.
7401 //
7402 // TODO(3141533): We should be able to get the real value for
7403 // optimized frames.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007404 result = frame_argument_value->Call(context, exec_state, argc, argv)
7405 .ToLocalChecked();
7406 CHECK(result->IsUndefined() ||
7407 (result->Int32Value(context).FromJust() == 1 - i));
Ben Murdochb0fe1622011-05-05 13:52:32 +01007408 // Get the name of the first local variable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007409 result = frame_local_name->Call(context, exec_state, argc, argv)
7410 .ToLocalChecked();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007411 CHECK(result->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007412 v8::Local<v8::String> local_name(
7413 result->ToString(context).ToLocalChecked());
7414 CHECK(local_name->Equals(context, v8_str(isolate, "local")).FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +01007415 // Get the value of the first local variable. If the function
7416 // is optimized the value will be undefined, otherwise it will
7417 // be 42.
7418 //
7419 // TODO(3141533): We should be able to get the real value for
7420 // optimized frames.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007421 result = frame_local_value->Call(context, exec_state, argc, argv)
7422 .ToLocalChecked();
7423 CHECK(result->IsUndefined() ||
7424 (result->Int32Value(context).FromJust() == 42));
Ben Murdochb0fe1622011-05-05 13:52:32 +01007425 }
7426 }
7427 }
7428}
7429
7430
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007431static void ScheduleBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007432 v8::Debug::SetDebugEventListener(args.GetIsolate(),
7433 DebugEventBreakWithOptimizedStack);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007434 v8::Debug::DebugBreak(args.GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +01007435}
7436
7437
7438TEST(DebugBreakStackInspection) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01007439 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007440 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007441 v8::Local<v8::Context> context = env.context();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007442
7443 frame_function_name =
7444 CompileFunction(&env, frame_function_name_source, "frame_function_name");
7445 frame_argument_name =
7446 CompileFunction(&env, frame_argument_name_source, "frame_argument_name");
7447 frame_argument_value = CompileFunction(&env,
7448 frame_argument_value_source,
7449 "frame_argument_value");
7450 frame_local_name =
7451 CompileFunction(&env, frame_local_name_source, "frame_local_name");
7452 frame_local_value =
7453 CompileFunction(&env, frame_local_value_source, "frame_local_value");
7454
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007455 v8::Local<v8::FunctionTemplate> schedule_break_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007456 v8::FunctionTemplate::New(env->GetIsolate(), ScheduleBreak);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007457 v8::Local<v8::Function> schedule_break =
7458 schedule_break_template->GetFunction(context).ToLocalChecked();
7459 CHECK(env->Global()
7460 ->Set(context, v8_str("scheduleBreak"), schedule_break)
7461 .FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +01007462
7463 const char* src =
7464 "function loop(count) {"
7465 " var local = 42;"
7466 " if (count < 1) { scheduleBreak(); loop(count + 1); }"
7467 "}"
7468 "loop(0);";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007469 v8::Script::Compile(context, v8_str(env->GetIsolate(), src))
7470 .ToLocalChecked()
7471 ->Run(context)
7472 .ToLocalChecked();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007473}
7474
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08007475
7476// Test that setting the terminate execution flag during debug break processing.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007477static void TestDebugBreakInLoop(const char* loop_head,
7478 const char** loop_bodies,
7479 const char* loop_tail) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007480 // Receive 10 breaks for each test and then terminate JavaScript execution.
7481 static const int kBreaksPerTest = 10;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007482
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007483 for (int i = 0; loop_bodies[i] != NULL; i++) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007484 // Perform a lazy deoptimization after various numbers of breaks
7485 // have been hit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007486
7487 EmbeddedVector<char, 1024> buffer;
7488 SNPrintF(buffer, "function f() {%s%s%s}", loop_head, loop_bodies[i],
7489 loop_tail);
7490
7491 i::PrintF("%s\n", buffer.start());
7492
7493 for (int j = 0; j < 3; j++) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007494 break_point_hit_count_deoptimize = j;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007495 if (j == 2) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007496 break_point_hit_count_deoptimize = kBreaksPerTest;
7497 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007498
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007499 break_point_hit_count = 0;
7500 max_break_point_hit_count = kBreaksPerTest;
7501 terminate_after_max_break_point_hit = true;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007502
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007503 // Function with infinite loop.
7504 CompileRun(buffer.start());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007505
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007506 // Set the debug break to enter the debugger as soon as possible.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007507 v8::Debug::DebugBreak(CcTest::isolate());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007508
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007509 // Call function with infinite loop.
7510 CompileRun("f();");
7511 CHECK_EQ(kBreaksPerTest, break_point_hit_count);
7512
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007513 CHECK(!CcTest::isolate()->IsExecutionTerminating());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007514 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08007515 }
7516}
7517
7518
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007519static const char* loop_bodies_1[] = {"",
7520 "g()",
7521 "if (a == 0) { g() }",
7522 "if (a == 1) { g() }",
7523 "if (a == 0) { g() } else { h() }",
7524 "if (a == 0) { continue }",
7525 NULL};
7526
7527
7528static const char* loop_bodies_2[] = {
7529 "if (a == 1) { continue }",
7530 "switch (a) { case 1: g(); }",
7531 "switch (a) { case 1: continue; }",
7532 "switch (a) { case 1: g(); break; default: h() }",
7533 "switch (a) { case 1: continue; break; default: h() }",
7534 NULL};
7535
7536
7537void DebugBreakLoop(const char* loop_header, const char** loop_bodies,
7538 const char* loop_footer) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08007539 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007540 v8::HandleScope scope(env->GetIsolate());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08007541
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08007542 // Register a debug event listener which sets the break flag and counts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007543 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventBreakMax);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08007544
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007545 CompileRun(
7546 "var a = 1;\n"
7547 "function g() { }\n"
7548 "function h() { }");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007549
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007550 TestDebugBreakInLoop(loop_header, loop_bodies, loop_footer);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08007551
7552 // Get rid of the debug event listener.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007553 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
7554 CheckDebuggerUnloaded(env->GetIsolate());
7555}
7556
7557
7558TEST(DebugBreakInWhileTrue1) {
7559 DebugBreakLoop("while (true) {", loop_bodies_1, "}");
7560}
7561
7562
7563TEST(DebugBreakInWhileTrue2) {
7564 DebugBreakLoop("while (true) {", loop_bodies_2, "}");
7565}
7566
7567
7568TEST(DebugBreakInWhileCondition1) {
7569 DebugBreakLoop("while (a == 1) {", loop_bodies_1, "}");
7570}
7571
7572
7573TEST(DebugBreakInWhileCondition2) {
7574 DebugBreakLoop("while (a == 1) {", loop_bodies_2, "}");
7575}
7576
7577
7578TEST(DebugBreakInDoWhileTrue1) {
7579 DebugBreakLoop("do {", loop_bodies_1, "} while (true)");
7580}
7581
7582
7583TEST(DebugBreakInDoWhileTrue2) {
7584 DebugBreakLoop("do {", loop_bodies_2, "} while (true)");
7585}
7586
7587
7588TEST(DebugBreakInDoWhileCondition1) {
7589 DebugBreakLoop("do {", loop_bodies_1, "} while (a == 1)");
7590}
7591
7592
7593TEST(DebugBreakInDoWhileCondition2) {
7594 DebugBreakLoop("do {", loop_bodies_2, "} while (a == 1)");
7595}
7596
7597
7598TEST(DebugBreakInFor1) { DebugBreakLoop("for (;;) {", loop_bodies_1, "}"); }
7599
7600
7601TEST(DebugBreakInFor2) { DebugBreakLoop("for (;;) {", loop_bodies_2, "}"); }
7602
7603
7604TEST(DebugBreakInForCondition1) {
7605 DebugBreakLoop("for (;a == 1;) {", loop_bodies_1, "}");
7606}
7607
7608
7609TEST(DebugBreakInForCondition2) {
7610 DebugBreakLoop("for (;a == 1;) {", loop_bodies_2, "}");
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08007611}
7612
7613
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007614v8::Local<v8::Script> inline_script;
7615
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007616static void DebugBreakInlineListener(
7617 const v8::Debug::EventDetails& event_details) {
7618 v8::DebugEvent event = event_details.GetEvent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007619 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007620 if (event != v8::Break) return;
7621
7622 int expected_frame_count = 4;
7623 int expected_line_number[] = {1, 4, 7, 12};
7624
7625 i::Handle<i::Object> compiled_script = v8::Utils::OpenHandle(*inline_script);
7626 i::Handle<i::Script> source_script = i::Handle<i::Script>(i::Script::cast(
7627 i::JSFunction::cast(*compiled_script)->shared()->script()));
7628
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007629 int break_id = CcTest::i_isolate()->debug()->break_id();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007630 char script[128];
7631 i::Vector<char> script_vector(script, sizeof(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007632 SNPrintF(script_vector, "%%GetFrameCount(%d)", break_id);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007633 v8::Local<v8::Value> result = CompileRun(script);
7634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007635 int frame_count = result->Int32Value(context).FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007636 CHECK_EQ(expected_frame_count, frame_count);
7637
7638 for (int i = 0; i < frame_count; i++) {
7639 // The 5. element in the returned array of GetFrameDetails contains the
7640 // source position of that frame.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007641 SNPrintF(script_vector, "%%GetFrameDetails(%d, %d)[5]", break_id, i);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007642 v8::Local<v8::Value> result = CompileRun(script);
7643 CHECK_EQ(expected_line_number[i],
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007644 i::Script::GetLineNumber(source_script,
7645 result->Int32Value(context).FromJust()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007646 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007647 v8::Debug::SetDebugEventListener(CcTest::isolate(), nullptr);
7648 CcTest::isolate()->TerminateExecution();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007649}
7650
7651
7652TEST(DebugBreakInline) {
7653 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007654 DebugLocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007655 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007656 v8::Local<v8::Context> context = env.context();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007657 const char* source =
7658 "function debug(b) { \n"
7659 " if (b) debugger; \n"
7660 "} \n"
7661 "function f(b) { \n"
7662 " debug(b) \n"
7663 "}; \n"
7664 "function g(b) { \n"
7665 " f(b); \n"
7666 "}; \n"
7667 "g(false); \n"
7668 "g(false); \n"
7669 "%OptimizeFunctionOnNextCall(g); \n"
7670 "g(true);";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007671 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugBreakInlineListener);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007672 inline_script =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007673 v8::Script::Compile(context, v8_str(env->GetIsolate(), source))
7674 .ToLocalChecked();
7675 inline_script->Run(context).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007676}
7677
7678
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007679static void DebugEventStepNext(
7680 const v8::Debug::EventDetails& event_details) {
7681 v8::DebugEvent event = event_details.GetEvent();
7682 if (event == v8::Break) {
7683 PrepareStep(StepNext);
7684 }
7685}
7686
7687
7688static void RunScriptInANewCFrame(const char* source) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007689 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007690 CompileRun(source);
7691 CHECK(try_catch.HasCaught());
7692}
7693
7694
7695TEST(Regress131642) {
7696 // Bug description:
7697 // When doing StepNext through the first script, the debugger is not reset
7698 // after exiting through exception. A flawed implementation enabling the
7699 // debugger to step into Array.prototype.forEach breaks inside the callback
7700 // for forEach in the second script under the assumption that we are in a
7701 // recursive call. In an attempt to step out, we crawl the stack using the
7702 // recorded frame pointer from the first script and fail when not finding it
7703 // on the stack.
7704 DebugLocalContext env;
7705 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007706 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventStepNext);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007707
7708 // We step through the first script. It exits through an exception. We run
7709 // this inside a new frame to record a different FP than the second script
7710 // would expect.
7711 const char* script_1 = "debugger; throw new Error();";
7712 RunScriptInANewCFrame(script_1);
7713
7714 // The second script uses forEach.
7715 const char* script_2 = "[0].forEach(function() { });";
7716 CompileRun(script_2);
7717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007718 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007719}
7720
7721
7722// Import from test-heap.cc
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007723namespace v8 {
7724namespace internal {
7725
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007726int CountNativeContexts();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007727}
7728}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007729
7730
7731static void NopListener(const v8::Debug::EventDetails& event_details) {
7732}
7733
7734
7735TEST(DebuggerCreatesContextIffActive) {
7736 DebugLocalContext env;
7737 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007738 CHECK_EQ(1, v8::internal::CountNativeContexts());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007739
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007740 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007741 CompileRun("debugger;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007742 CHECK_EQ(1, v8::internal::CountNativeContexts());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007743
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007744 v8::Debug::SetDebugEventListener(env->GetIsolate(), NopListener);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007745 CompileRun("debugger;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007746 CHECK_EQ(2, v8::internal::CountNativeContexts());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007747
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007748 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007749}
7750
7751
7752TEST(LiveEditEnabled) {
7753 v8::internal::FLAG_allow_natives_syntax = true;
7754 LocalContext env;
7755 v8::HandleScope scope(env->GetIsolate());
7756 v8::Debug::SetLiveEditEnabled(env->GetIsolate(), true);
7757 CompileRun("%LiveEditCompareStrings('', '')");
7758}
7759
7760
7761TEST(LiveEditDisabled) {
7762 v8::internal::FLAG_allow_natives_syntax = true;
7763 LocalContext env;
7764 v8::HandleScope scope(env->GetIsolate());
7765 v8::Debug::SetLiveEditEnabled(env->GetIsolate(), false);
7766 CompileRun("%LiveEditCompareStrings('', '')");
7767}
7768
7769
7770TEST(PrecompiledFunction) {
7771 // Regression test for crbug.com/346207. If we have preparse data, parsing the
7772 // function in the presence of the debugger (and breakpoints) should still
7773 // succeed. The bug was that preparsing was done lazily and parsing was done
7774 // eagerly, so, the symbol streams didn't match.
7775 DebugLocalContext env;
7776 v8::HandleScope scope(env->GetIsolate());
7777 env.ExposeDebug();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007778 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugBreakInlineListener);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007779
7780 v8::Local<v8::Function> break_here =
7781 CompileFunction(&env, "function break_here(){}", "break_here");
7782 SetBreakPoint(break_here, 0);
7783
7784 const char* source =
7785 "var a = b = c = 1; \n"
7786 "function this_is_lazy() { \n"
7787 // This symbol won't appear in the preparse data.
7788 " var a; \n"
7789 "} \n"
7790 "function bar() { \n"
7791 " return \"bar\"; \n"
7792 "}; \n"
7793 "a = b = c = 2; \n"
7794 "bar(); \n";
7795 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
7796 CHECK(result->IsString());
7797 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007798 CHECK_EQ(0, strcmp("bar", *utf8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007799
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007800 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
7801 CheckDebuggerUnloaded(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007802}
7803
7804
7805static void DebugBreakStackTraceListener(
7806 const v8::Debug::EventDetails& event_details) {
7807 v8::StackTrace::CurrentStackTrace(CcTest::isolate(), 10);
7808}
7809
7810
7811static void AddDebugBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
7812 v8::Debug::DebugBreak(args.GetIsolate());
7813}
7814
7815
7816TEST(DebugBreakStackTrace) {
7817 DebugLocalContext env;
7818 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007819 v8::Debug::SetDebugEventListener(env->GetIsolate(),
7820 DebugBreakStackTraceListener);
7821 v8::Local<v8::Context> context = env.context();
7822 v8::Local<v8::FunctionTemplate> add_debug_break_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007823 v8::FunctionTemplate::New(env->GetIsolate(), AddDebugBreak);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007824 v8::Local<v8::Function> add_debug_break =
7825 add_debug_break_template->GetFunction(context).ToLocalChecked();
7826 CHECK(env->Global()
7827 ->Set(context, v8_str("add_debug_break"), add_debug_break)
7828 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007829
7830 CompileRun("(function loop() {"
7831 " for (var j = 0; j < 1000; j++) {"
7832 " for (var i = 0; i < 1000; i++) {"
7833 " if (i == 999) add_debug_break();"
7834 " }"
7835 " }"
7836 "})()");
7837}
7838
7839
7840v8::base::Semaphore terminate_requested_semaphore(0);
7841v8::base::Semaphore terminate_fired_semaphore(0);
7842bool terminate_already_fired = false;
7843
7844
7845static void DebugBreakTriggerTerminate(
7846 const v8::Debug::EventDetails& event_details) {
7847 if (event_details.GetEvent() != v8::Break || terminate_already_fired) return;
7848 terminate_requested_semaphore.Signal();
7849 // Wait for at most 2 seconds for the terminate request.
7850 CHECK(terminate_fired_semaphore.WaitFor(v8::base::TimeDelta::FromSeconds(2)));
7851 terminate_already_fired = true;
7852}
7853
7854
7855class TerminationThread : public v8::base::Thread {
7856 public:
7857 explicit TerminationThread(v8::Isolate* isolate)
7858 : Thread(Options("terminator")), isolate_(isolate) {}
7859
7860 virtual void Run() {
7861 terminate_requested_semaphore.Wait();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007862 isolate_->TerminateExecution();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007863 terminate_fired_semaphore.Signal();
7864 }
7865
7866 private:
7867 v8::Isolate* isolate_;
7868};
7869
7870
7871TEST(DebugBreakOffThreadTerminate) {
7872 DebugLocalContext env;
7873 v8::Isolate* isolate = env->GetIsolate();
7874 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007875 v8::Debug::SetDebugEventListener(isolate, DebugBreakTriggerTerminate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007876 TerminationThread terminator(isolate);
7877 terminator.Start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007878 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007879 v8::Debug::DebugBreak(isolate);
7880 CompileRun("while (true);");
7881 CHECK(try_catch.HasTerminated());
7882}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007883
7884
7885static void DebugEventExpectNoException(
7886 const v8::Debug::EventDetails& event_details) {
7887 v8::DebugEvent event = event_details.GetEvent();
7888 CHECK_NE(v8::Exception, event);
7889}
7890
7891
7892static void TryCatchWrappedThrowCallback(
7893 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007894 v8::TryCatch try_catch(args.GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007895 CompileRun("throw 'rejection';");
7896 CHECK(try_catch.HasCaught());
7897}
7898
7899
7900TEST(DebugPromiseInterceptedByTryCatch) {
7901 DebugLocalContext env;
7902 v8::Isolate* isolate = env->GetIsolate();
7903 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007904 v8::Debug::SetDebugEventListener(isolate, &DebugEventExpectNoException);
7905 v8::Local<v8::Context> context = env.context();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007906 ChangeBreakOnException(false, true);
7907
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007908 v8::Local<v8::FunctionTemplate> fun =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007909 v8::FunctionTemplate::New(isolate, TryCatchWrappedThrowCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007910 CHECK(env->Global()
7911 ->Set(context, v8_str("fun"),
7912 fun->GetFunction(context).ToLocalChecked())
7913 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007914
7915 CompileRun("var p = new Promise(function(res, rej) { fun(); res(); });");
7916 CompileRun(
7917 "var r;"
7918 "p.chain(function() { r = 'resolved'; },"
7919 " function() { r = 'rejected'; });");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007920 CHECK(CompileRun("r")->Equals(context, v8_str("resolved")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007921}
7922
7923
7924static int exception_event_counter = 0;
7925
7926
7927static void DebugEventCountException(
7928 const v8::Debug::EventDetails& event_details) {
7929 v8::DebugEvent event = event_details.GetEvent();
7930 if (event == v8::Exception) exception_event_counter++;
7931}
7932
7933
7934static void ThrowCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
7935 CompileRun("throw 'rejection';");
7936}
7937
7938
7939TEST(DebugPromiseRejectedByCallback) {
7940 DebugLocalContext env;
7941 v8::Isolate* isolate = env->GetIsolate();
7942 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007943 v8::Debug::SetDebugEventListener(isolate, &DebugEventCountException);
7944 v8::Local<v8::Context> context = env.context();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007945 ChangeBreakOnException(false, true);
7946 exception_event_counter = 0;
7947
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007948 v8::Local<v8::FunctionTemplate> fun =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007949 v8::FunctionTemplate::New(isolate, ThrowCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007950 CHECK(env->Global()
7951 ->Set(context, v8_str("fun"),
7952 fun->GetFunction(context).ToLocalChecked())
7953 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007954
7955 CompileRun("var p = new Promise(function(res, rej) { fun(); res(); });");
7956 CompileRun(
7957 "var r;"
7958 "p.chain(function() { r = 'resolved'; },"
7959 " function(e) { r = 'rejected' + e; });");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007960 CHECK(
7961 CompileRun("r")->Equals(context, v8_str("rejectedrejection")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007962 CHECK_EQ(1, exception_event_counter);
7963}
7964
7965
7966TEST(DebugBreakOnExceptionInObserveCallback) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007967 i::FLAG_harmony_object_observe = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007968 DebugLocalContext env;
7969 v8::Isolate* isolate = env->GetIsolate();
7970 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007971 v8::Debug::SetDebugEventListener(isolate, &DebugEventCountException);
7972 v8::Local<v8::Context> context = env.context();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007973 // Break on uncaught exception
7974 ChangeBreakOnException(false, true);
7975 exception_event_counter = 0;
7976
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007977 v8::Local<v8::FunctionTemplate> fun =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007978 v8::FunctionTemplate::New(isolate, ThrowCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007979 CHECK(env->Global()
7980 ->Set(context, v8_str("fun"),
7981 fun->GetFunction(context).ToLocalChecked())
7982 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007983
7984 CompileRun(
7985 "var obj = {};"
7986 "var callbackRan = false;"
7987 "Object.observe(obj, function() {"
7988 " callbackRan = true;"
7989 " throw Error('foo');"
7990 "});"
7991 "obj.prop = 1");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007992 CHECK(CompileRun("callbackRan")->BooleanValue(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007993 CHECK_EQ(1, exception_event_counter);
7994}
7995
7996
7997static void DebugHarmonyScopingListener(
7998 const v8::Debug::EventDetails& event_details) {
7999 v8::DebugEvent event = event_details.GetEvent();
8000 if (event != v8::Break) return;
8001
8002 int break_id = CcTest::i_isolate()->debug()->break_id();
8003
8004 char script[128];
8005 i::Vector<char> script_vector(script, sizeof(script));
8006 SNPrintF(script_vector, "%%GetFrameCount(%d)", break_id);
8007 ExpectInt32(script, 1);
8008
8009 SNPrintF(script_vector, "var frame = new FrameMirror(%d, 0);", break_id);
8010 CompileRun(script);
8011 ExpectInt32("frame.evaluate('x').value_", 1);
8012 ExpectInt32("frame.evaluate('y').value_", 2);
8013
8014 CompileRun("var allScopes = frame.allScopes()");
8015 ExpectInt32("allScopes.length", 2);
8016
8017 ExpectBoolean("allScopes[0].scopeType() === ScopeType.Script", true);
8018
8019 ExpectInt32("allScopes[0].scopeObject().value_.x", 1);
8020
8021 ExpectInt32("allScopes[0].scopeObject().value_.y", 2);
8022
8023 CompileRun("allScopes[0].setVariableValue('x', 5);");
8024 CompileRun("allScopes[0].setVariableValue('y', 6);");
8025 ExpectInt32("frame.evaluate('x + y').value_", 11);
8026}
8027
8028
8029TEST(DebugBreakInLexicalScopes) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008030 i::FLAG_allow_natives_syntax = true;
8031
8032 DebugLocalContext env;
8033 v8::Isolate* isolate = env->GetIsolate();
8034 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008035 v8::Debug::SetDebugEventListener(isolate, DebugHarmonyScopingListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008036
8037 CompileRun(
8038 "'use strict'; \n"
8039 "let x = 1; \n");
8040 ExpectInt32(
8041 "'use strict'; \n"
8042 "let y = 2; \n"
8043 "debugger; \n"
8044 "x * y",
8045 30);
8046 ExpectInt32(
8047 "x = 1; y = 2; \n"
8048 "debugger;"
8049 "x * y",
8050 30);
8051}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008052
8053static int after_compile_handler_depth = 0;
8054static void HandleInterrupt(v8::Isolate* isolate, void* data) {
8055 CHECK_EQ(0, after_compile_handler_depth);
8056}
8057
8058static void NoInterruptsOnDebugEvent(
8059 const v8::Debug::EventDetails& event_details) {
8060 if (event_details.GetEvent() != v8::AfterCompile) return;
8061 ++after_compile_handler_depth;
8062 // Do not allow nested AfterCompile events.
8063 CHECK(after_compile_handler_depth <= 1);
8064 v8::Isolate* isolate = event_details.GetEventContext()->GetIsolate();
8065 isolate->RequestInterrupt(&HandleInterrupt, nullptr);
8066 CompileRun("function foo() {}; foo();");
8067 --after_compile_handler_depth;
8068}
8069
8070
8071TEST(NoInterruptsInDebugListener) {
8072 DebugLocalContext env;
8073 v8::Debug::SetDebugEventListener(env->GetIsolate(), NoInterruptsOnDebugEvent);
8074 CompileRun("void(0);");
8075}