diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/JavaScriptGlue/UserObjectImp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/osswebengine/JavaScriptGlue/UserObjectImp.cpp Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2005 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 "UserObjectImp.h" +#include + +const ClassInfo UserObjectImp::info = {"UserObject", 0, 0, 0}; + +UserObjectImp::UserObjectImp(JSUserObject* userObject) + : fJSUserObject((JSUserObject*)userObject->Retain()) +{ +} + +UserObjectImp::~UserObjectImp() +{ + if (fJSUserObject) + fJSUserObject->Release(); +} + +const ClassInfo * UserObjectImp::classInfo() const +{ + return &info; +} + +bool UserObjectImp::implementsCall() const +{ + return fJSUserObject ? fJSUserObject->ImplementsCall() : false; +} + +JSValue *UserObjectImp::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) +{ + JSValue *result = jsUndefined(); + JSUserObject* jsThisObj = KJSValueToJSObject(thisObj, exec); + if (jsThisObj) { + CFIndex argCount = args.size(); + CFArrayCallBacks arrayCallBacks; + JSTypeGetCFArrayCallBacks(&arrayCallBacks); + CFMutableArrayRef jsArgs = CFArrayCreateMutable(0, 0, &arrayCallBacks); + if (jsArgs) { + for (CFIndex i = 0; i < argCount; i++) { + JSUserObject* jsArg = KJSValueToJSObject(args[i], exec); + CFArrayAppendValue(jsArgs, (void*)jsArg); + jsArg->Release(); + } + } + + JSUserObject* jsResult; + { // scope + JSLock::DropAllLocks dropLocks; + + // implementsCall should have guarded against a NULL fJSUserObject. + assert(fJSUserObject); + jsResult = fJSUserObject->CallFunction(jsThisObj, jsArgs); + } + + if (jsResult) { + result = JSObjectKJSValue(jsResult); + jsResult->Release(); + } + + ReleaseCFType(jsArgs); + jsThisObj->Release(); + } + return result; +} + + +void UserObjectImp::getPropertyNames(ExecState *exec, PropertyNameArray& propertyNames) +{ + JSUserObject* ptr = GetJSUserObject(); + if (ptr) { + CFArrayRef cfPropertyNames = ptr->CopyPropertyNames(); + if (cfPropertyNames) { + CFIndex count = CFArrayGetCount(cfPropertyNames); + CFIndex i; + for (i = 0; i < count; i++) { + CFStringRef propertyName = (CFStringRef)CFArrayGetValueAtIndex(cfPropertyNames, i); + propertyNames.add(CFStringToIdentifier(propertyName)); + } + CFRelease(cfPropertyNames); + } + } + JSObject::getPropertyNames(exec, propertyNames); +} + +JSValue *UserObjectImp::userObjectGetter(ExecState *, JSObject *, const Identifier& propertyName, const PropertySlot& slot) +{ + UserObjectImp *thisObj = static_cast(slot.slotBase()); + // getOwnPropertySlot should have guarded against a null fJSUserObject. + assert(thisObj->fJSUserObject); + + CFStringRef cfPropName = IdentifierToCFString(propertyName); + JSUserObject *jsResult = thisObj->fJSUserObject->CopyProperty(cfPropName); + ReleaseCFType(cfPropName); + JSValue *result = JSObjectKJSValue(jsResult); + jsResult->Release(); + + return result; +} + +bool UserObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) +{ + if (!fJSUserObject) + return false; + + CFStringRef cfPropName = IdentifierToCFString(propertyName); + JSUserObject *jsResult = fJSUserObject->CopyProperty(cfPropName); + ReleaseCFType(cfPropName); + if (jsResult) { + slot.setCustom(this, userObjectGetter); + jsResult->Release(); + return true; + } else { + JSValue *kjsValue = toPrimitive(exec); + if (kjsValue->type() != NullType && kjsValue->type() != UndefinedType) { + JSObject *kjsObject = kjsValue->toObject(exec); + if (kjsObject->getPropertySlot(exec, propertyName, slot)) + return true; + } + } + return JSObject::getOwnPropertySlot(exec, propertyName, slot); +} + +void UserObjectImp::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) +{ + if (!fJSUserObject) + return; + + CFStringRef cfPropName = IdentifierToCFString(propertyName); + JSUserObject *jsValueObj = KJSValueToJSObject(value, exec); + + fJSUserObject->SetProperty(cfPropName, jsValueObj); + + if (jsValueObj) jsValueObj->Release(); + ReleaseCFType(cfPropName); +} + +JSUserObject* UserObjectImp::GetJSUserObject() const +{ + return fJSUserObject; +} + +JSValue *UserObjectImp::toPrimitive(ExecState *exec, JSType preferredType) const +{ + JSValue *result = jsUndefined(); + JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec); + CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0; + if (cfValue) { + CFTypeID cfType = CFGetTypeID(cfValue); // toPrimitive + if (cfValue == GetCFNull()) { + result = jsNull(); + } + else if (cfType == CFBooleanGetTypeID()) { + if (cfValue == kCFBooleanTrue) { + result = jsBoolean(true); + } else { + result = jsBoolean(false); + } + } else if (cfType == CFStringGetTypeID()) { + result = jsString(CFStringToUString((CFStringRef)cfValue)); + } else if (cfType == CFNumberGetTypeID()) { + double d = 0.0; + CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d); + result = jsNumber(d); + } else if (cfType == CFURLGetTypeID()) { + CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue); + if (absURL) { + result = jsString(CFStringToUString(CFURLGetString(absURL))); + ReleaseCFType(absURL); + } + } + ReleaseCFType(cfValue); + } + if (jsObjPtr) + jsObjPtr->Release(); + return result; +} + + +bool UserObjectImp::toBoolean(ExecState *exec) const +{ + bool result = false; + JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec); + CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0; + if (cfValue) + { + CFTypeID cfType = CFGetTypeID(cfValue); // toPrimitive + if (cfValue == GetCFNull()) + { + // + } + else if (cfType == CFBooleanGetTypeID()) + { + if (cfValue == kCFBooleanTrue) + { + result = true; + } + } + else if (cfType == CFStringGetTypeID()) + { + if (CFStringGetLength((CFStringRef)cfValue)) + { + result = true; + } + } + else if (cfType == CFNumberGetTypeID()) + { + if (cfValue != kCFNumberNaN) + { + double d; + if (CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d)) + { + if (d != 0) + { + result = true; + } + } + } + } + else if (cfType == CFArrayGetTypeID()) + { + if (CFArrayGetCount((CFArrayRef)cfValue)) + { + result = true; + } + } + else if (cfType == CFDictionaryGetTypeID()) + { + if (CFDictionaryGetCount((CFDictionaryRef)cfValue)) + { + result = true; + } + } + else if (cfType == CFSetGetTypeID()) + { + if (CFSetGetCount((CFSetRef)cfValue)) + { + result = true; + } + } + else if (cfType == CFURLGetTypeID()) + { + CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue); + if (absURL) + { + CFStringRef cfStr = CFURLGetString(absURL); + if (cfStr && CFStringGetLength(cfStr)) + { + result = true; + } + ReleaseCFType(absURL); + } + } + } + if (jsObjPtr) jsObjPtr->Release(); + ReleaseCFType(cfValue); + return result; +} + +double UserObjectImp::toNumber(ExecState *exec) const +{ + double result = 0; + JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec); + CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0; + if (cfValue) + { + CFTypeID cfType = CFGetTypeID(cfValue); + + if (cfValue == GetCFNull()) + { + // + } + else if (cfType == CFBooleanGetTypeID()) + { + if (cfValue == kCFBooleanTrue) + { + result = 1; + } + } + else if (cfType == CFStringGetTypeID()) + { + result = CFStringGetDoubleValue((CFStringRef)cfValue); + } + else if (cfType == CFNumberGetTypeID()) + { + CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &result); + } + } + ReleaseCFType(cfValue); + if (jsObjPtr) jsObjPtr->Release(); + return result; +} + +UString UserObjectImp::toString(ExecState *exec) const +{ + UString result; + JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec); + CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0; + if (cfValue) + { + CFTypeID cfType = CFGetTypeID(cfValue); + if (cfValue == GetCFNull()) + { + // + } + else if (cfType == CFBooleanGetTypeID()) + { + if (cfValue == kCFBooleanTrue) + { + result = "true"; + } + else + { + result = "false"; + } + } + else if (cfType == CFStringGetTypeID()) + { + result = CFStringToUString((CFStringRef)cfValue); + } + else if (cfType == CFNumberGetTypeID()) + { + if (cfValue == kCFNumberNaN) + { + result = "Nan"; + } + else if (CFNumberCompare(kCFNumberPositiveInfinity, (CFNumberRef)cfValue, 0) == 0) + { + result = "Infinity"; + } + else if (CFNumberCompare(kCFNumberNegativeInfinity, (CFNumberRef)cfValue, 0) == 0) + { + result = "-Infinity"; + } + else + { + CFStringRef cfNumStr; + double d = 0; + CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d); + if (CFNumberIsFloatType((CFNumberRef)cfValue)) + { + cfNumStr = CFStringCreateWithFormat(0, 0, CFSTR("%f"), d); + } + else + { + cfNumStr = CFStringCreateWithFormat(0, 0, CFSTR("%.0f"), d); + } + result = CFStringToUString(cfNumStr); + ReleaseCFType(cfNumStr); + } + } + else if (cfType == CFArrayGetTypeID()) + { + // + } + else if (cfType == CFDictionaryGetTypeID()) + { + // + } + else if (cfType == CFSetGetTypeID()) + { + // + } + else if (cfType == CFURLGetTypeID()) + { + CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue); + if (absURL) + { + CFStringRef cfStr = CFURLGetString(absURL); + if (cfStr) + { + result = CFStringToUString(cfStr); + } + ReleaseCFType(absURL); + } + } + } + ReleaseCFType(cfValue); + if (jsObjPtr) jsObjPtr->Release(); + return result; +} + +void UserObjectImp::mark() +{ + JSObject::mark(); + if (fJSUserObject) + fJSUserObject->Mark(); +}