summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/bindings')
-rw-r--r--JavaScriptCore/bindings/NP_jsobject.cpp406
-rw-r--r--JavaScriptCore/bindings/NP_jsobject.h54
-rw-r--r--JavaScriptCore/bindings/c/c_class.cpp123
-rw-r--r--JavaScriptCore/bindings/c/c_class.h60
-rw-r--r--JavaScriptCore/bindings/c/c_instance.cpp212
-rw-r--r--JavaScriptCore/bindings/c/c_instance.h79
-rw-r--r--JavaScriptCore/bindings/c/c_runtime.cpp96
-rw-r--r--JavaScriptCore/bindings/c/c_runtime.h66
-rw-r--r--JavaScriptCore/bindings/c/c_utility.cpp185
-rw-r--r--JavaScriptCore/bindings/c/c_utility.h71
-rw-r--r--JavaScriptCore/bindings/jni/jni_class.cpp134
-rw-r--r--JavaScriptCore/bindings/jni/jni_class.h62
-rw-r--r--JavaScriptCore/bindings/jni/jni_instance.cpp353
-rw-r--r--JavaScriptCore/bindings/jni/jni_instance.h98
-rw-r--r--JavaScriptCore/bindings/jni/jni_jsobject.cpp585
-rw-r--r--JavaScriptCore/bindings/jni/jni_jsobject.h123
-rw-r--r--JavaScriptCore/bindings/jni/jni_objc.mm76
-rw-r--r--JavaScriptCore/bindings/jni/jni_runtime.cpp545
-rw-r--r--JavaScriptCore/bindings/jni/jni_runtime.h185
-rw-r--r--JavaScriptCore/bindings/jni/jni_utility.cpp987
-rw-r--r--JavaScriptCore/bindings/jni/jni_utility.h120
-rwxr-xr-xJavaScriptCore/bindings/make_testbindings2
-rw-r--r--JavaScriptCore/bindings/npapi.h714
-rw-r--r--JavaScriptCore/bindings/npruntime.cpp226
-rw-r--r--JavaScriptCore/bindings/npruntime.h354
-rw-r--r--JavaScriptCore/bindings/npruntime_impl.h64
-rw-r--r--JavaScriptCore/bindings/npruntime_internal.h39
-rw-r--r--JavaScriptCore/bindings/npruntime_priv.h41
-rw-r--r--JavaScriptCore/bindings/objc/WebScriptObject.h46
-rw-r--r--JavaScriptCore/bindings/objc/objc_class.h61
-rw-r--r--JavaScriptCore/bindings/objc/objc_class.mm258
-rw-r--r--JavaScriptCore/bindings/objc/objc_header.h53
-rw-r--r--JavaScriptCore/bindings/objc/objc_instance.h81
-rw-r--r--JavaScriptCore/bindings/objc/objc_instance.mm349
-rw-r--r--JavaScriptCore/bindings/objc/objc_runtime.h127
-rw-r--r--JavaScriptCore/bindings/objc/objc_runtime.mm289
-rw-r--r--JavaScriptCore/bindings/objc/objc_utility.h87
-rw-r--r--JavaScriptCore/bindings/objc/objc_utility.mm372
-rw-r--r--JavaScriptCore/bindings/qt/qt_class.cpp223
-rw-r--r--JavaScriptCore/bindings/qt/qt_class.h55
-rw-r--r--JavaScriptCore/bindings/qt/qt_instance.cpp394
-rw-r--r--JavaScriptCore/bindings/qt/qt_instance.h85
-rw-r--r--JavaScriptCore/bindings/qt/qt_runtime.cpp1590
-rw-r--r--JavaScriptCore/bindings/qt/qt_runtime.h217
-rw-r--r--JavaScriptCore/bindings/runtime.cpp156
-rw-r--r--JavaScriptCore/bindings/runtime.h174
-rw-r--r--JavaScriptCore/bindings/runtime_array.cpp118
-rw-r--r--JavaScriptCore/bindings/runtime_array.h65
-rw-r--r--JavaScriptCore/bindings/runtime_method.cpp94
-rw-r--r--JavaScriptCore/bindings/runtime_method.h51
-rw-r--r--JavaScriptCore/bindings/runtime_object.cpp238
-rw-r--r--JavaScriptCore/bindings/runtime_object.h73
-rw-r--r--JavaScriptCore/bindings/runtime_root.cpp305
-rw-r--r--JavaScriptCore/bindings/runtime_root.h109
-rw-r--r--JavaScriptCore/bindings/test.js19
-rw-r--r--JavaScriptCore/bindings/testC.js21
-rw-r--r--JavaScriptCore/bindings/testM.js29
-rw-r--r--JavaScriptCore/bindings/testbindings.cpp422
-rw-r--r--JavaScriptCore/bindings/testbindings.mm289
-rw-r--r--JavaScriptCore/bindings/testbindings.pro8
-rw-r--r--JavaScriptCore/bindings/testqtbindings.cpp142
61 files changed, 12660 insertions, 0 deletions
diff --git a/JavaScriptCore/bindings/NP_jsobject.cpp b/JavaScriptCore/bindings/NP_jsobject.cpp
new file mode 100644
index 0000000..059b5df
--- /dev/null
+++ b/JavaScriptCore/bindings/NP_jsobject.cpp
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2004, 2006 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "NP_jsobject.h"
+
+#include "JSGlobalObject.h"
+#include "PropertyNameArray.h"
+#include "c_utility.h"
+#include "interpreter.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+#include "object.h"
+#include "runtime_root.h"
+
+using namespace KJS;
+using namespace KJS::Bindings;
+
+static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, List& aList)
+{
+ for (unsigned i = 0; i < argCount; i++)
+ aList.append(convertNPVariantToValue(exec, &args[i], rootObject));
+}
+
+static NPObject* jsAllocate(NPP, NPClass*)
+{
+ return (NPObject*)malloc(sizeof(JavaScriptObject));
+}
+
+static void jsDeallocate(NPObject* npObj)
+{
+ JavaScriptObject* obj = (JavaScriptObject*)npObj;
+
+ if (obj->rootObject && obj->rootObject->isValid())
+ obj->rootObject->gcUnprotect(obj->imp);
+
+ if (obj->rootObject)
+ obj->rootObject->deref();
+
+ free(obj);
+}
+
+static NPClass javascriptClass = { 1, jsAllocate, jsDeallocate, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static NPClass noScriptClass = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+NPClass* NPScriptObjectClass = &javascriptClass;
+static NPClass* NPNoScriptObjectClass = &noScriptClass;
+
+NPObject* _NPN_CreateScriptObject(NPP npp, JSObject* imp, PassRefPtr<RootObject> rootObject)
+{
+ JavaScriptObject* obj = (JavaScriptObject*)_NPN_CreateObject(npp, NPScriptObjectClass);
+
+ obj->rootObject = rootObject.releaseRef();
+
+ if (obj->rootObject)
+ obj->rootObject->gcProtect(imp);
+ obj->imp = imp;
+
+ return (NPObject*)obj;
+}
+
+NPObject *_NPN_CreateNoScriptObject(void)
+{
+ return _NPN_CreateObject(0, NPNoScriptObjectClass);
+}
+
+bool _NPN_InvokeDefault(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, NPVariant* result)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+
+ VOID_TO_NPVARIANT(*result);
+
+ // Lookup the function object.
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+
+ // Call the function object.
+ JSObject *funcImp = static_cast<JSObject*>(obj->imp);
+ if (!funcImp->implementsCall())
+ return false;
+
+ List argList;
+ getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+ rootObject->globalObject()->startTimeoutCheck();
+ JSValue *resultV = funcImp->call (exec, funcImp, argList);
+ rootObject->globalObject()->stopTimeoutCheck();
+
+ // Convert and return the result of the function call.
+ convertValueToNPVariant(exec, resultV, result);
+ return true;
+ }
+
+ if (o->_class->invokeDefault)
+ return o->_class->invokeDefault(o, args, argCount, result);
+ VOID_TO_NPVARIANT(*result);
+ return true;
+}
+
+bool _NPN_Invoke(NPP npp, NPObject* o, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+
+ PrivateIdentifier* i = (PrivateIdentifier*)methodName;
+ if (!i->isString)
+ return false;
+
+ // Special case the "eval" method.
+ if (methodName == _NPN_GetStringIdentifier("eval")) {
+ if (argCount != 1)
+ return false;
+ if (args[0].type != NPVariantType_String)
+ return false;
+ return _NPN_Evaluate(npp, o, (NPString *)&args[0].value.stringValue, result);
+ }
+
+ // Lookup the function object.
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+ JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
+ if (func->isNull()) {
+ NULL_TO_NPVARIANT(*result);
+ return false;
+ }
+ if (func->isUndefined()) {
+ VOID_TO_NPVARIANT(*result);
+ return false;
+ }
+ // Call the function object.
+ JSObject *funcImp = static_cast<JSObject*>(func);
+ JSObject *thisObj = const_cast<JSObject*>(obj->imp);
+ List argList;
+ getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+ rootObject->globalObject()->startTimeoutCheck();
+ JSValue *resultV = funcImp->call (exec, thisObj, argList);
+ rootObject->globalObject()->stopTimeoutCheck();
+
+ // Convert and return the result of the function call.
+ convertValueToNPVariant(exec, resultV, result);
+ return true;
+ }
+
+ if (o->_class->invoke)
+ return o->_class->invoke(o, methodName, args, argCount, result);
+
+ VOID_TO_NPVARIANT(*result);
+ return true;
+}
+
+bool _NPN_Evaluate(NPP, NPObject* o, NPString* s, NPVariant* variant)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+
+ JSLock lock;
+ NPUTF16* scriptString;
+ unsigned int UTF16Length;
+ convertNPStringToUTF16(s, &scriptString, &UTF16Length); // requires free() of returned memory
+ rootObject->globalObject()->startTimeoutCheck();
+ Completion completion = Interpreter::evaluate(rootObject->globalObject()->globalExec(), UString(), 0, UString(reinterpret_cast<const UChar*>(scriptString), UTF16Length));
+ rootObject->globalObject()->stopTimeoutCheck();
+ ComplType type = completion.complType();
+
+ JSValue* result;
+ if (type == Normal) {
+ result = completion.value();
+ if (!result)
+ result = jsUndefined();
+ } else
+ result = jsUndefined();
+
+ free(scriptString);
+
+ convertValueToNPVariant(exec, result, variant);
+
+ return true;
+ }
+
+ VOID_TO_NPVARIANT(*variant);
+ return false;
+}
+
+bool _NPN_GetProperty(NPP, NPObject* o, NPIdentifier propertyName, NPVariant* variant)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
+
+ JSLock lock;
+ JSValue *result;
+ if (i->isString)
+ result = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
+ else
+ result = obj->imp->get(exec, i->value.number);
+
+ convertValueToNPVariant(exec, result, variant);
+ return true;
+ }
+
+ if (o->_class->hasProperty && o->_class->getProperty) {
+ if (o->_class->hasProperty(o, propertyName))
+ return o->_class->getProperty(o, propertyName, variant);
+ return false;
+ }
+
+ VOID_TO_NPVARIANT(*variant);
+ return false;
+}
+
+bool _NPN_SetProperty(NPP, NPObject* o, NPIdentifier propertyName, const NPVariant* variant)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+ PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
+ if (i->isString)
+ obj->imp->put(exec, identifierFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant, rootObject));
+ else
+ obj->imp->put(exec, i->value.number, convertNPVariantToValue(exec, variant, rootObject));
+ return true;
+ }
+
+ if (o->_class->setProperty)
+ return o->_class->setProperty(o, propertyName, variant);
+
+ return false;
+}
+
+bool _NPN_RemoveProperty(NPP, NPObject* o, NPIdentifier propertyName)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
+ if (i->isString) {
+ if (!obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string)))
+ return false;
+ } else {
+ if (!obj->imp->hasProperty(exec, i->value.number))
+ return false;
+ }
+
+ JSLock lock;
+ if (i->isString)
+ obj->imp->deleteProperty(exec, identifierFromNPIdentifier(i->value.string));
+ else
+ obj->imp->deleteProperty(exec, i->value.number);
+
+ return true;
+ }
+ return false;
+}
+
+bool _NPN_HasProperty(NPP, NPObject* o, NPIdentifier propertyName)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
+ JSLock lock;
+ if (i->isString)
+ return obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string));
+ return obj->imp->hasProperty(exec, i->value.number);
+ }
+
+ if (o->_class->hasProperty)
+ return o->_class->hasProperty(o, propertyName);
+
+ return false;
+}
+
+bool _NPN_HasMethod(NPP, NPObject* o, NPIdentifier methodName)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+
+ PrivateIdentifier* i = (PrivateIdentifier*)methodName;
+ if (!i->isString)
+ return false;
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+ JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
+ return !func->isUndefined();
+ }
+
+ if (o->_class->hasMethod)
+ return o->_class->hasMethod(o, methodName);
+
+ return false;
+}
+
+void _NPN_SetException(NPObject* o, const NPUTF8* message)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+ throwError(exec, GeneralError, message);
+ }
+}
+
+bool _NPN_Enumerate(NPP, NPObject *o, NPIdentifier **identifier, uint32_t *count)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = (JavaScriptObject*)o;
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+ PropertyNameArray propertyNames;
+
+ obj->imp->getPropertyNames(exec, propertyNames);
+ unsigned size = static_cast<unsigned>(propertyNames.size());
+ // FIXME: This should really call NPN_MemAlloc but that's in WebKit
+ NPIdentifier *identifiers = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier) * size));
+
+ for (unsigned i = 0; i < size; i++)
+ identifiers[i] = _NPN_GetStringIdentifier(propertyNames[i].ustring().UTF8String().c_str());
+
+ *identifier = identifiers;
+ *count = size;
+
+ return true;
+ }
+
+ if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o->_class) && o->_class->enumerate)
+ return o->_class->enumerate(o, identifier, count);
+
+ return false;
+}
+
+#endif
diff --git a/JavaScriptCore/bindings/NP_jsobject.h b/JavaScriptCore/bindings/NP_jsobject.h
new file mode 100644
index 0000000..dd9ccae
--- /dev/null
+++ b/JavaScriptCore/bindings/NP_jsobject.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004, 2006 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 NP_JSOBJECT_H
+#define NP_JSOBJECT_H
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+#include <wtf/Forward.h>
+
+namespace KJS {
+ class JSObject;
+ namespace Bindings {
+ class RootObject;
+ }
+}
+
+extern NPClass* NPScriptObjectClass;
+
+struct JavaScriptObject
+{
+ NPObject object;
+ KJS::JSObject* imp;
+ KJS::Bindings::RootObject* rootObject;
+};
+
+NPObject* _NPN_CreateScriptObject(NPP npp, KJS::JSObject*, PassRefPtr<KJS::Bindings::RootObject> rootObject);
+NPObject* _NPN_CreateNoScriptObject(void);
+
+#endif
+#endif
diff --git a/JavaScriptCore/bindings/c/c_class.cpp b/JavaScriptCore/bindings/c/c_class.cpp
new file mode 100644
index 0000000..f0bb8da
--- /dev/null
+++ b/JavaScriptCore/bindings/c/c_class.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2003, 2006 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "c_class.h"
+
+#include "c_instance.h"
+#include "c_runtime.h"
+#include "identifier.h"
+#include "npruntime_impl.h"
+
+namespace KJS { namespace Bindings {
+
+CClass::CClass(NPClass* aClass)
+{
+ _isa = aClass;
+}
+
+CClass::~CClass()
+{
+ JSLock lock;
+
+ deleteAllValues(_methods);
+ _methods.clear();
+
+ deleteAllValues(_fields);
+ _fields.clear();
+}
+
+typedef HashMap<NPClass*, CClass*> ClassesByIsAMap;
+static ClassesByIsAMap* classesByIsA = 0;
+
+CClass* CClass::classForIsA(NPClass* isa)
+{
+ if (!classesByIsA)
+ classesByIsA = new ClassesByIsAMap;
+
+ CClass* aClass = classesByIsA->get(isa);
+ if (!aClass) {
+ aClass = new CClass(isa);
+ classesByIsA->set(isa, aClass);
+ }
+
+ return aClass;
+}
+
+const char* CClass::name() const
+{
+ return "";
+}
+
+MethodList CClass::methodsNamed(const Identifier& identifier, Instance* instance) const
+{
+ MethodList methodList;
+
+ Method* method = _methods.get(identifier.ustring().rep());
+ if (method) {
+ methodList.append(method);
+ return methodList;
+ }
+
+ NPIdentifier ident = _NPN_GetStringIdentifier(identifier.ascii());
+ const CInstance* inst = static_cast<const CInstance*>(instance);
+ NPObject* obj = inst->getObject();
+ if (_isa->hasMethod && _isa->hasMethod(obj, ident)){
+ Method* aMethod = new CMethod(ident); // deleted in the CClass destructor
+ {
+ JSLock lock;
+ _methods.set(identifier.ustring().rep(), aMethod);
+ }
+ methodList.append(aMethod);
+ }
+
+ return methodList;
+}
+
+Field* CClass::fieldNamed(const Identifier& identifier, Instance* instance) const
+{
+ Field* aField = _fields.get(identifier.ustring().rep());
+ if (aField)
+ return aField;
+
+ NPIdentifier ident = _NPN_GetStringIdentifier(identifier.ascii());
+ const CInstance* inst = static_cast<const CInstance*>(instance);
+ NPObject* obj = inst->getObject();
+ if (_isa->hasProperty && _isa->hasProperty(obj, ident)){
+ aField = new CField(ident); // deleted in the CClass destructor
+ {
+ JSLock lock;
+ _fields.set(identifier.ustring().rep(), aField);
+ }
+ }
+ return aField;
+}
+
+} } // namespace KJS::Bindings
+
+#endif
diff --git a/JavaScriptCore/bindings/c/c_class.h b/JavaScriptCore/bindings/c/c_class.h
new file mode 100644
index 0000000..8134d5d
--- /dev/null
+++ b/JavaScriptCore/bindings/c/c_class.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#ifndef BINDINGS_C_CLASS_H_
+#define BINDINGS_C_CLASS_H_
+
+#include "npruntime_internal.h"
+#include "runtime.h"
+#include <wtf/HashMap.h>
+
+namespace KJS {
+namespace Bindings {
+
+class CClass : public Class {
+protected:
+ CClass(NPClass*); // Use classForIsA to create a CClass.
+
+public:
+ static CClass* classForIsA(NPClass*);
+ virtual ~CClass();
+
+ virtual const char* name() const;
+ virtual MethodList methodsNamed(const Identifier&, Instance*) const;
+ virtual Field* fieldNamed(const Identifier&, Instance*) const;
+
+private:
+ NPClass* _isa;
+ mutable MethodMap _methods;
+ mutable FieldMap _fields;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
+#endif
diff --git a/JavaScriptCore/bindings/c/c_instance.cpp b/JavaScriptCore/bindings/c/c_instance.cpp
new file mode 100644
index 0000000..3d04054
--- /dev/null
+++ b/JavaScriptCore/bindings/c/c_instance.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2003, 2006 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "c_instance.h"
+
+#include "c_class.h"
+#include "c_runtime.h"
+#include "c_utility.h"
+#include "list.h"
+#include "npruntime_impl.h"
+#include "PropertyNameArray.h"
+#include "runtime_root.h"
+#include <wtf/Assertions.h>
+#include <wtf/StringExtras.h>
+#include <wtf/Vector.h>
+
+namespace KJS {
+namespace Bindings {
+
+CInstance::CInstance(NPObject* o, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+{
+ _object = _NPN_RetainObject(o);
+ _class = 0;
+}
+
+CInstance::~CInstance()
+{
+ _NPN_ReleaseObject(_object);
+}
+
+Class *CInstance::getClass() const
+{
+ if (!_class)
+ _class = CClass::classForIsA(_object->_class);
+ return _class;
+}
+
+void CInstance::begin()
+{
+ // Do nothing.
+}
+
+void CInstance::end()
+{
+ // Do nothing.
+}
+
+bool CInstance::implementsCall() const
+{
+ return (_object->_class->invokeDefault != 0);
+}
+
+JSValue* CInstance::invokeMethod(ExecState* exec, const MethodList& methodList, const List& args)
+{
+ // Overloading methods are not allowed by NPObjects. Should only be one
+ // name match for a particular method.
+ ASSERT(methodList.size() == 1);
+
+ CMethod* method = static_cast<CMethod*>(methodList[0]);
+
+ NPIdentifier ident = _NPN_GetStringIdentifier(method->name());
+ if (!_object->_class->hasMethod(_object, ident))
+ return jsUndefined();
+
+ unsigned count = args.size();
+ Vector<NPVariant, 128> cArgs(count);
+
+ unsigned i;
+ for (i = 0; i < count; i++)
+ convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
+
+ // Invoke the 'C' method.
+ NPVariant resultVariant;
+ VOID_TO_NPVARIANT(resultVariant);
+
+ {
+ JSLock::DropAllLocks dropAllLocks;
+ _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant);
+ }
+
+ for (i = 0; i < count; i++)
+ _NPN_ReleaseVariantValue(&cArgs[i]);
+
+ JSValue* resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
+ _NPN_ReleaseVariantValue(&resultVariant);
+ return resultValue;
+}
+
+
+JSValue* CInstance::invokeDefaultMethod(ExecState* exec, const List& args)
+{
+ if (!_object->_class->invokeDefault)
+ return jsUndefined();
+
+ unsigned count = args.size();
+ Vector<NPVariant, 128> cArgs(count);
+
+ unsigned i;
+ for (i = 0; i < count; i++)
+ convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
+
+ // Invoke the 'C' method.
+ NPVariant resultVariant;
+ VOID_TO_NPVARIANT(resultVariant);
+ {
+ JSLock::DropAllLocks dropAllLocks;
+ _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant);
+ }
+
+ for (i = 0; i < count; i++)
+ _NPN_ReleaseVariantValue(&cArgs[i]);
+
+ JSValue* resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
+ _NPN_ReleaseVariantValue(&resultVariant);
+ return resultValue;
+}
+
+
+JSValue* CInstance::defaultValue(JSType hint) const
+{
+ if (hint == StringType)
+ return stringValue();
+ if (hint == NumberType)
+ return numberValue();
+ if (hint == BooleanType)
+ return booleanValue();
+ return valueOf();
+}
+
+JSValue* CInstance::stringValue() const
+{
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class);
+ return jsString(buf);
+}
+
+JSValue* CInstance::numberValue() const
+{
+ // FIXME: Implement something sensible.
+ return jsNumber(0);
+}
+
+JSValue* CInstance::booleanValue() const
+{
+ // FIXME: Implement something sensible.
+ return jsBoolean(false);
+}
+
+JSValue* CInstance::valueOf() const
+{
+ return stringValue();
+}
+
+void CInstance::getPropertyNames(ExecState*, PropertyNameArray& nameArray)
+{
+ if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) ||
+ !_object->_class->enumerate)
+ return;
+
+ unsigned count;
+ NPIdentifier* identifiers;
+
+ {
+ JSLock::DropAllLocks dropAllLocks;
+ if (!_object->_class->enumerate(_object, &identifiers, &count))
+ return;
+ }
+
+ for (unsigned i = 0; i < count; i++) {
+ PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(identifiers[i]);
+
+ if (identifier->isString)
+ nameArray.add(identifierFromNPIdentifier(identifier->value.string));
+ else
+ nameArray.add(Identifier::from(identifier->value.number));
+ }
+
+ // FIXME: This should really call NPN_MemFree but that's in WebKit
+ free(identifiers);
+}
+
+}
+}
+
+#endif
diff --git a/JavaScriptCore/bindings/c/c_instance.h b/JavaScriptCore/bindings/c/c_instance.h
new file mode 100644
index 0000000..9991a18
--- /dev/null
+++ b/JavaScriptCore/bindings/c/c_instance.h
@@ -0,0 +1,79 @@
+/*
+ * 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 BINDINGS_C_INSTANCE_H_
+#define BINDINGS_C_INSTANCE_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "runtime.h"
+#include <wtf/Noncopyable.h>
+
+typedef struct NPObject NPObject;
+
+namespace KJS {
+
+namespace Bindings {
+
+class CClass;
+
+class CInstance : public Instance {
+public:
+ CInstance (NPObject*, PassRefPtr<RootObject>);
+ ~CInstance ();
+
+ virtual Class *getClass() const;
+
+ virtual void begin();
+ virtual void end();
+
+ virtual JSValue *valueOf() const;
+ virtual JSValue *defaultValue (JSType hint) const;
+
+ virtual bool implementsCall() const;
+
+ virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const List &args);
+ virtual JSValue *invokeDefaultMethod (ExecState *exec, const List &args);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ JSValue *stringValue() const;
+ JSValue *numberValue() const;
+ JSValue *booleanValue() const;
+
+ NPObject *getObject() const { return _object; }
+
+ virtual BindingLanguage getBindingLanguage() const { return CLanguage; }
+
+private:
+ mutable CClass *_class;
+ NPObject *_object;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
+#endif
diff --git a/JavaScriptCore/bindings/c/c_runtime.cpp b/JavaScriptCore/bindings/c/c_runtime.cpp
new file mode 100644
index 0000000..c5636cd
--- /dev/null
+++ b/JavaScriptCore/bindings/c/c_runtime.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "c_runtime.h"
+
+#include "c_instance.h"
+#include "c_utility.h"
+#include "npruntime_impl.h"
+
+namespace KJS {
+namespace Bindings {
+
+// ---------------------- CMethod ----------------------
+
+const char* CMethod::name() const
+{
+ PrivateIdentifier *i = (PrivateIdentifier *)_methodIdentifier;
+ return i->isString ? i->value.string : 0;
+}
+
+// ---------------------- CField ----------------------
+
+const char* CField::name() const
+{
+ PrivateIdentifier *i = (PrivateIdentifier *)_fieldIdentifier;
+ return i->isString ? i->value.string : 0;
+}
+
+JSValue* CField::valueFromInstance(ExecState* exec, const Instance* inst) const
+{
+ const CInstance* instance = static_cast<const CInstance*>(inst);
+ NPObject* obj = instance->getObject();
+ if (obj->_class->getProperty) {
+ NPVariant property;
+ VOID_TO_NPVARIANT(property);
+
+ bool result;
+ {
+ JSLock::DropAllLocks dropAllLocks;
+ result = obj->_class->getProperty(obj, _fieldIdentifier, &property);
+ }
+ if (result) {
+ JSValue* result = convertNPVariantToValue(exec, &property, instance->rootObject());
+ _NPN_ReleaseVariantValue(&property);
+ return result;
+ }
+ }
+ return jsUndefined();
+}
+
+void CField::setValueToInstance(ExecState *exec, const Instance *inst, JSValue *aValue) const
+{
+ const CInstance* instance = static_cast<const CInstance*>(inst);
+ NPObject* obj = instance->getObject();
+ if (obj->_class->setProperty) {
+ NPVariant variant;
+ convertValueToNPVariant(exec, aValue, &variant);
+
+ {
+ JSLock::DropAllLocks dropAllLocks;
+ obj->_class->setProperty(obj, _fieldIdentifier, &variant);
+ }
+
+ _NPN_ReleaseVariantValue(&variant);
+ }
+}
+
+} }
+
+#endif
diff --git a/JavaScriptCore/bindings/c/c_runtime.h b/JavaScriptCore/bindings/c/c_runtime.h
new file mode 100644
index 0000000..469008a
--- /dev/null
+++ b/JavaScriptCore/bindings/c/c_runtime.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004, 2006 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 BINDINGS_C_RUNTIME_H_
+#define BINDINGS_C_RUNTIME_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+#include "runtime.h"
+
+namespace KJS {
+namespace Bindings {
+
+class CField : public Field {
+public:
+ CField(NPIdentifier ident) : _fieldIdentifier(ident) { }
+
+ virtual JSValue* valueFromInstance(ExecState*, const Instance*) const;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue*) const;
+ virtual const char* name() const;
+
+private:
+ NPIdentifier _fieldIdentifier;
+};
+
+
+class CMethod : public Method
+{
+public:
+ CMethod(NPIdentifier ident) : _methodIdentifier(ident) { }
+
+ virtual const char* name() const;
+ virtual int numParameters() const { return 0; }
+
+private:
+ NPIdentifier _methodIdentifier;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
+#endif
diff --git a/JavaScriptCore/bindings/c/c_utility.cpp b/JavaScriptCore/bindings/c/c_utility.cpp
new file mode 100644
index 0000000..7e2a19f
--- /dev/null
+++ b/JavaScriptCore/bindings/c/c_utility.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "c_utility.h"
+
+#include "NP_jsobject.h"
+#include "c_instance.h"
+#include "JSGlobalObject.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include "Platform.h"
+#include <wtf/Assertions.h>
+#include <wtf/unicode/UTF8.h>
+
+using namespace WTF::Unicode;
+
+namespace KJS { namespace Bindings {
+
+// Requires free() of returned UTF16Chars.
+static void convertUTF8ToUTF16WithLatin1Fallback(const NPUTF8* UTF8Chars, int UTF8Length, NPUTF16** UTF16Chars, unsigned int* UTF16Length)
+{
+ ASSERT(UTF8Chars || UTF8Length == 0);
+ ASSERT(UTF16Chars);
+
+ if (UTF8Length == -1)
+ UTF8Length = static_cast<int>(strlen(UTF8Chars));
+
+ *UTF16Length = UTF8Length;
+ *UTF16Chars = static_cast<NPUTF16*>(malloc(sizeof(NPUTF16) * (*UTF16Length)));
+
+ const char* sourcestart = UTF8Chars;
+ const char* sourceend = sourcestart + UTF8Length;
+
+ ::UChar* targetstart = reinterpret_cast< ::UChar*>(*UTF16Chars);
+ ::UChar* targetend = targetstart + UTF8Length;
+
+ ConversionResult result = convertUTF8ToUTF16(&sourcestart, sourceend, &targetstart, targetend);
+
+ *UTF16Length = targetstart - reinterpret_cast< ::UChar*>(*UTF16Chars);
+
+ // Check to see if the conversion was successful
+ // Some plugins return invalid UTF-8 in NPVariantType_String, see <http://bugs.webkit.org/show_bug.cgi?id=5163>
+ // There is no "bad data" for latin1. It is unlikely that the plugin was really sending text in this encoding,
+ // but it should have used UTF-8, and now we are simply avoiding a crash.
+ if (result != conversionOK) {
+ *UTF16Length = UTF8Length;
+
+ if (!*UTF16Chars) // If the memory wasn't allocated, allocate it.
+ *UTF16Chars = (NPUTF16*)malloc(sizeof(NPUTF16) * (*UTF16Length));
+
+ for (unsigned i = 0; i < *UTF16Length; i++)
+ (*UTF16Chars)[i] = UTF8Chars[i] & 0xFF;
+ }
+}
+
+// Variant value must be released with NPReleaseVariantValue()
+void convertValueToNPVariant(ExecState *exec, JSValue *value, NPVariant *result)
+{
+ JSLock lock;
+
+ JSType type = value->type();
+
+ VOID_TO_NPVARIANT(*result);
+
+ if (type == StringType) {
+ UString ustring = value->toString(exec);
+ CString cstring = ustring.UTF8String();
+ NPString string = { (const NPUTF8 *)cstring.c_str(), static_cast<uint32_t>(cstring.size()) };
+ NPN_InitializeVariantWithStringCopy(result, &string);
+ } else if (type == NumberType) {
+ DOUBLE_TO_NPVARIANT(value->toNumber(exec), *result);
+ } else if (type == BooleanType) {
+ BOOLEAN_TO_NPVARIANT(value->toBoolean(exec), *result);
+ } else if (type == UnspecifiedType) {
+ VOID_TO_NPVARIANT(*result);
+ } else if (type == NullType) {
+ NULL_TO_NPVARIANT(*result);
+ } else if (type == ObjectType) {
+ JSObject* object = static_cast<JSObject*>(value);
+ if (object->classInfo() == &RuntimeObjectImp::info) {
+ RuntimeObjectImp* imp = static_cast<RuntimeObjectImp *>(value);
+ CInstance* instance = static_cast<CInstance*>(imp->getInternalInstance());
+ if (instance) {
+ NPObject* obj = instance->getObject();
+ _NPN_RetainObject(obj);
+ OBJECT_TO_NPVARIANT(obj, *result);
+ }
+ } else {
+ JSGlobalObject* globalObject = exec->dynamicGlobalObject();
+
+ RootObject* rootObject = findRootObject(globalObject);
+ if (rootObject) {
+ NPObject* npObject = _NPN_CreateScriptObject(0, object, rootObject);
+ OBJECT_TO_NPVARIANT(npObject, *result);
+ }
+ }
+ }
+}
+
+JSValue *convertNPVariantToValue(ExecState*, const NPVariant* variant, RootObject* rootObject)
+{
+ JSLock lock;
+
+ NPVariantType type = variant->type;
+
+ if (type == NPVariantType_Bool)
+ return jsBoolean(NPVARIANT_TO_BOOLEAN(*variant));
+ if (type == NPVariantType_Null)
+ return jsNull();
+ if (type == NPVariantType_Void)
+ return jsUndefined();
+ if (type == NPVariantType_Int32)
+ return jsNumber(NPVARIANT_TO_INT32(*variant));
+ if (type == NPVariantType_Double)
+ return jsNumber(NPVARIANT_TO_DOUBLE(*variant));
+ if (type == NPVariantType_String) {
+ NPUTF16 *stringValue;
+ unsigned int UTF16Length;
+ convertNPStringToUTF16(&variant->value.stringValue, &stringValue, &UTF16Length); // requires free() of returned memory
+ UString resultString((const UChar *)stringValue,UTF16Length);
+ free(stringValue);
+ return jsString(resultString);
+ }
+ if (type == NPVariantType_Object) {
+ NPObject *obj = variant->value.objectValue;
+
+ if (obj->_class == NPScriptObjectClass)
+ // Get JSObject from NP_JavaScriptObject.
+ return ((JavaScriptObject *)obj)->imp;
+
+ // Wrap NPObject in a CInstance.
+ return Instance::createRuntimeObject(Instance::CLanguage, obj, rootObject);
+ }
+
+ return jsUndefined();
+}
+
+// Requires free() of returned UTF16Chars.
+void convertNPStringToUTF16(const NPString *string, NPUTF16 **UTF16Chars, unsigned int *UTF16Length)
+{
+ convertUTF8ToUTF16WithLatin1Fallback(string->UTF8Characters, string->UTF8Length, UTF16Chars, UTF16Length);
+}
+
+Identifier identifierFromNPIdentifier(const NPUTF8* name)
+{
+ NPUTF16 *methodName;
+ unsigned UTF16Length;
+ convertUTF8ToUTF16WithLatin1Fallback(name, -1, &methodName, &UTF16Length); // requires free() of returned memory.
+ Identifier identifier((const KJS::UChar*)methodName, UTF16Length);
+ free(methodName);
+ return identifier;
+}
+
+} }
+
+#endif
diff --git a/JavaScriptCore/bindings/c/c_utility.h b/JavaScriptCore/bindings/c/c_utility.h
new file mode 100644
index 0000000..18bc0d4
--- /dev/null
+++ b/JavaScriptCore/bindings/c/c_utility.h
@@ -0,0 +1,71 @@
+/*
+ * 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 C_UTILITY_H_
+#define C_UTILITY_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+
+namespace KJS {
+
+class ExecState;
+class Identifier;
+class JSValue;
+
+namespace Bindings {
+
+class RootObject;
+
+typedef uint16_t NPUTF16;
+
+enum NP_ValueType {
+ NP_NumberValueType,
+ NP_StringValueType,
+ NP_BooleanValueType,
+ NP_NullValueType,
+ NP_UndefinedValueType,
+ NP_ObjectValueType,
+ NP_InvalidValueType
+};
+
+void convertNPStringToUTF16(const NPString*, NPUTF16** UTF16Chars, unsigned int* UTF16Length);
+void convertValueToNPVariant(ExecState*, JSValue*, NPVariant* result);
+JSValue* convertNPVariantToValue(ExecState*, const NPVariant*, RootObject*);
+Identifier identifierFromNPIdentifier(const NPUTF8* name);
+
+struct PrivateIdentifier {
+ union {
+ const NPUTF8* string;
+ int32_t number;
+ } value;
+ bool isString;
+};
+
+} }
+
+#endif
+#endif
diff --git a/JavaScriptCore/bindings/jni/jni_class.cpp b/JavaScriptCore/bindings/jni/jni_class.cpp
new file mode 100644
index 0000000..72b1a73
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_class.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+#include "config.h"
+#include <jni_class.h>
+
+#include "identifier.h"
+#include <jni_utility.h>
+#include <jni_runtime.h>
+
+using namespace KJS::Bindings;
+
+JavaClass::JavaClass(jobject anInstance)
+{
+ jobject aClass = callJNIObjectMethod(anInstance, "getClass", "()Ljava/lang/Class;");
+
+ if (!aClass) {
+ fprintf(stderr, "%s: unable to call getClass on instance %p\n", __PRETTY_FUNCTION__, anInstance);
+ return;
+ }
+
+ jstring className = (jstring)callJNIObjectMethod(aClass, "getName", "()Ljava/lang/String;");
+ const char *classNameC = getCharactersFromJString(className);
+ _name = strdup(classNameC);
+ releaseCharactersForJString(className, classNameC);
+
+ int i;
+ JNIEnv *env = getJNIEnv();
+
+ // Get the fields
+ jarray fields = (jarray)callJNIObjectMethod(aClass, "getFields", "()[Ljava/lang/reflect/Field;");
+ int numFields = env->GetArrayLength(fields);
+ for (i = 0; i < numFields; i++) {
+ jobject aJField = env->GetObjectArrayElement((jobjectArray)fields, i);
+ Field *aField = new JavaField(env, aJField); // deleted in the JavaClass destructor
+ {
+ JSLock lock;
+ _fields.set(Identifier(aField->name()).ustring().rep(), aField);
+ }
+ env->DeleteLocalRef(aJField);
+ }
+
+ // Get the methods
+ jarray methods = (jarray)callJNIObjectMethod(aClass, "getMethods", "()[Ljava/lang/reflect/Method;");
+ int numMethods = env->GetArrayLength(methods);
+ for (i = 0; i < numMethods; i++) {
+ jobject aJMethod = env->GetObjectArrayElement((jobjectArray)methods, i);
+ Method *aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor
+ MethodList* methodList;
+ {
+ JSLock lock;
+
+ methodList = _methods.get(Identifier(aMethod->name()).ustring().rep());
+ if (!methodList) {
+ methodList = new MethodList();
+ _methods.set(Identifier(aMethod->name()).ustring().rep(), methodList);
+ }
+ }
+ methodList->append(aMethod);
+ env->DeleteLocalRef(aJMethod);
+ }
+}
+
+JavaClass::~JavaClass() {
+ free((void *)_name);
+
+ JSLock lock;
+
+ deleteAllValues(_fields);
+ _fields.clear();
+
+ MethodListMap::const_iterator end = _methods.end();
+ for (MethodListMap::const_iterator it = _methods.begin(); it != end; ++it) {
+ const MethodList* methodList = it->second;
+ deleteAllValues(*methodList);
+ delete methodList;
+ }
+ _methods.clear();
+}
+
+MethodList JavaClass::methodsNamed(const Identifier& identifier, Instance*) const
+{
+ MethodList *methodList = _methods.get(identifier.ustring().rep());
+
+ if (methodList)
+ return *methodList;
+ return MethodList();
+}
+
+Field *JavaClass::fieldNamed(const Identifier& identifier, Instance*) const
+{
+ return _fields.get(identifier.ustring().rep());
+}
+
+bool JavaClass::isNumberClass() const
+{
+ return ((strcmp(_name, "java.lang.Byte") == 0 ||
+ strcmp(_name, "java.lang.Short") == 0 ||
+ strcmp(_name, "java.lang.Integer") == 0 ||
+ strcmp(_name, "java.lang.Long") == 0 ||
+ strcmp(_name, "java.lang.Float") == 0 ||
+ strcmp(_name, "java.lang.Double") == 0) );
+}
+
+bool JavaClass::isBooleanClass() const
+{
+ return strcmp(_name, "java.lang.Boolean") == 0;
+}
+
+bool JavaClass::isStringClass() const
+{
+ return strcmp(_name, "java.lang.String") == 0;
+}
diff --git a/JavaScriptCore/bindings/jni/jni_class.h b/JavaScriptCore/bindings/jni/jni_class.h
new file mode 100644
index 0000000..7c5dbcc
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_class.h
@@ -0,0 +1,62 @@
+/*
+ * 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 JNI_CLASS_H_
+#define JNI_CLASS_H_
+
+#include <jni_runtime.h>
+#include <wtf/HashMap.h>
+
+namespace KJS {
+
+namespace Bindings {
+
+class JavaClass : public Class {
+public:
+ JavaClass (jobject anInstance);
+ ~JavaClass ();
+
+ virtual const char *name() const { return _name; };
+
+ virtual MethodList methodsNamed(const Identifier&, Instance* instance) const;
+ virtual Field *fieldNamed(const Identifier&, Instance* instance) const;
+
+ bool isNumberClass() const;
+ bool isBooleanClass() const;
+ bool isStringClass() const;
+
+private:
+ JavaClass (); // prevent default construction
+
+ const char *_name;
+ FieldMap _fields;
+ MethodListMap _methods;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif // JNI_CLASS_H_
diff --git a/JavaScriptCore/bindings/jni/jni_instance.cpp b/JavaScriptCore/bindings/jni/jni_instance.cpp
new file mode 100644
index 0000000..d5d89aa
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_instance.cpp
@@ -0,0 +1,353 @@
+/*
+ * 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.
+ */
+#include "config.h"
+
+#include "jni_class.h"
+#include "jni_instance.h"
+#include "jni_runtime.h"
+#include "jni_utility.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+
+#ifdef NDEBUG
+#define JS_LOG(formatAndArgs...) ((void)0)
+#else
+#define JS_LOG(formatAndArgs...) { \
+ fprintf (stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
+ fprintf(stderr, formatAndArgs); \
+}
+#endif
+
+using namespace KJS::Bindings;
+using namespace KJS;
+
+JavaInstance::JavaInstance (jobject instance, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+{
+ _instance = new JObjectWrapper (instance);
+ _class = 0;
+}
+
+JavaInstance::~JavaInstance ()
+{
+ delete _class;
+}
+
+#define NUM_LOCAL_REFS 64
+
+void JavaInstance::begin()
+{
+ getJNIEnv()->PushLocalFrame (NUM_LOCAL_REFS);
+}
+
+void JavaInstance::end()
+{
+ getJNIEnv()->PopLocalFrame (NULL);
+}
+
+Class *JavaInstance::getClass() const
+{
+ if (_class == 0)
+ _class = new JavaClass (_instance->_instance);
+ return _class;
+}
+
+JSValue *JavaInstance::stringValue() const
+{
+ JSLock lock;
+
+ jstring stringValue = (jstring)callJNIObjectMethod (_instance->_instance, "toString", "()Ljava/lang/String;");
+ JNIEnv *env = getJNIEnv();
+ const jchar *c = getUCharactersFromJStringInEnv(env, stringValue);
+ UString u((const UChar *)c, (int)env->GetStringLength(stringValue));
+ releaseUCharactersForJStringInEnv(env, stringValue, c);
+ return jsString(u);
+}
+
+JSValue *JavaInstance::numberValue() const
+{
+ jdouble doubleValue = callJNIDoubleMethod (_instance->_instance, "doubleValue", "()D");
+ return jsNumber(doubleValue);
+}
+
+JSValue *JavaInstance::booleanValue() const
+{
+ jboolean booleanValue = callJNIBooleanMethod (_instance->_instance, "booleanValue", "()Z");
+ return jsBoolean(booleanValue);
+}
+
+JSValue *JavaInstance::invokeMethod (ExecState *exec, const MethodList &methodList, const List &args)
+{
+ int i, count = args.size();
+ jvalue *jArgs;
+ JSValue *resultValue;
+ Method *method = 0;
+ size_t numMethods = methodList.size();
+
+ // Try to find a good match for the overloaded method. The
+ // fundamental problem is that JavaScript doesn have the
+ // notion of method overloading and Java does. We could
+ // get a bit more sophisticated and attempt to does some
+ // type checking as we as checking the number of parameters.
+ Method *aMethod;
+ for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) {
+ aMethod = methodList[methodIndex];
+ if (aMethod->numParameters() == count) {
+ method = aMethod;
+ break;
+ }
+ }
+ if (method == 0) {
+ JS_LOG ("unable to find an appropiate method\n");
+ return jsUndefined();
+ }
+
+ const JavaMethod *jMethod = static_cast<const JavaMethod*>(method);
+ JS_LOG ("call %s %s on %p\n", method->name(), jMethod->signature(), _instance->_instance);
+
+ if (count > 0) {
+ jArgs = (jvalue *)malloc (count * sizeof(jvalue));
+ }
+ else
+ jArgs = 0;
+
+ for (i = 0; i < count; i++) {
+ JavaParameter* aParameter = jMethod->parameterAt(i);
+ jArgs[i] = convertValueToJValue (exec, args.at(i), aParameter->getJNIType(), aParameter->type());
+ JS_LOG("arg[%d] = %s\n", i, args.at(i)->toString(exec).ascii());
+ }
+
+ jvalue result;
+
+ // Try to use the JNI abstraction first, otherwise fall back to
+ // nornmal JNI. The JNI dispatch abstraction allows the Java plugin
+ // to dispatch the call on the appropriate internal VM thread.
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return jsUndefined();
+
+ bool handled = false;
+ if (rootObject->nativeHandle()) {
+ jobject obj = _instance->_instance;
+ JSValue *exceptionDescription = NULL;
+ const char *callingURL = 0; // FIXME, need to propagate calling URL to Java
+ handled = dispatchJNICall(rootObject->nativeHandle(), obj, jMethod->isStatic(), jMethod->JNIReturnType(), jMethod->methodID(obj), jArgs, result, callingURL, exceptionDescription);
+ if (exceptionDescription) {
+ throwError(exec, GeneralError, exceptionDescription->toString(exec));
+ free (jArgs);
+ return jsUndefined();
+ }
+ }
+
+ // The following code can be conditionally removed once we have a Tiger update that
+ // contains the new Java plugin. It is needed for builds prior to Tiger.
+ if (!handled) {
+ jobject obj = _instance->_instance;
+ switch (jMethod->JNIReturnType()){
+ case void_type: {
+ callJNIVoidMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case object_type: {
+ result.l = callJNIObjectMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case boolean_type: {
+ result.z = callJNIBooleanMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case byte_type: {
+ result.b = callJNIByteMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case char_type: {
+ result.c = callJNICharMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case short_type: {
+ result.s = callJNIShortMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case int_type: {
+ result.i = callJNIIntMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case long_type: {
+ result.j = callJNILongMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case float_type: {
+ result.f = callJNIFloatMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case double_type: {
+ result.d = callJNIDoubleMethodIDA (obj, jMethod->methodID(obj), jArgs);
+ }
+ break;
+
+ case invalid_type:
+ default: {
+ }
+ break;
+ }
+ }
+
+ switch (jMethod->JNIReturnType()){
+ case void_type: {
+ resultValue = jsUndefined();
+ }
+ break;
+
+ case object_type: {
+ if (result.l != 0) {
+ const char *arrayType = jMethod->returnType();
+ if (arrayType[0] == '[') {
+ resultValue = JavaArray::convertJObjectToArray(exec, result.l, arrayType, rootObject);
+ }
+ else {
+ resultValue = Instance::createRuntimeObject(Instance::JavaLanguage, result.l, rootObject);
+ }
+ }
+ else {
+ resultValue = jsUndefined();
+ }
+ }
+ break;
+
+ case boolean_type: {
+ resultValue = jsBoolean(result.z);
+ }
+ break;
+
+ case byte_type: {
+ resultValue = jsNumber(result.b);
+ }
+ break;
+
+ case char_type: {
+ resultValue = jsNumber(result.c);
+ }
+ break;
+
+ case short_type: {
+ resultValue = jsNumber(result.s);
+ }
+ break;
+
+ case int_type: {
+ resultValue = jsNumber(result.i);
+ }
+ break;
+
+ case long_type: {
+ resultValue = jsNumber(result.j);
+ }
+ break;
+
+ case float_type: {
+ resultValue = jsNumber(result.f);
+ }
+ break;
+
+ case double_type: {
+ resultValue = jsNumber(result.d);
+ }
+ break;
+
+ case invalid_type:
+ default: {
+ resultValue = jsUndefined();
+ }
+ break;
+ }
+
+ free (jArgs);
+
+ return resultValue;
+}
+
+JSValue *JavaInstance::defaultValue (JSType hint) const
+{
+ if (hint == StringType) {
+ return stringValue();
+ }
+ else if (hint == NumberType) {
+ return numberValue();
+ }
+ else if (hint == BooleanType) {
+ return booleanValue();
+ }
+ else if (hint == UnspecifiedType) {
+ JavaClass *aClass = static_cast<JavaClass*>(getClass());
+ if (aClass->isStringClass()) {
+ return stringValue();
+ }
+ else if (aClass->isNumberClass()) {
+ return numberValue();
+ }
+ else if (aClass->isBooleanClass()) {
+ return booleanValue();
+ }
+ }
+
+ return valueOf();
+}
+
+JSValue *JavaInstance::valueOf() const
+{
+ return stringValue();
+}
+
+JObjectWrapper::JObjectWrapper(jobject instance)
+: _refCount(0)
+{
+ assert (instance != 0);
+
+ // Cache the JNIEnv used to get the global ref for this java instanace.
+ // It'll be used to delete the reference.
+ _env = getJNIEnv();
+
+ _instance = _env->NewGlobalRef (instance);
+
+ JS_LOG ("new global ref %p for %p\n", _instance, instance);
+
+ if (_instance == NULL) {
+ fprintf (stderr, "%s: could not get GlobalRef for %p\n", __PRETTY_FUNCTION__, instance);
+ }
+}
+
+JObjectWrapper::~JObjectWrapper() {
+ JS_LOG ("deleting global ref %p\n", _instance);
+ _env->DeleteGlobalRef (_instance);
+}
diff --git a/JavaScriptCore/bindings/jni/jni_instance.h b/JavaScriptCore/bindings/jni/jni_instance.h
new file mode 100644
index 0000000..eb89e3f
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_instance.h
@@ -0,0 +1,98 @@
+/*
+ * 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 _JNI_INSTANCE_H_
+#define _JNI_INSTANCE_H_
+
+#include "runtime.h"
+
+#include <JavaVM/jni.h>
+
+
+namespace KJS {
+
+namespace Bindings {
+
+class JavaClass;
+
+class JObjectWrapper
+{
+friend class RefPtr<JObjectWrapper>;
+friend class JavaArray;
+friend class JavaField;
+friend class JavaInstance;
+friend class JavaMethod;
+
+protected:
+ JObjectWrapper(jobject instance);
+ ~JObjectWrapper();
+
+ void ref() { _refCount++; }
+ void deref()
+ {
+ if (--_refCount == 0)
+ delete this;
+ }
+
+ jobject _instance;
+
+private:
+ JNIEnv *_env;
+ unsigned int _refCount;
+};
+
+class JavaInstance : public Instance
+{
+public:
+ JavaInstance(jobject instance, PassRefPtr<RootObject>);
+ ~JavaInstance();
+
+ virtual Class *getClass() const;
+
+ virtual void begin();
+ virtual void end();
+
+ virtual JSValue *valueOf() const;
+ virtual JSValue *defaultValue (JSType hint) const;
+
+ virtual JSValue *invokeMethod (ExecState *exec, const MethodList &method, const List &args);
+
+ jobject javaInstance() const { return _instance->_instance; }
+
+ JSValue *stringValue() const;
+ JSValue *numberValue() const;
+ JSValue *booleanValue() const;
+
+ virtual BindingLanguage getBindingLanguage() const { return JavaLanguage; }
+
+private:
+ RefPtr<JObjectWrapper> _instance;
+ mutable JavaClass *_class;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/jni/jni_jsobject.cpp b/JavaScriptCore/bindings/jni/jni_jsobject.cpp
new file mode 100644
index 0000000..347f24f
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_jsobject.cpp
@@ -0,0 +1,585 @@
+/*
+ * 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.
+ */
+#include "config.h"
+
+#include "identifier.h"
+#include "internal.h"
+#include "interpreter.h"
+#include "jni_jsobject.h"
+#include "jni_runtime.h"
+#include "jni_utility.h"
+#include "JSGlobalObject.h"
+#include "list.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <wtf/Assertions.h>
+
+using namespace KJS::Bindings;
+using namespace KJS;
+
+#ifdef NDEBUG
+#define JS_LOG(formatAndArgs...) ((void)0)
+#else
+#define JS_LOG(formatAndArgs...) { \
+ fprintf (stderr, "%s(%p,%p): ", __PRETTY_FUNCTION__, RootObject::runLoop(), CFRunLoopGetCurrent()); \
+ fprintf(stderr, formatAndArgs); \
+}
+#endif
+
+#define UndefinedHandle 1
+
+static bool isJavaScriptThread()
+{
+ return (RootObject::runLoop() == CFRunLoopGetCurrent());
+}
+
+jvalue JavaJSObject::invoke (JSObjectCallContext *context)
+{
+ jvalue result;
+
+ bzero ((void *)&result, sizeof(jvalue));
+
+ if (!isJavaScriptThread()) {
+ // Send the call context to the thread that is allowed to
+ // call JavaScript.
+ RootObject::dispatchToJavaScriptThread(context);
+ result = context->result;
+ }
+ else {
+ jlong nativeHandle = context->nativeHandle;
+ if (nativeHandle == UndefinedHandle || nativeHandle == 0) {
+ return result;
+ }
+
+ if (context->type == CreateNative) {
+ result.j = JavaJSObject::createNative(nativeHandle);
+ }
+ else {
+ JSObject *imp = jlong_to_impptr(nativeHandle);
+ if (!findProtectingRootObject(imp)) {
+ fprintf (stderr, "%s:%d: Attempt to access JavaScript from destroyed applet, type %d.\n", __FILE__, __LINE__, context->type);
+ return result;
+ }
+
+ switch (context->type){
+ case Call: {
+ result.l = JavaJSObject(nativeHandle).call(context->string, context->args);
+ break;
+ }
+
+ case Eval: {
+ result.l = JavaJSObject(nativeHandle).eval(context->string);
+ break;
+ }
+
+ case GetMember: {
+ result.l = JavaJSObject(nativeHandle).getMember(context->string);
+ break;
+ }
+
+ case SetMember: {
+ JavaJSObject(nativeHandle).setMember(context->string, context->value);
+ break;
+ }
+
+ case RemoveMember: {
+ JavaJSObject(nativeHandle).removeMember(context->string);
+ break;
+ }
+
+ case GetSlot: {
+ result.l = JavaJSObject(nativeHandle).getSlot(context->index);
+ break;
+ }
+
+ case SetSlot: {
+ JavaJSObject(nativeHandle).setSlot(context->index, context->value);
+ break;
+ }
+
+ case ToString: {
+ result.l = (jobject) JavaJSObject(nativeHandle).toString();
+ break;
+ }
+
+ case Finalize: {
+ JavaJSObject(nativeHandle).finalize();
+ break;
+ }
+
+ default: {
+ fprintf (stderr, "%s: invalid JavaScript call\n", __PRETTY_FUNCTION__);
+ }
+ }
+ }
+ context->result = result;
+ }
+
+ return result;
+}
+
+
+JavaJSObject::JavaJSObject(jlong nativeJSObject)
+{
+ _imp = jlong_to_impptr(nativeJSObject);
+
+ ASSERT(_imp);
+ _rootObject = findProtectingRootObject(_imp);
+ ASSERT(_rootObject);
+}
+
+RootObject* JavaJSObject::rootObject() const
+{
+ return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
+}
+
+jobject JavaJSObject::call(jstring methodName, jobjectArray args) const
+{
+ JS_LOG ("methodName = %s\n", JavaString(methodName).UTF8String());
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ // Lookup the function object.
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+
+ Identifier identifier(JavaString(methodName).ustring());
+ JSValue *func = _imp->get (exec, identifier);
+ if (func->isUndefinedOrNull())
+ return 0;
+
+ // Call the function object.
+ JSObject *funcImp = static_cast<JSObject*>(func);
+ JSObject *thisObj = const_cast<JSObject*>(_imp);
+ List argList;
+ getListFromJArray(args, argList);
+ rootObject->globalObject()->startTimeoutCheck();
+ JSValue *result = funcImp->call(exec, thisObj, argList);
+ rootObject->globalObject()->stopTimeoutCheck();
+
+ return convertValueToJObject(result);
+}
+
+jobject JavaJSObject::eval(jstring script) const
+{
+ JS_LOG ("script = %s\n", JavaString(script).UTF8String());
+
+ JSObject *thisObj = const_cast<JSObject*>(_imp);
+ JSValue *result;
+
+ JSLock lock;
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ rootObject->globalObject()->startTimeoutCheck();
+ Completion completion = Interpreter::evaluate(rootObject->globalObject()->globalExec(), UString(), 0, JavaString(script).ustring(),thisObj);
+ rootObject->globalObject()->stopTimeoutCheck();
+ ComplType type = completion.complType();
+
+ if (type == Normal) {
+ result = completion.value();
+ if (!result)
+ result = jsUndefined();
+ } else
+ result = jsUndefined();
+
+ return convertValueToJObject (result);
+}
+
+jobject JavaJSObject::getMember(jstring memberName) const
+{
+ JS_LOG ("(%p) memberName = %s\n", _imp, JavaString(memberName).UTF8String());
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+
+ JSLock lock;
+ JSValue *result = _imp->get (exec, Identifier (JavaString(memberName).ustring()));
+
+ return convertValueToJObject(result);
+}
+
+void JavaJSObject::setMember(jstring memberName, jobject value) const
+{
+ JS_LOG ("memberName = %s, value = %p\n", JavaString(memberName).UTF8String(), value);
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+ _imp->put(exec, Identifier (JavaString(memberName).ustring()), convertJObjectToValue(value));
+}
+
+
+void JavaJSObject::removeMember(jstring memberName) const
+{
+ JS_LOG ("memberName = %s\n", JavaString(memberName).UTF8String());
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+ _imp->deleteProperty(exec, Identifier (JavaString(memberName).ustring()));
+}
+
+
+jobject JavaJSObject::getSlot(jint index) const
+{
+#ifdef __LP64__
+ JS_LOG ("index = %d\n", index);
+#else
+ JS_LOG ("index = %ld\n", index);
+#endif
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+
+ JSLock lock;
+ JSValue *result = _imp->get (exec, (unsigned)index);
+
+ return convertValueToJObject(result);
+}
+
+
+void JavaJSObject::setSlot(jint index, jobject value) const
+{
+#ifdef __LP64__
+ JS_LOG ("index = %d, value = %p\n", index, value);
+#else
+ JS_LOG ("index = %ld, value = %p\n", index, value);
+#endif
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock;
+ _imp->put(exec, (unsigned)index, convertJObjectToValue(value));
+}
+
+
+jstring JavaJSObject::toString() const
+{
+ JS_LOG ("\n");
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ JSLock lock;
+ JSObject *thisObj = const_cast<JSObject*>(_imp);
+ ExecState* exec = rootObject->globalObject()->globalExec();
+
+ return (jstring)convertValueToJValue (exec, thisObj, object_type, "java.lang.String").l;
+}
+
+void JavaJSObject::finalize() const
+{
+ if (RootObject* rootObject = this->rootObject())
+ rootObject->gcUnprotect(_imp);
+}
+
+// We're either creating a 'Root' object (via a call to JavaJSObject.getWindow()), or
+// another JavaJSObject.
+jlong JavaJSObject::createNative(jlong nativeHandle)
+{
+ JS_LOG ("nativeHandle = %d\n", (int)nativeHandle);
+
+ if (nativeHandle == UndefinedHandle)
+ return nativeHandle;
+
+ if (findProtectingRootObject(jlong_to_impptr(nativeHandle)))
+ return nativeHandle;
+
+ CreateRootObjectFunction createRootObject = RootObject::createRootObject();
+ if (!createRootObject)
+ return ptr_to_jlong(0);
+
+ RefPtr<RootObject> rootObject = createRootObject(jlong_to_ptr(nativeHandle));
+
+ // If rootObject is !NULL We must have been called via netscape.javascript.JavaJSObject.getWindow(),
+ // otherwise we are being called after creating a JavaJSObject in
+ // JavaJSObject::convertValueToJObject().
+ if (rootObject) {
+ JSObject* globalObject = rootObject->globalObject();
+ // We call gcProtect here to get the object into the root object's "protect set" which
+ // is used to test if a native handle is valid as well as getting the root object given the handle.
+ rootObject->gcProtect(globalObject);
+ return ptr_to_jlong(globalObject);
+ }
+
+ return nativeHandle;
+}
+
+jobject JavaJSObject::convertValueToJObject (JSValue *value) const
+{
+ JSLock lock;
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JNIEnv *env = getJNIEnv();
+ jobject result = 0;
+
+ // See section 22.7 of 'JavaScript: The Definitive Guide, 4th Edition',
+ // figure 22-5.
+ // number -> java.lang.Double
+ // string -> java.lang.String
+ // boolean -> java.lang.Boolean
+ // Java instance -> Java instance
+ // Everything else -> JavaJSObject
+
+ JSType type = value->type();
+ if (type == NumberType) {
+ jclass JSObjectClass = env->FindClass ("java/lang/Double");
+ jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(D)V");
+ if (constructorID != NULL) {
+ result = env->NewObject (JSObjectClass, constructorID, (jdouble)value->toNumber(exec));
+ }
+ }
+ else if (type == StringType) {
+ UString stringValue = value->toString(exec);
+ JNIEnv *env = getJNIEnv();
+ result = env->NewString ((const jchar *)stringValue.data(), stringValue.size());
+ }
+ else if (type == BooleanType) {
+ jclass JSObjectClass = env->FindClass ("java/lang/Boolean");
+ jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(Z)V");
+ if (constructorID != NULL) {
+ result = env->NewObject (JSObjectClass, constructorID, (jboolean)value->toBoolean(exec));
+ }
+ }
+ else {
+ // Create a JavaJSObject.
+ jlong nativeHandle;
+
+ if (type == ObjectType){
+ JSObject *imp = static_cast<JSObject*>(value);
+
+ // We either have a wrapper around a Java instance or a JavaScript
+ // object. If we have a wrapper around a Java instance, return that
+ // instance, otherwise create a new Java JavaJSObject with the JSObject*
+ // as it's nativeHandle.
+ if (imp->classInfo() && strcmp(imp->classInfo()->className, "RuntimeObject") == 0) {
+ RuntimeObjectImp *runtimeImp = static_cast<RuntimeObjectImp*>(value);
+ JavaInstance *runtimeInstance = static_cast<JavaInstance *>(runtimeImp->getInternalInstance());
+ if (!runtimeInstance)
+ return 0;
+
+ return runtimeInstance->javaInstance();
+ }
+ else {
+ nativeHandle = ptr_to_jlong(imp);
+ rootObject->gcProtect(imp);
+ }
+ }
+ // All other types will result in an undefined object.
+ else {
+ nativeHandle = UndefinedHandle;
+ }
+
+ // Now create the Java JavaJSObject. Look for the JavaJSObject in it's new (Tiger)
+ // location and in the original Java 1.4.2 location.
+ jclass JSObjectClass;
+
+ JSObjectClass = env->FindClass ("sun/plugin/javascript/webkit/JSObject");
+ if (!JSObjectClass) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ JSObjectClass = env->FindClass ("apple/applet/JSObject");
+ }
+
+ jmethodID constructorID = env->GetMethodID (JSObjectClass, "<init>", "(J)V");
+ if (constructorID != NULL) {
+ result = env->NewObject (JSObjectClass, constructorID, nativeHandle);
+ }
+ }
+
+ return result;
+}
+
+JSValue *JavaJSObject::convertJObjectToValue (jobject theObject) const
+{
+ // Instances of netscape.javascript.JSObject get converted back to
+ // JavaScript objects. All other objects are wrapped. It's not
+ // possible to pass primitive types from the Java to JavaScript.
+ // See section 22.7 of 'JavaScript: The Definitive Guide, 4th Edition',
+ // figure 22-4.
+ jobject classOfInstance = callJNIObjectMethod(theObject, "getClass", "()Ljava/lang/Class;");
+ jstring className = (jstring)callJNIObjectMethod(classOfInstance, "getName", "()Ljava/lang/String;");
+
+ // Only the sun.plugin.javascript.webkit.JSObject has a member called nativeJSObject. This class is
+ // created above to wrap internal browser objects. The constructor of this class takes the native
+ // pointer and stores it in this object, so that it can be retrieved below.
+ if (strcmp(JavaString(className).UTF8String(), "sun.plugin.javascript.webkit.JSObject") == 0) {
+ // Pull the nativeJSObject value from the Java instance. This is a
+ // pointer to the JSObject.
+ JNIEnv *env = getJNIEnv();
+ jfieldID fieldID = env->GetFieldID((jclass)classOfInstance, "nativeJSObject", "J");
+ if (fieldID == NULL) {
+ return jsUndefined();
+ }
+ jlong nativeHandle = env->GetLongField(theObject, fieldID);
+ if (nativeHandle == UndefinedHandle) {
+ return jsUndefined();
+ }
+ JSObject *imp = static_cast<JSObject*>(jlong_to_impptr(nativeHandle));
+ return imp;
+ }
+
+ JSLock lock;
+ JavaInstance* javaInstance = new JavaInstance(theObject, _rootObject);
+ return KJS::Bindings::Instance::createRuntimeObject(javaInstance);
+}
+
+void JavaJSObject::getListFromJArray(jobjectArray jArray, List& list) const
+{
+ JNIEnv *env = getJNIEnv();
+ int i, numObjects = jArray ? env->GetArrayLength (jArray) : 0;
+
+ for (i = 0; i < numObjects; i++) {
+ jobject anObject = env->GetObjectArrayElement ((jobjectArray)jArray, i);
+ if (anObject) {
+ list.append(convertJObjectToValue(anObject));
+ env->DeleteLocalRef (anObject);
+ }
+ else {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ }
+}
+
+extern "C" {
+
+jlong KJS_JSCreateNativeJSObject (JNIEnv*, jclass, jstring, jlong nativeHandle, jboolean)
+{
+ JSObjectCallContext context;
+ context.type = CreateNative;
+ context.nativeHandle = nativeHandle;
+ return JavaJSObject::invoke (&context).j;
+}
+
+void KJS_JSObject_JSFinalize (JNIEnv*, jclass, jlong nativeHandle)
+{
+ JSObjectCallContext context;
+ context.type = Finalize;
+ context.nativeHandle = nativeHandle;
+ JavaJSObject::invoke (&context);
+}
+
+jobject KJS_JSObject_JSObjectCall (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring methodName, jobjectArray args, jboolean)
+{
+ JSObjectCallContext context;
+ context.type = Call;
+ context.nativeHandle = nativeHandle;
+ context.string = methodName;
+ context.args = args;
+ return JavaJSObject::invoke (&context).l;
+}
+
+jobject KJS_JSObject_JSObjectEval (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jscript, jboolean)
+{
+ JSObjectCallContext context;
+ context.type = Eval;
+ context.nativeHandle = nativeHandle;
+ context.string = jscript;
+ return JavaJSObject::invoke (&context).l;
+}
+
+jobject KJS_JSObject_JSObjectGetMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jboolean)
+{
+ JSObjectCallContext context;
+ context.type = GetMember;
+ context.nativeHandle = nativeHandle;
+ context.string = jname;
+ return JavaJSObject::invoke (&context).l;
+}
+
+void KJS_JSObject_JSObjectSetMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jobject value, jboolean)
+{
+ JSObjectCallContext context;
+ context.type = SetMember;
+ context.nativeHandle = nativeHandle;
+ context.string = jname;
+ context.value = value;
+ JavaJSObject::invoke (&context);
+}
+
+void KJS_JSObject_JSObjectRemoveMember (JNIEnv*, jclass, jlong nativeHandle, jstring, jstring jname, jboolean)
+{
+ JSObjectCallContext context;
+ context.type = RemoveMember;
+ context.nativeHandle = nativeHandle;
+ context.string = jname;
+ JavaJSObject::invoke (&context);
+}
+
+jobject KJS_JSObject_JSObjectGetSlot (JNIEnv*, jclass, jlong nativeHandle, jstring, jint jindex, jboolean)
+{
+ JSObjectCallContext context;
+ context.type = GetSlot;
+ context.nativeHandle = nativeHandle;
+ context.index = jindex;
+ return JavaJSObject::invoke (&context).l;
+}
+
+void KJS_JSObject_JSObjectSetSlot (JNIEnv*, jclass, jlong nativeHandle, jstring, jint jindex, jobject value, jboolean)
+{
+ JSObjectCallContext context;
+ context.type = SetSlot;
+ context.nativeHandle = nativeHandle;
+ context.index = jindex;
+ context.value = value;
+ JavaJSObject::invoke (&context);
+}
+
+jstring KJS_JSObject_JSObjectToString (JNIEnv*, jclass, jlong nativeHandle)
+{
+ JSObjectCallContext context;
+ context.type = ToString;
+ context.nativeHandle = nativeHandle;
+ return (jstring)JavaJSObject::invoke (&context).l;
+}
+
+}
diff --git a/JavaScriptCore/bindings/jni/jni_jsobject.h b/JavaScriptCore/bindings/jni/jni_jsobject.h
new file mode 100644
index 0000000..75f37a2
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_jsobject.h
@@ -0,0 +1,123 @@
+/*
+ * 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 JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H
+#define JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <JavaVM/jni.h>
+#include <wtf/RefPtr.h>
+
+#define jlong_to_ptr(a) ((void*)(uintptr_t)(a))
+#define jlong_to_impptr(a) (static_cast<KJS::JSObject*>(((void*)(uintptr_t)(a))))
+#define ptr_to_jlong(a) ((jlong)(uintptr_t)(a))
+
+namespace KJS {
+
+class List;
+class JSObject;
+class JSValue;
+
+namespace Bindings {
+
+class RootObject;
+
+enum JSObjectCallType {
+ CreateNative,
+ Call,
+ Eval,
+ GetMember,
+ SetMember,
+ RemoveMember,
+ GetSlot,
+ SetSlot,
+ ToString,
+ Finalize
+};
+
+struct JSObjectCallContext
+{
+ JSObjectCallType type;
+ jlong nativeHandle;
+ jstring string;
+ jobjectArray args;
+ jint index;
+ jobject value;
+ CFRunLoopRef originatingLoop;
+ jvalue result;
+};
+
+class JavaJSObject
+{
+public:
+ JavaJSObject(jlong nativeHandle);
+
+ static jlong createNative(jlong nativeHandle);
+ jobject call(jstring methodName, jobjectArray args) const;
+ jobject eval(jstring script) const;
+ jobject getMember(jstring memberName) const;
+ void setMember(jstring memberName, jobject value) const;
+ void removeMember(jstring memberName) const;
+ jobject getSlot(jint index) const;
+ void setSlot(jint index, jobject value) const;
+ jstring toString() const;
+ void finalize() const;
+
+ static jvalue invoke(JSObjectCallContext*);
+
+ jobject convertValueToJObject(JSValue*) const;
+ JSValue* convertJObjectToValue(jobject) const;
+ void getListFromJArray(jobjectArray, List&) const;
+
+ RootObject* rootObject() const;
+
+private:
+ RefPtr<RootObject> _rootObject;
+ JSObject* _imp;
+};
+
+
+} // namespace Bindings
+
+} // namespace KJS
+
+extern "C" {
+
+// The Java VM calls these functions to handle calls to methods in Java's JSObject class.
+jlong KJS_JSCreateNativeJSObject(JNIEnv*, jclass, jstring jurl, jlong nativeHandle, jboolean ctx);
+void KJS_JSObject_JSFinalize(JNIEnv*, jclass, jlong nativeJSObject);
+jobject KJS_JSObject_JSObjectCall(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring methodName, jobjectArray args, jboolean ctx);
+jobject KJS_JSObject_JSObjectEval(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jscript, jboolean ctx);
+jobject KJS_JSObject_JSObjectGetMember(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jname, jboolean ctx);
+void KJS_JSObject_JSObjectSetMember(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jname, jobject value, jboolean ctx);
+void KJS_JSObject_JSObjectRemoveMember(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jstring jname, jboolean ctx);
+jobject KJS_JSObject_JSObjectGetSlot(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jint jindex, jboolean ctx);
+void KJS_JSObject_JSObjectSetSlot(JNIEnv*, jclass, jlong nativeJSObject, jstring jurl, jint jindex, jobject value, jboolean ctx);
+jstring KJS_JSObject_JSObjectToString(JNIEnv*, jclass, jlong nativeJSObject);
+
+}
+
+#endif
diff --git a/JavaScriptCore/bindings/jni/jni_objc.mm b/JavaScriptCore/bindings/jni/jni_objc.mm
new file mode 100644
index 0000000..43d2da0
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_objc.mm
@@ -0,0 +1,76 @@
+/*
+ * 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"
+#import <Foundation/Foundation.h>
+#import <JavaScriptCore/jni_utility.h>
+#import <JavaScriptCore/objc_utility.h>
+
+using namespace KJS::Bindings;
+
+@interface NSObject (WebScriptingPrivate)
+- (jvalue)webPlugInCallJava:(jobject)object method:(jmethodID)method returnType:(JNIType)returnType arguments:(jvalue*)args;
+- (jvalue)webPlugInCallJava:(jobject)object
+ isStatic:(BOOL)isStatic
+ returnType:(JNIType)returnType
+ method:(jmethodID)method
+ arguments:(jvalue*)args
+ callingURL:(NSURL *)url
+ exceptionDescription:(NSString **)exceptionString;
+@end
+
+bool KJS::Bindings::dispatchJNICall (const void *targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue *args, jvalue &result, const char*, JSValue *&exceptionDescription)
+{
+ id view = (id)targetAppletView;
+
+ // As array_type is not known by the Mac JVM, change it to a compatible type.
+ if (returnType == array_type)
+ returnType = object_type;
+
+ if ([view respondsToSelector:@selector(webPlugInCallJava:isStatic:returnType:method:arguments:callingURL:exceptionDescription:)]) {
+ NSString *_exceptionDescription = 0;
+
+ // Passing nil as the calling URL will cause the Java plugin to use the URL
+ // of the page that contains the applet. The execution restrictions
+ // implemented in WebCore will guarantee that only appropriate JavaScript
+ // can reference the applet.
+ {
+ JSLock::DropAllLocks dropAllLocks;
+ result = [view webPlugInCallJava:obj isStatic:isStatic returnType:returnType method:methodID arguments:args callingURL:nil exceptionDescription:&_exceptionDescription];
+ }
+
+ if (_exceptionDescription != 0) {
+ exceptionDescription = convertNSStringToString(_exceptionDescription);
+ }
+ return true;
+ }
+ else if ([view respondsToSelector:@selector(webPlugInCallJava:method:returnType:arguments:)]) {
+ JSLock::DropAllLocks dropAllLocks;
+ result = [view webPlugInCallJava:obj method:methodID returnType:returnType arguments:args];
+ return true;
+ }
+
+ bzero (&result, sizeof(jvalue));
+ return false;
+}
diff --git a/JavaScriptCore/bindings/jni/jni_runtime.cpp b/JavaScriptCore/bindings/jni/jni_runtime.cpp
new file mode 100644
index 0000000..7d7cb31
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_runtime.cpp
@@ -0,0 +1,545 @@
+/*
+ * 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.
+ */
+#include "config.h"
+#include <internal.h>
+#include <ustring.h>
+#include <value.h>
+
+#include <jni_utility.h>
+#include <jni_runtime.h>
+
+#include <runtime_array.h>
+#include <runtime_object.h>
+#include <runtime_root.h>
+
+#ifdef NDEBUG
+#define JS_LOG(formatAndArgs...) ((void)0)
+#else
+#define JS_LOG(formatAndArgs...) { \
+ fprintf (stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
+ fprintf(stderr, formatAndArgs); \
+}
+#endif
+
+using namespace KJS;
+using namespace KJS::Bindings;
+
+
+JavaParameter::JavaParameter (JNIEnv *env, jstring type)
+{
+ _type = JavaString (env, type);
+ _JNIType = JNITypeFromClassName (_type.UTF8String());
+}
+
+JavaField::JavaField (JNIEnv *env, jobject aField)
+{
+ // Get field type
+ jobject fieldType = callJNIObjectMethod (aField, "getType", "()Ljava/lang/Class;");
+ jstring fieldTypeName = (jstring)callJNIObjectMethod (fieldType, "getName", "()Ljava/lang/String;");
+ _type = JavaString(env, fieldTypeName);
+ _JNIType = JNITypeFromClassName (_type.UTF8String());
+
+ // Get field name
+ jstring fieldName = (jstring)callJNIObjectMethod (aField, "getName", "()Ljava/lang/String;");
+ _name = JavaString(env, fieldName);
+
+ _field = new JObjectWrapper(aField);
+}
+
+JSValue* JavaArray::convertJObjectToArray(ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject> rootObject)
+{
+ if (type[0] != '[')
+ return jsUndefined();
+
+ return new RuntimeArray(exec, new JavaArray((jobject)anObject, type, rootObject));
+}
+
+jvalue JavaField::dispatchValueFromInstance(ExecState *exec, const JavaInstance *instance, const char *name, const char *sig, JNIType returnType) const
+{
+ jobject jinstance = instance->javaInstance();
+ jobject fieldJInstance = _field->_instance;
+ JNIEnv *env = getJNIEnv();
+ jvalue result;
+
+ bzero (&result, sizeof(jvalue));
+ jclass cls = env->GetObjectClass(fieldJInstance);
+ if ( cls != NULL ) {
+ jmethodID mid = env->GetMethodID(cls, name, sig);
+ if ( mid != NULL )
+ {
+ RootObject* rootObject = instance->rootObject();
+ if (rootObject && rootObject->nativeHandle()) {
+ JSValue *exceptionDescription = NULL;
+ jvalue args[1];
+
+ args[0].l = jinstance;
+ dispatchJNICall(rootObject->nativeHandle(), fieldJInstance, false, returnType, mid, args, result, 0, exceptionDescription);
+ if (exceptionDescription)
+ throwError(exec, GeneralError, exceptionDescription->toString(exec));
+ }
+ }
+ }
+ return result;
+}
+
+JSValue *JavaField::valueFromInstance(ExecState *exec, const Instance *i) const
+{
+ const JavaInstance *instance = static_cast<const JavaInstance *>(i);
+
+ JSValue *jsresult = jsUndefined();
+
+ switch (_JNIType) {
+ case array_type:
+ case object_type: {
+ jvalue result = dispatchValueFromInstance (exec, instance, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", object_type);
+ jobject anObject = result.l;
+
+ const char *arrayType = type();
+ if (arrayType[0] == '[') {
+ jsresult = JavaArray::convertJObjectToArray(exec, anObject, arrayType, instance->rootObject());
+ }
+ else if (anObject != 0){
+ jsresult = Instance::createRuntimeObject(Instance::JavaLanguage, anObject, instance->rootObject());
+ }
+ }
+ break;
+
+ case boolean_type:
+ jsresult = jsBoolean(dispatchValueFromInstance(exec, instance, "getBoolean", "(Ljava/lang/Object;)Z", boolean_type).z);
+ break;
+
+ case byte_type:
+ case char_type:
+ case short_type:
+
+ case int_type: {
+ jint value;
+ jvalue result = dispatchValueFromInstance (exec, instance, "getInt", "(Ljava/lang/Object;)I", int_type);
+ value = result.i;
+ jsresult = jsNumber((int)value);
+ }
+ break;
+
+ case long_type:
+ case float_type:
+ case double_type: {
+ jdouble value;
+ jvalue result = dispatchValueFromInstance (exec, instance, "getDouble", "(Ljava/lang/Object;)D", double_type);
+ value = result.i;
+ jsresult = jsNumber((double)value);
+ }
+ break;
+ default:
+ break;
+ }
+
+ JS_LOG ("getting %s = %s\n", name(), jsresult->toString(exec).ascii());
+
+ return jsresult;
+}
+
+void JavaField::dispatchSetValueToInstance(ExecState *exec, const JavaInstance *instance, jvalue javaValue, const char *name, const char *sig) const
+{
+ jobject jinstance = instance->javaInstance();
+ jobject fieldJInstance = _field->_instance;
+ JNIEnv *env = getJNIEnv();
+
+ jclass cls = env->GetObjectClass(fieldJInstance);
+ if ( cls != NULL ) {
+ jmethodID mid = env->GetMethodID(cls, name, sig);
+ if ( mid != NULL )
+ {
+ RootObject* rootObject = instance->rootObject();
+ if (rootObject && rootObject->nativeHandle()) {
+ JSValue *exceptionDescription = NULL;
+ jvalue args[2];
+ jvalue result;
+
+ args[0].l = jinstance;
+ args[1] = javaValue;
+ dispatchJNICall(rootObject->nativeHandle(), fieldJInstance, false, void_type, mid, args, result, 0, exceptionDescription);
+ if (exceptionDescription)
+ throwError(exec, GeneralError, exceptionDescription->toString(exec));
+ }
+ }
+ }
+}
+
+void JavaField::setValueToInstance(ExecState *exec, const Instance *i, JSValue *aValue) const
+{
+ const JavaInstance *instance = static_cast<const JavaInstance *>(i);
+ jvalue javaValue = convertValueToJValue (exec, aValue, _JNIType, type());
+
+ JS_LOG ("setting value %s to %s\n", name(), aValue->toString(exec).ascii());
+
+ switch (_JNIType) {
+ case array_type:
+ case object_type: {
+ dispatchSetValueToInstance (exec, instance, javaValue, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V");
+ }
+ break;
+
+ case boolean_type: {
+ dispatchSetValueToInstance (exec, instance, javaValue, "setBoolean", "(Ljava/lang/Object;Z)V");
+ }
+ break;
+
+ case byte_type: {
+ dispatchSetValueToInstance (exec, instance, javaValue, "setByte", "(Ljava/lang/Object;B)V");
+ }
+ break;
+
+ case char_type: {
+ dispatchSetValueToInstance (exec, instance, javaValue, "setChar", "(Ljava/lang/Object;C)V");
+ }
+ break;
+
+ case short_type: {
+ dispatchSetValueToInstance (exec, instance, javaValue, "setShort", "(Ljava/lang/Object;S)V");
+ }
+ break;
+
+ case int_type: {
+ dispatchSetValueToInstance (exec, instance, javaValue, "setInt", "(Ljava/lang/Object;I)V");
+ }
+ break;
+
+ case long_type: {
+ dispatchSetValueToInstance (exec, instance, javaValue, "setLong", "(Ljava/lang/Object;J)V");
+ }
+ break;
+
+ case float_type: {
+ dispatchSetValueToInstance (exec, instance, javaValue, "setFloat", "(Ljava/lang/Object;F)V");
+ }
+ break;
+
+ case double_type: {
+ dispatchSetValueToInstance (exec, instance, javaValue, "setDouble", "(Ljava/lang/Object;D)V");
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+JavaMethod::JavaMethod (JNIEnv *env, jobject aMethod)
+{
+ // Get return type
+ jobject returnType = callJNIObjectMethod (aMethod, "getReturnType", "()Ljava/lang/Class;");
+ jstring returnTypeName = (jstring)callJNIObjectMethod (returnType, "getName", "()Ljava/lang/String;");
+ _returnType =JavaString (env, returnTypeName);
+ _JNIReturnType = JNITypeFromClassName (_returnType.UTF8String());
+ env->DeleteLocalRef (returnType);
+ env->DeleteLocalRef (returnTypeName);
+
+ // Get method name
+ jstring methodName = (jstring)callJNIObjectMethod (aMethod, "getName", "()Ljava/lang/String;");
+ _name = JavaString (env, methodName);
+ env->DeleteLocalRef (methodName);
+
+ // Get parameters
+ jarray jparameters = (jarray)callJNIObjectMethod (aMethod, "getParameterTypes", "()[Ljava/lang/Class;");
+ _numParameters = env->GetArrayLength (jparameters);
+ _parameters = new JavaParameter[_numParameters];
+
+ int i;
+ for (i = 0; i < _numParameters; i++) {
+ jobject aParameter = env->GetObjectArrayElement ((jobjectArray)jparameters, i);
+ jstring parameterName = (jstring)callJNIObjectMethod (aParameter, "getName", "()Ljava/lang/String;");
+ _parameters[i] = JavaParameter(env, parameterName);
+ env->DeleteLocalRef (aParameter);
+ env->DeleteLocalRef (parameterName);
+ }
+ env->DeleteLocalRef (jparameters);
+
+ // Created lazily.
+ _signature = 0;
+ _methodID = 0;
+
+ jclass modifierClass = env->FindClass("java/lang/reflect/Modifier");
+ int modifiers = callJNIIntMethod (aMethod, "getModifiers", "()I");
+ _isStatic = (bool)callJNIStaticBooleanMethod (modifierClass, "isStatic", "(I)Z", modifiers);
+}
+
+JavaMethod::~JavaMethod()
+{
+ if (_signature)
+ free(_signature);
+ delete [] _parameters;
+};
+
+// JNI method signatures use '/' between components of a class name, but
+// we get '.' between components from the reflection API.
+static void appendClassName(UString& aString, const char* className)
+{
+ ASSERT(JSLock::lockCount() > 0);
+
+ char *result, *cp = strdup(className);
+
+ result = cp;
+ while (*cp) {
+ if (*cp == '.')
+ *cp = '/';
+ cp++;
+ }
+
+ aString.append(result);
+
+ free (result);
+}
+
+const char *JavaMethod::signature() const
+{
+ if (!_signature) {
+ JSLock lock;
+
+ UString signatureBuilder("(");
+ for (int i = 0; i < _numParameters; i++) {
+ JavaParameter* aParameter = parameterAt(i);
+ JNIType _JNIType = aParameter->getJNIType();
+ if (_JNIType == array_type)
+ appendClassName(signatureBuilder, aParameter->type());
+ else {
+ signatureBuilder.append(signatureFromPrimitiveType(_JNIType));
+ if (_JNIType == object_type) {
+ appendClassName(signatureBuilder, aParameter->type());
+ signatureBuilder.append(";");
+ }
+ }
+ }
+ signatureBuilder.append(")");
+
+ const char *returnType = _returnType.UTF8String();
+ if (_JNIReturnType == array_type) {
+ appendClassName(signatureBuilder, returnType);
+ } else {
+ signatureBuilder.append(signatureFromPrimitiveType(_JNIReturnType));
+ if (_JNIReturnType == object_type) {
+ appendClassName(signatureBuilder, returnType);
+ signatureBuilder.append(";");
+ }
+ }
+
+ _signature = strdup(signatureBuilder.ascii());
+ }
+
+ return _signature;
+}
+
+JNIType JavaMethod::JNIReturnType() const
+{
+ return _JNIReturnType;
+}
+
+jmethodID JavaMethod::methodID (jobject obj) const
+{
+ if (_methodID == 0) {
+ _methodID = getMethodID (obj, name(), signature());
+ }
+ return _methodID;
+}
+
+
+JavaArray::JavaArray(jobject array, const char* type, PassRefPtr<RootObject> rootObject)
+ : Array(rootObject)
+{
+ _array = new JObjectWrapper(array);
+ // Java array are fixed length, so we can cache length.
+ JNIEnv *env = getJNIEnv();
+ _length = env->GetArrayLength((jarray)_array->_instance);
+ _type = strdup(type);
+ _rootObject = rootObject;
+}
+
+JavaArray::~JavaArray ()
+{
+ free ((void *)_type);
+}
+
+RootObject* JavaArray::rootObject() const
+{
+ return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
+}
+
+void JavaArray::setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const
+{
+ JNIEnv *env = getJNIEnv();
+ char *javaClassName = 0;
+
+ JNIType arrayType = JNITypeFromPrimitiveType(_type[1]);
+ if (_type[1] == 'L'){
+ // The type of the array will be something like:
+ // "[Ljava.lang.string;". This is guaranteed, so no need
+ // for extra sanity checks.
+ javaClassName = strdup(&_type[2]);
+ javaClassName[strchr(javaClassName, ';')-javaClassName] = 0;
+ }
+ jvalue aJValue = convertValueToJValue (exec, aValue, arrayType, javaClassName);
+
+ switch (arrayType) {
+ case object_type: {
+ env->SetObjectArrayElement((jobjectArray)javaArray(), index, aJValue.l);
+ break;
+ }
+
+ case boolean_type: {
+ env->SetBooleanArrayRegion((jbooleanArray)javaArray(), index, 1, &aJValue.z);
+ break;
+ }
+
+ case byte_type: {
+ env->SetByteArrayRegion((jbyteArray)javaArray(), index, 1, &aJValue.b);
+ break;
+ }
+
+ case char_type: {
+ env->SetCharArrayRegion((jcharArray)javaArray(), index, 1, &aJValue.c);
+ break;
+ }
+
+ case short_type: {
+ env->SetShortArrayRegion((jshortArray)javaArray(), index, 1, &aJValue.s);
+ break;
+ }
+
+ case int_type: {
+ env->SetIntArrayRegion((jintArray)javaArray(), index, 1, &aJValue.i);
+ break;
+ }
+
+ case long_type: {
+ env->SetLongArrayRegion((jlongArray)javaArray(), index, 1, &aJValue.j);
+ }
+
+ case float_type: {
+ env->SetFloatArrayRegion((jfloatArray)javaArray(), index, 1, &aJValue.f);
+ break;
+ }
+
+ case double_type: {
+ env->SetDoubleArrayRegion((jdoubleArray)javaArray(), index, 1, &aJValue.d);
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (javaClassName)
+ free ((void *)javaClassName);
+}
+
+
+JSValue *JavaArray::valueAt(ExecState *exec, unsigned int index) const
+{
+ JNIEnv *env = getJNIEnv();
+ JNIType arrayType = JNITypeFromPrimitiveType(_type[1]);
+ switch (arrayType) {
+ case object_type: {
+ jobjectArray objectArray = (jobjectArray)javaArray();
+ jobject anObject;
+ anObject = env->GetObjectArrayElement(objectArray, index);
+
+ // No object?
+ if (!anObject) {
+ return jsNull();
+ }
+
+ // Nested array?
+ if (_type[1] == '[') {
+ return JavaArray::convertJObjectToArray(exec, anObject, _type+1, rootObject());
+ }
+ // or array of other object type?
+ return Instance::createRuntimeObject(Instance::JavaLanguage, anObject, rootObject());
+ }
+
+ case boolean_type: {
+ jbooleanArray booleanArray = (jbooleanArray)javaArray();
+ jboolean aBoolean;
+ env->GetBooleanArrayRegion(booleanArray, index, 1, &aBoolean);
+ return jsBoolean(aBoolean);
+ }
+
+ case byte_type: {
+ jbyteArray byteArray = (jbyteArray)javaArray();
+ jbyte aByte;
+ env->GetByteArrayRegion(byteArray, index, 1, &aByte);
+ return jsNumber(aByte);
+ }
+
+ case char_type: {
+ jcharArray charArray = (jcharArray)javaArray();
+ jchar aChar;
+ env->GetCharArrayRegion(charArray, index, 1, &aChar);
+ return jsNumber(aChar);
+ break;
+ }
+
+ case short_type: {
+ jshortArray shortArray = (jshortArray)javaArray();
+ jshort aShort;
+ env->GetShortArrayRegion(shortArray, index, 1, &aShort);
+ return jsNumber(aShort);
+ }
+
+ case int_type: {
+ jintArray intArray = (jintArray)javaArray();
+ jint anInt;
+ env->GetIntArrayRegion(intArray, index, 1, &anInt);
+ return jsNumber(anInt);
+ }
+
+ case long_type: {
+ jlongArray longArray = (jlongArray)javaArray();
+ jlong aLong;
+ env->GetLongArrayRegion(longArray, index, 1, &aLong);
+ return jsNumber(aLong);
+ }
+
+ case float_type: {
+ jfloatArray floatArray = (jfloatArray)javaArray();
+ jfloat aFloat;
+ env->GetFloatArrayRegion(floatArray, index, 1, &aFloat);
+ return jsNumber(aFloat);
+ }
+
+ case double_type: {
+ jdoubleArray doubleArray = (jdoubleArray)javaArray();
+ jdouble aDouble;
+ env->GetDoubleArrayRegion(doubleArray, index, 1, &aDouble);
+ return jsNumber(aDouble);
+ }
+ default:
+ break;
+ }
+ return jsUndefined();
+}
+
+unsigned int JavaArray::getLength() const
+{
+ return _length;
+}
+
+
diff --git a/JavaScriptCore/bindings/jni/jni_runtime.h b/JavaScriptCore/bindings/jni/jni_runtime.h
new file mode 100644
index 0000000..9ea1371
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_runtime.h
@@ -0,0 +1,185 @@
+/*
+ * 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 _JNI_RUNTIME_H_
+#define _JNI_RUNTIME_H_
+
+#include <jni_utility.h>
+#include <jni_instance.h>
+
+
+namespace KJS
+{
+
+namespace Bindings
+{
+
+typedef const char* RuntimeType;
+
+class JavaString
+{
+public:
+ JavaString()
+ {
+ JSLock lock;
+ _rep = UString().rep();
+ }
+
+ void _commonInit (JNIEnv *e, jstring s)
+ {
+ int _size = e->GetStringLength (s);
+ const jchar *uc = getUCharactersFromJStringInEnv (e, s);
+ {
+ JSLock lock;
+ _rep = UString((UChar *)uc,_size).rep();
+ }
+ releaseUCharactersForJStringInEnv (e, s, uc);
+ }
+
+ JavaString (JNIEnv *e, jstring s) {
+ _commonInit (e, s);
+ }
+
+ JavaString (jstring s) {
+ _commonInit (getJNIEnv(), s);
+ }
+
+ ~JavaString()
+ {
+ JSLock lock;
+ _rep = 0;
+ }
+
+ const char *UTF8String() const {
+ if (_utf8String.c_str() == 0) {
+ JSLock lock;
+ _utf8String = UString(_rep).UTF8String();
+ }
+ return _utf8String.c_str();
+ }
+ const jchar *uchars() const { return (const jchar *)_rep->data(); }
+ int length() const { return _rep->size(); }
+ UString ustring() const { return UString(_rep); }
+
+private:
+ RefPtr<UString::Rep> _rep;
+ mutable CString _utf8String;
+};
+
+class JavaParameter
+{
+public:
+ JavaParameter () : _JNIType(invalid_type) {};
+ JavaParameter (JNIEnv *env, jstring type);
+ virtual ~JavaParameter() { }
+
+ RuntimeType type() const { return _type.UTF8String(); }
+ JNIType getJNIType() const { return _JNIType; }
+
+private:
+ JavaString _type;
+ JNIType _JNIType;
+};
+
+
+class JavaField : public Field
+{
+public:
+ JavaField (JNIEnv *env, jobject aField);
+
+ virtual JSValue *valueFromInstance(ExecState *exec, const Instance *instance) const;
+ virtual void setValueToInstance(ExecState *exec, const Instance *instance, JSValue *aValue) const;
+
+ virtual const char *name() const { return _name.UTF8String(); }
+ virtual RuntimeType type() const { return _type.UTF8String(); }
+
+ JNIType getJNIType() const { return _JNIType; }
+
+private:
+ void dispatchSetValueToInstance(ExecState *exec, const JavaInstance *instance, jvalue javaValue, const char *name, const char *sig) const;
+ jvalue dispatchValueFromInstance(ExecState *exec, const JavaInstance *instance, const char *name, const char *sig, JNIType returnType) const;
+
+ JavaString _name;
+ JavaString _type;
+ JNIType _JNIType;
+ RefPtr<JObjectWrapper> _field;
+};
+
+
+class JavaMethod : public Method
+{
+public:
+ JavaMethod(JNIEnv* env, jobject aMethod);
+ ~JavaMethod();
+
+ virtual const char *name() const { return _name.UTF8String(); };
+ RuntimeType returnType() const { return _returnType.UTF8String(); };
+ JavaParameter* parameterAt(int i) const { return &_parameters[i]; };
+ int numParameters() const { return _numParameters; };
+
+ const char *signature() const;
+ JNIType JNIReturnType() const;
+
+ jmethodID methodID (jobject obj) const;
+
+ bool isStatic() const { return _isStatic; }
+
+private:
+ JavaParameter* _parameters;
+ int _numParameters;
+ JavaString _name;
+ mutable char* _signature;
+ JavaString _returnType;
+ JNIType _JNIReturnType;
+ mutable jmethodID _methodID;
+ bool _isStatic;
+};
+
+class JavaArray : public Array
+{
+public:
+ JavaArray(jobject array, const char* type, PassRefPtr<RootObject>);
+ virtual ~JavaArray();
+
+ RootObject* rootObject() const;
+
+ 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;
+
+ jobject javaArray() const { return _array->_instance; }
+
+ static JSValue* convertJObjectToArray (ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject>);
+
+private:
+ RefPtr<JObjectWrapper> _array;
+ unsigned int _length;
+ const char *_type;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/jni/jni_utility.cpp b/JavaScriptCore/bindings/jni/jni_utility.cpp
new file mode 100644
index 0000000..8a8c656
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_utility.cpp
@@ -0,0 +1,987 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "jni_utility.h"
+
+#include "list.h"
+#include "jni_runtime.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include <dlfcn.h>
+
+namespace KJS {
+
+namespace Bindings {
+
+static jint KJS_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs)
+{
+ static void* javaVMFramework = 0;
+ if (!javaVMFramework)
+ javaVMFramework = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM", RTLD_LAZY);
+ if (!javaVMFramework)
+ return JNI_ERR;
+
+ static jint(*functionPointer)(JavaVM**, jsize, jsize *) = 0;
+ if (!functionPointer)
+ functionPointer = (jint(*)(JavaVM**, jsize, jsize *))dlsym(javaVMFramework, "JNI_GetCreatedJavaVMs");
+ if (!functionPointer)
+ return JNI_ERR;
+ return functionPointer(vmBuf, bufLen, nVMs);
+}
+
+static JavaVM *jvm = 0;
+
+// Provide the ability for an outside component to specify the JavaVM to use
+// If the jvm value is set, the getJavaVM function below will just return.
+// In getJNIEnv(), if AttachCurrentThread is called to a VM that is already
+// attached, the result is a no-op.
+void setJavaVM(JavaVM *javaVM)
+{
+ jvm = javaVM;
+}
+
+JavaVM *getJavaVM()
+{
+ if (jvm)
+ return jvm;
+
+ JavaVM *jvmArray[1];
+ jsize bufLen = 1;
+ jsize nJVMs = 0;
+ jint jniError = 0;
+
+ // Assumes JVM is already running ..., one per process
+ jniError = KJS_GetCreatedJavaVMs(jvmArray, bufLen, &nJVMs);
+ if ( jniError == JNI_OK && nJVMs > 0 ) {
+ jvm = jvmArray[0];
+ }
+ else
+ fprintf(stderr, "%s: JNI_GetCreatedJavaVMs failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError);
+
+ return jvm;
+}
+
+JNIEnv* getJNIEnv()
+{
+ union {
+ JNIEnv* env;
+ void* dummy;
+ } u;
+ jint jniError = 0;
+
+ jniError = (getJavaVM())->AttachCurrentThread(&u.dummy, NULL);
+ if (jniError == JNI_OK)
+ return u.env;
+ else
+ fprintf(stderr, "%s: AttachCurrentThread failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError);
+ return NULL;
+}
+
+static jvalue callJNIMethod (JNIType type, jobject obj, const char *name, const char *sig, va_list args)
+{
+ JavaVM *jvm = getJavaVM();
+ JNIEnv *env = getJNIEnv();
+ jvalue result;
+
+ bzero (&result, sizeof(jvalue));
+ if ( obj != NULL && jvm != NULL && env != NULL) {
+ jclass cls = env->GetObjectClass(obj);
+ if ( cls != NULL ) {
+ jmethodID mid = env->GetMethodID(cls, name, sig);
+ if ( mid != NULL )
+ {
+ switch (type) {
+ case void_type:
+ env->functions->CallVoidMethodV(env, obj, mid, args);
+ break;
+ case array_type:
+ case object_type:
+ result.l = env->functions->CallObjectMethodV(env, obj, mid, args);
+ break;
+ case boolean_type:
+ result.z = env->functions->CallBooleanMethodV(env, obj, mid, args);
+ break;
+ case byte_type:
+ result.b = env->functions->CallByteMethodV(env, obj, mid, args);
+ break;
+ case char_type:
+ result.c = env->functions->CallCharMethodV(env, obj, mid, args);
+ break;
+ case short_type:
+ result.s = env->functions->CallShortMethodV(env, obj, mid, args);
+ break;
+ case int_type:
+ result.i = env->functions->CallIntMethodV(env, obj, mid, args);
+ break;
+ case long_type:
+ result.j = env->functions->CallLongMethodV(env, obj, mid, args);
+ break;
+ case float_type:
+ result.f = env->functions->CallFloatMethodV(env, obj, mid, args);
+ break;
+ case double_type:
+ result.d = env->functions->CallDoubleMethodV(env, obj, mid, args);
+ break;
+ default:
+ fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, obj);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf (stderr, "\n");
+ }
+
+ env->DeleteLocalRef(cls);
+ }
+ else {
+ fprintf(stderr, "%s: Could not find class for %p\n", __PRETTY_FUNCTION__, obj);
+ }
+ }
+
+ return result;
+}
+
+static jvalue callJNIStaticMethod (JNIType type, jclass cls, const char *name, const char *sig, va_list args)
+{
+ JavaVM *jvm = getJavaVM();
+ JNIEnv *env = getJNIEnv();
+ jvalue result;
+
+ bzero (&result, sizeof(jvalue));
+ if ( cls != NULL && jvm != NULL && env != NULL) {
+ jmethodID mid = env->GetStaticMethodID(cls, name, sig);
+ if ( mid != NULL )
+ {
+ switch (type) {
+ case void_type:
+ env->functions->CallStaticVoidMethodV(env, cls, mid, args);
+ break;
+ case array_type:
+ case object_type:
+ result.l = env->functions->CallStaticObjectMethodV(env, cls, mid, args);
+ break;
+ case boolean_type:
+ result.z = env->functions->CallStaticBooleanMethodV(env, cls, mid, args);
+ break;
+ case byte_type:
+ result.b = env->functions->CallStaticByteMethodV(env, cls, mid, args);
+ break;
+ case char_type:
+ result.c = env->functions->CallStaticCharMethodV(env, cls, mid, args);
+ break;
+ case short_type:
+ result.s = env->functions->CallStaticShortMethodV(env, cls, mid, args);
+ break;
+ case int_type:
+ result.i = env->functions->CallStaticIntMethodV(env, cls, mid, args);
+ break;
+ case long_type:
+ result.j = env->functions->CallStaticLongMethodV(env, cls, mid, args);
+ break;
+ case float_type:
+ result.f = env->functions->CallStaticFloatMethodV(env, cls, mid, args);
+ break;
+ case double_type:
+ result.d = env->functions->CallStaticDoubleMethodV(env, cls, mid, args);
+ break;
+ default:
+ fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, cls);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf (stderr, "\n");
+ }
+ }
+
+ return result;
+}
+
+static jvalue callJNIMethodIDA (JNIType type, jobject obj, jmethodID mid, jvalue *args)
+{
+ JNIEnv *env = getJNIEnv();
+ jvalue result;
+
+ bzero (&result, sizeof(jvalue));
+ if ( obj != NULL && mid != NULL )
+ {
+ switch (type) {
+ case void_type:
+ env->functions->CallVoidMethodA(env, obj, mid, args);
+ break;
+ case array_type:
+ case object_type:
+ result.l = env->functions->CallObjectMethodA(env, obj, mid, args);
+ break;
+ case boolean_type:
+ result.z = env->functions->CallBooleanMethodA(env, obj, mid, args);
+ break;
+ case byte_type:
+ result.b = env->functions->CallByteMethodA(env, obj, mid, args);
+ break;
+ case char_type:
+ result.c = env->functions->CallCharMethodA(env, obj, mid, args);
+ break;
+ case short_type:
+ result.s = env->functions->CallShortMethodA(env, obj, mid, args);
+ break;
+ case int_type:
+ result.i = env->functions->CallIntMethodA(env, obj, mid, args);
+ break;
+ case long_type:
+ result.j = env->functions->CallLongMethodA(env, obj, mid, args);
+ break;
+ case float_type:
+ result.f = env->functions->CallFloatMethodA(env, obj, mid, args);
+ break;
+ case double_type:
+ result.d = env->functions->CallDoubleMethodA(env, obj, mid, args);
+ break;
+ default:
+ fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+ }
+ }
+
+ return result;
+}
+
+static jvalue callJNIMethodA (JNIType type, jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ JavaVM *jvm = getJavaVM();
+ JNIEnv *env = getJNIEnv();
+ jvalue result;
+
+ bzero (&result, sizeof(jvalue));
+ if ( obj != NULL && jvm != NULL && env != NULL) {
+ jclass cls = env->GetObjectClass(obj);
+ if ( cls != NULL ) {
+ jmethodID mid = env->GetMethodID(cls, name, sig);
+ if ( mid != NULL ) {
+ result = callJNIMethodIDA (type, obj, mid, args);
+ }
+ else {
+ fprintf(stderr, "%s: Could not find method: %s\n", __PRETTY_FUNCTION__, name);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf (stderr, "\n");
+ }
+
+ env->DeleteLocalRef(cls);
+ }
+ else {
+ fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__);
+ }
+ }
+
+ return result;
+}
+
+jmethodID getMethodID (jobject obj, const char *name, const char *sig)
+{
+ JNIEnv *env = getJNIEnv();
+ jmethodID mid = 0;
+
+ if ( env != NULL) {
+ jclass cls = env->GetObjectClass(obj);
+ if ( cls != NULL ) {
+ mid = env->GetMethodID(cls, name, sig);
+ if (!mid) {
+ env->ExceptionClear();
+ mid = env->GetStaticMethodID(cls, name, sig);
+ if (!mid) {
+ env->ExceptionClear();
+ }
+ }
+ }
+ env->DeleteLocalRef(cls);
+ }
+ return mid;
+}
+
+
+#define CALL_JNI_METHOD(function_type,obj,name,sig) \
+ va_list args;\
+ va_start (args, sig);\
+ \
+ jvalue result = callJNIMethod(function_type, obj, name, sig, args);\
+ \
+ va_end (args);
+
+#define CALL_JNI_STATIC_METHOD(function_type,cls,name,sig) \
+ va_list args;\
+ va_start (args, sig);\
+ \
+ jvalue result = callJNIStaticMethod(function_type, cls, name, sig, args);\
+ \
+ va_end (args);
+
+void callJNIVoidMethod (jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (void_type, obj, name, sig);
+}
+
+jobject callJNIObjectMethod (jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (object_type, obj, name, sig);
+ return result.l;
+}
+
+jboolean callJNIBooleanMethod( jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (boolean_type, obj, name, sig);
+ return result.z;
+}
+
+jboolean callJNIStaticBooleanMethod (jclass cls, const char *name, const char *sig, ... )
+{
+ CALL_JNI_STATIC_METHOD (boolean_type, cls, name, sig);
+ return result.z;
+}
+
+jbyte callJNIByteMethod( jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (byte_type, obj, name, sig);
+ return result.b;
+}
+
+jchar callJNICharMethod (jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (char_type, obj, name, sig);
+ return result.c;
+}
+
+jshort callJNIShortMethod (jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (short_type, obj, name, sig);
+ return result.s;
+}
+
+jint callJNIIntMethod (jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (int_type, obj, name, sig);
+ return result.i;
+}
+
+jlong callJNILongMethod (jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (long_type, obj, name, sig);
+ return result.j;
+}
+
+jfloat callJNIFloatMethod (jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (float_type, obj, name, sig);
+ return result.f;
+}
+
+jdouble callJNIDoubleMethod (jobject obj, const char *name, const char *sig, ... )
+{
+ CALL_JNI_METHOD (double_type, obj, name, sig);
+ return result.d;
+}
+
+void callJNIVoidMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (void_type, obj, name, sig, args);
+}
+
+jobject callJNIObjectMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (object_type, obj, name, sig, args);
+ return result.l;
+}
+
+jbyte callJNIByteMethodA ( jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (byte_type, obj, name, sig, args);
+ return result.b;
+}
+
+jchar callJNICharMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (char_type, obj, name, sig, args);
+ return result.c;
+}
+
+jshort callJNIShortMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (short_type, obj, name, sig, args);
+ return result.s;
+}
+
+jint callJNIIntMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (int_type, obj, name, sig, args);
+ return result.i;
+}
+
+jlong callJNILongMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (long_type, obj, name, sig, args);
+ return result.j;
+}
+
+jfloat callJNIFloatMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (float_type, obj, name, sig, args);
+ return result.f;
+}
+
+jdouble callJNIDoubleMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (double_type, obj, name, sig, args);
+ return result.d;
+}
+
+jboolean callJNIBooleanMethodA (jobject obj, const char *name, const char *sig, jvalue *args)
+{
+ jvalue result = callJNIMethodA (boolean_type, obj, name, sig, args);
+ return result.z;
+}
+
+void callJNIVoidMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (void_type, obj, methodID, args);
+}
+
+jobject callJNIObjectMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (object_type, obj, methodID, args);
+ return result.l;
+}
+
+jbyte callJNIByteMethodIDA ( jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (byte_type, obj, methodID, args);
+ return result.b;
+}
+
+jchar callJNICharMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (char_type, obj, methodID, args);
+ return result.c;
+}
+
+jshort callJNIShortMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (short_type, obj, methodID, args);
+ return result.s;
+}
+
+jint callJNIIntMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (int_type, obj, methodID, args);
+ return result.i;
+}
+
+jlong callJNILongMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (long_type, obj, methodID, args);
+ return result.j;
+}
+
+jfloat callJNIFloatMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (float_type, obj, methodID, args);
+ return result.f;
+}
+
+jdouble callJNIDoubleMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (double_type, obj, methodID, args);
+ return result.d;
+}
+
+jboolean callJNIBooleanMethodIDA (jobject obj, jmethodID methodID, jvalue *args)
+{
+ jvalue result = callJNIMethodIDA (boolean_type, obj, methodID, args);
+ return result.z;
+}
+
+const char *getCharactersFromJString (jstring aJString)
+{
+ return getCharactersFromJStringInEnv (getJNIEnv(), aJString);
+}
+
+void releaseCharactersForJString (jstring aJString, const char *s)
+{
+ releaseCharactersForJStringInEnv (getJNIEnv(), aJString, s);
+}
+
+const char *getCharactersFromJStringInEnv (JNIEnv *env, jstring aJString)
+{
+ jboolean isCopy;
+ const char *s = env->GetStringUTFChars((jstring)aJString, &isCopy);
+ if (!s) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf (stderr, "\n");
+ }
+ return s;
+}
+
+void releaseCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const char *s)
+{
+ env->ReleaseStringUTFChars (aJString, s);
+}
+
+const jchar *getUCharactersFromJStringInEnv (JNIEnv *env, jstring aJString)
+{
+ jboolean isCopy;
+ const jchar *s = env->GetStringChars((jstring)aJString, &isCopy);
+ if (!s) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf (stderr, "\n");
+ }
+ return s;
+}
+
+void releaseUCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const jchar *s)
+{
+ env->ReleaseStringChars (aJString, s);
+}
+
+JNIType JNITypeFromClassName(const char *name)
+{
+ JNIType type;
+
+ if (strcmp("byte",name) == 0)
+ type = byte_type;
+ else if (strcmp("short",name) == 0)
+ type = short_type;
+ else if (strcmp("int",name) == 0)
+ type = int_type;
+ else if (strcmp("long",name) == 0)
+ type = long_type;
+ else if (strcmp("float",name) == 0)
+ type = float_type;
+ else if (strcmp("double",name) == 0)
+ type = double_type;
+ else if (strcmp("char",name) == 0)
+ type = char_type;
+ else if (strcmp("boolean",name) == 0)
+ type = boolean_type;
+ else if (strcmp("void",name) == 0)
+ type = void_type;
+ else if ('[' == name[0])
+ type = array_type;
+ else
+ type = object_type;
+
+ return type;
+}
+
+const char *signatureFromPrimitiveType(JNIType type)
+{
+ switch (type){
+ case void_type:
+ return "V";
+
+ case array_type:
+ return "[";
+
+ case object_type:
+ return "L";
+
+ case boolean_type:
+ return "Z";
+
+ case byte_type:
+ return "B";
+
+ case char_type:
+ return "C";
+
+ case short_type:
+ return "S";
+
+ case int_type:
+ return "I";
+
+ case long_type:
+ return "J";
+
+ case float_type:
+ return "F";
+
+ case double_type:
+ return "D";
+
+ case invalid_type:
+ default:
+ break;
+ }
+ return "";
+}
+
+JNIType JNITypeFromPrimitiveType(char type)
+{
+ switch (type){
+ case 'V':
+ return void_type;
+
+ case 'L':
+ return object_type;
+
+ case '[':
+ return array_type;
+
+ case 'Z':
+ return boolean_type;
+
+ case 'B':
+ return byte_type;
+
+ case 'C':
+ return char_type;
+
+ case 'S':
+ return short_type;
+
+ case 'I':
+ return int_type;
+
+ case 'J':
+ return long_type;
+
+ case 'F':
+ return float_type;
+
+ case 'D':
+ return double_type;
+
+ default:
+ break;
+ }
+ return invalid_type;
+}
+
+jvalue getJNIField( jobject obj, JNIType type, const char *name, const char *signature)
+{
+ JavaVM *jvm = getJavaVM();
+ JNIEnv *env = getJNIEnv();
+ jvalue result;
+
+ bzero (&result, sizeof(jvalue));
+ if ( obj != NULL && jvm != NULL && env != NULL) {
+ jclass cls = env->GetObjectClass(obj);
+ if ( cls != NULL ) {
+ jfieldID field = env->GetFieldID(cls, name, signature);
+ if ( field != NULL ) {
+ switch (type) {
+ case array_type:
+ case object_type:
+ result.l = env->functions->GetObjectField(env, obj, field);
+ break;
+ case boolean_type:
+ result.z = env->functions->GetBooleanField(env, obj, field);
+ break;
+ case byte_type:
+ result.b = env->functions->GetByteField(env, obj, field);
+ break;
+ case char_type:
+ result.c = env->functions->GetCharField(env, obj, field);
+ break;
+ case short_type:
+ result.s = env->functions->GetShortField(env, obj, field);
+ break;
+ case int_type:
+ result.i = env->functions->GetIntField(env, obj, field);
+ break;
+ case long_type:
+ result.j = env->functions->GetLongField(env, obj, field);
+ break;
+ case float_type:
+ result.f = env->functions->GetFloatField(env, obj, field);
+ break;
+ case double_type:
+ result.d = env->functions->GetDoubleField(env, obj, field);
+ break;
+ default:
+ fprintf(stderr, "%s: invalid field type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s: Could not find field: %s\n", __PRETTY_FUNCTION__, name);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf (stderr, "\n");
+ }
+
+ env->DeleteLocalRef(cls);
+ }
+ else {
+ fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__);
+ }
+ }
+
+ return result;
+}
+
+static jobject convertArrayInstanceToJavaArray(ExecState *exec, JSValue *value, const char *javaClassName) {
+
+ ASSERT(JSLock::lockCount() > 0);
+
+ JNIEnv *env = getJNIEnv();
+ // As JS Arrays can contain a mixture of objects, assume we can convert to
+ // the requested Java Array type requested, unless the array type is some object array
+ // other than a string.
+ ArrayInstance *jsArray = static_cast<ArrayInstance *>(value);
+ unsigned length = jsArray->getLength();
+ jobjectArray jarray = 0;
+
+ // Build the correct array type
+ switch (JNITypeFromPrimitiveType(javaClassName[1])) {
+ case object_type: {
+ // Only support string object types
+ if (0 == strcmp("[Ljava.lang.String;", javaClassName)) {
+ jarray = (jobjectArray)env->NewObjectArray(length,
+ env->FindClass("java/lang/String"),
+ env->NewStringUTF(""));
+ for(unsigned i = 0; i < length; i++) {
+ JSValue* item = jsArray->getItem(i);
+ UString stringValue = item->toString(exec);
+ env->SetObjectArrayElement(jarray,i,
+ env->functions->NewString(env, (const jchar *)stringValue.data(), stringValue.size()));
+ }
+ }
+ break;
+ }
+
+ case boolean_type: {
+ jarray = (jobjectArray)env->NewBooleanArray(length);
+ for(unsigned i = 0; i < length; i++) {
+ JSValue* item = jsArray->getItem(i);
+ jboolean value = (jboolean)item->toNumber(exec);
+ env->SetBooleanArrayRegion((jbooleanArray)jarray, (jsize)i, (jsize)1, &value);
+ }
+ break;
+ }
+
+ case byte_type: {
+ jarray = (jobjectArray)env->NewByteArray(length);
+ for(unsigned i = 0; i < length; i++) {
+ JSValue* item = jsArray->getItem(i);
+ jbyte value = (jbyte)item->toNumber(exec);
+ env->SetByteArrayRegion((jbyteArray)jarray, (jsize)i, (jsize)1, &value);
+ }
+ break;
+ }
+
+ case char_type: {
+ jarray = (jobjectArray)env->NewCharArray(length);
+ for(unsigned i = 0; i < length; i++) {
+ JSValue* item = jsArray->getItem(i);
+ UString stringValue = item->toString(exec);
+ jchar value = 0;
+ if (stringValue.size() > 0)
+ value = ((const jchar*)stringValue.data())[0];
+ env->SetCharArrayRegion((jcharArray)jarray, (jsize)i, (jsize)1, &value);
+ }
+ break;
+ }
+
+ case short_type: {
+ jarray = (jobjectArray)env->NewShortArray(length);
+ for(unsigned i = 0; i < length; i++) {
+ JSValue* item = jsArray->getItem(i);
+ jshort value = (jshort)item->toNumber(exec);
+ env->SetShortArrayRegion((jshortArray)jarray, (jsize)i, (jsize)1, &value);
+ }
+ break;
+ }
+
+ case int_type: {
+ jarray = (jobjectArray)env->NewIntArray(length);
+ for(unsigned i = 0; i < length; i++) {
+ JSValue* item = jsArray->getItem(i);
+ jint value = (jint)item->toNumber(exec);
+ env->SetIntArrayRegion((jintArray)jarray, (jsize)i, (jsize)1, &value);
+ }
+ break;
+ }
+
+ case long_type: {
+ jarray = (jobjectArray)env->NewLongArray(length);
+ for(unsigned i = 0; i < length; i++) {
+ JSValue* item = jsArray->getItem(i);
+ jlong value = (jlong)item->toNumber(exec);
+ env->SetLongArrayRegion((jlongArray)jarray, (jsize)i, (jsize)1, &value);
+ }
+ break;
+ }
+
+ case float_type: {
+ jarray = (jobjectArray)env->NewFloatArray(length);
+ for(unsigned i = 0; i < length; i++) {
+ JSValue* item = jsArray->getItem(i);
+ jfloat value = (jfloat)item->toNumber(exec);
+ env->SetFloatArrayRegion((jfloatArray)jarray, (jsize)i, (jsize)1, &value);
+ }
+ break;
+ }
+
+ case double_type: {
+ jarray = (jobjectArray)env->NewDoubleArray(length);
+ for(unsigned i = 0; i < length; i++) {
+ JSValue* item = jsArray->getItem(i);
+ jdouble value = (jdouble)item->toNumber(exec);
+ env->SetDoubleArrayRegion((jdoubleArray)jarray, (jsize)i, (jsize)1, &value);
+ }
+ break;
+ }
+
+ case array_type: // don't handle embedded arrays
+ case void_type: // Don't expect arrays of void objects
+ case invalid_type: // Array of unknown objects
+ break;
+ }
+
+ // if it was not one of the cases handled, then null is returned
+ return jarray;
+}
+
+
+jvalue convertValueToJValue (ExecState *exec, JSValue *value, JNIType _JNIType, const char *javaClassName)
+{
+ JSLock lock;
+
+ jvalue result;
+
+ switch (_JNIType){
+ case array_type:
+ case object_type: {
+ result.l = (jobject)0;
+
+ // First see if we have a Java instance.
+ if (value->isObject()){
+ JSObject *objectImp = static_cast<JSObject*>(value);
+ if (objectImp->classInfo() == &RuntimeObjectImp::info) {
+ RuntimeObjectImp *imp = static_cast<RuntimeObjectImp *>(value);
+ JavaInstance *instance = static_cast<JavaInstance*>(imp->getInternalInstance());
+ if (instance)
+ result.l = instance->javaInstance();
+ }
+ else if (objectImp->classInfo() == &RuntimeArray::info) {
+ // Input is a JavaScript Array that was originally created from a Java Array
+ RuntimeArray *imp = static_cast<RuntimeArray *>(value);
+ JavaArray *array = static_cast<JavaArray*>(imp->getConcreteArray());
+ result.l = array->javaArray();
+ }
+ else if (objectImp->classInfo() == &ArrayInstance::info) {
+ // Input is a Javascript Array. We need to create it to a Java Array.
+ result.l = convertArrayInstanceToJavaArray(exec, value, javaClassName);
+ }
+ }
+
+ // Now convert value to a string if the target type is a java.lang.string, and we're not
+ // converting from a Null.
+ if (result.l == 0 && strcmp(javaClassName, "java.lang.String") == 0) {
+#ifdef CONVERT_NULL_TO_EMPTY_STRING
+ if (value->isNull()) {
+ JNIEnv *env = getJNIEnv();
+ jchar buf[2];
+ jobject javaString = env->functions->NewString (env, buf, 0);
+ result.l = javaString;
+ }
+ else
+#else
+ if (!value->isNull())
+#endif
+ {
+ UString stringValue = value->toString(exec);
+ JNIEnv *env = getJNIEnv();
+ jobject javaString = env->functions->NewString (env, (const jchar *)stringValue.data(), stringValue.size());
+ result.l = javaString;
+ }
+ } else if (result.l == 0)
+ bzero (&result, sizeof(jvalue)); // Handle it the same as a void case
+ }
+ break;
+
+ case boolean_type: {
+ result.z = (jboolean)value->toNumber(exec);
+ }
+ break;
+
+ case byte_type: {
+ result.b = (jbyte)value->toNumber(exec);
+ }
+ break;
+
+ case char_type: {
+ result.c = (jchar)value->toNumber(exec);
+ }
+ break;
+
+ case short_type: {
+ result.s = (jshort)value->toNumber(exec);
+ }
+ break;
+
+ case int_type: {
+ result.i = (jint)value->toNumber(exec);
+ }
+ break;
+
+ case long_type: {
+ result.j = (jlong)value->toNumber(exec);
+ }
+ break;
+
+ case float_type: {
+ result.f = (jfloat)value->toNumber(exec);
+ }
+ break;
+
+ case double_type: {
+ result.d = (jdouble)value->toNumber(exec);
+ }
+ break;
+
+ break;
+
+ case invalid_type:
+ default:
+ case void_type: {
+ bzero (&result, sizeof(jvalue));
+ }
+ break;
+ }
+ return result;
+}
+
+} // end of namespace Bindings
+
+} // end of namespace KJS
diff --git a/JavaScriptCore/bindings/jni/jni_utility.h b/JavaScriptCore/bindings/jni/jni_utility.h
new file mode 100644
index 0000000..69aa739
--- /dev/null
+++ b/JavaScriptCore/bindings/jni/jni_utility.h
@@ -0,0 +1,120 @@
+/*
+ * 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 _JNI_UTILITY_H_
+#define _JNI_UTILITY_H_
+
+#include <list.h>
+
+#include <JavaVM/jni.h>
+
+// The order of these items can not be modified as they are tightly
+// bound with the JVM on Mac OSX. If new types need to be added, they
+// should be added to the end. It is used in jni_obc.mm when calling
+// through to the JVM. Newly added items need to be made compatible
+// in that file.
+typedef enum {
+ invalid_type = 0,
+ void_type,
+ object_type,
+ boolean_type,
+ byte_type,
+ char_type,
+ short_type,
+ int_type,
+ long_type,
+ float_type,
+ double_type,
+ array_type
+} JNIType;
+
+namespace KJS {
+
+namespace Bindings {
+
+class JavaParameter;
+
+const char *getCharactersFromJString(jstring aJString);
+void releaseCharactersForJString(jstring aJString, const char *s);
+
+const char *getCharactersFromJStringInEnv(JNIEnv *env, jstring aJString);
+void releaseCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const char *s);
+const jchar *getUCharactersFromJStringInEnv(JNIEnv *env, jstring aJString);
+void releaseUCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const jchar *s);
+
+JNIType JNITypeFromClassName(const char *name);
+JNIType JNITypeFromPrimitiveType(char type);
+const char *signatureFromPrimitiveType(JNIType type);
+
+jvalue convertValueToJValue(ExecState *exec, JSValue *value, JNIType _JNIType, const char *javaClassName);
+
+jvalue getJNIField(jobject obj, JNIType type, const char *name, const char *signature);
+
+jmethodID getMethodID(jobject obj, const char *name, const char *sig);
+
+jobject callJNIObjectMethod(jobject obj, const char *name, const char *sig, ... );
+void callJNIVoidMethod(jobject obj, const char *name, const char *sig, ... );
+jboolean callJNIBooleanMethod(jobject obj, const char *name, const char *sig, ... );
+jboolean callJNIStaticBooleanMethod(jclass cls, const char *name, const char *sig, ... );
+jbyte callJNIByteMethod(jobject obj, const char *name, const char *sig, ... );
+jchar callJNICharMethod(jobject obj, const char *name, const char *sig, ... );
+jshort callJNIShortMethod(jobject obj, const char *name, const char *sig, ... );
+jint callJNIIntMethod(jobject obj, const char *name, const char *sig, ... );
+jlong callJNILongMethod(jobject obj, const char *name, const char *sig, ... );
+jfloat callJNIFloatMethod(jobject obj, const char *name, const char *sig, ... );
+jdouble callJNIDoubleMethod(jobject obj, const char *name, const char *sig, ... );
+
+jobject callJNIObjectMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+void callJNIVoidMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jboolean callJNIBooleanMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jbyte callJNIByteMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jchar callJNICharMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jshort callJNIShortMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jint callJNIIntMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jlong callJNILongMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jfloat callJNIFloatMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+jdouble callJNIDoubleMethodA(jobject obj, const char *name, const char *sig, jvalue *args);
+
+jobject callJNIObjectMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+void callJNIVoidMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jboolean callJNIBooleanMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jbyte callJNIByteMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jchar callJNICharMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jshort callJNIShortMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jint callJNIIntMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jlong callJNILongMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jfloat callJNIFloatMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+jdouble callJNIDoubleMethodIDA(jobject obj, jmethodID methodID, jvalue *args);
+
+JavaVM *getJavaVM();
+void setJavaVM(JavaVM *javaVM);
+JNIEnv *getJNIEnv();
+
+bool dispatchJNICall(const void *targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue *args, jvalue &result, const char *callingURL, JSValue *&exceptionDescription);
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif // _JNI_UTILITY_H_
diff --git a/JavaScriptCore/bindings/make_testbindings b/JavaScriptCore/bindings/make_testbindings
new file mode 100755
index 0000000..1f528fe
--- /dev/null
+++ b/JavaScriptCore/bindings/make_testbindings
@@ -0,0 +1,2 @@
+cc -g -o testbindingsM testbindings.mm -I../kjs -F$SYMROOTS -framework JavaScriptCore -framework Foundation -lstdc++
+cc -g -o testbindingsC testbindings.cpp -I../kjs -F$SYMROOTS -framework JavaScriptCore -framework Foundation -lstdc++
diff --git a/JavaScriptCore/bindings/npapi.h b/JavaScriptCore/bindings/npapi.h
new file mode 100644
index 0000000..ba8b6c7
--- /dev/null
+++ b/JavaScriptCore/bindings/npapi.h
@@ -0,0 +1,714 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+ /*
+ * Netscape client plug-in API spec
+ */
+
+
+#ifndef _NPAPI_H_
+#define _NPAPI_H_
+
+#ifdef INCLUDE_JAVA
+#include "jri.h" /* Java Runtime Interface */
+#else
+#define jref void *
+#define JRIEnv void
+#endif
+
+#ifdef _WIN32
+# ifndef XP_WIN
+# define XP_WIN 1
+# endif /* XP_WIN */
+#endif /* _WIN32 */
+
+#ifdef __MWERKS__
+# define _declspec __declspec
+# ifdef macintosh
+# ifndef XP_MAC
+# define XP_MAC 1
+# endif /* XP_MAC */
+# endif /* macintosh */
+# ifdef __INTEL__
+# undef NULL
+# ifndef XP_WIN
+# define XP_WIN 1
+# endif /* __INTEL__ */
+# endif /* XP_PC */
+#endif /* __MWERKS__ */
+
+#if defined(__APPLE_CC__) && !defined(__MACOS_CLASSIC__) && !defined(XP_UNIX)
+# define XP_MACOSX
+#endif
+
+#ifdef XP_MAC
+ #include <Quickdraw.h>
+ #include <Events.h>
+#endif
+
+#ifdef XP_MACOSX
+ #include <Carbon/Carbon.h>
+ #include <ApplicationServices/ApplicationServices.h>
+ #include <OpenGL/OpenGL.h>
+#endif
+
+#ifdef XP_UNIX
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ #include <stdio.h>
+#endif
+
+#ifdef XP_WIN
+ #include <windows.h>
+#endif
+
+#if defined(XP_MACOSX) && defined(__LP64__)
+#error 64-bit Netscape plug-ins are not supported on Mac OS X
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Plugin Version Constants */
+/*----------------------------------------------------------------------*/
+
+#define NP_VERSION_MAJOR 0
+#define NP_VERSION_MINOR 18
+
+
+
+/*----------------------------------------------------------------------*/
+/* Definition of Basic Types */
+/*----------------------------------------------------------------------*/
+
+#ifndef _UINT16
+#define _UINT16
+typedef unsigned short uint16;
+#endif
+
+#ifndef _UINT32
+#define _UINT32
+#ifdef __LP64__
+typedef unsigned int uint32;
+#else /* __LP64__ */
+typedef unsigned long uint32;
+#endif /* __LP64__ */
+#endif
+
+#ifndef _INT16
+#define _INT16
+typedef short int16;
+#endif
+
+#ifndef _INT32
+#define _INT32
+#ifdef __LP64__
+typedef int int32;
+#else /* __LP64__ */
+typedef long int32;
+#endif /* __LP64__ */
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+#ifndef TRUE
+#define TRUE (1)
+#endif
+#ifndef NULL
+#define NULL (0L)
+#endif
+
+typedef unsigned char NPBool;
+typedef int16 NPError;
+typedef int16 NPReason;
+typedef char* NPMIMEType;
+
+
+
+/*----------------------------------------------------------------------*/
+/* Structures and definitions */
+/*----------------------------------------------------------------------*/
+
+#if !defined(__LP64__)
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#pragma options align=mac68k
+#endif
+#endif /* __LP64__ */
+
+/*
+ * NPP is a plug-in's opaque instance handle
+ */
+typedef struct _NPP
+{
+ void* pdata; /* plug-in private data */
+ void* ndata; /* netscape private data */
+} NPP_t;
+
+typedef NPP_t* NPP;
+
+
+typedef struct _NPStream
+{
+ void* pdata; /* plug-in private data */
+ void* ndata; /* netscape private data */
+ const char* url;
+ uint32 end;
+ uint32 lastmodified;
+ void* notifyData;
+ const char* headers; /* Response headers from host.
+ * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
+ * Used for HTTP only; NULL for non-HTTP.
+ * Available from NPP_NewStream onwards.
+ * Plugin should copy this data before storing it.
+ * Includes HTTP status line and all headers,
+ * preferably verbatim as received from server,
+ * headers formatted as in HTTP ("Header: Value"),
+ * and newlines (\n, NOT \r\n) separating lines.
+ * Terminated by \n\0 (NOT \n\n\0). */
+} NPStream;
+
+
+typedef struct _NPByteRange
+{
+ int32 offset; /* negative offset means from the end */
+ uint32 length;
+ struct _NPByteRange* next;
+} NPByteRange;
+
+
+typedef struct _NPSavedData
+{
+ int32 len;
+ void* buf;
+} NPSavedData;
+
+
+typedef struct _NPRect
+{
+ uint16 top;
+ uint16 left;
+ uint16 bottom;
+ uint16 right;
+} NPRect;
+
+
+#ifdef XP_UNIX
+/*
+ * Unix specific structures and definitions
+ */
+
+/*
+ * Callback Structures.
+ *
+ * These are used to pass additional platform specific information.
+ */
+enum {
+ NP_SETWINDOW = 1,
+ NP_PRINT
+};
+
+typedef struct
+{
+ int32 type;
+} NPAnyCallbackStruct;
+
+typedef struct
+{
+ int32 type;
+ Display* display;
+ Visual* visual;
+ Colormap colormap;
+ unsigned int depth;
+} NPSetWindowCallbackStruct;
+
+typedef struct
+{
+ int32 type;
+ FILE* fp;
+} NPPrintCallbackStruct;
+
+#endif /* XP_UNIX */
+
+/*
+ * The following masks are applied on certain platforms to NPNV and
+ * NPPV selectors that pass around pointers to COM interfaces. Newer
+ * compilers on some platforms may generate vtables that are not
+ * compatible with older compilers. To prevent older plugins from
+ * not understanding a new browser's ABI, these masks change the
+ * values of those selectors on those platforms. To remain backwards
+ * compatible with differenet versions of the browser, plugins can
+ * use these masks to dynamically determine and use the correct C++
+ * ABI that the browser is expecting. This does not apply to Windows
+ * as Microsoft's COM ABI will likely not change.
+ */
+
+#define NP_ABI_GCC3_MASK 0x10000000
+/*
+ * gcc 3.x generated vtables on UNIX and OSX are incompatible with
+ * previous compilers.
+ */
+#if (defined (XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3))
+#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK
+#else
+#define _NP_ABI_MIXIN_FOR_GCC3 0
+#endif
+
+#define NP_ABI_MACHO_MASK 0x01000000
+/*
+ * On OSX, the Mach-O executable format is significantly
+ * different than CFM. In addition to having a different
+ * C++ ABI, it also has has different C calling convention.
+ * You must use glue code when calling between CFM and
+ * Mach-O C functions.
+ */
+#if (defined(TARGET_RT_MAC_MACHO))
+#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK
+#else
+#define _NP_ABI_MIXIN_FOR_MACHO 0
+#endif
+
+
+#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO)
+
+/*
+ * List of variable names for which NPP_GetValue shall be implemented
+ */
+typedef enum {
+ NPPVpluginNameString = 1,
+ NPPVpluginDescriptionString,
+ NPPVpluginWindowBool,
+ NPPVpluginTransparentBool,
+
+ NPPVjavaClass, /* Not implemented in WebKit */
+ NPPVpluginWindowSize, /* Not implemented in WebKit */
+ NPPVpluginTimerInterval, /* Not implemented in WebKit */
+
+ NPPVpluginScriptableInstance = (10 | NP_ABI_MASK), /* Not implemented in WebKit */
+ NPPVpluginScriptableIID = 11, /* Not implemented in WebKit */
+
+ /* 12 and over are available on Mozilla builds starting with 0.9.9 */
+ NPPVjavascriptPushCallerBool = 12, /* Not implemented in WebKit */
+ NPPVpluginKeepLibraryInMemory = 13, /* Not implemented in WebKit */
+ NPPVpluginNeedsXEmbed = 14, /* Not implemented in WebKit */
+
+ /* Get the NPObject for scripting the plugin. */
+ NPPVpluginScriptableNPObject = 15,
+
+ /* Get the plugin value (as \0-terminated UTF-8 string data) for
+ * form submission if the plugin is part of a form. Use
+ * NPN_MemAlloc() to allocate memory for the string data.
+ */
+ NPPVformValue = 16, /* Not implemented in WebKit */
+#ifdef XP_MACOSX
+ /* Used for negotiating drawing models */
+ NPPVpluginDrawingModel = 1000
+#endif
+} NPPVariable;
+
+/*
+ * List of variable names for which NPN_GetValue is implemented by Mozilla
+ */
+typedef enum {
+ NPNVxDisplay = 1,
+ NPNVxtAppContext,
+ NPNVnetscapeWindow,
+ NPNVjavascriptEnabledBool,
+ NPNVasdEnabledBool,
+ NPNVisOfflineBool,
+
+ /* 10 and over are available on Mozilla builds starting with 0.9.4 */
+ NPNVserviceManager = (10 | NP_ABI_MASK), /* Not implemented in WebKit */
+ NPNVDOMElement = (11 | NP_ABI_MASK), /* Not implemented in WebKit */
+ NPNVDOMWindow = (12 | NP_ABI_MASK), /* Not implemented in WebKit */
+ NPNVToolkit = (13 | NP_ABI_MASK), /* Not implemented in WebKit */
+ NPNVSupportsXEmbedBool = 14, /* Not implemented in WebKit */
+
+ /* Get the NPObject wrapper for the browser window. */
+ NPNVWindowNPObject = 15,
+
+ /* Get the NPObject wrapper for the plugins DOM element. */
+ NPNVPluginElementNPObject
+
+#ifdef XP_MACOSX
+ , NPNVpluginDrawingModel = 1000 /* The NPDrawingModel specified by the plugin */
+
+#ifndef NP_NO_QUICKDRAW
+ , NPNVsupportsQuickDrawBool = 2000 /* TRUE if the browser supports the QuickDraw drawing model */
+#endif
+ , NPNVsupportsCoreGraphicsBool = 2001 /* TRUE if the browser supports the CoreGraphics drawing model */
+ , NPNVsupportsOpenGLBool = 2002 /* TRUE if the browser supports the OpenGL drawing model (CGL on Mac) */
+#endif /* XP_MACOSX */
+} NPNVariable;
+
+/*
+ * The type of a NPWindow - it specifies the type of the data structure
+ * returned in the window field.
+ */
+typedef enum {
+ NPWindowTypeWindow = 1,
+ NPWindowTypeDrawable
+} NPWindowType;
+
+#ifdef XP_MACOSX
+
+/*
+ * The drawing model for a Mac OS X plugin. These are the possible values for the NPNVpluginDrawingModel variable.
+ */
+
+typedef enum {
+#ifndef NP_NO_QUICKDRAW
+ NPDrawingModelQuickDraw = 0,
+#endif
+ NPDrawingModelCoreGraphics = 1,
+ NPDrawingModelOpenGL = 2
+} NPDrawingModel;
+
+#endif
+
+typedef struct _NPWindow
+{
+ void* window; /* Platform specific window handle */
+ int32 x; /* Position of top left corner relative */
+ int32 y; /* to a netscape page. */
+ uint32 width; /* Maximum window size */
+ uint32 height;
+ NPRect clipRect; /* Clipping rectangle in port coordinates */
+ /* Used by MAC only. */
+#ifdef XP_UNIX
+ void * ws_info; /* Platform-dependent additonal data */
+#endif /* XP_UNIX */
+ NPWindowType type; /* Is this a window or a drawable? */
+} NPWindow;
+
+
+typedef struct _NPFullPrint
+{
+ NPBool pluginPrinted; /* Set TRUE if plugin handled fullscreen */
+ /* printing */
+ NPBool printOne; /* TRUE if plugin should print one copy */
+ /* to default printer */
+ void* platformPrint; /* Platform-specific printing info */
+} NPFullPrint;
+
+typedef struct _NPEmbedPrint
+{
+ NPWindow window;
+ void* platformPrint; /* Platform-specific printing info */
+} NPEmbedPrint;
+
+typedef struct _NPPrint
+{
+ uint16 mode; /* NP_FULL or NP_EMBED */
+ union
+ {
+ NPFullPrint fullPrint; /* if mode is NP_FULL */
+ NPEmbedPrint embedPrint; /* if mode is NP_EMBED */
+ } print;
+} NPPrint;
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+typedef EventRecord NPEvent;
+#elif defined(XP_WIN)
+typedef struct _NPEvent
+{
+ uint16 event;
+ uint32 wParam;
+ uint32 lParam;
+} NPEvent;
+#elif defined (XP_UNIX)
+typedef XEvent NPEvent;
+#else
+typedef void* NPEvent;
+#endif /* XP_MAC */
+
+#if defined(XP_MAC)
+typedef RgnHandle NPRegion;
+#elif defined(XP_MACOSX)
+/*
+ * NPRegion's type depends on the drawing model specified by the plugin (see NPNVpluginDrawingModel).
+ * NPQDRegion represents a QuickDraw RgnHandle and is used with the QuickDraw drawing model.
+ * NPCGRegion repesents a graphical region when using any other drawing model.
+ */
+typedef void *NPRegion;
+#ifndef NP_NO_QUICKDRAW
+typedef RgnHandle NPQDRegion;
+#endif
+typedef CGPathRef NPCGRegion;
+#elif defined(XP_WIN)
+typedef HRGN NPRegion;
+#elif defined(XP_UNIX)
+typedef Region NPRegion;
+#else
+typedef void *NPRegion;
+#endif /* XP_MAC */
+
+#ifdef XP_MACOSX
+
+/*
+ * NP_CGContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelCoreGraphics
+ * as its drawing model.
+ */
+
+typedef struct NP_CGContext
+{
+ CGContextRef context;
+ WindowRef window;
+} NP_CGContext;
+
+/*
+ * NP_GLContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelOpenGL as its
+ * drawing model.
+ */
+
+typedef struct NP_GLContext
+{
+ CGLContextObj context;
+ WindowRef window;
+} NP_GLContext;
+
+#endif /* XP_MACOSX */
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+
+/*
+ * Mac-specific structures and definitions.
+ */
+
+#ifndef NP_NO_QUICKDRAW
+
+/*
+ * NP_Port is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelQuickDraw as its
+ * drawing model, or the plugin does not specify a drawing model.
+ *
+ * It is not recommended that new plugins use NPDrawingModelQuickDraw or NP_Port, as QuickDraw has been
+ * deprecated in Mac OS X 10.5. CoreGraphics is the preferred drawing API.
+ *
+ * NP_Port is not available in 64-bit.
+ */
+
+typedef struct NP_Port
+{
+ CGrafPtr port; /* Grafport */
+ int32 portx; /* position inside the topmost window */
+ int32 porty;
+} NP_Port;
+
+#endif /* NP_NO_QUICKDRAW */
+
+/*
+ * Non-standard event types that can be passed to HandleEvent
+ */
+#define getFocusEvent (osEvt + 16)
+#define loseFocusEvent (osEvt + 17)
+#define adjustCursorEvent (osEvt + 18)
+
+#endif /* XP_MAC */
+
+
+/*
+ * Values for mode passed to NPP_New:
+ */
+#define NP_EMBED 1
+#define NP_FULL 2
+
+/*
+ * Values for stream type passed to NPP_NewStream:
+ */
+#define NP_NORMAL 1
+#define NP_SEEK 2
+#define NP_ASFILE 3
+#define NP_ASFILEONLY 4
+
+#define NP_MAXREADY (((unsigned)(~0)<<1)>>1)
+
+#if !defined(__LP64__)
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#pragma options align=reset
+#endif
+#endif /* __LP64__ */
+
+
+/*----------------------------------------------------------------------*/
+/* Error and Reason Code definitions */
+/*----------------------------------------------------------------------*/
+
+/*
+ * Values of type NPError:
+ */
+#define NPERR_BASE 0
+#define NPERR_NO_ERROR (NPERR_BASE + 0)
+#define NPERR_GENERIC_ERROR (NPERR_BASE + 1)
+#define NPERR_INVALID_INSTANCE_ERROR (NPERR_BASE + 2)
+#define NPERR_INVALID_FUNCTABLE_ERROR (NPERR_BASE + 3)
+#define NPERR_MODULE_LOAD_FAILED_ERROR (NPERR_BASE + 4)
+#define NPERR_OUT_OF_MEMORY_ERROR (NPERR_BASE + 5)
+#define NPERR_INVALID_PLUGIN_ERROR (NPERR_BASE + 6)
+#define NPERR_INVALID_PLUGIN_DIR_ERROR (NPERR_BASE + 7)
+#define NPERR_INCOMPATIBLE_VERSION_ERROR (NPERR_BASE + 8)
+#define NPERR_INVALID_PARAM (NPERR_BASE + 9)
+#define NPERR_INVALID_URL (NPERR_BASE + 10)
+#define NPERR_FILE_NOT_FOUND (NPERR_BASE + 11)
+#define NPERR_NO_DATA (NPERR_BASE + 12)
+#define NPERR_STREAM_NOT_SEEKABLE (NPERR_BASE + 13)
+
+/*
+ * Values of type NPReason:
+ */
+#define NPRES_BASE 0
+#define NPRES_DONE (NPRES_BASE + 0)
+#define NPRES_NETWORK_ERR (NPRES_BASE + 1)
+#define NPRES_USER_BREAK (NPRES_BASE + 2)
+
+/*
+ * Don't use these obsolete error codes any more.
+ */
+#define NP_NOERR NP_NOERR_is_obsolete_use_NPERR_NO_ERROR
+#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR
+#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK
+
+/*
+ * Version feature information
+ */
+#define NPVERS_HAS_STREAMOUTPUT 8
+#define NPVERS_HAS_NOTIFICATION 9
+#define NPVERS_HAS_LIVECONNECT 9
+#define NPVERS_WIN16_HAS_LIVECONNECT 9
+#define NPVERS_68K_HAS_LIVECONNECT 11
+#define NPVERS_HAS_WINDOWLESS 11
+#define NPVERS_HAS_XPCONNECT_SCRIPTING 13 /* Not implemented in WebKit */
+#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14
+#define NPVERS_HAS_FORM_VALUES 15 /* Not implemented in WebKit; see bug 13061 */
+#define NPVERS_HAS_POPUPS_ENABLED_STATE 16 /* Not implemented in WebKit */
+#define NPVERS_HAS_RESPONSE_HEADERS 17
+#define NPVERS_HAS_NPOBJECT_ENUM 18
+
+
+/*----------------------------------------------------------------------*/
+/* Function Prototypes */
+/*----------------------------------------------------------------------*/
+
+#if defined(_WINDOWS) && !defined(WIN32)
+#define NP_LOADDS _loadds
+#else
+#define NP_LOADDS
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * NPP_* functions are provided by the plugin and called by the navigator.
+ */
+
+#ifdef XP_UNIX
+char* NPP_GetMIMEDescription(void);
+#endif /* XP_UNIX */
+
+NPError NPP_Initialize(void);
+void NPP_Shutdown(void);
+NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
+ uint16 mode, int16 argc, char* argn[],
+ char* argv[], NPSavedData* saved);
+NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save);
+NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window);
+NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type,
+ NPStream* stream, NPBool seekable,
+ uint16* stype);
+NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
+ NPReason reason);
+int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream);
+int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset,
+ int32 len, void* buffer);
+void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream,
+ const char* fname);
+void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint);
+int16 NPP_HandleEvent(NPP instance, void* event);
+void NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
+ NPReason reason, void* notifyData);
+jref NP_LOADDS NPP_GetJavaClass(void);
+NPError NPP_GetValue(NPP instance, NPPVariable variable,
+ void *value);
+NPError NPP_SetValue(NPP instance, NPNVariable variable,
+ void *value);
+
+/*
+ * NPN_* functions are provided by the navigator and called by the plugin.
+ */
+
+void NPN_Version(int* plugin_major, int* plugin_minor,
+ int* netscape_major, int* netscape_minor);
+NPError NPN_GetURLNotify(NPP instance, const char* url,
+ const char* target, void* notifyData);
+NPError NPN_GetURL(NPP instance, const char* url,
+ const char* target);
+NPError NPN_PostURLNotify(NPP instance, const char* url,
+ const char* target, uint32 len,
+ const char* buf, NPBool file,
+ void* notifyData);
+NPError NPN_PostURL(NPP instance, const char* url,
+ const char* target, uint32 len,
+ const char* buf, NPBool file);
+NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList);
+NPError NPN_NewStream(NPP instance, NPMIMEType type,
+ const char* target, NPStream** stream);
+int32 NPN_Write(NPP instance, NPStream* stream, int32 len,
+ void* buffer);
+NPError NPN_DestroyStream(NPP instance, NPStream* stream,
+ NPReason reason);
+void NPN_Status(NPP instance, const char* message);
+const char* NPN_UserAgent(NPP instance);
+void* NPN_MemAlloc(uint32 size);
+void NPN_MemFree(void* ptr);
+uint32 NPN_MemFlush(uint32 size);
+void NPN_ReloadPlugins(NPBool reloadPages);
+JRIEnv* NPN_GetJavaEnv(void);
+jref NPN_GetJavaPeer(NPP instance);
+NPError NPN_GetValue(NPP instance, NPNVariable variable,
+ void *value);
+NPError NPN_SetValue(NPP instance, NPPVariable variable,
+ void *value);
+void NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
+void NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);
+void NPN_ForceRedraw(NPP instance);
+void NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
+void NPN_PopPopupsEnabledState(NPP instance);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* _NPAPI_H_ */
diff --git a/JavaScriptCore/bindings/npruntime.cpp b/JavaScriptCore/bindings/npruntime.cpp
new file mode 100644
index 0000000..ea7ea63
--- /dev/null
+++ b/JavaScriptCore/bindings/npruntime.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2004, 2006 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"
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+
+#include "JSLock.h"
+#include "c_utility.h"
+#include "identifier.h"
+#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+
+using namespace KJS::Bindings;
+
+typedef HashMap<RefPtr<KJS::UString::Rep>, PrivateIdentifier*> StringIdentifierMap;
+
+static StringIdentifierMap* getStringIdentifierMap()
+{
+ static StringIdentifierMap* stringIdentifierMap = 0;
+ if (!stringIdentifierMap)
+ stringIdentifierMap = new StringIdentifierMap;
+ return stringIdentifierMap;
+}
+
+typedef HashMap<int, PrivateIdentifier*> IntIdentifierMap;
+
+static IntIdentifierMap* getIntIdentifierMap()
+{
+ static IntIdentifierMap* intIdentifierMap = 0;
+ if (!intIdentifierMap)
+ intIdentifierMap = new IntIdentifierMap;
+ return intIdentifierMap;
+}
+
+NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name)
+{
+ ASSERT(name);
+
+ if (name) {
+ PrivateIdentifier* identifier = 0;
+
+ KJS::JSLock lock;
+
+ identifier = getStringIdentifierMap()->get(identifierFromNPIdentifier(name).ustring().rep());
+ if (identifier == 0) {
+ identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
+ // We never release identifier names, so this dictionary will grow, as will
+ // the memory for the identifier name strings.
+ identifier->isString = true;
+ identifier->value.string = strdup(name);
+
+ getStringIdentifierMap()->set(identifierFromNPIdentifier(name).ustring().rep(), identifier);
+ }
+ return (NPIdentifier)identifier;
+ }
+
+ return 0;
+}
+
+void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers)
+{
+ ASSERT(names);
+ ASSERT(identifiers);
+
+ if (names && identifiers)
+ for (int i = 0; i < nameCount; i++)
+ identifiers[i] = _NPN_GetStringIdentifier(names[i]);
+}
+
+NPIdentifier _NPN_GetIntIdentifier(int32_t intid)
+{
+ PrivateIdentifier* identifier;
+
+ if (intid == 0 || intid == -1) {
+ static PrivateIdentifier* negativeOneAndZeroIdentifiers[2];
+
+ identifier = negativeOneAndZeroIdentifiers[intid + 1];
+ if (!identifier) {
+ identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
+ identifier->isString = false;
+ identifier->value.number = intid;
+
+ negativeOneAndZeroIdentifiers[intid + 1] = identifier;
+ }
+ } else {
+ identifier = getIntIdentifierMap()->get(intid);
+ if (!identifier) {
+ identifier = (PrivateIdentifier*)malloc(sizeof(PrivateIdentifier));
+ // We never release identifier names, so this dictionary will grow.
+ identifier->isString = false;
+ identifier->value.number = intid;
+
+ getIntIdentifierMap()->set(intid, identifier);
+ }
+ }
+ return (NPIdentifier)identifier;
+}
+
+bool _NPN_IdentifierIsString(NPIdentifier identifier)
+{
+ PrivateIdentifier* i = (PrivateIdentifier*)identifier;
+ return i->isString;
+}
+
+NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier)
+{
+ PrivateIdentifier* i = (PrivateIdentifier*)identifier;
+ if (!i->isString || !i->value.string)
+ return NULL;
+
+ return (NPUTF8 *)strdup(i->value.string);
+}
+
+int32_t _NPN_IntFromIdentifier(NPIdentifier identifier)
+{
+ PrivateIdentifier* i = (PrivateIdentifier*)identifier;
+ if (!i->isString)
+ return 0;
+ return i->value.number;
+}
+
+void NPN_InitializeVariantWithStringCopy(NPVariant* variant, const NPString* value)
+{
+ variant->type = NPVariantType_String;
+ variant->value.stringValue.UTF8Length = value->UTF8Length;
+ variant->value.stringValue.UTF8Characters = (NPUTF8 *)malloc(sizeof(NPUTF8) * value->UTF8Length);
+ memcpy((void*)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length);
+}
+
+void _NPN_ReleaseVariantValue(NPVariant* variant)
+{
+ ASSERT(variant);
+
+ if (variant->type == NPVariantType_Object) {
+ _NPN_ReleaseObject(variant->value.objectValue);
+ variant->value.objectValue = 0;
+ } else if (variant->type == NPVariantType_String) {
+ free((void*)variant->value.stringValue.UTF8Characters);
+ variant->value.stringValue.UTF8Characters = 0;
+ variant->value.stringValue.UTF8Length = 0;
+ }
+
+ variant->type = NPVariantType_Void;
+}
+
+NPObject *_NPN_CreateObject(NPP npp, NPClass* aClass)
+{
+ ASSERT(aClass);
+
+ if (aClass) {
+ NPObject* obj;
+ if (aClass->allocate != NULL)
+ obj = aClass->allocate(npp, aClass);
+ else
+ obj = (NPObject*)malloc(sizeof(NPObject));
+
+ obj->_class = aClass;
+ obj->referenceCount = 1;
+
+ return obj;
+ }
+
+ return 0;
+}
+
+NPObject* _NPN_RetainObject(NPObject* obj)
+{
+ ASSERT(obj);
+
+ if (obj)
+ obj->referenceCount++;
+
+ return obj;
+}
+
+void _NPN_ReleaseObject(NPObject* obj)
+{
+ ASSERT(obj);
+ ASSERT(obj->referenceCount >= 1);
+
+ if (obj && obj->referenceCount >= 1) {
+ if (--obj->referenceCount == 0)
+ _NPN_DeallocateObject(obj);
+ }
+}
+
+void _NPN_DeallocateObject(NPObject *obj)
+{
+ ASSERT(obj);
+
+ if (obj) {
+ if (obj->_class->deallocate)
+ obj->_class->deallocate(obj);
+ else
+ free(obj);
+ }
+}
+
+#endif
diff --git a/JavaScriptCore/bindings/npruntime.h b/JavaScriptCore/bindings/npruntime.h
new file mode 100644
index 0000000..fd1c192
--- /dev/null
+++ b/JavaScriptCore/bindings/npruntime.h
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2004, Apple Computer, Inc. and The Mozilla Foundation.
+ * 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 names of Apple Computer, Inc. ("Apple") or The Mozilla
+ * Foundation ("Mozilla") nor the names of their contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR 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, MOZILLA OR
+ * THEIR 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.
+ *
+ * Revision 1 (March 4, 2004):
+ * Initial proposal.
+ *
+ * Revision 2 (March 10, 2004):
+ * All calls into script were made asynchronous. Results are
+ * provided via the NPScriptResultFunctionPtr callback.
+ *
+ * Revision 3 (March 10, 2004):
+ * Corrected comments to not refer to class retain/release FunctionPtrs.
+ *
+ * Revision 4 (March 11, 2004):
+ * Added additional convenience NPN_SetExceptionWithUTF8().
+ * Changed NPHasPropertyFunctionPtr and NPHasMethodFunctionPtr to take NPClass
+ * pointers instead of NPObject pointers.
+ * Added NPIsValidIdentifier().
+ *
+ * Revision 5 (March 17, 2004):
+ * Added context parameter to result callbacks from ScriptObject functions.
+ *
+ * Revision 6 (March 29, 2004):
+ * Renamed functions implemented by user agent to NPN_*. Removed _ from
+ * type names.
+ * Renamed "JavaScript" types to "Script".
+ *
+ * Revision 7 (April 21, 2004):
+ * NPIdentifier becomes a void*, was int32_t
+ * Remove NP_IsValidIdentifier, renamed NP_IdentifierFromUTF8 to NP_GetIdentifier
+ * Added NPVariant and modified functions to use this new type.
+ *
+ * Revision 8 (July 9, 2004):
+ * Updated to joint Apple-Mozilla license.
+ *
+ * Revision 9 (August 12, 2004):
+ * Changed NPVariantType enum values to form PVariantType_XXX
+ * Added NPP arguments to NPObject functions.
+ * Replaced NPVariant functions with macros.
+ */
+#ifndef _NP_RUNTIME_H_
+#define _NP_RUNTIME_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "npapi.h"
+
+#if defined(XP_MACOSX) && defined(__LP64__)
+#error 64-bit Netscape plug-ins are not supported on Mac OS X
+#endif
+
+/*
+ This API is used to facilitate binding code written in C to script
+ objects. The API in this header does not assume the presence of a
+ user agent. That is, it can be used to bind C code to scripting
+ environments outside of the context of a user agent.
+
+ However, the normal use of the this API is in the context of a
+ scripting environment running in a browser or other user agent.
+ In particular it is used to support the extended Netscape
+ script-ability API for plugins (NP-SAP). NP-SAP is an extension
+ of the Netscape plugin API. As such we have adopted the use of
+ the "NP" prefix for this API.
+
+ The following NP{N|P}Variables were added to the Netscape plugin
+ API (in npapi.h):
+
+ NPNVWindowNPObject
+ NPNVPluginElementNPObject
+ NPPVpluginScriptableNPObject
+
+ These variables are exposed through NPN_GetValue() and
+ NPP_GetValue() (respectively) and are used to establish the
+ initial binding between the user agent and native code. The DOM
+ objects in the user agent can be examined and manipulated using
+ the NPN_ functions that operate on NPObjects described in this
+ header.
+
+ To the extent possible the assumptions about the scripting
+ language used by the scripting environment have been minimized.
+*/
+
+
+/*
+ Objects (non-primitive data) passed between 'C' and script is
+ always wrapped in an NPObject. The 'interface' of an NPObject is
+ described by an NPClass.
+*/
+typedef struct NPObject NPObject;
+typedef struct NPClass NPClass;
+
+typedef char NPUTF8;
+typedef struct _NPString {
+ const NPUTF8 *UTF8Characters;
+ uint32_t UTF8Length;
+} NPString;
+
+typedef enum {
+ NPVariantType_Void,
+ NPVariantType_Null,
+ NPVariantType_Bool,
+ NPVariantType_Int32,
+ NPVariantType_Double,
+ NPVariantType_String,
+ NPVariantType_Object
+} NPVariantType;
+
+typedef struct _NPVariant {
+ NPVariantType type;
+ union {
+ bool boolValue;
+ int32_t intValue;
+ double doubleValue;
+ NPString stringValue;
+ NPObject *objectValue;
+ } value;
+} NPVariant;
+
+/*
+ NPN_ReleaseVariantValue is called on all 'out' parameters references.
+ Specifically it is called on variants that are resultant out parameters
+ in NPGetPropertyFunctionPtr and NPInvokeFunctionPtr. Resultant variants
+ from these two functions should be initialized using the
+ NPN_InitializeVariantXXX() functions.
+
+ After calling NPReleaseVariantValue, the type of the variant will
+ be set to NPVariantUndefinedType.
+*/
+void NPN_ReleaseVariantValue (NPVariant *variant);
+
+#define NPVARIANT_IS_VOID(_v) ((_v).type == NPVariantType_Void)
+#define NPVARIANT_IS_NULL(_v) ((_v).type == NPVariantType_Null)
+#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool)
+#define NPVARIANT_IS_INT32(_v) ((_v).type == NPVariantType_Int32)
+#define NPVARIANT_IS_DOUBLE(_v) ((_v).type == NPVariantType_Double)
+#define NPVARIANT_IS_STRING(_v) ((_v).type == NPVariantType_String)
+#define NPVARIANT_IS_OBJECT(_v) ((_v).type == NPVariantType_Object)
+
+#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue)
+#define NPVARIANT_TO_INT32(_v) ((_v).value.intValue)
+#define NPVARIANT_TO_DOUBLE(_v) ((_v).value.doubleValue)
+#define NPVARIANT_TO_STRING(_v) ((_v).value.stringValue)
+#define NPVARIANT_TO_OBJECT(_v) ((_v).value.objectValue)
+
+#define NP_BEGIN_MACRO do {
+#define NP_END_MACRO } while (0)
+
+#define VOID_TO_NPVARIANT(_v) NP_BEGIN_MACRO (_v).type = NPVariantType_Void; (_v).value.objectValue = NULL; NP_END_MACRO
+#define NULL_TO_NPVARIANT(_v) NP_BEGIN_MACRO (_v).type = NPVariantType_Null; (_v).value.objectValue = NULL; NP_END_MACRO
+#define BOOLEAN_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_Bool; (_v).value.boolValue = !!(_val); NP_END_MACRO
+#define INT32_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_Int32; (_v).value.intValue = _val; NP_END_MACRO
+#define DOUBLE_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_Double; (_v).value.doubleValue = _val; NP_END_MACRO
+#define STRINGZ_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_String; NPString str = { _val, strlen(_val) }; (_v).value.stringValue = str; NP_END_MACRO
+#define STRINGN_TO_NPVARIANT(_val, _len, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_String; NPString str = { _val, _len }; (_v).value.stringValue = str; NP_END_MACRO
+#define OBJECT_TO_NPVARIANT(_val, _v) NP_BEGIN_MACRO (_v).type = NPVariantType_Object; (_v).value.objectValue = _val; NP_END_MACRO
+
+/*
+ Type mappings (JavaScript types have been used for illustration
+ purposes):
+
+ JavaScript to C (NPVariant with type:)
+ undefined NPVariantType_Void
+ null NPVariantType_Null
+ Boolean NPVariantType_Bool
+ Number NPVariantType_Double or NPVariantType_Int32
+ String NPVariantType_String
+ Object NPVariantType_Object
+
+ C (NPVariant with type:) to JavaScript
+ NPVariantType_Void undefined
+ NPVariantType_Null null
+ NPVariantType_Bool Boolean
+ NPVariantType_Int32 Number
+ NPVariantType_Double Number
+ NPVariantType_String String
+ NPVariantType_Object Object
+*/
+
+typedef void *NPIdentifier;
+
+/*
+ NPObjects have methods and properties. Methods and properties are
+ identified with NPIdentifiers. These identifiers may be reflected
+ in script. NPIdentifiers can be either strings or integers, IOW,
+ methods and properties can be identified by either strings or
+ integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be
+ compared using ==. In case of any errors, the requested
+ NPIdentifier(s) will be NULL.
+*/
+NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name);
+void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers);
+NPIdentifier NPN_GetIntIdentifier(int32_t intid);
+bool NPN_IdentifierIsString(NPIdentifier identifier);
+
+/*
+ The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed.
+*/
+NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier);
+
+/*
+ Get the integer represented by identifier. If identifier is not an
+ integer identifier, the behaviour is undefined.
+*/
+int32_t NPN_IntFromIdentifier(NPIdentifier identifier);
+
+/*
+ NPObject behavior is implemented using the following set of
+ callback functions.
+
+ The NPVariant *result argument of these functions (where
+ applicable) should be released using NPN_ReleaseVariantValue().
+*/
+typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass);
+typedef void (*NPDeallocateFunctionPtr)(NPObject *obj);
+typedef void (*NPInvalidateFunctionPtr)(NPObject *obj);
+typedef bool (*NPHasMethodFunctionPtr)(NPObject *obj, NPIdentifier name);
+typedef bool (*NPInvokeFunctionPtr)(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);
+typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+typedef bool (*NPHasPropertyFunctionPtr)(NPObject *obj, NPIdentifier name);
+typedef bool (*NPGetPropertyFunctionPtr)(NPObject *obj, NPIdentifier name, NPVariant *result);
+typedef bool (*NPSetPropertyFunctionPtr)(NPObject *obj, NPIdentifier name, const NPVariant *value);
+typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj, NPIdentifier name);
+typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value, uint32_t *count);
+
+/*
+ NPObjects returned by create have a reference count of one. It is the caller's responsibility
+ to release the returned object.
+
+ NPInvokeFunctionPtr function may return false to indicate a the method could not be invoked.
+
+ NPGetPropertyFunctionPtr and NPSetPropertyFunctionPtr may return false to indicate a property doesn't
+ exist.
+
+ NPInvalidateFunctionPtr is called by the scripting environment when the native code is
+ shutdown. Any attempt to message a NPObject instance after the invalidate
+ callback has been called will result in undefined behavior, even if the
+ native code is still retaining those NPObject instances.
+ (The runtime will typically return immediately, with 0 or NULL, from an attempt to
+ dispatch to a NPObject, but this behavior should not be depended upon.)
+
+ The NPEnumerationFunctionPtr function may pass an array of
+ NPIdentifiers back to the caller. The callee allocs the memory of
+ the array using NPN_MemAlloc(), and it's the caller's responsibility
+ to release it using NPN_MemFree().
+*/
+struct NPClass
+{
+ uint32_t structVersion;
+ NPAllocateFunctionPtr allocate;
+ NPDeallocateFunctionPtr deallocate;
+ NPInvalidateFunctionPtr invalidate;
+ NPHasMethodFunctionPtr hasMethod;
+ NPInvokeFunctionPtr invoke;
+ NPInvokeDefaultFunctionPtr invokeDefault;
+ NPHasPropertyFunctionPtr hasProperty;
+ NPGetPropertyFunctionPtr getProperty;
+ NPSetPropertyFunctionPtr setProperty;
+ NPRemovePropertyFunctionPtr removeProperty;
+ NPEnumerationFunctionPtr enumerate;
+};
+
+#define NP_CLASS_STRUCT_VERSION 2
+#define NP_CLASS_STRUCT_VERSION_ENUM 2
+#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \
+ ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
+
+struct NPObject {
+ NPClass *_class;
+ uint32_t referenceCount;
+ // Additional space may be allocated here by types of NPObjects
+};
+
+/*
+ If the class has an allocate function, NPN_CreateObject invokes that function,
+ otherwise a NPObject is allocated and returned. If a class has an allocate
+ function it is the responsibility of that implementation to set the initial retain
+ count to 1.
+*/
+NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
+
+/*
+ Increment the NPObject's reference count.
+*/
+NPObject *NPN_RetainObject (NPObject *obj);
+
+/*
+ Decremented the NPObject's reference count. If the reference
+ count goes to zero, the class's destroy function is invoke if
+ specified, otherwise the object is freed directly.
+*/
+void NPN_ReleaseObject (NPObject *obj);
+
+/*
+ Functions to access script objects represented by NPObject.
+
+ Calls to script objects are synchronous. If a function returns a
+ value, it will be supplied via the result NPVariant
+ argument. Successful calls will return true, false will be
+ returned in case of an error.
+
+ Calls made from plugin code to script must be made from the thread
+ on which the plugin was initialized.
+*/
+bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
+bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, NPVariant *result);
+bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVariant *result);
+bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value);
+bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
+bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count);
+
+/*
+ NPN_SetException may be called to trigger a script exception upon return
+ from entry points into NPObjects.
+*/
+void NPN_SetException (NPObject *obj, const NPUTF8 *message);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/JavaScriptCore/bindings/npruntime_impl.h b/JavaScriptCore/bindings/npruntime_impl.h
new file mode 100644
index 0000000..84e63ce
--- /dev/null
+++ b/JavaScriptCore/bindings/npruntime_impl.h
@@ -0,0 +1,64 @@
+/*
+ * 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 _NP_RUNTIME_IMPL_H_
+#define _NP_RUNTIME_IMPL_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void _NPN_ReleaseVariantValue(NPVariant *variant);
+extern NPIdentifier _NPN_GetStringIdentifier(const NPUTF8 *name);
+extern void _NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers);
+extern NPIdentifier _NPN_GetIntIdentifier(int32_t intid);
+extern bool _NPN_IdentifierIsString(NPIdentifier identifier);
+extern NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier);
+extern int32_t _NPN_IntFromIdentifier(NPIdentifier identifier);
+extern NPObject *_NPN_CreateObject(NPP npp, NPClass *aClass);
+extern NPObject *_NPN_RetainObject(NPObject *obj);
+extern void _NPN_ReleaseObject(NPObject *obj);
+extern void _NPN_DeallocateObject(NPObject *obj);
+extern bool _NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
+extern bool _NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+extern bool _NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, NPVariant *result);
+extern bool _NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPVariant *result);
+extern bool _NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value);
+extern bool _NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+extern bool _NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
+extern bool _NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
+extern void _NPN_SetException(NPObject *obj, const NPUTF8 *message);
+extern bool _NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif
+#endif
diff --git a/JavaScriptCore/bindings/npruntime_internal.h b/JavaScriptCore/bindings/npruntime_internal.h
new file mode 100644
index 0000000..f5357cd
--- /dev/null
+++ b/JavaScriptCore/bindings/npruntime_internal.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007 Collabora, Ltd. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * This is a internal include header for npapi.h
+ *
+ * Some of the #defines which are in X11 headers conflict with type and enum
+ * names in JavaScriptCore and WebCore
+ * This header #undefs those defines to fix the conflicts
+ * If you need to include npapi.h or npruntime.h when building on X11,
+ * include this file instead of the actual npapi.h or npruntime.h
+ */
+
+#include "npruntime.h"
+
+#ifdef XP_UNIX
+ #include <X11/Xresource.h>
+
+ #undef None
+ #undef Above
+ #undef Below
+ #undef Auto
+ #undef Complex
+ #undef Status
+#endif
diff --git a/JavaScriptCore/bindings/npruntime_priv.h b/JavaScriptCore/bindings/npruntime_priv.h
new file mode 100644
index 0000000..b19b16a
--- /dev/null
+++ b/JavaScriptCore/bindings/npruntime_priv.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2003, 2006 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 NP_RUNTIME_PRIV_H_
+#define NP_RUNTIME_PRIV_H_
+
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+
+#include "npruntime_internal.h"
+
+/*
+ NPN_InitializeVariantWithStringCopy() will copy string data. The string data
+ will be deallocated by calls to NPReleaseVariantValue().
+*/
+void NPN_InitializeVariantWithStringCopy(NPVariant*, const NPString*);
+
+#endif
+#endif
+
diff --git a/JavaScriptCore/bindings/objc/WebScriptObject.h b/JavaScriptCore/bindings/objc/WebScriptObject.h
new file mode 100644
index 0000000..14d77d7
--- /dev/null
+++ b/JavaScriptCore/bindings/objc/WebScriptObject.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+#include "internal.h"
+#include "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:(KJS::JSValue *)value originRootObject:(KJS::Bindings::RootObject*)originRootObject rootObject:(KJS::Bindings::RootObject*)rootObject;
+- _initWithJSObject:(KJS::JSObject*)imp originRootObject:(PassRefPtr<KJS::Bindings::RootObject>)originRootObject rootObject:(PassRefPtr<KJS::Bindings::RootObject>)rootObject;
+- (KJS::JSObject *)_imp;
+@end
+
+@protocol WebUndefined
++ (WebUndefined *)undefined;
+@end
diff --git a/JavaScriptCore/bindings/objc/objc_class.h b/JavaScriptCore/bindings/objc/objc_class.h
new file mode 100644
index 0000000..3faee18
--- /dev/null
+++ b/JavaScriptCore/bindings/objc/objc_class.h
@@ -0,0 +1,61 @@
+/*
+ * 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 <JavaScriptCore/objc_runtime.h>
+
+namespace KJS {
+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 const char *name() const;
+
+ 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 KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/objc/objc_class.mm b/JavaScriptCore/bindings/objc/objc_class.mm
new file mode 100644
index 0000000..e3a72f7
--- /dev/null
+++ b/JavaScriptCore/bindings/objc/objc_class.mm
@@ -0,0 +1,258 @@
+/*
+ * 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 KJS {
+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;
+}
+
+const char* ObjcClass::name() const
+{
+ return object_getClassName(_isa);
+}
+
+MethodList ObjcClass::methodsNamed(const Identifier& identifier, Instance*) const
+{
+ MethodList methodList;
+ char fixedSizeBuffer[1024];
+ char* buffer = fixedSizeBuffer;
+ const char* JSName = identifier.ascii();
+ if (!convertJSMethodNameToObjc(JSName, buffer, sizeof(fixedSizeBuffer))) {
+ int length = strlen(JSName) + 1;
+ buffer = new char[length];
+ if (!buffer || !convertJSMethodNameToObjc(JSName, 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, objcMethodSelectorName); // 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;
+
+ const char* name = identifier.ascii();
+ RetainPtr<CFStringRef> fieldName(AdoptCF, CFStringCreateWithCString(NULL, name, 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, name) == 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*, 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 ObjcFallbackObjectImp(objcInstance, propertyName);
+}
+
+}
+}
diff --git a/JavaScriptCore/bindings/objc/objc_header.h b/JavaScriptCore/bindings/objc/objc_header.h
new file mode 100644
index 0000000..07954a1
--- /dev/null
+++ b/JavaScriptCore/bindings/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/JavaScriptCore/bindings/objc/objc_instance.h b/JavaScriptCore/bindings/objc/objc_instance.h
new file mode 100644
index 0000000..2233791
--- /dev/null
+++ b/JavaScriptCore/bindings/objc/objc_instance.h
@@ -0,0 +1,81 @@
+/*
+ * 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 BINDINGS_OBJC_INSTANCE_H_
+#define BINDINGS_OBJC_INSTANCE_H_
+
+#include <JavaScriptCore/objc_class.h>
+#include <JavaScriptCore/objc_utility.h>
+
+namespace KJS {
+
+namespace Bindings {
+
+class ObjcClass;
+
+class ObjcInstance : public Instance {
+public:
+ ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject>);
+
+ ~ObjcInstance();
+
+ virtual Class *getClass() const;
+
+ virtual void begin();
+ virtual void end();
+
+ virtual JSValue *valueOf() const;
+ virtual JSValue *defaultValue(JSType hint) const;
+
+ virtual bool implementsCall() const;
+
+ virtual JSValue *invokeMethod(ExecState *exec, const MethodList &method, const List &args);
+ virtual JSValue *invokeDefaultMethod(ExecState *exec, const List &args);
+
+ virtual bool supportsSetValueOfUndefinedField();
+ virtual void setValueOfUndefinedField(ExecState *exec, const Identifier &property, JSValue *aValue);
+
+ virtual JSValue *getValueOfUndefinedField(ExecState *exec, const Identifier &property, JSType hint) const;
+
+ ObjectStructPtr getObject() const { return _instance.get(); }
+
+ JSValue *stringValue() const;
+ JSValue *numberValue() const;
+ JSValue *booleanValue() const;
+
+ virtual BindingLanguage getBindingLanguage() const { return ObjectiveCLanguage; }
+
+private:
+ RetainPtr<ObjectStructPtr> _instance;
+ mutable ObjcClass *_class;
+ ObjectStructPtr _pool;
+ int _beginCount;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif // BINDINGS_OBJC_INSTANCE_H_
diff --git a/JavaScriptCore/bindings/objc/objc_instance.mm b/JavaScriptCore/bindings/objc/objc_instance.mm
new file mode 100644
index 0000000..57ebfe8
--- /dev/null
+++ b/JavaScriptCore/bindings/objc/objc_instance.mm
@@ -0,0 +1,349 @@
+/*
+ * 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.
+ */
+
+#import "config.h"
+#import "objc_instance.h"
+
+#import "WebScriptObject.h"
+#include <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 KJS::Bindings;
+using namespace KJS;
+
+ObjcInstance::ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+ , _instance(instance)
+ , _class(0)
+ , _pool(0)
+ , _beginCount(0)
+{
+}
+
+ObjcInstance::~ObjcInstance()
+{
+ begin(); // -finalizeForWebScript and -dealloc/-finalize may require autorelease pools.
+ if ([_instance.get() respondsToSelector:@selector(finalizeForWebScript)])
+ [_instance.get() performSelector:@selector(finalizeForWebScript)];
+ _instance = 0;
+ end();
+}
+
+void ObjcInstance::begin()
+{
+ if (!_pool)
+ _pool = [[NSAutoreleasePool alloc] init];
+ _beginCount++;
+}
+
+void ObjcInstance::end()
+{
+ _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::implementsCall() const
+{
+ return [_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)];
+}
+
+JSValue* ObjcInstance::invokeMethod(ExecState* exec, const MethodList &methodList, const List &args)
+{
+ JSValue* result = jsUndefined();
+
+ JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ // Overloading methods is not allowed in ObjectiveC. Should only be one
+ // name match for a particular method.
+ ASSERT(methodList.size() == 1);
+
+@try {
+ ObjcMethod* method = 0;
+ method = static_cast<ObjcMethod*>(methodList[0]);
+ NSMethodSignature* signature = method->getMethodSignature();
+ NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ [invocation setSelector:sel_registerName(method->name())];
+#else
+ [invocation setSelector:(SEL)method->name()];
+#endif
+ [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 = args.size();
+ for (int i = 0; i < count; i++) {
+ ObjcValue value = convertValueToObjcValue(exec, args.at(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, args.at(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, _rootObject.get());
+ }
+} @catch(NSException* localException) {
+}
+ return result;
+}
+
+JSValue* ObjcInstance::invokeDefaultMethod(ExecState* exec, const List &args)
+{
+ JSValue* result = jsUndefined();
+
+ JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+@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 = args.size();
+ for (unsigned i = 0; i < count; i++) {
+ ObjcValue value = convertValueToObjcValue(exec, args.at(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, _rootObject.get());
+} @catch(NSException* localException) {
+}
+
+ return result;
+}
+
+bool ObjcInstance::supportsSetValueOfUndefinedField()
+{
+ id targetObject = getObject();
+ if ([targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)])
+ return true;
+ return false;
+}
+
+void ObjcInstance::setValueOfUndefinedField(ExecState* exec, const Identifier &property, JSValue* aValue)
+{
+ id targetObject = getObject();
+
+ JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ // This check is not really necessary because NSObject implements
+ // setValue:forUndefinedKey:, and unfortnately the default implementation
+ // throws an exception.
+ if ([targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)]){
+ ObjcValue objcValue = convertValueToObjcValue(exec, aValue, ObjcObjectType);
+
+ @try {
+ [targetObject setValue:objcValue.objectValue forUndefinedKey:[NSString stringWithCString:property.ascii() encoding:NSASCIIStringEncoding]];
+ } @catch(NSException* localException) {
+ // Do nothing. Class did not override valueForUndefinedKey:.
+ }
+ }
+}
+
+JSValue* ObjcInstance::getValueOfUndefinedField(ExecState* exec, const Identifier& property, JSType) const
+{
+ JSValue* result = jsUndefined();
+
+ id targetObject = getObject();
+
+ JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ // This check is not really necessary because NSObject implements
+ // valueForUndefinedKey:, and unfortnately the default implementation
+ // throws an exception.
+ if ([targetObject respondsToSelector:@selector(valueForUndefinedKey:)]){
+ @try {
+ id objcValue = [targetObject valueForUndefinedKey:[NSString stringWithCString:property.ascii() encoding:NSASCIIStringEncoding]];
+ result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, _rootObject.get());
+ } @catch(NSException* localException) {
+ // Do nothing. Class did not override valueForUndefinedKey:.
+ }
+ }
+
+ return result;
+}
+
+JSValue* ObjcInstance::defaultValue(JSType hint) const
+{
+ switch (hint) {
+ case StringType:
+ return stringValue();
+ case NumberType:
+ return numberValue();
+ case BooleanType:
+ return booleanValue();
+ case UnspecifiedType:
+ if ([_instance.get() isKindOfClass:[NSString class]])
+ return stringValue();
+ if ([_instance.get() isKindOfClass:[NSNumber class]])
+ return numberValue();
+ default:
+ return valueOf();
+ }
+}
+
+JSValue* ObjcInstance::stringValue() const
+{
+ return convertNSStringToString([getObject() description]);
+}
+
+JSValue* ObjcInstance::numberValue() const
+{
+ // FIXME: Implement something sensible
+ return jsNumber(0);
+}
+
+JSValue* ObjcInstance::booleanValue() const
+{
+ // FIXME: Implement something sensible
+ return jsBoolean(false);
+}
+
+JSValue* ObjcInstance::valueOf() const
+{
+ return stringValue();
+}
diff --git a/JavaScriptCore/bindings/objc/objc_runtime.h b/JavaScriptCore/bindings/objc/objc_runtime.h
new file mode 100644
index 0000000..74bc49e
--- /dev/null
+++ b/JavaScriptCore/bindings/objc/objc_runtime.h
@@ -0,0 +1,127 @@
+/*
+ * 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_RUNTIME_H
+#define KJS_BINDINGS_OBJC_RUNTIME_H
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <JavaScriptCore/objc_header.h>
+#include <JavaScriptCore/object.h>
+#include <JavaScriptCore/runtime.h>
+
+#include <wtf/RetainPtr.h>
+
+namespace KJS {
+namespace Bindings {
+
+extern ClassStructPtr webScriptObjectClass();
+extern ClassStructPtr webUndefinedClass();
+
+class ObjcInstance;
+
+class ObjcField : public Field
+{
+public:
+ ObjcField(IvarStructPtr ivar);
+ ObjcField(CFStringRef name);
+
+ virtual JSValue *valueFromInstance(ExecState *exec, const Instance *instance) const;
+ virtual void setValueToInstance(ExecState *exec, const Instance *instance, JSValue *aValue) const;
+
+ virtual const char *name() const;
+
+private:
+ IvarStructPtr _ivar;
+ RetainPtr<CFStringRef> _name;
+};
+
+class ObjcMethod : public Method
+{
+public:
+ ObjcMethod() : _objcClass(0), _selector(0), _javaScriptName(0) {}
+ ObjcMethod(ClassStructPtr aClass, const char *_selector);
+
+ virtual const char *name() const;
+
+ virtual int numParameters() const;
+
+ NSMethodSignature *getMethodSignature() const;
+
+ bool isFallbackMethod() const { return strcmp(_selector, "invokeUndefinedMethodFromWebScript:withArguments:") == 0; }
+ void setJavaScriptName(CFStringRef n) { _javaScriptName = n; }
+ CFStringRef javaScriptName() const { return _javaScriptName.get(); }
+
+private:
+ ClassStructPtr _objcClass;
+ const char *_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 JSObject {
+public:
+ ObjcFallbackObjectImp(ObjcInstance *i, const Identifier propertyName);
+
+ const ClassInfo *classInfo() const { return &info; }
+
+ virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
+ virtual bool implementsCall() const;
+ virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+ virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
+ virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
+
+ virtual JSType type() const;
+ virtual bool toBoolean(ExecState *exec) const;
+
+private:
+ ObjcFallbackObjectImp(); // prevent default construction
+
+ static const ClassInfo info;
+
+ RefPtr<ObjcInstance> _instance;
+ Identifier _item;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/objc/objc_runtime.mm b/JavaScriptCore/bindings/objc/objc_runtime.mm
new file mode 100644
index 0000000..14877b4
--- /dev/null
+++ b/JavaScriptCore/bindings/objc/objc_runtime.mm
@@ -0,0 +1,289 @@
+/*
+ * 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_runtime.h"
+
+#include "objc_instance.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include "WebScriptObject.h"
+
+using namespace KJS;
+using namespace KJS::Bindings;
+
+extern ClassStructPtr KJS::Bindings::webScriptObjectClass()
+{
+ static ClassStructPtr<WebScriptObject> webScriptObjectClass = NSClassFromString(@"WebScriptObject");
+ return webScriptObjectClass;
+}
+
+extern ClassStructPtr KJS::Bindings::webUndefinedClass()
+{
+ static ClassStructPtr<WebUndefined> webUndefinedClass = NSClassFromString(@"WebUndefined");
+ return webUndefinedClass;
+}
+
+// ---------------------- ObjcMethod ----------------------
+
+ObjcMethod::ObjcMethod(ClassStructPtr aClass, const char* name)
+{
+ _objcClass = aClass;
+ _selector = name; // Assume ObjC runtime keeps these around forever.
+ _javaScriptName = 0;
+}
+
+const char* ObjcMethod::name() const
+{
+ return _selector;
+}
+
+int ObjcMethod::numParameters() const
+{
+ return [getMethodSignature() numberOfArguments] - 2;
+}
+
+NSMethodSignature* ObjcMethod::getMethodSignature() const
+{
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ return [_objcClass instanceMethodSignatureForSelector:sel_registerName(_selector)];
+#else
+ return [_objcClass instanceMethodSignatureForSelector:(SEL)_selector];
+#endif
+}
+
+// ---------------------- ObjcField ----------------------
+
+ObjcField::ObjcField(Ivar ivar)
+{
+ _ivar = ivar; // Assume ObjectiveC runtime will keep this alive forever
+ _name = 0;
+}
+
+ObjcField::ObjcField(CFStringRef name)
+{
+ _ivar = 0;
+ _name = (CFStringRef)CFRetain(name);
+}
+
+const char* ObjcField::name() const
+{
+#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
+ if (_ivar)
+ return ivar_getName(_ivar);
+#else
+ if (_ivar)
+ return _ivar->ivar_name;
+#endif
+ return [(NSString*)_name.get() UTF8String];
+}
+
+JSValue* ObjcField::valueFromInstance(ExecState* exec, const Instance* instance) const
+{
+ JSValue* result = jsUndefined();
+
+ id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();
+
+ JSLock::DropAllLocks dropAllLocks; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ @try {
+ NSString* key = [NSString stringWithCString:name() encoding:NSASCIIStringEncoding];
+ if (id objcValue = [targetObject valueForKey:key])
+ result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, instance->rootObject());
+ } @catch(NSException* localException) {
+ JSLock::lock();
+ throwError(exec, GeneralError, [localException reason]);
+ JSLock::unlock();
+ }
+
+ return 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; // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ @try {
+ NSString* key = [NSString stringWithCString:name() encoding:NSASCIIStringEncoding];
+ [targetObject setValue:value forKey:key];
+ } @catch(NSException* localException) {
+ JSLock::lock();
+ throwError(exec, GeneralError, [localException reason]);
+ JSLock::unlock();
+ }
+}
+
+// ---------------------- 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, TypeError, "Array is not mutable.");
+ return;
+ }
+
+ if (index > [_array.get() count]) {
+ throwError(exec, RangeError, "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, GeneralError, "Objective-C exception.");
+ }
+}
+
+JSValue* ObjcArray::valueAt(ExecState* exec, unsigned int index) const
+{
+ if (index > [_array.get() count])
+ return throwError(exec, RangeError, "Index exceeds array size.");
+ @try {
+ id obj = [_array.get() objectAtIndex:index];
+ if (obj)
+ return convertObjcValueToValue (exec, &obj, ObjcObjectType, _rootObject.get());
+ } @catch(NSException* localException) {
+ return throwError(exec, GeneralError, "Objective-C exception.");
+ }
+ return jsUndefined();
+}
+
+unsigned int ObjcArray::getLength() const
+{
+ return [_array.get() count];
+}
+
+const ClassInfo ObjcFallbackObjectImp::info = { "ObjcFallbackObject", 0, 0 };
+
+ObjcFallbackObjectImp::ObjcFallbackObjectImp(ObjcInstance* i, const KJS::Identifier propertyName)
+: _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(this);
+ return true;
+}
+
+void ObjcFallbackObjectImp::put(ExecState*, const Identifier&, JSValue*)
+{
+}
+
+JSType ObjcFallbackObjectImp::type() const
+{
+ id targetObject = _instance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return ObjectType;
+
+ return UndefinedType;
+}
+
+bool ObjcFallbackObjectImp::implementsCall() const
+{
+ id targetObject = _instance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return true;
+
+ return false;
+}
+
+JSValue* ObjcFallbackObjectImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
+{
+ if (thisObj->classInfo() != &KJS::RuntimeObjectImp::info)
+ return throwError(exec, TypeError);
+
+ JSValue* result = jsUndefined();
+
+ RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(thisObj);
+ Instance* instance = imp->getInternalInstance();
+
+ if (!instance)
+ return RuntimeObjectImp::throwInvalidAccessError(exec);
+
+ instance->begin();
+
+ ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);
+ id targetObject = objcInstance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)]){
+ MethodList methodList;
+ ObjcClass* objcClass = static_cast<ObjcClass*>(instance->getClass());
+ ObjcMethod* fallbackMethod = new ObjcMethod (objcClass->isa(), sel_getName(@selector(invokeUndefinedMethodFromWebScript:withArguments:)));
+ fallbackMethod->setJavaScriptName((CFStringRef)[NSString stringWithCString:_item.ascii() encoding:NSASCIIStringEncoding]);
+ methodList.append(fallbackMethod);
+ result = instance->invokeMethod(exec, methodList, args);
+ delete fallbackMethod;
+ }
+
+ instance->end();
+
+ return result;
+}
+
+bool ObjcFallbackObjectImp::deleteProperty(ExecState*, const Identifier&)
+{
+ return false;
+}
+
+JSValue* ObjcFallbackObjectImp::defaultValue(ExecState* exec, JSType hint) const
+{
+ return _instance->getValueOfUndefinedField(exec, _item, hint);
+}
+
+bool ObjcFallbackObjectImp::toBoolean(ExecState *) const
+{
+ id targetObject = _instance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return true;
+
+ return false;
+}
diff --git a/JavaScriptCore/bindings/objc/objc_utility.h b/JavaScriptCore/bindings/objc/objc_utility.h
new file mode 100644
index 0000000..e674fcc
--- /dev/null
+++ b/JavaScriptCore/bindings/objc/objc_utility.h
@@ -0,0 +1,87 @@
+/*
+ * 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 "object.h"
+#include "objc_header.h"
+
+#ifdef __OBJC__
+@class NSString;
+#else
+class NSString;
+#endif
+
+namespace KJS {
+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 *exec, JSValue *value, ObjcValueType type);
+JSValue *convertNSStringToString(NSString *nsstring);
+JSValue *convertObjcValueToValue(ExecState *exec, void *buffer, ObjcValueType type, RootObject*);
+ObjcValueType objcValueTypeForType(const char *type);
+
+bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize);
+
+JSObject *throwError(ExecState *, ErrorType, NSString *message);
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/objc/objc_utility.mm b/JavaScriptCore/bindings/objc/objc_utility.mm
new file mode 100644
index 0000000..62a0ad0
--- /dev/null
+++ b/JavaScriptCore/bindings/objc/objc_utility.mm
@@ -0,0 +1,372 @@
+/*
+ * 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 "JSGlobalObject.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include "WebScriptObject.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 KJS {
+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;
+
+ JSGlobalObject *originGlobalObject = exec->dynamicGlobalObject();
+ RootObject* originRootObject = findRootObject(originGlobalObject);
+
+ JSGlobalObject* globalObject = 0;
+ if (value->isObject() && static_cast<JSObject*>(value)->isGlobalObject())
+ globalObject = static_cast<JSGlobalObject*>(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(NSString *nsstring)
+{
+ JSLock lock;
+
+ 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(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;
+
+ switch (type) {
+ case ObjcObjectType: {
+ id obj = *(id*)buffer;
+ if ([obj isKindOfClass:[NSString class]])
+ return convertNSStringToString((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 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 Instance::createRuntimeObject(Instance::ObjectiveCLanguage, obj, rootObject);
+ }
+ 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 0;
+}
+
+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, ErrorType type, NSString *message)
+{
+ ASSERT(message);
+ size_t length = [message length];
+ unichar *buffer = new unichar[length];
+ [message getCharacters:buffer];
+ JSObject *error = throwError(exec, type, UString(reinterpret_cast<UChar *>(buffer), length));
+ delete [] buffer;
+ return error;
+}
+
+}
+}
diff --git a/JavaScriptCore/bindings/qt/qt_class.cpp b/JavaScriptCore/bindings/qt/qt_class.cpp
new file mode 100644
index 0000000..59730b8
--- /dev/null
+++ b/JavaScriptCore/bindings/qt/qt_class.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "identifier.h"
+
+#include "qt_class.h"
+#include "qt_instance.h"
+#include "qt_runtime.h"
+
+#include <qmetaobject.h>
+#include <qdebug.h>
+
+namespace KJS {
+namespace Bindings {
+
+QtClass::QtClass(const QMetaObject* mo)
+ : m_metaObject(mo)
+{
+}
+
+QtClass::~QtClass()
+{
+}
+
+typedef HashMap<const QMetaObject*, QtClass*> ClassesByMetaObject;
+static ClassesByMetaObject* classesByMetaObject = 0;
+
+QtClass* QtClass::classForObject(QObject* o)
+{
+ if (!classesByMetaObject)
+ classesByMetaObject = new ClassesByMetaObject;
+
+ const QMetaObject* mo = o->metaObject();
+ QtClass* aClass = classesByMetaObject->get(mo);
+ if (!aClass) {
+ aClass = new QtClass(mo);
+ classesByMetaObject->set(mo, aClass);
+ }
+
+ return aClass;
+}
+
+const char* QtClass::name() const
+{
+ return m_metaObject->className();
+}
+
+// We use this to get at signals (so we can return a proper function object,
+// and not get wrapped in RuntimeMethod). Also, use this for methods,
+// so we can cache the JSValue* and return the same JSValue for the same
+// identifier...
+//
+// Unfortunately... we need to gcProtect our JSValues, since we don't have
+// access to an actual JS class that can mark() our JSValues.
+//
+JSValue* QtClass::fallbackObject(ExecState *exec, Instance *inst, const Identifier &identifier)
+{
+ QtInstance* qtinst = static_cast<QtInstance*>(inst);
+
+ QByteArray name(identifier.ascii());
+
+ // First see if we have a cache hit
+ JSValue* val = qtinst->m_methods.value(name);
+ if (val)
+ return val;
+
+ // Nope, create an entry
+ QByteArray normal = QMetaObject::normalizedSignature(name.constData());
+
+ // See if there is an exact match
+ int index = -1;
+ if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) {
+ QMetaMethod m = m_metaObject->method(index);
+ if (m.access() != QMetaMethod::Private) {
+ JSValue *val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
+ gcProtect(val);
+ qtinst->m_methods.insert(name, val);
+ return val;
+ }
+ }
+
+ // Nope.. try a basename match
+ int count = m_metaObject->methodCount();
+ for (index = count - 1; index >= 0; --index) {
+ const QMetaMethod m = m_metaObject->method(index);
+ if (m.access() == QMetaMethod::Private)
+ continue;
+
+ QByteArray signature = m.signature();
+ signature.truncate(signature.indexOf('('));
+
+ if (normal == signature) {
+ JSValue* val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
+ gcProtect(val);
+ qtinst->m_methods.insert(name, val);
+ return val;
+ }
+ }
+
+ return jsUndefined();
+}
+
+// This functionality is handled by the fallback case above...
+MethodList QtClass::methodsNamed(const Identifier&, Instance*) const
+{
+ return MethodList();
+}
+
+// ### we may end up with a different search order than QtScript by not
+// folding this code into the fallbackMethod above, but Fields propagate out
+// of the binding code
+Field* QtClass::fieldNamed(const Identifier& identifier, Instance* instance) const
+{
+ // Check static properties first
+ QtInstance* qtinst = static_cast<QtInstance*>(instance);
+
+ QObject* obj = qtinst->getObject();
+ UString ustring = identifier.ustring();
+ QString objName(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()));
+ QByteArray ba = objName.toAscii();
+
+ // First check for a cached field
+ QtField* f = qtinst->m_fields.value(objName);
+
+ if (obj) {
+ if (f) {
+ // We only cache real metaproperties, but we do store the
+ // other types so we can delete them later
+ if (f->fieldType() == QtField::MetaProperty)
+ return f;
+ else if (f->fieldType() == QtField::DynamicProperty) {
+ if (obj->dynamicPropertyNames().indexOf(ba) >= 0)
+ return f;
+ else {
+ // Dynamic property that disappeared
+ qtinst->m_fields.remove(objName);
+ delete f;
+ }
+ } else {
+ QList<QObject*> children = obj->children();
+ for (int index = 0; index < children.count(); ++index) {
+ QObject *child = children.at(index);
+ if (child->objectName() == objName)
+ return f;
+ }
+
+ // Didn't find it, delete it from the cache
+ qtinst->m_fields.remove(objName);
+ delete f;
+ }
+ }
+
+ int index = m_metaObject->indexOfProperty(identifier.ascii());
+ if (index >= 0) {
+ QMetaProperty prop = m_metaObject->property(index);
+
+ if (prop.isScriptable(obj)) {
+ f = new QtField(prop);
+ qtinst->m_fields.insert(objName, f);
+ return f;
+ }
+ }
+
+ // Dynamic properties
+ index = obj->dynamicPropertyNames().indexOf(ba);
+ if (index >= 0) {
+ f = new QtField(ba);
+ qtinst->m_fields.insert(objName, f);
+ return f;
+ }
+
+ // Child objects
+
+ QList<QObject*> children = obj->children();
+ for (index = 0; index < children.count(); ++index) {
+ QObject *child = children.at(index);
+ if (child->objectName() == objName) {
+ f = new QtField(child);
+ qtinst->m_fields.insert(objName, f);
+ return f;
+ }
+ }
+
+ // Nothing named this
+ return 0;
+ } else {
+ QByteArray ba(identifier.ascii());
+ // For compatibility with qtscript, cached methods don't cause
+ // errors until they are accessed, so don't blindly create an error
+ // here.
+ if (qtinst->m_methods.contains(ba))
+ return 0;
+
+ // deleted qobject, but can't throw an error from here (no exec)
+ // create a fake QtField that will throw upon access
+ if (!f) {
+ f = new QtField(ba);
+ qtinst->m_fields.insert(objName, f);
+ }
+ return f;
+ }
+}
+
+}
+}
+
diff --git a/JavaScriptCore/bindings/qt/qt_class.h b/JavaScriptCore/bindings/qt/qt_class.h
new file mode 100644
index 0000000..c3e59ec
--- /dev/null
+++ b/JavaScriptCore/bindings/qt/qt_class.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef BINDINGS_QT_CLASS_H_
+#define BINDINGS_QT_CLASS_H_
+
+#include "runtime.h"
+class QObject;
+class QMetaObject;
+
+namespace KJS {
+namespace Bindings {
+
+
+class QtClass : public Class {
+protected:
+ QtClass(const QMetaObject*);
+
+public:
+ static QtClass* classForObject(QObject*);
+ virtual ~QtClass();
+
+ virtual const char* name() const;
+ virtual MethodList methodsNamed(const Identifier&, Instance*) const;
+ virtual Field* fieldNamed(const Identifier&, Instance*) const;
+
+ virtual JSValue* fallbackObject(ExecState*, Instance*, const Identifier&);
+
+private:
+ QtClass(const QtClass&); // prohibit copying
+ QtClass& operator=(const QtClass&); // prohibit assignment
+
+ const QMetaObject* m_metaObject;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/qt/qt_instance.cpp b/JavaScriptCore/bindings/qt/qt_instance.cpp
new file mode 100644
index 0000000..0197b84
--- /dev/null
+++ b/JavaScriptCore/bindings/qt/qt_instance.cpp
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "qt_instance.h"
+
+#include "JSGlobalObject.h"
+#include "list.h"
+#include "qt_class.h"
+#include "qt_runtime.h"
+#include "PropertyNameArray.h"
+#include "runtime_object.h"
+#include "object_object.h"
+
+#include <qmetaobject.h>
+#include <qdebug.h>
+#include <qmetatype.h>
+#include <qhash.h>
+
+namespace KJS {
+namespace Bindings {
+
+// Cache QtInstances
+typedef QMultiHash<void*, QtInstance*> QObjectInstanceMap;
+static QObjectInstanceMap cachedInstances;
+
+// Cache JSObjects
+typedef QHash<QtInstance*, JSObject*> InstanceJSObjectMap;
+static InstanceJSObjectMap cachedObjects;
+
+// Derived RuntimeObject
+class QtRuntimeObjectImp : public RuntimeObjectImp {
+ public:
+ QtRuntimeObjectImp(Instance*);
+ ~QtRuntimeObjectImp();
+ virtual void invalidate();
+
+ // Additions
+ virtual bool implementsConstruct() const {return implementsCall();}
+ virtual JSObject* construct(ExecState* exec, const List& args);
+ protected:
+ void removeFromCache();
+};
+
+QtRuntimeObjectImp::QtRuntimeObjectImp(Instance* instance)
+ : RuntimeObjectImp(instance)
+{
+}
+
+QtRuntimeObjectImp::~QtRuntimeObjectImp()
+{
+ removeFromCache();
+}
+
+void QtRuntimeObjectImp::invalidate()
+{
+ removeFromCache();
+ RuntimeObjectImp::invalidate();
+}
+
+void QtRuntimeObjectImp::removeFromCache()
+{
+ JSLock lock;
+ QtInstance* key = cachedObjects.key(this);
+ if (key)
+ cachedObjects.remove(key);
+}
+
+JSObject* QtRuntimeObjectImp::construct(ExecState* exec, const List& args)
+{
+ // ECMA 15.2.2.1 (?)
+ JSValue *val = callAsFunction(exec, this, args);
+
+ if (!val || val->type() == NullType || val->type() == UndefinedType)
+ return new JSObject(exec->lexicalGlobalObject()->objectPrototype());
+ else
+ return val->toObject(exec);
+}
+
+// QtInstance
+QtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+ , m_class(0)
+ , m_object(o)
+ , m_hashkey(o)
+ , m_defaultMethod(0)
+ , m_defaultMethodIndex(-2)
+{
+}
+
+QtInstance::~QtInstance()
+{
+ JSLock lock;
+
+ cachedObjects.remove(this);
+ cachedInstances.remove(m_hashkey);
+
+ // clean up (unprotect from gc) the JSValues we've created
+ foreach(JSValue* val, m_methods.values()) {
+ gcUnprotect(val);
+ }
+ m_methods.clear();
+
+ foreach(QtField* f, m_fields.values()) {
+ delete f;
+ }
+ m_fields.clear();
+
+ if (m_defaultMethod)
+ gcUnprotect(m_defaultMethod);
+}
+
+QtInstance* QtInstance::getQtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
+{
+ JSLock lock;
+
+ foreach(QtInstance* instance, cachedInstances.values(o)) {
+ if (instance->rootObject() == rootObject)
+ return instance;
+ }
+
+ QtInstance* ret = new QtInstance(o, rootObject);
+ cachedInstances.insert(o, ret);
+
+ return ret;
+}
+
+JSObject* QtInstance::getRuntimeObject(QtInstance* instance)
+{
+ JSLock lock;
+ JSObject* ret = cachedObjects.value(instance);
+ if (!ret) {
+ ret = new QtRuntimeObjectImp(instance);
+ cachedObjects.insert(instance, ret);
+ }
+ return ret;
+}
+
+Class* QtInstance::getClass() const
+{
+ if (!m_class)
+ m_class = QtClass::classForObject(m_object);
+ return m_class;
+}
+
+void QtInstance::begin()
+{
+ // Do nothing.
+}
+
+void QtInstance::end()
+{
+ // Do nothing.
+}
+
+void QtInstance::getPropertyNames(ExecState* , PropertyNameArray& array)
+{
+ // This is the enumerable properties, so put:
+ // properties
+ // dynamic properties
+ // slots
+ QObject* obj = getObject();
+ if (obj) {
+ const QMetaObject* meta = obj->metaObject();
+
+ int i;
+ for (i=0; i < meta->propertyCount(); i++) {
+ QMetaProperty prop = meta->property(i);
+ if (prop.isScriptable()) {
+ array.add(Identifier(prop.name()));
+ }
+ }
+
+ QList<QByteArray> dynProps = obj->dynamicPropertyNames();
+ foreach(QByteArray ba, dynProps) {
+ array.add(Identifier(ba.constData()));
+ }
+
+ for (i=0; i < meta->methodCount(); i++) {
+ QMetaMethod method = meta->method(i);
+ if (method.access() != QMetaMethod::Private) {
+ array.add(Identifier(method.signature()));
+ }
+ }
+ }
+}
+
+JSValue* QtInstance::invokeMethod(ExecState*, const MethodList&, const List&)
+{
+ // Implemented via fallbackMethod & QtRuntimeMetaMethod::callAsFunction
+ return jsUndefined();
+}
+
+bool QtInstance::implementsCall() const
+{
+ // See if we have qscript_call
+ if (m_defaultMethodIndex == -2) {
+ if (m_object) {
+ const QMetaObject* meta = m_object->metaObject();
+ int count = meta->methodCount();
+ const QByteArray defsig("qscript_call");
+ for (int index = count - 1; index >= 0; --index) {
+ const QMetaMethod m = meta->method(index);
+
+ QByteArray signature = m.signature();
+ signature.truncate(signature.indexOf('('));
+
+ if (defsig == signature) {
+ m_defaultMethodIndex = index;
+ break;
+ }
+ }
+ }
+
+ if (m_defaultMethodIndex == -2) // Not checked
+ m_defaultMethodIndex = -1; // No qscript_call
+ }
+
+ // typeof object that implements call == function
+ return (m_defaultMethodIndex >= 0);
+}
+
+JSValue* QtInstance::invokeDefaultMethod(ExecState* exec, const List& args)
+{
+ // QtScript tries to invoke a meta method qscript_call
+ if (!getObject())
+ return throwError(exec, GeneralError, "cannot call function of deleted QObject");
+
+ // implementsCall will update our default method cache, if possible
+ if (implementsCall()) {
+ if (!m_defaultMethod) {
+ m_defaultMethod = new QtRuntimeMetaMethod(exec, Identifier("[[Call]]"),this, m_defaultMethodIndex, QByteArray("qscript_call"), true);
+ gcProtect(m_defaultMethod);
+ }
+
+ return m_defaultMethod->callAsFunction(exec, 0, args); // Luckily QtRuntimeMetaMethod ignores the obj parameter
+ } else
+ return throwError(exec, TypeError, "not a function");
+}
+
+JSValue* QtInstance::defaultValue(JSType hint) const
+{
+ if (hint == StringType)
+ return stringValue();
+ if (hint == NumberType)
+ return numberValue();
+ if (hint == BooleanType)
+ return booleanValue();
+ return valueOf();
+}
+
+JSValue* QtInstance::stringValue() const
+{
+ // Hmm.. see if there is a toString defined
+ QByteArray buf;
+ bool useDefault = true;
+ getClass();
+ QObject* obj = getObject();
+ if (m_class && obj) {
+ // Cheat and don't use the full name resolution
+ int index = obj->metaObject()->indexOfMethod("toString()");
+ if (index >= 0) {
+ QMetaMethod m = obj->metaObject()->method(index);
+ // Check to see how much we can call it
+ if (m.access() != QMetaMethod::Private
+ && m.methodType() != QMetaMethod::Signal
+ && m.parameterTypes().count() == 0) {
+ const char* retsig = m.typeName();
+ if (retsig && *retsig) {
+ QVariant ret(QMetaType::type(retsig), (void*)0);
+ void * qargs[1];
+ qargs[0] = ret.data();
+
+ if (obj->qt_metacall(QMetaObject::InvokeMetaMethod, index, qargs) < 0) {
+ if (ret.isValid() && ret.canConvert(QVariant::String)) {
+ buf = ret.toString().toLatin1().constData(); // ### Latin 1? Ascii?
+ useDefault = false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (useDefault) {
+ const QMetaObject* meta = obj ? obj->metaObject() : &QObject::staticMetaObject;
+ QString name = obj ? obj->objectName() : QString::fromUtf8("unnamed");
+ QString str = QString::fromUtf8("%0(name = \"%1\")")
+ .arg(QLatin1String(meta->className())).arg(name);
+
+ buf = str.toLatin1();
+ }
+ return jsString(buf.constData());
+}
+
+JSValue* QtInstance::numberValue() const
+{
+ return jsNumber(0);
+}
+
+JSValue* QtInstance::booleanValue() const
+{
+ // ECMA 9.2
+ return jsBoolean(true);
+}
+
+JSValue* QtInstance::valueOf() const
+{
+ return stringValue();
+}
+
+// In qt_runtime.cpp
+JSValue* convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant);
+QVariant convertValueToQVariant(ExecState* exec, JSValue* value, QMetaType::Type hint, int *distance);
+
+const char* QtField::name() const
+{
+ if (m_type == MetaProperty)
+ return m_property.name();
+ else if (m_type == ChildObject && m_childObject)
+ return m_childObject->objectName().toLatin1();
+ else if (m_type == DynamicProperty)
+ return m_dynamicProperty.constData();
+ return ""; // deleted child object
+}
+
+JSValue* QtField::valueFromInstance(ExecState* exec, const Instance* inst) const
+{
+ const QtInstance* instance = static_cast<const QtInstance*>(inst);
+ QObject* obj = instance->getObject();
+
+ if (obj) {
+ QVariant val;
+ if (m_type == MetaProperty) {
+ if (m_property.isReadable())
+ val = m_property.read(obj);
+ else
+ return jsUndefined();
+ } else if (m_type == ChildObject)
+ val = QVariant::fromValue((QObject*) m_childObject);
+ else if (m_type == DynamicProperty)
+ val = obj->property(m_dynamicProperty);
+
+ return convertQVariantToValue(exec, inst->rootObject(), val);
+ } else {
+ QString msg = QString("cannot access member `%1' of deleted QObject").arg(name());
+ return throwError(exec, GeneralError, msg.toLatin1().constData());
+ }
+}
+
+void QtField::setValueToInstance(ExecState* exec, const Instance* inst, JSValue* aValue) const
+{
+ if (m_type == ChildObject) // QtScript doesn't allow setting to a named child
+ return;
+
+ const QtInstance* instance = static_cast<const QtInstance*>(inst);
+ QObject* obj = instance->getObject();
+ if (obj) {
+ QMetaType::Type argtype = QMetaType::Void;
+ if (m_type == MetaProperty)
+ argtype = (QMetaType::Type) QMetaType::type(m_property.typeName());
+
+ // dynamic properties just get any QVariant
+ QVariant val = convertValueToQVariant(exec, aValue, argtype, 0);
+ if (m_type == MetaProperty) {
+ if (m_property.isWritable())
+ m_property.write(obj, val);
+ } else if (m_type == DynamicProperty)
+ obj->setProperty(m_dynamicProperty.constData(), val);
+ } else {
+ QString msg = QString("cannot access member `%1' of deleted QObject").arg(name());
+ throwError(exec, GeneralError, msg.toLatin1().constData());
+ }
+}
+
+
+}
+}
diff --git a/JavaScriptCore/bindings/qt/qt_instance.h b/JavaScriptCore/bindings/qt/qt_instance.h
new file mode 100644
index 0000000..2304ac5
--- /dev/null
+++ b/JavaScriptCore/bindings/qt/qt_instance.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef BINDINGS_QT_INSTANCE_H_
+#define BINDINGS_QT_INSTANCE_H_
+
+#include "runtime.h"
+#include "runtime_root.h"
+#include <qpointer.h>
+#include <qhash.h>
+
+class QObject;
+
+namespace KJS {
+
+namespace Bindings {
+
+class QtClass;
+class QtField;
+class QtRuntimeMetaMethod;
+
+class QtInstance : public Instance
+{
+public:
+ ~QtInstance ();
+
+ virtual Class* getClass() const;
+
+ virtual void begin();
+ virtual void end();
+
+ virtual JSValue* valueOf() const;
+ virtual JSValue* defaultValue (JSType hint) const;
+
+ virtual bool implementsCall() const;
+
+ virtual JSValue* invokeMethod (ExecState *exec, const MethodList &method, const List &args);
+ virtual JSValue* invokeDefaultMethod (ExecState *exec, const List &args);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual BindingLanguage getBindingLanguage() const { return QtLanguage; }
+
+ JSValue* stringValue() const;
+ JSValue* numberValue() const;
+ JSValue* booleanValue() const;
+
+ QObject* getObject() const { return m_object; }
+
+ static QtInstance* getQtInstance(QObject*, PassRefPtr<RootObject>);
+ static JSObject* getRuntimeObject(QtInstance*);
+
+private:
+ friend class QtClass;
+ QtInstance(QObject*, PassRefPtr<RootObject>); // Factory produced only..
+ mutable QtClass* m_class;
+ QPointer<QObject> m_object;
+ QObject* m_hashkey;
+ mutable QHash<QByteArray,JSValue*> m_methods;
+ mutable QHash<QString,QtField*> m_fields;
+ mutable QtRuntimeMetaMethod* m_defaultMethod;
+ mutable int m_defaultMethodIndex;
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/qt/qt_runtime.cpp b/JavaScriptCore/bindings/qt/qt_runtime.cpp
new file mode 100644
index 0000000..113f0c5
--- /dev/null
+++ b/JavaScriptCore/bindings/qt/qt_runtime.cpp
@@ -0,0 +1,1590 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "qt_runtime.h"
+#include "qt_instance.h"
+#include "object.h"
+#include "array_instance.h"
+#include "date_object.h"
+#include "DateMath.h"
+#include "regexp_object.h"
+#include <runtime_object.h>
+#include <runtime_array.h>
+#include <function.h>
+#include "PropertyNameArray.h"
+#include "qmetatype.h"
+#include "qmetaobject.h"
+#include "qobject.h"
+#include "qstringlist.h"
+#include "qdebug.h"
+#include "qvarlengtharray.h"
+#include "qdatetime.h"
+#include <limits.h>
+
+// QtScript has these
+Q_DECLARE_METATYPE(QObjectList);
+Q_DECLARE_METATYPE(QList<int>);
+Q_DECLARE_METATYPE(QVariant);
+
+
+namespace KJS {
+namespace Bindings {
+
+// Debugging
+//#define QTWK_RUNTIME_CONVERSION_DEBUG
+//#define QTWK_RUNTIME_MATCH_DEBUG
+
+class QWKNoDebug
+{
+public:
+ inline QWKNoDebug(){}
+ inline ~QWKNoDebug(){}
+
+ template<typename T>
+ inline QWKNoDebug &operator<<(const T &) { return *this; }
+};
+
+#ifdef QTWK_RUNTIME_CONVERSION_DEBUG
+#define qConvDebug() qDebug()
+#else
+#define qConvDebug() QWKNoDebug()
+#endif
+
+#ifdef QTWK_RUNTIME_MATCH_DEBUG
+#define qMatchDebug() qDebug()
+#else
+#define qMatchDebug() QWKNoDebug()
+#endif
+
+typedef enum {
+ Variant,
+ Number,
+ Boolean,
+ String,
+ Date,
+ RegExp,
+ Array,
+ QObj,
+ Object,
+ Null
+} JSRealType;
+
+static JSRealType valueRealType(ExecState* exec, JSValue* val)
+{
+ if (val->isNumber())
+ return Number;
+ else if (val->isString())
+ return String;
+ else if (val->isBoolean())
+ return Boolean;
+ else if (val->isNull())
+ return Null;
+ else if (val->isObject()) {
+ JSObject *object = val->toObject(exec);
+ if (object->inherits(&ArrayInstance::info))
+ return Array;
+ else if (object->inherits(&DateInstance::info))
+ return Date;
+ else if (object->inherits(&RegExpImp::info))
+ return RegExp;
+ else if (object->inherits(&RuntimeObjectImp::info))
+ return QObj;
+ return Object;
+ }
+
+ return String; // I don't know.
+}
+
+QVariant convertValueToQVariant(ExecState* exec, JSValue* value, QMetaType::Type hint, int *distance)
+{
+ // check magic pointer values before dereferencing value
+ if (value == jsNaN() || value == jsUndefined()) {
+ if (distance)
+ *distance = -1;
+ return QVariant();
+ }
+
+ JSLock lock;
+ JSRealType type = valueRealType(exec, value);
+ if (hint == QMetaType::Void) {
+ switch(type) {
+ case Number:
+ hint = QMetaType::Double;
+ break;
+ case Boolean:
+ hint = QMetaType::Bool;
+ break;
+ case String:
+ default:
+ hint = QMetaType::QString;
+ break;
+ case Date:
+ hint = QMetaType::QDateTime;
+ break;
+ case RegExp:
+ hint = QMetaType::QRegExp;
+ break;
+ case QObj:
+ hint = QMetaType::QObjectStar;
+ break;
+ case Array:
+ hint = QMetaType::QVariantList;
+ break;
+ }
+ }
+
+ if (value == jsNull()
+ && hint != QMetaType::QObjectStar
+ && hint != QMetaType::VoidStar) {
+ if (distance)
+ *distance = -1;
+ return QVariant();
+ }
+
+ QVariant ret;
+ int dist = -1;
+ switch (hint) {
+ case QMetaType::Bool:
+ ret = QVariant(value->toBoolean(exec));
+ if (type == Boolean)
+ dist = 0;
+ else
+ dist = 10;
+ break;
+
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ case QMetaType::Long:
+ case QMetaType::ULong:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::Float:
+ case QMetaType::Double:
+ ret = QVariant(value->toNumber(exec));
+ ret.convert((QVariant::Type)hint);
+ if (type == Number) {
+ switch (hint) {
+ case QMetaType::Double:
+ dist = 0;
+ break;
+ case QMetaType::Float:
+ dist = 1;
+ break;
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ dist = 2;
+ break;
+ case QMetaType::Long:
+ case QMetaType::ULong:
+ dist = 3;
+ break;
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ dist = 4;
+ break;
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ dist = 5;
+ break;
+ break;
+ default:
+ dist = 10;
+ break;
+ }
+ } else {
+ dist = 10;
+ }
+ break;
+
+ case QMetaType::QChar:
+ if (type == Number || type == Boolean) {
+ ret = QVariant(QChar((ushort)value->toNumber(exec)));
+ if (type == Boolean)
+ dist = 3;
+ else
+ dist = 6;
+ } else {
+ UString str = value->toString(exec);
+ ret = QVariant(QChar(str.size() ? *(const ushort*)str.rep()->data() : 0));
+ if (type == String)
+ dist = 3;
+ else
+ dist = 10;
+ }
+ break;
+
+ case QMetaType::QString: {
+ UString ustring = value->toString(exec);
+ ret = QVariant(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()));
+ if (type == String)
+ dist = 0;
+ else
+ dist = 10;
+ break;
+ }
+
+ case QMetaType::QVariantMap:
+ if (type == Object || type == Array) {
+ // Enumerate the contents of the object
+ JSObject* object = value->toObject(exec);
+
+ PropertyNameArray properties;
+ object->getPropertyNames(exec, properties);
+ PropertyNameArray::const_iterator it = properties.begin();
+
+ QVariantMap result;
+ int objdist = 0;
+ while(it != properties.end()) {
+ if (object->propertyIsEnumerable(exec, *it)) {
+ JSValue* val = object->get(exec, *it);
+ QVariant v = convertValueToQVariant(exec, val, QMetaType::Void, &objdist);
+ if (objdist >= 0) {
+ UString ustring = (*it).ustring();
+ QString id = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+ result.insert(id, v);
+ }
+ }
+ ++it;
+ }
+ dist = 1;
+ ret = QVariant(result);
+ }
+ break;
+
+ case QMetaType::QVariantList:
+ if (type == Array) {
+ JSObject* object = value->toObject(exec);
+ ArrayInstance* array = static_cast<ArrayInstance*>(object);
+
+ QVariantList result;
+ int len = array->getLength();
+ int objdist = 0;
+ for (int i = 0; i < len; ++i) {
+ JSValue *val = array->getItem(i);
+ result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist));
+ if (objdist == -1)
+ break; // Failed converting a list entry, so fail the array
+ }
+ if (objdist != -1) {
+ dist = 5;
+ ret = QVariant(result);
+ }
+ } else {
+ // Make a single length array
+ QVariantList result;
+ int objdist;
+ result.append(convertValueToQVariant(exec, value, QMetaType::Void, &objdist));
+ if (objdist != -1) {
+ ret = QVariant(result);
+ dist = 10;
+ }
+ }
+ break;
+
+ case QMetaType::QStringList: {
+ if (type == Array) {
+ JSObject* object = value->toObject(exec);
+ ArrayInstance* array = static_cast<ArrayInstance*>(object);
+
+ QStringList result;
+ int len = array->getLength();
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = array->getItem(i);
+ UString ustring = val->toString(exec);
+ QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+
+ result.append(qstring);
+ }
+ dist = 5;
+ ret = QVariant(result);
+ } else {
+ // Make a single length array
+ UString ustring = value->toString(exec);
+ QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+ QStringList result;
+ result.append(qstring);
+ ret = QVariant(result);
+ dist = 10;
+ }
+ break;
+ }
+
+ case QMetaType::QByteArray: {
+ UString ustring = value->toString(exec);
+ ret = QVariant(QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size()).toLatin1());
+ if (type == String)
+ dist = 5;
+ else
+ dist = 10;
+ break;
+ }
+
+ case QMetaType::QDateTime:
+ case QMetaType::QDate:
+ case QMetaType::QTime:
+ if (type == Date) {
+ JSObject* object = value->toObject(exec);
+ DateInstance* date = static_cast<DateInstance*>(object);
+ GregorianDateTime gdt;
+ date->getUTCTime(gdt);
+ if (hint == QMetaType::QDateTime) {
+ ret = QDateTime(QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay), QTime(gdt.hour, gdt.minute, gdt.second), Qt::UTC);
+ dist = 0;
+ } else if (hint == QMetaType::QDate) {
+ ret = QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay);
+ dist = 1;
+ } else {
+ ret = QTime(gdt.hour + 1900, gdt.minute, gdt.second);
+ dist = 2;
+ }
+ } else if (type == Number) {
+ double b = value->toNumber(exec);
+ GregorianDateTime gdt;
+ msToGregorianDateTime(b, true, gdt);
+ if (hint == QMetaType::QDateTime) {
+ ret = QDateTime(QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay), QTime(gdt.hour, gdt.minute, gdt.second), Qt::UTC);
+ dist = 6;
+ } else if (hint == QMetaType::QDate) {
+ ret = QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay);
+ dist = 8;
+ } else {
+ ret = QTime(gdt.hour, gdt.minute, gdt.second);
+ dist = 10;
+ }
+ } else if (type == String) {
+ UString ustring = value->toString(exec);
+ QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+
+ if (hint == QMetaType::QDateTime) {
+ QDateTime dt = QDateTime::fromString(qstring, Qt::ISODate);
+ if (!dt.isValid())
+ dt = QDateTime::fromString(qstring, Qt::TextDate);
+ if (!dt.isValid())
+ dt = QDateTime::fromString(qstring, Qt::SystemLocaleDate);
+ if (!dt.isValid())
+ dt = QDateTime::fromString(qstring, Qt::LocaleDate);
+ if (dt.isValid()) {
+ ret = dt;
+ dist = 2;
+ }
+ } else if (hint == QMetaType::QDate) {
+ QDate dt = QDate::fromString(qstring, Qt::ISODate);
+ if (!dt.isValid())
+ dt = QDate::fromString(qstring, Qt::TextDate);
+ if (!dt.isValid())
+ dt = QDate::fromString(qstring, Qt::SystemLocaleDate);
+ if (!dt.isValid())
+ dt = QDate::fromString(qstring, Qt::LocaleDate);
+ if (dt.isValid()) {
+ ret = dt;
+ dist = 3;
+ }
+ } else {
+ QTime dt = QTime::fromString(qstring, Qt::ISODate);
+ if (!dt.isValid())
+ dt = QTime::fromString(qstring, Qt::TextDate);
+ if (!dt.isValid())
+ dt = QTime::fromString(qstring, Qt::SystemLocaleDate);
+ if (!dt.isValid())
+ dt = QTime::fromString(qstring, Qt::LocaleDate);
+ if (dt.isValid()) {
+ ret = dt;
+ dist = 3;
+ }
+ }
+ }
+ break;
+
+ case QMetaType::QRegExp:
+ if (type == RegExp) {
+/* JSObject *object = value->toObject(exec);
+ RegExpImp *re = static_cast<RegExpImp*>(object);
+*/
+ // Attempt to convert.. a bit risky
+ UString ustring = value->toString(exec);
+ QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+
+ // this is of the form '/xxxxxx/i'
+ int firstSlash = qstring.indexOf('/');
+ int lastSlash = qstring.lastIndexOf('/');
+ if (firstSlash >=0 && lastSlash > firstSlash) {
+ QRegExp realRe;
+
+ realRe.setPattern(qstring.mid(firstSlash + 1, lastSlash - firstSlash - 1));
+
+ if (qstring.mid(lastSlash + 1).contains('i'))
+ realRe.setCaseSensitivity(Qt::CaseInsensitive);
+
+ ret = qVariantFromValue(realRe);
+ dist = 0;
+ } else {
+ qConvDebug() << "couldn't parse a JS regexp";
+ }
+ } else if (type == String) {
+ UString ustring = value->toString(exec);
+ QString qstring = QString::fromUtf16((const ushort*)ustring.rep()->data(),ustring.size());
+
+ QRegExp re(qstring);
+ if (re.isValid()) {
+ ret = qVariantFromValue(re);
+ dist = 10;
+ }
+ }
+ break;
+
+ case QMetaType::QObjectStar:
+ if (type == QObj) {
+ JSObject* object = value->toObject(exec);
+ QtInstance* qtinst = static_cast<QtInstance*>(Instance::getInstance(object, Instance::QtLanguage));
+ if (qtinst) {
+ if (qtinst->getObject()) {
+ qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
+ ret = qVariantFromValue(qtinst->getObject());
+ qConvDebug() << ret;
+ dist = 0;
+ } else {
+ qConvDebug() << "can't convert deleted qobject";
+ }
+ } else {
+ qConvDebug() << "wasn't a qtinstance";
+ }
+ } else if (type == Null) {
+ QObject* nullobj = 0;
+ ret = qVariantFromValue(nullobj);
+ dist = 0;
+ } else {
+ qConvDebug() << "previous type was not an object:" << type;
+ }
+ break;
+
+ case QMetaType::VoidStar:
+ if (type == QObj) {
+ JSObject* object = value->toObject(exec);
+ QtInstance* qtinst = static_cast<QtInstance*>(Instance::getInstance(object, Instance::QtLanguage));
+ if (qtinst) {
+ if (qtinst->getObject()) {
+ qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
+ ret = qVariantFromValue((void *)qtinst->getObject());
+ qConvDebug() << ret;
+ dist = 0;
+ } else {
+ qConvDebug() << "can't convert deleted qobject";
+ }
+ } else {
+ qConvDebug() << "wasn't a qtinstance";
+ }
+ } else if (type == Null) {
+ ret = qVariantFromValue((void*)0);
+ dist = 0;
+ } else if (type == Number) {
+ // I don't think that converting a double to a pointer is a wise
+ // move. Except maybe 0.
+ qConvDebug() << "got number for void * - not converting, seems unsafe:" << value->toNumber(exec);
+ } else {
+ qConvDebug() << "void* - unhandled type" << type;
+ }
+ break;
+
+ default:
+ // Non const type ids
+ if (hint == (QMetaType::Type) qMetaTypeId<QObjectList>())
+ {
+ if (type == Array) {
+ JSObject* object = value->toObject(exec);
+ ArrayInstance* array = static_cast<ArrayInstance *>(object);
+
+ QObjectList result;
+ int len = array->getLength();
+ for (int i = 0; i < len; ++i) {
+ JSValue *val = array->getItem(i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist);
+ if (itemdist >= 0)
+ result.append(item.value<QObject*>());
+ else
+ break;
+ }
+ // If we didn't fail conversion
+ if (result.count() == len) {
+ dist = 5;
+ ret = QVariant::fromValue(result);
+ } else {
+ qConvDebug() << "type conversion failed (wanted" << len << ", got " << result.count() << ")";
+ }
+ } else {
+ // Make a single length array
+ QObjectList result;
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, value, QMetaType::QObjectStar, &itemdist);
+ if (itemdist >= 0) {
+ result.append(item.value<QObject*>());
+ dist = 10;
+ ret = QVariant::fromValue(result);
+ }
+ }
+ break;
+ } else if (hint == (QMetaType::Type) qMetaTypeId<QList<int> >()) {
+ if (type == Array) {
+ JSObject* object = value->toObject(exec);
+ ArrayInstance* array = static_cast<ArrayInstance *>(object);
+
+ QList<int> result;
+ int len = array->getLength();
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = array->getItem(i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist);
+ if (itemdist >= 0)
+ result.append(item.value<int>());
+ else
+ break;
+ }
+ // If we didn't fail conversion
+ if (result.count() == len) {
+ dist = 5;
+ ret = QVariant::fromValue(result);
+ } else {
+ qConvDebug() << "type conversion failed (wanted" << len << ", got " << result.count() << ")";
+ }
+ } else {
+ // Make a single length array
+ QList<int> result;
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, value, QMetaType::Int, &itemdist);
+ if (itemdist >= 0) {
+ result.append(item.value<int>());
+ dist = 10;
+ ret = QVariant::fromValue(result);
+ }
+ }
+ break;
+ } else if (hint == (QMetaType::Type) qMetaTypeId<QVariant>()) {
+ // Well.. we can do anything... just recurse with the autodetect flag
+ ret = convertValueToQVariant(exec, value, QMetaType::Void, distance);
+ dist = 10;
+ break;
+ }
+
+ dist = 10;
+ break;
+ }
+
+ if (!ret.isValid())
+ dist = -1;
+ if (distance)
+ *distance = dist;
+
+ return ret;
+}
+
+JSValue* convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant)
+{
+ // Variants with QObject * can be isNull but not a null pointer
+ // An empty QString variant is also null
+ QMetaType::Type type = (QMetaType::Type) variant.userType();
+ if (variant.isNull() &&
+ type != QMetaType::QObjectStar &&
+ type != QMetaType::VoidStar &&
+ type != QMetaType::QWidgetStar &&
+ type != QMetaType::QString) {
+ return jsNull();
+ }
+
+ JSLock lock;
+
+ if (type == QMetaType::Bool)
+ return jsBoolean(variant.toBool());
+
+ if (type == QMetaType::Int ||
+ type == QMetaType::UInt ||
+ type == QMetaType::Long ||
+ type == QMetaType::ULong ||
+ type == QMetaType::LongLong ||
+ type == QMetaType::ULongLong ||
+ type == QMetaType::Short ||
+ type == QMetaType::UShort ||
+ type == QMetaType::Float ||
+ type == QMetaType::Double)
+ return jsNumber(variant.toDouble());
+
+ if (type == QMetaType::QRegExp) {
+ QRegExp re = variant.value<QRegExp>();
+
+ if (re.isValid()) {
+ RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalGlobalObject()->regExpConstructor());
+ List args;
+ UString uflags;
+
+ if (re.caseSensitivity() == Qt::CaseInsensitive)
+ uflags = "i"; // ### Can't do g or m
+ UString ustring((KJS::UChar*)re.pattern().utf16(), re.pattern().length());
+ args.append(jsString(ustring));
+ args.append(jsString(uflags));
+ return regExpObj->construct(exec, args);
+ }
+ }
+
+ if (type == QMetaType::QDateTime ||
+ type == QMetaType::QDate ||
+ type == QMetaType::QTime) {
+ DateObjectImp *dateObj = static_cast<DateObjectImp*>(exec->lexicalGlobalObject()->dateConstructor());
+ List args;
+
+ QDate date = QDate::currentDate();
+ QTime time(0,0,0); // midnight
+
+ if (type == QMetaType::QDate)
+ date = variant.value<QDate>();
+ else if (type == QMetaType::QTime)
+ time = variant.value<QTime>();
+ else {
+ QDateTime dt = variant.value<QDateTime>().toLocalTime();
+ date = dt.date();
+ time = dt.time();
+ }
+
+ // Dates specified this way are in local time (we convert DateTimes above)
+ args.append(jsNumber(date.year()));
+ args.append(jsNumber(date.month() - 1));
+ args.append(jsNumber(date.day()));
+ args.append(jsNumber(time.hour()));
+ args.append(jsNumber(time.minute()));
+ args.append(jsNumber(time.second()));
+ args.append(jsNumber(time.msec()));
+ return dateObj->construct(exec, args);
+ }
+
+ if (type == QMetaType::QByteArray) {
+ QByteArray ba = variant.value<QByteArray>();
+ UString ustring(ba.constData());
+ return jsString(ustring);
+ }
+
+ if (type == QMetaType::QObjectStar || type == QMetaType::QWidgetStar) {
+ QObject* obj = variant.value<QObject*>();
+ return Instance::createRuntimeObject(Instance::QtLanguage, obj, root);
+ }
+
+ if (type == QMetaType::QVariantMap) {
+ // create a new object, and stuff properties into it
+ JSObject* ret = new JSObject(exec->lexicalGlobalObject()->objectPrototype());
+ QVariantMap map = variant.value<QVariantMap>();
+ QVariantMap::const_iterator i = map.constBegin();
+ while (i != map.constEnd()) {
+ QString s = i.key();
+ JSValue* val = convertQVariantToValue(exec, root, i.value());
+ if (val)
+ ret->put(exec, Identifier((const UChar *)s.constData(), s.length()), val);
+ // ### error case?
+ ++i;
+ }
+
+ return ret;
+ }
+
+ // List types
+ if (type == QMetaType::QVariantList) {
+ QVariantList vl = variant.toList();
+ return new RuntimeArray(exec, new QtArray<QVariant>(vl, QMetaType::Void, root));
+ } else if (type == QMetaType::QStringList) {
+ QStringList sl = variant.value<QStringList>();
+ return new RuntimeArray(exec, new QtArray<QString>(sl, QMetaType::QString, root));
+ } else if (type == (QMetaType::Type) qMetaTypeId<QObjectList>()) {
+ QObjectList ol= variant.value<QObjectList>();
+ return new RuntimeArray(exec, new QtArray<QObject*>(ol, QMetaType::QObjectStar, root));
+ } else if (type == (QMetaType::Type)qMetaTypeId<QList<int> >()) {
+ QList<int> il= variant.value<QList<int> >();
+ return new RuntimeArray(exec, new QtArray<int>(il, QMetaType::Int, root));
+ }
+
+ if (type == (QMetaType::Type)qMetaTypeId<QVariant>()) {
+ QVariant real = variant.value<QVariant>();
+ qConvDebug() << "real variant is:" << real;
+ return convertQVariantToValue(exec, root, real);
+ }
+
+ qConvDebug() << "fallback path for" << variant << variant.userType();
+
+ QString string = variant.toString();
+ UString ustring((KJS::UChar*)string.utf16(), string.length());
+ return jsString(ustring);
+}
+
+// ===============
+
+// Qt-like macros
+#define QW_D(Class) Class##Data* d = d_func()
+#define QW_DS(Class,Instance) Class##Data* d = Instance->d_func()
+
+QtRuntimeMethod::QtRuntimeMethod(QtRuntimeMethodData* dd, ExecState *exec, const Identifier &ident, PassRefPtr<QtInstance> inst)
+ : InternalFunctionImp (static_cast<FunctionPrototype*>(exec->lexicalGlobalObject()->functionPrototype()), ident)
+ , d_ptr(dd)
+{
+ QW_D(QtRuntimeMethod);
+ d->m_instance = inst;
+}
+
+QtRuntimeMethod::~QtRuntimeMethod()
+{
+ delete d_ptr;
+}
+
+CodeType QtRuntimeMethod::codeType() const
+{
+ return FunctionCode;
+}
+
+Completion QtRuntimeMethod::execute(ExecState*)
+{
+ return Completion(Normal, jsUndefined());
+}
+
+// ===============
+
+QtRuntimeMethodData::~QtRuntimeMethodData()
+{
+}
+
+QtRuntimeMetaMethodData::~QtRuntimeMetaMethodData()
+{
+
+}
+
+QtRuntimeConnectionMethodData::~QtRuntimeConnectionMethodData()
+{
+
+}
+
+// ===============
+
+// Type conversion metadata (from QtScript originally)
+class QtMethodMatchType
+{
+public:
+ enum Kind {
+ Invalid,
+ Variant,
+ MetaType,
+ Unresolved,
+ MetaEnum
+ };
+
+
+ QtMethodMatchType()
+ : m_kind(Invalid) { }
+
+ Kind kind() const
+ { return m_kind; }
+
+ QMetaType::Type typeId() const;
+
+ bool isValid() const
+ { return (m_kind != Invalid); }
+
+ bool isVariant() const
+ { return (m_kind == Variant); }
+
+ bool isMetaType() const
+ { return (m_kind == MetaType); }
+
+ bool isUnresolved() const
+ { return (m_kind == Unresolved); }
+
+ bool isMetaEnum() const
+ { return (m_kind == MetaEnum); }
+
+ QByteArray name() const;
+
+ int enumeratorIndex() const
+ { Q_ASSERT(isMetaEnum()); return m_typeId; }
+
+ static QtMethodMatchType variant()
+ { return QtMethodMatchType(Variant); }
+
+ static QtMethodMatchType metaType(int typeId, const QByteArray &name)
+ { return QtMethodMatchType(MetaType, typeId, name); }
+
+ static QtMethodMatchType metaEnum(int enumIndex, const QByteArray &name)
+ { return QtMethodMatchType(MetaEnum, enumIndex, name); }
+
+ static QtMethodMatchType unresolved(const QByteArray &name)
+ { return QtMethodMatchType(Unresolved, /*typeId=*/0, name); }
+
+private:
+ QtMethodMatchType(Kind kind, int typeId = 0, const QByteArray &name = QByteArray())
+ : m_kind(kind), m_typeId(typeId), m_name(name) { }
+
+ Kind m_kind;
+ int m_typeId;
+ QByteArray m_name;
+};
+
+QMetaType::Type QtMethodMatchType::typeId() const
+{
+ if (isVariant())
+ return (QMetaType::Type) QMetaType::type("QVariant");
+ return (QMetaType::Type) (isMetaEnum() ? QMetaType::Int : m_typeId);
+}
+
+QByteArray QtMethodMatchType::name() const
+{
+ if (!m_name.isEmpty())
+ return m_name;
+ else if (m_kind == Variant)
+ return "QVariant";
+ return QByteArray();
+}
+
+struct QtMethodMatchData
+{
+ int matchDistance;
+ int index;
+ QVector<QtMethodMatchType> types;
+ QVarLengthArray<QVariant, 10> args;
+
+ QtMethodMatchData(int dist, int idx, QVector<QtMethodMatchType> typs,
+ const QVarLengthArray<QVariant, 10> &as)
+ : matchDistance(dist), index(idx), types(typs), args(as) { }
+ QtMethodMatchData()
+ : index(-1) { }
+
+ bool isValid() const
+ { return (index != -1); }
+
+ int firstUnresolvedIndex() const
+ {
+ for (int i=0; i < types.count(); i++) {
+ if (types.at(i).isUnresolved())
+ return i;
+ }
+ return -1;
+ }
+};
+
+static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str)
+{
+ QByteArray scope;
+ QByteArray name;
+ int scopeIdx = str.indexOf("::");
+ if (scopeIdx != -1) {
+ scope = str.left(scopeIdx);
+ name = str.mid(scopeIdx + 2);
+ } else {
+ name = str;
+ }
+ for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
+ QMetaEnum m = meta->enumerator(i);
+ if ((m.name() == name)/* && (scope.isEmpty() || (m.scope() == scope))*/)
+ return i;
+ }
+ return -1;
+}
+
+// Helper function for resolving methods
+// Largely based on code in QtScript for compatibility reasons
+static int findMethodIndex(ExecState* exec,
+ const QMetaObject* meta,
+ const QByteArray& signature,
+ bool allowPrivate,
+ const List& jsArgs,
+ QVarLengthArray<QVariant, 10> &vars,
+ void** vvars,
+ JSObject **pError)
+{
+ QList<int> matchingIndices;
+
+ bool overloads = !signature.contains('(');
+
+ int count = meta->methodCount();
+ for (int i = count - 1; i >= 0; --i) {
+ const QMetaMethod m = meta->method(i);
+
+ // Don't choose private methods
+ if (m.access() == QMetaMethod::Private && !allowPrivate)
+ continue;
+
+ // try and find all matching named methods
+ if (m.signature() == signature)
+ matchingIndices.append(i);
+ else if (overloads) {
+ QByteArray rawsignature = m.signature();
+ rawsignature.truncate(rawsignature.indexOf('('));
+ if (rawsignature == signature)
+ matchingIndices.append(i);
+ }
+ }
+
+ int chosenIndex = -1;
+ *pError = 0;
+ QVector<QtMethodMatchType> chosenTypes;
+
+ QVarLengthArray<QVariant, 10> args;
+ QVector<QtMethodMatchData> candidates;
+ QVector<QtMethodMatchData> unresolved;
+ QVector<int> tooFewArgs;
+ QVector<int> conversionFailed;
+
+ foreach(int index, matchingIndices) {
+ QMetaMethod method = meta->method(index);
+
+ QVector<QtMethodMatchType> types;
+ bool unresolvedTypes = false;
+
+ // resolve return type
+ QByteArray returnTypeName = method.typeName();
+ int rtype = QMetaType::type(returnTypeName);
+ if ((rtype == 0) && !returnTypeName.isEmpty()) {
+ if (returnTypeName == "QVariant") {
+ types.append(QtMethodMatchType::variant());
+ } else if (returnTypeName.endsWith('*')) {
+ types.append(QtMethodMatchType::metaType(QMetaType::VoidStar, returnTypeName));
+ } else {
+ int enumIndex = indexOfMetaEnum(meta, returnTypeName);
+ if (enumIndex != -1)
+ types.append(QtMethodMatchType::metaEnum(enumIndex, returnTypeName));
+ else {
+ unresolvedTypes = true;
+ types.append(QtMethodMatchType::unresolved(returnTypeName));
+ }
+ }
+ } else {
+ if (returnTypeName == "QVariant")
+ types.append(QtMethodMatchType::variant());
+ else
+ types.append(QtMethodMatchType::metaType(rtype, returnTypeName));
+ }
+
+ // resolve argument types
+ QList<QByteArray> parameterTypeNames = method.parameterTypes();
+ for (int i = 0; i < parameterTypeNames.count(); ++i) {
+ QByteArray argTypeName = parameterTypeNames.at(i);
+ int atype = QMetaType::type(argTypeName);
+ if (atype == 0) {
+ if (argTypeName == "QVariant") {
+ types.append(QtMethodMatchType::variant());
+ } else {
+ int enumIndex = indexOfMetaEnum(meta, argTypeName);
+ if (enumIndex != -1)
+ types.append(QtMethodMatchType::metaEnum(enumIndex, argTypeName));
+ else {
+ unresolvedTypes = true;
+ types.append(QtMethodMatchType::unresolved(argTypeName));
+ }
+ }
+ } else {
+ if (argTypeName == "QVariant")
+ types.append(QtMethodMatchType::variant());
+ else
+ types.append(QtMethodMatchType::metaType(atype, argTypeName));
+ }
+ }
+
+ if (jsArgs.size() < (types.count() - 1)) {
+ qMatchDebug() << "Match:too few args for" << method.signature();
+ tooFewArgs.append(index);
+ continue;
+ }
+
+ if (unresolvedTypes) {
+ qMatchDebug() << "Match:unresolved arg types for" << method.signature();
+ // remember it so we can give an error message later, if necessary
+ unresolved.append(QtMethodMatchData(/*matchDistance=*/INT_MAX, index,
+ types, QVarLengthArray<QVariant, 10>()));
+ continue;
+ }
+
+ // Now convert arguments
+ if (args.count() != types.count())
+ args.resize(types.count());
+
+ QtMethodMatchType retType = types[0];
+ args[0] = QVariant(retType.typeId(), (void *)0); // the return value
+
+ bool converted = true;
+ int matchDistance = 0;
+ for (int i = 0; converted && i < types.count() - 1; ++i) {
+ JSValue* arg = i < jsArgs.size() ? jsArgs[i] : jsUndefined();
+
+ int argdistance = -1;
+ QVariant v = convertValueToQVariant(exec, arg, types.at(i+1).typeId(), &argdistance);
+ if (argdistance >= 0) {
+ matchDistance += argdistance;
+ args[i+1] = v;
+ } else {
+ qMatchDebug() << "failed to convert argument " << i << "type" << types.at(i+1).typeId() << QMetaType::typeName(types.at(i+1).typeId());
+ converted = false;
+ }
+ }
+
+ qMatchDebug() << "Match: " << method.signature() << (converted ? "converted":"failed to convert") << "distance " << matchDistance;
+
+ if (converted) {
+ if ((jsArgs.size() == types.count() - 1)
+ && (matchDistance == 0)) {
+ // perfect match, use this one
+ chosenIndex = index;
+ break;
+ } else {
+ QtMethodMatchData metaArgs(matchDistance, index, types, args);
+ if (candidates.isEmpty()) {
+ candidates.append(metaArgs);
+ } else {
+ QtMethodMatchData otherArgs = candidates.at(0);
+ if ((args.count() > otherArgs.args.count())
+ || ((args.count() == otherArgs.args.count())
+ && (matchDistance <= otherArgs.matchDistance))) {
+ candidates.prepend(metaArgs);
+ } else {
+ candidates.append(metaArgs);
+ }
+ }
+ }
+ } else {
+ conversionFailed.append(index);
+ }
+
+ if (!overloads)
+ break;
+ }
+
+ if (chosenIndex == -1 && candidates.count() == 0) {
+ // No valid functions at all - format an error message
+ if (!conversionFailed.isEmpty()) {
+ QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n")
+ .arg(QLatin1String(signature));
+ for (int i = 0; i < conversionFailed.size(); ++i) {
+ if (i > 0)
+ message += QLatin1String("\n");
+ QMetaMethod mtd = meta->method(conversionFailed.at(i));
+ message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
+ }
+ *pError = throwError(exec, TypeError, message.toLatin1().constData());
+ } else if (!unresolved.isEmpty()) {
+ QtMethodMatchData argsInstance = unresolved.first();
+ int unresolvedIndex = argsInstance.firstUnresolvedIndex();
+ Q_ASSERT(unresolvedIndex != -1);
+ QtMethodMatchType unresolvedType = argsInstance.types.at(unresolvedIndex);
+ QString message = QString::fromLatin1("cannot call %0(): unknown type `%1'")
+ .arg(QString::fromLatin1(signature))
+ .arg(QLatin1String(unresolvedType.name()));
+ *pError = throwError(exec, TypeError, message.toLatin1().constData());
+ } else {
+ QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
+ .arg(QLatin1String(signature));
+ for (int i = 0; i < tooFewArgs.size(); ++i) {
+ if (i > 0)
+ message += QLatin1String("\n");
+ QMetaMethod mtd = meta->method(tooFewArgs.at(i));
+ message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
+ }
+ *pError = throwError(exec, SyntaxError, message.toLatin1().constData());
+ }
+ }
+
+ if (chosenIndex == -1 && candidates.count() > 0) {
+ QtMethodMatchData metaArgs = candidates.at(0);
+ if ((candidates.size() > 1)
+ && (metaArgs.args.count() == candidates.at(1).args.count())
+ && (metaArgs.matchDistance == candidates.at(1).matchDistance)) {
+ // ambiguous call
+ QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n")
+ .arg(QLatin1String(signature));
+ for (int i = 0; i < candidates.size(); ++i) {
+ if (i > 0)
+ message += QLatin1String("\n");
+ QMetaMethod mtd = meta->method(candidates.at(i).index);
+ message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature()));
+ }
+ *pError = throwError(exec, TypeError, message.toLatin1().constData());
+ } else {
+ chosenIndex = metaArgs.index;
+ args = metaArgs.args;
+ }
+ }
+
+ if (chosenIndex != -1) {
+ /* Copy the stuff over */
+ int i;
+ vars.resize(args.count());
+ for (i=0; i < args.count(); i++) {
+ vars[i] = args[i];
+ vvars[i] = vars[i].data();
+ }
+ }
+
+ return chosenIndex;
+}
+
+// Signals are not fuzzy matched as much as methods
+static int findSignalIndex(const QMetaObject* meta, int initialIndex, QByteArray signature)
+{
+ int index = initialIndex;
+ QMetaMethod method = meta->method(index);
+ bool overloads = !signature.contains('(');
+ if (overloads && (method.attributes() & QMetaMethod::Cloned)) {
+ // find the most general method
+ do {
+ method = meta->method(--index);
+ } while (method.attributes() & QMetaMethod::Cloned);
+ }
+ return index;
+}
+
+QtRuntimeMetaMethod::QtRuntimeMetaMethod(ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate)
+ : QtRuntimeMethod (new QtRuntimeMetaMethodData(), exec, ident, inst)
+{
+ QW_D(QtRuntimeMetaMethod);
+ d->m_signature = signature;
+ d->m_index = index;
+ d->m_connect = 0;
+ d->m_disconnect = 0;
+ d->m_allowPrivate = allowPrivate;
+}
+
+void QtRuntimeMetaMethod::mark()
+{
+ QtRuntimeMethod::mark();
+ QW_D(QtRuntimeMetaMethod);
+ if (d->m_connect)
+ d->m_connect->mark();
+ if (d->m_disconnect)
+ d->m_disconnect->mark();
+}
+
+JSValue* QtRuntimeMetaMethod::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+ QW_D(QtRuntimeMetaMethod);
+
+ // We're limited to 10 args
+ if (args.size() > 10)
+ return jsUndefined();
+
+ // We have to pick a method that matches..
+ JSLock lock;
+
+ QObject *obj = d->m_instance->getObject();
+ if (obj) {
+ QVarLengthArray<QVariant, 10> vargs;
+ void *qargs[11];
+
+ int methodIndex;
+ JSObject* errorObj = 0;
+ if ((methodIndex = findMethodIndex(exec, obj->metaObject(), d->m_signature, d->m_allowPrivate, args, vargs, (void **)qargs, &errorObj)) != -1) {
+ if (obj->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0)
+ return jsUndefined();
+
+ if (vargs[0].isValid())
+ return convertQVariantToValue(exec, d->m_instance->rootObject(), vargs[0]);
+ }
+
+ if (errorObj)
+ return errorObj;
+ } else {
+ return throwError(exec, GeneralError, "cannot call function of deleted QObject");
+ }
+
+ // void functions return undefined
+ return jsUndefined();
+}
+
+bool QtRuntimeMetaMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == "connect") {
+ slot.setCustom(this, connectGetter);
+ return true;
+ } else if (propertyName == "disconnect") {
+ slot.setCustom(this, disconnectGetter);
+ return true;
+ } else if (propertyName == exec->propertyNames().length) {
+ slot.setCustom(this, lengthGetter);
+ return true;
+ }
+
+ return QtRuntimeMethod::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+JSValue *QtRuntimeMetaMethod::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&)
+{
+ // QtScript always returns 0
+ return jsNumber(0);
+}
+
+JSValue *QtRuntimeMetaMethod::connectGetter(ExecState* exec, JSObject*, const Identifier& ident, const PropertySlot& slot)
+{
+ QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(slot.slotBase());
+ QW_DS(QtRuntimeMetaMethod, thisObj);
+
+ if (!d->m_connect)
+ d->m_connect = new QtRuntimeConnectionMethod(exec, ident, true, d->m_instance, d->m_index, d->m_signature);
+ return d->m_connect;
+}
+
+JSValue* QtRuntimeMetaMethod::disconnectGetter(ExecState* exec, JSObject*, const Identifier& ident, const PropertySlot& slot)
+{
+ QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(slot.slotBase());
+ QW_DS(QtRuntimeMetaMethod, thisObj);
+
+ if (!d->m_disconnect)
+ d->m_disconnect = new QtRuntimeConnectionMethod(exec, ident, false, d->m_instance, d->m_index, d->m_signature);
+ return d->m_disconnect;
+}
+
+// ===============
+
+QMultiMap<QObject*, QtConnectionObject*> QtRuntimeConnectionMethod::connections;
+
+QtRuntimeConnectionMethod::QtRuntimeConnectionMethod(ExecState* exec, const Identifier& ident, bool isConnect, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature)
+ : QtRuntimeMethod (new QtRuntimeConnectionMethodData(), exec, ident, inst)
+{
+ QW_D(QtRuntimeConnectionMethod);
+
+ d->m_signature = signature;
+ d->m_index = index;
+ d->m_isConnect = isConnect;
+}
+
+JSValue *QtRuntimeConnectionMethod::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+ QW_D(QtRuntimeConnectionMethod);
+
+ JSLock lock;
+
+ QObject* sender = d->m_instance->getObject();
+
+ if (sender) {
+
+ JSObject* thisObject = exec->lexicalGlobalObject();
+ JSObject* funcObject = 0;
+
+ // QtScript checks signalness first, arguments second
+ int signalIndex = -1;
+
+ // Make sure the initial index is a signal
+ QMetaMethod m = sender->metaObject()->method(d->m_index);
+ if (m.methodType() == QMetaMethod::Signal)
+ signalIndex = findSignalIndex(sender->metaObject(), d->m_index, d->m_signature);
+
+ if (signalIndex != -1) {
+ if (args.size() == 1) {
+ funcObject = args[0]->toObject(exec);
+ if (!funcObject->implementsCall()) {
+ if (d->m_isConnect)
+ return throwError(exec, TypeError, "QtMetaMethod.connect: target is not a function");
+ else
+ return throwError(exec, TypeError, "QtMetaMethod.disconnect: target is not a function");
+ }
+ } else if (args.size() >= 2) {
+ if (args[0]->type() == ObjectType) {
+ thisObject = args[0]->toObject(exec);
+
+ // Get the actual function to call
+ JSObject *asObj = args[1]->toObject(exec);
+ if (asObj->implementsCall()) {
+ // Function version
+ funcObject = asObj;
+ } else {
+ // Convert it to a string
+ UString funcName = args[1]->toString(exec);
+ Identifier funcIdent(funcName);
+
+ // ### DropAllLocks
+ // This is resolved at this point in QtScript
+ JSValue* val = thisObject->get(exec, funcIdent);
+ JSObject* asFuncObj = val->toObject(exec);
+
+ if (asFuncObj->implementsCall()) {
+ funcObject = asFuncObj;
+ } else {
+ if (d->m_isConnect)
+ return throwError(exec, TypeError, "QtMetaMethod.connect: target is not a function");
+ else
+ return throwError(exec, TypeError, "QtMetaMethod.disconnect: target is not a function");
+ }
+ }
+ } else {
+ if (d->m_isConnect)
+ return throwError(exec, TypeError, "QtMetaMethod.connect: thisObject is not an object");
+ else
+ return throwError(exec, TypeError, "QtMetaMethod.disconnect: thisObject is not an object");
+ }
+ } else {
+ if (d->m_isConnect)
+ return throwError(exec, GeneralError, "QtMetaMethod.connect: no arguments given");
+ else
+ return throwError(exec, GeneralError, "QtMetaMethod.disconnect: no arguments given");
+ }
+
+ if (d->m_isConnect) {
+ // to connect, we need:
+ // target object [from ctor]
+ // target signal index etc. [from ctor]
+ // receiver function [from arguments]
+ // receiver this object [from arguments]
+
+ QtConnectionObject* conn = new QtConnectionObject(d->m_instance, signalIndex, thisObject, funcObject);
+ bool ok = QMetaObject::connect(sender, signalIndex, conn, conn->metaObject()->methodOffset());
+ if (!ok) {
+ delete conn;
+ QString msg = QString("QtMetaMethod.connect: failed to connect to %1::%2()")
+ .arg(sender->metaObject()->className())
+ .arg(QLatin1String(d->m_signature));
+ return throwError(exec, GeneralError, msg.toLatin1().constData());
+ }
+ else {
+ // Store connection
+ connections.insert(sender, conn);
+ }
+ } else {
+ // Now to find our previous connection object. Hmm.
+ QList<QtConnectionObject*> conns = connections.values(sender);
+ bool ret = false;
+
+ foreach(QtConnectionObject* conn, conns) {
+ // Is this the right connection?
+ if (conn->match(sender, signalIndex, thisObject, funcObject)) {
+ // Yep, disconnect it
+ QMetaObject::disconnect(sender, signalIndex, conn, conn->metaObject()->methodOffset());
+ delete conn; // this will also remove it from the map
+ ret = true;
+ break;
+ }
+ }
+
+ if (!ret) {
+ QString msg = QString("QtMetaMethod.disconnect: failed to disconnect from %1::%2()")
+ .arg(sender->metaObject()->className())
+ .arg(QLatin1String(d->m_signature));
+ return throwError(exec, GeneralError, msg.toLatin1().constData());
+ }
+ }
+ } else {
+ QString msg = QString("QtMetaMethod.%1: %2::%3() is not a signal")
+ .arg(d->m_isConnect ? "connect": "disconnect")
+ .arg(sender->metaObject()->className())
+ .arg(QLatin1String(d->m_signature));
+ return throwError(exec, TypeError, msg.toLatin1().constData());
+ }
+ } else {
+ return throwError(exec, GeneralError, "cannot call function of deleted QObject");
+ }
+
+ return jsUndefined();
+}
+
+bool QtRuntimeConnectionMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ slot.setCustom(this, lengthGetter);
+ return true;
+ }
+
+ return QtRuntimeMethod::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+JSValue *QtRuntimeConnectionMethod::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&)
+{
+ // we have one formal argument, and one optional
+ return jsNumber(1);
+}
+
+// ===============
+
+QtConnectionObject::QtConnectionObject(PassRefPtr<QtInstance> instance, int signalIndex, JSObject* thisObject, JSObject* funcObject)
+ : m_instance(instance)
+ , m_signalIndex(signalIndex)
+ , m_originalObject(m_instance->getObject())
+ , m_thisObject(thisObject)
+ , m_funcObject(funcObject)
+{
+ setParent(m_originalObject);
+ ASSERT(JSLock::currentThreadIsHoldingLock()); // so our ProtectedPtrs are safe
+}
+
+QtConnectionObject::~QtConnectionObject()
+{
+ // Remove us from the map of active connections
+ QtRuntimeConnectionMethod::connections.remove(m_originalObject, this);
+}
+
+static const uint qt_meta_data_QtConnectionObject[] = {
+
+ // content:
+ 1, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 1, 10, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+
+ // slots: signature, parameters, type, tag, flags
+ 28, 27, 27, 27, 0x0a,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_QtConnectionObject[] = {
+ "KJS::Bindings::QtConnectionObject\0\0execute()\0"
+};
+
+const QMetaObject QtConnectionObject::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_QtConnectionObject,
+ qt_meta_data_QtConnectionObject, 0 }
+};
+
+const QMetaObject *QtConnectionObject::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+void *QtConnectionObject::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_QtConnectionObject))
+ return static_cast<void*>(const_cast<QtConnectionObject*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int QtConnectionObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ switch (_id) {
+ case 0: execute(_a); break;
+ }
+ _id -= 1;
+ }
+ return _id;
+}
+
+void QtConnectionObject::execute(void **argv)
+{
+ QObject* obj = m_instance->getObject();
+ if (obj) {
+ const QMetaObject* meta = obj->metaObject();
+ const QMetaMethod method = meta->method(m_signalIndex);
+
+ QList<QByteArray> parameterTypes = method.parameterTypes();
+
+ int argc = parameterTypes.count();
+
+ JSLock lock;
+
+ // ### Should the Interpreter/ExecState come from somewhere else?
+ RefPtr<RootObject> ro = m_instance->rootObject();
+ if (ro) {
+ JSGlobalObject* globalobj = ro->globalObject();
+ if (globalobj) {
+ ExecState* exec = globalobj->globalExec();
+ if (exec) {
+ // Build the argument list (up to the formal argument length of the slot)
+ List l;
+ // ### DropAllLocks?
+ int funcArgC = m_funcObject->get(exec, exec->propertyNames().length)->toInt32(exec);
+ int argTotal = qMax(funcArgC, argc);
+ for(int i=0; i < argTotal; i++) {
+ if (i < argc) {
+ int argType = QMetaType::type(parameterTypes.at(i));
+ l.append(convertQVariantToValue(exec, ro, QVariant(argType, argv[i+1])));
+ } else {
+ l.append(jsUndefined());
+ }
+ }
+ // Stuff in the __qt_sender property, if we can
+ if (m_funcObject->inherits(&FunctionImp::info)) {
+ FunctionImp* fimp = static_cast<FunctionImp*>(m_funcObject.get());
+
+ JSObject* qt_sender = Instance::createRuntimeObject(Instance::QtLanguage, sender(), ro);
+ JSObject* wrapper = new JSObject();
+ wrapper->put(exec, "__qt_sender__", qt_sender);
+ ScopeChain oldsc = fimp->scope();
+ ScopeChain sc = oldsc;
+ sc.push(wrapper);
+ fimp->setScope(sc);
+ fimp->call(exec, m_thisObject, l);
+ fimp->setScope(oldsc);
+ } else
+ m_funcObject->call(exec, m_thisObject, l);
+ }
+ }
+ }
+ } else {
+ // A strange place to be - a deleted object emitted a signal here.
+ qWarning() << "sender deleted, cannot deliver signal";
+ }
+}
+
+bool QtConnectionObject::match(QObject* sender, int signalIndex, JSObject* thisObject, JSObject *funcObject)
+{
+ if (m_originalObject == sender && m_signalIndex == signalIndex
+ && thisObject == (JSObject*)m_thisObject && funcObject == (JSObject*)m_funcObject)
+ return true;
+ return false;
+}
+
+// ===============
+
+template <typename T> QtArray<T>::QtArray(QList<T> list, QMetaType::Type type, PassRefPtr<RootObject> rootObject)
+ : Array(rootObject)
+ , m_list(list)
+ , m_type(type)
+{
+ m_length = m_list.count();
+}
+
+template <typename T> QtArray<T>::~QtArray ()
+{
+}
+
+template <typename T> RootObject* QtArray<T>::rootObject() const
+{
+ return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
+}
+
+template <typename T> void QtArray<T>::setValueAt(ExecState *exec, unsigned int index, JSValue *aValue) const
+{
+ // QtScript sets the value, but doesn't forward it to the original source
+ // (e.g. if you do 'object.intList[5] = 6', the object is not updated, but the
+ // copy of the list is).
+ int dist = -1;
+ QVariant val = convertValueToQVariant(exec, aValue, m_type, &dist);
+
+ if (dist >= 0) {
+ m_list[index] = val.value<T>();
+ }
+}
+
+
+template <typename T> JSValue* QtArray<T>::valueAt(ExecState *exec, unsigned int index) const
+{
+ if (index < m_length) {
+ T val = m_list.at(index);
+ return convertQVariantToValue(exec, rootObject(), QVariant::fromValue(val));
+ }
+
+ return jsUndefined();
+}
+
+// ===============
+
+} }
diff --git a/JavaScriptCore/bindings/qt/qt_runtime.h b/JavaScriptCore/bindings/qt/qt_runtime.h
new file mode 100644
index 0000000..e44af7b
--- /dev/null
+++ b/JavaScriptCore/bindings/qt/qt_runtime.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef BINDINGS_QT_RUNTIME_H_
+#define BINDINGS_QT_RUNTIME_H_
+
+#include "runtime.h"
+#include "runtime_method.h"
+#include "protect.h"
+
+#include <qbytearray.h>
+#include <qmetaobject.h>
+#include <qpointer.h>
+
+namespace KJS {
+namespace Bindings {
+
+class QtInstance;
+
+class QtField : public Field {
+public:
+
+ typedef enum {
+ MetaProperty,
+ DynamicProperty,
+ ChildObject
+ } QtFieldType;
+
+ QtField(const QMetaProperty &p)
+ : m_type(MetaProperty), m_property(p)
+ {}
+
+ QtField(const QByteArray &b)
+ : m_type(DynamicProperty), m_dynamicProperty(b)
+ {}
+
+ QtField(QObject *child)
+ : m_type(ChildObject), m_childObject(child)
+ {}
+
+ virtual JSValue* valueFromInstance(ExecState*, const Instance*) const;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue*) const;
+ virtual const char* name() const;
+ QtFieldType fieldType() const {return m_type;}
+private:
+ QtFieldType m_type;
+ QByteArray m_dynamicProperty;
+ QMetaProperty m_property;
+ QPointer<QObject> m_childObject;
+};
+
+
+class QtMethod : public Method
+{
+public:
+ QtMethod(const QMetaObject *mo, int i, const QByteArray &ident, int numParameters)
+ : m_metaObject(mo),
+ m_index(i),
+ m_identifier(ident),
+ m_nParams(numParameters)
+ { }
+
+ virtual const char* name() const { return m_identifier.constData(); }
+ virtual int numParameters() const { return m_nParams; }
+
+private:
+ friend class QtInstance;
+ const QMetaObject *m_metaObject;
+ int m_index;
+ QByteArray m_identifier;
+ int m_nParams;
+};
+
+
+template <typename T> class QtArray : public Array
+{
+public:
+ QtArray(QList<T> list, QMetaType::Type type, PassRefPtr<RootObject>);
+ virtual ~QtArray();
+
+ RootObject* rootObject() const;
+
+ 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 {return m_length;}
+
+private:
+ mutable QList<T> m_list; // setValueAt is const!
+ unsigned int m_length;
+ QMetaType::Type m_type;
+};
+
+// Based on RuntimeMethod
+
+// Extra data classes (to avoid the CELL_SIZE limit on JS objects)
+
+class QtRuntimeMethodData {
+ public:
+ virtual ~QtRuntimeMethodData();
+ RefPtr<QtInstance> m_instance;
+};
+
+class QtRuntimeConnectionMethod;
+class QtRuntimeMetaMethodData : public QtRuntimeMethodData {
+ public:
+ ~QtRuntimeMetaMethodData();
+ QByteArray m_signature;
+ bool m_allowPrivate;
+ int m_index;
+ QtRuntimeConnectionMethod *m_connect;
+ QtRuntimeConnectionMethod *m_disconnect;
+};
+
+class QtRuntimeConnectionMethodData : public QtRuntimeMethodData {
+ public:
+ ~QtRuntimeConnectionMethodData();
+ QByteArray m_signature;
+ int m_index;
+ bool m_isConnect;
+};
+
+// Common base class (doesn't really do anything interesting)
+class QtRuntimeMethod : public InternalFunctionImp
+{
+public:
+ virtual ~QtRuntimeMethod();
+
+ virtual CodeType codeType() const;
+ virtual Completion execute(ExecState *exec);
+
+protected:
+ QtRuntimeMethodData *d_func() const {return d_ptr;}
+ QtRuntimeMethod(QtRuntimeMethodData *dd, ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst);
+ QtRuntimeMethodData *d_ptr;
+};
+
+class QtRuntimeMetaMethod : public QtRuntimeMethod
+{
+public:
+ QtRuntimeMetaMethod(ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate);
+
+ virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+ virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+
+ virtual void mark();
+
+protected:
+ QtRuntimeMetaMethodData* d_func() const {return reinterpret_cast<QtRuntimeMetaMethodData*>(d_ptr);}
+
+private:
+ static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+ static JSValue *connectGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+ static JSValue *disconnectGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+};
+
+class QtConnectionObject;
+class QtRuntimeConnectionMethod : public QtRuntimeMethod
+{
+public:
+ QtRuntimeConnectionMethod(ExecState *exec, const Identifier &n, bool isConnect, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature );
+
+ virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+ virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+
+protected:
+ QtRuntimeConnectionMethodData* d_func() const {return reinterpret_cast<QtRuntimeConnectionMethodData*>(d_ptr);}
+
+private:
+ static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+ static QMultiMap<QObject *, QtConnectionObject *> connections;
+ friend class QtConnectionObject;
+};
+
+class QtConnectionObject: public QObject
+{
+public:
+ QtConnectionObject(PassRefPtr<QtInstance> instance, int signalIndex, JSObject* thisObject, JSObject* funcObject);
+ ~QtConnectionObject();
+
+ static const QMetaObject staticMetaObject;
+ virtual const QMetaObject *metaObject() const;
+ virtual void *qt_metacast(const char *);
+ virtual int qt_metacall(QMetaObject::Call, int, void **argv);
+
+ bool match(QObject *sender, int signalIndex, JSObject* thisObject, JSObject *funcObject);
+
+ // actual slot:
+ void execute(void **argv);
+
+private:
+ RefPtr<QtInstance> m_instance;
+ int m_signalIndex;
+ QObject* m_originalObject; // only used as a key, not dereferenced
+ ProtectedPtr<JSObject> m_thisObject;
+ ProtectedPtr<JSObject> m_funcObject;
+};
+
+} // namespace Bindings
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/runtime.cpp b/JavaScriptCore/bindings/runtime.cpp
new file mode 100644
index 0000000..cc68fa6
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2003, 2006 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 "runtime.h"
+
+#include "JSLock.h"
+#include "NP_jsobject.h"
+#include "c_instance.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+
+#if HAVE(JNI)
+#include "jni_instance.h"
+#endif
+#if PLATFORM(MAC)
+#include "objc_instance.h"
+#endif
+#if PLATFORM(QT)
+#include "qt_instance.h"
+#endif
+
+namespace KJS { namespace Bindings {
+
+Array::Array(PassRefPtr<RootObject> rootObject)
+ : _rootObject(rootObject)
+{
+ ASSERT(_rootObject);
+}
+
+Array::~Array()
+{
+}
+
+Instance::Instance(PassRefPtr<RootObject> rootObject)
+ : _rootObject(rootObject)
+ , _refCount(0)
+{
+ ASSERT(_rootObject);
+}
+
+Instance::~Instance()
+{
+}
+
+static KJSDidExecuteFunctionPtr _DidExecuteFunction;
+
+void Instance::setDidExecuteFunction(KJSDidExecuteFunctionPtr func) { _DidExecuteFunction = func; }
+KJSDidExecuteFunctionPtr Instance::didExecuteFunction() { return _DidExecuteFunction; }
+
+JSValue *Instance::getValueOfField(ExecState *exec, const Field *aField) const
+{
+ return aField->valueFromInstance(exec, this);
+}
+
+void Instance::setValueOfField(ExecState *exec, const Field *aField, JSValue *aValue) const
+{
+ aField->setValueToInstance(exec, this, aValue);
+}
+
+Instance* Instance::createBindingForLanguageInstance(BindingLanguage language, void* nativeInstance, PassRefPtr<RootObject> rootObject)
+{
+ Instance *newInstance = 0;
+
+ switch (language) {
+#if HAVE(JNI)
+ case Instance::JavaLanguage: {
+ newInstance = new Bindings::JavaInstance((jobject)nativeInstance, rootObject);
+ break;
+ }
+#endif
+#if PLATFORM(MAC)
+ case Instance::ObjectiveCLanguage: {
+ newInstance = new Bindings::ObjcInstance((ObjectStructPtr)nativeInstance, rootObject);
+ break;
+ }
+#endif
+#if !PLATFORM(DARWIN) || !defined(__LP64__)
+ case Instance::CLanguage: {
+ newInstance = new Bindings::CInstance((NPObject *)nativeInstance, rootObject);
+ break;
+ }
+#endif
+#if PLATFORM(QT)
+ case Instance::QtLanguage: {
+ newInstance = Bindings::QtInstance::getQtInstance((QObject *)nativeInstance, rootObject);
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ return newInstance;
+}
+
+JSObject* Instance::createRuntimeObject(BindingLanguage language, void* nativeInstance, PassRefPtr<RootObject> rootObject)
+{
+ Instance* instance = Instance::createBindingForLanguageInstance(language, nativeInstance, rootObject);
+
+ return createRuntimeObject(instance);
+}
+
+JSObject* Instance::createRuntimeObject(Instance* instance)
+{
+#if PLATFORM(QT)
+ if (instance->getBindingLanguage() == QtLanguage)
+ return QtInstance::getRuntimeObject(static_cast<QtInstance*>(instance));
+#endif
+ JSLock lock;
+
+ return new RuntimeObjectImp(instance);
+}
+
+Instance* Instance::getInstance(JSObject* object, BindingLanguage language)
+{
+ if (!object)
+ return 0;
+ if (!object->inherits(&RuntimeObjectImp::info))
+ return 0;
+ Instance* instance = (static_cast<RuntimeObjectImp*>(object))->getInternalInstance();
+ if (!instance)
+ return 0;
+ if (instance->getBindingLanguage() != language)
+ return 0;
+ return instance;
+}
+
+RootObject* Instance::rootObject() const
+{
+ return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0;
+}
+
+} } // namespace KJS::Bindings
diff --git a/JavaScriptCore/bindings/runtime.h b/JavaScriptCore/bindings/runtime.h
new file mode 100644
index 0000000..dbb324c
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime.h
@@ -0,0 +1,174 @@
+/*
+ * 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 JAVASCRIPTCORE_BINDINGS_RUNTIME_H
+#define JAVASCRIPTCORE_BINDINGS_RUNTIME_H
+
+#include "value.h"
+
+#include <wtf/Noncopyable.h>
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+namespace KJS {
+
+class Identifier;
+class List;
+class PropertyNameArray;
+
+namespace Bindings {
+
+class Instance;
+class Method;
+class RootObject;
+
+typedef Vector<Method*> MethodList;
+
+class Field
+{
+public:
+ virtual const char* name() const = 0;
+
+ virtual JSValue* valueFromInstance(ExecState*, const Instance*) const = 0;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue*) const = 0;
+
+ virtual ~Field() {}
+};
+
+class Method : Noncopyable
+{
+public:
+ virtual const char *name() const = 0;
+
+ virtual int numParameters() const = 0;
+
+ virtual ~Method() {}
+};
+
+class Class : Noncopyable
+{
+public:
+ virtual const char *name() const = 0;
+
+ virtual MethodList methodsNamed(const Identifier&, Instance*) const = 0;
+
+ virtual Field *fieldNamed(const Identifier&, Instance*) const = 0;
+
+ virtual JSValue* fallbackObject(ExecState*, Instance*, const Identifier&) { return jsUndefined(); }
+
+ virtual ~Class() {}
+};
+
+typedef void (*KJSDidExecuteFunctionPtr)(ExecState*, JSObject* rootObject);
+
+class Instance : Noncopyable {
+public:
+ typedef enum {
+ JavaLanguage,
+ ObjectiveCLanguage,
+ CLanguage
+#if PLATFORM(QT)
+ , QtLanguage
+#endif
+ } BindingLanguage;
+
+ Instance(PassRefPtr<RootObject>);
+
+ static void setDidExecuteFunction(KJSDidExecuteFunctionPtr func);
+ static KJSDidExecuteFunctionPtr didExecuteFunction();
+
+ static Instance* createBindingForLanguageInstance(BindingLanguage, void* nativeInstance, PassRefPtr<RootObject>);
+ static JSObject* createRuntimeObject(BindingLanguage, void* nativeInstance, PassRefPtr<RootObject>);
+ static JSObject* createRuntimeObject(Instance*);
+
+ static Instance* getInstance(JSObject*, BindingLanguage);
+
+ void ref() { _refCount++; }
+ void deref()
+ {
+ if (--_refCount == 0)
+ delete this;
+ }
+
+ // These functions are called before and after the main entry points into
+ // the native implementations. They can be used to establish and cleanup
+ // any needed state.
+ virtual void begin() {}
+ virtual void end() {}
+
+ virtual Class *getClass() const = 0;
+
+ virtual JSValue* getValueOfField(ExecState*, const Field*) const;
+ virtual JSValue* getValueOfUndefinedField(ExecState*, const Identifier&, JSType) const { return jsUndefined(); }
+ virtual void setValueOfField(ExecState*, const Field*, JSValue*) const;
+ virtual bool supportsSetValueOfUndefinedField() { return false; }
+ virtual void setValueOfUndefinedField(ExecState*, const Identifier&, JSValue*) {}
+
+ virtual bool implementsCall() const { return false; }
+
+ virtual JSValue* invokeMethod(ExecState*, const MethodList&, const List& args) = 0;
+ virtual JSValue* invokeDefaultMethod(ExecState*, const List&) { return jsUndefined(); }
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&) { }
+
+ virtual JSValue* defaultValue(JSType hint) const = 0;
+
+ virtual JSValue* valueOf() const { return jsString(getClass()->name()); }
+
+ RootObject* rootObject() const;
+
+ virtual ~Instance();
+
+ virtual BindingLanguage getBindingLanguage() const = 0;
+
+protected:
+ RefPtr<RootObject> _rootObject;
+ unsigned _refCount;
+};
+
+class Array : Noncopyable
+{
+public:
+ Array(PassRefPtr<RootObject>);
+ virtual ~Array();
+
+ virtual void setValueAt(ExecState *, unsigned index, JSValue*) const = 0;
+ virtual JSValue* valueAt(ExecState *, unsigned index) const = 0;
+ virtual unsigned int getLength() const = 0;
+protected:
+ RefPtr<RootObject> _rootObject;
+};
+
+const char *signatureForParameters(const List&);
+
+typedef HashMap<RefPtr<UString::Rep>, MethodList*> MethodListMap;
+typedef HashMap<RefPtr<UString::Rep>, Method*> MethodMap;
+typedef HashMap<RefPtr<UString::Rep>, Field*> FieldMap;
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/runtime_array.cpp b/JavaScriptCore/bindings/runtime_array.cpp
new file mode 100644
index 0000000..005bae2
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime_array.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "runtime_array.h"
+
+#include "JSGlobalObject.h"
+#include "array_object.h"
+
+using namespace KJS;
+
+const ClassInfo RuntimeArray::info = { "RuntimeArray", &ArrayInstance::info, 0 };
+
+RuntimeArray::RuntimeArray(ExecState *exec, Bindings::Array *a)
+ : JSObject(exec->lexicalGlobalObject()->arrayPrototype())
+ , _array(a)
+{
+}
+
+JSValue *RuntimeArray::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
+{
+ RuntimeArray *thisObj = static_cast<RuntimeArray *>(slot.slotBase());
+ return jsNumber(thisObj->getLength());
+}
+
+JSValue *RuntimeArray::indexGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
+{
+ RuntimeArray *thisObj = static_cast<RuntimeArray *>(slot.slotBase());
+ return thisObj->getConcreteArray()->valueAt(exec, slot.index());
+}
+
+bool RuntimeArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ slot.setCustom(this, lengthGetter);
+ return true;
+ }
+
+ bool ok;
+ unsigned index = propertyName.toArrayIndex(&ok);
+ if (ok) {
+ if (index < getLength()) {
+ slot.setCustomIndex(this, index, indexGetter);
+ return true;
+ }
+ }
+
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool RuntimeArray::getOwnPropertySlot(ExecState *exec, unsigned index, PropertySlot& slot)
+{
+ if (index < getLength()) {
+ slot.setCustomIndex(this, index, indexGetter);
+ return true;
+ }
+
+ return JSObject::getOwnPropertySlot(exec, index, slot);
+}
+
+void RuntimeArray::put(ExecState* exec, const Identifier& propertyName, JSValue* value)
+{
+ if (propertyName == exec->propertyNames().length) {
+ throwError(exec, RangeError);
+ return;
+ }
+
+ bool ok;
+ unsigned index = propertyName.toArrayIndex(&ok);
+ if (ok) {
+ getConcreteArray()->setValueAt(exec, index, value);
+ return;
+ }
+
+ JSObject::put(exec, propertyName, value);
+}
+
+void RuntimeArray::put(ExecState* exec, unsigned index, JSValue* value)
+{
+ if (index >= getLength()) {
+ throwError(exec, RangeError);
+ return;
+ }
+
+ getConcreteArray()->setValueAt(exec, index, value);
+}
+
+bool RuntimeArray::deleteProperty(ExecState*, const Identifier&)
+{
+ return false;
+}
+
+bool RuntimeArray::deleteProperty(ExecState*, unsigned)
+{
+ return false;
+}
diff --git a/JavaScriptCore/bindings/runtime_array.h b/JavaScriptCore/bindings/runtime_array.h
new file mode 100644
index 0000000..74b540f
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime_array.h
@@ -0,0 +1,65 @@
+/*
+ * 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 RUNTIME_ARRAY_H_
+#define RUNTIME_ARRAY_H_
+
+#include <wtf/OwnPtr.h>
+
+#include "array_instance.h"
+#include "runtime.h"
+
+namespace KJS {
+
+class RuntimeArray : public JSObject {
+public:
+ RuntimeArray(ExecState *exec, Bindings::Array *i);
+
+ virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState *, unsigned, PropertySlot&);
+ virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value);
+ virtual void put(ExecState *exec, unsigned propertyName, JSValue *value);
+
+ virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
+ virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
+
+ virtual const ClassInfo *classInfo() const { return &info; }
+
+ unsigned getLength() const { return getConcreteArray()->getLength(); }
+
+ Bindings::Array *getConcreteArray() const { return _array.get(); }
+
+ static const ClassInfo info;
+
+private:
+ static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+ static JSValue *indexGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+
+ OwnPtr<Bindings::Array> _array;
+};
+
+} // namespace KJS
+
+#endif // RUNTIME_ARRAY_H_
diff --git a/JavaScriptCore/bindings/runtime_method.cpp b/JavaScriptCore/bindings/runtime_method.cpp
new file mode 100644
index 0000000..4430f25
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime_method.cpp
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "runtime_method.h"
+
+#include "ExecState.h"
+#include "JSGlobalObject.h"
+#include "runtime_object.h"
+#include "function_object.h"
+
+using namespace KJS::Bindings;
+using namespace KJS;
+
+RuntimeMethod::RuntimeMethod(ExecState *exec, const Identifier &ident, Bindings::MethodList &m)
+ : InternalFunctionImp(exec->lexicalGlobalObject()->functionPrototype(), ident)
+ , _methodList(new MethodList(m))
+{
+}
+
+JSValue *RuntimeMethod::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
+{
+ RuntimeMethod *thisObj = static_cast<RuntimeMethod *>(slot.slotBase());
+
+ // Ick! There may be more than one method with this name. Arbitrarily
+ // just pick the first method. The fundamental problem here is that
+ // JavaScript doesn't have the notion of method overloading and
+ // Java does.
+ // FIXME: a better solution might be to give the maximum number of parameters
+ // of any method
+ return jsNumber(thisObj->_methodList->at(0)->numParameters());
+}
+
+bool RuntimeMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ slot.setCustom(this, lengthGetter);
+ return true;
+ }
+
+ return InternalFunctionImp::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+JSValue *RuntimeMethod::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
+{
+ if (_methodList->isEmpty())
+ return jsUndefined();
+
+ RuntimeObjectImp *imp = 0;
+
+ if (thisObj->classInfo() == &KJS::RuntimeObjectImp::info) {
+ imp = static_cast<RuntimeObjectImp*>(thisObj);
+ } else {
+ // If thisObj is the DOM object for a plugin, get the corresponding
+ // runtime object from the DOM object.
+ JSValue* value = thisObj->get(exec, "__apple_runtime_object");
+ if (value->isObject(&KJS::RuntimeObjectImp::info))
+ imp = static_cast<RuntimeObjectImp*>(value);
+ }
+
+ if (!imp)
+ return throwError(exec, TypeError);
+
+ RefPtr<Instance> instance = imp->getInternalInstance();
+ if (!instance)
+ return RuntimeObjectImp::throwInvalidAccessError(exec);
+
+ instance->begin();
+ JSValue *aValue = instance->invokeMethod(exec, *_methodList, args);
+ instance->end();
+ return aValue;
+}
diff --git a/JavaScriptCore/bindings/runtime_method.h b/JavaScriptCore/bindings/runtime_method.h
new file mode 100644
index 0000000..7fbe32a
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime_method.h
@@ -0,0 +1,51 @@
+/*
+ * 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 RUNTIME_FUNCTION_H_
+#define RUNTIME_FUNCTION_H_
+
+#include "function.h"
+#include "runtime.h"
+#include "object.h"
+
+namespace KJS {
+
+class RuntimeMethod : public InternalFunctionImp {
+public:
+ RuntimeMethod(ExecState *exec, const Identifier &n, Bindings::MethodList &methodList);
+
+ virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+
+ virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+
+private:
+ static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+
+ OwnPtr<Bindings::MethodList> _methodList;
+};
+
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/runtime_object.cpp b/JavaScriptCore/bindings/runtime_object.cpp
new file mode 100644
index 0000000..30ab488
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime_object.cpp
@@ -0,0 +1,238 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "runtime_object.h"
+
+#include "error_object.h"
+#include "operations.h"
+#include "runtime_method.h"
+#include "runtime_root.h"
+
+using namespace KJS;
+using namespace Bindings;
+
+const ClassInfo RuntimeObjectImp::info = { "RuntimeObject", 0, 0 };
+
+RuntimeObjectImp::RuntimeObjectImp(Bindings::Instance *i)
+: instance(i)
+{
+ instance->rootObject()->addRuntimeObject(this);
+}
+
+RuntimeObjectImp::~RuntimeObjectImp()
+{
+ if (instance)
+ instance->rootObject()->removeRuntimeObject(this);
+}
+
+void RuntimeObjectImp::invalidate()
+{
+ ASSERT(instance);
+ instance = 0;
+}
+
+JSValue *RuntimeObjectImp::fallbackObjectGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
+{
+ RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
+ RefPtr<Bindings::Instance> instance = thisObj->instance;
+
+ if (!instance)
+ return throwInvalidAccessError(exec);
+
+ instance->begin();
+
+ Class *aClass = instance->getClass();
+ JSValue* result = aClass->fallbackObject(exec, instance.get(), propertyName);
+
+ instance->end();
+
+ return result;
+}
+
+JSValue *RuntimeObjectImp::fieldGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
+{
+ RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
+ RefPtr<Bindings::Instance> instance = thisObj->instance;
+
+ if (!instance)
+ return throwInvalidAccessError(exec);
+
+ instance->begin();
+
+ Class *aClass = instance->getClass();
+ Field* aField = aClass->fieldNamed(propertyName, instance.get());
+ JSValue *result = instance->getValueOfField(exec, aField);
+
+ instance->end();
+
+ return result;
+}
+
+JSValue *RuntimeObjectImp::methodGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
+{
+ RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
+ RefPtr<Bindings::Instance> instance = thisObj->instance;
+
+ if (!instance)
+ return throwInvalidAccessError(exec);
+
+ instance->begin();
+
+ Class *aClass = instance->getClass();
+ MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
+ JSValue *result = new RuntimeMethod(exec, propertyName, methodList);
+
+ instance->end();
+
+ return result;
+}
+
+bool RuntimeObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (!instance) {
+ throwInvalidAccessError(exec);
+ return false;
+ }
+
+ instance->begin();
+
+ Class *aClass = instance->getClass();
+
+ if (aClass) {
+ // See if the instance has a field with the specified name.
+ Field *aField = aClass->fieldNamed(propertyName, instance.get());
+ if (aField) {
+ slot.setCustom(this, fieldGetter);
+ instance->end();
+ return true;
+ } else {
+ // Now check if a method with specified name exists, if so return a function object for
+ // that method.
+ MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
+ if (methodList.size() > 0) {
+ slot.setCustom(this, methodGetter);
+
+ instance->end();
+ return true;
+ }
+ }
+
+ // Try a fallback object.
+ if (!aClass->fallbackObject(exec, instance.get(), propertyName)->isUndefined()) {
+ slot.setCustom(this, fallbackObjectGetter);
+ instance->end();
+ return true;
+ }
+ }
+
+ instance->end();
+
+ // don't call superclass, because runtime objects can't have custom properties or a prototype
+ return false;
+}
+
+void RuntimeObjectImp::put(ExecState* exec, const Identifier& propertyName, JSValue* value)
+{
+ if (!instance) {
+ throwInvalidAccessError(exec);
+ return;
+ }
+
+ RefPtr<Bindings::Instance> protector(instance);
+ instance->begin();
+
+ // Set the value of the property.
+ Field *aField = instance->getClass()->fieldNamed(propertyName, instance.get());
+ if (aField)
+ instance->setValueOfField(exec, aField, value);
+ else if (instance->supportsSetValueOfUndefinedField())
+ instance->setValueOfUndefinedField(exec, propertyName, value);
+
+ instance->end();
+}
+
+bool RuntimeObjectImp::deleteProperty(ExecState*, const Identifier&)
+{
+ // Can never remove a property of a RuntimeObject.
+ return false;
+}
+
+JSValue *RuntimeObjectImp::defaultValue(ExecState* exec, JSType hint) const
+{
+ if (!instance)
+ return throwInvalidAccessError(exec);
+
+ JSValue *result;
+
+ RefPtr<Bindings::Instance> protector(instance);
+ instance->begin();
+
+ result = instance->defaultValue(hint);
+
+ instance->end();
+
+ return result;
+}
+
+bool RuntimeObjectImp::implementsCall() const
+{
+ if (!instance)
+ return false;
+
+ return instance->implementsCall();
+}
+
+JSValue *RuntimeObjectImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
+{
+ if (!instance)
+ return throwInvalidAccessError(exec);
+
+ RefPtr<Bindings::Instance> protector(instance);
+ instance->begin();
+
+ JSValue *aValue = instance->invokeDefaultMethod(exec, args);
+
+ instance->end();
+
+ return aValue;
+}
+
+void RuntimeObjectImp::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ if (!instance) {
+ throwInvalidAccessError(exec);
+ return;
+ }
+
+ instance->begin();
+ instance->getPropertyNames(exec, propertyNames);
+ instance->end();
+}
+
+JSObject* RuntimeObjectImp::throwInvalidAccessError(ExecState* exec)
+{
+ return throwError(exec, ReferenceError, "Trying to access object from destroyed plug-in.");
+}
diff --git a/JavaScriptCore/bindings/runtime_object.h b/JavaScriptCore/bindings/runtime_object.h
new file mode 100644
index 0000000..e2387e3
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime_object.h
@@ -0,0 +1,73 @@
+/*
+ * 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_RUNTIME_OBJECT_H
+#define KJS_RUNTIME_OBJECT_H
+
+#include "runtime.h"
+#include "object.h"
+
+#include <wtf/Noncopyable.h>
+
+namespace KJS {
+
+class RuntimeObjectImp : public JSObject {
+public:
+ virtual ~RuntimeObjectImp();
+
+ const ClassInfo *classInfo() const { return &info; }
+
+ virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+ virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value);
+ virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
+ virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
+ virtual bool implementsCall() const;
+ virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual void invalidate();
+ Bindings::Instance *getInternalInstance() const { return instance.get(); }
+
+ static JSObject* throwInvalidAccessError(ExecState*);
+
+ static const ClassInfo info;
+
+protected:
+ friend class Bindings::Instance;
+ RuntimeObjectImp(Bindings::Instance*); // Only allow Instances and derived classes to create us
+
+private:
+ RuntimeObjectImp(); // prevent default construction
+
+ static JSValue *fallbackObjectGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+ static JSValue *fieldGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+ static JSValue *methodGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+
+ RefPtr<Bindings::Instance> instance;
+};
+
+} // namespace
+
+#endif
diff --git a/JavaScriptCore/bindings/runtime_root.cpp b/JavaScriptCore/bindings/runtime_root.cpp
new file mode 100644
index 0000000..e7ae28f
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime_root.cpp
@@ -0,0 +1,305 @@
+/*
+ * 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 "runtime_root.h"
+
+#include "JSGlobalObject.h"
+#include "object.h"
+#include "runtime.h"
+#include "runtime_object.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
+
+namespace KJS { namespace Bindings {
+
+// This code attempts to solve two problems: (1) plug-ins leaking references to
+// JS and the DOM; (2) plug-ins holding stale references to JS and the DOM. Previous
+// comments in this file claimed that problem #1 was an issue in Java, in particular,
+// because Java, allegedly, didn't always call finalize when collecting an object.
+
+typedef HashSet<RootObject*> RootObjectSet;
+
+static RootObjectSet* rootObjectSet()
+{
+ static RootObjectSet staticRootObjectSet;
+ return &staticRootObjectSet;
+}
+
+// FIXME: These two functions are a potential performance problem. We could
+// fix them by adding a JSObject to RootObject dictionary.
+
+RootObject* findProtectingRootObject(JSObject* jsObject)
+{
+ RootObjectSet::const_iterator end = rootObjectSet()->end();
+ for (RootObjectSet::const_iterator it = rootObjectSet()->begin(); it != end; ++it) {
+ if ((*it)->gcIsProtected(jsObject))
+ return *it;
+ }
+ return 0;
+}
+
+RootObject* findRootObject(JSGlobalObject* globalObject)
+{
+ RootObjectSet::const_iterator end = rootObjectSet()->end();
+ for (RootObjectSet::const_iterator it = rootObjectSet()->begin(); it != end; ++it) {
+ if ((*it)->globalObject() == globalObject)
+ return *it;
+ }
+ return 0;
+}
+
+#if PLATFORM(MAC)
+// May only be set by dispatchToJavaScriptThread().
+static CFRunLoopSourceRef completionSource;
+
+static void completedJavaScriptAccess (void *i)
+{
+ assert (CFRunLoopGetCurrent() != RootObject::runLoop());
+
+ JSObjectCallContext *callContext = (JSObjectCallContext *)i;
+ CFRunLoopRef runLoop = (CFRunLoopRef)callContext->originatingLoop;
+
+ assert (CFRunLoopGetCurrent() == runLoop);
+
+ CFRunLoopStop(runLoop);
+}
+
+static pthread_once_t javaScriptAccessLockOnce = PTHREAD_ONCE_INIT;
+static pthread_mutex_t javaScriptAccessLock;
+static int javaScriptAccessLockCount = 0;
+
+static void initializeJavaScriptAccessLock()
+{
+ pthread_mutexattr_t attr;
+
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+
+ pthread_mutex_init(&javaScriptAccessLock, &attr);
+}
+
+static inline void lockJavaScriptAccess()
+{
+ // Perhaps add deadlock detection?
+ pthread_once(&javaScriptAccessLockOnce, initializeJavaScriptAccessLock);
+ pthread_mutex_lock(&javaScriptAccessLock);
+ javaScriptAccessLockCount++;
+}
+
+static inline void unlockJavaScriptAccess()
+{
+ javaScriptAccessLockCount--;
+ pthread_mutex_unlock(&javaScriptAccessLock);
+}
+
+
+void RootObject::dispatchToJavaScriptThread(JSObjectCallContext *context)
+{
+ // This lock guarantees that only one thread can invoke
+ // at a time, and also guarantees that completionSource;
+ // won't get clobbered.
+ lockJavaScriptAccess();
+
+ CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
+
+ assert (currentRunLoop != RootObject::runLoop());
+
+ // Setup a source to signal once the invocation of the JavaScript
+ // call completes.
+ //
+ // FIXME: This could be a potential performance issue. Creating and
+ // adding run loop sources is expensive. We could create one source
+ // per thread, as needed, instead.
+ context->originatingLoop = currentRunLoop;
+ CFRunLoopSourceContext sourceContext = {0, context, NULL, NULL, NULL, NULL, NULL, NULL, NULL, completedJavaScriptAccess};
+ completionSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
+ CFRunLoopAddSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
+
+ // Wakeup JavaScript access thread and make it do it's work.
+ CFRunLoopSourceSignal(RootObject::performJavaScriptSource());
+ if (CFRunLoopIsWaiting(RootObject::runLoop())) {
+ CFRunLoopWakeUp(RootObject::runLoop());
+ }
+
+ // Wait until the JavaScript access thread is done.
+ CFRunLoopRun ();
+
+ CFRunLoopRemoveSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
+ CFRelease (completionSource);
+
+ unlockJavaScriptAccess();
+}
+
+static void performJavaScriptAccess(void*)
+{
+ assert (CFRunLoopGetCurrent() == RootObject::runLoop());
+
+ // Dispatch JavaScript calls here.
+ CFRunLoopSourceContext sourceContext;
+ CFRunLoopSourceGetContext (completionSource, &sourceContext);
+ JSObjectCallContext *callContext = (JSObjectCallContext *)sourceContext.info;
+ CFRunLoopRef originatingLoop = callContext->originatingLoop;
+
+ JavaJSObject::invoke (callContext);
+
+ // Signal the originating thread that we're done.
+ CFRunLoopSourceSignal (completionSource);
+ if (CFRunLoopIsWaiting(originatingLoop)) {
+ CFRunLoopWakeUp(originatingLoop);
+ }
+}
+
+CreateRootObjectFunction RootObject::_createRootObject = 0;
+CFRunLoopRef RootObject::_runLoop = 0;
+CFRunLoopSourceRef RootObject::_performJavaScriptSource = 0;
+
+// Must be called from the thread that will be used to access JavaScript.
+void RootObject::setCreateRootObject(CreateRootObjectFunction createRootObject) {
+ // Should only be called once.
+ ASSERT(!_createRootObject);
+
+ _createRootObject = createRootObject;
+
+ // Assume that we can retain this run loop forever. It'll most
+ // likely (always?) be the main loop.
+ _runLoop = (CFRunLoopRef)CFRetain (CFRunLoopGetCurrent ());
+
+ // Setup a source the other threads can use to signal the _runLoop
+ // thread that a JavaScript call needs to be invoked.
+ CFRunLoopSourceContext sourceContext = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, performJavaScriptAccess};
+ RootObject::_performJavaScriptSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
+ CFRunLoopAddSource(RootObject::_runLoop, RootObject::_performJavaScriptSource, kCFRunLoopDefaultMode);
+}
+
+#endif
+
+PassRefPtr<RootObject> RootObject::create(const void* nativeHandle, JSGlobalObject* globalObject)
+{
+ return adoptRef(new RootObject(nativeHandle, globalObject));
+}
+
+RootObject::RootObject(const void* nativeHandle, JSGlobalObject* globalObject)
+ : m_isValid(true)
+ , m_nativeHandle(nativeHandle)
+ , m_globalObject(globalObject)
+{
+ ASSERT(globalObject);
+ rootObjectSet()->add(this);
+}
+
+RootObject::~RootObject()
+{
+ if (m_isValid)
+ invalidate();
+}
+
+void RootObject::invalidate()
+{
+ if (!m_isValid)
+ return;
+
+ {
+ HashSet<RuntimeObjectImp*>::iterator end = m_runtimeObjects.end();
+ for (HashSet<RuntimeObjectImp*>::iterator it = m_runtimeObjects.begin(); it != end; ++it)
+ (*it)->invalidate();
+
+ m_runtimeObjects.clear();
+ }
+
+ m_isValid = false;
+
+ m_nativeHandle = 0;
+ m_globalObject = 0;
+
+ ProtectCountSet::iterator end = m_protectCountSet.end();
+ for (ProtectCountSet::iterator it = m_protectCountSet.begin(); it != end; ++it) {
+ JSLock lock;
+ KJS::gcUnprotect(it->first);
+ }
+ m_protectCountSet.clear();
+
+ rootObjectSet()->remove(this);
+}
+
+void RootObject::gcProtect(JSObject* jsObject)
+{
+ ASSERT(m_isValid);
+
+ if (!m_protectCountSet.contains(jsObject)) {
+ JSLock lock;
+ KJS::gcProtect(jsObject);
+ }
+ m_protectCountSet.add(jsObject);
+}
+
+void RootObject::gcUnprotect(JSObject* jsObject)
+{
+ ASSERT(m_isValid);
+
+ if (!jsObject)
+ return;
+
+ if (m_protectCountSet.count(jsObject) == 1) {
+ JSLock lock;
+ KJS::gcUnprotect(jsObject);
+ }
+ m_protectCountSet.remove(jsObject);
+}
+
+bool RootObject::gcIsProtected(JSObject* jsObject)
+{
+ ASSERT(m_isValid);
+ return m_protectCountSet.contains(jsObject);
+}
+
+const void* RootObject::nativeHandle() const
+{
+ ASSERT(m_isValid);
+ return m_nativeHandle;
+}
+
+JSGlobalObject* RootObject::globalObject() const
+{
+ ASSERT(m_isValid);
+ return m_globalObject;
+}
+
+void RootObject::addRuntimeObject(RuntimeObjectImp* object)
+{
+ ASSERT(m_isValid);
+ ASSERT(!m_runtimeObjects.contains(object));
+
+ m_runtimeObjects.add(object);
+}
+
+void RootObject::removeRuntimeObject(RuntimeObjectImp* object)
+{
+ ASSERT(m_isValid);
+ ASSERT(m_runtimeObjects.contains(object));
+
+ m_runtimeObjects.remove(object);
+}
+
+} } // namespace KJS::Bindings
diff --git a/JavaScriptCore/bindings/runtime_root.h b/JavaScriptCore/bindings/runtime_root.h
new file mode 100644
index 0000000..4db02d4
--- /dev/null
+++ b/JavaScriptCore/bindings/runtime_root.h
@@ -0,0 +1,109 @@
+/*
+ * 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 RUNTIME_ROOT_H_
+#define RUNTIME_ROOT_H_
+
+#if PLATFORM(MAC)
+#include "jni_jsobject.h"
+#endif
+#include "protect.h"
+
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RefCounted.h>
+
+namespace KJS {
+
+class Interpreter;
+class JSGlobalObject;
+class RuntimeObjectImp;
+
+namespace Bindings {
+
+class RootObject;
+
+typedef PassRefPtr<RootObject> (*CreateRootObjectFunction)(void* nativeHandle);
+typedef HashCountedSet<JSObject*> ProtectCountSet;
+
+extern RootObject* findProtectingRootObject(JSObject*);
+extern RootObject* findRootObject(JSGlobalObject*);
+
+class RootObject : public RefCounted<RootObject> {
+ friend class JavaJSObject;
+
+public:
+ ~RootObject();
+
+ static PassRefPtr<RootObject> create(const void* nativeHandle, JSGlobalObject*);
+
+ bool isValid() { return m_isValid; }
+ void invalidate();
+
+ void gcProtect(JSObject*);
+ void gcUnprotect(JSObject*);
+ bool gcIsProtected(JSObject*);
+
+ const void* nativeHandle() const;
+ JSGlobalObject* globalObject() const;
+
+#if PLATFORM(MAC)
+ // Must be called from the thread that will be used to access JavaScript.
+ static void setCreateRootObject(CreateRootObjectFunction);
+ static CreateRootObjectFunction createRootObject() {
+ return _createRootObject;
+ }
+
+ static CFRunLoopRef runLoop() { return _runLoop; }
+ static CFRunLoopSourceRef performJavaScriptSource() { return _performJavaScriptSource; }
+
+ static void dispatchToJavaScriptThread(JSObjectCallContext *context);
+#endif
+
+ void addRuntimeObject(RuntimeObjectImp*);
+ void removeRuntimeObject(RuntimeObjectImp*);
+private:
+ RootObject(const void* nativeHandle, JSGlobalObject*);
+
+ bool m_isValid;
+
+ const void* m_nativeHandle;
+ ProtectedPtr<JSGlobalObject> m_globalObject;
+ ProtectCountSet m_protectCountSet;
+
+ HashSet<RuntimeObjectImp*> m_runtimeObjects;
+
+#if PLATFORM(MAC)
+ static CreateRootObjectFunction _createRootObject;
+ static CFRunLoopRef _runLoop;
+ static CFRunLoopSourceRef _performJavaScriptSource;
+#endif
+};
+
+} // namespace Bindings
+
+} // namespace KJS
+
+#endif
diff --git a/JavaScriptCore/bindings/test.js b/JavaScriptCore/bindings/test.js
new file mode 100644
index 0000000..5d4f79f
--- /dev/null
+++ b/JavaScriptCore/bindings/test.js
@@ -0,0 +1,19 @@
+myInterface.logMessage ("Starting test");
+
+myInterface.logMessage ("Testing properties:");
+myInterface.logMessage ("myInterface.doubleValue = " + myInterface.doubleValue);
+myInterface.logMessage ("myInterface.intValue = " + myInterface.intValue);
+myInterface.logMessage ("myInterface.stringValue = " + myInterface.stringValue);
+myInterface.logMessage ("myInterface.booleanValue = " + myInterface.booleanValue);
+myInterface.logMessage ("myInterface.nullValue = " + myInterface.nullValue);
+myInterface.logMessage ("myInterface.undefinedValue = " + myInterface.undefinedValue);
+
+myInterface.logMessage ("myInterface.setInt_(666) = " + myInterface.setInt_(666));
+myInterface.logMessage ("myInterface.getInt() = " + myInterface.getInt());
+myInterface.logMessage ("myInterface.getString() = " + myInterface.getString());
+myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
+myInterface.logMessage ("setting myInterface.myInt = 777");
+myInterface.myInt = 777;
+myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
+myInterface.logMessage ("myInterface.getMySecondInterface().doubleValue = " + myInterface.getMySecondInterface().doubleValue);
+myInterface.logMessage ("myInterface.getMySecondInterface() = " + myInterface.getMySecondInterface());
diff --git a/JavaScriptCore/bindings/testC.js b/JavaScriptCore/bindings/testC.js
new file mode 100644
index 0000000..44677c7
--- /dev/null
+++ b/JavaScriptCore/bindings/testC.js
@@ -0,0 +1,21 @@
+myInterface.logMessage ("Starting test");
+
+myInterface.logMessage ("Testing properties:");
+myInterface.logMessage (" myInterface.doubleValue = " + myInterface.doubleValue);
+myInterface.logMessage (" myInterface.intValue = " + myInterface.intValue);
+myInterface.logMessage (" myInterface.stringValue = " + myInterface.stringValue);
+myInterface.logMessage (" myInterface.booleanValue = " + myInterface.booleanValue);
+myInterface.logMessage (" myInterface.nullValue = " + myInterface.nullValue);
+myInterface.logMessage (" myInterface.undefinedValue = " + myInterface.undefinedValue);
+
+myInterface.logMessage ("Testing methods:");
+myInterface.logMessage (" myInterface.setDoubleValue(1234.1234) = " + myInterface.setDoubleValue(1234.1234));
+myInterface.logMessage (" myInterface.setIntValue(5678) = " + myInterface.setIntValue(5678));
+myInterface.logMessage (" myInterface.setStringValue(Goodbye) = " + myInterface.setStringValue('Goodbye'));
+myInterface.logMessage (" myInterface.setBooleanValue(false) = " + myInterface.setBooleanValue(false));
+
+myInterface.logMessage ("Value of properties after calling setters:");
+myInterface.logMessage (" myInterface.getDoubleValue() = " + myInterface.getDoubleValue());
+myInterface.logMessage (" myInterface.getIntValue() = " + myInterface.getIntValue());
+myInterface.logMessage (" myInterface.getStringValue() = " + myInterface.getStringValue());
+myInterface.logMessage (" myInterface.getBooleanValue() = " + myInterface.getBooleanValue());
diff --git a/JavaScriptCore/bindings/testM.js b/JavaScriptCore/bindings/testM.js
new file mode 100644
index 0000000..7985d21
--- /dev/null
+++ b/JavaScriptCore/bindings/testM.js
@@ -0,0 +1,29 @@
+myInterface.logMessage ("Starting test");
+
+myInterface.logMessage ("Testing properties:");
+
+myInterface.jsobject = new Function ("arg1","arg2","return arg1 + arg2;");
+myInterface.logMessage ("myInterface.jsobject =" + myInterface.jsobject);
+
+var functionBody = 'return arg1*arg2;'
+
+myInterface.setJSObject_(new Function ("arg1","arg2",functionBody));
+myInterface.logMessage ("myInterface.jsobject =" + myInterface.jsobject);
+myInterface.callJSObject__(5,6);
+myInterface.callJSObject__(8,9);
+
+myInterface.logMessage ("myInterface.setInt_(666) = " + myInterface.setInt_(666));
+myInterface.logMessage ("myInterface.getInt() = " + myInterface.getInt());
+myInterface.logMessage ("myInterface.getString().foo() = " + myInterface.getString().foo());
+myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
+myInterface.logMessage ("setting myInterface.myInt = 777");
+myInterface.myInt = 777;
+myInterface.logMessage ("myInterface.myInt = " + myInterface.myInt);
+myInterface.logMessage ("myInterface.getMySecondInterface().doubleValue = " + myInterface.getMySecondInterface().doubleValue);
+myInterface.logMessage ("myInterface.getMySecondInterface() = " + myInterface.getMySecondInterface());
+
+myInterface.logMessageWithPrefix ("msg", "prefix");
+
+var strings = [ "one", "two", "three" ];
+
+myInterface.logMessages (strings); \ No newline at end of file
diff --git a/JavaScriptCore/bindings/testbindings.cpp b/JavaScriptCore/bindings/testbindings.cpp
new file mode 100644
index 0000000..25f1f99
--- /dev/null
+++ b/JavaScriptCore/bindings/testbindings.cpp
@@ -0,0 +1,422 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include "config.h"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "value.h"
+#include "object.h"
+#include "types.h"
+#include "interpreter.h"
+
+#include "npruntime_internal.h"
+
+#include "runtime.h"
+#include "runtime_object.h"
+
+
+#define LOG(formatAndArgs...) { \
+ fprintf (stderr, "%s: ", __PRETTY_FUNCTION__); \
+ fprintf(stderr, formatAndArgs); \
+}
+
+
+// ------------------ NP Interface definition --------------------
+typedef struct
+{
+ NPObject object;
+ double doubleValue;
+ int intValue;
+ NPVariant stringValue;
+ bool boolValue;
+} MyObject;
+
+
+static bool identifiersInitialized = false;
+
+#define ID_DOUBLE_VALUE 0
+#define ID_INT_VALUE 1
+#define ID_STRING_VALUE 2
+#define ID_BOOLEAN_VALUE 3
+#define ID_NULL_VALUE 4
+#define ID_UNDEFINED_VALUE 5
+#define NUM_PROPERTY_IDENTIFIERS 6
+
+static NPIdentifier myPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
+static const NPUTF8 *myPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
+ "doubleValue",
+ "intValue",
+ "stringValue",
+ "booleanValue",
+ "nullValue",
+ "undefinedValue"
+};
+
+#define ID_LOG_MESSAGE 0
+#define ID_SET_DOUBLE_VALUE 1
+#define ID_SET_INT_VALUE 2
+#define ID_SET_STRING_VALUE 3
+#define ID_SET_BOOLEAN_VALUE 4
+#define ID_GET_DOUBLE_VALUE 5
+#define ID_GET_INT_VALUE 6
+#define ID_GET_STRING_VALUE 7
+#define ID_GET_BOOLEAN_VALUE 8
+#define NUM_METHOD_IDENTIFIERS 9
+
+static NPIdentifier myMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
+static const NPUTF8 *myMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
+ "logMessage",
+ "setDoubleValue",
+ "setIntValue",
+ "setStringValue",
+ "setBooleanValue",
+ "getDoubleValue",
+ "getIntValue",
+ "getStringValue",
+ "getBooleanValue"
+};
+
+static void initializeIdentifiers()
+{
+ NPN_GetStringIdentifiers (myPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, myPropertyIdentifiers);
+ NPN_GetStringIdentifiers (myMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, myMethodIdentifiers);
+};
+
+bool myHasProperty (NPClass *theClass, NPIdentifier name)
+{
+ int i;
+ for (i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++) {
+ if (name == myPropertyIdentifiers[i]){
+ return true;
+ }
+ }
+ return false;
+}
+
+bool myHasMethod (NPClass *theClass, NPIdentifier name)
+{
+ int i;
+ for (i = 0; i < NUM_METHOD_IDENTIFIERS; i++) {
+ if (name == myMethodIdentifiers[i]){
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void logMessage (const NPVariant *message)
+{
+ if (message->type == NPVariantStringType) {
+ char msgBuf[1024];
+ strncpy (msgBuf, message->value.stringValue.UTF8Characters, message->value.stringValue.UTF8Length);
+ msgBuf[message->value.stringValue.UTF8Length] = 0;
+ printf ("%s\n", msgBuf);
+ }
+ else if (message->type == NPVariantDoubleType)
+ printf ("%f\n", (float)message->value.doubleValue);
+ else if (message->type == NPVariantInt32Type)
+ printf ("%d\n", message->value.intValue);
+ else if (message->type == NPVariantObjectType)
+ printf ("%p\n", message->value.objectValue);
+}
+
+void setDoubleValue (MyObject *obj, const NPVariant *variant)
+{
+ if (!NPN_VariantToDouble (variant, &obj->doubleValue)) {
+ NPUTF8 *msg = "Attempt to set double value with invalid type.";
+ NPString aString;
+ aString.UTF8Characters = msg;
+ aString.UTF8Length = strlen (msg);
+ NPN_SetException ((NPObject *)obj, &aString);
+ }
+}
+
+void setIntValue (MyObject *obj, const NPVariant *variant)
+{
+ if (!NPN_VariantToInt32 (variant, &obj->intValue)) {
+ NPUTF8 *msg = "Attempt to set int value with invalid type.";
+ NPString aString;
+ aString.UTF8Characters = msg;
+ aString.UTF8Length = strlen (msg);
+ NPN_SetException ((NPObject *)obj, &aString);
+ }
+}
+
+void setStringValue (MyObject *obj, const NPVariant *variant)
+{
+ NPN_ReleaseVariantValue (&obj->stringValue);
+ NPN_InitializeVariantWithVariant (&obj->stringValue, variant);
+}
+
+void setBooleanValue (MyObject *obj, const NPVariant *variant)
+{
+ if (!NPN_VariantToBool (variant, (NPBool *)&obj->boolValue)) {
+ NPUTF8 *msg = "Attempt to set bool value with invalid type.";
+ NPString aString;
+ aString.UTF8Characters = msg;
+ aString.UTF8Length = strlen (msg);
+ NPN_SetException ((NPObject *)obj, &aString);
+ }
+}
+
+void getDoubleValue (MyObject *obj, NPVariant *variant)
+{
+ NPN_InitializeVariantWithDouble (variant, obj->doubleValue);
+}
+
+void getIntValue (MyObject *obj, NPVariant *variant)
+{
+ NPN_InitializeVariantWithInt32 (variant, obj->intValue);
+}
+
+void getStringValue (MyObject *obj, NPVariant *variant)
+{
+ NPN_InitializeVariantWithVariant (variant, &obj->stringValue);
+}
+
+void getBooleanValue (MyObject *obj, NPVariant *variant)
+{
+ NPN_InitializeVariantWithBool (variant, obj->boolValue);
+}
+
+void myGetProperty (MyObject *obj, NPIdentifier name, NPVariant *variant)
+{
+ if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]){
+ getDoubleValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_INT_VALUE]){
+ getIntValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_STRING_VALUE]){
+ getStringValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]){
+ getBooleanValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_NULL_VALUE]){
+ return NPN_InitializeVariantAsNull (variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]){
+ return NPN_InitializeVariantAsUndefined (variant);
+ }
+ else
+ NPN_InitializeVariantAsUndefined(variant);
+}
+
+void mySetProperty (MyObject *obj, NPIdentifier name, const NPVariant *variant)
+{
+ if (name == myPropertyIdentifiers[ID_DOUBLE_VALUE]) {
+ setDoubleValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_INT_VALUE]) {
+ setIntValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_STRING_VALUE]) {
+ setStringValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_BOOLEAN_VALUE]) {
+ setBooleanValue (obj, variant);
+ }
+ else if (name == myPropertyIdentifiers[ID_NULL_VALUE]) {
+ // Do nothing!
+ }
+ else if (name == myPropertyIdentifiers[ID_UNDEFINED_VALUE]) {
+ // Do nothing!
+ }
+}
+
+void myInvoke (MyObject *obj, NPIdentifier name, NPVariant *args, unsigned argCount, NPVariant *result)
+{
+ if (name == myMethodIdentifiers[ID_LOG_MESSAGE]) {
+ if (argCount == 1 && NPN_VariantIsString(&args[0]))
+ logMessage (&args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_SET_DOUBLE_VALUE]) {
+ if (argCount == 1 && NPN_VariantIsDouble (&args[0]))
+ setDoubleValue (obj, &args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_SET_INT_VALUE]) {
+ if (argCount == 1 && (NPN_VariantIsDouble (&args[0]) || NPN_VariantIsInt32 (&args[0])))
+ setIntValue (obj, &args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_SET_STRING_VALUE]) {
+ if (argCount == 1 && NPN_VariantIsString (&args[0]))
+ setStringValue (obj, &args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_SET_BOOLEAN_VALUE]) {
+ if (argCount == 1 && NPN_VariantIsBool (&args[0]))
+ setBooleanValue (obj, &args[0]);
+ NPN_InitializeVariantAsVoid (result);
+ }
+ else if (name == myMethodIdentifiers[ID_GET_DOUBLE_VALUE]) {
+ getDoubleValue (obj, result);
+ }
+ else if (name == myMethodIdentifiers[ID_GET_INT_VALUE]) {
+ getIntValue (obj, result);
+ }
+ else if (name == myMethodIdentifiers[ID_GET_STRING_VALUE]) {
+ getStringValue (obj, result);
+ }
+ else if (name == myMethodIdentifiers[ID_GET_BOOLEAN_VALUE]) {
+ getBooleanValue (obj, result);
+ }
+ else
+ NPN_InitializeVariantAsUndefined (result);
+}
+
+NPObject *myAllocate ()
+{
+ MyObject *newInstance = (MyObject *)malloc (sizeof(MyObject));
+
+ if (!identifiersInitialized) {
+ identifiersInitialized = true;
+ initializeIdentifiers();
+ }
+
+
+ newInstance->doubleValue = 666.666;
+ newInstance->intValue = 1234;
+ newInstance->boolValue = true;
+ newInstance->stringValue.type = NPVariantType_String;
+ newInstance->stringValue.value.stringValue.UTF8Length = strlen ("Hello world");
+ newInstance->stringValue.value.stringValue.UTF8Characters = strdup ("Hello world");
+
+ return (NPObject *)newInstance;
+}
+
+void myInvalidate ()
+{
+ // Make sure we've released any remaining references to JavaScript objects.
+}
+
+void myDeallocate (MyObject *obj)
+{
+ free ((void *)obj);
+}
+
+static NPClass _myFunctionPtrs = {
+ kNPClassStructVersionCurrent,
+ (NPAllocateFunctionPtr) myAllocate,
+ (NPDeallocateFunctionPtr) myDeallocate,
+ (NPInvalidateFunctionPtr) myInvalidate,
+ (NPHasMethodFunctionPtr) myHasMethod,
+ (NPInvokeFunctionPtr) myInvoke,
+ (NPHasPropertyFunctionPtr) myHasProperty,
+ (NPGetPropertyFunctionPtr) myGetProperty,
+ (NPSetPropertyFunctionPtr) mySetProperty,
+};
+static NPClass *myFunctionPtrs = &_myFunctionPtrs;
+
+// --------------------------------------------------------
+
+using namespace KJS;
+using namespace KJS::Bindings;
+
+class GlobalImp : public ObjectImp {
+public:
+ virtual UString className() const { return "global"; }
+};
+
+#define BufferSize 200000
+static char code[BufferSize];
+
+const char *readJavaScriptFromFile (const char *file)
+{
+ FILE *f = fopen(file, "r");
+ if (!f) {
+ fprintf(stderr, "Error opening %s.\n", file);
+ return 0;
+ }
+
+ int num = fread(code, 1, BufferSize, f);
+ code[num] = '\0';
+ if(num >= BufferSize)
+ fprintf(stderr, "Warning: File may have been too long.\n");
+
+ fclose(f);
+
+ return code;
+}
+
+int main(int argc, char **argv)
+{
+ // expecting a filename
+ if (argc < 2) {
+ fprintf(stderr, "You have to specify at least one filename\n");
+ return -1;
+ }
+
+ bool ret = true;
+ {
+ JSLock lock;
+
+ // create interpreter w/ global object
+ Object global(new GlobalImp());
+ Interpreter interp;
+ interp.setGlobalObject(global);
+ ExecState *exec = interp.globalExec();
+
+ MyObject *myObject = (MyObject *)NPN_CreateObject (myFunctionPtrs);
+
+ global.put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::CLanguage, (void *)myObject));
+
+ for (int i = 1; i < argc; i++) {
+ const char *code = readJavaScriptFromFile(argv[i]);
+
+ if (code) {
+ // run
+ Completion comp(interp.evaluate(code));
+
+ if (comp.complType() == Throw) {
+ Value exVal = comp.value();
+ char *msg = exVal.toString(exec).ascii();
+ int lineno = -1;
+ if (exVal.type() == ObjectType) {
+ Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
+ if (lineVal.type() == NumberType)
+ lineno = int(lineVal.toNumber(exec));
+ }
+ if (lineno != -1)
+ fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
+ else
+ fprintf(stderr,"Exception: %s\n",msg);
+ ret = false;
+ }
+ else if (comp.complType() == ReturnValue) {
+ char *msg = comp.value().toString(interp.globalExec()).ascii();
+ fprintf(stderr,"Return value: %s\n",msg);
+ }
+ }
+ }
+
+ NPN_ReleaseObject ((NPObject *)myObject);
+
+ } // end block, so that Interpreter and global get deleted
+
+ return ret ? 0 : 3;
+}
diff --git a/JavaScriptCore/bindings/testbindings.mm b/JavaScriptCore/bindings/testbindings.mm
new file mode 100644
index 0000000..7061503
--- /dev/null
+++ b/JavaScriptCore/bindings/testbindings.mm
@@ -0,0 +1,289 @@
+/*
+ * 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 <Foundation/Foundation.h>
+
+#import <WebKit/WebScriptObject.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "value.h"
+#include "object.h"
+#include "types.h"
+#include "interpreter.h"
+
+#include "runtime.h"
+#include "runtime_object.h"
+
+#define LOG(formatAndArgs...) { \
+ fprintf (stderr, "%s: ", __PRETTY_FUNCTION__); \
+ fprintf(stderr, formatAndArgs); \
+}
+
+@interface MySecondInterface : NSObject
+{
+ double doubleValue;
+}
+
+- init;
+
+@end
+
+@implementation MySecondInterface
+
+- init
+{
+ LOG ("\n");
+ doubleValue = 666.666;
+ return self;
+}
+
+@end
+
+@interface MyFirstInterface : NSObject
+{
+ int myInt;
+ MySecondInterface *mySecondInterface;
+ id jsobject;
+ NSString *string;
+}
+
+- (int)getInt;
+- (void)setInt: (int)anInt;
+- (MySecondInterface *)getMySecondInterface;
+- (void)logMessage:(NSString *)message;
+- (void)setJSObject:(id)jsobject;
+@end
+
+@implementation MyFirstInterface
+
++ (NSString *)webScriptNameForSelector:(SEL)aSelector
+{
+ if (aSelector == @selector(logMessage:))
+ return @"logMessage";
+ if (aSelector == @selector(logMessages:))
+ return @"logMessages";
+ if (aSelector == @selector(logMessage:prefix:))
+ return @"logMessageWithPrefix";
+ return nil;
+}
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
+{
+ return NO;
+}
+
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name
+{
+ return NO;
+}
+
+/*
+- (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args;
+{
+ NSLog (@"Call to undefined method %@", name);
+ NSLog (@"%d args\n", [args count]);
+ int i;
+ for (i = 0; i < [args count]; i++) {
+ NSLog (@"%d: %@\n", i, [args objectAtIndex:i]);
+ }
+ return @"success";
+}
+*/
+
+/*
+- (id)valueForUndefinedKey:(NSString *)key
+{
+ NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key);
+ return @"aValue";
+}
+*/
+
+- (void)setValue:(id)value forUndefinedKey:(NSString *)key
+{
+ NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key);
+}
+
+- init
+{
+ LOG ("\n");
+ mySecondInterface = [[MySecondInterface alloc] init];
+ return self;
+}
+
+- (void)dealloc
+{
+ LOG ("\n");
+ [mySecondInterface release];
+ [super dealloc];
+}
+
+- (int)getInt
+{
+ LOG ("myInt = %d\n", myInt);
+ return myInt;
+}
+
+- (void)setInt: (int)anInt
+{
+ LOG ("anInt = %d\n", anInt);
+ myInt = anInt;
+}
+
+- (NSString *)getString
+{
+ return string;
+}
+
+- (MySecondInterface *)getMySecondInterface
+{
+ LOG ("\n");
+ return mySecondInterface;
+}
+
+- (void)logMessage:(NSString *)message
+{
+ printf ("%s\n", [message lossyCString]);
+}
+
+- (void)logMessages:(id)messages
+{
+ int i, count = [[messages valueForKey:@"length"] intValue];
+ for (i = 0; i < count; i++)
+ printf ("%s\n", [[messages webScriptValueAtIndex:i] lossyCString]);
+}
+
+- (void)logMessage:(NSString *)message prefix:(NSString *)prefix
+{
+ printf ("%s:%s\n", [prefix lossyCString], [message lossyCString]);
+}
+
+- (void)setJSObject:(id)jso
+{
+ [jsobject autorelease];
+ jsobject = [jso retain];
+}
+
+- (void)callJSObject:(int)arg1 :(int)arg2
+{
+ id foo1 = [jsobject callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObjects:jsobject, [NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil]];
+ printf ("foo (via call) = %s\n", [[foo1 description] lossyCString] );
+ id foo2 = [jsobject callWebScriptMethod:@"apply" withArguments:[NSArray arrayWithObjects:jsobject, [NSArray arrayWithObjects:[NSNumber numberWithInt:arg1], [NSNumber numberWithInt:arg2], nil], nil]];
+ printf ("foo (via apply) = %s\n", [[foo2 description] lossyCString] );
+}
+
+@end
+
+
+using namespace KJS;
+using namespace KJS::Bindings;
+
+class GlobalImp : public ObjectImp {
+public:
+ virtual UString className() const { return "global"; }
+};
+
+#define BufferSize 200000
+static char code[BufferSize];
+
+const char *readJavaScriptFromFile (const char *file)
+{
+ FILE *f = fopen(file, "r");
+ if (!f) {
+ fprintf(stderr, "Error opening %s.\n", file);
+ return 0;
+ }
+
+ int num = fread(code, 1, BufferSize, f);
+ code[num] = '\0';
+ if(num >= BufferSize)
+ fprintf(stderr, "Warning: File may have been too long.\n");
+
+ fclose(f);
+
+ return code;
+}
+
+int main(int argc, char **argv)
+{
+ // expecting a filename
+ if (argc < 2) {
+ fprintf(stderr, "You have to specify at least one filename\n");
+ return -1;
+ }
+
+ bool ret = true;
+ {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ JSLock lock;
+
+ // create interpreter w/ global object
+ Object global(new GlobalImp());
+ Interpreter interp;
+ interp.setGlobalObject(global);
+ ExecState *exec = interp.globalExec();
+
+ MyFirstInterface *myInterface = [[MyFirstInterface alloc] init];
+
+ global.put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::ObjectiveCLanguage, (void *)myInterface));
+
+ for (int i = 1; i < argc; i++) {
+ const char *code = readJavaScriptFromFile(argv[i]);
+
+ if (code) {
+ // run
+ Completion comp(interp.evaluate(code));
+
+ if (comp.complType() == Throw) {
+ Value exVal = comp.value();
+ char *msg = exVal.toString(exec).ascii();
+ int lineno = -1;
+ if (exVal.type() == ObjectType) {
+ Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
+ if (lineVal.type() == NumberType)
+ lineno = int(lineVal.toNumber(exec));
+ }
+ if (lineno != -1)
+ fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
+ else
+ fprintf(stderr,"Exception: %s\n",msg);
+ ret = false;
+ }
+ else if (comp.complType() == ReturnValue) {
+ char *msg = comp.value().toString(interp.globalExec()).ascii();
+ fprintf(stderr,"Return value: %s\n",msg);
+ }
+ }
+ }
+
+ [myInterface release];
+ [pool drain];
+ } // end block, so that Interpreter and global get deleted
+
+ return ret ? 0 : 3;
+}
diff --git a/JavaScriptCore/bindings/testbindings.pro b/JavaScriptCore/bindings/testbindings.pro
new file mode 100644
index 0000000..e6e0b9d
--- /dev/null
+++ b/JavaScriptCore/bindings/testbindings.pro
@@ -0,0 +1,8 @@
+QT -= gui
+
+include(../../WebKit.pri)
+INCLUDEPATH += .. ../kjs .
+qt-port:INCLUDEPATH += bindings/qt
+
+SOURCES += testqtbindings.cpp
+
diff --git a/JavaScriptCore/bindings/testqtbindings.cpp b/JavaScriptCore/bindings/testqtbindings.cpp
new file mode 100644
index 0000000..490b3ff
--- /dev/null
+++ b/JavaScriptCore/bindings/testqtbindings.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * 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 <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "value.h"
+#include "object.h"
+#include "types.h"
+#include "interpreter.h"
+
+#include "qobject.h"
+#include "qdebug.h"
+
+#include "runtime.h"
+#include "runtime_object.h"
+
+
+
+class MyObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString testString READ testString WRITE setTestString)
+ Q_PROPERTY(int testInt READ testInt WRITE setTestInt)
+
+public:
+ MyObject() : QObject(0), integer(0){}
+
+ void setTestString(const QString &str) {
+ qDebug() << "called setTestString" << str;
+ string = str;
+ }
+ void setTestInt(int i) {
+ qDebug() << "called setTestInt" << i;
+ integer = i;
+ }
+ QString testString() const {
+ qDebug() << "called testString" << string;
+ return string;
+ }
+ int testInt() const {
+ qDebug() << "called testInt" << integer;
+ return integer;
+ }
+ QString string;
+ int integer;
+
+public slots:
+ void foo() { qDebug() << "foo invoked"; }
+};
+
+// --------------------------------------------------------
+
+using namespace KJS;
+using namespace KJS::Bindings;
+
+class Global : public JSObject {
+public:
+ virtual UString className() const { return "global"; }
+};
+
+static char code[] =
+ "myInterface.foo();\n"
+ "myInterface.testString = \"Hello\";\n"
+ "str = myInterface.testString;\n"
+ "myInterface.testInt = 10;\n"
+ "i = myInterface.testInt;\n";
+
+int main(int argc, char** argv)
+{
+ // expecting a filename
+ bool ret = true;
+ {
+ JSLock lock;
+
+ // create interpreter w/ global object
+ Global* global = new Global();
+
+ // create interpreter
+ RefPtr<Interpreter> interp = new Interpreter(global);
+ ExecState* exec = interp->globalExec();
+
+ MyObject* myObject = new MyObject;
+
+ global->put(exec, Identifier("myInterface"), Instance::createRuntimeObject(Instance::QtLanguage, (void*)myObject));
+
+
+ if (code) {
+ // run
+ Completion comp(interp->evaluate("", 0, code));
+
+ if (comp.complType() == Throw) {
+ qDebug() << "exception thrown";
+ JSValue* exVal = comp.value();
+ char* msg = exVal->toString(exec).ascii();
+ int lineno = -1;
+ if (exVal->type() == ObjectType) {
+ JSValue* lineVal = exVal->getObject()->get(exec, Identifier("line"));
+ if (lineVal->type() == NumberType)
+ lineno = int(lineVal->toNumber(exec));
+ }
+ if (lineno != -1)
+ fprintf(stderr,"Exception, line %d: %s\n",lineno,msg);
+ else
+ fprintf(stderr,"Exception: %s\n",msg);
+ ret = false;
+ }
+ else if (comp.complType() == ReturnValue) {
+ char* msg = comp.value()->toString(interp->globalExec()).ascii();
+ fprintf(stderr,"Return value: %s\n",msg);
+ }
+ }
+
+ } // end block, so that Interpreter and global get deleted
+
+ return ret ? 0 : 1;
+}
+
+#include "testqtbindings.moc"