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