2 * Copyright (C) 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "JSGlobalObjectInspectorController.h"
31 #include "Completion.h"
32 #include "ErrorHandlingScope.h"
33 #include "InjectedScriptHost.h"
34 #include "InjectedScriptManager.h"
35 #include "InspectorAgent.h"
36 #include "InspectorBackendDispatcher.h"
37 #include "InspectorFrontendChannel.h"
38 #include "JSConsoleClient.h"
39 #include "JSGlobalObject.h"
40 #include "JSGlobalObjectConsoleAgent.h"
41 #include "JSGlobalObjectDebuggerAgent.h"
42 #include "JSGlobalObjectProfilerAgent.h"
43 #include "JSGlobalObjectRuntimeAgent.h"
44 #include "ScriptArguments.h"
45 #include "ScriptCallStack.h"
46 #include "ScriptCallStackFactory.h"
55 JSGlobalObjectInspectorController::JSGlobalObjectInspectorController(JSGlobalObject
& globalObject
)
56 : m_globalObject(globalObject
)
57 , m_injectedScriptManager(std::make_unique
<InjectedScriptManager
>(*this, InjectedScriptHost::create()))
58 , m_inspectorFrontendChannel(nullptr)
59 , m_includeNativeCallStackWithExceptions(true)
61 auto runtimeAgent
= std::make_unique
<JSGlobalObjectRuntimeAgent
>(m_injectedScriptManager
.get(), m_globalObject
);
62 auto consoleAgent
= std::make_unique
<JSGlobalObjectConsoleAgent
>(m_injectedScriptManager
.get());
63 auto debuggerAgent
= std::make_unique
<JSGlobalObjectDebuggerAgent
>(m_injectedScriptManager
.get(), m_globalObject
, consoleAgent
.get());
64 auto profilerAgent
= std::make_unique
<JSGlobalObjectProfilerAgent
>(m_globalObject
);
66 m_consoleAgent
= consoleAgent
.get();
67 m_consoleClient
= std::make_unique
<JSConsoleClient
>(m_consoleAgent
, profilerAgent
.get());
69 runtimeAgent
->setScriptDebugServer(&debuggerAgent
->scriptDebugServer());
70 profilerAgent
->setScriptDebugServer(&debuggerAgent
->scriptDebugServer());
72 m_agents
.append(std::make_unique
<InspectorAgent
>());
73 m_agents
.append(WTF::move(runtimeAgent
));
74 m_agents
.append(WTF::move(consoleAgent
));
75 m_agents
.append(WTF::move(debuggerAgent
));
78 JSGlobalObjectInspectorController::~JSGlobalObjectInspectorController()
80 m_agents
.discardAgents();
83 void JSGlobalObjectInspectorController::globalObjectDestroyed()
85 disconnectFrontend(InspectorDisconnectReason::InspectedTargetDestroyed
);
87 m_injectedScriptManager
->disconnect();
90 void JSGlobalObjectInspectorController::connectFrontend(InspectorFrontendChannel
* frontendChannel
)
92 ASSERT(!m_inspectorFrontendChannel
);
93 ASSERT(!m_inspectorBackendDispatcher
);
95 m_inspectorFrontendChannel
= frontendChannel
;
96 m_inspectorBackendDispatcher
= InspectorBackendDispatcher::create(frontendChannel
);
98 m_agents
.didCreateFrontendAndBackend(frontendChannel
, m_inspectorBackendDispatcher
.get());
101 void JSGlobalObjectInspectorController::disconnectFrontend(InspectorDisconnectReason reason
)
103 if (!m_inspectorFrontendChannel
)
106 m_agents
.willDestroyFrontendAndBackend(reason
);
108 m_inspectorBackendDispatcher
->clearFrontend();
109 m_inspectorBackendDispatcher
.clear();
110 m_inspectorFrontendChannel
= nullptr;
113 void JSGlobalObjectInspectorController::dispatchMessageFromFrontend(const String
& message
)
115 if (m_inspectorBackendDispatcher
)
116 m_inspectorBackendDispatcher
->dispatch(message
);
119 void JSGlobalObjectInspectorController::appendAPIBacktrace(ScriptCallStack
* callStack
)
121 static const int framesToShow
= 31;
122 static const int framesToSkip
= 3; // WTFGetBacktrace, appendAPIBacktrace, reportAPIException.
124 void* samples
[framesToShow
+ framesToSkip
];
125 int frames
= framesToShow
+ framesToSkip
;
126 WTFGetBacktrace(samples
, &frames
);
128 void** stack
= samples
+ framesToSkip
;
129 int size
= frames
- framesToSkip
;
130 for (int i
= 0; i
< size
; ++i
) {
131 const char* mangledName
= nullptr;
132 char* cxaDemangled
= nullptr;
134 if (dladdr(stack
[i
], &info
) && info
.dli_sname
)
135 mangledName
= info
.dli_sname
;
137 cxaDemangled
= abi::__cxa_demangle(mangledName
, nullptr, nullptr, nullptr);
138 if (mangledName
|| cxaDemangled
)
139 callStack
->append(ScriptCallFrame(cxaDemangled
? cxaDemangled
: mangledName
, ASCIILiteral("[native code]"), 0, 0));
141 callStack
->append(ScriptCallFrame(ASCIILiteral("?"), ASCIILiteral("[native code]"), 0, 0));
146 void JSGlobalObjectInspectorController::reportAPIException(ExecState
* exec
, JSValue exception
)
148 if (isTerminatedExecutionException(exception
))
151 ErrorHandlingScope
errorScope(exec
->vm());
153 RefPtr
<ScriptCallStack
> callStack
= createScriptCallStackFromException(exec
, exception
, ScriptCallStack::maxCallStackSizeToCapture
);
154 if (includesNativeCallStackWhenReportingExceptions())
155 appendAPIBacktrace(callStack
.get());
157 // FIXME: <http://webkit.org/b/115087> Web Inspector: Should not evaluate JavaScript handling exceptions
158 // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception.
159 String errorMessage
= exception
.toString(exec
)->value(exec
);
160 exec
->clearException();
162 if (JSConsoleClient::logToSystemConsole()) {
163 if (callStack
->size()) {
164 const ScriptCallFrame
& callFrame
= callStack
->at(0);
165 ConsoleClient::printConsoleMessage(MessageSource::JS
, MessageType::Log
, MessageLevel::Error
, errorMessage
, callFrame
.sourceURL(), callFrame
.lineNumber(), callFrame
.columnNumber());
167 ConsoleClient::printConsoleMessage(MessageSource::JS
, MessageType::Log
, MessageLevel::Error
, errorMessage
, String(), 0, 0);
170 m_consoleAgent
->addMessageToConsole(MessageSource::JS
, MessageType::Log
, MessageLevel::Error
, errorMessage
, callStack
);
173 ConsoleClient
* JSGlobalObjectInspectorController::consoleClient() const
175 return m_consoleClient
.get();
178 InspectorFunctionCallHandler
JSGlobalObjectInspectorController::functionCallHandler() const
183 InspectorEvaluateHandler
JSGlobalObjectInspectorController::evaluateHandler() const
185 return JSC::evaluate
;
188 } // namespace Inspector
190 #endif // ENABLE(INSPECTOR)