Chromium Code Reviews| 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/InspectedContext.h" | 8 #include "platform/v8_inspector/InspectedContext.h" |
| 9 #include "platform/v8_inspector/V8DebuggerAgentImpl.h" | 9 #include "platform/v8_inspector/V8DebuggerAgentImpl.h" |
| 10 #include "platform/v8_inspector/V8DebuggerImpl.h" | 10 #include "platform/v8_inspector/V8DebuggerImpl.h" |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 if (m_info[0]->IsObject()) { | 112 if (m_info[0]->IsObject()) { |
| 113 if (!m_info[0].As<v8::Object>()->ObjectProtoToString(m_context).ToLo cal(&titleValue)) | 113 if (!m_info[0].As<v8::Object>()->ObjectProtoToString(m_context).ToLo cal(&titleValue)) |
| 114 return defaultValue; | 114 return defaultValue; |
| 115 } else { | 115 } else { |
| 116 if (!m_info[0]->ToString(m_context).ToLocal(&titleValue)) | 116 if (!m_info[0]->ToString(m_context).ToLocal(&titleValue)) |
| 117 return defaultValue; | 117 return defaultValue; |
| 118 } | 118 } |
| 119 return toProtocolString(titleValue); | 119 return toProtocolString(titleValue); |
| 120 } | 120 } |
| 121 | 121 |
| 122 v8::MaybeLocal<v8::Object> firstArgAsObject() | |
| 123 { | |
| 124 if (m_info.Length() < 1 || !m_info[0]->IsObject()) | |
| 125 return v8::MaybeLocal<v8::Object>(); | |
| 126 return m_info[0].As<v8::Object>(); | |
| 127 } | |
| 128 | |
| 129 v8::MaybeLocal<v8::Function> firstArgAsFunction() | |
| 130 { | |
| 131 if (m_info.Length() < 1 || !m_info[0]->IsFunction()) | |
| 132 return v8::MaybeLocal<v8::Function>(); | |
| 133 return m_info[0].As<v8::Function>(); | |
| 134 } | |
| 135 | |
| 122 v8::MaybeLocal<v8::Map> privateMap(const char* name) | 136 v8::MaybeLocal<v8::Map> privateMap(const char* name) |
| 123 { | 137 { |
| 124 v8::Local<v8::Object> console = ensureConsole(); | 138 v8::Local<v8::Object> console = ensureConsole(); |
| 125 v8::Local<v8::Private> privateKey = v8::Private::ForApi(m_isolate, toV8S tringInternalized(m_isolate, name)); | 139 v8::Local<v8::Private> privateKey = v8::Private::ForApi(m_isolate, toV8S tringInternalized(m_isolate, name)); |
| 126 v8::Local<v8::Value> mapValue; | 140 v8::Local<v8::Value> mapValue; |
| 127 if (!console->GetPrivate(m_context, privateKey).ToLocal(&mapValue)) | 141 if (!console->GetPrivate(m_context, privateKey).ToLocal(&mapValue)) |
| 128 return v8::MaybeLocal<v8::Map>(); | 142 return v8::MaybeLocal<v8::Map>(); |
| 129 if (mapValue->IsUndefined()) { | 143 if (mapValue->IsUndefined()) { |
| 130 v8::Local<v8::Map> map = v8::Map::New(m_isolate); | 144 v8::Local<v8::Map> map = v8::Map::New(m_isolate); |
| 131 if (!console->SetPrivate(m_context, privateKey, map).FromMaybe(false )) | 145 if (!console->SetPrivate(m_context, privateKey, map).FromMaybe(false )) |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 return; | 457 return; |
| 444 info.GetReturnValue().Set(memoryValue); | 458 info.GetReturnValue().Set(memoryValue); |
| 445 } | 459 } |
| 446 } | 460 } |
| 447 | 461 |
| 448 void V8Console::memorySetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | 462 void V8Console::memorySetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
| 449 { | 463 { |
| 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 | 464 // 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 } | 465 } |
| 452 | 466 |
| 453 v8::MaybeLocal<v8::Object> V8Console::create(v8::Local<v8::Context> context, Ins pectedContext* inspectedContext, bool hasMemoryAttribute) | 467 void V8Console::keysCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
| 468 { | |
| 469 v8::Isolate* isolate = info.GetIsolate(); | |
| 470 info.GetReturnValue().Set(v8::Array::New(isolate)); | |
| 471 | |
| 472 ConsoleHelper helper(info); | |
| 473 v8::Local<v8::Object> obj; | |
| 474 if (!helper.firstArgAsObject().ToLocal(&obj)) | |
| 475 return; | |
| 476 v8::Local<v8::Array> names; | |
| 477 if (!obj->GetOwnPropertyNames(isolate->GetCurrentContext()).ToLocal(&names)) | |
| 478 return; | |
| 479 info.GetReturnValue().Set(names); | |
| 480 } | |
| 481 | |
| 482 void V8Console::valuesCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 483 { | |
| 484 v8::Isolate* isolate = info.GetIsolate(); | |
| 485 info.GetReturnValue().Set(v8::Array::New(isolate)); | |
| 486 | |
| 487 ConsoleHelper helper(info); | |
| 488 v8::Local<v8::Object> obj; | |
| 489 if (!helper.firstArgAsObject().ToLocal(&obj)) | |
| 490 return; | |
| 491 v8::Local<v8::Array> names; | |
| 492 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 493 if (!obj->GetOwnPropertyNames(context).ToLocal(&names)) | |
| 494 return; | |
| 495 v8::Local<v8::Array> values = v8::Array::New(isolate, names->Length()); | |
| 496 for (size_t i = 0; i < names->Length(); ++i) { | |
| 497 v8::Local<v8::Value> key; | |
| 498 if (!names->Get(context, i).ToLocal(&key)) | |
| 499 continue; | |
| 500 v8::Local<v8::Value> value; | |
| 501 if (!obj->Get(context, key).ToLocal(&value)) | |
| 502 continue; | |
| 503 if (!values->Set(context, i, value).FromMaybe(false)) | |
| 504 continue; | |
| 505 } | |
| 506 info.GetReturnValue().Set(values); | |
| 507 } | |
| 508 | |
| 509 static void setFunctionBreakpoint(ConsoleHelper& helper, v8::Local<v8::Function> function, V8DebuggerAgentImpl::BreakpointSource source, const String16& conditi on, bool enable) | |
| 510 { | |
| 511 if (V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent()) { | |
|
dgozman
2016/04/25 18:09:50
nit: early bailout
kozy
2016/04/25 19:31:06
Done.
| |
| 512 String16 scriptId = String16::number(function->ScriptId()); | |
| 513 int lineNumber = function->GetScriptLineNumber(); | |
| 514 int columnNumber = function->GetScriptColumnNumber(); | |
| 515 if (lineNumber == v8::Function::kLineOffsetNotFound || columnNumber == v 8::Function::kLineOffsetNotFound) | |
| 516 return; | |
| 517 if (enable) | |
| 518 debuggerAgent->setBreakpointAt(scriptId, lineNumber, columnNumber, s ource, condition); | |
| 519 else | |
| 520 debuggerAgent->removeBreakpointAt(scriptId, lineNumber, columnNumber , source); | |
| 521 } | |
| 522 } | |
| 523 | |
| 524 void V8Console::debugFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
| 525 { | |
| 526 ConsoleHelper helper(info); | |
| 527 v8::Local<v8::Function> function; | |
| 528 if (!helper.firstArgAsFunction().ToLocal(&function)) | |
| 529 return; | |
| 530 setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::DebugCommandBre akpointSource, String16(), true); | |
| 531 } | |
| 532 | |
| 533 void V8Console::undebugFunctionCallback(const v8::FunctionCallbackInfo<v8::Value >& info) | |
| 534 { | |
| 535 ConsoleHelper helper(info); | |
| 536 v8::Local<v8::Function> function; | |
| 537 if (!helper.firstArgAsFunction().ToLocal(&function)) | |
| 538 return; | |
| 539 setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::DebugCommandBre akpointSource, String16(), false); | |
| 540 } | |
| 541 | |
| 542 void V8Console::monitorFunctionCallback(const v8::FunctionCallbackInfo<v8::Value >& info) | |
| 543 { | |
| 544 ConsoleHelper helper(info); | |
| 545 v8::Local<v8::Function> function; | |
| 546 if (!helper.firstArgAsFunction().ToLocal(&function)) | |
| 547 return; | |
| 548 v8::Local<v8::Value> name; | |
| 549 if (info.Length() > 0 && info[0]->IsFunction()) { | |
| 550 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(info[0] ); | |
|
dgozman
2016/04/25 18:09:50
You already got this at line 545.
kozy
2016/04/25 19:31:06
Done.
| |
| 551 name = function->GetName(); | |
| 552 if (!name->IsString() || !v8::Local<v8::String>::Cast(name)->Length()) | |
| 553 name = function->GetInferredName(); | |
| 554 } | |
| 555 String16 functionName = toProtocolStringWithTypeCheck(name); | |
| 556 String16Builder builder; | |
| 557 builder.append("console.log(\"function "); | |
| 558 if (functionName.isEmpty()) | |
| 559 builder.append("(anonymous function)"); | |
| 560 else | |
| 561 builder.append(functionName); | |
| 562 builder.append(" called\" + (arguments.length > 0 ? \" with arguments: \" + Array.prototype.join.call(arguments, \", \") : \"\")) && false"); | |
| 563 setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::MonitorCommandB reakpointSource, builder.toString(), true); | |
| 564 } | |
| 565 | |
| 566 void V8Console::unmonitorFunctionCallback(const v8::FunctionCallbackInfo<v8::Val ue>& info) | |
| 567 { | |
| 568 ConsoleHelper helper(info); | |
| 569 v8::Local<v8::Function> function; | |
| 570 if (!helper.firstArgAsFunction().ToLocal(&function)) | |
| 571 return; | |
| 572 setFunctionBreakpoint(helper, function, V8DebuggerAgentImpl::MonitorCommandB reakpointSource, String16(), false); | |
| 573 } | |
| 574 | |
| 575 v8::MaybeLocal<v8::Object> V8Console::createConsole(v8::Local<v8::Context> conte xt, InspectedContext* inspectedContext, bool hasMemoryAttribute) | |
| 454 { | 576 { |
| 455 v8::Isolate* isolate = context->GetIsolate(); | 577 v8::Isolate* isolate = context->GetIsolate(); |
| 456 v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunM icrotasks); | 578 v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunM icrotasks); |
| 457 | 579 |
| 458 v8::Local<v8::Object> console; | 580 v8::Local<v8::Object> console; |
| 459 if (!createObjectWithClassName(inspectedContext->debugger(), context, "Conso le").ToLocal(&console)) | 581 if (!createObjectWithClassName(inspectedContext->debugger(), context, "Conso le").ToLocal(&console)) |
| 460 return v8::MaybeLocal<v8::Object>(); | 582 return v8::MaybeLocal<v8::Object>(); |
| 461 | 583 |
| 462 v8::Local<v8::Object> prototype; | 584 v8::Local<v8::Object> prototype; |
| 463 if (!createObjectWithClassName(inspectedContext->debugger(), context, "Conso lePrototype").ToLocal(&prototype)) | 585 if (!createObjectWithClassName(inspectedContext->debugger(), context, "Conso lePrototype").ToLocal(&prototype)) |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 490 if (!console->SetPrototype(context, prototype).FromMaybe(false)) | 612 if (!console->SetPrototype(context, prototype).FromMaybe(false)) |
| 491 return v8::MaybeLocal<v8::Object>(); | 613 return v8::MaybeLocal<v8::Object>(); |
| 492 | 614 |
| 493 if (hasMemoryAttribute) | 615 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); | 616 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 | 617 |
| 496 console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::Extern al::New(isolate, inspectedContext)); | 618 console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::Extern al::New(isolate, inspectedContext)); |
| 497 return console; | 619 return console; |
| 498 } | 620 } |
| 499 | 621 |
| 622 v8::Local<v8::Object> V8Console::createCommandLineAPI(v8::Local<v8::Context> con text, InspectedContext* inspectedContext) | |
| 623 { | |
| 624 v8::Isolate* isolate = context->GetIsolate(); | |
| 625 v8::MicrotasksScope microtasksScope(isolate, v8::MicrotasksScope::kDoNotRunM icrotasks); | |
| 626 | |
| 627 v8::Local<v8::Object> commandLineAPI = v8::Object::New(isolate); | |
| 628 | |
| 629 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "dir", V8Console::dirCallback); | |
| 630 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "dirxml ", V8Console::dirxmlCallback); | |
| 631 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "profil e", V8Console::profileCallback); | |
| 632 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "profil eEnd", V8Console::profileEndCallback); | |
| 633 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "clear" , V8Console::clearCallback); | |
| 634 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "table" , V8Console::tableCallback); | |
| 635 | |
| 636 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "keys", V8Console::keysCallback); | |
| 637 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "values ", V8Console::valuesCallback); | |
| 638 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "debug" , V8Console::debugFunctionCallback); | |
| 639 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "undebu g", V8Console::undebugFunctionCallback); | |
| 640 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "monito r", V8Console::monitorFunctionCallback); | |
| 641 createBoundFunctionProperty(context, commandLineAPI, commandLineAPI, "unmoni tor", V8Console::unmonitorFunctionCallback); | |
| 642 | |
| 643 commandLineAPI->SetPrivate(context, inspectedContextPrivateKey(isolate), v8: :External::New(isolate, inspectedContext)); | |
| 644 return commandLineAPI; | |
| 645 } | |
| 646 | |
| 500 void V8Console::clearInspectedContextIfNeeded(v8::Local<v8::Context> context, v8 ::Local<v8::Object> console) | 647 void V8Console::clearInspectedContextIfNeeded(v8::Local<v8::Context> context, v8 ::Local<v8::Object> console) |
| 501 { | 648 { |
| 502 v8::Isolate* isolate = context->GetIsolate(); | 649 v8::Isolate* isolate = context->GetIsolate(); |
| 503 console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::Extern al::New(isolate, nullptr)); | 650 console->SetPrivate(context, inspectedContextPrivateKey(isolate), v8::Extern al::New(isolate, nullptr)); |
| 504 } | 651 } |
| 505 | 652 |
| 653 bool V8Debugger::isCommandLineAPIMethod(const String16& name) | |
| 654 { | |
| 655 DEFINE_STATIC_LOCAL(protocol::HashSet<String16>, methods, ()); | |
| 656 if (methods.size() == 0) { | |
| 657 const char* members[] = { "$", "$$", "$x", "dir", "dirxml", "keys", "val ues", "profile", "profileEnd", | |
| 658 "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "get EventListeners", | |
| 659 "debug", "undebug", "monitor", "unmonitor", "table", "$_" }; | |
| 660 for (size_t i = 0; i < sizeof(members) / sizeof(const char*); ++i) | |
|
dgozman
2016/04/25 18:09:50
Not yours, but let's change to WTF_ARRAY_LENGTH.
kozy
2016/04/25 19:31:06
Done.
| |
| 661 methods.add(members[i]); | |
| 662 } | |
| 663 return methods.find(name) != methods.end(); | |
| 664 } | |
| 665 | |
| 666 bool V8Debugger::isCommandLineAPIGetter(const String16& name) | |
| 667 { | |
| 668 DEFINE_STATIC_LOCAL(protocol::HashSet<String16>, getters, ()); | |
| 669 if (getters.size() == 0) { | |
| 670 const char* members[] = { "$0", "$1", "$2", "$3", "$4" }; | |
| 671 for (size_t i = 0; i < sizeof(members) / sizeof(const char*); ++i) | |
|
dgozman
2016/04/25 18:09:50
ditto
kozy
2016/04/25 19:31:06
Done.
| |
| 672 getters.add(members[i]); | |
| 673 } | |
| 674 return getters.find(name) != getters.end(); | |
| 675 } | |
| 676 | |
| 506 } // namespace blink | 677 } // namespace blink |
| OLD | NEW |