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 "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>::s_info))
    133             return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
    134         if (o->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_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     // Our JSValue representation relies on a standard bit pattern for NaN. NaNs
    217     // generated internally to JavaScriptCore naturally have that representation,
    218     // but an external NaN might not.
    219     if (isnan(value))
    220         value = NaN;
    221 
    222     return toRef(exec, jsNumber(value));
    223 }
    224 
    225 JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
    226 {
    227     ExecState* exec = toJS(ctx);
    228     APIEntryShim entryShim(exec);
    229 
    230     return toRef(exec, jsString(exec, string->ustring()));
    231 }
    232 
    233 JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string)
    234 {
    235     ExecState* exec = toJS(ctx);
    236     APIEntryShim entryShim(exec);
    237     LiteralParser parser(exec, string->ustring(), LiteralParser::StrictJSON);
    238     return toRef(exec, parser.tryLiteralParse());
    239 }
    240 
    241 JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef apiValue, unsigned indent, JSValueRef* exception)
    242 {
    243     ExecState* exec = toJS(ctx);
    244     APIEntryShim entryShim(exec);
    245     JSValue value = toJS(exec, apiValue);
    246     UString result = JSONStringify(exec, value, indent);
    247     if (exception)
    248         *exception = 0;
    249     if (exec->hadException()) {
    250         if (exception)
    251             *exception = toRef(exec, exec->exception());
    252         exec->clearException();
    253         return 0;
    254     }
    255     return OpaqueJSString::create(result).leakRef();
    256 }
    257 
    258 bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
    259 {
    260     ExecState* exec = toJS(ctx);
    261     APIEntryShim entryShim(exec);
    262 
    263     JSValue jsValue = toJS(exec, value);
    264     return jsValue.toBoolean(exec);
    265 }
    266 
    267 double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
    268 {
    269     ExecState* exec = toJS(ctx);
    270     APIEntryShim entryShim(exec);
    271 
    272     JSValue jsValue = toJS(exec, value);
    273 
    274     double number = jsValue.toNumber(exec);
    275     if (exec->hadException()) {
    276         if (exception)
    277             *exception = toRef(exec, exec->exception());
    278         exec->clearException();
    279         number = NaN;
    280     }
    281     return number;
    282 }
    283 
    284 JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
    285 {
    286     ExecState* exec = toJS(ctx);
    287     APIEntryShim entryShim(exec);
    288 
    289     JSValue jsValue = toJS(exec, value);
    290 
    291     RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)));
    292     if (exec->hadException()) {
    293         if (exception)
    294             *exception = toRef(exec, exec->exception());
    295         exec->clearException();
    296         stringRef.clear();
    297     }
    298     return stringRef.release().leakRef();
    299 }
    300 
    301 JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
    302 {
    303     ExecState* exec = toJS(ctx);
    304     APIEntryShim entryShim(exec);
    305 
    306     JSValue jsValue = toJS(exec, value);
    307 
    308     JSObjectRef objectRef = toRef(jsValue.toObject(exec));
    309     if (exec->hadException()) {
    310         if (exception)
    311             *exception = toRef(exec, exec->exception());
    312         exec->clearException();
    313         objectRef = 0;
    314     }
    315     return objectRef;
    316 }
    317 
    318 void JSValueProtect(JSContextRef ctx, JSValueRef value)
    319 {
    320     ExecState* exec = toJS(ctx);
    321     APIEntryShim entryShim(exec);
    322 
    323     JSValue jsValue = toJSForGC(exec, value);
    324     gcProtect(jsValue);
    325 }
    326 
    327 void JSValueUnprotect(JSContextRef ctx, JSValueRef value)
    328 {
    329     ExecState* exec = toJS(ctx);
    330     APIEntryShim entryShim(exec);
    331 
    332     JSValue jsValue = toJSForGC(exec, value);
    333     gcUnprotect(jsValue);
    334 }
    335