[inspector] disable debug breaks for builtins when called from API

TBR=luoe@chromium.org

Bug: chromium:976713
Change-Id: Ib92c6054a017a94ad23721de240b8a20d87c9f85
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1680544
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62437}
This commit is contained in:
Yang Guo 2019-06-28 10:08:48 +02:00 committed by Commit Bot
parent 1340645339
commit f3b302193c
5 changed files with 169 additions and 41 deletions

View File

@ -4276,10 +4276,10 @@ MaybeLocal<String> v8::Object::ObjectProtoToString(Local<Context> context) {
PREPARE_FOR_EXECUTION(context, Object, ObjectProtoToString, String);
auto self = Utils::OpenHandle(this);
Local<Value> result;
has_pending_exception =
!ToLocal<Value>(i::Execution::Call(isolate, isolate->object_to_string(),
self, 0, nullptr),
&result);
has_pending_exception = !ToLocal<Value>(
i::Execution::CallBuiltin(isolate, isolate->object_to_string(), self, 0,
nullptr),
&result);
RETURN_ON_FAILED_EXECUTION(String);
RETURN_ESCAPED(Local<String>::Cast(result));
}
@ -6616,8 +6616,8 @@ MaybeLocal<Value> Map::Get(Local<Context> context, Local<Value> key) {
Local<Value> result;
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
has_pending_exception =
!ToLocal<Value>(i::Execution::Call(isolate, isolate->map_get(), self,
arraysize(argv), argv),
!ToLocal<Value>(i::Execution::CallBuiltin(isolate, isolate->map_get(),
self, arraysize(argv), argv),
&result);
RETURN_ON_FAILED_EXECUTION(Value);
RETURN_ESCAPED(result);
@ -6630,9 +6630,10 @@ MaybeLocal<Map> Map::Set(Local<Context> context, Local<Value> key,
i::Handle<i::Object> result;
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key),
Utils::OpenHandle(*value)};
has_pending_exception = !i::Execution::Call(isolate, isolate->map_set(), self,
arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->map_set(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION(Map);
RETURN_ESCAPED(Local<Map>::Cast(Utils::ToLocal(result)));
}
@ -6643,9 +6644,10 @@ Maybe<bool> Map::Has(Local<Context> context, Local<Value> key) {
auto self = Utils::OpenHandle(this);
i::Handle<i::Object> result;
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
has_pending_exception = !i::Execution::Call(isolate, isolate->map_has(), self,
arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->map_has(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
return Just(result->IsTrue(isolate));
}
@ -6656,9 +6658,10 @@ Maybe<bool> Map::Delete(Local<Context> context, Local<Value> key) {
auto self = Utils::OpenHandle(this);
i::Handle<i::Object> result;
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
has_pending_exception = !i::Execution::Call(isolate, isolate->map_delete(),
self, arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->map_delete(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
return Just(result->IsTrue(isolate));
}
@ -6744,9 +6747,10 @@ MaybeLocal<Set> Set::Add(Local<Context> context, Local<Value> key) {
auto self = Utils::OpenHandle(this);
i::Handle<i::Object> result;
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
has_pending_exception = !i::Execution::Call(isolate, isolate->set_add(), self,
arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->set_add(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION(Set);
RETURN_ESCAPED(Local<Set>::Cast(Utils::ToLocal(result)));
}
@ -6757,9 +6761,10 @@ Maybe<bool> Set::Has(Local<Context> context, Local<Value> key) {
auto self = Utils::OpenHandle(this);
i::Handle<i::Object> result;
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
has_pending_exception = !i::Execution::Call(isolate, isolate->set_has(), self,
arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->set_has(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
return Just(result->IsTrue(isolate));
}
@ -6770,9 +6775,10 @@ Maybe<bool> Set::Delete(Local<Context> context, Local<Value> key) {
auto self = Utils::OpenHandle(this);
i::Handle<i::Object> result;
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
has_pending_exception = !i::Execution::Call(isolate, isolate->set_delete(),
self, arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->set_delete(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
return Just(result->IsTrue(isolate));
}
@ -6873,9 +6879,10 @@ MaybeLocal<Promise> Promise::Catch(Local<Context> context,
auto self = Utils::OpenHandle(this);
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*handler)};
i::Handle<i::Object> result;
has_pending_exception = !i::Execution::Call(isolate, isolate->promise_catch(),
self, arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->promise_catch(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION(Promise);
RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
}
@ -6886,9 +6893,10 @@ MaybeLocal<Promise> Promise::Then(Local<Context> context,
auto self = Utils::OpenHandle(this);
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*handler)};
i::Handle<i::Object> result;
has_pending_exception = !i::Execution::Call(isolate, isolate->promise_then(),
self, arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->promise_then(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION(Promise);
RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
}
@ -6901,9 +6909,10 @@ MaybeLocal<Promise> Promise::Then(Local<Context> context,
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*on_fulfilled),
Utils::OpenHandle(*on_rejected)};
i::Handle<i::Object> result;
has_pending_exception = !i::Execution::Call(isolate, isolate->promise_then(),
self, arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->promise_then(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION(Promise);
RETURN_ESCAPED(Local<Promise>::Cast(Utils::ToLocal(result)));
}
@ -9600,8 +9609,8 @@ v8::MaybeLocal<v8::Value> debug::WeakMap::Get(v8::Local<v8::Context> context,
Local<Value> result;
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
has_pending_exception =
!ToLocal<Value>(i::Execution::Call(isolate, isolate->weakmap_get(), self,
arraysize(argv), argv),
!ToLocal<Value>(i::Execution::CallBuiltin(isolate, isolate->weakmap_get(),
self, arraysize(argv), argv),
&result);
RETURN_ON_FAILED_EXECUTION(Value);
RETURN_ESCAPED(result);
@ -9615,9 +9624,10 @@ v8::MaybeLocal<debug::WeakMap> debug::WeakMap::Set(
i::Handle<i::Object> result;
i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key),
Utils::OpenHandle(*value)};
has_pending_exception = !i::Execution::Call(isolate, isolate->weakmap_set(),
self, arraysize(argv), argv)
.ToHandle(&result);
has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->weakmap_set(), self,
arraysize(argv), argv)
.ToHandle(&result);
RETURN_ON_FAILED_EXECUTION(WeakMap);
RETURN_ESCAPED(Local<WeakMap>::Cast(Utils::ToLocal(result)));
}

View File

@ -489,13 +489,13 @@ class PostponeInterruptsScope {
class WeakMap : public v8::Object {
public:
V8_WARN_UNUSED_RESULT v8::MaybeLocal<v8::Value> Get(
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT v8::MaybeLocal<v8::Value> Get(
v8::Local<v8::Context> context, v8::Local<v8::Value> key);
V8_WARN_UNUSED_RESULT v8::MaybeLocal<WeakMap> Set(
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT v8::MaybeLocal<WeakMap> Set(
v8::Local<v8::Context> context, v8::Local<v8::Value> key,
v8::Local<v8::Value> value);
static Local<WeakMap> New(v8::Isolate* isolate);
V8_EXPORT_PRIVATE static Local<WeakMap> New(v8::Isolate* isolate);
V8_INLINE static WeakMap* Cast(Value* obj);
private:

View File

@ -358,6 +358,16 @@ MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
argc, argv));
}
MaybeHandle<Object> Execution::CallBuiltin(Isolate* isolate,
Handle<JSFunction> builtin,
Handle<Object> receiver, int argc,
Handle<Object> argv[]) {
DCHECK(builtin->code().is_builtin());
DisableBreak no_break(isolate->debug());
return Invoke(isolate, InvokeParams::SetUpForCall(isolate, builtin, receiver,
argc, argv));
}
// static
MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
int argc, Handle<Object> argv[]) {

View File

@ -31,6 +31,10 @@ class Execution final : public AllStatic {
Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
int argc, Handle<Object> argv[]);
V8_WARN_UNUSED_RESULT static MaybeHandle<Object> CallBuiltin(
Isolate* isolate, Handle<JSFunction> builtin, Handle<Object> receiver,
int argc, Handle<Object> argv[]);
// Construct object from function, the caller supplies an array of
// arguments.
V8_WARN_UNUSED_RESULT static MaybeHandle<Object> New(

View File

@ -569,6 +569,110 @@ TEST(BreakPointBuiltin) {
CheckDebuggerUnloaded();
}
TEST(BreakPointApiIntrinsics) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
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 =
CompileRun("WeakMap.prototype.get").As<v8::Function>();
SetBreakPoint(weakmap_get, 0);
v8::Local<v8::Function> weakmap_set =
CompileRun("WeakMap.prototype.set").As<v8::Function>();
SetBreakPoint(weakmap_set, 0);
// Run with breakpoint.
break_point_hit_count = 0;
CompileRun("var w = new WeakMap(); w.set(w, 1); w.get(w);");
CHECK_EQ(2, break_point_hit_count);
break_point_hit_count = 0;
v8::Local<v8::debug::WeakMap> weakmap =
v8::debug::WeakMap::New(env->GetIsolate());
CHECK(!weakmap->Set(env.local(), weakmap, v8_num(1)).IsEmpty());
CHECK(!weakmap->Get(env.local(), weakmap).IsEmpty());
CHECK_EQ(0, break_point_hit_count);
}
{
v8::Local<v8::Function> object_to_string =
CompileRun("Object.prototype.toString").As<v8::Function>();
SetBreakPoint(object_to_string, 0);
// Run with breakpoint.
break_point_hit_count = 0;
CompileRun("var o = {}; o.toString();");
CHECK_EQ(1, break_point_hit_count);
break_point_hit_count = 0;
v8::Local<v8::Object> object = v8::Object::New(env->GetIsolate());
CHECK(!object->ObjectProtoToString(env.local()).IsEmpty());
CHECK_EQ(0, break_point_hit_count);
}
{
v8::Local<v8::Function> map_set =
CompileRun("Map.prototype.set").As<v8::Function>();
v8::Local<v8::Function> map_get =
CompileRun("Map.prototype.get").As<v8::Function>();
v8::Local<v8::Function> map_has =
CompileRun("Map.prototype.has").As<v8::Function>();
v8::Local<v8::Function> map_delete =
CompileRun("Map.prototype.delete").As<v8::Function>();
SetBreakPoint(map_set, 0);
SetBreakPoint(map_get, 0);
SetBreakPoint(map_has, 0);
SetBreakPoint(map_delete, 0);
// Run with breakpoint.
break_point_hit_count = 0;
CompileRun(
"var m = new Map(); m.set(m, 1); m.get(m); m.has(m); m.delete(m);");
CHECK_EQ(4, break_point_hit_count);
break_point_hit_count = 0;
v8::Local<v8::Map> map = v8::Map::New(env->GetIsolate());
CHECK(!map->Set(env.local(), map, v8_num(1)).IsEmpty());
CHECK(!map->Get(env.local(), map).IsEmpty());
CHECK(map->Has(env.local(), map).FromJust());
CHECK(map->Delete(env.local(), map).FromJust());
CHECK_EQ(0, break_point_hit_count);
}
{
v8::Local<v8::Function> set_add =
CompileRun("Set.prototype.add").As<v8::Function>();
v8::Local<v8::Function> set_get =
CompileRun("Set.prototype.has").As<v8::Function>();
v8::Local<v8::Function> set_delete =
CompileRun("Set.prototype.delete").As<v8::Function>();
SetBreakPoint(set_add, 0);
SetBreakPoint(set_get, 0);
SetBreakPoint(set_delete, 0);
// Run with breakpoint.
break_point_hit_count = 0;
CompileRun("var s = new Set(); s.add(s); s.has(s); s.delete(s);");
CHECK_EQ(3, break_point_hit_count);
break_point_hit_count = 0;
v8::Local<v8::Set> set = v8::Set::New(env->GetIsolate());
CHECK(!set->Add(env.local(), set).IsEmpty());
CHECK(set->Has(env.local(), set).FromJust());
CHECK(set->Delete(env.local(), set).FromJust());
CHECK_EQ(0, break_point_hit_count);
}
v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
CheckDebuggerUnloaded();
}
TEST(BreakPointJSBuiltin) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());