Web Inspector: JSContext inspection should report exceptions in the console
[WebKit-https.git] / Source / JavaScriptCore / API / JSBase.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2013 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 COMPUTER, 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 COMPUTER, 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 "JSBase.h"
28 #include "JSBasePrivate.h"
29
30 #include "APICast.h"
31 #include "APIShims.h"
32 #include "CallFrame.h"
33 #include "Completion.h"
34 #include "InitializeThreading.h"
35 #include "JSGlobalObject.h"
36 #include "JSLock.h"
37 #include "JSObject.h"
38 #include "OpaqueJSString.h"
39 #include "JSCInlines.h"
40 #include "SourceCode.h"
41 #include <wtf/text/StringHash.h>
42
43 #if ENABLE(REMOTE_INSPECTOR)
44 #include "JSGlobalObjectInspectorController.h"
45 #endif
46
47 using namespace JSC;
48
49 JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
50 {
51     if (!ctx) {
52         ASSERT_NOT_REACHED();
53         return 0;
54     }
55     ExecState* exec = toJS(ctx);
56     APIEntryShim entryShim(exec);
57
58     JSObject* jsThisObject = toJS(thisObject);
59
60     startingLineNumber = std::max(1, startingLineNumber);
61
62     // evaluate sets "this" to the global object if it is NULL
63     JSGlobalObject* globalObject = exec->vmEntryGlobalObject();
64     SourceCode source = makeSource(script->string(), sourceURL->string(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
65
66     JSValue evaluationException;
67     JSValue returnValue = evaluate(globalObject->globalExec(), source, jsThisObject, &evaluationException);
68
69     if (evaluationException) {
70         if (exception)
71             *exception = toRef(exec, evaluationException);
72 #if ENABLE(REMOTE_INSPECTOR)
73         // FIXME: If we have a debugger attached we could learn about ParseError exceptions through
74         // ScriptDebugServer::sourceParsed and this path could produce a duplicate warning. The
75         // Debugger path is currently ignored by inspector.
76         // NOTE: If we don't have a debugger, this SourceCode will be forever lost to the inspector.
77         // We could stash it in the inspector in case an inspector is ever opened.
78         globalObject->inspectorController().reportAPIException(exec, evaluationException);
79 #endif
80         return 0;
81     }
82
83     if (returnValue)
84         return toRef(exec, returnValue);
85
86     // happens, for example, when the only statement is an empty (';') statement
87     return toRef(exec, jsUndefined());
88 }
89
90 bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
91 {
92     if (!ctx) {
93         ASSERT_NOT_REACHED();
94         return false;
95     }
96     ExecState* exec = toJS(ctx);
97     APIEntryShim entryShim(exec);
98
99     startingLineNumber = std::max(1, startingLineNumber);
100
101     SourceCode source = makeSource(script->string(), sourceURL->string(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
102     
103     JSValue syntaxException;
104     bool isValidSyntax = checkSyntax(exec->vmEntryGlobalObject()->globalExec(), source, &syntaxException);
105
106     if (!isValidSyntax) {
107         if (exception)
108             *exception = toRef(exec, syntaxException);
109 #if ENABLE(REMOTE_INSPECTOR)
110         exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, syntaxException);
111 #endif
112         return false;
113     }
114
115     return true;
116 }
117
118 void JSGarbageCollect(JSContextRef ctx)
119 {
120     // We used to recommend passing NULL as an argument here, which caused the only heap to be collected.
121     // As there is no longer a shared heap, the previously recommended usage became a no-op (but the GC
122     // will happen when the context group is destroyed).
123     // Because the function argument was originally ignored, some clients may pass their released context here,
124     // in which case there is a risk of crashing if another thread performs GC on the same heap in between.
125     if (!ctx)
126         return;
127
128     ExecState* exec = toJS(ctx);
129     APIEntryShim entryShim(exec, false);
130
131     exec->vm().heap.reportAbandonedObjectGraph();
132 }
133
134 void JSReportExtraMemoryCost(JSContextRef ctx, size_t size)
135 {
136     if (!ctx) {
137         ASSERT_NOT_REACHED();
138         return;
139     }
140     ExecState* exec = toJS(ctx);
141     APIEntryShim entryShim(exec);
142     exec->vm().heap.reportExtraMemoryCost(size);
143 }
144
145 extern "C" JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef);
146
147 void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx)
148 {
149     if (!ctx)
150         return;
151
152     ExecState* exec = toJS(ctx);
153     APIEntryShim entryShim(exec);
154     exec->vm().heap.collectAllGarbage();
155 }
156
157 void JSDisableGCTimer(void)
158 {
159     GCActivityCallback::s_shouldCreateGCTimer = false;
160 }
161
162 #if PLATFORM(IOS)
163 // FIXME: Expose symbols to tell dyld where to find JavaScriptCore on older versions of
164 // iOS (< 7.0). We should remove these symbols once we no longer need to support such
165 // versions of iOS. See <rdar://problem/13696872> for more details.
166 JS_EXPORT extern const char iosInstallName43 __asm("$ld$install_name$os4.3$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
167 JS_EXPORT extern const char iosInstallName50 __asm("$ld$install_name$os5.0$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
168 JS_EXPORT extern const char iosInstallName51 __asm("$ld$install_name$os5.1$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
169 JS_EXPORT extern const char iosInstallName60 __asm("$ld$install_name$os6.0$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
170 JS_EXPORT extern const char iosInstallName61 __asm("$ld$install_name$os6.1$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
171
172 const char iosInstallName43 = 0;
173 const char iosInstallName50 = 0;
174 const char iosInstallName51 = 0;
175 const char iosInstallName60 = 0;
176 const char iosInstallName61 = 0;
177 #endif