]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/ConsoleClient.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / ConsoleClient.cpp
1 /*
2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26 #include "config.h"
27 #include "ConsoleClient.h"
28
29 #include "ScriptArguments.h"
30 #include "ScriptCallStack.h"
31 #include "ScriptCallStackFactory.h"
32 #include "ScriptValue.h"
33 #include <wtf/Assertions.h>
34 #include <wtf/text/CString.h>
35 #include <wtf/text/StringBuilder.h>
36 #include <wtf/text/WTFString.h>
37
38 using namespace Inspector;
39
40 namespace JSC {
41
42 static void appendURLAndPosition(StringBuilder& builder, const String& url, unsigned lineNumber, unsigned columnNumber)
43 {
44 if (url.isEmpty())
45 return;
46
47 builder.append(url);
48
49 if (lineNumber > 0) {
50 builder.append(':');
51 builder.appendNumber(lineNumber);
52 }
53
54 if (columnNumber > 0) {
55 builder.append(':');
56 builder.appendNumber(columnNumber);
57 }
58 }
59
60 static void appendMessagePrefix(StringBuilder& builder, MessageSource source, MessageType type, MessageLevel level)
61 {
62 const char* sourceString;
63 switch (source) {
64 case MessageSource::XML:
65 sourceString = "XML";
66 break;
67 case MessageSource::JS:
68 sourceString = "JS";
69 break;
70 case MessageSource::Network:
71 sourceString = "NETWORK";
72 break;
73 case MessageSource::ConsoleAPI:
74 sourceString = "CONSOLE";
75 break;
76 case MessageSource::Storage:
77 sourceString = "STORAGE";
78 break;
79 case MessageSource::AppCache:
80 sourceString = "APPCACHE";
81 break;
82 case MessageSource::Rendering:
83 sourceString = "RENDERING";
84 break;
85 case MessageSource::CSS:
86 sourceString = "CSS";
87 break;
88 case MessageSource::Security:
89 sourceString = "SECURITY";
90 break;
91 case MessageSource::Other:
92 sourceString = "OTHER";
93 break;
94 default:
95 ASSERT_NOT_REACHED();
96 sourceString = "UNKNOWN";
97 break;
98 }
99
100 const char* levelString;
101 switch (level) {
102 case MessageLevel::Debug:
103 levelString = "DEBUG";
104 break;
105 case MessageLevel::Log:
106 levelString = "LOG";
107 break;
108 case MessageLevel::Info:
109 levelString = "INFO";
110 break;
111 case MessageLevel::Warning:
112 levelString = "WARN";
113 break;
114 case MessageLevel::Error:
115 levelString = "ERROR";
116 break;
117 default:
118 ASSERT_NOT_REACHED();
119 levelString = "UNKNOWN";
120 break;
121 }
122
123 if (type == MessageType::Trace)
124 levelString = "TRACE";
125 else if (type == MessageType::Table)
126 levelString = "TABLE";
127
128 builder.append(sourceString);
129 builder.append(' ');
130 builder.append(levelString);
131 }
132
133 void ConsoleClient::printConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, const String& url, unsigned lineNumber, unsigned columnNumber)
134 {
135 StringBuilder builder;
136
137 if (!url.isEmpty()) {
138 appendURLAndPosition(builder, url, lineNumber, columnNumber);
139 builder.appendLiteral(": ");
140 }
141
142 appendMessagePrefix(builder, source, type, level);
143 builder.append(' ');
144 builder.append(message);
145
146 WTFLogAlways("%s", builder.toString().utf8().data());
147 }
148
149 void ConsoleClient::printConsoleMessageWithArguments(MessageSource source, MessageType type, MessageLevel level, JSC::ExecState* exec, RefPtr<ScriptArguments>&& prpArguments)
150 {
151 RefPtr<ScriptArguments> arguments = prpArguments;
152
153 bool isTraceMessage = type == MessageType::Trace;
154 size_t stackSize = isTraceMessage ? ScriptCallStack::maxCallStackSizeToCapture : 1;
155 RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(exec, stackSize));
156 const ScriptCallFrame& lastCaller = callStack->at(0);
157
158 StringBuilder builder;
159
160 if (!lastCaller.sourceURL().isEmpty()) {
161 appendURLAndPosition(builder, lastCaller.sourceURL(), lastCaller.lineNumber(), lastCaller.columnNumber());
162 builder.appendLiteral(": ");
163 }
164
165 appendMessagePrefix(builder, source, type, level);
166 for (size_t i = 0; i < arguments->argumentCount(); ++i) {
167 String argAsString = arguments->argumentAt(i).toString(arguments->globalState());
168 builder.append(' ');
169 builder.append(argAsString.utf8().data());
170 }
171
172 WTFLogAlways("%s", builder.toString().utf8().data());
173
174 if (isTraceMessage) {
175 for (size_t i = 0; i < callStack->size(); ++i) {
176 const ScriptCallFrame& callFrame = callStack->at(i);
177 String functionName = String(callFrame.functionName());
178 if (functionName.isEmpty())
179 functionName = ASCIILiteral("(unknown)");
180
181 StringBuilder callFrameBuilder;
182 callFrameBuilder.appendNumber(static_cast<unsigned long>(i));
183 callFrameBuilder.appendLiteral(": ");
184 callFrameBuilder.append(functionName);
185 callFrameBuilder.append('(');
186 appendURLAndPosition(callFrameBuilder, callFrame.sourceURL(), callFrame.lineNumber(), callFrame.columnNumber());
187 callFrameBuilder.append(')');
188
189 WTFLogAlways("%s", callFrameBuilder.toString().utf8().data());
190 }
191 }
192 }
193
194 void ConsoleClient::internalMessageWithTypeAndLevel(MessageType type, MessageLevel level, JSC::ExecState* exec, RefPtr<ScriptArguments>&& prpArguments, ArgumentRequirement argumentRequirement)
195 {
196 RefPtr<ScriptArguments> arguments = prpArguments;
197 if (argumentRequirement == ArgumentRequired && !arguments->argumentCount())
198 return;
199
200 messageWithTypeAndLevel(type, level, exec, arguments.release());
201 }
202
203 void ConsoleClient::logWithLevel(ExecState* exec, RefPtr<ScriptArguments>&& arguments, MessageLevel level)
204 {
205 internalMessageWithTypeAndLevel(MessageType::Log, level, exec, WTF::move(arguments), ArgumentRequired);
206 }
207
208 void ConsoleClient::clear(ExecState* exec, RefPtr<ScriptArguments>&& arguments)
209 {
210 internalMessageWithTypeAndLevel(MessageType::Clear, MessageLevel::Log, exec, WTF::move(arguments), ArgumentNotRequired);
211 }
212
213 void ConsoleClient::dir(ExecState* exec, RefPtr<ScriptArguments>&& arguments)
214 {
215 internalMessageWithTypeAndLevel(MessageType::Dir, MessageLevel::Log, exec, WTF::move(arguments), ArgumentRequired);
216 }
217
218 void ConsoleClient::dirXML(ExecState* exec, RefPtr<ScriptArguments>&& arguments)
219 {
220 internalMessageWithTypeAndLevel(MessageType::DirXML, MessageLevel::Log, exec, WTF::move(arguments), ArgumentRequired);
221 }
222
223 void ConsoleClient::table(ExecState* exec, RefPtr<ScriptArguments>&& arguments)
224 {
225 internalMessageWithTypeAndLevel(MessageType::Table, MessageLevel::Log, exec, WTF::move(arguments), ArgumentRequired);
226 }
227
228 void ConsoleClient::trace(ExecState* exec, RefPtr<ScriptArguments>&& arguments)
229 {
230 internalMessageWithTypeAndLevel(MessageType::Trace, MessageLevel::Log, exec, WTF::move(arguments), ArgumentNotRequired);
231 }
232
233 void ConsoleClient::assertCondition(ExecState* exec, RefPtr<ScriptArguments>&& arguments, bool condition)
234 {
235 if (condition)
236 return;
237
238 internalMessageWithTypeAndLevel(MessageType::Assert, MessageLevel::Error, exec, WTF::move(arguments), ArgumentNotRequired);
239 }
240
241 void ConsoleClient::group(ExecState* exec, RefPtr<ScriptArguments>&& arguments)
242 {
243 internalMessageWithTypeAndLevel(MessageType::StartGroup, MessageLevel::Log, exec, WTF::move(arguments), ArgumentNotRequired);
244 }
245
246 void ConsoleClient::groupCollapsed(ExecState* exec, RefPtr<ScriptArguments>&& arguments)
247 {
248 internalMessageWithTypeAndLevel(MessageType::StartGroupCollapsed, MessageLevel::Log, exec, WTF::move(arguments), ArgumentNotRequired);
249 }
250
251 void ConsoleClient::groupEnd(ExecState* exec, RefPtr<ScriptArguments>&& arguments)
252 {
253 internalMessageWithTypeAndLevel(MessageType::EndGroup, MessageLevel::Log, exec, WTF::move(arguments), ArgumentNotRequired);
254 }
255
256 } // namespace JSC