summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-debug.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/cctest/test-debug.cc')
-rw-r--r--deps/v8/test/cctest/test-debug.cc403
1 files changed, 278 insertions, 125 deletions
diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc
index 1f55824e3a..f8f8e6a8a6 100644
--- a/deps/v8/test/cctest/test-debug.cc
+++ b/deps/v8/test/cctest/test-debug.cc
@@ -165,6 +165,8 @@ void CheckDebuggerUnloaded() {
CHECK(!CcTest::i_isolate()->debug()->debug_info_list_);
// Collect garbage to ensure weak handles are cleared.
+ i::DisableConservativeStackScanningScopeForTesting no_stack_scanning(
+ CcTest::heap());
CcTest::CollectAllGarbage();
CcTest::CollectAllGarbage();
@@ -253,8 +255,9 @@ class DebugEventBreak : public v8::debug::DebugDelegate {
}
};
+v8::debug::BreakReasons break_right_now_reasons = {};
static void BreakRightNow(v8::Isolate* isolate, void*) {
- v8::debug::BreakRightNow(isolate);
+ v8::debug::BreakRightNow(isolate, break_right_now_reasons);
}
// Debug event handler which re-issues a debug break until a limit has been
@@ -580,8 +583,6 @@ TEST(BreakPointApiIntrinsics) {
DebugEventCounter delegate;
v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
- v8::Local<v8::Function> builtin;
-
// === Test that using API-exposed functions won't trigger breakpoints ===
{
v8::Local<v8::Function> weakmap_get =
@@ -2716,7 +2717,6 @@ TEST(DebugStepWith) {
v8::Object::New(env->GetIsolate()))
.FromJust());
v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
- v8::Local<v8::Value> result;
SetBreakPoint(foo, 8); // "var a = {};"
run_step.set_step_action(StepInto);
@@ -3828,6 +3828,12 @@ void DebugBreakLoop(const char* loop_header, const char** loop_bodies,
TestDebugBreakInLoop(loop_header, loop_bodies, loop_footer);
+ // Also test with "Scheduled" break reason.
+ break_right_now_reasons =
+ v8::debug::BreakReasons{v8::debug::BreakReason::kScheduled};
+ TestDebugBreakInLoop(loop_header, loop_bodies, loop_footer);
+ break_right_now_reasons = v8::debug::BreakReasons{};
+
// Get rid of the debug event listener.
v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
CheckDebuggerUnloaded();
@@ -4202,6 +4208,12 @@ class ArchiveRestoreThread : public v8::base::Thread,
// child.GetBreakCount() will return 1 if the debugger fails to stop
// on the `next()` line after the grandchild thread returns.
CHECK_EQ(child.GetBreakCount(), 5);
+
+ // This test on purpose unlocks the isolate without exiting and
+ // re-entering. It must however update the stack start, which would have
+ // been done automatically if the isolate was properly re-entered.
+ reinterpret_cast<i::Isolate*>(isolate_)->heap()->SetStackStart(
+ v8::base::Stack::GetStackStart());
}
}
@@ -4565,7 +4577,7 @@ TEST(BuiltinsExceptionPrediction) {
bool fail = false;
for (i::Builtin builtin = i::Builtins::kFirst; builtin <= i::Builtins::kLast;
++builtin) {
- i::CodeT code = builtins->code(builtin);
+ i::Code code = builtins->code(builtin);
if (code.kind() != i::CodeKind::BUILTIN) continue;
auto prediction = code.GetBuiltinCatchPrediction();
USE(prediction);
@@ -4963,7 +4975,8 @@ TEST(GetPrivateFields) {
.ToLocalChecked());
std::vector<v8::Local<v8::Value>> names;
std::vector<v8::Local<v8::Value>> values;
- CHECK(v8::debug::GetPrivateMembers(context, object, &names, &values));
+ int filter = static_cast<int>(v8::debug::PrivateMemberFilter::kPrivateFields);
+ CHECK(v8::debug::GetPrivateMembers(context, object, filter, &names, &values));
CHECK_EQ(names.size(), 2);
for (int i = 0; i < 2; i++) {
@@ -4995,7 +5008,7 @@ TEST(GetPrivateFields) {
env->Global()
->Get(context, v8_str(env->GetIsolate(), "x"))
.ToLocalChecked());
- CHECK(v8::debug::GetPrivateMembers(context, object, &names, &values));
+ CHECK(v8::debug::GetPrivateMembers(context, object, filter, &names, &values));
CHECK_EQ(names.size(), 3);
for (int i = 0; i < 3; i++) {
@@ -5030,7 +5043,7 @@ TEST(GetPrivateFields) {
env->Global()
->Get(context, v8_str(env->GetIsolate(), "x"))
.ToLocalChecked());
- CHECK(v8::debug::GetPrivateMembers(context, object, &names, &values));
+ CHECK(v8::debug::GetPrivateMembers(context, object, filter, &names, &values));
CHECK_EQ(names.size(), 2);
for (int i = 0; i < 2; i++) {
@@ -5069,31 +5082,46 @@ TEST(GetPrivateMethodsAndAccessors) {
.ToLocalChecked());
std::vector<v8::Local<v8::Value>> names;
std::vector<v8::Local<v8::Value>> values;
- CHECK(v8::debug::GetPrivateMembers(context, object, &names, &values));
- CHECK_EQ(names.size(), 4);
- for (int i = 0; i < 4; i++) {
+ int accessor_filter =
+ static_cast<int>(v8::debug::PrivateMemberFilter::kPrivateAccessors);
+ int method_filter =
+ static_cast<int>(v8::debug::PrivateMemberFilter::kPrivateMethods);
+
+ CHECK(v8::debug::GetPrivateMembers(context, object, method_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 1);
+ {
+ v8::Local<v8::Value> name = names[0];
+ v8::Local<v8::Value> value = values[0];
+ CHECK(name->IsString());
+ CHECK(v8_str("#method")->Equals(context, name.As<v8::String>()).FromJust());
+ CHECK(value->IsFunction());
+ }
+
+ names.clear();
+ values.clear();
+ CHECK(v8::debug::GetPrivateMembers(context, object, accessor_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 3);
+ for (int i = 0; i < 3; i++) {
v8::Local<v8::Value> name = names[i];
v8::Local<v8::Value> value = values[i];
CHECK(name->IsString());
std::string name_str = FromString(v8_isolate, name.As<v8::String>());
- if (name_str == "#method") {
- CHECK(value->IsFunction());
+ CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
+ v8::Local<v8::debug::AccessorPair> accessors =
+ value.As<v8::debug::AccessorPair>();
+ if (name_str == "#accessor") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsFunction());
+ } else if (name_str == "#readOnly") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsNull());
} else {
- CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
- v8::Local<v8::debug::AccessorPair> accessors =
- value.As<v8::debug::AccessorPair>();
- if (name_str == "#accessor") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsFunction());
- } else if (name_str == "#readOnly") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsNull());
- } else {
- CHECK_EQ(name_str, "#writeOnly");
- CHECK(accessors->getter()->IsNull());
- CHECK(accessors->setter()->IsFunction());
- }
+ CHECK_EQ(name_str, "#writeOnly");
+ CHECK(accessors->getter()->IsNull());
+ CHECK(accessors->setter()->IsFunction());
}
}
@@ -5115,31 +5143,41 @@ TEST(GetPrivateMethodsAndAccessors) {
env->Global()
->Get(context, v8_str(env->GetIsolate(), "x"))
.ToLocalChecked());
- CHECK(v8::debug::GetPrivateMembers(context, object, &names, &values));
- CHECK_EQ(names.size(), 4);
- for (int i = 0; i < 4; i++) {
+ CHECK(v8::debug::GetPrivateMembers(context, object, method_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 1);
+ {
+ v8::Local<v8::Value> name = names[0];
+ v8::Local<v8::Value> value = values[0];
+ CHECK(name->IsString());
+ CHECK(v8_str("#method")->Equals(context, name.As<v8::String>()).FromJust());
+ CHECK(value->IsFunction());
+ }
+
+ names.clear();
+ values.clear();
+ CHECK(v8::debug::GetPrivateMembers(context, object, accessor_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 3);
+ for (int i = 0; i < 3; i++) {
v8::Local<v8::Value> name = names[i];
v8::Local<v8::Value> value = values[i];
CHECK(name->IsString());
std::string name_str = FromString(v8_isolate, name.As<v8::String>());
- if (name_str == "#method") {
- CHECK(value->IsFunction());
+ CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
+ v8::Local<v8::debug::AccessorPair> accessors =
+ value.As<v8::debug::AccessorPair>();
+ if (name_str == "#accessor") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsFunction());
+ } else if (name_str == "#readOnly") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsNull());
} else {
- CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
- v8::Local<v8::debug::AccessorPair> accessors =
- value.As<v8::debug::AccessorPair>();
- if (name_str == "#accessor") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsFunction());
- } else if (name_str == "#readOnly") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsNull());
- } else {
- CHECK_EQ(name_str, "#writeOnly");
- CHECK(accessors->getter()->IsNull());
- CHECK(accessors->setter()->IsFunction());
- }
+ CHECK_EQ(name_str, "#writeOnly");
+ CHECK(accessors->getter()->IsNull());
+ CHECK(accessors->setter()->IsFunction());
}
}
@@ -5162,24 +5200,34 @@ TEST(GetPrivateMethodsAndAccessors) {
env->Global()
->Get(context, v8_str(env->GetIsolate(), "x"))
.ToLocalChecked());
- CHECK(v8::debug::GetPrivateMembers(context, object, &names, &values));
- CHECK_EQ(names.size(), 2);
- for (int i = 0; i < 2; i++) {
- v8::Local<v8::Value> name = names[i];
- v8::Local<v8::Value> value = values[i];
+ CHECK(v8::debug::GetPrivateMembers(context, object, method_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 1);
+ {
+ v8::Local<v8::Value> name = names[0];
+ v8::Local<v8::Value> value = values[0];
CHECK(name->IsString());
- std::string name_str = FromString(v8_isolate, name.As<v8::String>());
- if (name_str == "#method") {
- CHECK(value->IsFunction());
- } else {
- CHECK_EQ(name_str, "#accessor");
- CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
- v8::Local<v8::debug::AccessorPair> accessors =
- value.As<v8::debug::AccessorPair>();
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsFunction());
- }
+ CHECK(v8_str("#method")->Equals(context, name.As<v8::String>()).FromJust());
+ CHECK(value->IsFunction());
+ }
+
+ names.clear();
+ values.clear();
+ CHECK(v8::debug::GetPrivateMembers(context, object, accessor_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 1);
+ {
+ v8::Local<v8::Value> name = names[0];
+ v8::Local<v8::Value> value = values[0];
+ CHECK(name->IsString());
+ CHECK(
+ v8_str("#accessor")->Equals(context, name.As<v8::String>()).FromJust());
+ CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
+ v8::Local<v8::debug::AccessorPair> accessors =
+ value.As<v8::debug::AccessorPair>();
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsFunction());
}
}
@@ -5204,31 +5252,48 @@ TEST(GetPrivateStaticMethodsAndAccessors) {
.ToLocalChecked());
std::vector<v8::Local<v8::Value>> names;
std::vector<v8::Local<v8::Value>> values;
- CHECK(v8::debug::GetPrivateMembers(context, object, &names, &values));
- CHECK_EQ(names.size(), 4);
- for (int i = 0; i < 4; i++) {
+ int accessor_filter =
+ static_cast<int>(v8::debug::PrivateMemberFilter::kPrivateAccessors);
+ int method_filter =
+ static_cast<int>(v8::debug::PrivateMemberFilter::kPrivateMethods);
+
+ CHECK(v8::debug::GetPrivateMembers(context, object, method_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 1);
+ {
+ v8::Local<v8::Value> name = names[0];
+ v8::Local<v8::Value> value = values[0];
+ CHECK(name->IsString());
+ CHECK(v8_str("#staticMethod")
+ ->Equals(context, name.As<v8::String>())
+ .FromJust());
+ CHECK(value->IsFunction());
+ }
+
+ names.clear();
+ values.clear();
+ CHECK(v8::debug::GetPrivateMembers(context, object, accessor_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 3);
+ for (int i = 0; i < 3; i++) {
v8::Local<v8::Value> name = names[i];
v8::Local<v8::Value> value = values[i];
CHECK(name->IsString());
std::string name_str = FromString(v8_isolate, name.As<v8::String>());
- if (name_str == "#staticMethod") {
- CHECK(value->IsFunction());
+ CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
+ v8::Local<v8::debug::AccessorPair> accessors =
+ value.As<v8::debug::AccessorPair>();
+ if (name_str == "#staticAccessor") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsFunction());
+ } else if (name_str == "#staticReadOnly") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsNull());
} else {
- CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
- v8::Local<v8::debug::AccessorPair> accessors =
- value.As<v8::debug::AccessorPair>();
- if (name_str == "#staticAccessor") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsFunction());
- } else if (name_str == "#staticReadOnly") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsNull());
- } else {
- CHECK_EQ(name_str, "#staticWriteOnly");
- CHECK(accessors->getter()->IsNull());
- CHECK(accessors->setter()->IsFunction());
- }
+ CHECK_EQ(name_str, "#staticWriteOnly");
+ CHECK(accessors->getter()->IsNull());
+ CHECK(accessors->setter()->IsFunction());
}
}
}
@@ -5260,31 +5325,47 @@ TEST(GetPrivateStaticAndInstanceMethodsAndAccessors) {
.ToLocalChecked());
std::vector<v8::Local<v8::Value>> names;
std::vector<v8::Local<v8::Value>> values;
- CHECK(v8::debug::GetPrivateMembers(context, object, &names, &values));
+ int accessor_filter =
+ static_cast<int>(v8::debug::PrivateMemberFilter::kPrivateAccessors);
+ int method_filter =
+ static_cast<int>(v8::debug::PrivateMemberFilter::kPrivateMethods);
+
+ CHECK(v8::debug::GetPrivateMembers(context, object, method_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 1);
+ {
+ v8::Local<v8::Value> name = names[0];
+ v8::Local<v8::Value> value = values[0];
+ CHECK(name->IsString());
+ CHECK(v8_str("#staticMethod")
+ ->Equals(context, name.As<v8::String>())
+ .FromJust());
+ CHECK(value->IsFunction());
+ }
- CHECK_EQ(names.size(), 4);
- for (int i = 0; i < 4; i++) {
+ names.clear();
+ values.clear();
+ CHECK(v8::debug::GetPrivateMembers(context, object, accessor_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 3);
+ for (int i = 0; i < 3; i++) {
v8::Local<v8::Value> name = names[i];
v8::Local<v8::Value> value = values[i];
CHECK(name->IsString());
std::string name_str = FromString(v8_isolate, name.As<v8::String>());
- if (name_str == "#staticMethod") {
- CHECK(value->IsFunction());
+ CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
+ v8::Local<v8::debug::AccessorPair> accessors =
+ value.As<v8::debug::AccessorPair>();
+ if (name_str == "#staticAccessor") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsFunction());
+ } else if (name_str == "#staticReadOnly") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsNull());
} else {
- CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
- v8::Local<v8::debug::AccessorPair> accessors =
- value.As<v8::debug::AccessorPair>();
- if (name_str == "#staticAccessor") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsFunction());
- } else if (name_str == "#staticReadOnly") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsNull());
- } else {
- CHECK_EQ(name_str, "#staticWriteOnly");
- CHECK(accessors->getter()->IsNull());
- CHECK(accessors->setter()->IsFunction());
- }
+ CHECK_EQ(name_str, "#staticWriteOnly");
+ CHECK(accessors->getter()->IsNull());
+ CHECK(accessors->setter()->IsFunction());
}
}
@@ -5294,31 +5375,40 @@ TEST(GetPrivateStaticAndInstanceMethodsAndAccessors) {
env->Global()
->Get(context, v8_str(env->GetIsolate(), "x"))
.ToLocalChecked());
- CHECK(v8::debug::GetPrivateMembers(context, object, &names, &values));
+ CHECK(v8::debug::GetPrivateMembers(context, object, method_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 1);
+ {
+ v8::Local<v8::Value> name = names[0];
+ v8::Local<v8::Value> value = values[0];
+ CHECK(name->IsString());
+ CHECK(v8_str("#method")->Equals(context, name.As<v8::String>()).FromJust());
+ CHECK(value->IsFunction());
+ }
- CHECK_EQ(names.size(), 4);
- for (int i = 0; i < 4; i++) {
+ names.clear();
+ values.clear();
+ CHECK(v8::debug::GetPrivateMembers(context, object, accessor_filter, &names,
+ &values));
+ CHECK_EQ(names.size(), 3);
+ for (int i = 0; i < 3; i++) {
v8::Local<v8::Value> name = names[i];
v8::Local<v8::Value> value = values[i];
CHECK(name->IsString());
std::string name_str = FromString(v8_isolate, name.As<v8::String>());
- if (name_str == "#method") {
- CHECK(value->IsFunction());
+ CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
+ v8::Local<v8::debug::AccessorPair> accessors =
+ value.As<v8::debug::AccessorPair>();
+ if (name_str == "#accessor") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsFunction());
+ } else if (name_str == "#readOnly") {
+ CHECK(accessors->getter()->IsFunction());
+ CHECK(accessors->setter()->IsNull());
} else {
- CHECK(v8::debug::AccessorPair::IsAccessorPair(value));
- v8::Local<v8::debug::AccessorPair> accessors =
- value.As<v8::debug::AccessorPair>();
- if (name_str == "#accessor") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsFunction());
- } else if (name_str == "#readOnly") {
- CHECK(accessors->getter()->IsFunction());
- CHECK(accessors->setter()->IsNull());
- } else {
- CHECK_EQ(name_str, "#writeOnly");
- CHECK(accessors->getter()->IsNull());
- CHECK(accessors->setter()->IsFunction());
- }
+ CHECK_EQ(name_str, "#writeOnly");
+ CHECK(accessors->getter()->IsNull());
+ CHECK(accessors->setter()->IsFunction());
}
}
}
@@ -5924,8 +6014,8 @@ class ScopeListener : public v8::debug::DebugDelegate {
const std::vector<v8::debug::BreakpointId>&,
v8::debug::BreakReasons break_reasons) override {
i::Isolate* isolate = CcTest::i_isolate();
- i::StackTraceFrameIterator iterator_(isolate,
- isolate->debug()->break_frame_id());
+ i::DebuggableStackFrameIterator iterator_(
+ isolate, isolate->debug()->break_frame_id());
// Go up one frame so we are on the script level.
iterator_.Advance();
@@ -5944,8 +6034,6 @@ class ScopeListener : public v8::debug::DebugDelegate {
} // namespace
TEST(ScopeIteratorDoesNotCreateBlocklistForScriptScope) {
- i::v8_flags.experimental_reuse_locals_blocklists = true;
-
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
@@ -5987,8 +6075,6 @@ class DebugEvaluateListener : public v8::debug::DebugDelegate {
// scope nested inside an eval scope with the exact same source positions.
// This can confuse the blocklist mechanism if not handled correctly.
TEST(DebugEvaluateInWrappedScript) {
- i::v8_flags.experimental_reuse_locals_blocklists = true;
-
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
@@ -6012,3 +6098,70 @@ TEST(DebugEvaluateInWrappedScript) {
v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
CheckDebuggerUnloaded();
}
+
+namespace {
+
+class ConditionListener : public v8::debug::DebugDelegate {
+ public:
+ void BreakpointConditionEvaluated(
+ v8::Local<v8::Context> context, v8::debug::BreakpointId breakpoint_id_arg,
+ bool exception_thrown_arg, v8::Local<v8::Value> exception_arg) override {
+ breakpoint_id = breakpoint_id_arg;
+ exception_thrown = exception_thrown_arg;
+ exception = exception_arg;
+ }
+
+ void BreakProgramRequested(v8::Local<v8::Context> context,
+ const std::vector<v8::debug::BreakpointId>&,
+ v8::debug::BreakReasons break_reasons) override {
+ break_point_hit_count++;
+ }
+
+ v8::debug::BreakpointId breakpoint_id;
+ bool exception_thrown = false;
+ v8::Local<v8::Value> exception;
+};
+
+} // namespace
+
+TEST(SuccessfulBreakpointConditionEvaluationEvent) {
+ break_point_hit_count = 0;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ ConditionListener delegate;
+ v8::debug::SetDebugDelegate(isolate, &delegate);
+
+ v8::Local<v8::Function> foo =
+ CompileFunction(&env, "function foo() { const x = 5; }", "foo");
+
+ i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0, "true");
+ foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
+ CHECK_EQ(1, break_point_hit_count);
+ CHECK_EQ(bp->id(), delegate.breakpoint_id);
+ CHECK(!delegate.exception_thrown);
+ CHECK(delegate.exception.IsEmpty());
+}
+
+// Checks that SyntaxErrors in breakpoint conditions are reported to the
+// DebugDelegate.
+TEST(FailedBreakpointConditoinEvaluationEvent) {
+ break_point_hit_count = 0;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ ConditionListener delegate;
+ v8::debug::SetDebugDelegate(isolate, &delegate);
+
+ v8::Local<v8::Function> foo =
+ CompileFunction(&env, "function foo() { const x = 5; }", "foo");
+
+ i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0, "bar().");
+ foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
+ CHECK_EQ(0, break_point_hit_count);
+ CHECK_EQ(bp->id(), delegate.breakpoint_id);
+ CHECK(delegate.exception_thrown);
+ CHECK(!delegate.exception.IsEmpty());
+}