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 return toRef(exec, jsNumber(exec, value)); 215 } 216 217 JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) 218 { 219 ExecState* exec = toJS(ctx); 220 APIEntryShim entryShim(exec); 221 222 return toRef(exec, jsString(exec, string->ustring())); 223 } 224 225 bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) 226 { 227 ExecState* exec = toJS(ctx); 228 APIEntryShim entryShim(exec); 229 230 JSValue jsValue = toJS(exec, value); 231 return jsValue.toBoolean(exec); 232 } 233 234 double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception) 235 { 236 ExecState* exec = toJS(ctx); 237 APIEntryShim entryShim(exec); 238 239 JSValue jsValue = toJS(exec, value); 240 241 double number = jsValue.toNumber(exec); 242 if (exec->hadException()) { 243 if (exception) 244 *exception = toRef(exec, exec->exception()); 245 exec->clearException(); 246 number = NaN; 247 } 248 return number; 249 } 250 251 JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception) 252 { 253 ExecState* exec = toJS(ctx); 254 APIEntryShim entryShim(exec); 255 256 JSValue jsValue = toJS(exec, value); 257 258 RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec))); 259 if (exec->hadException()) { 260 if (exception) 261 *exception = toRef(exec, exec->exception()); 262 exec->clearException(); 263 stringRef.clear(); 264 } 265 return stringRef.release().releaseRef(); 266 } 267 268 JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) 269 { 270 ExecState* exec = toJS(ctx); 271 APIEntryShim entryShim(exec); 272 273 JSValue jsValue = toJS(exec, value); 274 275 JSObjectRef objectRef = toRef(jsValue.toObject(exec)); 276 if (exec->hadException()) { 277 if (exception) 278 *exception = toRef(exec, exec->exception()); 279 exec->clearException(); 280 objectRef = 0; 281 } 282 return objectRef; 283 } 284 285 void JSValueProtect(JSContextRef ctx, JSValueRef value) 286 { 287 ExecState* exec = toJS(ctx); 288 APIEntryShim entryShim(exec); 289 290 JSValue jsValue = toJSForGC(exec, value); 291 gcProtect(jsValue); 292 } 293 294 void JSValueUnprotect(JSContextRef ctx, JSValueRef value) 295 { 296 ExecState* exec = toJS(ctx); 297 APIEntryShim entryShim(exec); 298 299 JSValue jsValue = toJSForGC(exec, value); 300 gcUnprotect(jsValue); 301 } 302