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