summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptGlue/UserObjectImp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptGlue/UserObjectImp.cpp')
-rw-r--r--Source/JavaScriptGlue/UserObjectImp.cpp417
1 files changed, 417 insertions, 0 deletions
diff --git a/Source/JavaScriptGlue/UserObjectImp.cpp b/Source/JavaScriptGlue/UserObjectImp.cpp
new file mode 100644
index 0000000..1728a7e
--- /dev/null
+++ b/Source/JavaScriptGlue/UserObjectImp.cpp
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2005, 2008, 2009 Apple 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 <JavaScriptCore/JSString.h>
+#include <JavaScriptCore/PropertyNameArray.h>
+
+const ClassInfo UserObjectImp::info = { "UserObject", 0, 0, 0 };
+
+UserObjectImp::UserObjectImp(PassRefPtr<Structure> structure, JSUserObject* userObject)
+ : JSObject(structure)
+ , fJSUserObject((JSUserObject*)userObject->Retain())
+{
+}
+
+UserObjectImp::~UserObjectImp()
+{
+ if (fJSUserObject)
+ fJSUserObject->Release();
+}
+
+const ClassInfo * UserObjectImp::classInfo() const
+{
+ return &info;
+}
+
+CallType UserObjectImp::getCallData(CallData& callData)
+{
+ return fJSUserObject ? fJSUserObject->getCallData(callData) : CallTypeNone;
+}
+
+JSValue UserObjectImp::callAsFunction(ExecState *exec)
+{
+ JSValue result = jsUndefined();
+ JSUserObject* jsThisObj = KJSValueToJSObject(exec->hostThisValue().toThisObject(exec), exec);
+ if (jsThisObj) {
+ CFIndex argCount = exec->argumentCount();
+ CFArrayCallBacks arrayCallBacks;
+ JSTypeGetCFArrayCallBacks(&arrayCallBacks);
+ CFMutableArrayRef jsArgs = CFArrayCreateMutable(0, 0, &arrayCallBacks);
+ if (jsArgs) {
+ for (CFIndex i = 0; i < argCount; i++) {
+ JSUserObject* jsArg = KJSValueToJSObject(exec->argument(i), exec);
+ CFArrayAppendValue(jsArgs, (void*)jsArg);
+ jsArg->Release();
+ }
+ }
+
+ JSUserObject* jsResult;
+ { // scope
+ JSGlueAPICallback apiCallback(exec);
+
+ // getCallData 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::getOwnPropertyNames(ExecState *exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ 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, exec));
+ }
+ CFRelease(cfPropertyNames);
+ }
+ }
+ JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+JSValue UserObjectImp::userObjectGetter(ExecState*, JSValue slotBase, const Identifier& propertyName)
+{
+ UserObjectImp *thisObj = static_cast<UserObjectImp *>(asObject(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.isUndefinedOrNull()) {
+ 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, PutPropertySlot&)
+{
+ 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) 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(exec, 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(exec, 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::markChildren(MarkStack& markStack)
+{
+ JSObject::markChildren(markStack);
+ if (fJSUserObject)
+ fJSUserObject->Mark();
+}