diff options
Diffstat (limited to 'WebCore/bridge')
36 files changed, 1030 insertions, 513 deletions
diff --git a/WebCore/bridge/IdentifierRep.h b/WebCore/bridge/IdentifierRep.h index 8e0e0d9..8128bf8 100644 --- a/WebCore/bridge/IdentifierRep.h +++ b/WebCore/bridge/IdentifierRep.h @@ -27,11 +27,12 @@ #define IdentifierRep_h #include <wtf/Assertions.h> +#include <wtf/FastAllocBase.h> #include <string.h> namespace WebCore { -class IdentifierRep { +class IdentifierRep : public FastAllocBase { public: static IdentifierRep* get(int); static IdentifierRep* get(const char*); diff --git a/WebCore/bridge/NP_jsobject.cpp b/WebCore/bridge/NP_jsobject.cpp index 4a6a2b1..59900c5 100644 --- a/WebCore/bridge/NP_jsobject.cpp +++ b/WebCore/bridge/NP_jsobject.cpp @@ -31,12 +31,10 @@ #include "PlatformString.h" #include "StringSourceProvider.h" -#ifdef ANDROID_NPN_SETEXCEPTION -#include "c_runtime.h" -#endif // ANDROID_NPN_SETEXCEPTION #include "c_utility.h" #include "c_instance.h" #include "IdentifierRep.h" +#include "JSDOMBinding.h" #include "npruntime_impl.h" #include "npruntime_priv.h" #include "runtime_root.h" @@ -126,7 +124,7 @@ bool _NPN_InvokeDefault(NPP, NPObject* o, const NPVariant* args, uint32_t argCou getListFromVariantArgs(exec, args, argCount, rootObject, argList); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); globalObject->globalData()->timeoutChecker.start(); - JSValue resultV = call(exec, function, callType, callData, function, argList); + JSValue resultV = JSC::call(exec, function, callType, callData, function, argList); globalObject->globalData()->timeoutChecker.stop(); // Convert and return the result of the function call. @@ -176,7 +174,7 @@ bool _NPN_Invoke(NPP npp, NPObject* o, NPIdentifier methodName, const NPVariant* getListFromVariantArgs(exec, args, argCount, rootObject, argList); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); globalObject->globalData()->timeoutChecker.start(); - JSValue resultV = call(exec, function, callType, callData, obj->imp, argList); + JSValue resultV = JSC::call(exec, function, callType, callData, obj->imp, argList); globalObject->globalData()->timeoutChecker.stop(); // Convert and return the result of the function call. @@ -206,7 +204,7 @@ bool _NPN_Evaluate(NPP, NPObject* o, NPString* s, NPVariant* variant) String scriptString = convertNPStringToUTF16(s); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); globalObject->globalData()->timeoutChecker.start(); - Completion completion = JSC::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(scriptString)); + Completion completion = JSC::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(scriptString), JSC::JSValue()); globalObject->globalData()->timeoutChecker.stop(); ComplType type = completion.complType(); @@ -379,21 +377,11 @@ bool _NPN_HasMethod(NPP, NPObject* o, NPIdentifier methodName) return false; } -#ifdef ANDROID_NPN_SETEXCEPTION -void _NPN_SetException(NPObject* o, const NPUTF8* message) -#else void _NPN_SetException(NPObject*, const NPUTF8* message) -#endif { -#ifdef ANDROID_NPN_SETEXCEPTION - if (o->_class == NPScriptObjectClass) { - JSC::Bindings::SetGlobalException(message); - } -#else // Ignorning the NPObject param is consistent with the Mozilla implementation. UString exception(message); CInstance::setGlobalException(exception); -#endif // ANDROID_NPN_SETEXCEPTION } bool _NPN_Enumerate(NPP, NPObject* o, NPIdentifier** identifier, uint32_t* count) @@ -456,7 +444,7 @@ bool _NPN_Construct(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, getListFromVariantArgs(exec, args, argCount, rootObject, argList); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); globalObject->globalData()->timeoutChecker.start(); - JSValue resultV = construct(exec, constructor, constructType, constructData, argList); + JSValue resultV = JSC::construct(exec, constructor, constructType, constructData, argList); globalObject->globalData()->timeoutChecker.stop(); // Convert and return the result. diff --git a/WebCore/bridge/c/c_instance.cpp b/WebCore/bridge/c/c_instance.cpp index 6ce6572..77b5966 100644 --- a/WebCore/bridge/c/c_instance.cpp +++ b/WebCore/bridge/c/c_instance.cpp @@ -121,27 +121,25 @@ JSValue CInstance::invokeMethod(ExecState* exec, const MethodList& methodList, c convertValueToNPVariant(exec, args.at(i), &cArgs[i]); // Invoke the 'C' method. -#ifdef ANDROID_NPN_SETEXCEPTION - SetGlobalException(0); -#endif + bool retval = true; NPVariant resultVariant; VOID_TO_NPVARIANT(resultVariant); { JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); ASSERT(globalExceptionString().isNull()); - _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant); + retval = _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant); moveGlobalExceptionToExecState(exec); } + + if (!retval) + throwError(exec, GeneralError, "Error calling method on NPObject!"); for (i = 0; i < count; i++) _NPN_ReleaseVariantValue(&cArgs[i]); JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get()); _NPN_ReleaseVariantValue(&resultVariant); -#ifdef ANDROID_NPN_SETEXCEPTION - MoveGlobalExceptionToExecState(exec); -#endif return resultValue; } @@ -159,26 +157,24 @@ JSValue CInstance::invokeDefaultMethod(ExecState* exec, const ArgList& args) convertValueToNPVariant(exec, args.at(i), &cArgs[i]); // Invoke the 'C' method. -#ifdef ANDROID_NPN_SETEXCEPTION - SetGlobalException(0); -#endif + bool retval = true; NPVariant resultVariant; VOID_TO_NPVARIANT(resultVariant); { JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); ASSERT(globalExceptionString().isNull()); - _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant); + retval = _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant); moveGlobalExceptionToExecState(exec); } + + if (!retval) + throwError(exec, GeneralError, "Error calling method on NPObject!"); for (i = 0; i < count; i++) _NPN_ReleaseVariantValue(&cArgs[i]); JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get()); _NPN_ReleaseVariantValue(&resultVariant); -#ifdef ANDROID_NPN_SETEXCEPTION - MoveGlobalExceptionToExecState(exec); -#endif return resultValue; } @@ -200,14 +196,18 @@ JSValue CInstance::invokeConstruct(ExecState* exec, const ArgList& args) convertValueToNPVariant(exec, args.at(i), &cArgs[i]); // Invoke the 'C' method. + bool retval = true; NPVariant resultVariant; VOID_TO_NPVARIANT(resultVariant); { JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); ASSERT(globalExceptionString().isNull()); - _object->_class->construct(_object, cArgs.data(), count, &resultVariant); + retval = _object->_class->construct(_object, cArgs.data(), count, &resultVariant); moveGlobalExceptionToExecState(exec); } + + if (!retval) + throwError(exec, GeneralError, "Error calling method on NPObject!"); for (i = 0; i < count; i++) _NPN_ReleaseVariantValue(&cArgs[i]); diff --git a/WebCore/bridge/c/c_runtime.cpp b/WebCore/bridge/c/c_runtime.cpp index 46d7c6f..e9a7bb6 100644 --- a/WebCore/bridge/c/c_runtime.cpp +++ b/WebCore/bridge/c/c_runtime.cpp @@ -32,47 +32,11 @@ #include "c_instance.h" #include "c_utility.h" #include "npruntime_impl.h" -#ifdef ANDROID_NPN_SETEXCEPTION -#include "runtime/Error.h" -#endif // ANDROID_NPN_SETEXCEPTION #include <runtime/JSLock.h> namespace JSC { namespace Bindings { -#ifdef ANDROID_NPN_SETEXCEPTION -/* - * When throwing an exception, we need to use the current ExecState. - * The following two methods implement a similar solution to the - * Objective-C implementation, where _NPN_SetException set a global - * exception (using SetGlobalException). - * We then test (using MoveGlobalExceptionToExecState) if the exception - * is set, after each javascript call that might result in an exception. - * If the exception is set we throw it with the passed ExecState. - */ - -static UString* globalLastException = 0; - -void SetGlobalException(const NPUTF8* exception) -{ - if (globalLastException != 0) { - delete globalLastException; - globalLastException = 0; - } - if (exception != 0) - globalLastException = new UString(exception); -} - -void MoveGlobalExceptionToExecState(ExecState* exec) -{ - if (!globalLastException) - return; - JSLock lock(exec); - throwError(exec, GeneralError, *globalLastException); - SetGlobalException(0); -} -#endif // ANDROID_NPN_SETEXCEPTION - JSValue CField::valueFromInstance(ExecState* exec, const Instance* inst) const { const CInstance* instance = static_cast<const CInstance*>(inst); @@ -81,17 +45,11 @@ JSValue CField::valueFromInstance(ExecState* exec, const Instance* inst) const NPVariant property; VOID_TO_NPVARIANT(property); -#ifdef ANDROID_NPN_SETEXCEPTION - SetGlobalException(0); -#endif // ANDROID_NPN_SETEXCEPTION bool result; { JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); result = obj->_class->getProperty(obj, _fieldIdentifier, &property); } -#ifdef ANDROID_NPN_SETEXCEPTION - MoveGlobalExceptionToExecState(exec); -#endif // ANDROID_NPN_SETEXCEPTION if (result) { JSValue result = convertNPVariantToValue(exec, &property, instance->rootObject()); _NPN_ReleaseVariantValue(&property); @@ -109,18 +67,12 @@ void CField::setValueToInstance(ExecState *exec, const Instance *inst, JSValue a NPVariant variant; convertValueToNPVariant(exec, aValue, &variant); -#ifdef ANDROID_NPN_SETEXCEPTION - SetGlobalException(0); -#endif // ANDROID_NPN_SETEXCEPTION { JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly); obj->_class->setProperty(obj, _fieldIdentifier, &variant); } _NPN_ReleaseVariantValue(&variant); -#ifdef ANDROID_NPN_SETEXCEPTION - MoveGlobalExceptionToExecState(exec); -#endif // ANDROID_NPN_SETEXCEPTION } } diff --git a/WebCore/bridge/c/c_runtime.h b/WebCore/bridge/c/c_runtime.h index 676d949..e797342 100644 --- a/WebCore/bridge/c/c_runtime.h +++ b/WebCore/bridge/c/c_runtime.h @@ -60,11 +60,6 @@ private: NPIdentifier _methodIdentifier; }; -#ifdef ANDROID_NPN_SETEXCEPTION -void SetGlobalException(const NPUTF8* exception); -void MoveGlobalExceptionToExecState(ExecState* exec); -#endif // ANDROID_NPN_SETEXCEPTION - } // namespace Bindings } // namespace JSC diff --git a/WebCore/bridge/jni/jni_class.cpp b/WebCore/bridge/jni/jni_class.cpp index 0877e50..6728e7b 100644 --- a/WebCore/bridge/jni/jni_class.cpp +++ b/WebCore/bridge/jni/jni_class.cpp @@ -85,11 +85,10 @@ JavaClass::JavaClass(jobject anInstance) methodList->append(aMethod); env->DeleteLocalRef(aJMethod); } -#ifdef ANDROID_FIX + env->DeleteLocalRef(fields); env->DeleteLocalRef(methods); env->DeleteLocalRef(aClass); -#endif } JavaClass::~JavaClass() { diff --git a/WebCore/bridge/jni/jni_instance.cpp b/WebCore/bridge/jni/jni_instance.cpp index 0022196..3783d10 100644 --- a/WebCore/bridge/jni/jni_instance.cpp +++ b/WebCore/bridge/jni/jni_instance.cpp @@ -26,21 +26,22 @@ #include "config.h" #include "jni_instance.h" -#ifdef ANDROID -#include <assert.h> -#endif - #if ENABLE(MAC_JAVA_BRIDGE) #include "jni_class.h" #include "jni_runtime.h" #include "jni_utility.h" +#include "jni_utility_private.h" #include "runtime_object.h" #include "runtime_root.h" #include <runtime/ArgList.h> #include <runtime/Error.h> #include <runtime/JSLock.h> +#if PLATFORM(ANDROID) +#include <assert.h> +#endif + #ifdef NDEBUG #define JS_LOG(formatAndArgs...) ((void)0) #else diff --git a/WebCore/bridge/jni/jni_instance.h b/WebCore/bridge/jni/jni_instance.h index 96dda7d..049bfdb 100644 --- a/WebCore/bridge/jni/jni_instance.h +++ b/WebCore/bridge/jni/jni_instance.h @@ -33,12 +33,6 @@ #include <JavaVM/jni.h> -#if PLATFORM(ANDROID) -namespace android { -class WeakJavaInstance; -} -#endif - namespace JSC { namespace Bindings { @@ -52,9 +46,10 @@ friend class JavaArray; friend class JavaField; friend class JavaInstance; friend class JavaMethod; -#if PLATFORM(ANDROID) -friend class android::WeakJavaInstance; -#endif + +public: + jobject instance() const { return _instance; } + void setInstance(jobject instance) { _instance = instance; } protected: JObjectWrapper(jobject instance); @@ -98,14 +93,10 @@ public: JSValue booleanValue() const; protected: + JavaInstance(jobject instance, PassRefPtr<RootObject>); virtual void virtualBegin(); virtual void virtualEnd(); -#if !PLATFORM(ANDROID) // Submit patch to webkit.org -private: -#endif - JavaInstance(jobject instance, PassRefPtr<RootObject>); - RefPtr<JObjectWrapper> _instance; mutable JavaClass *_class; }; diff --git a/WebCore/bridge/jni/jni_jsobject.mm b/WebCore/bridge/jni/jni_jsobject.mm index c9af8b0..6683af6 100644 --- a/WebCore/bridge/jni/jni_jsobject.mm +++ b/WebCore/bridge/jni/jni_jsobject.mm @@ -29,19 +29,20 @@ #if ENABLE(MAC_JAVA_BRIDGE) #include "Frame.h" +#include "JSDOMBinding.h" +#include "ScriptController.h" +#include "StringSourceProvider.h" #include "WebCoreFrameView.h" #include "jni_runtime.h" #include "jni_utility.h" -#include "ScriptController.h" +#include "jni_utility_private.h" #include "runtime_object.h" #include "runtime_root.h" #include <interpreter/CallFrame.h> +#include <runtime/Completion.h> #include <runtime/JSGlobalObject.h> #include <runtime/JSLock.h> -#include <runtime/Completion.h> -#include <runtime/Completion.h> #include <wtf/Assertions.h> -#include <parser/SourceProvider.h> using WebCore::Frame; @@ -322,7 +323,7 @@ jobject JavaJSObject::eval(jstring script) const return 0; rootObject->globalObject()->globalData()->timeoutChecker.start(); - Completion completion = JSC::evaluate(rootObject->globalObject()->globalExec(), rootObject->globalObject()->globalScopeChain(), makeSource(JavaString(script))); + Completion completion = JSC::evaluate(rootObject->globalObject()->globalExec(), rootObject->globalObject()->globalScopeChain(), makeSource(JavaString(script)), JSC::JSValue()); rootObject->globalObject()->globalData()->timeoutChecker.stop(); ComplType type = completion.complType(); diff --git a/WebCore/bridge/jni/jni_objc.mm b/WebCore/bridge/jni/jni_objc.mm index 0306bfd..fb2d694 100644 --- a/WebCore/bridge/jni/jni_objc.mm +++ b/WebCore/bridge/jni/jni_objc.mm @@ -29,6 +29,7 @@ #import <Foundation/Foundation.h> #import "jni_utility.h" +#import "jni_utility_private.h" #import "objc_utility.h" #include <runtime/JSLock.h> diff --git a/WebCore/bridge/jni/jni_runtime.cpp b/WebCore/bridge/jni/jni_runtime.cpp index 2bac17a..be11981 100644 --- a/WebCore/bridge/jni/jni_runtime.cpp +++ b/WebCore/bridge/jni/jni_runtime.cpp @@ -28,8 +28,8 @@ #if ENABLE(MAC_JAVA_BRIDGE) -#include <jni_utility.h> - +#include "jni_utility.h" +#include "jni_utility_private.h" #include "runtime_array.h" #include "runtime_object.h" #include "runtime_root.h" @@ -284,9 +284,7 @@ JavaMethod::JavaMethod (JNIEnv *env, jobject aMethod) jclass modifierClass = env->FindClass("java/lang/reflect/Modifier"); int modifiers = callJNIMethod<jint>(aMethod, "getModifiers", "()I"); _isStatic = (bool)callJNIStaticMethod<jboolean>(modifierClass, "isStatic", "(I)Z", modifiers); -#ifdef ANDROID_FIX env->DeleteLocalRef(modifierClass); -#endif } JavaMethod::~JavaMethod() diff --git a/WebCore/bridge/jni/jni_utility.cpp b/WebCore/bridge/jni/jni_utility.cpp index e57e475..faa7a8b 100644 --- a/WebCore/bridge/jni/jni_utility.cpp +++ b/WebCore/bridge/jni/jni_utility.cpp @@ -28,14 +28,6 @@ #if ENABLE(MAC_JAVA_BRIDGE) -#if USE(JSC) -#include "jni_runtime.h" -#include "runtime_array.h" -#include "runtime_object.h" -#include <runtime/JSArray.h> -#include <runtime/JSLock.h> -#endif - #include <dlfcn.h> namespace JSC { @@ -350,238 +342,6 @@ jvalue getJNIField( jobject obj, JNIType type, const char *name, const char *sig return result; } -#if USE(JSC) -static jobject convertArrayInstanceToJavaArray(ExecState* exec, JSArray* jsArray, const char* javaClassName) -{ - 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. - unsigned length = jsArray->length(); - 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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(SilenceAssertionsOnly); - - 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 = asObject(value); - if (objectImp->classInfo() == &RuntimeObjectImp::s_info) { - RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(objectImp); - JavaInstance *instance = static_cast<JavaInstance*>(imp->getInternalInstance()); - if (instance) - result.l = instance->javaInstance(); - } - else if (objectImp->classInfo() == &RuntimeArray::s_info) { - // Input is a JavaScript Array that was originally created from a Java Array - RuntimeArray* imp = static_cast<RuntimeArray*>(objectImp); - JavaArray *array = static_cast<JavaArray*>(imp->getConcreteArray()); - result.l = array->javaArray(); - } - else if (objectImp->classInfo() == &JSArray::info) { - // Input is a Javascript Array. We need to create it to a Java Array. - result.l = convertArrayInstanceToJavaArray(exec, asArray(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; -} -#endif // USE(JSC) - } // end of namespace Bindings } // end of namespace JSC diff --git a/WebCore/bridge/jni/jni_utility.h b/WebCore/bridge/jni/jni_utility.h index 959330d..66b3b2f 100644 --- a/WebCore/bridge/jni/jni_utility.h +++ b/WebCore/bridge/jni/jni_utility.h @@ -28,9 +28,6 @@ #if ENABLE(MAC_JAVA_BRIDGE) -#if USE(JSC) -#include <runtime/JSValue.h> -#endif #include <JavaVM/jni.h> // The order of these items can not be modified as they are tightly @@ -55,11 +52,6 @@ typedef enum { namespace JSC { -#if USE(JSC) -class ExecState; -class JSObject; -#endif - namespace Bindings { class JavaParameter; @@ -76,10 +68,6 @@ JNIType JNITypeFromClassName(const char *name); JNIType JNITypeFromPrimitiveType(char type); const char *signatureFromPrimitiveType(JNIType type); -#if USE(JSC) -jvalue convertValueToJValue(ExecState*, JSValue, JNIType, const char* javaClassName); -#endif - jvalue getJNIField(jobject obj, JNIType type, const char *name, const char *signature); jmethodID getMethodID(jobject obj, const char *name, const char *sig); @@ -222,9 +210,8 @@ static T callJNIMethodV(jobject obj, const char *name, const char *sig, va_list jmethodID mid = env->GetMethodID(cls, name, sig); if ( mid != NULL ) { -#ifdef ANDROID_FIX // Avoids references to cls without popping the local frame. + // Avoids references to cls without popping the local frame. env->DeleteLocalRef(cls); -#endif return JNICaller<T>::callV(obj, mid, args); } else @@ -285,10 +272,7 @@ T callJNIStaticMethod(jclass cls, const char* methodName, const char* methodSign return result; } -#if USE(JSC) -bool dispatchJNICall(ExecState*, const void* targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue* args, jvalue& result, const char* callingURL, JSValue& exceptionDescription); -#endif - + } // namespace Bindings } // namespace JSC diff --git a/WebCore/bridge/jni/jsc/jni_utility_private.cpp b/WebCore/bridge/jni/jsc/jni_utility_private.cpp new file mode 100644 index 0000000..7f8afd5 --- /dev/null +++ b/WebCore/bridge/jni/jsc/jni_utility_private.cpp @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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_private.h" + +#if ENABLE(MAC_JAVA_BRIDGE) + +#include "jni_runtime.h" +#include "runtime_array.h" +#include "runtime_object.h" +#include <runtime/JSArray.h> +#include <runtime/JSLock.h> + +namespace JSC { + +namespace Bindings { + +static jobject convertArrayInstanceToJavaArray(ExecState* exec, JSArray* jsArray, const char* javaClassName) +{ + 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. + unsigned length = jsArray->length(); + jobjectArray jarray = 0; + + // Build the correct array type + switch (JNITypeFromPrimitiveType(javaClassName[1])) { + case object_type: + { + // Only support string object types + if (!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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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->get(exec, 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(SilenceAssertionsOnly); + + 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 = asObject(value); + if (objectImp->classInfo() == &RuntimeObjectImp::s_info) { + RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(objectImp); + JavaInstance* instance = static_cast<JavaInstance*>(imp->getInternalInstance()); + if (instance) + result.l = instance->javaInstance(); + } else if (objectImp->classInfo() == &RuntimeArray::s_info) { + // Input is a JavaScript Array that was originally created from a Java Array + RuntimeArray* imp = static_cast<RuntimeArray*>(objectImp); + JavaArray* array = static_cast<JavaArray*>(imp->getConcreteArray()); + result.l = array->javaArray(); + } else if (objectImp->classInfo() == &JSArray::info) { + // Input is a Javascript Array. We need to create it to a Java Array. + result.l = convertArrayInstanceToJavaArray(exec, asArray(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 && !strcmp(javaClassName, "java.lang.String")) { +#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) + 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 JSC + +#endif // ENABLE(MAC_JAVA_BRIDGE) diff --git a/WebCore/bridge/jni/jsc/jni_utility_private.h b/WebCore/bridge/jni/jsc/jni_utility_private.h new file mode 100644 index 0000000..647852e --- /dev/null +++ b/WebCore/bridge/jni/jsc/jni_utility_private.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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_PRIVATE_H_ +#define _JNI_UTILITY_PRIVATE_H_ + +#if ENABLE(MAC_JAVA_BRIDGE) + +#include "jni_utility.h" +#include <runtime/JSValue.h> + +namespace JSC { + +class ExecState; +class JSObject; + +namespace Bindings { + +jvalue convertValueToJValue(ExecState*, JSValue, JNIType, const char* javaClassName); +bool dispatchJNICall(ExecState*, const void* targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue* args, jvalue& result, const char* callingURL, JSValue& exceptionDescription); + +} // namespace Bindings + +} // namespace JSC + +#endif // ENABLE(MAC_JAVA_BRIDGE) + +#endif // _JNI_UTILITY_H_ diff --git a/WebCore/bridge/jni/v8/jni_utility_private.cpp b/WebCore/bridge/jni/v8/jni_utility_private.cpp new file mode 100644 index 0000000..6c8f018 --- /dev/null +++ b/WebCore/bridge/jni/v8/jni_utility_private.cpp @@ -0,0 +1,258 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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_private.h" + +#include "jni_runtime.h" +#include "jni_npobject.h" + +namespace JSC { + +namespace Bindings { + +jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* javaClassName) +{ + jvalue result; + NPVariantType type = value.type; + + switch (jniType) { + case array_type: + case object_type: + { + result.l = (jobject)0; + + // First see if we have a Java instance. + if (type == NPVariantType_Object) { + NPObject* objectImp = NPVARIANT_TO_OBJECT(value); + if (JavaInstance* instance = ExtractJavaInstance(objectImp)) + result.l = instance->javaInstance(); + } + + // 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 (type == NPVariantType_Null) { + JNIEnv *env = getJNIEnv(); + jchar buf[2]; + jobject javaString = env->functions->NewString (env, buf, 0); + result.l = javaString; + } + else +#else + if (type == NPVariantType_String) { +#endif + NPString src = NPVARIANT_TO_STRING(value); + JNIEnv *env = getJNIEnv(); + jobject javaString = env->NewStringUTF(src.UTF8Characters); + result.l = javaString; + } + } else if (result.l == 0) + bzero (&result, sizeof(jvalue)); // Handle it the same as a void case + } + break; + + case boolean_type: + { + if (type == NPVariantType_Bool) + result.z = NPVARIANT_TO_BOOLEAN(value); + else + bzero(&result, sizeof(jvalue)); // as void case + } + break; + + case byte_type: + { + if (type == NPVariantType_Int32) + result.b = (char)NPVARIANT_TO_INT32(value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case char_type: + { + if (type == NPVariantType_Int32) + result.c = (char)NPVARIANT_TO_INT32(value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case short_type: + { + if (type == NPVariantType_Int32) + result.s = (jshort)NPVARIANT_TO_INT32(value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case int_type: + { + if (type == NPVariantType_Int32) + result.i = (jint)NPVARIANT_TO_INT32(value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case long_type: + { + if (type == NPVariantType_Int32) + result.j = (jlong)NPVARIANT_TO_INT32(value); + else if (type == NPVariantType_Double) + result.j = (jlong)NPVARIANT_TO_DOUBLE(value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case float_type: + { + if (type == NPVariantType_Int32) + result.j = (jfloat)NPVARIANT_TO_INT32(value); + else if (type == NPVariantType_Double) + result.j = (jfloat)NPVARIANT_TO_DOUBLE(value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case double_type: + { + if (type == NPVariantType_Int32) + result.j = (jdouble)NPVARIANT_TO_INT32(value); + else if (type == NPVariantType_Double) + result.j = (jdouble)NPVARIANT_TO_DOUBLE(value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + break; + + case invalid_type: + default: + case void_type: + { + bzero(&result, sizeof(jvalue)); + } + break; + } + return result; +} + + +void convertJValueToNPVariant(jvalue value, JNIType jniType, const char* javaTypeName, NPVariant* result) +{ + switch (jniType) { + case void_type: + { + VOID_TO_NPVARIANT(*result); + } + break; + + case object_type: + { + if (value.l != 0) { + if (strcmp(javaTypeName, "java.lang.String") == 0) { + const char* v = getCharactersFromJString((jstring)value.l); + // s is freed in NPN_ReleaseVariantValue (see npruntime.cpp) + const char* s = strdup(v); + releaseCharactersForJString((jstring)value.l, v); + STRINGZ_TO_NPVARIANT(s, *result); + } else { + OBJECT_TO_NPVARIANT(JavaInstanceToNPObject(new JavaInstance(value.l)), *result); + } + } + else { + VOID_TO_NPVARIANT(*result); + } + } + break; + + case boolean_type: + { + BOOLEAN_TO_NPVARIANT(value.z, *result); + } + break; + + case byte_type: + { + INT32_TO_NPVARIANT(value.b, *result); + } + break; + + case char_type: + { + INT32_TO_NPVARIANT(value.c, *result); + } + break; + + case short_type: + { + INT32_TO_NPVARIANT(value.s, *result); + } + break; + + case int_type: + { + INT32_TO_NPVARIANT(value.i, *result); + } + break; + + // TODO: Check if cast to double is needed. + case long_type: + { + DOUBLE_TO_NPVARIANT(value.j, *result); + } + break; + + case float_type: + { + DOUBLE_TO_NPVARIANT(value.f, *result); + } + break; + + case double_type: + { + DOUBLE_TO_NPVARIANT(value.d, *result); + } + break; + + case invalid_type: + default: + { + VOID_TO_NPVARIANT(*result); + } + break; + } +} + +} // end of namespace Bindings + +} // end of namespace JSC diff --git a/WebCore/bridge/jni/v8/jni_utility_private.h b/WebCore/bridge/jni/v8/jni_utility_private.h new file mode 100644 index 0000000..397de7b --- /dev/null +++ b/WebCore/bridge/jni/v8/jni_utility_private.h @@ -0,0 +1,43 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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_PRIVATE_H_ +#define _JNI_UTILITY_PRIVATE_H_ + +#include "jni_utility.h" +#include "npruntime.h" + +namespace JSC { + +namespace Bindings { + +jvalue convertNPVariantToJValue(NPVariant, JNIType, const char* javaClassName); +void convertJValueToNPVariant(jvalue, JNIType, const char* javaClassName, NPVariant*); + +} // namespace Bindings + +} // namespace JSC + +#endif // _JNI_UTILITY_H_ diff --git a/WebCore/bridge/npapi.h b/WebCore/bridge/npapi.h index 126d513..41f9bda 100644 --- a/WebCore/bridge/npapi.h +++ b/WebCore/bridge/npapi.h @@ -56,6 +56,12 @@ # endif /* XP_WIN */ #endif /* _WIN32 */ +#ifdef __SYMBIAN32__ +# ifndef XP_SYMBIAN +# define XP_SYMBIAN 1 +# endif +#endif /* __SYMBIAN32__ */ + #ifdef __MWERKS__ # define _declspec __declspec # ifdef macintosh @@ -64,11 +70,13 @@ # endif /* XP_MAC */ # endif /* macintosh */ # ifdef __INTEL__ -# undef NULL -# ifndef XP_WIN -# define XP_WIN 1 -# endif /* __INTEL__ */ -# endif /* XP_PC */ +# ifndef XP_SYMBIAN +# undef NULL +# ifndef XP_WIN +# define XP_WIN 1 +# endif /* XP_WIN */ +# endif /* XP_SYMBIAN */ +# endif /* __INTEL__ */ #endif /* __MWERKS__ */ #if defined(__APPLE_CC__) && !defined(__MACOS_CLASSIC__) && !defined(XP_UNIX) @@ -99,6 +107,11 @@ #include <stdio.h> #endif +#if defined(XP_SYMBIAN) + #include <QEvent> + #include <QRegion> +#endif + #ifdef XP_WIN #include <windows.h> #endif @@ -114,6 +127,14 @@ /* Definition of Basic Types */ /*----------------------------------------------------------------------*/ +/* QNX sets the _INT16 and friends defines, but does not typedef the types */ +#ifdef __QNXNTO__ +#undef _UINT16 +#undef _INT16 +#undef _UINT32 +#undef _INT32 +#endif + #ifndef _UINT16 #define _UINT16 typedef unsigned short uint16; @@ -354,6 +375,7 @@ typedef enum { #endif #ifdef ANDROID + // TODO(andreip): Remove? NPPFakeValueToForce32Bits = 0x7FFFFFFF #endif } NPPVariable; @@ -519,9 +541,9 @@ typedef struct _NPWindow uint32 height; NPRect clipRect; /* Clipping rectangle in port coordinates */ /* Used by MAC only. */ -#ifdef XP_UNIX +#if defined(XP_UNIX) || defined(XP_SYMBIAN) void * ws_info; /* Platform-dependent additonal data */ -#endif /* XP_UNIX */ +#endif /* XP_UNIX || XP_SYMBIAN */ NPWindowType type; /* Is this a window or a drawable? */ } NPWindow; @@ -571,6 +593,8 @@ typedef enum { typedef EventRecord NPEvent; #endif +#elif defined(XP_SYMBIAN) +typedef QEvent NPEvent; #elif defined(XP_WIN) typedef struct _NPEvent { @@ -601,6 +625,8 @@ typedef CGPathRef NPCGRegion; typedef HRGN NPRegion; #elif defined(XP_UNIX) typedef Region NPRegion; +#elif defined(XP_SYMBIAN) +typedef QRegion* NPRegion; #else typedef void *NPRegion; #endif /* XP_MAC */ diff --git a/WebCore/bridge/objc/objc_instance.h b/WebCore/bridge/objc/objc_instance.h index 6f1eb0d..64cd491 100644 --- a/WebCore/bridge/objc/objc_instance.h +++ b/WebCore/bridge/objc/objc_instance.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2003, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,16 +37,12 @@ class ObjcClass; class ObjcInstance : public Instance { public: - static PassRefPtr<ObjcInstance> create(ObjectStructPtr instance, PassRefPtr<RootObject> rootObject) - { - return adoptRef(new ObjcInstance(instance, rootObject)); - } - + static PassRefPtr<ObjcInstance> create(ObjectStructPtr, PassRefPtr<RootObject>); + virtual ~ObjcInstance(); + static void setGlobalException(NSString*, JSGlobalObject* exceptionEnvironment = 0); // A null exceptionEnvironment means the exception should propogate to any execution environment. - ~ObjcInstance(); - - virtual Class *getClass() const; + virtual Class* getClass() const; virtual JSValue valueOf(ExecState*) const; virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const; @@ -71,7 +67,7 @@ protected: private: static void moveGlobalExceptionToExecState(ExecState*); - ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject>); + ObjcInstance(ObjectStructPtr, PassRefPtr<RootObject>); RetainPtr<ObjectStructPtr> _instance; mutable ObjcClass *_class; diff --git a/WebCore/bridge/objc/objc_instance.mm b/WebCore/bridge/objc/objc_instance.mm index b84f7bb..9f2e3bb 100644 --- a/WebCore/bridge/objc/objc_instance.mm +++ b/WebCore/bridge/objc/objc_instance.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2008 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,9 +28,10 @@ #import "FoundationExtras.h" #import "WebScriptObject.h" -#include <runtime/Error.h> -#include <runtime/JSLock.h> -#include <wtf/Assertions.h> +#import <objc/objc-auto.h> +#import <runtime/Error.h> +#import <runtime/JSLock.h> +#import <wtf/Assertions.h> #ifdef NDEBUG #define OBJC_LOG(formatAndArgs...) ((void)0) @@ -44,8 +45,21 @@ using namespace JSC::Bindings; using namespace JSC; -static NSString* s_exception; +static NSString *s_exception; static JSGlobalObject* s_exceptionEnvironment; // No need to protect this value, since we just use it for a pointer comparison. +static NSMapTable *s_instanceWrapperCache; + +static NSMapTable *createInstanceWrapperCache() +{ +#ifdef BUILDING_ON_TIGER + return NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); +#else + // NSMapTable with zeroing weak pointers is the recommended way to build caches like this under garbage collection. + NSPointerFunctionsOptions keyOptions = NSPointerFunctionsZeroingWeakMemory | NSPointerFunctionsObjectPersonality; + NSPointerFunctionsOptions valueOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality; + return [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0]; +#endif +} void ObjcInstance::setGlobalException(NSString* exception, JSGlobalObject* exceptionEnvironment) { @@ -74,7 +88,7 @@ void ObjcInstance::moveGlobalExceptionToExecState(ExecState* exec) s_exceptionEnvironment = 0; } -ObjcInstance::ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject> rootObject) +ObjcInstance::ObjcInstance(id instance, PassRefPtr<RootObject> rootObject) : Instance(rootObject) , _instance(instance) , _class(0) @@ -83,20 +97,49 @@ ObjcInstance::ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject> root { } +PassRefPtr<ObjcInstance> ObjcInstance::create(id instance, PassRefPtr<RootObject> rootObject) +{ + if (!s_instanceWrapperCache) + s_instanceWrapperCache = createInstanceWrapperCache(); + if (void* existingWrapper = NSMapGet(s_instanceWrapperCache, instance)) + return static_cast<ObjcInstance*>(existingWrapper); + RefPtr<ObjcInstance> wrapper = adoptRef(new ObjcInstance(instance, rootObject)); + NSMapInsert(s_instanceWrapperCache, instance, wrapper.get()); + return wrapper.release(); +} + ObjcInstance::~ObjcInstance() { - // -finalizeForWebScript and -dealloc/-finalize may require autorelease pools. + // Both -finalizeForWebScript and -dealloc/-finalize of _instance may require autorelease pools. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + ASSERT(s_instanceWrapperCache); + ASSERT(_instance); + NSMapRemove(s_instanceWrapperCache, _instance.get()); + if ([_instance.get() respondsToSelector:@selector(finalizeForWebScript)]) [_instance.get() performSelector:@selector(finalizeForWebScript)]; _instance = 0; + [pool drain]; } +static NSAutoreleasePool* allocateAutoReleasePool() +{ +#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2 + // If GC is enabled an autorelease pool is unnecessary, and the + // pool cannot be protected from GC so may be collected leading + // to a crash when we try to drain the release pool. + if (objc_collectingEnabled()) + return nil; +#endif + return [[NSAutoreleasePool alloc] init]; +} + void ObjcInstance::virtualBegin() { if (!_pool) - _pool = [[NSAutoreleasePool alloc] init]; + _pool = allocateAutoReleasePool(); _beginCount++; } diff --git a/WebCore/bridge/objc/objc_runtime.h b/WebCore/bridge/objc/objc_runtime.h index 82d563b..63f3254 100644 --- a/WebCore/bridge/objc/objc_runtime.h +++ b/WebCore/bridge/objc/objc_runtime.h @@ -104,11 +104,13 @@ public: static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } private: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags; virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual CallType getCallData(CallData&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); diff --git a/WebCore/bridge/objc/objc_runtime.mm b/WebCore/bridge/objc/objc_runtime.mm index 2d69c1c..5efc865 100644 --- a/WebCore/bridge/objc/objc_runtime.mm +++ b/WebCore/bridge/objc/objc_runtime.mm @@ -203,13 +203,20 @@ bool ObjcFallbackObjectImp::getOwnPropertySlot(ExecState*, const Identifier&, Pr return true; } +bool ObjcFallbackObjectImp::getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor& descriptor) +{ + // keep the prototype from getting called instead of just returning false + descriptor.setUndefined(); + return true; +} + void ObjcFallbackObjectImp::put(ExecState*, const Identifier&, JSValue, PutPropertySlot&) { } static JSValue JSC_HOST_CALL callObjCFallbackObject(ExecState* exec, JSObject* function, JSValue thisValue, const ArgList& args) { - if (!thisValue.isObject(&RuntimeObjectImp::s_info)) + if (!thisValue.inherits(&RuntimeObjectImp::s_info)) return throwError(exec, TypeError); JSValue result = jsUndefined(); diff --git a/WebCore/bridge/qt/qt_class.h b/WebCore/bridge/qt/qt_class.h index 19d4207..dc6b130 100644 --- a/WebCore/bridge/qt/qt_class.h +++ b/WebCore/bridge/qt/qt_class.h @@ -26,7 +26,7 @@ QT_BEGIN_NAMESPACE class QObject; -class QMetaObject; +struct QMetaObject; QT_END_NAMESPACE namespace JSC { diff --git a/WebCore/bridge/qt/qt_instance.cpp b/WebCore/bridge/qt/qt_instance.cpp index 506697a..c6185e9 100644 --- a/WebCore/bridge/qt/qt_instance.cpp +++ b/WebCore/bridge/qt/qt_instance.cpp @@ -43,30 +43,29 @@ namespace Bindings { 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(ExecState*, PassRefPtr<Instance>); - ~QtRuntimeObjectImp(); - virtual void invalidate(); static const ClassInfo s_info; - virtual void mark() + virtual void markChildren(MarkStack& markStack) { + RuntimeObjectImp::markChildren(markStack); QtInstance* instance = static_cast<QtInstance*>(getInternalInstance()); if (instance) - instance->mark(); - RuntimeObjectImp::mark(); + instance->markAggregate(markStack); + } + + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } protected: - void removeFromCache(); - + static const unsigned StructureFlags = RuntimeObjectImp::StructureFlags | OverridesMarkChildren; + private: virtual const ClassInfo* classInfo() const { return &s_info; } }; @@ -78,25 +77,6 @@ QtRuntimeObjectImp::QtRuntimeObjectImp(ExecState* exec, PassRefPtr<Instance> ins { } -QtRuntimeObjectImp::~QtRuntimeObjectImp() -{ - removeFromCache(); -} - -void QtRuntimeObjectImp::invalidate() -{ - removeFromCache(); - RuntimeObjectImp::invalidate(); -} - -void QtRuntimeObjectImp::removeFromCache() -{ - JSLock lock(SilenceAssertionsOnly); - QtInstance* key = cachedObjects.key(this); - if (key) - cachedObjects.remove(key); -} - // QtInstance QtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject, QScriptEngine::ValueOwnership ownership) : Instance(rootObject) @@ -112,7 +92,6 @@ QtInstance::~QtInstance() { JSLock lock(SilenceAssertionsOnly); - cachedObjects.remove(this); cachedInstances.remove(m_hashkey); // clean up (unprotect from gc) the JSValues we've created @@ -140,10 +119,17 @@ PassRefPtr<QtInstance> QtInstance::getQtInstance(QObject* o, PassRefPtr<RootObje { JSLock lock(SilenceAssertionsOnly); - foreach(QtInstance* instance, cachedInstances.values(o)) { - if (instance->rootObject() == rootObject) - return instance; - } + foreach(QtInstance* instance, cachedInstances.values(o)) + if (instance->rootObject() == rootObject) { + // The garbage collector removes instances, but it may happen that the wrapped + // QObject dies before the gc kicks in. To handle that case we have to do an additional + // check if to see if the instance's wrapped object is still alive. If it isn't, then + // we have to create a new wrapper. + if (!instance->getObject()) + cachedInstances.remove(instance->hashKey()); + else + return instance; + } RefPtr<QtInstance> ret = QtInstance::create(o, rootObject, ownership); cachedInstances.insert(o, ret.get()); @@ -190,25 +176,19 @@ Class* QtInstance::getClass() const return m_class; } -RuntimeObjectImp* QtInstance::createRuntimeObject(ExecState* exec) +RuntimeObjectImp* QtInstance::newRuntimeObject(ExecState* exec) { JSLock lock(SilenceAssertionsOnly); - RuntimeObjectImp* ret = static_cast<RuntimeObjectImp*>(cachedObjects.value(this)); - if (!ret) { - ret = new (exec) QtRuntimeObjectImp(exec, this); - cachedObjects.insert(this, ret); - ret = static_cast<RuntimeObjectImp*>(cachedObjects.value(this)); - } - return ret; + return new (exec) QtRuntimeObjectImp(exec, this); } -void QtInstance::mark() +void QtInstance::markAggregate(MarkStack& markStack) { - if (m_defaultMethod && !m_defaultMethod->marked()) - m_defaultMethod->mark(); + if (m_defaultMethod) + markStack.append(m_defaultMethod); foreach(JSObject* val, m_methods.values()) { - if (val && !val->marked()) - val->mark(); + if (val) + markStack.append(val); } } diff --git a/WebCore/bridge/qt/qt_instance.h b/WebCore/bridge/qt/qt_instance.h index 23766b1..0afc6c7 100644 --- a/WebCore/bridge/qt/qt_instance.h +++ b/WebCore/bridge/qt/qt_instance.h @@ -40,7 +40,7 @@ public: ~QtInstance(); virtual Class* getClass() const; - virtual RuntimeObjectImp* createRuntimeObject(ExecState*); + virtual RuntimeObjectImp* newRuntimeObject(ExecState*); virtual void begin(); virtual void end(); @@ -48,7 +48,7 @@ public: virtual JSValue valueOf(ExecState*) const; virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const; - virtual void mark(); // This isn't inherited + void markAggregate(MarkStack&); virtual JSValue invokeMethod(ExecState*, const MethodList&, const ArgList&); @@ -59,6 +59,7 @@ public: JSValue booleanValue() const; QObject* getObject() const { return m_object; } + QObject* hashKey() const { return m_hashkey; } static PassRefPtr<QtInstance> getQtInstance(QObject*, PassRefPtr<RootObject>, QScriptEngine::ValueOwnership ownership); diff --git a/WebCore/bridge/qt/qt_runtime.cpp b/WebCore/bridge/qt/qt_runtime.cpp index 6be119c..94749b4 100644 --- a/WebCore/bridge/qt/qt_runtime.cpp +++ b/WebCore/bridge/qt/qt_runtime.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "qt_runtime.h" +#include "BooleanObject.h" #include "DateInstance.h" #include "DateMath.h" #include "DatePrototype.h" @@ -46,9 +47,9 @@ #include <JSFunction.h> #include <limits.h> #include <runtime.h> +#include <runtime/Error.h> #include <runtime_array.h> #include <runtime_object.h> -#include "BooleanObject.h" // QtScript has these Q_DECLARE_METATYPE(QObjectList); @@ -456,8 +457,8 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type case QMetaType::QTime: if (type == Date) { DateInstance* date = static_cast<DateInstance*>(object); - WTF::GregorianDateTime gdt; - date->getUTCTime(gdt); + GregorianDateTime gdt; + msToGregorianDateTime(exec, date->internalNumber(), 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 = 0; @@ -470,8 +471,8 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type } } else if (type == Number) { double b = value.toNumber(exec); - WTF::GregorianDateTime gdt; - msToGregorianDateTime(b, true, gdt); + GregorianDateTime gdt; + msToGregorianDateTime(exec, 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; @@ -823,7 +824,7 @@ JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, con } // Dates specified this way are in local time (we convert DateTimes above) - WTF::GregorianDateTime dt; + GregorianDateTime dt; dt.year = date.year() - 1900; dt.month = date.month() - 1; dt.monthDay = date.day(); @@ -831,11 +832,9 @@ JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, con dt.minute = time.minute(); dt.second = time.second(); dt.isDST = -1; - double ms = WTF::gregorianDateTimeToMS(dt, time.msec(), /*inputIsUTC*/ false); + double ms = gregorianDateTimeToMS(exec, dt, time.msec(), /*inputIsUTC*/ false); - DateInstance* instance = new (exec) DateInstance(exec->lexicalGlobalObject()->dateStructure()); - instance->setInternalValue(jsNumber(exec, trunc(ms))); - return instance; + return new (exec) DateInstance(exec, trunc(ms)); } if (type == QMetaType::QByteArray) { @@ -1162,7 +1161,7 @@ static int findMethodIndex(ExecState* exec, } // If the native method requires more arguments than what was passed from JavaScript - if (jsArgs.size() < (types.count() - 1)) { + if (jsArgs.size() + 1 < static_cast<unsigned>(types.count())) { qMatchDebug() << "Match:too few args for" << method.signature(); tooFewArgs.append(index); continue; @@ -1185,7 +1184,7 @@ static int findMethodIndex(ExecState* exec, bool converted = true; int matchDistance = 0; - for (int i = 0; converted && i < types.count() - 1; ++i) { + for (unsigned i = 0; converted && i + 1 < static_cast<unsigned>(types.count()); ++i) { JSValue arg = i < jsArgs.size() ? jsArgs.at(i) : jsUndefined(); int argdistance = -1; @@ -1202,7 +1201,7 @@ static int findMethodIndex(ExecState* exec, qMatchDebug() << "Match: " << method.signature() << (converted ? "converted":"failed to convert") << "distance " << matchDistance; if (converted) { - if ((jsArgs.size() == types.count() - 1) + if ((jsArgs.size() + 1 == static_cast<unsigned>(types.count())) && (matchDistance == 0)) { // perfect match, use this one chosenIndex = index; @@ -1328,17 +1327,17 @@ QtRuntimeMetaMethod::QtRuntimeMetaMethod(ExecState* exec, const Identifier& iden d->m_allowPrivate = allowPrivate; } -void QtRuntimeMetaMethod::mark() +void QtRuntimeMetaMethod::markChildren(MarkStack& markStack) { - QtRuntimeMethod::mark(); + QtRuntimeMethod::markChildren(markStack); QW_D(QtRuntimeMetaMethod); if (d->m_connect) - d->m_connect->mark(); + markStack.append(d->m_connect); if (d->m_disconnect) - d->m_disconnect->mark(); + markStack.append(d->m_disconnect); } -JSValue QtRuntimeMetaMethod::call(ExecState* exec, JSObject* functionObject, JSValue thisValue, const ArgList& args) +JSValue QtRuntimeMetaMethod::call(ExecState* exec, JSObject* functionObject, JSValue, const ArgList& args) { QtRuntimeMetaMethodData* d = static_cast<QtRuntimeMetaMethod *>(functionObject)->d_func(); @@ -1436,7 +1435,7 @@ QtRuntimeConnectionMethod::QtRuntimeConnectionMethod(ExecState* exec, const Iden d->m_isConnect = isConnect; } -JSValue QtRuntimeConnectionMethod::call(ExecState* exec, JSObject* functionObject, JSValue thisValue, const ArgList& args) +JSValue QtRuntimeConnectionMethod::call(ExecState* exec, JSObject* functionObject, JSValue, const ArgList& args) { QtRuntimeConnectionMethodData* d = static_cast<QtRuntimeConnectionMethod *>(functionObject)->d_func(); diff --git a/WebCore/bridge/qt/qt_runtime.h b/WebCore/bridge/qt/qt_runtime.h index 72d93eb..dc55f61 100644 --- a/WebCore/bridge/qt/qt_runtime.h +++ b/WebCore/bridge/qt/qt_runtime.h @@ -151,10 +151,12 @@ public: static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags | OverridesMarkChildren; + QtRuntimeMethodData *d_func() const {return d_ptr;} QtRuntimeMethod(QtRuntimeMethodData *dd, ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst); QtRuntimeMethodData *d_ptr; @@ -167,7 +169,7 @@ public: virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&); - virtual void mark(); + virtual void markChildren(MarkStack& markStack); protected: QtRuntimeMetaMethodData* d_func() const {return reinterpret_cast<QtRuntimeMetaMethodData*>(d_ptr);} diff --git a/WebCore/bridge/runtime.cpp b/WebCore/bridge/runtime.cpp index 6934406..eac8586 100644 --- a/WebCore/bridge/runtime.cpp +++ b/WebCore/bridge/runtime.cpp @@ -48,12 +48,14 @@ Array::~Array() Instance::Instance(PassRefPtr<RootObject> rootObject) : _rootObject(rootObject) + , m_runtimeObject(0) { ASSERT(_rootObject); } Instance::~Instance() { + ASSERT(!m_runtimeObject); } static KJSDidExecuteFunctionPtr s_didExecuteFunction; @@ -80,11 +82,37 @@ void Instance::end() RuntimeObjectImp* Instance::createRuntimeObject(ExecState* exec) { + ASSERT(_rootObject); + ASSERT(_rootObject->isValid()); + if (m_runtimeObject) + return m_runtimeObject; + JSLock lock(SilenceAssertionsOnly); + m_runtimeObject = newRuntimeObject(exec); + _rootObject->addRuntimeObject(m_runtimeObject); + return m_runtimeObject; +} + +RuntimeObjectImp* Instance::newRuntimeObject(ExecState* exec) +{ JSLock lock(SilenceAssertionsOnly); - return new (exec) RuntimeObjectImp(exec, this); } +void Instance::willDestroyRuntimeObject() +{ + ASSERT(_rootObject); + ASSERT(_rootObject->isValid()); + ASSERT(m_runtimeObject); + _rootObject->removeRuntimeObject(m_runtimeObject); + m_runtimeObject = 0; +} + +void Instance::willInvalidateRuntimeObject() +{ + ASSERT(m_runtimeObject); + m_runtimeObject = 0; +} + RootObject* Instance::rootObject() const { return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0; diff --git a/WebCore/bridge/runtime.h b/WebCore/bridge/runtime.h index 2f74a4e..6682a97 100644 --- a/WebCore/bridge/runtime.h +++ b/WebCore/bridge/runtime.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -86,8 +86,10 @@ public: void begin(); void end(); - virtual Class *getClass() const = 0; - virtual RuntimeObjectImp* createRuntimeObject(ExecState*); + virtual Class* getClass() const = 0; + RuntimeObjectImp* createRuntimeObject(ExecState*); + void willInvalidateRuntimeObject(); + void willDestroyRuntimeObject(); // Returns false if the value was not set successfully. virtual bool setValueOfUndefinedField(ExecState*, const Identifier&, JSValue) { return false; } @@ -111,13 +113,18 @@ public: virtual ~Instance(); virtual bool getOwnPropertySlot(JSObject*, ExecState*, const Identifier&, PropertySlot&) { return false; } + virtual bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&) { return false; } virtual void put(JSObject*, ExecState*, const Identifier&, JSValue, PutPropertySlot&) { } protected: virtual void virtualBegin() { } virtual void virtualEnd() { } + virtual RuntimeObjectImp* newRuntimeObject(ExecState*); RefPtr<RootObject> _rootObject; + +private: + RuntimeObjectImp* m_runtimeObject; }; class Array : public Noncopyable { diff --git a/WebCore/bridge/runtime_array.cpp b/WebCore/bridge/runtime_array.cpp index 2849822..feadb07 100644 --- a/WebCore/bridge/runtime_array.cpp +++ b/WebCore/bridge/runtime_array.cpp @@ -75,6 +75,29 @@ bool RuntimeArray::getOwnPropertySlot(ExecState* exec, const Identifier& propert return JSObject::getOwnPropertySlot(exec, propertyName, slot); } +bool RuntimeArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + if (propertyName == exec->propertyNames().length) { + PropertySlot slot; + slot.setCustom(this, lengthGetter); + descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); + return true; + } + + bool ok; + unsigned index = propertyName.toArrayIndex(&ok); + if (ok) { + if (index < getLength()) { + PropertySlot slot; + slot.setCustomIndex(this, index, indexGetter); + descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | DontEnum); + return true; + } + } + + return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + bool RuntimeArray::getOwnPropertySlot(ExecState *exec, unsigned index, PropertySlot& slot) { if (index < getLength()) { diff --git a/WebCore/bridge/runtime_array.h b/WebCore/bridge/runtime_array.h index 5a86e9d..1218b8c 100644 --- a/WebCore/bridge/runtime_array.h +++ b/WebCore/bridge/runtime_array.h @@ -37,6 +37,7 @@ public: virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&); virtual bool getOwnPropertySlot(ExecState *, unsigned, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState *, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue); @@ -58,10 +59,11 @@ public: static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } private: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags; static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&); static JSValue indexGetter(ExecState*, const Identifier&, const PropertySlot&); diff --git a/WebCore/bridge/runtime_method.cpp b/WebCore/bridge/runtime_method.cpp index 0af0af5..ffe4c0a 100644 --- a/WebCore/bridge/runtime_method.cpp +++ b/WebCore/bridge/runtime_method.cpp @@ -73,6 +73,18 @@ bool RuntimeMethod::getOwnPropertySlot(ExecState* exec, const Identifier& proper return InternalFunction::getOwnPropertySlot(exec, propertyName, slot); } +bool RuntimeMethod::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor &descriptor) +{ + if (propertyName == exec->propertyNames().length) { + PropertySlot slot; + slot.setCustom(this, lengthGetter); + descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); + return true; + } + + return InternalFunction::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + static JSValue JSC_HOST_CALL callRuntimeMethod(ExecState* exec, JSObject* function, JSValue thisValue, const ArgList& args) { RuntimeMethod* method = static_cast<RuntimeMethod*>(function); @@ -82,13 +94,13 @@ static JSValue JSC_HOST_CALL callRuntimeMethod(ExecState* exec, JSObject* functi RuntimeObjectImp* imp; - if (thisValue.isObject(&RuntimeObjectImp::s_info)) { + if (thisValue.inherits(&RuntimeObjectImp::s_info)) { imp = static_cast<RuntimeObjectImp*>(asObject(thisValue)); } else { // If thisObj is the DOM object for a plugin, get the corresponding // runtime object from the DOM object. JSValue value = thisValue.get(exec, Identifier(exec, "__apple_runtime_object")); - if (value.isObject(&RuntimeObjectImp::s_info)) + if (value.inherits(&RuntimeObjectImp::s_info)) imp = static_cast<RuntimeObjectImp*>(asObject(value)); else return throwError(exec, TypeError); diff --git a/WebCore/bridge/runtime_method.h b/WebCore/bridge/runtime_method.h index 5333c14..9676048 100644 --- a/WebCore/bridge/runtime_method.h +++ b/WebCore/bridge/runtime_method.h @@ -47,12 +47,14 @@ public: static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } private: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | InternalFunction::StructureFlags; static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual CallType getCallData(CallData&); OwnPtr<Bindings::MethodList> _methodList; diff --git a/WebCore/bridge/runtime_object.cpp b/WebCore/bridge/runtime_object.cpp index 385f914..9583fb2 100644 --- a/WebCore/bridge/runtime_object.cpp +++ b/WebCore/bridge/runtime_object.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,7 +28,6 @@ #include "JSDOMBinding.h" #include "runtime_method.h" -#include "runtime_root.h" #include <runtime/Error.h> #include <runtime/ObjectPrototype.h> @@ -40,38 +39,38 @@ using namespace Bindings; const ClassInfo RuntimeObjectImp::s_info = { "RuntimeObject", 0, 0, 0 }; -RuntimeObjectImp::RuntimeObjectImp(ExecState* exec, PassRefPtr<Instance> i) +RuntimeObjectImp::RuntimeObjectImp(ExecState* exec, PassRefPtr<Instance> instance) // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object // We need to pass in the right global object for "i". : JSObject(deprecatedGetDOMStructure<RuntimeObjectImp>(exec)) - , instance(i) + , m_instance(instance) { - instance->rootObject()->addRuntimeObject(this); } - -RuntimeObjectImp::RuntimeObjectImp(ExecState*, PassRefPtr<Structure> structure, PassRefPtr<Instance> i) + +RuntimeObjectImp::RuntimeObjectImp(ExecState*, NonNullPassRefPtr<Structure> structure, PassRefPtr<Instance> instance) : JSObject(structure) - , instance(i) + , m_instance(instance) { - instance->rootObject()->addRuntimeObject(this); } RuntimeObjectImp::~RuntimeObjectImp() { - if (instance) - instance->rootObject()->removeRuntimeObject(this); + if (m_instance) + m_instance->willDestroyRuntimeObject(); } void RuntimeObjectImp::invalidate() { - ASSERT(instance); - instance = 0; + ASSERT(m_instance); + if (m_instance) + m_instance->willInvalidateRuntimeObject(); + m_instance = 0; } JSValue RuntimeObjectImp::fallbackObjectGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase())); - RefPtr<Instance> instance = thisObj->instance; + RefPtr<Instance> instance = thisObj->m_instance; if (!instance) return throwInvalidAccessError(exec); @@ -89,7 +88,7 @@ JSValue RuntimeObjectImp::fallbackObjectGetter(ExecState* exec, const Identifier JSValue RuntimeObjectImp::fieldGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase())); - RefPtr<Instance> instance = thisObj->instance; + RefPtr<Instance> instance = thisObj->m_instance; if (!instance) return throwInvalidAccessError(exec); @@ -108,7 +107,7 @@ JSValue RuntimeObjectImp::fieldGetter(ExecState* exec, const Identifier& propert JSValue RuntimeObjectImp::methodGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase())); - RefPtr<Instance> instance = thisObj->instance; + RefPtr<Instance> instance = thisObj->m_instance; if (!instance) return throwInvalidAccessError(exec); @@ -126,11 +125,13 @@ JSValue RuntimeObjectImp::methodGetter(ExecState* exec, const Identifier& proper bool RuntimeObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { - if (!instance) { + if (!m_instance) { throwInvalidAccessError(exec); return false; } + RefPtr<Instance> instance = m_instance; + instance->begin(); Class *aClass = instance->getClass(); @@ -167,14 +168,63 @@ bool RuntimeObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& pro return instance->getOwnPropertySlot(this, exec, propertyName, slot); } +bool RuntimeObjectImp::getOwnPropertyDescriptor(ExecState *exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + if (!m_instance) { + throwInvalidAccessError(exec); + return false; + } + + RefPtr<Instance> instance = m_instance; + 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) { + PropertySlot slot; + slot.setCustom(this, fieldGetter); + instance->end(); + descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete); + 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) { + PropertySlot slot; + slot.setCustom(this, methodGetter); + instance->end(); + descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly); + return true; + } + } + + // Try a fallback object. + if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) { + PropertySlot slot; + slot.setCustom(this, fallbackObjectGetter); + instance->end(); + descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum); + return true; + } + } + + instance->end(); + + return instance->getOwnPropertyDescriptor(this, exec, propertyName, descriptor); +} + void RuntimeObjectImp::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - if (!instance) { + if (!m_instance) { throwInvalidAccessError(exec); return; } - RefPtr<Instance> protector(instance); + RefPtr<Instance> instance = m_instance; instance->begin(); // Set the value of the property. @@ -195,10 +245,11 @@ bool RuntimeObjectImp::deleteProperty(ExecState*, const Identifier&) JSValue RuntimeObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const { - if (!instance) + if (!m_instance) return throwInvalidAccessError(exec); - RefPtr<Instance> protector(instance); + RefPtr<Instance> instance = m_instance; + instance->begin(); JSValue result = instance->defaultValue(exec, hint); instance->end(); @@ -216,8 +267,13 @@ static JSValue JSC_HOST_CALL callRuntimeObject(ExecState* exec, JSObject* functi CallType RuntimeObjectImp::getCallData(CallData& callData) { - if (!instance || !instance->supportsInvokeDefaultMethod()) + if (!m_instance) return CallTypeNone; + + RefPtr<Instance> instance = m_instance; + if (!instance->supportsInvokeDefaultMethod()) + return CallTypeNone; + callData.native.function = callRuntimeObject; return CallTypeHost; } @@ -235,24 +291,36 @@ static JSObject* callRuntimeConstructor(ExecState* exec, JSObject* constructor, ConstructType RuntimeObjectImp::getConstructData(ConstructData& constructData) { - if (!instance || !instance->supportsConstruct()) + if (!m_instance) return ConstructTypeNone; + + RefPtr<Instance> instance = m_instance; + if (!instance->supportsConstruct()) + return ConstructTypeNone; + constructData.native.function = callRuntimeConstructor; return ConstructTypeHost; } void RuntimeObjectImp::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) { - if (!instance) { + if (!m_instance) { throwInvalidAccessError(exec); return; } + + RefPtr<Instance> instance = m_instance; instance->begin(); instance->getPropertyNames(exec, propertyNames); instance->end(); } +void RuntimeObjectImp::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +{ + getOwnPropertyNames(exec, propertyNames); +} + JSObject* RuntimeObjectImp::throwInvalidAccessError(ExecState* exec) { return throwError(exec, ReferenceError, "Trying to access object from destroyed plug-in."); diff --git a/WebCore/bridge/runtime_object.h b/WebCore/bridge/runtime_object.h index f01fe1e..391e078 100644 --- a/WebCore/bridge/runtime_object.h +++ b/WebCore/bridge/runtime_object.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,20 +34,22 @@ namespace JSC { class RuntimeObjectImp : public JSObject { public: RuntimeObjectImp(ExecState*, PassRefPtr<Bindings::Instance>); - virtual ~RuntimeObjectImp(); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState* , const Identifier& propertyName); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const; virtual CallType getCallData(CallData&); virtual ConstructType getConstructData(ConstructData&); - + virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&); + + void invalidate(); - virtual void invalidate(); - Bindings::Instance* getInternalInstance() const { return instance.get(); } + Bindings::Instance* getInternalInstance() const { return m_instance.get(); } static JSObject* throwInvalidAccessError(ExecState*); @@ -60,11 +62,12 @@ public: static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } protected: - RuntimeObjectImp(ExecState*, PassRefPtr<Structure>, PassRefPtr<Bindings::Instance>); + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags; + RuntimeObjectImp(ExecState*, NonNullPassRefPtr<Structure>, PassRefPtr<Bindings::Instance>); private: virtual const ClassInfo* classInfo() const { return &s_info; } @@ -73,7 +76,7 @@ private: static JSValue fieldGetter(ExecState*, const Identifier&, const PropertySlot&); static JSValue methodGetter(ExecState*, const Identifier&, const PropertySlot&); - RefPtr<Bindings::Instance> instance; + RefPtr<Bindings::Instance> m_instance; }; } // namespace diff --git a/WebCore/bridge/runtime_root.h b/WebCore/bridge/runtime_root.h index eacbb57..fdd73c4 100644 --- a/WebCore/bridge/runtime_root.h +++ b/WebCore/bridge/runtime_root.h @@ -31,8 +31,10 @@ #endif #include <runtime/Protect.h> +#include <wtf/Forward.h> #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace JSC { |
