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