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