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