1 /* 2 * Copyright (C) 2005, 2009 Apple Computer, 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 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "config.h" 30 #include "JSValueWrapper.h" 31 #include "JSRun.h" 32 #include <JavaScriptCore/JSArray.h> 33 #include <JavaScriptCore/PropertyNameArray.h> 34 #include <pthread.h> 35 36 JSValueWrapper::JSValueWrapper(JSValue inValue) 37 : fValue(getThreadGlobalExecState()->globalData(), inValue) 38 { 39 } 40 41 JSValueWrapper::~JSValueWrapper() 42 { 43 } 44 45 JSValue JSValueWrapper::GetValue() 46 { 47 return fValue.get(); 48 } 49 50 void JSValueWrapper::GetJSObectCallBacks(JSObjectCallBacks& callBacks) 51 { 52 callBacks.dispose = (JSObjectDisposeProcPtr)JSValueWrapper::JSObjectDispose; 53 callBacks.equal = (JSObjectEqualProcPtr)0; 54 callBacks.copyPropertyNames = (JSObjectCopyPropertyNamesProcPtr)JSValueWrapper::JSObjectCopyPropertyNames; 55 callBacks.copyCFValue = (JSObjectCopyCFValueProcPtr)JSValueWrapper::JSObjectCopyCFValue; 56 callBacks.copyProperty = (JSObjectCopyPropertyProcPtr)JSValueWrapper::JSObjectCopyProperty; 57 callBacks.setProperty = (JSObjectSetPropertyProcPtr)JSValueWrapper::JSObjectSetProperty; 58 callBacks.callFunction = (JSObjectCallFunctionProcPtr)JSValueWrapper::JSObjectCallFunction; 59 } 60 61 void JSValueWrapper::JSObjectDispose(void *data) 62 { 63 JSValueWrapper* ptr = (JSValueWrapper*)data; 64 delete ptr; 65 } 66 67 68 CFArrayRef JSValueWrapper::JSObjectCopyPropertyNames(void *data) 69 { 70 JSGlueAPIEntry entry; 71 72 CFMutableArrayRef result = 0; 73 JSValueWrapper* ptr = (JSValueWrapper*)data; 74 if (ptr) 75 { 76 ExecState* exec = getThreadGlobalExecState(); 77 JSObject* object = ptr->GetValue().toObject(exec); 78 PropertyNameArray propNames(exec); 79 object->getPropertyNames(exec, propNames); 80 PropertyNameArray::const_iterator iterator = propNames.begin(); 81 82 while (iterator != propNames.end()) { 83 Identifier name = *iterator; 84 CFStringRef nameStr = IdentifierToCFString(name); 85 86 if (!result) 87 { 88 result = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); 89 } 90 if (result && nameStr) 91 { 92 CFArrayAppendValue(result, nameStr); 93 } 94 ReleaseCFType(nameStr); 95 iterator++; 96 } 97 98 } 99 return result; 100 } 101 102 103 JSObjectRef JSValueWrapper::JSObjectCopyProperty(void *data, CFStringRef propertyName) 104 { 105 JSGlueAPIEntry entry; 106 107 JSObjectRef result = 0; 108 JSValueWrapper* ptr = (JSValueWrapper*)data; 109 if (ptr) 110 { 111 ExecState* exec = getThreadGlobalExecState(); 112 JSValue propValue = ptr->GetValue().toObject(exec)->get(exec, CFStringToIdentifier(propertyName, exec)); 113 JSValueWrapper* wrapperValue = new JSValueWrapper(propValue); 114 115 JSObjectCallBacks callBacks; 116 GetJSObectCallBacks(callBacks); 117 result = JSObjectCreateInternal(wrapperValue, &callBacks, JSValueWrapper::JSObjectMark, kJSUserObjectDataTypeJSValueWrapper); 118 119 if (!result) 120 { 121 delete wrapperValue; 122 } 123 } 124 return result; 125 } 126 127 void JSValueWrapper::JSObjectSetProperty(void *data, CFStringRef propertyName, JSObjectRef jsValue) 128 { 129 JSGlueAPIEntry entry; 130 131 JSValueWrapper* ptr = (JSValueWrapper*)data; 132 if (ptr) 133 { 134 ExecState* exec = getThreadGlobalExecState(); 135 JSValue value = JSObjectKJSValue((JSUserObject*)jsValue); 136 JSObject *objValue = ptr->GetValue().toObject(exec); 137 PutPropertySlot slot; 138 objValue->put(exec, CFStringToIdentifier(propertyName, exec), value, slot); 139 } 140 } 141 142 JSObjectRef JSValueWrapper::JSObjectCallFunction(void *data, JSObjectRef thisObj, CFArrayRef args) 143 { 144 JSGlueAPIEntry entry; 145 146 JSObjectRef result = 0; 147 JSValueWrapper* ptr = (JSValueWrapper*)data; 148 if (ptr) 149 { 150 ExecState* exec = getThreadGlobalExecState(); 151 152 JSValue value = JSObjectKJSValue((JSUserObject*)thisObj); 153 JSObject* ksjThisObj = value.toObject(exec); 154 JSObject* objValue = ptr->GetValue().toObject(exec); 155 156 MarkedArgumentBuffer listArgs; 157 CFIndex argCount = args ? CFArrayGetCount(args) : 0; 158 for (CFIndex i = 0; i < argCount; i++) 159 { 160 JSObjectRef jsArg = (JSObjectRef)CFArrayGetValueAtIndex(args, i); 161 JSValue kgsArg = JSObjectKJSValue((JSUserObject*)jsArg); 162 listArgs.append(kgsArg); 163 } 164 165 CallData callData; 166 CallType callType = objValue->getCallData(callData); 167 if (callType == CallTypeNone) 168 return 0; 169 JSValue resultValue = call(exec, objValue, callType, callData, ksjThisObj, listArgs); 170 JSValueWrapper* wrapperValue = new JSValueWrapper(resultValue); 171 JSObjectCallBacks callBacks; 172 GetJSObectCallBacks(callBacks); 173 result = JSObjectCreate(wrapperValue, &callBacks); 174 if (!result) 175 { 176 delete wrapperValue; 177 } 178 } 179 return result; 180 } 181 182 CFTypeRef JSValueWrapper::JSObjectCopyCFValue(void *data) 183 { 184 JSGlueAPIEntry entry; 185 186 CFTypeRef result = 0; 187 JSValueWrapper* ptr = (JSValueWrapper*)data; 188 if (ptr) 189 { 190 result = KJSValueToCFType(ptr->GetValue(), getThreadGlobalExecState()); 191 } 192 return result; 193 } 194 195 void JSValueWrapper::JSObjectMark(void *data) 196 { 197 } 198