| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project 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 "src/inspector/v8-debugger.h" | 5 #include "src/inspector/v8-debugger.h" |
| 6 | 6 |
| 7 #include "src/inspector/debugger-script.h" | 7 #include "src/inspector/debugger-script.h" |
| 8 #include "src/inspector/inspected-context.h" | 8 #include "src/inspector/inspected-context.h" |
| 9 #include "src/inspector/protocol/Protocol.h" | 9 #include "src/inspector/protocol/Protocol.h" |
| 10 #include "src/inspector/script-breakpoint.h" | 10 #include "src/inspector/script-breakpoint.h" |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 compileDebuggerScript(); | 187 compileDebuggerScript(); |
| 188 } | 188 } |
| 189 | 189 |
| 190 void V8Debugger::disable() { | 190 void V8Debugger::disable() { |
| 191 if (--m_enableCount) return; | 191 if (--m_enableCount) return; |
| 192 DCHECK(enabled()); | 192 DCHECK(enabled()); |
| 193 clearBreakpoints(); | 193 clearBreakpoints(); |
| 194 m_debuggerScript.Reset(); | 194 m_debuggerScript.Reset(); |
| 195 m_debuggerContext.Reset(); | 195 m_debuggerContext.Reset(); |
| 196 allAsyncTasksCanceled(); | 196 allAsyncTasksCanceled(); |
| 197 m_tasksWithScheduledBreak.clear(); |
| 197 m_wasmTranslation.Clear(); | 198 m_wasmTranslation.Clear(); |
| 198 v8::debug::SetDebugDelegate(m_isolate, nullptr); | 199 v8::debug::SetDebugDelegate(m_isolate, nullptr); |
| 199 v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr); | 200 v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr); |
| 200 m_isolate->RestoreOriginalHeapLimit(); | 201 m_isolate->RestoreOriginalHeapLimit(); |
| 201 } | 202 } |
| 202 | 203 |
| 203 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } | 204 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } |
| 204 | 205 |
| 205 void V8Debugger::getCompiledScripts( | 206 void V8Debugger::getCompiledScripts( |
| 206 int contextGroupId, | 207 int contextGroupId, |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 v8::Local<v8::Function> breakFunction; | 350 v8::Local<v8::Function> breakFunction; |
| 350 if (!v8::Function::New(m_isolate->GetCurrentContext(), | 351 if (!v8::Function::New(m_isolate->GetCurrentContext(), |
| 351 &V8Debugger::breakProgramCallback, | 352 &V8Debugger::breakProgramCallback, |
| 352 v8::External::New(m_isolate, this), 0, | 353 v8::External::New(m_isolate, this), 0, |
| 353 v8::ConstructorBehavior::kThrow) | 354 v8::ConstructorBehavior::kThrow) |
| 354 .ToLocal(&breakFunction)) | 355 .ToLocal(&breakFunction)) |
| 355 return; | 356 return; |
| 356 v8::debug::Call(debuggerContext(), breakFunction).ToLocalChecked(); | 357 v8::debug::Call(debuggerContext(), breakFunction).ToLocalChecked(); |
| 357 } | 358 } |
| 358 | 359 |
| 359 void V8Debugger::continueProgram() { | 360 void V8Debugger::continueProgramImpl() { |
| 360 if (isPaused()) m_inspector->client()->quitMessageLoopOnPause(); | 361 if (!isPaused()) return; |
| 362 m_inspector->client()->quitMessageLoopOnPause(); |
| 361 m_pausedContext.Clear(); | 363 m_pausedContext.Clear(); |
| 362 m_executionState.Clear(); | 364 m_executionState.Clear(); |
| 363 } | 365 } |
| 364 | 366 |
| 367 void V8Debugger::continueProgram() { |
| 368 if (!isPaused()) return; |
| 369 v8::debug::ClearStepping(m_isolate); |
| 370 continueProgramImpl(); |
| 371 } |
| 372 |
| 365 void V8Debugger::stepIntoStatement() { | 373 void V8Debugger::stepIntoStatement() { |
| 366 DCHECK(isPaused()); | 374 DCHECK(isPaused()); |
| 367 DCHECK(!m_executionState.IsEmpty()); | 375 DCHECK(!m_executionState.IsEmpty()); |
| 368 v8::debug::PrepareStep(m_isolate, v8::debug::StepIn); | 376 v8::debug::PrepareStep(m_isolate, v8::debug::StepIn); |
| 369 continueProgram(); | 377 continueProgramImpl(); |
| 370 } | 378 } |
| 371 | 379 |
| 372 void V8Debugger::stepOverStatement() { | 380 void V8Debugger::stepOverStatement() { |
| 373 DCHECK(isPaused()); | 381 DCHECK(isPaused()); |
| 374 DCHECK(!m_executionState.IsEmpty()); | 382 DCHECK(!m_executionState.IsEmpty()); |
| 375 v8::debug::PrepareStep(m_isolate, v8::debug::StepNext); | 383 v8::debug::PrepareStep(m_isolate, v8::debug::StepNext); |
| 376 continueProgram(); | 384 continueProgramImpl(); |
| 377 } | 385 } |
| 378 | 386 |
| 379 void V8Debugger::stepOutOfFunction() { | 387 void V8Debugger::stepOutOfFunction() { |
| 380 DCHECK(isPaused()); | 388 DCHECK(isPaused()); |
| 381 DCHECK(!m_executionState.IsEmpty()); | 389 DCHECK(!m_executionState.IsEmpty()); |
| 382 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); | 390 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); |
| 383 continueProgram(); | 391 continueProgramImpl(); |
| 392 } |
| 393 |
| 394 Response V8Debugger::stepIntoScheduledCallback() { |
| 395 DCHECK(isPaused()); |
| 396 DCHECK(!m_executionState.IsEmpty()); |
| 397 |
| 398 if (!stepIntoScheduledCallbackAvailable()) { |
| 399 return Response::Error("No scheduled callback for stepInto available."); |
| 400 } |
| 401 m_tasksWithScheduledBreak.insert(m_createdPromiseTask); |
| 402 v8::debug::ClearStepping(m_isolate); |
| 403 continueProgramImpl(); |
| 404 return Response::OK(); |
| 405 } |
| 406 |
| 407 bool V8Debugger::stepIntoScheduledCallbackAvailable() { |
| 408 return m_createdPromiseTask; |
| 384 } | 409 } |
| 385 | 410 |
| 386 Response V8Debugger::setScriptSource( | 411 Response V8Debugger::setScriptSource( |
| 387 const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, | 412 const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, |
| 388 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails, | 413 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails, |
| 389 JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged, | 414 JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged, |
| 390 bool* compileError) { | 415 bool* compileError) { |
| 391 class EnableLiveEditScope { | 416 class EnableLiveEditScope { |
| 392 public: | 417 public: |
| 393 explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { | 418 explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 | 643 |
| 619 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, | 644 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, |
| 620 const v8::debug::Location& start, | 645 const v8::debug::Location& start, |
| 621 const v8::debug::Location& end) { | 646 const v8::debug::Location& end) { |
| 622 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script); | 647 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script); |
| 623 if (!agent) return false; | 648 if (!agent) return false; |
| 624 return agent->isFunctionBlackboxed(String16::fromInteger(script->Id()), start, | 649 return agent->isFunctionBlackboxed(String16::fromInteger(script->Id()), start, |
| 625 end); | 650 end); |
| 626 } | 651 } |
| 627 | 652 |
| 628 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, | 653 void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context, |
| 629 int id, int parentId) { | 654 v8::debug::PromiseDebugActionType type, |
| 630 if (!m_maxAsyncCallStackDepth) return; | 655 int id, int parentId, bool breakable) { |
| 631 // Async task events from Promises are given misaligned pointers to prevent | 656 // Async task events from Promises are given misaligned pointers to prevent |
| 632 // from overlapping with other Blink task identifiers. There is a single | 657 // from overlapping with other Blink task identifiers. There is a single |
| 633 // namespace of such ids, managed by src/js/promise.js. | 658 // namespace of such ids, managed by src/js/promise.js. |
| 634 void* ptr = reinterpret_cast<void*>(id * 2 + 1); | 659 void* ptr = reinterpret_cast<void*>(id * 2 + 1); |
| 660 void* parentPtr = |
| 661 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; |
| 662 if ((breakable && type == v8::debug::kDebugPromiseCreated) || |
| 663 type == v8::debug::kDebugWillHandle || |
| 664 type == v8::debug::kDebugDidHandle || |
| 665 type == v8::debug::kDebugPromiseCollected) { |
| 666 steppingOnPromiseEvent(context, type, ptr, parentPtr); |
| 667 } |
| 668 if (!m_maxAsyncCallStackDepth) return; |
| 635 switch (type) { | 669 switch (type) { |
| 636 case v8::debug::kDebugPromiseCreated: | 670 case v8::debug::kDebugPromiseCreated: |
| 637 asyncTaskCreated( | 671 asyncTaskCreated(ptr, parentPtr); |
| 638 ptr, parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr); | |
| 639 break; | 672 break; |
| 640 case v8::debug::kDebugEnqueueAsyncFunction: | 673 case v8::debug::kDebugEnqueueAsyncFunction: |
| 641 asyncTaskScheduled("async function", ptr, true); | 674 asyncTaskScheduled("async function", ptr, true); |
| 642 break; | 675 break; |
| 643 case v8::debug::kDebugEnqueuePromiseResolve: | 676 case v8::debug::kDebugEnqueuePromiseResolve: |
| 644 asyncTaskScheduled("Promise.resolve", ptr, true); | 677 asyncTaskScheduled("Promise.resolve", ptr, true); |
| 645 break; | 678 break; |
| 646 case v8::debug::kDebugEnqueuePromiseReject: | 679 case v8::debug::kDebugEnqueuePromiseReject: |
| 647 asyncTaskScheduled("Promise.reject", ptr, true); | 680 asyncTaskScheduled("Promise.reject", ptr, true); |
| 648 break; | 681 break; |
| 649 case v8::debug::kDebugPromiseCollected: | 682 case v8::debug::kDebugPromiseCollected: |
| 650 asyncTaskCanceled(ptr); | 683 asyncTaskCanceled(ptr); |
| 651 break; | 684 break; |
| 652 case v8::debug::kDebugWillHandle: | 685 case v8::debug::kDebugWillHandle: |
| 653 asyncTaskStarted(ptr); | 686 asyncTaskStarted(ptr); |
| 654 break; | 687 break; |
| 655 case v8::debug::kDebugDidHandle: | 688 case v8::debug::kDebugDidHandle: |
| 656 asyncTaskFinished(ptr); | 689 asyncTaskFinished(ptr); |
| 657 break; | 690 break; |
| 658 } | 691 } |
| 659 } | 692 } |
| 660 | 693 |
| 694 void V8Debugger::steppingOnPromiseEvent(v8::Local<v8::Context> context, |
| 695 v8::debug::PromiseDebugActionType type, |
| 696 void* task, void* parentPtr) { |
| 697 if (type == v8::debug::kDebugPromiseCollected) { |
| 698 m_tasksWithScheduledBreak.erase(task); |
| 699 return; |
| 700 } |
| 701 DCHECK(!context.IsEmpty()); |
| 702 v8::Context::Scope contextScope(context); |
| 703 V8DebuggerAgentImpl* agent = |
| 704 m_inspector->enabledDebuggerAgentForGroup(currentContextGroupId()); |
| 705 if (!agent) return; |
| 706 if (type == v8::debug::kDebugPromiseCreated) { |
| 707 if (!parentPtr) return; |
| 708 m_createdPromiseTask = task; |
| 709 agent->breakProgramIfSteppingInto( |
| 710 protocol::Debugger::Paused::ReasonEnum::Other, nullptr); |
| 711 m_createdPromiseTask = nullptr; |
| 712 return; |
| 713 } |
| 714 if (m_tasksWithScheduledBreak.find(task) == m_tasksWithScheduledBreak.end()) { |
| 715 return; |
| 716 } |
| 717 if (type == v8::debug::kDebugWillHandle) { |
| 718 agent->schedulePauseOnNextStatement( |
| 719 protocol::Debugger::Paused::ReasonEnum::Other, nullptr); |
| 720 } else { |
| 721 agent->cancelPauseOnNextStatement(); |
| 722 } |
| 723 } |
| 724 |
| 661 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { | 725 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { |
| 662 if (!m_currentStacks.size()) return nullptr; | 726 if (!m_currentStacks.size()) return nullptr; |
| 663 return m_currentStacks.back().get(); | 727 return m_currentStacks.back().get(); |
| 664 } | 728 } |
| 665 | 729 |
| 666 void V8Debugger::compileDebuggerScript() { | 730 void V8Debugger::compileDebuggerScript() { |
| 667 if (!m_debuggerScript.IsEmpty()) { | 731 if (!m_debuggerScript.IsEmpty()) { |
| 668 UNREACHABLE(); | 732 UNREACHABLE(); |
| 669 return; | 733 return; |
| 670 } | 734 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 createDataProperty(context, properties, properties->Length(), | 859 createDataProperty(context, properties, properties->Length(), |
| 796 toV8StringInternalized(m_isolate, "[[Scopes]]")); | 860 toV8StringInternalized(m_isolate, "[[Scopes]]")); |
| 797 createDataProperty(context, properties, properties->Length(), scopes); | 861 createDataProperty(context, properties, properties->Length(), scopes); |
| 798 } | 862 } |
| 799 } | 863 } |
| 800 return properties; | 864 return properties; |
| 801 } | 865 } |
| 802 | 866 |
| 803 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace( | 867 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace( |
| 804 v8::Local<v8::StackTrace> stackTrace) { | 868 v8::Local<v8::StackTrace> stackTrace) { |
| 805 int contextGroupId = | 869 return V8StackTraceImpl::create(this, currentContextGroupId(), stackTrace, |
| 806 m_isolate->InContext() | |
| 807 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext()) | |
| 808 : 0; | |
| 809 return V8StackTraceImpl::create(this, contextGroupId, stackTrace, | |
| 810 V8StackTraceImpl::maxCallStackSizeToCapture); | 870 V8StackTraceImpl::maxCallStackSizeToCapture); |
| 811 } | 871 } |
| 812 | 872 |
| 813 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) { | 873 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) { |
| 814 if (depth <= 0) | 874 if (depth <= 0) |
| 815 m_maxAsyncCallStackDepthMap.erase(agent); | 875 m_maxAsyncCallStackDepthMap.erase(agent); |
| 816 else | 876 else |
| 817 m_maxAsyncCallStackDepthMap[agent] = depth; | 877 m_maxAsyncCallStackDepthMap[agent] = depth; |
| 818 | 878 |
| 819 int maxAsyncCallStackDepth = 0; | 879 int maxAsyncCallStackDepth = 0; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 836 if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) { | 896 if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) { |
| 837 void* taskToRemove = m_idToTask.begin()->second; | 897 void* taskToRemove = m_idToTask.begin()->second; |
| 838 asyncTaskCanceled(taskToRemove); | 898 asyncTaskCanceled(taskToRemove); |
| 839 } | 899 } |
| 840 } | 900 } |
| 841 | 901 |
| 842 void V8Debugger::asyncTaskCreated(void* task, void* parentTask) { | 902 void V8Debugger::asyncTaskCreated(void* task, void* parentTask) { |
| 843 if (!m_maxAsyncCallStackDepth) return; | 903 if (!m_maxAsyncCallStackDepth) return; |
| 844 if (parentTask) m_parentTask[task] = parentTask; | 904 if (parentTask) m_parentTask[task] = parentTask; |
| 845 v8::HandleScope scope(m_isolate); | 905 v8::HandleScope scope(m_isolate); |
| 846 // We don't need to pass context group id here because we gets this callback | 906 // We don't need to pass context group id here because we get this callback |
| 847 // from V8 for promise events only. | 907 // from V8 for promise events only. |
| 848 // Passing one as maxStackSize forces no async chain for the new stack and | 908 // Passing one as maxStackSize forces no async chain for the new stack and |
| 849 // allows us to not grow exponentially. | 909 // allows us to not grow exponentially. |
| 850 std::unique_ptr<V8StackTraceImpl> creationStack = | 910 std::unique_ptr<V8StackTraceImpl> creationStack = |
| 851 V8StackTraceImpl::capture(this, 0, 1, String16()); | 911 V8StackTraceImpl::capture(this, 0, 1, String16()); |
| 852 if (creationStack && !creationStack->isEmpty()) { | 912 if (creationStack && !creationStack->isEmpty()) { |
| 853 m_asyncTaskCreationStacks[task] = std::move(creationStack); | 913 m_asyncTaskCreationStacks[task] = std::move(creationStack); |
| 854 registerAsyncTaskIfNeeded(task); | 914 registerAsyncTaskIfNeeded(task); |
| 855 } | 915 } |
| 856 } | 916 } |
| 857 | 917 |
| 858 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, | 918 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, |
| 859 bool recurring) { | 919 bool recurring) { |
| 860 if (!m_maxAsyncCallStackDepth) return; | 920 if (!m_maxAsyncCallStackDepth) return; |
| 861 asyncTaskScheduled(toString16(taskName), task, recurring); | 921 asyncTaskScheduled(toString16(taskName), task, recurring); |
| 862 } | 922 } |
| 863 | 923 |
| 864 void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, | 924 void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, |
| 865 bool recurring) { | 925 bool recurring) { |
| 866 if (!m_maxAsyncCallStackDepth) return; | 926 if (!m_maxAsyncCallStackDepth) return; |
| 867 v8::HandleScope scope(m_isolate); | 927 v8::HandleScope scope(m_isolate); |
| 868 int contextGroupId = | |
| 869 m_isolate->InContext() | |
| 870 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext()) | |
| 871 : 0; | |
| 872 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( | 928 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( |
| 873 this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture, | 929 this, currentContextGroupId(), |
| 874 taskName); | 930 V8StackTraceImpl::maxCallStackSizeToCapture, taskName); |
| 875 if (chain) { | 931 if (chain) { |
| 876 m_asyncTaskStacks[task] = std::move(chain); | 932 m_asyncTaskStacks[task] = std::move(chain); |
| 877 if (recurring) m_recurringTasks.insert(task); | 933 if (recurring) m_recurringTasks.insert(task); |
| 878 registerAsyncTaskIfNeeded(task); | 934 registerAsyncTaskIfNeeded(task); |
| 879 } | 935 } |
| 880 } | 936 } |
| 881 | 937 |
| 882 void V8Debugger::asyncTaskCanceled(void* task) { | 938 void V8Debugger::asyncTaskCanceled(void* task) { |
| 883 if (!m_maxAsyncCallStackDepth) return; | 939 if (!m_maxAsyncCallStackDepth) return; |
| 884 m_asyncTaskStacks.erase(task); | 940 m_asyncTaskStacks.erase(task); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 void V8Debugger::unmuteScriptParsedEvents() { | 1003 void V8Debugger::unmuteScriptParsedEvents() { |
| 948 --m_ignoreScriptParsedEventsCounter; | 1004 --m_ignoreScriptParsedEventsCounter; |
| 949 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); | 1005 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); |
| 950 } | 1006 } |
| 951 | 1007 |
| 952 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( | 1008 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( |
| 953 bool fullStack) { | 1009 bool fullStack) { |
| 954 if (!m_isolate->InContext()) return nullptr; | 1010 if (!m_isolate->InContext()) return nullptr; |
| 955 | 1011 |
| 956 v8::HandleScope handles(m_isolate); | 1012 v8::HandleScope handles(m_isolate); |
| 957 int contextGroupId = | 1013 int contextGroupId = currentContextGroupId(); |
| 958 m_inspector->contextGroupId(m_isolate->GetCurrentContext()); | |
| 959 if (!contextGroupId) return nullptr; | 1014 if (!contextGroupId) return nullptr; |
| 960 | 1015 |
| 961 size_t stackSize = | 1016 size_t stackSize = |
| 962 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 1017 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
| 963 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 1018 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
| 964 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 1019 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
| 965 | 1020 |
| 966 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1021 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
| 967 } | 1022 } |
| 968 | 1023 |
| 1024 int V8Debugger::currentContextGroupId() { |
| 1025 if (!m_isolate->InContext()) return 0; |
| 1026 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); |
| 1027 } |
| 1028 |
| 969 } // namespace v8_inspector | 1029 } // namespace v8_inspector |
| OLD | NEW |