/* * Copyright (C) 2005, 2009 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "JSValueWrapper.h" #include "JSRun.h" #include <JavaScriptCore/JSArray.h> #include <JavaScriptCore/PropertyNameArray.h> #include <pthread.h> JSValueWrapper::JSValueWrapper(JSValue inValue) : fValue(getThreadGlobalExecState()->globalData(), inValue) { } JSValueWrapper::~JSValueWrapper() { } JSValue JSValueWrapper::GetValue() { return fValue.get(); } void JSValueWrapper::GetJSObectCallBacks(JSObjectCallBacks& callBacks) { callBacks.dispose = (JSObjectDisposeProcPtr)JSValueWrapper::JSObjectDispose; callBacks.equal = (JSObjectEqualProcPtr)0; callBacks.copyPropertyNames = (JSObjectCopyPropertyNamesProcPtr)JSValueWrapper::JSObjectCopyPropertyNames; callBacks.copyCFValue = (JSObjectCopyCFValueProcPtr)JSValueWrapper::JSObjectCopyCFValue; callBacks.copyProperty = (JSObjectCopyPropertyProcPtr)JSValueWrapper::JSObjectCopyProperty; callBacks.setProperty = (JSObjectSetPropertyProcPtr)JSValueWrapper::JSObjectSetProperty; callBacks.callFunction = (JSObjectCallFunctionProcPtr)JSValueWrapper::JSObjectCallFunction; } void JSValueWrapper::JSObjectDispose(void *data) { JSValueWrapper* ptr = (JSValueWrapper*)data; delete ptr; } CFArrayRef JSValueWrapper::JSObjectCopyPropertyNames(void *data) { JSGlueAPIEntry entry; CFMutableArrayRef result = 0; JSValueWrapper* ptr = (JSValueWrapper*)data; if (ptr) { ExecState* exec = getThreadGlobalExecState(); JSObject* object = ptr->GetValue().toObject(exec); PropertyNameArray propNames(exec); object->getPropertyNames(exec, propNames); PropertyNameArray::const_iterator iterator = propNames.begin(); while (iterator != propNames.end()) { Identifier name = *iterator; CFStringRef nameStr = IdentifierToCFString(name); if (!result) { result = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); } if (result && nameStr) { CFArrayAppendValue(result, nameStr); } ReleaseCFType(nameStr); iterator++; } } return result; } JSObjectRef JSValueWrapper::JSObjectCopyProperty(void *data, CFStringRef propertyName) { JSGlueAPIEntry entry; JSObjectRef result = 0; JSValueWrapper* ptr = (JSValueWrapper*)data; if (ptr) { ExecState* exec = getThreadGlobalExecState(); JSValue propValue = ptr->GetValue().toObject(exec)->get(exec, CFStringToIdentifier(propertyName, exec)); JSValueWrapper* wrapperValue = new JSValueWrapper(propValue); JSObjectCallBacks callBacks; GetJSObectCallBacks(callBacks); result = JSObjectCreateInternal(wrapperValue, &callBacks, JSValueWrapper::JSObjectMark, kJSUserObjectDataTypeJSValueWrapper); if (!result) { delete wrapperValue; } } return result; } void JSValueWrapper::JSObjectSetProperty(void *data, CFStringRef propertyName, JSObjectRef jsValue) { JSGlueAPIEntry entry; JSValueWrapper* ptr = (JSValueWrapper*)data; if (ptr) { ExecState* exec = getThreadGlobalExecState(); JSValue value = JSObjectKJSValue((JSUserObject*)jsValue); JSObject *objValue = ptr->GetValue().toObject(exec); PutPropertySlot slot; objValue->put(exec, CFStringToIdentifier(propertyName, exec), value, slot); } } JSObjectRef JSValueWrapper::JSObjectCallFunction(void *data, JSObjectRef thisObj, CFArrayRef args) { JSGlueAPIEntry entry; JSObjectRef result = 0; JSValueWrapper* ptr = (JSValueWrapper*)data; if (ptr) { ExecState* exec = getThreadGlobalExecState(); JSValue value = JSObjectKJSValue((JSUserObject*)thisObj); JSObject* ksjThisObj = value.toObject(exec); JSObject* objValue = ptr->GetValue().toObject(exec); MarkedArgumentBuffer listArgs; CFIndex argCount = args ? CFArrayGetCount(args) : 0; for (CFIndex i = 0; i < argCount; i++) { JSObjectRef jsArg = (JSObjectRef)CFArrayGetValueAtIndex(args, i); JSValue kgsArg = JSObjectKJSValue((JSUserObject*)jsArg); listArgs.append(kgsArg); } CallData callData; CallType callType = objValue->getCallData(callData); if (callType == CallTypeNone) return 0; JSValue resultValue = call(exec, objValue, callType, callData, ksjThisObj, listArgs); JSValueWrapper* wrapperValue = new JSValueWrapper(resultValue); JSObjectCallBacks callBacks; GetJSObectCallBacks(callBacks); result = JSObjectCreate(wrapperValue, &callBacks); if (!result) { delete wrapperValue; } } return result; } CFTypeRef JSValueWrapper::JSObjectCopyCFValue(void *data) { JSGlueAPIEntry entry; CFTypeRef result = 0; JSValueWrapper* ptr = (JSValueWrapper*)data; if (ptr) { result = KJSValueToCFType(ptr->GetValue(), getThreadGlobalExecState()); } return result; } void JSValueWrapper::JSObjectMark(void *data) { }