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