08a7a0355908c3c6b25c46ef926fdaaa4544f153
[WebKit-https.git] / Source / JavaScriptCore / runtime / ConsoleObject.cpp
1 /*
2  * Copyright (C) 2014-2016 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 "ConsoleObject.h"
28
29 #include "ConsoleClient.h"
30 #include "Error.h"
31 #include "JSCInlines.h"
32 #include "ScriptArguments.h"
33 #include "ScriptCallStackFactory.h"
34
35 namespace JSC {
36
37 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ConsoleObject);
38
39 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncDebug(ExecState*);
40 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncError(ExecState*);
41 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncLog(ExecState*);
42 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncInfo(ExecState*);
43 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncWarn(ExecState*);
44 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncClear(ExecState*);
45 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncDir(ExecState*);
46 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncDirXML(ExecState*);
47 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTable(ExecState*);
48 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTrace(ExecState*);
49 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncAssert(ExecState*);
50 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncCount(ExecState*);
51 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfile(ExecState*);
52 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfileEnd(ExecState*);
53 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTakeHeapSnapshot(ExecState*);
54 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTime(ExecState*);
55 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTimeEnd(ExecState*);
56 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTimeStamp(ExecState*);
57 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroup(ExecState*);
58 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroupCollapsed(ExecState*);
59 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroupEnd(ExecState*);
60
61 const ClassInfo ConsoleObject::s_info = { "Console", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ConsoleObject) };
62
63 ConsoleObject::ConsoleObject(VM& vm, Structure* structure)
64     : JSNonFinalObject(vm, structure)
65 {
66 }
67
68 void ConsoleObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
69 {
70     Base::finishCreation(vm);
71     ASSERT(inherits(vm, info()));
72
73     // For legacy reasons, console properties are enumerable, writable, deleteable,
74     // and all have a length of 0. This may change if Console is standardized.
75
76     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("debug", consoleProtoFuncDebug, static_cast<unsigned>(PropertyAttribute::None), 0);
77     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("error", consoleProtoFuncError, static_cast<unsigned>(PropertyAttribute::None), 0);
78     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("log", consoleProtoFuncLog, static_cast<unsigned>(PropertyAttribute::None), 0);
79     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("info", consoleProtoFuncInfo, static_cast<unsigned>(PropertyAttribute::None), 0);
80     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("warn", consoleProtoFuncWarn, static_cast<unsigned>(PropertyAttribute::None), 0);
81
82     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, consoleProtoFuncClear, static_cast<unsigned>(PropertyAttribute::None), 0);
83     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("dir", consoleProtoFuncDir, static_cast<unsigned>(PropertyAttribute::None), 0);
84     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("dirxml", consoleProtoFuncDirXML, static_cast<unsigned>(PropertyAttribute::None), 0);
85     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("table", consoleProtoFuncTable, static_cast<unsigned>(PropertyAttribute::None), 0);
86     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("trace", consoleProtoFuncTrace, static_cast<unsigned>(PropertyAttribute::None), 0);
87     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("assert", consoleProtoFuncAssert, static_cast<unsigned>(PropertyAttribute::None), 0);
88     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->count, consoleProtoFuncCount, static_cast<unsigned>(PropertyAttribute::None), 0);
89     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("profile", consoleProtoFuncProfile, static_cast<unsigned>(PropertyAttribute::None), 0);
90     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("profileEnd", consoleProtoFuncProfileEnd, static_cast<unsigned>(PropertyAttribute::None), 0);
91     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("time", consoleProtoFuncTime, static_cast<unsigned>(PropertyAttribute::None), 0);
92     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("timeEnd", consoleProtoFuncTimeEnd, static_cast<unsigned>(PropertyAttribute::None), 0);
93     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("timeStamp", consoleProtoFuncTimeStamp, static_cast<unsigned>(PropertyAttribute::None), 0);
94     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("takeHeapSnapshot", consoleProtoFuncTakeHeapSnapshot, static_cast<unsigned>(PropertyAttribute::None), 0);
95     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("group", consoleProtoFuncGroup, static_cast<unsigned>(PropertyAttribute::None), 0);
96     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("groupCollapsed", consoleProtoFuncGroupCollapsed, static_cast<unsigned>(PropertyAttribute::None), 0);
97     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("groupEnd", consoleProtoFuncGroupEnd, static_cast<unsigned>(PropertyAttribute::None), 0);
98 }
99
100 static String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
101 {
102     if (value.isUndefinedOrNull())
103         return String();
104     return value.toWTFString(exec);
105 }
106
107 static EncodedJSValue consoleLogWithLevel(ExecState* exec, MessageLevel level)
108 {
109     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
110     if (!client)
111         return JSValue::encode(jsUndefined());
112
113     client->logWithLevel(exec, Inspector::createScriptArguments(exec, 0), level);
114     return JSValue::encode(jsUndefined());
115 }
116
117 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncDebug(ExecState* exec)
118 {
119     return consoleLogWithLevel(exec, MessageLevel::Debug);
120 }
121
122 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncError(ExecState* exec)
123 {
124     return consoleLogWithLevel(exec, MessageLevel::Error);
125 }
126
127 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncLog(ExecState* exec)
128 {
129     return consoleLogWithLevel(exec, MessageLevel::Log);
130 }
131
132 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncInfo(ExecState* exec)
133 {
134     return consoleLogWithLevel(exec, MessageLevel::Info);
135 }
136
137 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncWarn(ExecState* exec)
138 {
139     return consoleLogWithLevel(exec, MessageLevel::Warning);
140 }
141
142 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncClear(ExecState* exec)
143 {
144     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
145     if (!client)
146         return JSValue::encode(jsUndefined());
147
148     client->clear(exec);
149     return JSValue::encode(jsUndefined());
150 }
151
152 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncDir(ExecState* exec)
153 {
154     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
155     if (!client)
156         return JSValue::encode(jsUndefined());
157
158     client->dir(exec, Inspector::createScriptArguments(exec, 0));
159     return JSValue::encode(jsUndefined());
160 }
161
162 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncDirXML(ExecState* exec)
163 {
164     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
165     if (!client)
166         return JSValue::encode(jsUndefined());
167
168     client->dirXML(exec, Inspector::createScriptArguments(exec, 0));
169     return JSValue::encode(jsUndefined());
170 }
171
172 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTable(ExecState* exec)
173 {
174     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
175     if (!client)
176         return JSValue::encode(jsUndefined());
177
178     client->table(exec, Inspector::createScriptArguments(exec, 0));
179     return JSValue::encode(jsUndefined());
180 }
181
182 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTrace(ExecState* exec)
183 {
184     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
185     if (!client)
186         return JSValue::encode(jsUndefined());
187
188     client->trace(exec, Inspector::createScriptArguments(exec, 0));
189     return JSValue::encode(jsUndefined());
190 }
191
192 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncAssert(ExecState* exec)
193 {
194     VM& vm = exec->vm();
195     auto scope = DECLARE_THROW_SCOPE(vm);
196     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
197     if (!client)
198         return JSValue::encode(jsUndefined());
199
200     bool condition = exec->argument(0).toBoolean(exec);
201     RETURN_IF_EXCEPTION(scope, encodedJSValue());
202
203     if (condition)
204         return JSValue::encode(jsUndefined());
205
206     client->assertion(exec, Inspector::createScriptArguments(exec, 1));
207     return JSValue::encode(jsUndefined());
208 }
209
210 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncCount(ExecState* exec)
211 {
212     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
213     if (!client)
214         return JSValue::encode(jsUndefined());
215
216     client->count(exec, Inspector::createScriptArguments(exec, 0));
217     return JSValue::encode(jsUndefined());
218 }
219
220 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfile(ExecState* exec)
221 {
222     VM& vm = exec->vm();
223     auto scope = DECLARE_THROW_SCOPE(vm);
224     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
225     if (!client)
226         return JSValue::encode(jsUndefined());
227
228     size_t argsCount = exec->argumentCount();
229     if (!argsCount) {
230         client->profile(exec, String());
231         return JSValue::encode(jsUndefined());
232     }
233
234     const String& title(valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)));
235     RETURN_IF_EXCEPTION(scope, encodedJSValue());
236
237     client->profile(exec, title);
238     return JSValue::encode(jsUndefined());
239 }
240
241 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncProfileEnd(ExecState* exec)
242 {
243     VM& vm = exec->vm();
244     auto scope = DECLARE_THROW_SCOPE(vm);
245     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
246     if (!client)
247         return JSValue::encode(jsUndefined());
248
249     size_t argsCount = exec->argumentCount();
250     if (!argsCount) {
251         client->profileEnd(exec, String());
252         return JSValue::encode(jsUndefined());
253     }
254
255     const String& title(valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)));
256     RETURN_IF_EXCEPTION(scope, encodedJSValue());
257
258     client->profileEnd(exec, title);
259     return JSValue::encode(jsUndefined());
260 }
261
262 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTakeHeapSnapshot(ExecState* exec)
263 {
264     VM& vm = exec->vm();
265     auto scope = DECLARE_THROW_SCOPE(vm);
266     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
267     if (!client)
268         return JSValue::encode(jsUndefined());
269
270     size_t argsCount = exec->argumentCount();
271     if (!argsCount) {
272         client->takeHeapSnapshot(exec, String());
273         return JSValue::encode(jsUndefined());
274     }
275
276     const String& title(valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)));
277     RETURN_IF_EXCEPTION(scope, encodedJSValue());
278
279     client->takeHeapSnapshot(exec, title);
280     return JSValue::encode(jsUndefined());
281 }
282
283 static String valueOrDefaultLabelString(ExecState* exec, JSValue value)
284 {
285     if (value.isUndefined())
286         return ASCIILiteral("default");
287     return value.toWTFString(exec);
288 }
289
290 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTime(ExecState* exec)
291 {
292     VM& vm = exec->vm();
293     auto scope = DECLARE_THROW_SCOPE(vm);
294     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
295     if (!client)
296         return JSValue::encode(jsUndefined());
297
298     String title;
299     if (exec->argumentCount() < 1)
300         title = ASCIILiteral("default");
301     else {
302         title = valueOrDefaultLabelString(exec, exec->argument(0));
303         RETURN_IF_EXCEPTION(scope, encodedJSValue());
304     }
305
306     client->time(exec, title);
307     return JSValue::encode(jsUndefined());
308 }
309
310 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTimeEnd(ExecState* exec)
311 {
312     VM& vm = exec->vm();
313     auto scope = DECLARE_THROW_SCOPE(vm);
314     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
315     if (!client)
316         return JSValue::encode(jsUndefined());
317
318     String title;
319     if (exec->argumentCount() < 1)
320         title =  ASCIILiteral("default");
321     else {
322         title = valueOrDefaultLabelString(exec, exec->argument(0));
323         RETURN_IF_EXCEPTION(scope, encodedJSValue());
324     }
325
326     client->timeEnd(exec, title);
327     return JSValue::encode(jsUndefined());
328 }
329
330 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncTimeStamp(ExecState* exec)
331 {
332     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
333     if (!client)
334         return JSValue::encode(jsUndefined());
335
336     client->timeStamp(exec, Inspector::createScriptArguments(exec, 0));
337     return JSValue::encode(jsUndefined());
338 }
339
340 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroup(ExecState* exec)
341 {
342     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
343     if (!client)
344         return JSValue::encode(jsUndefined());
345
346     client->group(exec, Inspector::createScriptArguments(exec, 0));
347     return JSValue::encode(jsUndefined());
348 }
349
350 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroupCollapsed(ExecState* exec)
351 {
352     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
353     if (!client)
354         return JSValue::encode(jsUndefined());
355
356     client->groupCollapsed(exec, Inspector::createScriptArguments(exec, 0));
357     return JSValue::encode(jsUndefined());
358 }
359
360 static EncodedJSValue JSC_HOST_CALL consoleProtoFuncGroupEnd(ExecState* exec)
361 {
362     ConsoleClient* client = exec->lexicalGlobalObject()->consoleClient();
363     if (!client)
364         return JSValue::encode(jsUndefined());
365
366     client->groupEnd(exec, Inspector::createScriptArguments(exec, 0));
367     return JSValue::encode(jsUndefined());
368 }
369
370 } // namespace JSC