| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/v8_inspector/V8Console.h" | 5 #include "platform/v8_inspector/V8Console.h" |
| 6 | 6 |
| 7 #include "platform/inspector_protocol/String16.h" | 7 #include "platform/inspector_protocol/String16.h" |
| 8 #include "platform/v8_inspector/InjectedScript.h" |
| 8 #include "platform/v8_inspector/InspectedContext.h" | 9 #include "platform/v8_inspector/InspectedContext.h" |
| 9 #include "platform/v8_inspector/V8DebuggerAgentImpl.h" | 10 #include "platform/v8_inspector/V8DebuggerAgentImpl.h" |
| 10 #include "platform/v8_inspector/V8DebuggerImpl.h" | 11 #include "platform/v8_inspector/V8DebuggerImpl.h" |
| 11 #include "platform/v8_inspector/V8InspectorSessionImpl.h" | 12 #include "platform/v8_inspector/V8InspectorSessionImpl.h" |
| 12 #include "platform/v8_inspector/V8ProfilerAgentImpl.h" | 13 #include "platform/v8_inspector/V8ProfilerAgentImpl.h" |
| 13 #include "platform/v8_inspector/V8StackTraceImpl.h" | 14 #include "platform/v8_inspector/V8StackTraceImpl.h" |
| 14 #include "platform/v8_inspector/V8StringUtil.h" | 15 #include "platform/v8_inspector/V8StringUtil.h" |
| 15 #include "platform/v8_inspector/public/ConsoleAPITypes.h" | 16 #include "platform/v8_inspector/public/ConsoleAPITypes.h" |
| 16 #include "platform/v8_inspector/public/ConsoleTypes.h" | 17 #include "platform/v8_inspector/public/ConsoleTypes.h" |
| 17 #include "platform/v8_inspector/public/V8DebuggerClient.h" | 18 #include "platform/v8_inspector/public/V8DebuggerClient.h" |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 if (m_info[0]->IsObject()) { | 113 if (m_info[0]->IsObject()) { |
| 113 if (!m_info[0].As<v8::Object>()->ObjectProtoToString(m_context).ToLo
cal(&titleValue)) | 114 if (!m_info[0].As<v8::Object>()->ObjectProtoToString(m_context).ToLo
cal(&titleValue)) |
| 114 return defaultValue; | 115 return defaultValue; |
| 115 } else { | 116 } else { |
| 116 if (!m_info[0]->ToString(m_context).ToLocal(&titleValue)) | 117 if (!m_info[0]->ToString(m_context).ToLocal(&titleValue)) |
| 117 return defaultValue; | 118 return defaultValue; |
| 118 } | 119 } |
| 119 return toProtocolString(titleValue); | 120 return toProtocolString(titleValue); |
| 120 } | 121 } |
| 121 | 122 |
| 123 v8::MaybeLocal<v8::Object> firstArgAsObject() |
| 124 { |
| 125 if (m_info.Length() < 1 || !m_info[0]->IsObject()) |
| 126 return v8::MaybeLocal<v8::Object>(); |
| 127 return m_info[0].As<v8::Object>(); |
| 128 } |
| 129 |
| 130 v8::MaybeLocal<v8::Function> firstArgAsFunction() |
| 131 { |
| 132 if (m_info.Length() < 1 || !m_info[0]->IsFunction()) |
| 133 return v8::MaybeLocal<v8::Function>(); |
| 134 return m_info[0].As<v8::Function>(); |
| 135 } |
| 136 |
| 122 v8::MaybeLocal<v8::Map> privateMap(const char* name) | 137 v8::MaybeLocal<v8::Map> privateMap(const char* name) |
| 123 { | 138 { |
| 124 v8::Local<v8::Object> console = ensureConsole(); | 139 v8::Local<v8::Object> console = ensureConsole(); |
| 125 v8::Local<v8::Private> privateKey = v8::Private::ForApi(m_isolate, toV8S
tringInternalized(m_isolate, name)); | 140 v8::Local<v8::Private> privateKey = v8::Private::ForApi(m_isolate, toV8S
tringInternalized(m_isolate, name)); |
| 126 v8::Local<v8::Value> mapValue; | 141 v8::Local<v8::Value> mapValue; |
| 127 if (!console->GetPrivate(m_context, privateKey).ToLocal(&mapValue)) | 142 if (!console->GetPrivate(m_context, privateKey).ToLocal(&mapValue)) |
| 128 return v8::MaybeLocal<v8::Map>(); | 143 return v8::MaybeLocal<v8::Map>(); |
| 129 if (mapValue->IsUndefined()) { | 144 if (mapValue->IsUndefined()) { |
| 130 v8::Local<v8::Map> map = v8::Map::New(m_isolate); | 145 v8::Local<v8::Map> map = v8::Map::New(m_isolate); |
| 131 if (!console->SetPrivate(m_context, privateKey, map).FromMaybe(false
)) | 146 if (!console->SetPrivate(m_context, privateKey, map).FromMaybe(false
)) |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 return; | 458 return; |
| 444 info.GetReturnValue().Set(memoryValue); | 459 info.GetReturnValue().Set(memoryValue); |
| 445 } | 460 } |
| 446 } | 461 } |
| 447 | 462 |
| 448 void V8Console::memorySetterCallback(const v8::FunctionCallbackInfo<v8::Value>&
info) | 463 void V8Console::memorySetterCallback(const v8::FunctionCallbackInfo<v8::Value>&
info) |
| 449 { | 464 { |
| 450 // We can't make the attribute readonly as it breaks existing code that reli
es on being able to assign to console.memory in strict mode. Instead, the setter
just ignores the passed value. http://crbug.com/468611 | 465 // We can't make the attribute readonly as it breaks existing code that reli
es on being able to assign to console.memory in strict mode. Instead, the setter
just ignores the passed value. http://crbug.com/468611 |
| 451 } | 466 } |
| 452 | 467 |
| 453 v8::MaybeLocal<v8::Object> V8Console::create(v8::Local<v8::Context> context, Ins
pectedContext* inspectedContext, bool hasMemoryAttribute) | 468 void V8Console::keysCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
| 454 { | 469 { |
| 470 v8::Isolate* isolate = info.GetIsolate(); |
| 471 info.GetReturnValue().Set(v8::Array::New(isolate)); |
| 472 |
| 473 ConsoleHelper helper(info); |
| 474 v8::Local<v8::Object> obj; |
| 475 if (!helper.firstArgAsObject().ToLocal(&obj)) |
| 476 return; |
| 477 v8::Local<v8::Array> names; |
| 478 if (!obj->GetOwnPropertyNames(isolate->GetCurrentContext()).ToLocal(&names)) |
| 479 return; |
| 480 info.GetReturnValue().Set(names); |
| 481 } |
| 482 |
| 483 void V8Console::valuesCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
| 484 { |
| 485 v8::Isolate* isolate = info.GetIsolate(); |
| 486 info.GetReturnValue().Set(v8::Array::New(isolate)); |
| 487 |
| 488 ConsoleHelper helper(info); |
| 489 v8::Local<v8::Object> obj; |
| 490 if (!helper.firstArgAsObject().ToLocal(&obj)) |
| 491 return; |
| 492 v8::Local<v8::Array> names; |
| 493 v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
| 494 if (!obj->GetOwnPropertyNames(context).ToLocal(&names)) |
| 495 return; |
| 496 v8::Local<v8::Array> values = v8::Array::New(isolate, names->Length()); |
| 497 for (size_t i = 0; i < names->Length(); ++i) { |
| 498 v8::Local<v8::Value> key; |
| 499 if (!names->Get(context, i).ToLocal(&key)) |
| 500 continue; |
| 501 v8::Local<v8::Value> value; |
| 502 if (!obj->Get(context, key).ToLocal(&value)) |
| 503 continue; |
| 504 if (!values->Set(context, i, value).FromMaybe(false)) |
| 505 continue; |
| 506 } |
| 507 info.GetReturnValue().Set(values); |
| 508 } |
| 509 |
| 510 static void setFunctionBreakpoint(ConsoleHelper& helper, v8::Local<v8::Function>
function, V8DebuggerAgentImpl::BreakpointSource source, const String16& conditi
on, bool enable) |
| 511 { |
| 512 V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent(); |
| 513 if (!debuggerAgent) |
| 514 return; |
| 515 String16 scriptId = String16::number(function->ScriptId()); |
| 516 int lineNumber = function->GetScriptLineNumber(); |
| 517 int columnNumber = function->GetScriptColumnNumber(); |
| 518 if (lineNumber == v8::Function::kLineOffsetNotFound || columnNumber == v8::F
unction::kLineOffsetNotFound) |
| 519 return; |
| 520 if (enable) |
| 521 debuggerAgent->setBreakpointAt(scriptId, lineNumber, columnNumber, sourc
e, condition); |
| 522 else |
| 523 debuggerAgent->removeBreakpointAt(scriptId, lineNumber, columnNumber, so
urce); |
| 524 } |
| 525 |
| 526 void V8Console::debugFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>&
info) |
| 527 { |
| 528 ConsoleHelper helper(info); |
| 529 v8::Local<v8::Function> function; |
| 530 if (!helper.firstArgAsFunction().ToLocal(&function)) |
| 531 return; |
| 532 setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::DebugCommandBre
akpointSource, String16(), true); |
| 533 } |
| 534 |
| 535 void V8Console::undebugFunctionCallback(const v8::FunctionCallbackInfo<v8::Value
>& info) |
| 536 { |
| 537 ConsoleHelper helper(info); |
| 538 v8::Local<v8::Function> function; |
| 539 if (!helper.firstArgAsFunction().ToLocal(&function)) |
| 540 return; |
| 541 setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::DebugCommandBre
akpointSource, String16(), false); |
| 542 } |
| 543 |
| 544 void V8Console::monitorFunctionCallback(const v8::FunctionCallbackInfo<v8::Value
>& info) |
| 545 { |
| 546 ConsoleHelper helper(info); |
| 547 v8::Local<v8::Function> function; |
| 548 if (!helper.firstArgAsFunction().ToLocal(&function)) |
| 549 return; |
| 550 v8::Local<v8::Value> name = function->GetName(); |
| 551 if (!name->IsString() || !v8::Local<v8::String>::Cast(name)->Length()) |
| 552 name = function->GetInferredName(); |
| 553 String16 functionName = toProtocolStringWithTypeCheck(name); |
| 554 String16Builder builder; |
| 555 builder.append("console.log(\"function "); |
| 556 if (functionName.isEmpty()) |
| 557 builder.append("(anonymous function)"); |
| 558 else |
| 559 builder.append(functionName); |
| 560 builder.append(" called\" + (arguments.length > 0 ? \" with arguments: \" +
Array.prototype.join.call(arguments, \", \") : \"\")) && false"); |
| 561 setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::MonitorCommandB
reakpointSource, builder.toString(), true); |
| 562 } |
| 563 |
| 564 void V8Console::unmonitorFunctionCallback(const v8::FunctionCallbackInfo<v8::Val
ue>& info) |
| 565 { |
| 566 ConsoleHelper helper(info); |
| 567 v8::Local<v8::Function> function; |
| 568 if (!helper.firstArgAsFunction().ToLocal(&function)) |
| 569 return; |
| 570 setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::MonitorCommandB
reakpointSource, String16(), false); |
| 571 } |
| 572 |
| 573 void V8Console::lastEvaluationResultCallback(const v8::FunctionCallbackInfo<v8::
Value>& info) |
| 574 { |
| 575 ConsoleHelper helper(info); |
| 576 InspectedContext* context = helper.ensureInspectedContext(); |
| 577 if (!context) |
| 578 return; |
| 579 if (InjectedScript* injectedScript = context->getInjectedScript()) |
| 580 info.GetReturnValue().Set(injectedScript->lastEvaluationResult()); |
| 581 } |
| 582 |
| 583 v8::MaybeLocal<v8::Object> V8Console::createConsole(InspectedContext* inspectedC
ontext, bool hasMemoryAttribute) |
| 584 { |
| 585 v8::Local<v8::Context> context = inspectedContext->context(); |
| 455 v8::Isolate* isolate = context->GetIsolate(); | 586 v8::Isolate* isolate = context->GetIsolate(); |
| 456 v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunM
icrotasks); | 587 v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunM
icrotasks); |
| 457 | 588 |
| 458 v8::Local<v8::Object> console; | 589 v8::Local<v8::Object> console; |
| 459 if (!createObjectWithClassName(inspectedContext->debugger(), context, "Conso
le").ToLocal(&console)) | 590 if (!createObjectWithClassName(inspectedContext->debugger(), context, "Conso
le").ToLocal(&console)) |
| 460 return v8::MaybeLocal<v8::Object>(); | 591 return v8::MaybeLocal<v8::Object>(); |
| 461 | 592 |
| 462 v8::Local<v8::Object> prototype; | 593 v8::Local<v8::Object> prototype; |
| 463 if (!createObjectWithClassName(inspectedContext->debugger(), context, "Conso
lePrototype").ToLocal(&prototype)) | 594 if (!createObjectWithClassName(inspectedContext->debugger(), context, "Conso
lePrototype").ToLocal(&prototype)) |
| 464 return v8::MaybeLocal<v8::Object>(); | 595 return v8::MaybeLocal<v8::Object>(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 490 if (!console->SetPrototype(context, prototype).FromMaybe(false)) | 621 if (!console->SetPrototype(context, prototype).FromMaybe(false)) |
| 491 return v8::MaybeLocal<v8::Object>(); | 622 return v8::MaybeLocal<v8::Object>(); |
| 492 | 623 |
| 493 if (hasMemoryAttribute) | 624 if (hasMemoryAttribute) |
| 494 console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"),
v8::Function::New(isolate, V8Console::memoryGetterCallback, console), v8::Functi
on::New(isolate, V8Console::memorySetterCallback), static_cast<v8::PropertyAttri
bute>(v8::None), v8::DEFAULT); | 625 console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"),
v8::Function::New(isolate, V8Console::memoryGetterCallback, console), v8::Functi
on::New(isolate, V8Console::memorySetterCallback), static_cast<v8::PropertyAttri
bute>(v8::None), v8::DEFAULT); |
| 495 | 626 |
| 496 console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::Extern
al::New(isolate, inspectedContext)); | 627 console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::Extern
al::New(isolate, inspectedContext)); |
| 497 return console; | 628 return console; |
| 498 } | 629 } |
| 499 | 630 |
| 631 v8::Local<v8::Object> V8Console::createCommandLineAPI(InspectedContext* inspecte
dContext) |
| 632 { |
| 633 v8::Local<v8::Context> context = inspectedContext->context(); |
| 634 v8::Isolate* isolate = context->GetIsolate(); |
| 635 v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunM
icrotasks); |
| 636 |
| 637 v8::Local<v8::Object> commandLineAPI = v8::Object::New(isolate); |
| 638 |
| 639 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "dir",
V8Console::dirCallback); |
| 640 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "dirxml
", V8Console::dirxmlCallback); |
| 641 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "profil
e", V8Console::profileCallback); |
| 642 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "profil
eEnd", V8Console::profileEndCallback); |
| 643 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "clear"
, V8Console::clearCallback); |
| 644 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "table"
, V8Console::tableCallback); |
| 645 |
| 646 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "keys",
V8Console::keysCallback); |
| 647 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "values
", V8Console::valuesCallback); |
| 648 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "debug"
, V8Console::debugFunctionCallback); |
| 649 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "undebu
g", V8Console::undebugFunctionCallback); |
| 650 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "monito
r", V8Console::monitorFunctionCallback); |
| 651 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "unmoni
tor", V8Console::unmonitorFunctionCallback); |
| 652 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "$_", V
8Console::lastEvaluationResultCallback); |
| 653 |
| 654 commandLineAPI->SetPrivate(context, inspectedContextPrivateKey(isolate), v8:
:External::New(isolate, inspectedContext)); |
| 655 return commandLineAPI; |
| 656 } |
| 657 |
| 500 void V8Console::clearInspectedContextIfNeeded(v8::Local<v8::Context> context, v8
::Local<v8::Object> console) | 658 void V8Console::clearInspectedContextIfNeeded(v8::Local<v8::Context> context, v8
::Local<v8::Object> console) |
| 501 { | 659 { |
| 502 v8::Isolate* isolate = context->GetIsolate(); | 660 v8::Isolate* isolate = context->GetIsolate(); |
| 503 console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::Extern
al::New(isolate, nullptr)); | 661 console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::Extern
al::New(isolate, nullptr)); |
| 504 } | 662 } |
| 505 | 663 |
| 664 bool V8Debugger::isCommandLineAPIMethod(const String16& name) |
| 665 { |
| 666 DEFINE_STATIC_LOCAL(protocol::HashSet<String16>, methods, ()); |
| 667 if (methods.size() == 0) { |
| 668 const char* members[] = { "$", "$$", "$x", "dir", "dirxml", "keys", "val
ues", "profile", "profileEnd", |
| 669 "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "get
EventListeners", |
| 670 "debug", "undebug", "monitor", "unmonitor", "table" }; |
| 671 for (size_t i = 0; i < WTF_ARRAY_LENGTH(members); ++i) |
| 672 methods.add(members[i]); |
| 673 } |
| 674 return methods.find(name) != methods.end(); |
| 675 } |
| 676 |
| 677 bool V8Debugger::isCommandLineAPIGetter(const String16& name) |
| 678 { |
| 679 DEFINE_STATIC_LOCAL(protocol::HashSet<String16>, getters, ()); |
| 680 if (getters.size() == 0) { |
| 681 const char* members[] = { "$0", "$1", "$2", "$3", "$4", "$_" }; |
| 682 for (size_t i = 0; i < WTF_ARRAY_LENGTH(members); ++i) |
| 683 getters.add(members[i]); |
| 684 } |
| 685 return getters.find(name) != getters.end(); |
| 686 } |
| 687 |
| 506 } // namespace blink | 688 } // namespace blink |
| OLD | NEW |