summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/bridge/objc
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/bridge/objc
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/bridge/objc')
-rw-r--r--Source/WebCore/bridge/objc/ObjCRuntimeObject.h52
-rw-r--r--Source/WebCore/bridge/objc/ObjCRuntimeObject.mm52
-rw-r--r--Source/WebCore/bridge/objc/WebScriptObject.h44
-rw-r--r--Source/WebCore/bridge/objc/objc_class.h59
-rw-r--r--Source/WebCore/bridge/objc/objc_class.mm253
-rw-r--r--Source/WebCore/bridge/objc/objc_header.h53
-rw-r--r--Source/WebCore/bridge/objc/objc_instance.h86
-rw-r--r--Source/WebCore/bridge/objc/objc_instance.mm465
-rw-r--r--Source/WebCore/bridge/objc/objc_runtime.h131
-rw-r--r--Source/WebCore/bridge/objc/objc_runtime.mm280
-rw-r--r--Source/WebCore/bridge/objc/objc_utility.h88
-rw-r--r--Source/WebCore/bridge/objc/objc_utility.mm373
12 files changed, 1936 insertions, 0 deletions
diff --git a/Source/WebCore/bridge/objc/ObjCRuntimeObject.h b/Source/WebCore/bridge/objc/ObjCRuntimeObject.h
new file mode 100644
index 0000000..78550b9
--- /dev/null
+++ b/Source/WebCore/bridge/objc/ObjCRuntimeObject.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef ObjCRuntimeObject_h
+#define ObjCRuntimeObject_h
+
+#include "runtime_object.h"
+
+namespace JSC {
+namespace Bindings {
+
+class ObjcInstance;
+
+class ObjCRuntimeObject : public RuntimeObject {
+public:
+ ObjCRuntimeObject(ExecState*, JSGlobalObject*, PassRefPtr<ObjcInstance>);
+ virtual ~ObjCRuntimeObject();
+
+ ObjcInstance* getInternalObjCInstance() const;
+
+ static const ClassInfo s_info;
+
+private:
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+};
+
+}
+}
+
+#endif
diff --git a/Source/WebCore/bridge/objc/ObjCRuntimeObject.mm b/Source/WebCore/bridge/objc/ObjCRuntimeObject.mm
new file mode 100644
index 0000000..d9afdf2
--- /dev/null
+++ b/Source/WebCore/bridge/objc/ObjCRuntimeObject.mm
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#import "config.h"
+
+#import "ObjCRuntimeObject.h"
+#import "objc_instance.h"
+
+namespace JSC {
+namespace Bindings {
+
+const ClassInfo ObjCRuntimeObject::s_info = { "ObjCRuntimeObject", &RuntimeObject::s_info, 0, 0 };
+
+ObjCRuntimeObject::ObjCRuntimeObject(ExecState* exec, JSGlobalObject* globalObject, PassRefPtr<ObjcInstance> instance)
+ : RuntimeObject(exec, globalObject, instance)
+{
+}
+
+ObjCRuntimeObject::~ObjCRuntimeObject()
+{
+}
+
+ObjcInstance* ObjCRuntimeObject::getInternalObjCInstance() const
+{
+ return static_cast<ObjcInstance*>(getInternalInstance());
+}
+
+
+}
+}
diff --git a/Source/WebCore/bridge/objc/WebScriptObject.h b/Source/WebCore/bridge/objc/WebScriptObject.h
new file mode 100644
index 0000000..6d9ff2c
--- /dev/null
+++ b/Source/WebCore/bridge/objc/WebScriptObject.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2006 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import "runtime_root.h"
+
+@class WebUndefined;
+
+@protocol WebScriptObject
++ (NSString *)webScriptNameForSelector:(SEL)aSelector;
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
++ (NSString *)webScriptNameForKey:(const char *)name;
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
+
++ (id)_convertValueToObjcValue:(JSC::JSValue)value originRootObject:(JSC::Bindings::RootObject*)originRootObject rootObject:(JSC::Bindings::RootObject*)rootObject;
+- _initWithJSObject:(JSC::JSObject*)imp originRootObject:(PassRefPtr<JSC::Bindings::RootObject>)originRootObject rootObject:(PassRefPtr<JSC::Bindings::RootObject>)rootObject;
+- (JSC::JSObject *)_imp;
+@end
+
+@protocol WebUndefined
++ (WebUndefined *)undefined;
+@end
diff --git a/Source/WebCore/bridge/objc/objc_class.h b/Source/WebCore/bridge/objc/objc_class.h
new file mode 100644
index 0000000..eebfd2a
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_class.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2003 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef KJS_BINDINGS_OBJC_CLASS_H
+#define KJS_BINDINGS_OBJC_CLASS_H
+
+#include "objc_runtime.h"
+
+namespace JSC {
+namespace Bindings {
+
+class ObjcClass : public Class
+{
+protected:
+ ObjcClass (ClassStructPtr aClass); // Use classForIsA to create an ObjcClass.
+
+public:
+ // Return the cached ObjC of the specified name.
+ static ObjcClass *classForIsA(ClassStructPtr);
+
+ virtual MethodList methodsNamed(const Identifier&, Instance *instance) const;
+ virtual Field *fieldNamed(const Identifier&, Instance *instance) const;
+
+ virtual JSValue fallbackObject(ExecState *exec, Instance *instance, const Identifier &propertyName);
+
+ ClassStructPtr isa() { return _isa; }
+
+private:
+ ClassStructPtr _isa;
+ RetainPtr<CFMutableDictionaryRef> _methods;
+ RetainPtr<CFMutableDictionaryRef> _fields;
+};
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif
diff --git a/Source/WebCore/bridge/objc/objc_class.mm b/Source/WebCore/bridge/objc/objc_class.mm
new file mode 100644
index 0000000..2d29499
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_class.mm
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "objc_class.h"
+
+#include "objc_instance.h"
+#include "WebScriptObject.h"
+
+namespace JSC {
+namespace Bindings {
+
+static void deleteMethod(CFAllocatorRef, const void* value)
+{
+ delete static_cast<const Method*>(value);
+}
+
+static void deleteField(CFAllocatorRef, const void* value)
+{
+ delete static_cast<const Field*>(value);
+}
+
+const CFDictionaryValueCallBacks MethodDictionaryValueCallBacks = { 0, 0, &deleteMethod, 0 , 0 };
+const CFDictionaryValueCallBacks FieldDictionaryValueCallBacks = { 0, 0, &deleteField, 0 , 0 };
+
+ObjcClass::ObjcClass(ClassStructPtr aClass)
+ : _isa(aClass)
+ , _methods(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &MethodDictionaryValueCallBacks))
+ , _fields(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &FieldDictionaryValueCallBacks))
+{
+}
+
+static CFMutableDictionaryRef classesByIsA = 0;
+
+static void _createClassesByIsAIfNecessary()
+{
+ if (!classesByIsA)
+ classesByIsA = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+}
+
+ObjcClass* ObjcClass::classForIsA(ClassStructPtr isa)
+{
+ _createClassesByIsAIfNecessary();
+
+ ObjcClass* aClass = (ObjcClass*)CFDictionaryGetValue(classesByIsA, isa);
+ if (!aClass) {
+ aClass = new ObjcClass(isa);
+ CFDictionaryAddValue(classesByIsA, isa, aClass);
+ }
+
+ return aClass;
+}
+
+MethodList ObjcClass::methodsNamed(const Identifier& identifier, Instance*) const
+{
+ MethodList methodList;
+ char fixedSizeBuffer[1024];
+ char* buffer = fixedSizeBuffer;
+ CString jsName = identifier.ascii();
+ if (!convertJSMethodNameToObjc(jsName.data(), buffer, sizeof(fixedSizeBuffer))) {
+ int length = jsName.length() + 1;
+ buffer = new char[length];
+ if (!buffer || !convertJSMethodNameToObjc(jsName.data(), buffer, length))
+ return methodList;
+ }
+
+
+ RetainPtr<CFStringRef> methodName(AdoptCF, CFStringCreateWithCString(NULL, buffer, kCFStringEncodingASCII));
+ Method* method = (Method*)CFDictionaryGetValue(_methods.get(), methodName.get());
+ if (method) {
+ methodList.append(method);
+ return methodList;
+ }
+
+ ClassStructPtr thisClass = _isa;
+ while (thisClass && methodList.isEmpty()) {
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ unsigned numMethodsInClass = 0;
+ MethodStructPtr* objcMethodList = class_copyMethodList(thisClass, &numMethodsInClass);
+#else
+ void* iterator = 0;
+ struct objc_method_list* objcMethodList;
+ while ((objcMethodList = class_nextMethodList(thisClass, &iterator))) {
+ unsigned numMethodsInClass = objcMethodList->method_count;
+#endif
+ for (unsigned i = 0; i < numMethodsInClass; i++) {
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ MethodStructPtr objcMethod = objcMethodList[i];
+ SEL objcMethodSelector = method_getName(objcMethod);
+#else
+ struct objc_method* objcMethod = &objcMethodList->method_list[i];
+ SEL objcMethodSelector = objcMethod->method_name;
+#endif
+ const char* objcMethodSelectorName = sel_getName(objcMethodSelector);
+ NSString* mappedName = nil;
+
+ // See if the class wants to exclude the selector from visibility in JavaScript.
+ if ([thisClass respondsToSelector:@selector(isSelectorExcludedFromWebScript:)])
+ if ([thisClass isSelectorExcludedFromWebScript:objcMethodSelector])
+ continue;
+
+ // See if the class want to provide a different name for the selector in JavaScript.
+ // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
+ // of the class.
+ if ([thisClass respondsToSelector:@selector(webScriptNameForSelector:)])
+ mappedName = [thisClass webScriptNameForSelector:objcMethodSelector];
+
+ if ((mappedName && [mappedName isEqual:(NSString*)methodName.get()]) || strcmp(objcMethodSelectorName, buffer) == 0) {
+ Method* aMethod = new ObjcMethod(thisClass, objcMethodSelector); // deleted when the dictionary is destroyed
+ CFDictionaryAddValue(_methods.get(), methodName.get(), aMethod);
+ methodList.append(aMethod);
+ break;
+ }
+ }
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ thisClass = class_getSuperclass(thisClass);
+ free(objcMethodList);
+#else
+ }
+ thisClass = thisClass->super_class;
+#endif
+ }
+
+ if (buffer != fixedSizeBuffer)
+ delete [] buffer;
+
+ return methodList;
+}
+
+Field* ObjcClass::fieldNamed(const Identifier& identifier, Instance* instance) const
+{
+ ClassStructPtr thisClass = _isa;
+
+ CString jsName = identifier.ascii();
+ RetainPtr<CFStringRef> fieldName(AdoptCF, CFStringCreateWithCString(NULL, jsName.data(), kCFStringEncodingASCII));
+ Field* aField = (Field*)CFDictionaryGetValue(_fields.get(), fieldName.get());
+ if (aField)
+ return aField;
+
+ id targetObject = (static_cast<ObjcInstance*>(instance))->getObject();
+ id attributes = [targetObject attributeKeys];
+ if (attributes) {
+ // Class overrides attributeKeys, use that array of key names.
+ unsigned count = [attributes count];
+ for (unsigned i = 0; i < count; i++) {
+ NSString* keyName = [attributes objectAtIndex:i];
+ const char* UTF8KeyName = [keyName UTF8String]; // ObjC actually only supports ASCII names.
+
+ // See if the class wants to exclude the selector from visibility in JavaScript.
+ if ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])
+ if ([thisClass isKeyExcludedFromWebScript:UTF8KeyName])
+ continue;
+
+ // See if the class want to provide a different name for the selector in JavaScript.
+ // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
+ // of the class.
+ NSString* mappedName = nil;
+ if ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])
+ mappedName = [thisClass webScriptNameForKey:UTF8KeyName];
+
+ if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || [keyName isEqual:(NSString*)fieldName.get()]) {
+ aField = new ObjcField((CFStringRef)keyName); // deleted when the dictionary is destroyed
+ CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);
+ break;
+ }
+ }
+ } else {
+ // Class doesn't override attributeKeys, so fall back on class runtime
+ // introspection.
+
+ while (thisClass) {
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ unsigned numFieldsInClass = 0;
+ IvarStructPtr* ivarsInClass = class_copyIvarList(thisClass, &numFieldsInClass);
+#else
+ struct objc_ivar_list* fieldsInClass = thisClass->ivars;
+ if (fieldsInClass) {
+ unsigned numFieldsInClass = fieldsInClass->ivar_count;
+#endif
+ for (unsigned i = 0; i < numFieldsInClass; i++) {
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ IvarStructPtr objcIVar = ivarsInClass[i];
+ const char* objcIvarName = ivar_getName(objcIVar);
+#else
+ IvarStructPtr objcIVar = &fieldsInClass->ivar_list[i];
+ const char* objcIvarName = objcIVar->ivar_name;
+#endif
+ NSString* mappedName = 0;
+
+ // See if the class wants to exclude the selector from visibility in JavaScript.
+ if ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])
+ if ([thisClass isKeyExcludedFromWebScript:objcIvarName])
+ continue;
+
+ // See if the class want to provide a different name for the selector in JavaScript.
+ // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
+ // of the class.
+ if ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])
+ mappedName = [thisClass webScriptNameForKey:objcIvarName];
+
+ if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || strcmp(objcIvarName, jsName.data()) == 0) {
+ aField = new ObjcField(objcIVar); // deleted when the dictionary is destroyed
+ CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);
+ break;
+ }
+ }
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ thisClass = class_getSuperclass(thisClass);
+ free(ivarsInClass);
+#else
+ }
+ thisClass = thisClass->super_class;
+#endif
+ }
+ }
+
+ return aField;
+}
+
+JSValue ObjcClass::fallbackObject(ExecState* exec, Instance* instance, const Identifier &propertyName)
+{
+ ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);
+ id targetObject = objcInstance->getObject();
+
+ if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return jsUndefined();
+ return new (exec) ObjcFallbackObjectImp(exec, exec->lexicalGlobalObject(), objcInstance, propertyName);
+}
+
+}
+}
diff --git a/Source/WebCore/bridge/objc/objc_header.h b/Source/WebCore/bridge/objc/objc_header.h
new file mode 100644
index 0000000..07954a1
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_header.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef KJS_BINDINGS_OBJC_HEADER_H
+#define KJS_BINDINGS_OBJC_HEADER_H
+
+#ifdef __OBJC__
+
+#include <objc/objc.h>
+#include <objc/objc-class.h>
+#include <objc/objc-runtime.h>
+
+typedef Class ClassStructPtr;
+typedef id ObjectStructPtr;
+typedef Method MethodStructPtr;
+typedef Ivar IvarStructPtr;
+
+@class NSMethodSignature;
+
+#else
+
+typedef struct objc_class* ClassStructPtr;
+typedef struct objc_object* ObjectStructPtr;
+typedef struct objc_method* MethodStructPtr;
+typedef struct objc_ivar* IvarStructPtr;
+
+class NSMethodSignature;
+
+#endif
+
+#endif
diff --git a/Source/WebCore/bridge/objc/objc_instance.h b/Source/WebCore/bridge/objc/objc_instance.h
new file mode 100644
index 0000000..ae6972a
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_instance.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2003, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef BINDINGS_OBJC_INSTANCE_H_
+#define BINDINGS_OBJC_INSTANCE_H_
+
+#include "objc_class.h"
+#include "objc_utility.h"
+
+namespace JSC {
+
+namespace Bindings {
+
+class ObjcClass;
+
+class ObjcInstance : public Instance {
+public:
+ static PassRefPtr<ObjcInstance> create(ObjectStructPtr, PassRefPtr<RootObject>);
+ virtual ~ObjcInstance();
+
+ static void setGlobalException(NSString*, JSGlobalObject* exceptionEnvironment = 0); // A null exceptionEnvironment means the exception should propogate to any execution environment.
+
+ virtual Class* getClass() const;
+
+ virtual JSValue valueOf(ExecState*) const;
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual JSValue getMethod(ExecState* exec, const Identifier& propertyName);
+ JSValue invokeObjcMethod(ExecState*, ObjcMethod* method);
+ virtual JSValue invokeMethod(ExecState*, RuntimeMethod* method);
+ virtual bool supportsInvokeDefaultMethod() const;
+ virtual JSValue invokeDefaultMethod(ExecState*);
+
+ JSValue getValueOfUndefinedField(ExecState*, const Identifier&) const;
+ virtual bool setValueOfUndefinedField(ExecState*, const Identifier&, JSValue);
+
+ ObjectStructPtr getObject() const { return _instance.get(); }
+
+ JSValue stringValue(ExecState*) const;
+ JSValue numberValue(ExecState*) const;
+ JSValue booleanValue() const;
+
+protected:
+ virtual void virtualBegin();
+ virtual void virtualEnd();
+
+private:
+ static void moveGlobalExceptionToExecState(ExecState*);
+
+ ObjcInstance(ObjectStructPtr, PassRefPtr<RootObject>);
+
+ virtual RuntimeObject* newRuntimeObject(ExecState*);
+
+ RetainPtr<ObjectStructPtr> _instance;
+ mutable ObjcClass *_class;
+ ObjectStructPtr _pool;
+ int _beginCount;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // BINDINGS_OBJC_INSTANCE_H_
diff --git a/Source/WebCore/bridge/objc/objc_instance.mm b/Source/WebCore/bridge/objc/objc_instance.mm
new file mode 100644
index 0000000..ae9d95d
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_instance.mm
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2004, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#import "config.h"
+#import "objc_instance.h"
+
+#import "runtime_method.h"
+#import "ObjCRuntimeObject.h"
+#import "WebScriptObject.h"
+#import <objc/objc-auto.h>
+#import <runtime/Error.h>
+#import <runtime/JSLock.h>
+#import <wtf/Assertions.h>
+
+#ifdef NDEBUG
+#define OBJC_LOG(formatAndArgs...) ((void)0)
+#else
+#define OBJC_LOG(formatAndArgs...) { \
+ fprintf (stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
+ fprintf(stderr, formatAndArgs); \
+}
+#endif
+
+using namespace JSC::Bindings;
+using namespace JSC;
+
+static NSString *s_exception;
+static JSGlobalObject* s_exceptionEnvironment; // No need to protect this value, since we just use it for a pointer comparison.
+static NSMapTable *s_instanceWrapperCache;
+
+static NSMapTable *createInstanceWrapperCache()
+{
+#ifdef BUILDING_ON_TIGER
+ return NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0);
+#else
+ // NSMapTable with zeroing weak pointers is the recommended way to build caches like this under garbage collection.
+ NSPointerFunctionsOptions keyOptions = NSPointerFunctionsZeroingWeakMemory | NSPointerFunctionsOpaquePersonality;
+ NSPointerFunctionsOptions valueOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality;
+ return [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0];
+#endif
+}
+
+RuntimeObject* ObjcInstance::newRuntimeObject(ExecState* exec)
+{
+ return new (exec) ObjCRuntimeObject(exec, exec->lexicalGlobalObject(), this);
+}
+
+void ObjcInstance::setGlobalException(NSString* exception, JSGlobalObject* exceptionEnvironment)
+{
+ NSString *oldException = s_exception;
+ s_exception = [exception copy];
+ [oldException release];
+
+ s_exceptionEnvironment = exceptionEnvironment;
+}
+
+void ObjcInstance::moveGlobalExceptionToExecState(ExecState* exec)
+{
+ if (!s_exception) {
+ ASSERT(!s_exceptionEnvironment);
+ return;
+ }
+
+ if (!s_exceptionEnvironment || s_exceptionEnvironment == exec->dynamicGlobalObject()) {
+ JSLock lock(SilenceAssertionsOnly);
+ throwError(exec, s_exception);
+ }
+
+ [s_exception release];
+ s_exception = nil;
+ s_exceptionEnvironment = 0;
+}
+
+ObjcInstance::ObjcInstance(id instance, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+ , _instance(instance)
+ , _class(0)
+ , _pool(0)
+ , _beginCount(0)
+{
+}
+
+PassRefPtr<ObjcInstance> ObjcInstance::create(id instance, PassRefPtr<RootObject> rootObject)
+{
+ if (!s_instanceWrapperCache)
+ s_instanceWrapperCache = createInstanceWrapperCache();
+ if (void* existingWrapper = NSMapGet(s_instanceWrapperCache, instance))
+ return static_cast<ObjcInstance*>(existingWrapper);
+ RefPtr<ObjcInstance> wrapper = adoptRef(new ObjcInstance(instance, rootObject));
+ NSMapInsert(s_instanceWrapperCache, instance, wrapper.get());
+ return wrapper.release();
+}
+
+ObjcInstance::~ObjcInstance()
+{
+ // Both -finalizeForWebScript and -dealloc/-finalize of _instance may require autorelease pools.
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ ASSERT(s_instanceWrapperCache);
+ ASSERT(_instance);
+ NSMapRemove(s_instanceWrapperCache, _instance.get());
+
+ if ([_instance.get() respondsToSelector:@selector(finalizeForWebScript)])
+ [_instance.get() performSelector:@selector(finalizeForWebScript)];
+ _instance = 0;
+
+ [pool drain];
+}
+
+static NSAutoreleasePool* allocateAutoReleasePool()
+{
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ // If GC is enabled an autorelease pool is unnecessary, and the
+ // pool cannot be protected from GC so may be collected leading
+ // to a crash when we try to drain the release pool.
+ if (objc_collectingEnabled())
+ return nil;
+#endif
+ return [[NSAutoreleasePool alloc] init];
+}
+
+void ObjcInstance::virtualBegin()
+{
+ if (!_pool)
+ _pool = allocateAutoReleasePool();
+ _beginCount++;
+}
+
+void ObjcInstance::virtualEnd()
+{
+ _beginCount--;
+ ASSERT(_beginCount >= 0);
+ if (!_beginCount) {
+ [_pool drain];
+ _pool = 0;
+ }
+}
+
+Bindings::Class* ObjcInstance::getClass() const
+{
+ if (!_instance)
+ return 0;
+ if (!_class)
+ _class = ObjcClass::classForIsA(_instance->isa);
+ return static_cast<Bindings::Class*>(_class);
+}
+
+bool ObjcInstance::supportsInvokeDefaultMethod() const
+{
+ return [_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)];
+}
+
+class ObjCRuntimeMethod : public RuntimeMethod {
+public:
+ ObjCRuntimeMethod(ExecState* exec, JSGlobalObject* globalObject, const Identifier& name, Bindings::MethodList& list)
+ : RuntimeMethod(exec, globalObject, name, list)
+ {
+ }
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ static const ClassInfo s_info;
+};
+
+const ClassInfo ObjCRuntimeMethod::s_info = { "ObjCRuntimeMethod", &RuntimeMethod::s_info, 0, 0 };
+
+JSValue ObjcInstance::getMethod(ExecState* exec, const Identifier& propertyName)
+{
+ MethodList methodList = getClass()->methodsNamed(propertyName, this);
+ return new (exec) ObjCRuntimeMethod(exec, exec->lexicalGlobalObject(), propertyName, methodList);
+}
+
+JSValue ObjcInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
+{
+ if (!asObject(runtimeMethod)->inherits(&ObjCRuntimeMethod::s_info))
+ return throwError(exec, createTypeError(exec, "Attempt to invoke non-plug-in method on plug-in object."));
+
+ const MethodList& methodList = *runtimeMethod->methods();
+
+ // Overloading methods is not allowed in ObjectiveC. Should only be one
+ // name match for a particular method.
+ ASSERT(methodList.size() == 1);
+
+ return invokeObjcMethod(exec, static_cast<ObjcMethod*>(methodList[0]));
+}
+
+JSValue ObjcInstance::invokeObjcMethod(ExecState* exec, ObjcMethod* method)
+{
+ JSValue result = jsUndefined();
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ setGlobalException(nil);
+
+@try {
+ NSMethodSignature* signature = method->getMethodSignature();
+ NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
+ [invocation setSelector:method->selector()];
+ [invocation setTarget:_instance.get()];
+
+ if (method->isFallbackMethod()) {
+ if (objcValueTypeForType([signature methodReturnType]) != ObjcObjectType) {
+ NSLog(@"Incorrect signature for invokeUndefinedMethodFromWebScript:withArguments: -- return type must be object.");
+ return result;
+ }
+
+ // Invoke invokeUndefinedMethodFromWebScript:withArguments:, pass JavaScript function
+ // name as first (actually at 2) argument and array of args as second.
+ NSString* jsName = (NSString* )method->javaScriptName();
+ [invocation setArgument:&jsName atIndex:2];
+
+ NSMutableArray* objcArgs = [NSMutableArray array];
+ int count = exec->argumentCount();
+ for (int i = 0; i < count; i++) {
+ ObjcValue value = convertValueToObjcValue(exec, exec->argument(i), ObjcObjectType);
+ [objcArgs addObject:value.objectValue];
+ }
+ [invocation setArgument:&objcArgs atIndex:3];
+ } else {
+ unsigned count = [signature numberOfArguments];
+ for (unsigned i = 2; i < count ; i++) {
+ const char* type = [signature getArgumentTypeAtIndex:i];
+ ObjcValueType objcValueType = objcValueTypeForType(type);
+
+ // Must have a valid argument type. This method signature should have
+ // been filtered already to ensure that it has acceptable argument
+ // types.
+ ASSERT(objcValueType != ObjcInvalidType && objcValueType != ObjcVoidType);
+
+ ObjcValue value = convertValueToObjcValue(exec, exec->argument(i-2), objcValueType);
+
+ switch (objcValueType) {
+ case ObjcObjectType:
+ [invocation setArgument:&value.objectValue atIndex:i];
+ break;
+ case ObjcCharType:
+ case ObjcUnsignedCharType:
+ [invocation setArgument:&value.charValue atIndex:i];
+ break;
+ case ObjcShortType:
+ case ObjcUnsignedShortType:
+ [invocation setArgument:&value.shortValue atIndex:i];
+ break;
+ case ObjcIntType:
+ case ObjcUnsignedIntType:
+ [invocation setArgument:&value.intValue atIndex:i];
+ break;
+ case ObjcLongType:
+ case ObjcUnsignedLongType:
+ [invocation setArgument:&value.longValue atIndex:i];
+ break;
+ case ObjcLongLongType:
+ case ObjcUnsignedLongLongType:
+ [invocation setArgument:&value.longLongValue atIndex:i];
+ break;
+ case ObjcFloatType:
+ [invocation setArgument:&value.floatValue atIndex:i];
+ break;
+ case ObjcDoubleType:
+ [invocation setArgument:&value.doubleValue atIndex:i];
+ break;
+ default:
+ // Should never get here. Argument types are filtered (and
+ // the assert above should have fired in the impossible case
+ // of an invalid type anyway).
+ fprintf(stderr, "%s: invalid type (%d)\n", __PRETTY_FUNCTION__, (int)objcValueType);
+ ASSERT(false);
+ }
+ }
+ }
+
+ [invocation invoke];
+
+ // Get the return value type.
+ const char* type = [signature methodReturnType];
+ ObjcValueType objcValueType = objcValueTypeForType(type);
+
+ // Must have a valid return type. This method signature should have
+ // been filtered already to ensure that it have an acceptable return
+ // type.
+ ASSERT(objcValueType != ObjcInvalidType);
+
+ // Get the return value and convert it to a JavaScript value. Length
+ // of return value will never exceed the size of largest scalar
+ // or a pointer.
+ char buffer[1024];
+ ASSERT([signature methodReturnLength] < 1024);
+
+ if (*type != 'v') {
+ [invocation getReturnValue:buffer];
+ result = convertObjcValueToValue(exec, buffer, objcValueType, m_rootObject.get());
+ }
+} @catch(NSException* localException) {
+}
+ moveGlobalExceptionToExecState(exec);
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue&>(result);
+}
+
+JSValue ObjcInstance::invokeDefaultMethod(ExecState* exec)
+{
+ JSValue result = jsUndefined();
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+ setGlobalException(nil);
+
+@try {
+ if (![_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)])
+ return result;
+
+ NSMethodSignature* signature = [_instance.get() methodSignatureForSelector:@selector(invokeDefaultMethodWithArguments:)];
+ NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
+ [invocation setSelector:@selector(invokeDefaultMethodWithArguments:)];
+ [invocation setTarget:_instance.get()];
+
+ if (objcValueTypeForType([signature methodReturnType]) != ObjcObjectType) {
+ NSLog(@"Incorrect signature for invokeDefaultMethodWithArguments: -- return type must be object.");
+ return result;
+ }
+
+ NSMutableArray* objcArgs = [NSMutableArray array];
+ unsigned count = exec->argumentCount();
+ for (unsigned i = 0; i < count; i++) {
+ ObjcValue value = convertValueToObjcValue(exec, exec->argument(i), ObjcObjectType);
+ [objcArgs addObject:value.objectValue];
+ }
+ [invocation setArgument:&objcArgs atIndex:2];
+
+ [invocation invoke];
+
+ // Get the return value type, should always be "@" because of
+ // check above.
+ const char* type = [signature methodReturnType];
+ ObjcValueType objcValueType = objcValueTypeForType(type);
+
+ // Get the return value and convert it to a JavaScript value. Length
+ // of return value will never exceed the size of a pointer, so we're
+ // OK with 32 here.
+ char buffer[32];
+ [invocation getReturnValue:buffer];
+ result = convertObjcValueToValue(exec, buffer, objcValueType, m_rootObject.get());
+} @catch(NSException* localException) {
+}
+ moveGlobalExceptionToExecState(exec);
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue&>(result);
+}
+
+bool ObjcInstance::setValueOfUndefinedField(ExecState* exec, const Identifier& property, JSValue aValue)
+{
+ id targetObject = getObject();
+ if (![targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)])
+ return false;
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ // This check is not really necessary because NSObject implements
+ // setValue:forUndefinedKey:, and unfortunately the default implementation
+ // throws an exception.
+ if ([targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)]){
+ setGlobalException(nil);
+
+ ObjcValue objcValue = convertValueToObjcValue(exec, aValue, ObjcObjectType);
+
+ @try {
+ [targetObject setValue:objcValue.objectValue forUndefinedKey:[NSString stringWithCString:property.ascii().data() encoding:NSASCIIStringEncoding]];
+ } @catch(NSException* localException) {
+ // Do nothing. Class did not override valueForUndefinedKey:.
+ }
+
+ moveGlobalExceptionToExecState(exec);
+ }
+
+ return true;
+}
+
+JSValue ObjcInstance::getValueOfUndefinedField(ExecState* exec, const Identifier& property) const
+{
+ JSValue result = jsUndefined();
+
+ id targetObject = getObject();
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ // This check is not really necessary because NSObject implements
+ // valueForUndefinedKey:, and unfortunately the default implementation
+ // throws an exception.
+ if ([targetObject respondsToSelector:@selector(valueForUndefinedKey:)]){
+ setGlobalException(nil);
+
+ @try {
+ id objcValue = [targetObject valueForUndefinedKey:[NSString stringWithCString:property.ascii().data() encoding:NSASCIIStringEncoding]];
+ result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, m_rootObject.get());
+ } @catch(NSException* localException) {
+ // Do nothing. Class did not override valueForUndefinedKey:.
+ }
+
+ moveGlobalExceptionToExecState(exec);
+ }
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue&>(result);
+}
+
+JSValue ObjcInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ if ([_instance.get() isKindOfClass:[NSString class]])
+ return stringValue(exec);
+ if ([_instance.get() isKindOfClass:[NSNumber class]])
+ return numberValue(exec);
+ return valueOf(exec);
+}
+
+JSValue ObjcInstance::stringValue(ExecState* exec) const
+{
+ return convertNSStringToString(exec, [getObject() description]);
+}
+
+JSValue ObjcInstance::numberValue(ExecState*) const
+{
+ // FIXME: Implement something sensible
+ return jsNumber(0);
+}
+
+JSValue ObjcInstance::booleanValue() const
+{
+ // FIXME: Implement something sensible
+ return jsBoolean(false);
+}
+
+JSValue ObjcInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
diff --git a/Source/WebCore/bridge/objc/objc_runtime.h b/Source/WebCore/bridge/objc/objc_runtime.h
new file mode 100644
index 0000000..60fbdac
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_runtime.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2004, 2008 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef KJS_BINDINGS_OBJC_RUNTIME_H
+#define KJS_BINDINGS_OBJC_RUNTIME_H
+
+#include "Bridge.h"
+#include "objc_header.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSObjectWithGlobalObject.h>
+#include <wtf/RetainPtr.h>
+
+namespace JSC {
+namespace Bindings {
+
+ClassStructPtr webScriptObjectClass();
+ClassStructPtr webUndefinedClass();
+
+class ObjcInstance;
+
+class ObjcField : public Field {
+public:
+ ObjcField(IvarStructPtr);
+ ObjcField(CFStringRef name);
+
+ virtual JSValue valueFromInstance(ExecState*, const Instance*) const;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const;
+
+private:
+ IvarStructPtr _ivar;
+ RetainPtr<CFStringRef> _name;
+};
+
+class ObjcMethod : public Method {
+public:
+ ObjcMethod() : _objcClass(0), _selector(0), _javaScriptName(0) {}
+ ObjcMethod(ClassStructPtr aClass, SEL _selector);
+
+ virtual int numParameters() const;
+
+ NSMethodSignature *getMethodSignature() const;
+
+ bool isFallbackMethod() const { return _selector == @selector(invokeUndefinedMethodFromWebScript:withArguments:); }
+ void setJavaScriptName(CFStringRef n) { _javaScriptName = n; }
+ CFStringRef javaScriptName() const { return _javaScriptName.get(); }
+
+ SEL selector() const { return _selector; }
+
+private:
+ ClassStructPtr _objcClass;
+ SEL _selector;
+ RetainPtr<CFStringRef> _javaScriptName;
+};
+
+class ObjcArray : public Array {
+public:
+ ObjcArray(ObjectStructPtr, PassRefPtr<RootObject>);
+
+ virtual void setValueAt(ExecState *exec, unsigned int index, JSValue aValue) const;
+ virtual JSValue valueAt(ExecState *exec, unsigned int index) const;
+ virtual unsigned int getLength() const;
+
+ ObjectStructPtr getObjcArray() const { return _array.get(); }
+
+ static JSValue convertObjcArrayToArray(ExecState *exec, ObjectStructPtr anObject);
+
+private:
+ RetainPtr<ObjectStructPtr> _array;
+};
+
+class ObjcFallbackObjectImp : public JSObjectWithGlobalObject {
+public:
+ ObjcFallbackObjectImp(ExecState*, JSGlobalObject*, ObjcInstance*, const Identifier& propertyName);
+
+ static const ClassInfo s_info;
+
+ const Identifier& propertyName() const { return _item; }
+
+ static ObjectPrototype* createPrototype(ExecState*, JSGlobalObject* globalObject)
+ {
+ return globalObject->objectPrototype();
+ }
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+ }
+
+private:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual CallType getCallData(CallData&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual bool toBoolean(ExecState*) const;
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ RefPtr<ObjcInstance> _instance;
+ Identifier _item;
+};
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif
diff --git a/Source/WebCore/bridge/objc/objc_runtime.mm b/Source/WebCore/bridge/objc/objc_runtime.mm
new file mode 100644
index 0000000..3c4ba23
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_runtime.mm
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2004, 2008 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "objc_runtime.h"
+
+#include "JSDOMBinding.h"
+#include "ObjCRuntimeObject.h"
+#include "WebScriptObject.h"
+#include "objc_instance.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include <runtime/Error.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <runtime/ObjectPrototype.h>
+#include <wtf/RetainPtr.h>
+
+using namespace WebCore;
+
+namespace JSC {
+namespace Bindings {
+
+ClassStructPtr webScriptObjectClass()
+{
+ static ClassStructPtr<WebScriptObject> webScriptObjectClass = NSClassFromString(@"WebScriptObject");
+ return webScriptObjectClass;
+}
+
+ClassStructPtr webUndefinedClass()
+{
+ static ClassStructPtr<WebUndefined> webUndefinedClass = NSClassFromString(@"WebUndefined");
+ return webUndefinedClass;
+}
+
+// ---------------------- ObjcMethod ----------------------
+
+ObjcMethod::ObjcMethod(ClassStructPtr aClass, SEL selector)
+ : _objcClass(aClass)
+ , _selector(selector)
+{
+}
+
+int ObjcMethod::numParameters() const
+{
+ return [getMethodSignature() numberOfArguments] - 2;
+}
+
+NSMethodSignature* ObjcMethod::getMethodSignature() const
+{
+ return [_objcClass instanceMethodSignatureForSelector:_selector];
+}
+
+// ---------------------- ObjcField ----------------------
+
+ObjcField::ObjcField(Ivar ivar)
+ : _ivar(ivar)
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ , _name(AdoptCF, CFStringCreateWithCString(0, ivar_getName(_ivar), kCFStringEncodingASCII))
+#else
+ , _name(AdoptCF, CFStringCreateWithCString(0, _ivar->ivar_name, kCFStringEncodingASCII))
+#endif
+{
+}
+
+ObjcField::ObjcField(CFStringRef name)
+ : _ivar(0)
+ , _name(name)
+{
+}
+
+JSValue ObjcField::valueFromInstance(ExecState* exec, const Instance* instance) const
+{
+ JSValue result = jsUndefined();
+
+ id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ @try {
+ if (id objcValue = [targetObject valueForKey:(NSString *)_name.get()])
+ result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, instance->rootObject());
+ } @catch(NSException* localException) {
+ JSLock::lock(SilenceAssertionsOnly);
+ throwError(exec, [localException reason]);
+ JSLock::unlock(SilenceAssertionsOnly);
+ }
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue&>(result);
+}
+
+static id convertValueToObjcObject(ExecState* exec, JSValue value)
+{
+ RefPtr<RootObject> rootObject = findRootObject(exec->dynamicGlobalObject());
+ if (!rootObject)
+ return nil;
+ return [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:rootObject.get() rootObject:rootObject.get()];
+}
+
+void ObjcField::setValueToInstance(ExecState* exec, const Instance* instance, JSValue aValue) const
+{
+ id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();
+ id value = convertValueToObjcObject(exec, aValue);
+
+ JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ @try {
+ [targetObject setValue:value forKey:(NSString *)_name.get()];
+ } @catch(NSException* localException) {
+ JSLock::lock(SilenceAssertionsOnly);
+ throwError(exec, [localException reason]);
+ JSLock::unlock(SilenceAssertionsOnly);
+ }
+}
+
+// ---------------------- ObjcArray ----------------------
+
+ObjcArray::ObjcArray(ObjectStructPtr a, PassRefPtr<RootObject> rootObject)
+ : Array(rootObject)
+ , _array(a)
+{
+}
+
+void ObjcArray::setValueAt(ExecState* exec, unsigned int index, JSValue aValue) const
+{
+ if (![_array.get() respondsToSelector:@selector(insertObject:atIndex:)]) {
+ throwError(exec, createTypeError(exec, "Array is not mutable."));
+ return;
+ }
+
+ if (index > [_array.get() count]) {
+ throwError(exec, createRangeError(exec, "Index exceeds array size."));
+ return;
+ }
+
+ // Always try to convert the value to an ObjC object, so it can be placed in the
+ // array.
+ ObjcValue oValue = convertValueToObjcValue (exec, aValue, ObjcObjectType);
+
+ @try {
+ [_array.get() insertObject:oValue.objectValue atIndex:index];
+ } @catch(NSException* localException) {
+ throwError(exec, createError(exec, "Objective-C exception."));
+ }
+}
+
+JSValue ObjcArray::valueAt(ExecState* exec, unsigned int index) const
+{
+ if (index > [_array.get() count])
+ return throwError(exec, createRangeError(exec, "Index exceeds array size."));
+ @try {
+ id obj = [_array.get() objectAtIndex:index];
+ if (obj)
+ return convertObjcValueToValue (exec, &obj, ObjcObjectType, m_rootObject.get());
+ } @catch(NSException* localException) {
+ return throwError(exec, createError(exec, "Objective-C exception."));
+ }
+ return jsUndefined();
+}
+
+unsigned int ObjcArray::getLength() const
+{
+ return [_array.get() count];
+}
+
+const ClassInfo ObjcFallbackObjectImp::s_info = { "ObjcFallbackObject", 0, 0, 0 };
+
+ObjcFallbackObjectImp::ObjcFallbackObjectImp(ExecState* exec, JSGlobalObject* globalObject, ObjcInstance* i, const Identifier& propertyName)
+ // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
+ : JSObjectWithGlobalObject(globalObject, deprecatedGetDOMStructure<ObjcFallbackObjectImp>(exec))
+ , _instance(i)
+ , _item(propertyName)
+{
+}
+
+bool ObjcFallbackObjectImp::getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot& slot)
+{
+ // keep the prototype from getting called instead of just returning false
+ slot.setUndefined();
+ return true;
+}
+
+bool ObjcFallbackObjectImp::getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor& descriptor)
+{
+ // keep the prototype from getting called instead of just returning false
+ descriptor.setUndefined();
+ return true;
+}
+
+void ObjcFallbackObjectImp::put(ExecState*, const Identifier&, JSValue, PutPropertySlot&)
+{
+}
+
+static EncodedJSValue JSC_HOST_CALL callObjCFallbackObject(ExecState* exec)
+{
+ JSValue thisValue = exec->hostThisValue();
+ if (!thisValue.inherits(&ObjCRuntimeObject::s_info))
+ return throwVMTypeError(exec);
+
+ JSValue result = jsUndefined();
+
+ ObjCRuntimeObject* runtimeObject = static_cast<ObjCRuntimeObject*>(asObject(thisValue));
+ ObjcInstance* objcInstance = runtimeObject->getInternalObjCInstance();
+
+ if (!objcInstance)
+ return JSValue::encode(RuntimeObject::throwInvalidAccessError(exec));
+
+ objcInstance->begin();
+
+ id targetObject = objcInstance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)]){
+ ObjcClass* objcClass = static_cast<ObjcClass*>(objcInstance->getClass());
+ OwnPtr<ObjcMethod> fallbackMethod(new ObjcMethod(objcClass->isa(), @selector(invokeUndefinedMethodFromWebScript:withArguments:)));
+ const Identifier& nameIdentifier = static_cast<ObjcFallbackObjectImp*>(exec->callee())->propertyName();
+ RetainPtr<CFStringRef> name(AdoptCF, CFStringCreateWithCharacters(0, nameIdentifier.characters(), nameIdentifier.length()));
+ fallbackMethod->setJavaScriptName(name.get());
+ result = objcInstance->invokeObjcMethod(exec, fallbackMethod.get());
+ }
+
+ objcInstance->end();
+
+ return JSValue::encode(result);
+}
+
+CallType ObjcFallbackObjectImp::getCallData(CallData& callData)
+{
+ id targetObject = _instance->getObject();
+ if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return CallTypeNone;
+ callData.native.function = callObjCFallbackObject;
+ return CallTypeHost;
+}
+
+bool ObjcFallbackObjectImp::deleteProperty(ExecState*, const Identifier&)
+{
+ return false;
+}
+
+JSValue ObjcFallbackObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType) const
+{
+ return _instance->getValueOfUndefinedField(exec, _item);
+}
+
+bool ObjcFallbackObjectImp::toBoolean(ExecState *) const
+{
+ id targetObject = _instance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return true;
+
+ return false;
+}
+
+}
+}
diff --git a/Source/WebCore/bridge/objc/objc_utility.h b/Source/WebCore/bridge/objc/objc_utility.h
new file mode 100644
index 0000000..4810752
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_utility.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef KJS_BINDINGS_OBJC_UTILITY_H
+#define KJS_BINDINGS_OBJC_UTILITY_H
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "objc_header.h"
+#include <runtime/Error.h>
+#include <runtime/JSObject.h>
+
+#ifdef __OBJC__
+@class NSString;
+#else
+class NSString;
+#endif
+
+namespace JSC {
+namespace Bindings {
+
+typedef union {
+ ObjectStructPtr objectValue;
+ bool booleanValue;
+ char charValue;
+ short shortValue;
+ int intValue;
+ long longValue;
+ long long longLongValue;
+ float floatValue;
+ double doubleValue;
+} ObjcValue;
+
+typedef enum {
+ ObjcVoidType,
+ ObjcObjectType,
+ ObjcCharType,
+ ObjcUnsignedCharType,
+ ObjcShortType,
+ ObjcUnsignedShortType,
+ ObjcIntType,
+ ObjcUnsignedIntType,
+ ObjcLongType,
+ ObjcUnsignedLongType,
+ ObjcLongLongType,
+ ObjcUnsignedLongLongType,
+ ObjcFloatType,
+ ObjcDoubleType,
+ ObjcInvalidType
+} ObjcValueType;
+
+class RootObject;
+
+ObjcValue convertValueToObjcValue(ExecState*, JSValue, ObjcValueType);
+JSValue convertNSStringToString(ExecState* exec, NSString *nsstring);
+JSValue convertObjcValueToValue(ExecState*, void* buffer, ObjcValueType, RootObject*);
+ObjcValueType objcValueTypeForType(const char *type);
+
+bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize);
+
+JSObject *throwError(ExecState *, NSString *message);
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif
diff --git a/Source/WebCore/bridge/objc/objc_utility.mm b/Source/WebCore/bridge/objc/objc_utility.mm
new file mode 100644
index 0000000..dfba852
--- /dev/null
+++ b/Source/WebCore/bridge/objc/objc_utility.mm
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2004 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "objc_utility.h"
+
+#include "objc_instance.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include "WebScriptObject.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <wtf/Assertions.h>
+
+#if !defined(_C_LNG_LNG)
+#define _C_LNG_LNG 'q'
+#endif
+
+#if !defined(_C_ULNG_LNG)
+#define _C_ULNG_LNG 'Q'
+#endif
+
+#if !defined(_C_CONST)
+#define _C_CONST 'r'
+#endif
+
+#if !defined(_C_BYCOPY)
+#define _C_BYCOPY 'O'
+#endif
+
+#if !defined(_C_BYREF)
+#define _C_BYREF 'R'
+#endif
+
+#if !defined(_C_ONEWAY)
+#define _C_ONEWAY 'V'
+#endif
+
+#if !defined(_C_GCINVISIBLE)
+#define _C_GCINVISIBLE '!'
+#endif
+
+namespace JSC {
+namespace Bindings {
+
+/*
+ By default, a JavaScript method name is produced by concatenating the
+ components of an ObjectiveC method name, replacing ':' with '_', and
+ escaping '_' and '$' with a leading '$', such that '_' becomes "$_" and
+ '$' becomes "$$". For example:
+
+ ObjectiveC name Default JavaScript name
+ moveTo:: moveTo__
+ moveTo_ moveTo$_
+ moveTo$_ moveTo$$$_
+
+ This function performs the inverse of that operation.
+
+ @result Fills 'buffer' with the ObjectiveC method name that corresponds to 'JSName'.
+ Returns true for success, false for failure. (Failure occurs when 'buffer'
+ is not big enough to hold the result.)
+*/
+bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize)
+{
+ ASSERT(JSName && buffer);
+
+ const char *sp = JSName; // source pointer
+ char *dp = buffer; // destination pointer
+
+ char *end = buffer + bufferSize;
+ while (dp < end) {
+ if (*sp == '$') {
+ ++sp;
+ *dp = *sp;
+ } else if (*sp == '_')
+ *dp = ':';
+ else
+ *dp = *sp;
+
+ // If a future coder puts funny ++ operators above, we might write off the end
+ // of the buffer in the middle of this loop. Let's make sure to check for that.
+ ASSERT(dp < end);
+
+ if (*sp == 0) { // We finished converting JSName
+ ASSERT(strlen(JSName) < bufferSize);
+ return true;
+ }
+
+ ++sp;
+ ++dp;
+ }
+
+ return false; // We ran out of buffer before converting JSName
+}
+
+/*
+
+ JavaScript to ObjC
+ Number coerced to char, short, int, long, float, double, or NSNumber, as appropriate
+ String NSString
+ wrapper id
+ Object WebScriptObject
+ null NSNull
+ [], other exception
+
+*/
+ObjcValue convertValueToObjcValue(ExecState* exec, JSValue value, ObjcValueType type)
+{
+ ObjcValue result;
+ double d = 0;
+
+ if (value.isNumber() || value.isString() || value.isBoolean())
+ d = value.toNumber(exec);
+
+ switch (type) {
+ case ObjcObjectType: {
+ JSLock lock(SilenceAssertionsOnly);
+
+ JSGlobalObject *originGlobalObject = exec->dynamicGlobalObject();
+ RootObject* originRootObject = findRootObject(originGlobalObject);
+
+ JSGlobalObject* globalObject = 0;
+ if (value.isObject() && asObject(value)->isGlobalObject())
+ globalObject = static_cast<JSGlobalObject*>(asObject(value));
+
+ if (!globalObject)
+ globalObject = originGlobalObject;
+
+ RootObject* rootObject = findRootObject(globalObject);
+ result.objectValue = rootObject
+ ? [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:originRootObject rootObject:rootObject]
+ : nil;
+ }
+ break;
+
+ case ObjcCharType:
+ case ObjcUnsignedCharType:
+ result.charValue = (char)d;
+ break;
+ case ObjcShortType:
+ case ObjcUnsignedShortType:
+ result.shortValue = (short)d;
+ break;
+ case ObjcIntType:
+ case ObjcUnsignedIntType:
+ result.intValue = (int)d;
+ break;
+ case ObjcLongType:
+ case ObjcUnsignedLongType:
+ result.longValue = (long)d;
+ break;
+ case ObjcLongLongType:
+ case ObjcUnsignedLongLongType:
+ result.longLongValue = (long long)d;
+ break;
+ case ObjcFloatType:
+ result.floatValue = (float)d;
+ break;
+ case ObjcDoubleType:
+ result.doubleValue = (double)d;
+ break;
+ case ObjcVoidType:
+ bzero(&result, sizeof(ObjcValue));
+ break;
+
+ case ObjcInvalidType:
+ default:
+ // FIXME: throw an exception?
+ break;
+ }
+
+ return result;
+}
+
+JSValue convertNSStringToString(ExecState* exec, NSString *nsstring)
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ unichar *chars;
+ unsigned int length = [nsstring length];
+ chars = (unichar *)malloc(sizeof(unichar)*length);
+ [nsstring getCharacters:chars];
+ UString u((const UChar*)chars, length);
+ JSValue aValue = jsString(exec, u);
+ free((void *)chars);
+ return aValue;
+}
+
+/*
+ ObjC to JavaScript
+ ---- ----------
+ char number
+ short number
+ int number
+ long number
+ float number
+ double number
+ NSNumber boolean or number
+ NSString string
+ NSArray array
+ NSNull null
+ WebScriptObject underlying JavaScript object
+ WebUndefined undefined
+ id object wrapper
+ other should not happen
+*/
+JSValue convertObjcValueToValue(ExecState* exec, void* buffer, ObjcValueType type, RootObject* rootObject)
+{
+ JSLock lock(SilenceAssertionsOnly);
+
+ switch (type) {
+ case ObjcObjectType: {
+ id obj = *(id*)buffer;
+ if ([obj isKindOfClass:[NSString class]])
+ return convertNSStringToString(exec, (NSString *)obj);
+ if ([obj isKindOfClass:webUndefinedClass()])
+ return jsUndefined();
+ if ((CFBooleanRef)obj == kCFBooleanTrue)
+ return jsBoolean(true);
+ if ((CFBooleanRef)obj == kCFBooleanFalse)
+ return jsBoolean(false);
+ if ([obj isKindOfClass:[NSNumber class]])
+ return jsNumber([obj doubleValue]);
+ if ([obj isKindOfClass:[NSArray class]])
+ return new (exec) RuntimeArray(exec, new ObjcArray(obj, rootObject));
+ if ([obj isKindOfClass:webScriptObjectClass()]) {
+ JSObject* imp = [obj _imp];
+ return imp ? imp : jsUndefined();
+ }
+ if ([obj isKindOfClass:[NSNull class]])
+ return jsNull();
+ if (obj == 0)
+ return jsUndefined();
+ return ObjcInstance::create(obj, rootObject)->createRuntimeObject(exec);
+ }
+ case ObjcCharType:
+ return jsNumber(*(char*)buffer);
+ case ObjcUnsignedCharType:
+ return jsNumber(*(unsigned char*)buffer);
+ case ObjcShortType:
+ return jsNumber(*(short*)buffer);
+ case ObjcUnsignedShortType:
+ return jsNumber(*(unsigned short*)buffer);
+ case ObjcIntType:
+ return jsNumber(*(int*)buffer);
+ case ObjcUnsignedIntType:
+ return jsNumber(*(unsigned int*)buffer);
+ case ObjcLongType:
+ return jsNumber(*(long*)buffer);
+ case ObjcUnsignedLongType:
+ return jsNumber(*(unsigned long*)buffer);
+ case ObjcLongLongType:
+ return jsNumber(*(long long*)buffer);
+ case ObjcUnsignedLongLongType:
+ return jsNumber(*(unsigned long long*)buffer);
+ case ObjcFloatType:
+ return jsNumber(*(float*)buffer);
+ case ObjcDoubleType:
+ return jsNumber(*(double*)buffer);
+ default:
+ // Should never get here. Argument types are filtered.
+ fprintf(stderr, "%s: invalid type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+ ASSERT(false);
+ }
+
+ return jsUndefined();
+}
+
+ObjcValueType objcValueTypeForType(const char *type)
+{
+ int typeLength = strlen(type);
+ ObjcValueType objcValueType = ObjcInvalidType;
+
+ for (int i = 0; i < typeLength; ++i) {
+ char typeChar = type[i];
+ switch (typeChar) {
+ case _C_CONST:
+ case _C_BYCOPY:
+ case _C_BYREF:
+ case _C_ONEWAY:
+ case _C_GCINVISIBLE:
+ // skip these type modifiers
+ break;
+ case _C_ID:
+ objcValueType = ObjcObjectType;
+ break;
+ case _C_CHR:
+ objcValueType = ObjcCharType;
+ break;
+ case _C_UCHR:
+ objcValueType = ObjcUnsignedCharType;
+ break;
+ case _C_SHT:
+ objcValueType = ObjcShortType;
+ break;
+ case _C_USHT:
+ objcValueType = ObjcUnsignedShortType;
+ break;
+ case _C_INT:
+ objcValueType = ObjcIntType;
+ break;
+ case _C_UINT:
+ objcValueType = ObjcUnsignedIntType;
+ break;
+ case _C_LNG:
+ objcValueType = ObjcLongType;
+ break;
+ case _C_ULNG:
+ objcValueType = ObjcUnsignedLongType;
+ break;
+ case _C_LNG_LNG:
+ objcValueType = ObjcLongLongType;
+ break;
+ case _C_ULNG_LNG:
+ objcValueType = ObjcUnsignedLongLongType;
+ break;
+ case _C_FLT:
+ objcValueType = ObjcFloatType;
+ break;
+ case _C_DBL:
+ objcValueType = ObjcDoubleType;
+ break;
+ case _C_VOID:
+ objcValueType = ObjcVoidType;
+ break;
+ default:
+ // Unhandled type. We don't handle C structs, unions, etc.
+ // FIXME: throw an exception?
+ ASSERT(false);
+ }
+
+ if (objcValueType != ObjcInvalidType)
+ break;
+ }
+
+ return objcValueType;
+}
+
+JSObject *throwError(ExecState *exec, NSString *message)
+{
+ ASSERT(message);
+ size_t length = [message length];
+ unichar *buffer = new unichar[length];
+ [message getCharacters:buffer];
+ JSObject *error = JSC::throwError(exec, JSC::createError(exec, UString(buffer, length)));
+ delete [] buffer;
+ return error;
+}
+
+}
+}