Chromium Code Reviews| Index: third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp |
| diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp |
| index e945af47d5880b2adbcb0ab8c3f6454edfd5ac2e..46416cf6eb0d305c6075f071ff7bef02613d5d3f 100644 |
| --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp |
| +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp |
| @@ -644,6 +644,19 @@ v8::Local<v8::String> V8DebuggerImpl::v8InternalizedString(const char* str) cons |
| return v8::String::NewFromUtf8(m_isolate, str, v8::NewStringType::kInternalized).ToLocalChecked(); |
| } |
| +static bool markArrayWithPrivate(v8::Local<v8::Context> context, v8::Local<v8::Array> array, v8::Local<v8::Private> privateValue) |
| +{ |
| + v8::Isolate* isolate = context->GetIsolate(); |
| + for (size_t i = 0; i < array->Length(); ++i) { |
| + v8::Local<v8::Value> entry; |
| + if (!array->Get(context, i).ToLocal(&entry) || !entry->IsObject()) |
| + return false; |
| + if (!entry.As<v8::Object>()->SetPrivate(context, privateValue, v8::True(isolate)).FromMaybe(false)) |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| v8::MaybeLocal<v8::Value> V8DebuggerImpl::functionScopes(v8::Local<v8::Function> function) |
| { |
| if (!enabled()) { |
| @@ -651,7 +664,18 @@ v8::MaybeLocal<v8::Value> V8DebuggerImpl::functionScopes(v8::Local<v8::Function> |
| return v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate)); |
| } |
| v8::Local<v8::Value> argv[] = { function }; |
| - return callDebuggerMethod("getFunctionScopes", 1, argv); |
| + v8::Local<v8::Value> scopesValue; |
| + if (!callDebuggerMethod("getFunctionScopes", 1, argv).ToLocal(&scopesValue) || !scopesValue->IsArray()) |
| + return v8::MaybeLocal<v8::Value>(); |
| + v8::Local<v8::Array> scopes = scopesValue.As<v8::Array>(); |
| + v8::Local<v8::Context> context = m_debuggerContext.Get(m_isolate); |
| + if (!scopes->SetPrivate(context, V8InjectedScriptHost::internalScopesPrivate(m_isolate), v8::True(m_isolate)).FromMaybe(false)) |
|
dgozman
2016/07/07 19:59:24
I think we need an enum now, and helper functions:
kozy
2016/07/07 22:59:08
I'm not sure. What are advantages over current app
dgozman
2016/07/08 20:37:29
It brings some order to this system.
|
| + return v8::MaybeLocal<v8::Value>(); |
| + if (!markArrayWithPrivate(context, scopes, V8InjectedScriptHost::internalScopePrivate(m_isolate))) |
| + return v8::MaybeLocal<v8::Value>(); |
| + if (!scopes->SetPrototype(context, v8::Null(m_isolate)).FromMaybe(false)) |
| + return v8::Undefined(m_isolate); |
| + return scopes; |
| } |
| v8::MaybeLocal<v8::Array> V8DebuggerImpl::internalProperties(v8::Local<v8::Context> context, v8::Local<v8::Value> value) |
| @@ -659,6 +683,19 @@ v8::MaybeLocal<v8::Array> V8DebuggerImpl::internalProperties(v8::Local<v8::Conte |
| v8::Local<v8::Array> properties; |
| if (!v8::Debug::GetInternalProperties(m_isolate, value).ToLocal(&properties)) |
| return v8::MaybeLocal<v8::Array>(); |
| + if (value->IsFunction()) { |
| + v8::Local<v8::Function> function = value.As<v8::Function>(); |
| + v8::Local<v8::Value> location = functionLocation(context, function); |
| + if (location->IsObject()) { |
| + properties->Set(properties->Length(), v8InternalizedString("[[FunctionLocation]]")); |
| + properties->Set(properties->Length(), location); |
| + } |
| + v8::Local<v8::Value> functionName = function->GetDebugName(); |
| + if (functionName->IsString()) { |
| + properties->Set(properties->Length(), v8InternalizedString("[[FunctionName]]")); |
| + properties->Set(properties->Length(), functionName); |
| + } |
| + } |
| if (!enabled()) |
| return properties; |
| if (value->IsMap() || value->IsWeakMap() || value->IsSet() || value->IsWeakSet() || value->IsSetIterator() || value->IsMapIterator()) { |
| @@ -675,6 +712,17 @@ v8::MaybeLocal<v8::Array> V8DebuggerImpl::internalProperties(v8::Local<v8::Conte |
| properties->Set(properties->Length(), location); |
| } |
| } |
| + if (value->IsFunction()) { |
| + v8::Local<v8::Function> function = value.As<v8::Function>(); |
| + v8::Local<v8::Value> boundFunction = function->GetBoundFunction(); |
| + v8::Local<v8::Value> scopes; |
| + if (!boundFunction->IsFunction() && functionScopes(function).ToLocal(&scopes)) { |
|
dgozman
2016/07/07 19:59:24
Why do we check boundFunction _not_ being a functi
kozy
2016/07/07 22:59:08
Changed to IsUndefined check.
|
| + properties->Set(properties->Length(), v8InternalizedString("[[Scopes]]")); |
| + properties->Set(properties->Length(), scopes); |
| + } |
| + properties->Set(properties->Length(), v8InternalizedString("[[IsGenerator]]")); |
| + properties->Set(properties->Length(), v8::Boolean::New(m_isolate, function->IsGeneratorFunction())); |
|
dgozman
2016/07/07 19:59:24
This one we can do when disabled.
kozy
2016/07/07 22:59:08
Done.
|
| + } |
| return properties; |
| } |
| @@ -689,13 +737,8 @@ v8::Local<v8::Value> V8DebuggerImpl::collectionEntries(v8::Local<v8::Context> co |
| if (!entriesValue->IsArray()) |
| return v8::Undefined(m_isolate); |
| v8::Local<v8::Array> entries = entriesValue.As<v8::Array>(); |
| - for (size_t i = 0; i < entries->Length(); ++i) { |
| - v8::Local<v8::Value> entry; |
| - if (!entries->Get(context, i).ToLocal(&entry) || !entry->IsObject()) |
| - continue; |
| - if (!entry.As<v8::Object>()->SetPrivate(context, V8InjectedScriptHost::internalEntryPrivate(m_isolate), v8::True(m_isolate)).FromMaybe(false)) |
| - continue; |
| - } |
| + if (!markArrayWithPrivate(context, entries, V8InjectedScriptHost::internalEntryPrivate(m_isolate))) |
| + return v8::Undefined(m_isolate); |
| if (!entries->SetPrototype(context, v8::Null(m_isolate)).FromMaybe(false)) |
| return v8::Undefined(m_isolate); |
| return entries; |
| @@ -717,6 +760,27 @@ v8::Local<v8::Value> V8DebuggerImpl::generatorObjectLocation(v8::Local<v8::Objec |
| return location; |
| } |
| +v8::Local<v8::Value> V8DebuggerImpl::functionLocation(v8::Local<v8::Context> context, v8::Local<v8::Function> function) |
| +{ |
| + int scriptId = function->ScriptId(); |
| + if (scriptId == v8::UnboundScript::kNoScriptId) |
| + return v8::Null(m_isolate); |
| + int lineNumber = function->GetScriptLineNumber(); |
| + int columnNumber = function->GetScriptColumnNumber(); |
| + if (lineNumber == v8::Function::kLineOffsetNotFound || columnNumber == v8::Function::kLineOffsetNotFound) |
| + return v8::Null(m_isolate); |
| + v8::Local<v8::Object> location = v8::Object::New(m_isolate); |
| + if (!location->Set(context, v8InternalizedString("scriptId"), toV8String(m_isolate, String16::number(scriptId))).FromMaybe(false)) |
| + return v8::Null(m_isolate); |
| + if (!location->Set(context, v8InternalizedString("lineNumber"), v8::Integer::New(m_isolate, lineNumber)).FromMaybe(false)) |
| + return v8::Null(m_isolate); |
| + if (!location->Set(context, v8InternalizedString("columnNumber"), v8::Integer::New(m_isolate, columnNumber)).FromMaybe(false)) |
| + return v8::Null(m_isolate); |
| + if (!location.As<v8::Object>()->SetPrivate(context, V8InjectedScriptHost::internalLocationPrivate(m_isolate), v8::True(m_isolate)).FromMaybe(false)) |
| + return v8::Null(m_isolate); |
| + return location; |
| +} |
| + |
| bool V8DebuggerImpl::isPaused() |
| { |
| return !m_pausedContext.IsEmpty(); |