]> git.saurik.com Git - apple/javascriptcore.git/blame - API/JSValueRef.cpp
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / API / JSValueRef.cpp
CommitLineData
b37bf2e1
A
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 *
81345200 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
b37bf2e1
A
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
81345200 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
b37bf2e1
A
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
81345200 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
b37bf2e1
A
24 */
25
26#include "config.h"
27#include "JSValueRef.h"
28
b37bf2e1 29#include "APICast.h"
93a37866 30#include "JSAPIWrapperObject.h"
81345200 31#include "JSCJSValue.h"
b37bf2e1 32#include "JSCallbackObject.h"
81345200
A
33#include "JSGlobalObject.h"
34#include "JSONObject.h"
35#include "JSString.h"
36#include "LiteralParser.h"
37#include "JSCInlines.h"
38#include "Protect.h"
b37bf2e1
A
39
40#include <wtf/Assertions.h>
4e4e5a6f 41#include <wtf/text/StringHash.h>
93a37866 42#include <wtf/text/WTFString.h>
b37bf2e1
A
43
44#include <algorithm> // for std::min
45
93a37866
A
46#if PLATFORM(MAC)
47#include <mach-o/dyld.h>
48#endif
49
81345200
A
50#if ENABLE(REMOTE_INSPECTOR)
51#include "JSGlobalObjectInspectorController.h"
52#endif
53
f9bf01c6
A
54using namespace JSC;
55
93a37866
A
56#if PLATFORM(MAC)
57static bool evernoteHackNeeded()
58{
59 static const int32_t webkitLastVersionWithEvernoteHack = 35133959;
60 static bool hackNeeded = CFEqual(CFBundleGetIdentifier(CFBundleGetMainBundle()), CFSTR("com.evernote.Evernote"))
61 && NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitLastVersionWithEvernoteHack;
62
63 return hackNeeded;
64}
65#endif
66
f9bf01c6 67::JSType JSValueGetType(JSContextRef ctx, JSValueRef value)
b37bf2e1 68{
93a37866
A
69 if (!ctx) {
70 ASSERT_NOT_REACHED();
71 return kJSTypeUndefined;
72 }
f9bf01c6 73 ExecState* exec = toJS(ctx);
81345200 74 JSLockHolder locker(exec);
ba379fdc 75
f9bf01c6 76 JSValue jsValue = toJS(exec, value);
ba379fdc 77
9dae56ea
A
78 if (jsValue.isUndefined())
79 return kJSTypeUndefined;
80 if (jsValue.isNull())
81 return kJSTypeNull;
82 if (jsValue.isBoolean())
83 return kJSTypeBoolean;
84 if (jsValue.isNumber())
85 return kJSTypeNumber;
86 if (jsValue.isString())
87 return kJSTypeString;
88 ASSERT(jsValue.isObject());
89 return kJSTypeObject;
b37bf2e1
A
90}
91
ba379fdc 92bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value)
b37bf2e1 93{
93a37866
A
94 if (!ctx) {
95 ASSERT_NOT_REACHED();
96 return false;
97 }
ba379fdc 98 ExecState* exec = toJS(ctx);
81345200 99 JSLockHolder locker(exec);
ba379fdc
A
100
101 JSValue jsValue = toJS(exec, value);
9dae56ea 102 return jsValue.isUndefined();
b37bf2e1
A
103}
104
ba379fdc 105bool JSValueIsNull(JSContextRef ctx, JSValueRef value)
b37bf2e1 106{
93a37866
A
107 if (!ctx) {
108 ASSERT_NOT_REACHED();
109 return false;
110 }
ba379fdc 111 ExecState* exec = toJS(ctx);
81345200 112 JSLockHolder locker(exec);
ba379fdc
A
113
114 JSValue jsValue = toJS(exec, value);
9dae56ea 115 return jsValue.isNull();
b37bf2e1
A
116}
117
ba379fdc 118bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value)
b37bf2e1 119{
93a37866
A
120 if (!ctx) {
121 ASSERT_NOT_REACHED();
122 return false;
123 }
ba379fdc 124 ExecState* exec = toJS(ctx);
81345200 125 JSLockHolder locker(exec);
ba379fdc
A
126
127 JSValue jsValue = toJS(exec, value);
9dae56ea 128 return jsValue.isBoolean();
b37bf2e1
A
129}
130
ba379fdc 131bool JSValueIsNumber(JSContextRef ctx, JSValueRef value)
b37bf2e1 132{
93a37866
A
133 if (!ctx) {
134 ASSERT_NOT_REACHED();
135 return false;
136 }
ba379fdc 137 ExecState* exec = toJS(ctx);
81345200 138 JSLockHolder locker(exec);
ba379fdc
A
139
140 JSValue jsValue = toJS(exec, value);
9dae56ea 141 return jsValue.isNumber();
b37bf2e1
A
142}
143
ba379fdc 144bool JSValueIsString(JSContextRef ctx, JSValueRef value)
b37bf2e1 145{
93a37866
A
146 if (!ctx) {
147 ASSERT_NOT_REACHED();
148 return false;
149 }
ba379fdc 150 ExecState* exec = toJS(ctx);
81345200 151 JSLockHolder locker(exec);
ba379fdc
A
152
153 JSValue jsValue = toJS(exec, value);
9dae56ea 154 return jsValue.isString();
b37bf2e1
A
155}
156
ba379fdc 157bool JSValueIsObject(JSContextRef ctx, JSValueRef value)
b37bf2e1 158{
93a37866
A
159 if (!ctx) {
160 ASSERT_NOT_REACHED();
161 return false;
162 }
ba379fdc 163 ExecState* exec = toJS(ctx);
81345200 164 JSLockHolder locker(exec);
ba379fdc
A
165
166 JSValue jsValue = toJS(exec, value);
9dae56ea 167 return jsValue.isObject();
b37bf2e1
A
168}
169
ba379fdc 170bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass)
b37bf2e1 171{
93a37866
A
172 if (!ctx || !jsClass) {
173 ASSERT_NOT_REACHED();
174 return false;
175 }
ba379fdc 176 ExecState* exec = toJS(ctx);
81345200 177 JSLockHolder locker(exec);
ba379fdc
A
178
179 JSValue jsValue = toJS(exec, value);
b37bf2e1 180
9dae56ea 181 if (JSObject* o = jsValue.getObject()) {
81345200
A
182 if (o->inherits(JSProxy::info()))
183 o = jsCast<JSProxy*>(o)->target();
184
185 if (o->inherits(JSCallbackObject<JSGlobalObject>::info()))
6fe7ccc8 186 return jsCast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
81345200 187 if (o->inherits(JSCallbackObject<JSDestructibleObject>::info()))
93a37866
A
188 return jsCast<JSCallbackObject<JSDestructibleObject>*>(o)->inherits(jsClass);
189#if JSC_OBJC_API_ENABLED
81345200 190 if (o->inherits(JSCallbackObject<JSAPIWrapperObject>::info()))
93a37866
A
191 return jsCast<JSCallbackObject<JSAPIWrapperObject>*>(o)->inherits(jsClass);
192#endif
b37bf2e1
A
193 }
194 return false;
195}
196
197bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception)
198{
93a37866
A
199 if (!ctx) {
200 ASSERT_NOT_REACHED();
201 return false;
202 }
b37bf2e1 203 ExecState* exec = toJS(ctx);
81345200 204 JSLockHolder locker(exec);
9dae56ea 205
ba379fdc
A
206 JSValue jsA = toJS(exec, a);
207 JSValue jsB = toJS(exec, b);
b37bf2e1 208
ba379fdc 209 bool result = JSValue::equal(exec, jsA, jsB); // false if an exception is thrown
b37bf2e1 210 if (exec->hadException()) {
81345200 211 JSValue exceptionValue = exec->exception();
b37bf2e1 212 if (exception)
81345200 213 *exception = toRef(exec, exceptionValue);
b37bf2e1 214 exec->clearException();
81345200
A
215#if ENABLE(REMOTE_INSPECTOR)
216 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
217#endif
b37bf2e1
A
218 }
219 return result;
220}
221
ba379fdc 222bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b)
b37bf2e1 223{
93a37866
A
224 if (!ctx) {
225 ASSERT_NOT_REACHED();
226 return false;
227 }
ba379fdc 228 ExecState* exec = toJS(ctx);
81345200 229 JSLockHolder locker(exec);
ba379fdc
A
230
231 JSValue jsA = toJS(exec, a);
232 JSValue jsB = toJS(exec, b);
233
f9bf01c6 234 return JSValue::strictEqual(exec, jsA, jsB);
b37bf2e1
A
235}
236
237bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception)
238{
93a37866
A
239 if (!ctx) {
240 ASSERT_NOT_REACHED();
241 return false;
242 }
b37bf2e1 243 ExecState* exec = toJS(ctx);
81345200 244 JSLockHolder locker(exec);
9dae56ea 245
ba379fdc
A
246 JSValue jsValue = toJS(exec, value);
247
b37bf2e1 248 JSObject* jsConstructor = toJS(constructor);
9dae56ea 249 if (!jsConstructor->structure()->typeInfo().implementsHasInstance())
b37bf2e1 250 return false;
93a37866 251 bool result = jsConstructor->hasInstance(exec, jsValue); // false if an exception is thrown
b37bf2e1 252 if (exec->hadException()) {
81345200 253 JSValue exceptionValue = exec->exception();
b37bf2e1 254 if (exception)
81345200 255 *exception = toRef(exec, exceptionValue);
b37bf2e1 256 exec->clearException();
81345200
A
257#if ENABLE(REMOTE_INSPECTOR)
258 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
259#endif
b37bf2e1
A
260 }
261 return result;
262}
263
ba379fdc 264JSValueRef JSValueMakeUndefined(JSContextRef ctx)
b37bf2e1 265{
93a37866
A
266 if (!ctx) {
267 ASSERT_NOT_REACHED();
268 return 0;
269 }
ba379fdc 270 ExecState* exec = toJS(ctx);
81345200 271 JSLockHolder locker(exec);
ba379fdc
A
272
273 return toRef(exec, jsUndefined());
b37bf2e1
A
274}
275
ba379fdc 276JSValueRef JSValueMakeNull(JSContextRef ctx)
b37bf2e1 277{
93a37866
A
278 if (!ctx) {
279 ASSERT_NOT_REACHED();
280 return 0;
281 }
ba379fdc 282 ExecState* exec = toJS(ctx);
81345200 283 JSLockHolder locker(exec);
ba379fdc
A
284
285 return toRef(exec, jsNull());
b37bf2e1
A
286}
287
ba379fdc 288JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value)
b37bf2e1 289{
93a37866
A
290 if (!ctx) {
291 ASSERT_NOT_REACHED();
292 return 0;
293 }
ba379fdc 294 ExecState* exec = toJS(ctx);
81345200 295 JSLockHolder locker(exec);
ba379fdc
A
296
297 return toRef(exec, jsBoolean(value));
b37bf2e1
A
298}
299
9dae56ea 300JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
b37bf2e1 301{
93a37866
A
302 if (!ctx) {
303 ASSERT_NOT_REACHED();
304 return 0;
305 }
9dae56ea 306 ExecState* exec = toJS(ctx);
81345200 307 JSLockHolder locker(exec);
9dae56ea 308
81345200 309 return toRef(exec, jsNumber(purifyNaN(value)));
b37bf2e1
A
310}
311
9dae56ea 312JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
b37bf2e1 313{
93a37866
A
314 if (!ctx) {
315 ASSERT_NOT_REACHED();
316 return 0;
317 }
9dae56ea 318 ExecState* exec = toJS(ctx);
81345200 319 JSLockHolder locker(exec);
9dae56ea 320
93a37866 321 return toRef(exec, jsString(exec, string->string()));
b37bf2e1
A
322}
323
4e4e5a6f
A
324JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string)
325{
93a37866
A
326 if (!ctx) {
327 ASSERT_NOT_REACHED();
328 return 0;
329 }
4e4e5a6f 330 ExecState* exec = toJS(ctx);
81345200 331 JSLockHolder locker(exec);
93a37866
A
332 String str = string->string();
333 unsigned length = str.length();
81345200 334 if (!length || str.is8Bit()) {
93a37866 335 LiteralParser<LChar> parser(exec, str.characters8(), length, StrictJSON);
6fe7ccc8
A
336 return toRef(exec, parser.tryLiteralParse());
337 }
81345200 338 LiteralParser<UChar> parser(exec, str.characters16(), length, StrictJSON);
4e4e5a6f
A
339 return toRef(exec, parser.tryLiteralParse());
340}
341
342JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef apiValue, unsigned indent, JSValueRef* exception)
343{
93a37866
A
344 if (!ctx) {
345 ASSERT_NOT_REACHED();
346 return 0;
347 }
4e4e5a6f 348 ExecState* exec = toJS(ctx);
81345200 349 JSLockHolder locker(exec);
4e4e5a6f 350 JSValue value = toJS(exec, apiValue);
93a37866 351 String result = JSONStringify(exec, value, indent);
4e4e5a6f
A
352 if (exception)
353 *exception = 0;
354 if (exec->hadException()) {
81345200 355 JSValue exceptionValue = exec->exception();
4e4e5a6f 356 if (exception)
81345200 357 *exception = toRef(exec, exceptionValue);
4e4e5a6f 358 exec->clearException();
81345200
A
359#if ENABLE(REMOTE_INSPECTOR)
360 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
361#endif
4e4e5a6f
A
362 return 0;
363 }
14957cd0 364 return OpaqueJSString::create(result).leakRef();
4e4e5a6f
A
365}
366
b37bf2e1
A
367bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
368{
93a37866
A
369 if (!ctx) {
370 ASSERT_NOT_REACHED();
371 return false;
372 }
b37bf2e1 373 ExecState* exec = toJS(ctx);
81345200 374 JSLockHolder locker(exec);
ba379fdc
A
375
376 JSValue jsValue = toJS(exec, value);
9dae56ea 377 return jsValue.toBoolean(exec);
b37bf2e1
A
378}
379
380double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
381{
93a37866
A
382 if (!ctx) {
383 ASSERT_NOT_REACHED();
81345200 384 return PNaN;
93a37866 385 }
b37bf2e1 386 ExecState* exec = toJS(ctx);
81345200 387 JSLockHolder locker(exec);
b37bf2e1 388
ba379fdc 389 JSValue jsValue = toJS(exec, value);
9dae56ea
A
390
391 double number = jsValue.toNumber(exec);
b37bf2e1 392 if (exec->hadException()) {
81345200 393 JSValue exceptionValue = exec->exception();
b37bf2e1 394 if (exception)
81345200 395 *exception = toRef(exec, exceptionValue);
b37bf2e1 396 exec->clearException();
81345200
A
397#if ENABLE(REMOTE_INSPECTOR)
398 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
399#endif
400 number = PNaN;
b37bf2e1
A
401 }
402 return number;
403}
404
405JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
406{
93a37866
A
407 if (!ctx) {
408 ASSERT_NOT_REACHED();
409 return 0;
410 }
b37bf2e1 411 ExecState* exec = toJS(ctx);
81345200 412 JSLockHolder locker(exec);
9dae56ea 413
ba379fdc 414 JSValue jsValue = toJS(exec, value);
b37bf2e1 415
6fe7ccc8 416 RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)->value(exec)));
b37bf2e1 417 if (exec->hadException()) {
81345200 418 JSValue exceptionValue = exec->exception();
b37bf2e1 419 if (exception)
81345200 420 *exception = toRef(exec, exceptionValue);
b37bf2e1 421 exec->clearException();
81345200
A
422#if ENABLE(REMOTE_INSPECTOR)
423 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
424#endif
9dae56ea 425 stringRef.clear();
b37bf2e1 426 }
14957cd0 427 return stringRef.release().leakRef();
b37bf2e1
A
428}
429
430JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
431{
93a37866
A
432 if (!ctx) {
433 ASSERT_NOT_REACHED();
434 return 0;
435 }
b37bf2e1 436 ExecState* exec = toJS(ctx);
81345200 437 JSLockHolder locker(exec);
9dae56ea 438
ba379fdc 439 JSValue jsValue = toJS(exec, value);
b37bf2e1 440
9dae56ea 441 JSObjectRef objectRef = toRef(jsValue.toObject(exec));
b37bf2e1 442 if (exec->hadException()) {
81345200 443 JSValue exceptionValue = exec->exception();
b37bf2e1 444 if (exception)
81345200 445 *exception = toRef(exec, exceptionValue);
b37bf2e1 446 exec->clearException();
81345200
A
447#if ENABLE(REMOTE_INSPECTOR)
448 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
449#endif
b37bf2e1
A
450 objectRef = 0;
451 }
452 return objectRef;
81345200 453}
b37bf2e1 454
9dae56ea 455void JSValueProtect(JSContextRef ctx, JSValueRef value)
b37bf2e1 456{
93a37866
A
457 if (!ctx) {
458 ASSERT_NOT_REACHED();
459 return;
460 }
9dae56ea 461 ExecState* exec = toJS(ctx);
81345200 462 JSLockHolder locker(exec);
9dae56ea 463
f9bf01c6 464 JSValue jsValue = toJSForGC(exec, value);
b37bf2e1
A
465 gcProtect(jsValue);
466}
467
9dae56ea 468void JSValueUnprotect(JSContextRef ctx, JSValueRef value)
b37bf2e1 469{
93a37866
A
470#if PLATFORM(MAC)
471 if ((!value || !ctx) && evernoteHackNeeded())
472 return;
473#endif
474
9dae56ea 475 ExecState* exec = toJS(ctx);
81345200 476 JSLockHolder locker(exec);
9dae56ea 477
f9bf01c6 478 JSValue jsValue = toJSForGC(exec, value);
b37bf2e1
A
479 gcUnprotect(jsValue);
480}