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