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
49using namespace JSC;
50
51JSValueRef 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
81JSValueRef 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
99bool 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
130void 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
147void JSReportExtraMemoryCost(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
160extern "C" JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef);
161extern "C" JS_EXPORT void JSSynchronousEdenCollectForDebugging(JSContextRef);
162
163void 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
174void 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
185void 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.
194JS_EXPORT extern const char iosInstallName43 __asm("$ld$install_name$os4.3$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
195JS_EXPORT extern const char iosInstallName50 __asm("$ld$install_name$os5.0$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
196JS_EXPORT extern const char iosInstallName51 __asm("$ld$install_name$os5.1$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
197JS_EXPORT extern const char iosInstallName60 __asm("$ld$install_name$os6.0$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
198JS_EXPORT extern const char iosInstallName61 __asm("$ld$install_name$os6.1$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore");
199
200const char iosInstallName43 = 0;
201const char iosInstallName50 = 0;
202const char iosInstallName51 = 0;
203const char iosInstallName60 = 0;
204const char iosInstallName61 = 0;
205#endif
206