1 /*
2 * Copyright (C) 2006, 2007 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 "JSValueRef.h"
28
29 #include <wtf/Platform.h>
30 #include "APICast.h"
31 #include "JSCallbackObject.h"
32
33 #include <runtime/JSGlobalObject.h>
34 #include <runtime/JSString.h>
35 #include <runtime/Operations.h>
36 #include <runtime/Protect.h>
37 #include <runtime/UString.h>
38 #include <runtime/JSValue.h>
39
40 #include <wtf/Assertions.h>
41
42 #include <algorithm> // for std::min
43
JSValueGetType(JSContextRef,JSValueRef value)44 JSType JSValueGetType(JSContextRef, JSValueRef value)
45 {
46 JSC::JSValuePtr jsValue = toJS(value);
47 if (jsValue.isUndefined())
48 return kJSTypeUndefined;
49 if (jsValue.isNull())
50 return kJSTypeNull;
51 if (jsValue.isBoolean())
52 return kJSTypeBoolean;
53 if (jsValue.isNumber())
54 return kJSTypeNumber;
55 if (jsValue.isString())
56 return kJSTypeString;
57 ASSERT(jsValue.isObject());
58 return kJSTypeObject;
59 }
60
61 using namespace JSC; // placed here to avoid conflict between JSC::JSType and JSType, above.
62
JSValueIsUndefined(JSContextRef,JSValueRef value)63 bool JSValueIsUndefined(JSContextRef, JSValueRef value)
64 {
65 JSValuePtr jsValue = toJS(value);
66 return jsValue.isUndefined();
67 }
68
JSValueIsNull(JSContextRef,JSValueRef value)69 bool JSValueIsNull(JSContextRef, JSValueRef value)
70 {
71 JSValuePtr jsValue = toJS(value);
72 return jsValue.isNull();
73 }
74
JSValueIsBoolean(JSContextRef,JSValueRef value)75 bool JSValueIsBoolean(JSContextRef, JSValueRef value)
76 {
77 JSValuePtr jsValue = toJS(value);
78 return jsValue.isBoolean();
79 }
80
JSValueIsNumber(JSContextRef,JSValueRef value)81 bool JSValueIsNumber(JSContextRef, JSValueRef value)
82 {
83 JSValuePtr jsValue = toJS(value);
84 return jsValue.isNumber();
85 }
86
JSValueIsString(JSContextRef,JSValueRef value)87 bool JSValueIsString(JSContextRef, JSValueRef value)
88 {
89 JSValuePtr jsValue = toJS(value);
90 return jsValue.isString();
91 }
92
JSValueIsObject(JSContextRef,JSValueRef value)93 bool JSValueIsObject(JSContextRef, JSValueRef value)
94 {
95 JSValuePtr jsValue = toJS(value);
96 return jsValue.isObject();
97 }
98
JSValueIsObjectOfClass(JSContextRef,JSValueRef value,JSClassRef jsClass)99 bool JSValueIsObjectOfClass(JSContextRef, JSValueRef value, JSClassRef jsClass)
100 {
101 JSValuePtr jsValue = toJS(value);
102
103 if (JSObject* o = jsValue.getObject()) {
104 if (o->inherits(&JSCallbackObject<JSGlobalObject>::info))
105 return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
106 else if (o->inherits(&JSCallbackObject<JSObject>::info))
107 return static_cast<JSCallbackObject<JSObject>*>(o)->inherits(jsClass);
108 }
109 return false;
110 }
111
JSValueIsEqual(JSContextRef ctx,JSValueRef a,JSValueRef b,JSValueRef * exception)112 bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception)
113 {
114 ExecState* exec = toJS(ctx);
115 exec->globalData().heap.registerThread();
116 JSLock lock(exec);
117
118 JSValuePtr jsA = toJS(a);
119 JSValuePtr jsB = toJS(b);
120
121 bool result = JSValuePtr::equal(exec, jsA, jsB); // false if an exception is thrown
122 if (exec->hadException()) {
123 if (exception)
124 *exception = toRef(exec->exception());
125 exec->clearException();
126 }
127 return result;
128 }
129
JSValueIsStrictEqual(JSContextRef,JSValueRef a,JSValueRef b)130 bool JSValueIsStrictEqual(JSContextRef, JSValueRef a, JSValueRef b)
131 {
132 JSValuePtr jsA = toJS(a);
133 JSValuePtr jsB = toJS(b);
134
135 bool result = JSValuePtr::strictEqual(jsA, jsB);
136 return result;
137 }
138
JSValueIsInstanceOfConstructor(JSContextRef ctx,JSValueRef value,JSObjectRef constructor,JSValueRef * exception)139 bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception)
140 {
141 ExecState* exec = toJS(ctx);
142 exec->globalData().heap.registerThread();
143 JSLock lock(exec);
144
145 JSValuePtr jsValue = toJS(value);
146 JSObject* jsConstructor = toJS(constructor);
147 if (!jsConstructor->structure()->typeInfo().implementsHasInstance())
148 return false;
149 bool result = jsConstructor->hasInstance(exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown
150 if (exec->hadException()) {
151 if (exception)
152 *exception = toRef(exec->exception());
153 exec->clearException();
154 }
155 return result;
156 }
157
JSValueMakeUndefined(JSContextRef)158 JSValueRef JSValueMakeUndefined(JSContextRef)
159 {
160 return toRef(jsUndefined());
161 }
162
JSValueMakeNull(JSContextRef)163 JSValueRef JSValueMakeNull(JSContextRef)
164 {
165 return toRef(jsNull());
166 }
167
JSValueMakeBoolean(JSContextRef,bool value)168 JSValueRef JSValueMakeBoolean(JSContextRef, bool value)
169 {
170 return toRef(jsBoolean(value));
171 }
172
JSValueMakeNumber(JSContextRef ctx,double value)173 JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
174 {
175 ExecState* exec = toJS(ctx);
176 exec->globalData().heap.registerThread();
177 JSLock lock(exec);
178
179 return toRef(jsNumber(exec, value));
180 }
181
JSValueMakeString(JSContextRef ctx,JSStringRef string)182 JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
183 {
184 ExecState* exec = toJS(ctx);
185 exec->globalData().heap.registerThread();
186 JSLock lock(exec);
187
188 return toRef(jsString(exec, string->ustring()));
189 }
190
JSValueToBoolean(JSContextRef ctx,JSValueRef value)191 bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
192 {
193 ExecState* exec = toJS(ctx);
194 JSValuePtr jsValue = toJS(value);
195 return jsValue.toBoolean(exec);
196 }
197
JSValueToNumber(JSContextRef ctx,JSValueRef value,JSValueRef * exception)198 double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
199 {
200 ExecState* exec = toJS(ctx);
201 exec->globalData().heap.registerThread();
202 JSLock lock(exec);
203
204 JSValuePtr jsValue = toJS(value);
205
206 double number = jsValue.toNumber(exec);
207 if (exec->hadException()) {
208 if (exception)
209 *exception = toRef(exec->exception());
210 exec->clearException();
211 number = NaN;
212 }
213 return number;
214 }
215
JSValueToStringCopy(JSContextRef ctx,JSValueRef value,JSValueRef * exception)216 JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
217 {
218 ExecState* exec = toJS(ctx);
219 exec->globalData().heap.registerThread();
220 JSLock lock(exec);
221
222 JSValuePtr jsValue = toJS(value);
223
224 RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)));
225 if (exec->hadException()) {
226 if (exception)
227 *exception = toRef(exec->exception());
228 exec->clearException();
229 stringRef.clear();
230 }
231 return stringRef.release().releaseRef();
232 }
233
JSValueToObject(JSContextRef ctx,JSValueRef value,JSValueRef * exception)234 JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
235 {
236 ExecState* exec = toJS(ctx);
237 exec->globalData().heap.registerThread();
238 JSLock lock(exec);
239
240 JSValuePtr jsValue = toJS(value);
241
242 JSObjectRef objectRef = toRef(jsValue.toObject(exec));
243 if (exec->hadException()) {
244 if (exception)
245 *exception = toRef(exec->exception());
246 exec->clearException();
247 objectRef = 0;
248 }
249 return objectRef;
250 }
251
JSValueProtect(JSContextRef ctx,JSValueRef value)252 void JSValueProtect(JSContextRef ctx, JSValueRef value)
253 {
254 ExecState* exec = toJS(ctx);
255 exec->globalData().heap.registerThread();
256 JSLock lock(exec);
257
258 JSValuePtr jsValue = toJS(value);
259 gcProtect(jsValue);
260 }
261
JSValueUnprotect(JSContextRef ctx,JSValueRef value)262 void JSValueUnprotect(JSContextRef ctx, JSValueRef value)
263 {
264 ExecState* exec = toJS(ctx);
265 exec->globalData().heap.registerThread();
266 JSLock lock(exec);
267
268 JSValuePtr jsValue = toJS(value);
269 gcUnprotect(jsValue);
270 }
271