summaryrefslogtreecommitdiffstats
path: root/WebCore/bridge
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/bridge
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebCore/bridge')
-rw-r--r--WebCore/bridge/AXObjectCache.h102
-rw-r--r--WebCore/bridge/EditorClient.h145
-rw-r--r--WebCore/bridge/NP_jsobject.cpp465
-rw-r--r--WebCore/bridge/NP_jsobject.h (renamed from WebCore/bridge/win/FrameCairoWin.cpp)37
-rw-r--r--WebCore/bridge/c/c_class.cpp124
-rw-r--r--WebCore/bridge/c/c_class.h61
-rw-r--r--WebCore/bridge/c/c_instance.cpp246
-rw-r--r--WebCore/bridge/c/c_instance.h86
-rw-r--r--WebCore/bridge/c/c_runtime.cpp145
-rw-r--r--WebCore/bridge/c/c_runtime.h (renamed from WebCore/bridge/mac/WebCoreAXObject.h)71
-rw-r--r--WebCore/bridge/c/c_utility.cpp152
-rw-r--r--WebCore/bridge/c/c_utility.h (renamed from WebCore/bridge/win/GlobalHistoryWin.cpp)57
-rw-r--r--WebCore/bridge/jni/jni_class.cpp143
-rw-r--r--WebCore/bridge/jni/jni_class.h66
-rw-r--r--WebCore/bridge/jni/jni_instance.cpp334
-rw-r--r--WebCore/bridge/jni/jni_instance.h110
-rw-r--r--WebCore/bridge/jni/jni_jsobject.h129
-rw-r--r--WebCore/bridge/jni/jni_jsobject.mm720
-rw-r--r--WebCore/bridge/jni/jni_objc.mm83
-rw-r--r--WebCore/bridge/jni/jni_runtime.cpp547
-rw-r--r--WebCore/bridge/jni/jni_runtime.h191
-rw-r--r--WebCore/bridge/jni/jni_utility.cpp584
-rw-r--r--WebCore/bridge/jni/jni_utility.h288
-rw-r--r--WebCore/bridge/mac/AXObjectCacheMac.mm193
-rw-r--r--WebCore/bridge/mac/WebCoreAXObject.mm2744
-rw-r--r--WebCore/bridge/mac/WebCoreScriptDebugger.h94
-rw-r--r--WebCore/bridge/mac/WebCoreScriptDebugger.mm379
-rwxr-xr-xWebCore/bridge/make_testbindings2
-rw-r--r--WebCore/bridge/npapi.h838
-rw-r--r--WebCore/bridge/npruntime.cpp226
-rw-r--r--WebCore/bridge/npruntime.h357
-rw-r--r--WebCore/bridge/npruntime_impl.h66
-rw-r--r--WebCore/bridge/npruntime_internal.h50
-rw-r--r--WebCore/bridge/npruntime_priv.h (renamed from WebCore/bridge/GlobalHistory.h)20
-rw-r--r--WebCore/bridge/objc/WebScriptObject.h (renamed from WebCore/bridge/mac/GlobalHistoryMac.mm)27
-rw-r--r--WebCore/bridge/objc/objc_class.h61
-rw-r--r--WebCore/bridge/objc/objc_class.mm258
-rw-r--r--WebCore/bridge/objc/objc_header.h (renamed from WebCore/bridge/win/FrameWin.h)32
-rw-r--r--WebCore/bridge/objc/objc_instance.h90
-rw-r--r--WebCore/bridge/objc/objc_instance.mm397
-rw-r--r--WebCore/bridge/objc/objc_runtime.h130
-rw-r--r--WebCore/bridge/objc/objc_runtime.mm293
-rw-r--r--WebCore/bridge/objc/objc_utility.h88
-rw-r--r--WebCore/bridge/objc/objc_utility.mm373
-rw-r--r--WebCore/bridge/qt/qt_class.cpp217
-rw-r--r--WebCore/bridge/qt/qt_class.h60
-rw-r--r--WebCore/bridge/qt/qt_instance.cpp357
-rw-r--r--WebCore/bridge/qt/qt_instance.h88
-rw-r--r--WebCore/bridge/qt/qt_runtime.cpp1721
-rw-r--r--WebCore/bridge/qt/qt_runtime.h231
-rw-r--r--WebCore/bridge/runtime.cpp121
-rw-r--r--WebCore/bridge/runtime.h166
-rw-r--r--WebCore/bridge/runtime_array.cpp123
-rw-r--r--WebCore/bridge/runtime_array.h73
-rw-r--r--WebCore/bridge/runtime_method.cpp110
-rw-r--r--WebCore/bridge/runtime_method.h63
-rw-r--r--WebCore/bridge/runtime_object.cpp270
-rw-r--r--WebCore/bridge/runtime_object.h82
-rw-r--r--WebCore/bridge/runtime_root.cpp173
-rw-r--r--WebCore/bridge/runtime_root.h89
-rw-r--r--WebCore/bridge/test.js19
-rw-r--r--WebCore/bridge/testC.js21
-rw-r--r--WebCore/bridge/testM.js29
-rw-r--r--WebCore/bridge/testbindings.cpp421
-rw-r--r--WebCore/bridge/testbindings.mm289
-rw-r--r--WebCore/bridge/testbindings.pro8
-rw-r--r--WebCore/bridge/testqtbindings.cpp142
-rw-r--r--WebCore/bridge/win/FrameCGWin.cpp87
-rw-r--r--WebCore/bridge/win/FrameWin.cpp147
-rw-r--r--WebCore/bridge/win/PageWin.cpp38
70 files changed, 12737 insertions, 4012 deletions
diff --git a/WebCore/bridge/AXObjectCache.h b/WebCore/bridge/AXObjectCache.h
deleted file mode 100644
index d73a5a3..0000000
--- a/WebCore/bridge/AXObjectCache.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef AXObjectCache_h
-#define AXObjectCache_h
-
-#include <limits.h>
-
-#include <wtf/HashMap.h>
-#include <wtf/HashSet.h>
-
-#ifdef __OBJC__
-@class WebCoreAXObject;
-@class WebCoreTextMarker;
-#else
-class WebCoreAXObject;
-class WebCoreTextMarker;
-#endif
-
-namespace WebCore {
-
- class RenderObject;
- class String;
- class VisiblePosition;
-
- typedef unsigned AXID;
-
- struct AXIDHashTraits : WTF::GenericHashTraits<unsigned> {
- static TraitType deletedValue() { return UINT_MAX; }
- };
-
- class AXObjectCache {
- public:
- ~AXObjectCache();
-
- WebCoreAXObject* get(RenderObject*);
- void remove(RenderObject*);
-
- void removeAXID(WebCoreAXObject*);
-
- WebCoreTextMarker* textMarkerForVisiblePosition(const VisiblePosition&);
- VisiblePosition visiblePositionForTextMarker(WebCoreTextMarker*);
-
- void childrenChanged(RenderObject*);
- void postNotification(RenderObject*, const String& message);
- void postNotificationToElement(RenderObject*, const String& message);
- void handleFocusedUIElementChanged();
-
-#if PLATFORM(MAC)
- static void enableAccessibility() { gAccessibilityEnabled = true; }
- static bool accessibilityEnabled() { return gAccessibilityEnabled; }
-#else
- static bool accessibilityEnabled() { return false; }
-#endif
-
- private:
-#if PLATFORM(MAC)
- static bool gAccessibilityEnabled;
-#endif
-
- AXID getAXID(WebCoreAXObject*);
-
- HashMap<RenderObject*, WebCoreAXObject*> m_objects;
- HashSet<AXID, IntHash<AXID>, AXIDHashTraits> m_idsInUse;
- };
-
-#if !PLATFORM(MAC)
- inline AXObjectCache::~AXObjectCache() { }
- inline WebCoreAXObject* AXObjectCache::get(RenderObject*) { return 0; }
- inline void AXObjectCache::remove(RenderObject*) { }
- inline void AXObjectCache::removeAXID(WebCoreAXObject*) { }
- inline void AXObjectCache::childrenChanged(RenderObject*) { }
- inline void AXObjectCache::postNotification(RenderObject*, const String&) { }
- inline void AXObjectCache::postNotificationToElement(RenderObject*, const String&) { }
- inline void AXObjectCache::handleFocusedUIElementChanged() { }
-#endif
-
-}
-
-#endif
diff --git a/WebCore/bridge/EditorClient.h b/WebCore/bridge/EditorClient.h
deleted file mode 100644
index 802aa4f..0000000
--- a/WebCore/bridge/EditorClient.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2007 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.
- */
-
-#ifndef EditorClient_h
-#define EditorClient_h
-
-#include "EditorInsertAction.h"
-#include "PlatformString.h"
-#include "TextAffinity.h"
-#include <wtf/Forward.h>
-#include <wtf/Vector.h>
-
-#if PLATFORM(MAC)
-class NSArray;
-class NSData;
-class NSString;
-class NSURL;
-#endif
-
-namespace WebCore {
-
-class CSSStyleDeclaration;
-class EditCommand;
-class Element;
-class Frame;
-class HTMLElement;
-class KeyboardEvent;
-class Node;
-class Range;
-class Selection;
-class String;
-class VisiblePosition;
-
-struct GrammarDetail {
- int location;
- int length;
- Vector<String> guesses;
- String userDescription;
-};
-
-class EditorClient {
-public:
- virtual ~EditorClient() { }
- virtual void pageDestroyed() = 0;
-
- virtual bool shouldDeleteRange(Range*) = 0;
- virtual bool shouldShowDeleteInterface(HTMLElement*) = 0;
- virtual bool smartInsertDeleteEnabled() = 0;
- virtual bool isContinuousSpellCheckingEnabled() = 0;
- virtual void toggleContinuousSpellChecking() = 0;
- virtual bool isGrammarCheckingEnabled() = 0;
- virtual void toggleGrammarChecking() = 0;
- virtual int spellCheckerDocumentTag() = 0;
-
- virtual bool isEditable() = 0;
-
- virtual bool shouldBeginEditing(Range*) = 0;
- virtual bool shouldEndEditing(Range*) = 0;
- virtual bool shouldInsertNode(Node*, Range*, EditorInsertAction) = 0;
- virtual bool shouldInsertText(String, Range*, EditorInsertAction) = 0;
- virtual bool shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity, bool stillSelecting) = 0;
-
- virtual bool shouldApplyStyle(CSSStyleDeclaration*, Range*) = 0;
-// virtual bool shouldChangeTypingStyle(CSSStyleDeclaration* fromStyle, CSSStyleDeclaration* toStyle) = 0;
-// virtual bool doCommandBySelector(SEL selector) = 0;
- virtual bool shouldMoveRangeAfterDelete(Range*, Range*) = 0;
-
- virtual void didBeginEditing() = 0;
- virtual void respondToChangedContents() = 0;
- virtual void respondToChangedSelection() = 0;
- virtual void didEndEditing() = 0;
- virtual void didWriteSelectionToPasteboard() = 0;
- virtual void didSetSelectionTypesForPasteboard() = 0;
-// virtual void didChangeTypingStyle:(NSNotification *)notification = 0;
-// virtual void didChangeSelection:(NSNotification *)notification = 0;
-// virtual NSUndoManager* undoManager:(WebView *)webView = 0;
-
- virtual void registerCommandForUndo(PassRefPtr<EditCommand>) = 0;
- virtual void registerCommandForRedo(PassRefPtr<EditCommand>) = 0;
- virtual void clearUndoRedoOperations() = 0;
-
- virtual bool canUndo() const = 0;
- virtual bool canRedo() const = 0;
-
- virtual void undo() = 0;
- virtual void redo() = 0;
-
- virtual void handleKeyboardEvent(KeyboardEvent*) = 0;
- virtual void handleInputMethodKeydown(KeyboardEvent*) = 0;
-
- virtual void textFieldDidBeginEditing(Element*) = 0;
- virtual void textFieldDidEndEditing(Element*) = 0;
- virtual void textDidChangeInTextField(Element*) = 0;
- virtual bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*) = 0;
- virtual void textWillBeDeletedInTextField(Element*) = 0;
- virtual void textDidChangeInTextArea(Element*) = 0;
-
-#if PLATFORM(MAC)
- // FIXME: This should become SelectionController::toWebArchive()
- virtual NSData* dataForArchivedSelection(Frame*) = 0;
-
- virtual NSString* userVisibleString(NSURL*) = 0;
-#ifdef BUILDING_ON_TIGER
- virtual NSArray* pasteboardTypesForSelection(Frame*) = 0;
-#endif
-#endif
-
- virtual void ignoreWordInSpellDocument(const String&) = 0;
- virtual void learnWord(const String&) = 0;
- virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength) = 0;
- virtual void checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) = 0;
- virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail& detail) = 0;
- virtual void updateSpellingUIWithMisspelledWord(const String&) = 0;
- virtual void showSpellingUI(bool show) = 0;
- virtual bool spellingUIIsShowing() = 0;
- virtual void getGuessesForWord(const String&, Vector<String>& guesses) = 0;
- virtual void setInputMethodState(bool enabled) = 0;
-};
-
-}
-
-#endif // EditorClient_h
diff --git a/WebCore/bridge/NP_jsobject.cpp b/WebCore/bridge/NP_jsobject.cpp
new file mode 100644
index 0000000..9734862
--- /dev/null
+++ b/WebCore/bridge/NP_jsobject.cpp
@@ -0,0 +1,465 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "NP_jsobject.h"
+
+#include "PlatformString.h"
+#include "StringSourceProvider.h"
+#ifdef ANDROID_NPN_SETEXCEPTION
+#include "c_runtime.h"
+#endif // ANDROID_NPN_SETEXCEPTION
+#include "c_utility.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+#include "runtime_root.h"
+#include <runtime/Error.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <runtime/PropertyNameArray.h>
+#include <kjs/SourceCode.h>
+#include <kjs/completion.h>
+#include <kjs/interpreter.h>
+
+using WebCore::String;
+using WebCore::StringSourceProvider;
+using namespace JSC;
+using namespace JSC::Bindings;
+
+static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, ArgList& aList)
+{
+ for (unsigned i = 0; i < argCount; ++i)
+ aList.append(convertNPVariantToValue(exec, &args[i], rootObject));
+}
+
+static NPObject* jsAllocate(NPP, NPClass*)
+{
+ return static_cast<NPObject*>(malloc(sizeof(JavaScriptObject)));
+}
+
+static void jsDeallocate(NPObject* npObj)
+{
+ JavaScriptObject* obj = reinterpret_cast<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, 0 };
+static NPClass noScriptClass = { 1, 0, 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 = reinterpret_cast<JavaScriptObject*>(_NPN_CreateObject(npp, NPScriptObjectClass));
+
+ obj->rootObject = rootObject.releaseRef();
+
+ if (obj->rootObject)
+ obj->rootObject->gcProtect(imp);
+ obj->imp = imp;
+
+ return reinterpret_cast<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 = reinterpret_cast<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(false);
+
+ // Call the function object.
+ JSValue* function = obj->imp;
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+ if (callType == CallTypeNone)
+ return false;
+
+ ArgList argList;
+ getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+ rootObject->globalObject()->startTimeoutCheck();
+ JSValue* resultV = call(exec, function, callType, callData, function, argList);
+ rootObject->globalObject()->stopTimeoutCheck();
+
+ // Convert and return the result of the function call.
+ convertValueToNPVariant(exec, resultV, result);
+ exec->clearException();
+ 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 = reinterpret_cast<JavaScriptObject*>(o);
+
+ PrivateIdentifier* i = static_cast<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, const_cast<NPString*>(&args[0].value.stringValue), result);
+ }
+
+ // Look up the function object.
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(false);
+ JSValue* function = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+ if (callType == CallTypeNone)
+ return false;
+
+ // Call the function object.
+ ArgList argList;
+ getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+ rootObject->globalObject()->startTimeoutCheck();
+ JSValue* resultV = call(exec, function, callType, callData, obj->imp, argList);
+ rootObject->globalObject()->stopTimeoutCheck();
+
+ // Convert and return the result of the function call.
+ convertValueToNPVariant(exec, resultV, result);
+ exec->clearException();
+ 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 = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+
+ JSLock lock(false);
+ String scriptString = convertNPStringToUTF16(s);
+ rootObject->globalObject()->startTimeoutCheck();
+ Completion completion = Interpreter::evaluate(rootObject->globalObject()->globalExec(), rootObject->globalObject()->globalScopeChain(), makeSource(scriptString));
+ rootObject->globalObject()->stopTimeoutCheck();
+ ComplType type = completion.complType();
+
+ JSValue* result;
+ if (type == Normal) {
+ result = completion.value();
+ if (!result)
+ result = jsUndefined();
+ } else
+ result = jsUndefined();
+
+ convertValueToNPVariant(exec, result, variant);
+ exec->clearException();
+ return true;
+ }
+
+ VOID_TO_NPVARIANT(*variant);
+ return false;
+}
+
+bool _NPN_GetProperty(NPP, NPObject* o, NPIdentifier propertyName, NPVariant* variant)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ PrivateIdentifier* i = static_cast<PrivateIdentifier*>(propertyName);
+
+ JSLock lock(false);
+ 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);
+ exec->clearException();
+ 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 = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(false);
+ PrivateIdentifier* i = static_cast<PrivateIdentifier*>(propertyName);
+
+ if (i->isString) {
+ PutPropertySlot slot;
+ obj->imp->put(exec, identifierFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant, rootObject), slot);
+ } else
+ obj->imp->put(exec, i->value.number, convertNPVariantToValue(exec, variant, rootObject));
+ exec->clearException();
+ 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 = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ PrivateIdentifier* i = static_cast<PrivateIdentifier*>(propertyName);
+ if (i->isString) {
+ if (!obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string))) {
+ exec->clearException();
+ return false;
+ }
+ } else {
+ if (!obj->imp->hasProperty(exec, i->value.number)) {
+ exec->clearException();
+ return false;
+ }
+ }
+
+ JSLock lock(false);
+ if (i->isString)
+ obj->imp->deleteProperty(exec, identifierFromNPIdentifier(i->value.string));
+ else
+ obj->imp->deleteProperty(exec, i->value.number);
+
+ exec->clearException();
+ return true;
+ }
+ return false;
+}
+
+bool _NPN_HasProperty(NPP, NPObject* o, NPIdentifier propertyName)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ PrivateIdentifier* i = static_cast<PrivateIdentifier*>(propertyName);
+ JSLock lock(false);
+ if (i->isString) {
+ bool result = obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string));
+ exec->clearException();
+ return result;
+ }
+
+ bool result = obj->imp->hasProperty(exec, i->value.number);
+ exec->clearException();
+ return result;
+ }
+
+ 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 = reinterpret_cast<JavaScriptObject*>(o);
+
+ PrivateIdentifier* i = static_cast<PrivateIdentifier*>(methodName);
+ if (!i->isString)
+ return false;
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(false);
+ JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
+ exec->clearException();
+ return !func->isUndefined();
+ }
+
+ if (o->_class->hasMethod)
+ return o->_class->hasMethod(o, methodName);
+
+ return false;
+}
+
+void _NPN_SetException(NPObject* o, const NPUTF8* message)
+{
+ // FIXME:
+ // Bug 19888: Implement _NPN_SetException() correctly
+ // <https://bugs.webkit.org/show_bug.cgi?id=19888>
+#ifdef ANDROID_NPN_SETEXCEPTION
+ if (o->_class == NPScriptObjectClass) {
+ JSC::Bindings::SetGlobalException(message);
+ }
+#endif // ANDROID_NPN_SETEXCEPTION
+}
+
+bool _NPN_Enumerate(NPP, NPObject* o, NPIdentifier** identifier, uint32_t* count)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
+
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(false);
+ PropertyNameArray propertyNames(exec);
+
+ 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;
+
+ exec->clearException();
+ return true;
+ }
+
+ if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o->_class) && o->_class->enumerate)
+ return o->_class->enumerate(o, identifier, count);
+
+ return false;
+}
+
+bool _NPN_Construct(NPP npp, NPObject* o, const NPVariant* args, uint32_t argCount, NPVariant* result)
+{
+ if (o->_class == NPScriptObjectClass) {
+ JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
+
+ VOID_TO_NPVARIANT(*result);
+
+ // Lookup the constructor object.
+ RootObject* rootObject = obj->rootObject;
+ if (!rootObject || !rootObject->isValid())
+ return false;
+
+ ExecState* exec = rootObject->globalObject()->globalExec();
+ JSLock lock(false);
+
+ // Call the constructor object.
+ JSValue* constructor = obj->imp;
+ ConstructData constructData;
+ ConstructType constructType = constructor->getConstructData(constructData);
+ if (constructType == ConstructTypeNone)
+ return false;
+
+ ArgList argList;
+ getListFromVariantArgs(exec, args, argCount, rootObject, argList);
+ rootObject->globalObject()->startTimeoutCheck();
+ JSValue* resultV = construct(exec, constructor, constructType, constructData, argList);
+ rootObject->globalObject()->stopTimeoutCheck();
+
+ // Convert and return the result.
+ convertValueToNPVariant(exec, resultV, result);
+ exec->clearException();
+ return true;
+ }
+
+ if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(o->_class) && o->_class->construct)
+ return o->_class->construct(o, args, argCount, result);
+
+ return false;
+}
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/WebCore/bridge/win/FrameCairoWin.cpp b/WebCore/bridge/NP_jsobject.h
index a645a10..6c49d1b 100644
--- a/WebCore/bridge/win/FrameCairoWin.cpp
+++ b/WebCore/bridge/NP_jsobject.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
@@ -23,20 +23,33 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "FrameWin.h"
+#ifndef NP_JSOBJECT_H
+#define NP_JSOBJECT_H
-#include "EditorClient.h"
-#include "NotImplemented.h"
+#if ENABLE(NETSCAPE_PLUGIN_API)
-using std::min;
+#include "npruntime_internal.h"
+#include <wtf/Forward.h>
-namespace WebCore {
+namespace JSC {
+ class JSObject;
+ namespace Bindings {
+ class RootObject;
+ }
+}
+
+extern NPClass* NPScriptObjectClass;
-HBITMAP imageFromSelection(Frame* frame, bool forceBlackText)
+struct JavaScriptObject
{
- notImplemented();
- return 0;
-}
+ NPObject object;
+ JSC::JSObject* imp;
+ JSC::Bindings::RootObject* rootObject;
+};
+
+NPObject* _NPN_CreateScriptObject(NPP npp, JSC::JSObject*, PassRefPtr<JSC::Bindings::RootObject> rootObject);
+NPObject* _NPN_CreateNoScriptObject(void);
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
-} // namespace WebCore
+#endif
diff --git a/WebCore/bridge/c/c_class.cpp b/WebCore/bridge/c/c_class.cpp
new file mode 100644
index 0000000..1b72476
--- /dev/null
+++ b/WebCore/bridge/c/c_class.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "c_class.h"
+
+#include "c_instance.h"
+#include "c_runtime.h"
+#include "npruntime_impl.h"
+#include <kjs/identifier.h>
+#include <runtime/JSLock.h>
+
+namespace JSC { namespace Bindings {
+
+CClass::CClass(NPClass* aClass)
+{
+ _isa = aClass;
+}
+
+CClass::~CClass()
+{
+ JSLock lock(false);
+
+ 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(false);
+ _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(false);
+ _fields.set(identifier.ustring().rep(), aField);
+ }
+ }
+ return aField;
+}
+
+} } // namespace JSC::Bindings
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/WebCore/bridge/c/c_class.h b/WebCore/bridge/c/c_class.h
new file mode 100644
index 0000000..9a08605
--- /dev/null
+++ b/WebCore/bridge/c/c_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 BINDINGS_C_CLASS_H_
+#define BINDINGS_C_CLASS_H_
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "npruntime_internal.h"
+#include "runtime.h"
+#include <wtf/HashMap.h>
+
+namespace JSC {
+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 JSC
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/WebCore/bridge/c/c_instance.cpp b/WebCore/bridge/c/c_instance.cpp
new file mode 100644
index 0000000..79ae520
--- /dev/null
+++ b/WebCore/bridge/c/c_instance.cpp
@@ -0,0 +1,246 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "c_instance.h"
+
+#include "c_class.h"
+#include "c_runtime.h"
+#include "c_utility.h"
+#include "npruntime_impl.h"
+#include "runtime_root.h"
+#include <runtime/ArgList.h>
+#include <runtime/ExecState.h>
+#include <runtime/JSLock.h>
+#include <runtime/JSNumberCell.h>
+#include <runtime/PropertyNameArray.h>
+#include <wtf/Assertions.h>
+#include <wtf/StringExtras.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+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;
+}
+
+bool CInstance::supportsInvokeDefaultMethod() const
+{
+ return _object->_class->invokeDefault;
+}
+
+JSValue* CInstance::invokeMethod(ExecState* exec, const MethodList& methodList, const ArgList& 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, 8> cArgs(count);
+
+ unsigned i;
+ for (i = 0; i < count; i++)
+ convertValueToNPVariant(exec, args.at(exec, i), &cArgs[i]);
+
+ // Invoke the 'C' method.
+#ifdef ANDROID_NPN_SETEXCEPTION
+ SetGlobalException(0);
+#endif
+ NPVariant resultVariant;
+ VOID_TO_NPVARIANT(resultVariant);
+
+ {
+ JSLock::DropAllLocks dropAllLocks(false);
+ _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);
+#ifdef ANDROID_NPN_SETEXCEPTION
+ MoveGlobalExceptionToExecState(exec);
+#endif
+ return resultValue;
+}
+
+
+JSValue* CInstance::invokeDefaultMethod(ExecState* exec, const ArgList& args)
+{
+ if (!_object->_class->invokeDefault)
+ return jsUndefined();
+
+ unsigned count = args.size();
+ Vector<NPVariant, 8> cArgs(count);
+
+ unsigned i;
+ for (i = 0; i < count; i++)
+ convertValueToNPVariant(exec, args.at(exec, i), &cArgs[i]);
+
+ // Invoke the 'C' method.
+#ifdef ANDROID_NPN_SETEXCEPTION
+ SetGlobalException(0);
+#endif
+ NPVariant resultVariant;
+ VOID_TO_NPVARIANT(resultVariant);
+ {
+ JSLock::DropAllLocks dropAllLocks(false);
+ _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);
+#ifdef ANDROID_NPN_SETEXCEPTION
+ MoveGlobalExceptionToExecState(exec);
+#endif
+ return resultValue;
+}
+
+bool CInstance::supportsConstruct() const
+{
+ return _object->_class->construct;
+}
+
+JSValue* CInstance::invokeConstruct(ExecState* exec, const ArgList& args)
+{
+ if (!_object->_class->construct)
+ return jsUndefined();
+
+ unsigned count = args.size();
+ Vector<NPVariant, 8> cArgs(count);
+
+ unsigned i;
+ for (i = 0; i < count; i++)
+ convertValueToNPVariant(exec, args.at(exec, i), &cArgs[i]);
+
+ // Invoke the 'C' method.
+ NPVariant resultVariant;
+ VOID_TO_NPVARIANT(resultVariant);
+ {
+ JSLock::DropAllLocks dropAllLocks(false);
+ _object->_class->construct(_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(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ return valueOf(exec);
+}
+
+JSValue* CInstance::stringValue(ExecState* exec) const
+{
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class);
+ return jsString(exec, buf);
+}
+
+JSValue* CInstance::numberValue(ExecState* exec) const
+{
+ // FIXME: Implement something sensible.
+ return jsNumber(exec, 0);
+}
+
+JSValue* CInstance::booleanValue() const
+{
+ // FIXME: Implement something sensible.
+ return jsBoolean(false);
+}
+
+JSValue* CInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
+
+void CInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray)
+{
+ if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) || !_object->_class->enumerate)
+ return;
+
+ uint32_t count;
+ NPIdentifier* identifiers;
+
+ {
+ JSLock::DropAllLocks dropAllLocks(false);
+ if (!_object->_class->enumerate(_object, &identifiers, &count))
+ return;
+ }
+
+ for (uint32_t 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(exec, identifier->value.number));
+ }
+
+ // FIXME: This should really call NPN_MemFree but that's in WebKit
+ free(identifiers);
+}
+
+}
+}
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/WebCore/bridge/c/c_instance.h b/WebCore/bridge/c/c_instance.h
new file mode 100644
index 0000000..6cc4b8d
--- /dev/null
+++ b/WebCore/bridge/c/c_instance.h
@@ -0,0 +1,86 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "runtime.h"
+#include <wtf/PassRefPtr.h>
+#include "runtime_root.h"
+
+typedef struct NPObject NPObject;
+
+namespace JSC {
+
+namespace Bindings {
+
+class CClass;
+
+class CInstance : public Instance {
+public:
+ static PassRefPtr<CInstance> create(NPObject* object, PassRefPtr<RootObject> rootObject)
+ {
+ return adoptRef(new CInstance(object, rootObject));
+ }
+ ~CInstance ();
+
+ virtual Class *getClass() const;
+
+ virtual JSValue* valueOf(ExecState*) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual JSValue* invokeMethod(ExecState*, const MethodList&, const ArgList&);
+ virtual bool supportsInvokeDefaultMethod() const;
+ virtual JSValue* invokeDefaultMethod(ExecState*, const ArgList&);
+
+ virtual bool supportsConstruct() const;
+ virtual JSValue* invokeConstruct(ExecState*, const ArgList&);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ JSValue* stringValue(ExecState*) const;
+ JSValue* numberValue(ExecState*) const;
+ JSValue* booleanValue() const;
+
+ NPObject *getObject() const { return _object; }
+
+ virtual BindingLanguage getBindingLanguage() const { return CLanguage; }
+
+private:
+ CInstance(NPObject*, PassRefPtr<RootObject>);
+
+ mutable CClass *_class;
+ NPObject *_object;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/WebCore/bridge/c/c_runtime.cpp b/WebCore/bridge/c/c_runtime.cpp
new file mode 100644
index 0000000..7cf5dc9
--- /dev/null
+++ b/WebCore/bridge/c/c_runtime.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "c_runtime.h"
+
+#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
+
+// ---------------------- 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);
+
+#ifdef ANDROID_NPN_SETEXCEPTION
+ SetGlobalException(0);
+#endif // ANDROID_NPN_SETEXCEPTION
+ bool result;
+ {
+ JSLock::DropAllLocks dropAllLocks(false);
+ 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);
+ 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);
+
+#ifdef ANDROID_NPN_SETEXCEPTION
+ SetGlobalException(0);
+#endif // ANDROID_NPN_SETEXCEPTION
+ {
+ JSLock::DropAllLocks dropAllLocks(false);
+ obj->_class->setProperty(obj, _fieldIdentifier, &variant);
+ }
+
+ _NPN_ReleaseVariantValue(&variant);
+#ifdef ANDROID_NPN_SETEXCEPTION
+ MoveGlobalExceptionToExecState(exec);
+#endif // ANDROID_NPN_SETEXCEPTION
+ }
+}
+
+} }
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/WebCore/bridge/mac/WebCoreAXObject.h b/WebCore/bridge/c/c_runtime.h
index 2014ca6..998e6d4 100644
--- a/WebCore/bridge/mac/WebCoreAXObject.h
+++ b/WebCore/bridge/c/c_runtime.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * 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
@@ -20,46 +20,53 @@
* 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import "AXObjectCache.h"
+#ifndef BINDINGS_C_RUNTIME_H_
+#define BINDINGS_C_RUNTIME_H_
-namespace WebCore {
- class HTMLAreaElement;
- class RenderObject;
-}
+#if ENABLE(NETSCAPE_PLUGIN_API)
-@interface WebCoreAXObject : NSObject
-{
- WebCore::RenderObject* m_renderer;
- id m_data;
- WebCore::HTMLAreaElement* m_areaElement;
- NSMutableArray* m_children;
- WebCore::AXID m_id;
-}
+#include "npruntime_internal.h"
+#include "runtime.h"
+
+namespace JSC {
+namespace Bindings {
+
+class CField : public Field {
+public:
+ CField(NPIdentifier ident) : _fieldIdentifier(ident) { }
-- (id)initWithRenderer:(WebCore::RenderObject*)renderer;
+ virtual JSValue* valueFromInstance(ExecState*, const Instance*) const;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue*) const;
+ virtual const char* name() const;
-- (BOOL)detached;
-- (void)detach;
+private:
+ NPIdentifier _fieldIdentifier;
+};
+
+
+class CMethod : public Method
+{
+public:
+ CMethod(NPIdentifier ident) : _methodIdentifier(ident) { }
-- (id)data;
-- (void)setData:(id)data;
+ virtual const char* name() const;
+ virtual int numParameters() const { return 0; }
-- (WebCore::AXID)axObjectID;
-- (void)setAXObjectID:(WebCore::AXID)axObjectID;
-- (void)removeAXObjectID;
+private:
+ NPIdentifier _methodIdentifier;
+};
-- (WebCoreAXObject*)firstChild;
-- (WebCoreAXObject*)lastChild;
-- (WebCoreAXObject*)previousSibling;
-- (WebCoreAXObject*)nextSibling;
-- (WebCoreAXObject*)parentObject;
+#ifdef ANDROID_NPN_SETEXCEPTION
+void SetGlobalException(const NPUTF8* exception);
+void MoveGlobalExceptionToExecState(ExecState* exec);
+#endif // ANDROID_NPN_SETEXCEPTION
-- (WebCoreAXObject*)observableObject;
+} // namespace Bindings
+} // namespace JSC
-- (void)childrenChanged;
-- (void)clearChildren;
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
-@end
+#endif
diff --git a/WebCore/bridge/c/c_utility.cpp b/WebCore/bridge/c/c_utility.cpp
new file mode 100644
index 0000000..dced048
--- /dev/null
+++ b/WebCore/bridge/c/c_utility.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "c_utility.h"
+
+#include "JSDOMWindow.h"
+#include "NP_jsobject.h"
+#include "c_instance.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include "PlatformString.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <wtf/Assertions.h>
+
+using WebCore::String;
+
+namespace JSC { namespace Bindings {
+
+static String convertUTF8ToUTF16WithLatin1Fallback(const NPUTF8* UTF8Chars, int UTF8Length)
+{
+ ASSERT(UTF8Chars || UTF8Length == 0);
+
+ if (UTF8Length == -1)
+ UTF8Length = static_cast<int>(strlen(UTF8Chars));
+
+ String result = String::fromUTF8(UTF8Chars, UTF8Length);
+
+ // If we got back a null string indicating an unsuccessful conversion, fall back to latin 1.
+ // 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.isNull())
+ result = String(UTF8Chars, UTF8Length);
+
+ return result;
+}
+
+// Variant value must be released with NPReleaseVariantValue()
+void convertValueToNPVariant(ExecState* exec, JSValue* value, NPVariant* result)
+{
+ JSLock lock(false);
+
+ VOID_TO_NPVARIANT(*result);
+
+ if (value->isString()) {
+ 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 (value->isNumber()) {
+ DOUBLE_TO_NPVARIANT(value->toNumber(exec), *result);
+ } else if (value->isBoolean()) {
+ BOOLEAN_TO_NPVARIANT(value->toBoolean(exec), *result);
+ } else if (value->isNull()) {
+ NULL_TO_NPVARIANT(*result);
+ } else if (value->isObject()) {
+ JSObject* object = asObject(value);
+ if (object->classInfo() == &RuntimeObjectImp::s_info) {
+ RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(object);
+ 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* exec, const NPVariant* variant, RootObject* rootObject)
+{
+ JSLock lock(false);
+
+ 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(exec, NPVARIANT_TO_INT32(*variant));
+ if (type == NPVariantType_Double)
+ return jsNumber(exec, NPVARIANT_TO_DOUBLE(*variant));
+ if (type == NPVariantType_String)
+ return jsString(exec, convertNPStringToUTF16(&variant->value.stringValue));
+ 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(exec, CInstance::create(obj, rootObject));
+ }
+
+ return jsUndefined();
+}
+
+String convertNPStringToUTF16(const NPString* string)
+{
+ return convertUTF8ToUTF16WithLatin1Fallback(string->UTF8Characters, string->UTF8Length);
+}
+
+Identifier identifierFromNPIdentifier(const NPUTF8* name)
+{
+ return Identifier(WebCore::JSDOMWindow::commonJSGlobalData(), convertUTF8ToUTF16WithLatin1Fallback(name, -1));
+}
+
+} }
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/WebCore/bridge/win/GlobalHistoryWin.cpp b/WebCore/bridge/c/c_utility.h
index c81f09b..1e0dd22 100644
--- a/WebCore/bridge/win/GlobalHistoryWin.cpp
+++ b/WebCore/bridge/c/c_utility.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -23,17 +23,54 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "GlobalHistory.h"
+#ifndef C_UTILITY_H_
+#define C_UTILITY_H_
-#include "WebCoreHistory.h"
+#if ENABLE(NETSCAPE_PLUGIN_API)
-namespace WebCore {
+#include "npruntime_internal.h"
+#include <runtime/JSValue.h>
-bool historyContains(const UChar* characters, unsigned length)
-{
- WebCoreHistoryProvider* provider = WebCoreHistory::historyProvider();
- return provider && provider->containsURL(characters, length);
+namespace WebCore {
+ class String;
}
-} // namespace WebCore
+namespace JSC {
+
+class ExecState;
+class Identifier;
+
+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
+};
+
+WebCore::String convertNPStringToUTF16(const NPString *string);
+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 // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/WebCore/bridge/jni/jni_class.cpp b/WebCore/bridge/jni/jni_class.cpp
new file mode 100644
index 0000000..4140524
--- /dev/null
+++ b/WebCore/bridge/jni/jni_class.cpp
@@ -0,0 +1,143 @@
+/*
+ * 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"
+
+#if ENABLE(MAC_JAVA_BRIDGE)
+
+#include "JSDOMWindow.h"
+#include <kjs/identifier.h>
+#include <runtime/JSLock.h>
+#include "jni_utility.h"
+#include "jni_runtime.h"
+
+using namespace JSC::Bindings;
+
+JavaClass::JavaClass(jobject anInstance)
+{
+ jobject aClass = callJNIMethod<jobject>(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)callJNIMethod<jobject>(aClass, "getName", "()Ljava/lang/String;");
+ const char *classNameC = getCharactersFromJString(className);
+ _name = strdup(classNameC);
+ releaseCharactersForJString(className, classNameC);
+
+ int i;
+ JNIEnv *env = getJNIEnv();
+
+ JSGlobalData* globalData = WebCore::JSDOMWindow::commonJSGlobalData();
+
+ // Get the fields
+ jarray fields = (jarray)callJNIMethod<jobject>(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(false);
+ _fields.set(Identifier(globalData, UString(aField->name())).ustring().rep(), aField);
+ }
+ env->DeleteLocalRef(aJField);
+ }
+
+ // Get the methods
+ jarray methods = (jarray)callJNIMethod<jobject>(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(false);
+
+ methodList = _methods.get(Identifier(globalData, UString(aMethod->name())).ustring().rep());
+ if (!methodList) {
+ methodList = new MethodList();
+ _methods.set(Identifier(globalData, UString(aMethod->name())).ustring().rep(), methodList);
+ }
+ }
+ methodList->append(aMethod);
+ env->DeleteLocalRef(aJMethod);
+ }
+}
+
+JavaClass::~JavaClass() {
+ free((void *)_name);
+
+ JSLock lock(false);
+
+ 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;
+}
+
+#endif // ENABLE(MAC_JAVA_BRIDGE)
diff --git a/WebCore/bridge/jni/jni_class.h b/WebCore/bridge/jni/jni_class.h
new file mode 100644
index 0000000..75cfd89
--- /dev/null
+++ b/WebCore/bridge/jni/jni_class.h
@@ -0,0 +1,66 @@
+/*
+ * 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_
+
+#if ENABLE(MAC_JAVA_BRIDGE)
+
+#include <jni_runtime.h>
+#include <wtf/HashMap.h>
+
+namespace JSC {
+
+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 JSC
+
+#endif // ENABLE(MAC_JAVA_BRIDGE)
+
+#endif // JNI_CLASS_H_
diff --git a/WebCore/bridge/jni/jni_instance.cpp b/WebCore/bridge/jni/jni_instance.cpp
new file mode 100644
index 0000000..6b23900
--- /dev/null
+++ b/WebCore/bridge/jni/jni_instance.cpp
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "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 "runtime_object.h"
+#include "runtime_root.h"
+#include <runtime/ArgList.h>
+#include <runtime/Error.h>
+#include <runtime/JSLock.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 JSC::Bindings;
+using namespace JSC;
+
+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::virtualBegin()
+{
+ getJNIEnv()->PushLocalFrame (NUM_LOCAL_REFS);
+}
+
+void JavaInstance::virtualEnd()
+{
+ getJNIEnv()->PopLocalFrame (NULL);
+}
+
+Class *JavaInstance::getClass() const
+{
+ if (_class == 0)
+ _class = new JavaClass (_instance->_instance);
+ return _class;
+}
+
+JSValue* JavaInstance::stringValue(ExecState* exec) const
+{
+ JSLock lock(false);
+
+ jstring stringValue = (jstring)callJNIMethod<jobject>(_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(exec, u);
+}
+
+JSValue* JavaInstance::numberValue(ExecState* exec) const
+{
+ jdouble doubleValue = callJNIMethod<jdouble>(_instance->_instance, "doubleValue", "()D");
+ return jsNumber(exec, doubleValue);
+}
+
+JSValue* JavaInstance::booleanValue() const
+{
+ jboolean booleanValue = callJNIMethod<jboolean>(_instance->_instance, "booleanValue", "()Z");
+ return jsBoolean(booleanValue);
+}
+
+JSValue* JavaInstance::invokeMethod (ExecState *exec, const MethodList &methodList, const ArgList &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(exec, i), aParameter->getJNIType(), aParameter->type());
+ JS_LOG("arg[%d] = %s\n", i, args.at(exec, 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 = noValue();
+ const char *callingURL = 0; // FIXME, need to propagate calling URL to Java
+ handled = dispatchJNICall(exec, 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:
+ callJNIMethodIDA<void>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case object_type:
+ result.l = callJNIMethodIDA<jobject>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case boolean_type:
+ result.z = callJNIMethodIDA<jboolean>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case byte_type:
+ result.b = callJNIMethodIDA<jbyte>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case char_type:
+ result.c = callJNIMethodIDA<jchar>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case short_type:
+ result.s = callJNIMethodIDA<jshort>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case int_type:
+ result.i = callJNIMethodIDA<jint>(obj, jMethod->methodID(obj), jArgs);
+ break;
+
+ case long_type:
+ result.j = callJNIMethodIDA<jlong>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case float_type:
+ result.f = callJNIMethodIDA<jfloat>(obj, jMethod->methodID(obj), jArgs);
+ break;
+ case double_type:
+ result.d = callJNIMethodIDA<jdouble>(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(exec, JavaInstance::create(result.l, rootObject));
+ }
+ }
+ else {
+ resultValue = jsUndefined();
+ }
+ }
+ break;
+
+ case boolean_type: {
+ resultValue = jsBoolean(result.z);
+ }
+ break;
+
+ case byte_type: {
+ resultValue = jsNumber(exec, result.b);
+ }
+ break;
+
+ case char_type: {
+ resultValue = jsNumber(exec, result.c);
+ }
+ break;
+
+ case short_type: {
+ resultValue = jsNumber(exec, result.s);
+ }
+ break;
+
+ case int_type: {
+ resultValue = jsNumber(exec, result.i);
+ }
+ break;
+
+ case long_type: {
+ resultValue = jsNumber(exec, result.j);
+ }
+ break;
+
+ case float_type: {
+ resultValue = jsNumber(exec, result.f);
+ }
+ break;
+
+ case double_type: {
+ resultValue = jsNumber(exec, result.d);
+ }
+ break;
+
+ case invalid_type:
+ default: {
+ resultValue = jsUndefined();
+ }
+ break;
+ }
+
+ free (jArgs);
+
+ return resultValue;
+}
+
+JSValue* JavaInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ JavaClass *aClass = static_cast<JavaClass*>(getClass());
+ if (aClass->isStringClass())
+ return stringValue(exec);
+ if (aClass->isNumberClass())
+ return numberValue(exec);
+ if (aClass->isBooleanClass())
+ return booleanValue();
+ return valueOf(exec);
+}
+
+JSValue* JavaInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
+
+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);
+}
+
+#endif // ENABLE(MAC_JAVA_BRIDGE)
diff --git a/WebCore/bridge/jni/jni_instance.h b/WebCore/bridge/jni/jni_instance.h
new file mode 100644
index 0000000..7104865
--- /dev/null
+++ b/WebCore/bridge/jni/jni_instance.h
@@ -0,0 +1,110 @@
+/*
+ * 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_
+
+#if ENABLE(MAC_JAVA_BRIDGE)
+
+#include "runtime.h"
+#include "runtime_root.h"
+
+#include <JavaVM/jni.h>
+
+namespace JSC {
+
+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:
+ static PassRefPtr<JavaInstance> create(jobject instance, PassRefPtr<RootObject> rootObject)
+ {
+ return adoptRef(new JavaInstance(instance, rootObject));
+ }
+
+ ~JavaInstance();
+
+ virtual Class *getClass() const;
+
+ virtual JSValue* valueOf(ExecState*) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual JSValue* invokeMethod(ExecState* exec, const MethodList& method, const ArgList& args);
+
+ jobject javaInstance() const { return _instance->_instance; }
+
+ JSValue* stringValue(ExecState*) const;
+ JSValue* numberValue(ExecState*) const;
+ JSValue* booleanValue() const;
+
+ virtual BindingLanguage getBindingLanguage() const { return JavaLanguage; }
+
+protected:
+ virtual void virtualBegin();
+ virtual void virtualEnd();
+
+private:
+ JavaInstance(jobject instance, PassRefPtr<RootObject>);
+
+ RefPtr<JObjectWrapper> _instance;
+ mutable JavaClass *_class;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // ENABLE(MAC_JAVA_BRIDGE)
+
+#endif // _JNI_INSTANCE_H_
diff --git a/WebCore/bridge/jni/jni_jsobject.h b/WebCore/bridge/jni/jni_jsobject.h
new file mode 100644
index 0000000..812317d
--- /dev/null
+++ b/WebCore/bridge/jni/jni_jsobject.h
@@ -0,0 +1,129 @@
+/*
+ * 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
+
+#if ENABLE(MAC_JAVA_BRIDGE)
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <JavaVM/jni.h>
+#include <runtime/JSValue.h>
+#include <wtf/RefPtr.h>
+
+#define jlong_to_ptr(a) ((void*)(uintptr_t)(a))
+#define jlong_to_impptr(a) (static_cast<JSC::JSObject*>(((void*)(uintptr_t)(a))))
+#define ptr_to_jlong(a) ((jlong)(uintptr_t)(a))
+
+namespace JSC {
+
+class ArgList;
+class ExecState;
+class JSObject;
+
+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(ExecState*, jobject) const;
+ void getListFromJArray(ExecState*, jobjectArray, ArgList&) const;
+
+ RootObject* rootObject() const;
+
+ // Must be called from the thread that will be used to access JavaScript.
+ static void initializeJNIThreading();
+private:
+ RefPtr<RootObject> _rootObject;
+ JSObject* _imp;
+};
+
+
+} // namespace Bindings
+
+} // namespace JSC
+
+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 // ENABLE(MAC_JAVA_BRIDGE)
+
+#endif // JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H
diff --git a/WebCore/bridge/jni/jni_jsobject.mm b/WebCore/bridge/jni/jni_jsobject.mm
new file mode 100644
index 0000000..042d1ed
--- /dev/null
+++ b/WebCore/bridge/jni/jni_jsobject.mm
@@ -0,0 +1,720 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "jni_jsobject.h"
+
+#if ENABLE(MAC_JAVA_BRIDGE)
+
+#include "Frame.h"
+#include "WebCoreFrameView.h"
+#include "jni_runtime.h"
+#include "jni_utility.h"
+#include "ScriptController.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <runtime/ExecState.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <kjs/completion.h>
+#include <kjs/interpreter.h>
+#include <wtf/Assertions.h>
+#include <kjs/SourceProvider.h>
+
+using WebCore::Frame;
+
+using namespace JSC::Bindings;
+using namespace JSC;
+
+#ifdef NDEBUG
+#define JS_LOG(formatAndArgs...) ((void)0)
+#else
+#define JS_LOG(formatAndArgs...) { \
+ fprintf (stderr, "%s(%p,%p): ", __PRETTY_FUNCTION__, _performJavaScriptRunLoop, CFRunLoopGetCurrent()); \
+ fprintf(stderr, formatAndArgs); \
+}
+#endif
+
+#define UndefinedHandle 1
+
+static CFRunLoopSourceRef _performJavaScriptSource;
+static CFRunLoopRef _performJavaScriptRunLoop;
+
+// May only be set by dispatchToJavaScriptThread().
+static CFRunLoopSourceRef completionSource;
+
+static void completedJavaScriptAccess (void *i)
+{
+ assert (CFRunLoopGetCurrent() != _performJavaScriptRunLoop);
+
+ 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);
+}
+
+static void 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 != _performJavaScriptRunLoop);
+
+ // 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(_performJavaScriptSource);
+ if (CFRunLoopIsWaiting(_performJavaScriptRunLoop))
+ CFRunLoopWakeUp(_performJavaScriptRunLoop);
+
+ // Wait until the JavaScript access thread is done.
+ CFRunLoopRun ();
+
+ CFRunLoopRemoveSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);
+ CFRelease (completionSource);
+
+ unlockJavaScriptAccess();
+}
+
+static void performJavaScriptAccess(void*)
+{
+ assert (CFRunLoopGetCurrent() == _performJavaScriptRunLoop);
+
+ // 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);
+}
+
+// Must be called from the thread that will be used to access JavaScript.
+void JavaJSObject::initializeJNIThreading() {
+ // Should only be called once.
+ ASSERT(!_performJavaScriptRunLoop);
+
+ // Assume that we can retain this run loop forever. It'll most
+ // likely (always?) be the main loop.
+ _performJavaScriptRunLoop = (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};
+ _performJavaScriptSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
+ CFRunLoopAddSource(_performJavaScriptRunLoop, _performJavaScriptSource, kCFRunLoopDefaultMode);
+}
+
+static bool isJavaScriptThread()
+{
+ return (_performJavaScriptRunLoop == 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.
+ 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(false);
+
+ Identifier identifier(exec, JavaString(methodName));
+ JSValue* function = _imp->get(exec, identifier);
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+ if (callType == CallTypeNone)
+ return 0;
+
+ // Call the function object.
+ ArgList argList;
+ getListFromJArray(exec, args, argList);
+ rootObject->globalObject()->startTimeoutCheck();
+ JSValue* result = JSC::call(exec, function, callType, callData, _imp, argList);
+ rootObject->globalObject()->stopTimeoutCheck();
+
+ return convertValueToJObject(result);
+}
+
+jobject JavaJSObject::eval(jstring script) const
+{
+ JS_LOG ("script = %s\n", JavaString(script).UTF8String());
+
+ JSValue* result;
+
+ JSLock lock(false);
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ rootObject->globalObject()->startTimeoutCheck();
+ Completion completion = Interpreter::evaluate(rootObject->globalObject()->globalExec(), rootObject->globalObject()->globalScopeChain(), makeSource(JavaString(script)));
+ 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(false);
+ JSValue* result = _imp->get(exec, Identifier(exec, JavaString(memberName)));
+
+ 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(false);
+ PutPropertySlot slot;
+ _imp->put(exec, Identifier(exec, JavaString(memberName)), convertJObjectToValue(exec, value), slot);
+}
+
+
+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(false);
+ _imp->deleteProperty(exec, Identifier(exec, JavaString(memberName)));
+}
+
+
+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(false);
+ JSValue* result = _imp->get(exec, 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(false);
+ _imp->put(exec, (unsigned)index, convertJObjectToValue(exec, value));
+}
+
+
+jstring JavaJSObject::toString() const
+{
+ JS_LOG ("\n");
+
+ RootObject* rootObject = this->rootObject();
+ if (!rootObject)
+ return 0;
+
+ JSLock lock(false);
+ 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);
+}
+
+static PassRefPtr<RootObject> createRootObject(void* nativeHandle)
+{
+ Frame* frame = 0;
+ for (NSView *view = (NSView *)nativeHandle; view; view = [view superview]) {
+ if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
+ NSView<WebCoreFrameView> *webCoreFrameView = static_cast<NSView<WebCoreFrameView>*>(view);
+ frame = [webCoreFrameView _web_frame];
+ break;
+ }
+ }
+ if (!frame)
+ return 0;
+ return frame->script()->createRootObject(nativeHandle);
+}
+
+// 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;
+
+ 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(false);
+
+ 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
+
+ if (value->isNumber()) {
+ 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 (value->isString()) {
+ UString stringValue = value->toString(exec);
+ JNIEnv *env = getJNIEnv();
+ result = env->NewString ((const jchar *)stringValue.data(), stringValue.size());
+ } else if (value->isBoolean()) {
+ 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 (value->isObject()) {
+ JSObject* imp = asObject(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*>(imp);
+ 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(ExecState* exec, 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 = callJNIMethod<jobject>(theObject, "getClass", "()Ljava/lang/Class;");
+ jstring className = (jstring)callJNIMethod<jobject>(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(false);
+
+ return JSC::Bindings::Instance::createRuntimeObject(exec, JavaInstance::create(theObject, _rootObject));
+}
+
+void JavaJSObject::getListFromJArray(ExecState* exec, jobjectArray jArray, ArgList& list) const
+{
+ JNIEnv *env = getJNIEnv();
+ int numObjects = jArray ? env->GetArrayLength(jArray) : 0;
+
+ for (int i = 0; i < numObjects; i++) {
+ jobject anObject = env->GetObjectArrayElement ((jobjectArray)jArray, i);
+ if (anObject) {
+ list.append(convertJObjectToValue(exec, 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;
+}
+
+}
+
+#endif // ENABLE(MAC_JAVA_BRIDGE)
diff --git a/WebCore/bridge/jni/jni_objc.mm b/WebCore/bridge/jni/jni_objc.mm
new file mode 100644
index 0000000..45ee9f5
--- /dev/null
+++ b/WebCore/bridge/jni/jni_objc.mm
@@ -0,0 +1,83 @@
+/*
+ * 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 ENABLE(MAC_JAVA_BRIDGE)
+
+#import <Foundation/Foundation.h>
+#import "jni_utility.h"
+#import "objc_utility.h"
+#include <runtime/JSLock.h>
+
+using namespace JSC::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 JSC::Bindings::dispatchJNICall(ExecState* exec, 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(false);
+ result = [view webPlugInCallJava:obj isStatic:isStatic returnType:returnType method:methodID arguments:args callingURL:nil exceptionDescription:&_exceptionDescription];
+ }
+
+ if (_exceptionDescription != 0) {
+ exceptionDescription = convertNSStringToString(exec, _exceptionDescription);
+ }
+ return true;
+ }
+ else if ([view respondsToSelector:@selector(webPlugInCallJava:method:returnType:arguments:)]) {
+ JSLock::DropAllLocks dropAllLocks(false);
+ result = [view webPlugInCallJava:obj method:methodID returnType:returnType arguments:args];
+ return true;
+ }
+
+ bzero (&result, sizeof(jvalue));
+ return false;
+}
+
+#endif // ENABLE(MAC_JAVA_BRIDGE)
diff --git a/WebCore/bridge/jni/jni_runtime.cpp b/WebCore/bridge/jni/jni_runtime.cpp
new file mode 100644
index 0000000..3a9b950
--- /dev/null
+++ b/WebCore/bridge/jni/jni_runtime.cpp
@@ -0,0 +1,547 @@
+/*
+ * 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_runtime.h>
+
+#if ENABLE(MAC_JAVA_BRIDGE)
+
+#include <jni_utility.h>
+
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <runtime/Error.h>
+#include <runtime/JSLock.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 JSC;
+using namespace JSC::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 = callJNIMethod<jobject>(aField, "getType", "()Ljava/lang/Class;");
+ jstring fieldTypeName = (jstring)callJNIMethod<jobject>(fieldType, "getName", "()Ljava/lang/String;");
+ _type = JavaString(env, fieldTypeName);
+ _JNIType = JNITypeFromClassName (_type.UTF8String());
+
+ // Get field name
+ jstring fieldName = (jstring)callJNIMethod<jobject>(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 (exec) 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 = noValue();
+ jvalue args[1];
+
+ args[0].l = jinstance;
+ dispatchJNICall(exec, 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(exec, JavaInstance::create(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(exec, (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(exec, (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 = noValue();
+ jvalue args[2];
+ jvalue result;
+
+ args[0].l = jinstance;
+ args[1] = javaValue;
+ dispatchJNICall(exec, 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 = callJNIMethod<jobject>(aMethod, "getReturnType", "()Ljava/lang/Class;");
+ jstring returnTypeName = (jstring)callJNIMethod<jobject>(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)callJNIMethod<jobject>(aMethod, "getName", "()Ljava/lang/String;");
+ _name = JavaString (env, methodName);
+ env->DeleteLocalRef (methodName);
+
+ // Get parameters
+ jarray jparameters = (jarray)callJNIMethod<jobject>(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)callJNIMethod<jobject>(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 = callJNIMethod<jint>(aMethod, "getModifiers", "()I");
+ _isStatic = (bool)callJNIStaticMethod<jboolean>(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(false);
+
+ 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 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 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(exec, JavaInstance::create(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(exec, aByte);
+ }
+
+ case char_type: {
+ jcharArray charArray = (jcharArray)javaArray();
+ jchar aChar;
+ env->GetCharArrayRegion(charArray, index, 1, &aChar);
+ return jsNumber(exec, aChar);
+ break;
+ }
+
+ case short_type: {
+ jshortArray shortArray = (jshortArray)javaArray();
+ jshort aShort;
+ env->GetShortArrayRegion(shortArray, index, 1, &aShort);
+ return jsNumber(exec, aShort);
+ }
+
+ case int_type: {
+ jintArray intArray = (jintArray)javaArray();
+ jint anInt;
+ env->GetIntArrayRegion(intArray, index, 1, &anInt);
+ return jsNumber(exec, anInt);
+ }
+
+ case long_type: {
+ jlongArray longArray = (jlongArray)javaArray();
+ jlong aLong;
+ env->GetLongArrayRegion(longArray, index, 1, &aLong);
+ return jsNumber(exec, aLong);
+ }
+
+ case float_type: {
+ jfloatArray floatArray = (jfloatArray)javaArray();
+ jfloat aFloat;
+ env->GetFloatArrayRegion(floatArray, index, 1, &aFloat);
+ return jsNumber(exec, aFloat);
+ }
+
+ case double_type: {
+ jdoubleArray doubleArray = (jdoubleArray)javaArray();
+ jdouble aDouble;
+ env->GetDoubleArrayRegion(doubleArray, index, 1, &aDouble);
+ return jsNumber(exec, aDouble);
+ }
+ default:
+ break;
+ }
+ return jsUndefined();
+}
+
+unsigned int JavaArray::getLength() const
+{
+ return _length;
+}
+
+#endif // ENABLE(MAC_JAVA_BRIDGE)
diff --git a/WebCore/bridge/jni/jni_runtime.h b/WebCore/bridge/jni/jni_runtime.h
new file mode 100644
index 0000000..67bc06e
--- /dev/null
+++ b/WebCore/bridge/jni/jni_runtime.h
@@ -0,0 +1,191 @@
+/*
+ * 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_
+
+#if ENABLE(MAC_JAVA_BRIDGE)
+
+#include <jni_utility.h>
+#include <jni_instance.h>
+#include <runtime/JSLock.h>
+
+
+namespace JSC
+{
+
+namespace Bindings
+{
+
+typedef const char* RuntimeType;
+
+class JavaString
+{
+public:
+ JavaString()
+ {
+ JSLock lock(false);
+ _rep = UString().rep();
+ }
+
+ void _commonInit (JNIEnv *e, jstring s)
+ {
+ int _size = e->GetStringLength (s);
+ const jchar *uc = getUCharactersFromJStringInEnv (e, s);
+ {
+ JSLock lock(false);
+ _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(false);
+ _rep = 0;
+ }
+
+ const char *UTF8String() const {
+ if (_utf8String.c_str() == 0) {
+ JSLock lock(false);
+ _utf8String = UString(_rep).UTF8String();
+ }
+ return _utf8String.c_str();
+ }
+ const jchar *uchars() const { return (const jchar *)_rep->data(); }
+ int length() const { return _rep->size(); }
+ operator 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 JSC
+
+#endif // ENABLE(MAC_JAVA_BRIDGE)
+
+#endif // _JNI_RUNTIME_H_
diff --git a/WebCore/bridge/jni/jni_utility.cpp b/WebCore/bridge/jni/jni_utility.cpp
new file mode 100644
index 0000000..0fe7174
--- /dev/null
+++ b/WebCore/bridge/jni/jni_utility.cpp
@@ -0,0 +1,584 @@
+/*
+ * 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"
+
+#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>
+#include <dlfcn.h>
+
+namespace JSC {
+
+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;
+}
+
+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;
+}
+
+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, 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(false);
+
+ 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;
+}
+
+} // end of namespace Bindings
+
+} // end of namespace JSC
+
+#endif // ENABLE(MAC_JAVA_BRIDGE)
diff --git a/WebCore/bridge/jni/jni_utility.h b/WebCore/bridge/jni/jni_utility.h
new file mode 100644
index 0000000..b30c654
--- /dev/null
+++ b/WebCore/bridge/jni/jni_utility.h
@@ -0,0 +1,288 @@
+/*
+ * 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_
+
+#if ENABLE(MAC_JAVA_BRIDGE)
+
+#include <runtime/JSValue.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 JSC {
+
+class ExecState;
+class JSObject;
+
+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*, JSValue*, 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);
+JNIEnv* getJNIEnv();
+JavaVM* getJavaVM();
+void setJavaVM(JavaVM*);
+
+
+template <typename T> struct JNICaller;
+
+template<> struct JNICaller<void> {
+ static void callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallVoidMethodA(obj, mid, args);
+ }
+ static void callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallVoidMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jobject> {
+ static jobject callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallObjectMethodA(obj, mid, args);
+ }
+ static jobject callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallObjectMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jboolean> {
+ static jboolean callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallBooleanMethodA(obj, mid, args);
+ }
+ static jboolean callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallBooleanMethodV(obj, mid, args);
+ }
+ static jboolean callStaticV(jclass cls, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallStaticBooleanMethod(cls, mid, args);
+ }
+
+};
+
+template<> struct JNICaller<jbyte> {
+ static jbyte callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallByteMethodA(obj, mid, args);
+ }
+ static jbyte callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallByteMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jchar> {
+ static jchar callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallCharMethodA(obj, mid, args);
+ }
+ static jchar callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallCharMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jshort> {
+ static jshort callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallShortMethodA(obj, mid, args);
+ }
+ static jshort callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallShortMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jint> {
+ static jint callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallIntMethodA(obj, mid, args);
+ }
+ static jint callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallIntMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jlong> {
+ static jlong callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallLongMethodA(obj, mid, args);
+ }
+ static jlong callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallLongMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jfloat> {
+ static jfloat callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallFloatMethodA(obj, mid, args);
+ }
+ static jfloat callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallFloatMethodV(obj, mid, args);
+ }
+};
+
+template<> struct JNICaller<jdouble> {
+ static jdouble callA(jobject obj, jmethodID mid, jvalue* args)
+ {
+ return getJNIEnv()->CallDoubleMethodA(obj, mid, args);
+ }
+ static jdouble callV(jobject obj, jmethodID mid, va_list args)
+ {
+ return getJNIEnv()->CallDoubleMethodV(obj, mid, args);
+ }
+};
+
+template<typename T> T callJNIMethodIDA(jobject obj, jmethodID mid, jvalue *args)
+{
+ return JNICaller<T>::callA(obj, mid, args);
+}
+
+template<typename T>
+static T callJNIMethodV(jobject obj, const char *name, const char *sig, va_list args)
+{
+ JavaVM *jvm = getJavaVM();
+ JNIEnv *env = getJNIEnv();
+
+ 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 )
+ {
+ return JNICaller<T>::callV(obj, mid, args);
+ }
+ 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 0;
+}
+
+template<typename T>
+T callJNIMethod(jobject obj, const char* methodName, const char* methodSignature, ...)
+{
+ va_list args;
+ va_start(args, methodSignature);
+
+ T result= callJNIMethodV<T>(obj, methodName, methodSignature, args);
+
+ va_end(args);
+
+ return result;
+}
+
+template<typename T>
+T callJNIStaticMethod(jclass cls, const char* methodName, const char* methodSignature, ...)
+{
+ JavaVM *jvm = getJavaVM();
+ JNIEnv *env = getJNIEnv();
+ va_list args;
+
+ va_start(args, methodSignature);
+
+ T result = 0;
+
+ if (cls != NULL && jvm != NULL && env != NULL) {
+ jmethodID mid = env->GetStaticMethodID(cls, methodName, methodSignature);
+ if (mid != NULL)
+ result = JNICaller<T>::callStaticV(cls, mid, args);
+ else {
+ fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, methodName, cls);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ fprintf (stderr, "\n");
+ }
+ }
+
+ va_end(args);
+
+ return result;
+}
+
+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/mac/AXObjectCacheMac.mm b/WebCore/bridge/mac/AXObjectCacheMac.mm
deleted file mode 100644
index 61d0319..0000000
--- a/WebCore/bridge/mac/AXObjectCacheMac.mm
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2003, 2004, 2005, 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 "config.h"
-#import "AXObjectCache.h"
-
-#import "Document.h"
-#import "FoundationExtras.h"
-#import "RenderObject.h"
-#import "WebCoreAXObject.h"
-#import "WebCoreViewFactory.h"
-
-// The simple Cocoa calls in this file don't throw exceptions.
-
-namespace WebCore {
-
-struct TextMarkerData {
- AXID axID;
- Node* node;
- int offset;
- EAffinity affinity;
-};
-
-bool AXObjectCache::gAccessibilityEnabled = false;
-
-AXObjectCache::~AXObjectCache()
-{
- HashMap<RenderObject*, WebCoreAXObject*>::iterator end = m_objects.end();
- for (HashMap<RenderObject*, WebCoreAXObject*>::iterator it = m_objects.begin(); it != end; ++it) {
- WebCoreAXObject* obj = (*it).second;
- [obj detach];
- HardRelease(obj);
- }
-}
-
-WebCoreAXObject* AXObjectCache::get(RenderObject* renderer)
-{
- WebCoreAXObject* obj = m_objects.get(renderer);
- if (obj)
- return obj;
-
- obj = [[WebCoreAXObject alloc] initWithRenderer:renderer];
- HardRetainWithNSRelease(obj);
- m_objects.set(renderer, obj);
- return obj;
-}
-
-void AXObjectCache::remove(RenderObject* renderer)
-{
- WebCoreAXObject* obj = m_objects.take(renderer);
- if (!obj)
- return;
- [obj detach];
- HardRelease(obj);
-
- ASSERT(m_objects.size() >= m_idsInUse.size());
-}
-
-AXID AXObjectCache::getAXID(WebCoreAXObject* obj)
-{
- // check for already-assigned ID
- AXID objID = [obj axObjectID];
- if (objID) {
- ASSERT(m_idsInUse.contains(objID));
- return objID;
- }
-
- // generate a new ID
- static AXID lastUsedID = 0;
- objID = lastUsedID;
- do
- ++objID;
- while (objID == 0 || objID == AXIDHashTraits::deletedValue() || m_idsInUse.contains(objID));
- m_idsInUse.add(objID);
- lastUsedID = objID;
- [obj setAXObjectID:objID];
-
- return objID;
-}
-
-void AXObjectCache::removeAXID(WebCoreAXObject* obj)
-{
- AXID objID = [obj axObjectID];
- if (objID == 0)
- return;
- ASSERT(objID != AXIDHashTraits::deletedValue());
- ASSERT(m_idsInUse.contains(objID));
- [obj setAXObjectID:0];
- m_idsInUse.remove(objID);
-}
-
-WebCoreTextMarker* AXObjectCache::textMarkerForVisiblePosition(const VisiblePosition& visiblePos)
-{
- Position deepPos = visiblePos.deepEquivalent();
- Node* domNode = deepPos.node();
- ASSERT(domNode);
- if (!domNode)
- return nil;
-
- // locate the renderer, which must exist for a visible dom node
- RenderObject* renderer = domNode->renderer();
- ASSERT(renderer);
-
- // find or create an accessibility object for this renderer
- WebCoreAXObject* obj = get(renderer);
-
- // create a text marker, adding an ID for the WebCoreAXObject if needed
- TextMarkerData textMarkerData;
- textMarkerData.axID = getAXID(obj);
- textMarkerData.node = domNode;
- textMarkerData.offset = deepPos.offset();
- textMarkerData.affinity = visiblePos.affinity();
- return [[WebCoreViewFactory sharedFactory] textMarkerWithBytes:&textMarkerData length:sizeof(textMarkerData)];
-}
-
-VisiblePosition AXObjectCache::visiblePositionForTextMarker(WebCoreTextMarker* textMarker)
-{
- TextMarkerData textMarkerData;
-
- if (![[WebCoreViewFactory sharedFactory] getBytes:&textMarkerData fromTextMarker:textMarker length:sizeof(textMarkerData)])
- return VisiblePosition();
-
- // return empty position if the text marker is no longer valid
- if (!m_idsInUse.contains(textMarkerData.axID))
- return VisiblePosition();
-
- // generate a VisiblePosition from the data we stored earlier
- VisiblePosition visiblePos = VisiblePosition(textMarkerData.node, textMarkerData.offset, textMarkerData.affinity);
-
- // make sure the node and offset still match (catches stale markers). affinity is not critical for this.
- Position deepPos = visiblePos.deepEquivalent();
- if (deepPos.node() != textMarkerData.node || deepPos.offset() != textMarkerData.offset)
- return VisiblePosition();
-
- return visiblePos;
-}
-
-void AXObjectCache::childrenChanged(RenderObject* renderer)
-{
- WebCoreAXObject* obj = m_objects.get(renderer);
- if (obj)
- [obj childrenChanged];
-}
-
-void AXObjectCache::postNotification(RenderObject* renderer, const String& message)
-{
- if (!renderer)
- return;
-
- // notifications for text input objects are sent to that object
- // all others are sent to the top WebArea
- WebCoreAXObject* obj = [get(renderer) observableObject];
- if (obj)
- NSAccessibilityPostNotification(obj, message);
- else
- NSAccessibilityPostNotification(get(renderer->document()->renderer()), message);
-}
-
-void AXObjectCache::postNotificationToElement(RenderObject* renderer, const String& message)
-{
- // send the notification to the specified element itself, not one of its ancestors
- if (renderer)
- NSAccessibilityPostNotification(get(renderer), message);
-}
-
-void AXObjectCache::handleFocusedUIElementChanged()
-{
- [[WebCoreViewFactory sharedFactory] accessibilityHandleFocusChanged];
-}
-
-}
diff --git a/WebCore/bridge/mac/WebCoreAXObject.mm b/WebCore/bridge/mac/WebCoreAXObject.mm
deleted file mode 100644
index bc5efda..0000000
--- a/WebCore/bridge/mac/WebCoreAXObject.mm
+++ /dev/null
@@ -1,2744 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "config.h"
-#import "WebCoreAXObject.h"
-
-#import "DOMInternal.h"
-#import "ColorMac.h"
-#import "Document.h"
-#import "EventNames.h"
-#import "FocusController.h"
-#import "Frame.h"
-#import "FrameLoader.h"
-#import "FrameView.h"
-#import "HTMLAreaElement.h"
-#import "HTMLCollection.h"
-#import "HTMLFrameElementBase.h"
-#import "HTMLImageElement.h"
-#import "HTMLInputElement.h"
-#import "HTMLLabelElement.h"
-#import "HTMLMapElement.h"
-#import "HTMLNames.h"
-#import "HTMLSelectElement.h"
-#import "HTMLTextAreaElement.h"
-#import "HitTestRequest.h"
-#import "HitTestResult.h"
-#import "LocalizedStrings.h"
-#import "NodeList.h"
-#import "Page.h"
-#import "RenderImage.h"
-#import "RenderListMarker.h"
-#import "RenderMenuList.h"
-#import "RenderTextControl.h"
-#import "RenderTheme.h"
-#import "RenderView.h"
-#import "RenderWidget.h"
-#import "SelectionController.h"
-#import "SimpleFontData.h"
-#import "TextIterator.h"
-#import "WebCoreFrameBridge.h"
-#import "WebCoreFrameView.h"
-#import "WebCoreObjCExtras.h"
-#import "WebCoreViewFactory.h"
-#import "htmlediting.h"
-#import "kjs_html.h"
-#import "visible_units.h"
-#include <mach-o/dyld.h>
-
-using namespace WebCore;
-using namespace EventNames;
-using namespace HTMLNames;
-
-@interface WebCoreAXObject (PrivateWebCoreAXObject)
-// forward declarations as needed
-- (WebCoreTextMarker*)textMarkerForIndex: (NSNumber*) index lastIndexOK: (BOOL)lastIndexOK;
-- (id)doAXLineForTextMarker: (WebCoreTextMarker* ) textMarker;
-@end
-
-@implementation WebCoreAXObject
-
-#ifndef BUILDING_ON_TIGER
-+ (void)initialize
-{
- WebCoreObjCFinalizeOnMainThread(self);
-}
-#endif
-
--(id)initWithRenderer:(RenderObject*)renderer
-{
- [super init];
- m_renderer = renderer;
- return self;
-}
-
--(BOOL)detached
-{
- return !m_renderer;
-}
-
--(void)detach
-{
- // Send unregisterUniqueIdForUIElement unconditionally because if it is
- // ever accidently not done (via other bugs in our AX implementation) you
- // end up with a crash like <rdar://problem/4273149>. It is safe and not
- // expensive to send even if the object is not registered.
- [[WebCoreViewFactory sharedFactory] unregisterUniqueIdForUIElement:self];
- [m_data release];
- m_data = 0;
- [self removeAXObjectID];
- m_renderer = 0;
- [self clearChildren];
-}
-
-- (void)dealloc
-{
- [self detach];
- [super dealloc];
-}
-
-- (void)finalize
-{
- [self detach];
- [super finalize];
-}
-
--(id)data
-{
- return m_data;
-}
-
--(void)setData:(id)data
-{
- if (!m_renderer)
- return;
-
- [data retain];
- [m_data release];
- m_data = data;
-}
-
--(HTMLAnchorElement*)anchorElement
-{
- // return already-known anchor for image areas
- if (m_areaElement)
- return m_areaElement;
-
- // search up the render tree for a RenderObject with a DOM node. Defer to an earlier continuation, though.
- RenderObject* currRenderer;
- for (currRenderer = m_renderer; currRenderer && !currRenderer->element(); currRenderer = currRenderer->parent()) {
- if (currRenderer->continuation())
- return [currRenderer->document()->axObjectCache()->get(currRenderer->continuation()) anchorElement];
- }
-
- // bail of none found
- if (!currRenderer)
- return 0;
-
- // search up the DOM tree for an anchor element
- // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
- Node* elt = currRenderer->element();
- for ( ; elt; elt = elt->parentNode()) {
- if (elt->isLink() && elt->renderer() && !elt->renderer()->isImage())
- return static_cast<HTMLAnchorElement*>(elt);
- }
-
- return 0;
-}
-
--(BOOL)isImageButton
-{
- return m_renderer->isImage() && m_renderer->element() && m_renderer->element()->hasTagName(inputTag);
-}
-
--(Element*)mouseButtonListener
-{
- // FIXME: Do the continuation search like anchorElement does
- for (EventTargetNode* elt = static_cast<EventTargetNode*>(m_renderer->element()); elt; elt = static_cast<EventTargetNode*>(elt->parentNode())) {
- if (elt->getHTMLEventListener(clickEvent) || elt->getHTMLEventListener(mousedownEvent) || elt->getHTMLEventListener(mouseupEvent))
- return static_cast<Element*>(elt);
- }
-
- return 0;
-}
-
--(Element*)actionElement
-{
- if (m_renderer->element() && m_renderer->element()->hasTagName(inputTag)) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
- if (!input->disabled() && (input->inputType() == HTMLInputElement::CHECKBOX ||
- input->inputType() == HTMLInputElement::RADIO ||
- input->isTextButton()))
- return input;
- }
-
- if ([self isImageButton] || m_renderer->isMenuList())
- return static_cast<Element*>(m_renderer->element());
-
- Element* elt = [self anchorElement];
- if (!elt)
- elt = [self mouseButtonListener];
-
- return elt;
-}
-
--(WebCoreAXObject*)firstChild
-{
- if (!m_renderer || !m_renderer->firstChild())
- return nil;
-
- return m_renderer->document()->axObjectCache()->get(m_renderer->firstChild());
-}
-
--(WebCoreAXObject*)lastChild
-{
- if (!m_renderer || !m_renderer->lastChild())
- return nil;
-
- return m_renderer->document()->axObjectCache()->get(m_renderer->lastChild());
-}
-
--(WebCoreAXObject*)previousSibling
-{
- if (!m_renderer || !m_renderer->previousSibling())
- return nil;
-
- return m_renderer->document()->axObjectCache()->get(m_renderer->previousSibling());
-}
-
--(WebCoreAXObject*)nextSibling
-{
- if (!m_renderer || !m_renderer->nextSibling())
- return nil;
-
- return m_renderer->document()->axObjectCache()->get(m_renderer->nextSibling());
-}
-
--(WebCoreAXObject*)parentObject
-{
- if (m_areaElement)
- return m_renderer->document()->axObjectCache()->get(m_renderer);
-
- if (!m_renderer || !m_renderer->parent())
- return nil;
-
- return m_renderer->document()->axObjectCache()->get(m_renderer->parent());
-}
-
--(WebCoreAXObject*)parentObjectUnignored
-{
- WebCoreAXObject* obj = [self parentObject];
- if ([obj accessibilityIsIgnored])
- return [obj parentObjectUnignored];
-
- return obj;
-}
-
--(void)addChildrenToArray:(NSMutableArray*)array
-{
- // nothing to add if there is no RenderObject
- if (!m_renderer)
- return;
-
- // try to add RenderWidget's children, but fall thru if there are none
- if (m_renderer->isWidget()) {
- RenderWidget* renderWidget = static_cast<RenderWidget*>(m_renderer);
- Widget* widget = renderWidget->widget();
- if (widget) {
- NSArray* childArr = [(widget->getOuterView()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
- [array addObjectsFromArray: childArr];
- return;
- }
- }
-
- // add all unignored acc children
- for (WebCoreAXObject* obj = [self firstChild]; obj; obj = [obj nextSibling]) {
- if ([obj accessibilityIsIgnored])
- [obj addChildrenToArray: array];
- else
- [array addObject: obj];
- }
-
- // for a RenderImage, add the <area> elements as individual accessibility objects
- if (m_renderer->isImage() && !m_areaElement) {
- HTMLMapElement* map = static_cast<RenderImage*>(m_renderer)->imageMap();
- if (map) {
- for (Node* current = map->firstChild(); current; current = current->traverseNextNode(map)) {
- // add an <area> element for this child if it has a link
- // NOTE: can't cache these because they all have the same renderer, which is the cache key, right?
- // plus there may be little reason to since they are being added to the handy array
- if (current->isLink()) {
- WebCoreAXObject* obj = [[[WebCoreAXObject alloc] initWithRenderer: m_renderer] autorelease];
- obj->m_areaElement = static_cast<HTMLAreaElement*>(current);
- [array addObject: obj];
- }
- }
- }
- }
-}
-
--(BOOL)isWebArea
-{
- return m_renderer->isRenderView();
-}
-
--(BOOL)isAnchor
-{
- return m_areaElement || (!m_renderer->isImage() && m_renderer->element() && m_renderer->element()->isLink());
-}
-
--(BOOL)isTextControl
-{
- return m_renderer->isTextField() || m_renderer->isTextArea();
-}
-
-static bool isPasswordFieldElement(Node* node)
-{
- if (!node || !node->hasTagName(inputTag))
- return false;
-
- HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
- return input->inputType() == HTMLInputElement::PASSWORD;
-}
-
--(BOOL)isPasswordField
-{
- return m_renderer && isPasswordFieldElement(m_renderer->element());
-}
-
--(BOOL)isAttachment
-{
- // widgets are the replaced elements that we represent to AX as attachments
- BOOL result = m_renderer && m_renderer->isWidget();
-
- // assert that a widget is a replaced element that is not an image
- ASSERT(!result || (m_renderer->isReplaced() && !m_renderer->isImage()));
- return result;
-}
-
--(NSView*)attachmentView
-{
- ASSERT(m_renderer->isReplaced() && m_renderer->isWidget() && !m_renderer->isImage());
-
- RenderWidget* renderWidget = static_cast<RenderWidget*>(m_renderer);
- Widget* widget = renderWidget->widget();
- if (widget)
- return widget->getView();
-
- return nil;
-}
-
-static int blockquoteLevel(RenderObject* renderer)
-{
- int result = 0;
- for (Node* node = renderer->element(); node; node = node->parent()) {
- if (node->hasTagName(blockquoteTag))
- result += 1;
- }
-
- return result;
-}
-
-static int headingLevel(RenderObject* renderer)
-{
- if (!renderer->isBlockFlow())
- return 0;
-
- Node* node = renderer->element();
- if (!node)
- return 0;
-
- if (node->hasTagName(h1Tag))
- return 1;
-
- if (node->hasTagName(h2Tag))
- return 2;
-
- if (node->hasTagName(h3Tag))
- return 3;
-
- if (node->hasTagName(h4Tag))
- return 4;
-
- if (node->hasTagName(h5Tag))
- return 5;
-
- if (node->hasTagName(h6Tag))
- return 6;
-
- return 0;
-}
-
--(int)headingLevel
-{
- return headingLevel(m_renderer);
-}
-
--(BOOL)isHeading
-{
- return [self headingLevel] != 0;
-}
-
--(NSString*)role
-{
- if (!m_renderer)
- return NSAccessibilityUnknownRole;
-
- if (m_areaElement)
- return @"AXLink";
- if (m_renderer->element() && m_renderer->element()->isLink()) {
- if (m_renderer->isImage())
- return @"AXImageMap";
- return @"AXLink";
- }
- if (m_renderer->isListMarker())
- return @"AXListMarker";
- if (m_renderer->element() && m_renderer->element()->hasTagName(buttonTag))
- return NSAccessibilityButtonRole;
- if (m_renderer->isText())
- return NSAccessibilityStaticTextRole;
- if (m_renderer->isImage()) {
- if ([self isImageButton])
- return NSAccessibilityButtonRole;
- return NSAccessibilityImageRole;
- }
- if ([self isWebArea])
- return @"AXWebArea";
-
- if (m_renderer->isTextField())
- return NSAccessibilityTextFieldRole;
-
- if (m_renderer->isTextArea())
- return NSAccessibilityTextAreaRole;
-
- if (m_renderer->element() && m_renderer->element()->hasTagName(inputTag)) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
- if (input->inputType() == HTMLInputElement::CHECKBOX)
- return NSAccessibilityCheckBoxRole;
- if (input->inputType() == HTMLInputElement::RADIO)
- return NSAccessibilityRadioButtonRole;
- if (input->isTextButton())
- return NSAccessibilityButtonRole;
- }
-
- if (m_renderer->isMenuList())
- return NSAccessibilityPopUpButtonRole;
-
- if ([self isHeading])
- return @"AXHeading";
-
- if (m_renderer->isBlockFlow())
- return NSAccessibilityGroupRole;
- if ([self isAttachment])
- return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
-
- return NSAccessibilityUnknownRole;
-}
-
--(NSString*)subrole
-{
- if ([self isPasswordField])
- return NSAccessibilitySecureTextFieldSubrole;
-
- if ([self isAttachment]) {
- NSView* attachmentView = [self attachmentView];
- if ([[attachmentView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {
- return [attachmentView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
- }
- }
-
- return nil;
-}
-
--(NSString*)roleDescription
-{
- if (!m_renderer)
- return nil;
-
- // attachments have the AXImage role, but a different subrole
- if ([self isAttachment])
- return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
-
- // FIXME 3447564: It would be better to call some AppKit API to get these strings
- // (which would be the best way to localize them)
-
- NSString* role = [self role];
- if ([role isEqualToString:NSAccessibilityButtonRole])
- return NSAccessibilityRoleDescription(NSAccessibilityButtonRole, [self subrole]);
-
- if ([role isEqualToString:NSAccessibilityPopUpButtonRole])
- return NSAccessibilityRoleDescription(NSAccessibilityPopUpButtonRole, [self subrole]);
-
- if ([role isEqualToString:NSAccessibilityStaticTextRole])
- return NSAccessibilityRoleDescription(NSAccessibilityStaticTextRole, [self subrole]);
-
- if ([role isEqualToString:NSAccessibilityImageRole])
- return NSAccessibilityRoleDescription(NSAccessibilityImageRole, [self subrole]);
-
- if ([role isEqualToString:NSAccessibilityGroupRole])
- return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
-
- if ([role isEqualToString:NSAccessibilityCheckBoxRole])
- return NSAccessibilityRoleDescription(NSAccessibilityCheckBoxRole, [self subrole]);
-
- if ([role isEqualToString:NSAccessibilityRadioButtonRole])
- return NSAccessibilityRoleDescription(NSAccessibilityRadioButtonRole, [self subrole]);
-
- if ([role isEqualToString:NSAccessibilityTextFieldRole])
- return NSAccessibilityRoleDescription(NSAccessibilityTextFieldRole, [self subrole]);
-
- if ([role isEqualToString:NSAccessibilityTextAreaRole])
- return NSAccessibilityRoleDescription(NSAccessibilityTextAreaRole, [self subrole]);
-
- if ([role isEqualToString:@"AXWebArea"])
- return AXWebAreaText();
-
- if ([role isEqualToString:@"AXLink"])
- return AXLinkText();
-
- if ([role isEqualToString:@"AXListMarker"])
- return AXListMarkerText();
-
- if ([role isEqualToString:@"AXImageMap"])
- return AXImageMapText();
-
- if ([role isEqualToString:@"AXHeading"])
- return AXHeadingText();
-
- return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
-}
-
--(NSString*)helpText
-{
- if (!m_renderer)
- return nil;
-
- if (m_areaElement) {
- const AtomicString& summary = static_cast<Element*>(m_areaElement)->getAttribute(summaryAttr);
- if (!summary.isEmpty())
- return summary;
- const AtomicString& title = static_cast<Element*>(m_areaElement)->getAttribute(titleAttr);
- if (!title.isEmpty())
- return title;
- }
-
- for (RenderObject* curr = m_renderer; curr; curr = curr->parent()) {
- if (curr->element() && curr->element()->isHTMLElement()) {
- const AtomicString& summary = static_cast<Element*>(curr->element())->getAttribute(summaryAttr);
- if (!summary.isEmpty())
- return summary;
- const AtomicString& title = static_cast<Element*>(curr->element())->getAttribute(titleAttr);
- if (!title.isEmpty())
- return title;
- }
- }
-
- return nil;
-}
-
--(NSString*)textUnderElement
-{
- if (!m_renderer)
- return nil;
-
- Node* e = m_renderer->element();
- Document* d = m_renderer->document();
- if (e && d) {
- Frame* p = d->frame();
- if (p) {
- // catch stale WebCoreAXObject (see <rdar://problem/3960196>)
- if (p->document() != d)
- return nil;
- return plainText(rangeOfContents(e).get());
- }
- }
-
- // return nil for anonymous text because it is non-trivial to get
- // the actual text and, so far, that is not needed
- return nil;
-}
-
--(id)value
-{
- if (!m_renderer || m_areaElement || [self isPasswordField])
- return nil;
-
- if (m_renderer->isText())
- return [self textUnderElement];
-
- if (m_renderer->isMenuList())
- return static_cast<RenderMenuList*>(m_renderer)->text();
-
- if (m_renderer->isListMarker())
- return static_cast<RenderListMarker*>(m_renderer)->text();
-
- if ([self isWebArea]) {
- if (m_renderer->document()->frame())
- return nil;
-
- // FIXME: should use startOfDocument and endOfDocument (or rangeForDocument?) here
- VisiblePosition startVisiblePosition = m_renderer->positionForCoordinates(0, 0);
- VisiblePosition endVisiblePosition = m_renderer->positionForCoordinates(INT_MAX, INT_MAX);
- if (startVisiblePosition.isNull() || endVisiblePosition.isNull())
- return nil;
-
- return plainText(makeRange(startVisiblePosition, endVisiblePosition).get());
- }
-
- if ([self isAttachment]) {
- NSView* attachmentView = [self attachmentView];
- if ([[attachmentView accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])
- return [attachmentView accessibilityAttributeValue:NSAccessibilityValueAttribute];
- return nil;
- }
-
- if ([self isHeading])
- return [NSNumber numberWithInt:[self headingLevel]];
-
- if ([self isTextControl])
- return (NSString*)(static_cast<RenderTextControl*>(m_renderer)->text());
-
- if (m_renderer->element() && m_renderer->element()->hasTagName(inputTag)) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
-
- // Checkboxes return their state as an integer. 0 for off, 1 for on.
- if (input->inputType() == HTMLInputElement::CHECKBOX ||
- input->inputType() == HTMLInputElement::RADIO)
- return [NSNumber numberWithInt:input->checked()];
- }
-
- // FIXME: We might need to implement a value here for more types
- // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
- // this would require subclassing or making accessibilityAttributeNames do something other than return a
- // single static array.
- return nil;
-}
-
-static HTMLLabelElement* labelForElement(Element* element)
-{
- RefPtr<NodeList> list = element->document()->getElementsByTagName("label");
- unsigned len = list->length();
- for (unsigned i = 0; i < len; i++) {
- HTMLLabelElement* label = static_cast<HTMLLabelElement*>(list->item(i));
- if (label->correspondingControl() == element)
- return label;
- }
-
- return 0;
-}
-
--(NSString*)title
-{
- if (!m_renderer || m_areaElement || !m_renderer->element())
- return nil;
-
- if (m_renderer->element()->hasTagName(buttonTag))
- return [self textUnderElement];
-
- if (m_renderer->element()->hasTagName(inputTag)) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
- if (input->isTextButton())
- return input->value();
-
- HTMLLabelElement* label = labelForElement(input);
- if (label)
- return label->innerText();
- }
-
- if (m_renderer->element()->isLink() || [self isHeading])
- return [self textUnderElement];
-
- if ([self isAttachment]) {
- NSView* attachmentView = [self attachmentView];
- if ([[attachmentView accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])
- return [attachmentView accessibilityAttributeValue:NSAccessibilityTitleAttribute];
- }
-
- return nil;
-}
-
-- (NSString*)accessibilityDescription
-{
- if (!m_renderer || m_areaElement)
- return nil;
-
- if (m_renderer->isImage()) {
- if (m_renderer->element() && m_renderer->element()->isHTMLElement()) {
- const AtomicString& alt = static_cast<Element*>(m_renderer->element())->getAttribute(altAttr);
- if (alt.isEmpty())
- return nil;
- return alt;
- }
- } else if ([self isAttachment]) {
- NSView* attachmentView = [self attachmentView];
- if ([[attachmentView accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
- return [attachmentView accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
- }
-
- if ([self isWebArea]) {
- Document *document = m_renderer->document();
- Node* owner = document->ownerElement();
- if (owner) {
- if (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag)) {
- HTMLFrameElementBase* frameElement = static_cast<HTMLFrameElementBase*>(owner);
- return frameElement->name();
- } else if (owner->isHTMLElement()) {
- return static_cast<Element*>(owner)->getAttribute(nameAttr);
- }
- } else {
- owner = document->body();
- if (owner && owner->isHTMLElement())
- return static_cast<Element*>(owner)->getAttribute(nameAttr);
- }
- }
-
- return nil;
-}
-
-static IntRect boundingBoxRect(RenderObject* obj)
-{
- IntRect rect;
- if (obj) {
- if (obj->isInlineContinuation())
- obj = obj->element()->renderer();
- Vector<IntRect> rects;
- int x, y;
- obj->absolutePosition(x, y);
- obj->absoluteRects(rects, x, y);
- const size_t n = rects.size();
- for (size_t i = 0; i < n; ++i) {
- IntRect r = rects[i];
- if (!r.isEmpty()) {
- if (obj->style()->hasAppearance())
- theme()->adjustRepaintRect(obj, r);
- rect.unite(r);
- }
- }
- }
- return rect;
-}
-
--(NSValue*)position
-{
- IntRect rect = m_areaElement ? m_areaElement->getRect(m_renderer) : boundingBoxRect(m_renderer);
-
- // The Cocoa accessibility API wants the lower-left corner.
- NSPoint point = NSMakePoint(rect.x(), rect.bottom());
- if (m_renderer && m_renderer->view() && m_renderer->view()->frameView()) {
- NSView* view = m_renderer->view()->frameView()->getDocumentView();
- point = [[view window] convertBaseToScreen: [view convertPoint: point toView:nil]];
- }
-
- return [NSValue valueWithPoint: point];
-}
-
--(NSValue*)size
-{
- IntRect rect = m_areaElement ? m_areaElement->getRect(m_renderer) : boundingBoxRect(m_renderer);
- return [NSValue valueWithSize: NSMakeSize(rect.width(), rect.height())];
-}
-
-// accessibilityShouldUseUniqueId is an AppKit method we override so that
-// objects will be given a unique ID, and therefore allow AppKit to know when they
-// become obsolete (e.g. when the user navigates to a new web page, making this one
-// unrendered but not deallocated because it is in the back/forward cache).
-// It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the
-// appropriate place (e.g. dealloc) to remove these non-retained references from
-// AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.
-//
-// Registering an object is also required for observing notifications. Only registered objects can be observed.
-- (BOOL)accessibilityShouldUseUniqueId {
- if (!m_renderer)
- return NO;
-
- if ([self isWebArea])
- return YES;
-
- if ([self isTextControl])
- return YES;
-
- return NO;
-}
-
--(BOOL)accessibilityIsIgnored
-{
- // ignore invisible element
- if (!m_renderer || m_renderer->style()->visibility() != VISIBLE)
- return YES;
-
- // ignore popup menu items because AppKit does
- for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
- if (parent->isMenuList())
- return YES;
- }
-
- // NOTE: BRs always have text boxes now, so the text box check here can be removed
- if (m_renderer->isText())
- return m_renderer->isBR() || !static_cast<RenderText*>(m_renderer)->firstTextBox();
-
- // delegate to the attachment
- if ([self isAttachment])
- return [[self attachmentView] accessibilityIsIgnored];
-
- if (m_areaElement || (m_renderer->element() && m_renderer->element()->isLink()))
- return NO;
-
- // all controls are accessible
- if (m_renderer->element() && m_renderer->element()->isControl())
- return NO;
-
- if (m_renderer->isBlockFlow() && m_renderer->childrenInline())
- return !static_cast<RenderBlock*>(m_renderer)->firstLineBox() && ![self mouseButtonListener];
-
- // ignore images seemingly used as spacers
- if (m_renderer->isImage()) {
- // informal standard is to ignore images with zero-length alt strings
- Element* elt = static_cast<Element*>(m_renderer->element());
- if (elt) {
- const AtomicString& alt = elt->getAttribute(altAttr);
- if (alt.isEmpty() && !alt.isNull())
- return YES;
- }
-
- // check for one-dimensional image
- if (m_renderer->height() <= 1 || m_renderer->width() <= 1)
- return YES;
-
- // check whether rendered image was stretched from one-dimensional file image
- RenderImage* image = static_cast<RenderImage*>(m_renderer);
- if (image->cachedImage()) {
- IntSize imageSize = image->cachedImage()->imageSize();
- return (imageSize.height() <= 1 || imageSize.width() <= 1);
- }
-
- return NO;
- }
-
- return (!m_renderer->isListMarker() && ![self isWebArea]);
-}
-
-- (NSArray*)accessibilityAttributeNames
-{
- if ([self isAttachment])
- return [[self attachmentView] accessibilityAttributeNames];
-
- static NSArray* attributes = nil;
- static NSArray* anchorAttrs = nil;
- static NSArray* webAreaAttrs = nil;
- static NSArray* textAttrs = nil;
- NSMutableArray* tempArray;
- if (attributes == nil) {
- attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
- NSAccessibilitySubroleAttribute,
- NSAccessibilityRoleDescriptionAttribute,
- NSAccessibilityChildrenAttribute,
- NSAccessibilityHelpAttribute,
- NSAccessibilityParentAttribute,
- NSAccessibilityPositionAttribute,
- NSAccessibilitySizeAttribute,
- NSAccessibilityTitleAttribute,
- NSAccessibilityDescriptionAttribute,
- NSAccessibilityValueAttribute,
- NSAccessibilityFocusedAttribute,
- NSAccessibilityEnabledAttribute,
- NSAccessibilityWindowAttribute,
- @"AXSelectedTextMarkerRange",
- @"AXStartTextMarker",
- @"AXEndTextMarker",
- @"AXVisited",
- nil];
- }
- if (anchorAttrs == nil) {
- tempArray = [[NSMutableArray alloc] initWithArray:attributes];
- [tempArray addObject: NSAccessibilityURLAttribute];
- anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
- [tempArray release];
- }
- if (webAreaAttrs == nil) {
- tempArray = [[NSMutableArray alloc] initWithArray:attributes];
- [tempArray addObject: @"AXLinkUIElements"];
- [tempArray addObject: @"AXLoaded"];
- [tempArray addObject: @"AXLayoutCount"];
- webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
- [tempArray release];
- }
- if (textAttrs == nil) {
- tempArray = [[NSMutableArray alloc] initWithArray:attributes];
- [tempArray addObject: NSAccessibilityNumberOfCharactersAttribute];
- [tempArray addObject: NSAccessibilitySelectedTextAttribute];
- [tempArray addObject: NSAccessibilitySelectedTextRangeAttribute];
- [tempArray addObject: NSAccessibilityVisibleCharacterRangeAttribute];
- [tempArray addObject: NSAccessibilityInsertionPointLineNumberAttribute];
- textAttrs = [[NSArray alloc] initWithArray:tempArray];
- [tempArray release];
- }
-
- if (!m_renderer || [self isPasswordField])
- return attributes;
-
- if ([self isWebArea])
- return webAreaAttrs;
-
- if ([self isTextControl])
- return textAttrs;
-
- if ([self isAnchor] || m_renderer->isImage())
- return anchorAttrs;
-
- return attributes;
-}
-
-- (NSArray*)accessibilityActionNames
-{
- static NSArray* actions = nil;
-
- if (actions == nil) {
- if ([self actionElement])
- actions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, nil];
- else if ([self isAttachment])
- actions = [[[self attachmentView] accessibilityActionNames] retain];
- }
-
- return actions;
-}
-
-- (NSString*)accessibilityActionDescription:(NSString*)action
-{
- // we have no custom actions
- return NSAccessibilityActionDescription(action);
-}
-
-- (void)accessibilityPerformAction:(NSString*)action
-{
- if ([action isEqualToString:NSAccessibilityPressAction]) {
- if ([self isAttachment]) {
- [[self attachmentView] accessibilityPerformAction:action];
- return;
- }
-
- Element* actionElement = [self actionElement];
- if (!actionElement)
- return;
- if (Frame* f = actionElement->document()->frame())
- f->loader()->resetMultipleFormSubmissionProtection();
- actionElement->accessKeyAction(true);
- }
-}
-
-- (WebCoreTextMarkerRange*) textMarkerRangeFromMarkers: (WebCoreTextMarker*) textMarker1 andEndMarker:(WebCoreTextMarker*) textMarker2
-{
- return [[WebCoreViewFactory sharedFactory] textMarkerRangeWithStart:textMarker1 end:textMarker2];
-}
-
-- (WebCoreTextMarker*) textMarkerForVisiblePosition: (VisiblePosition)visiblePos
-{
- if (visiblePos.isNull())
- return nil;
-
- if (isPasswordFieldElement(visiblePos.deepEquivalent().node()))
- return nil;
-
- return m_renderer->document()->axObjectCache()->textMarkerForVisiblePosition(visiblePos);
-}
-
-- (VisiblePosition) visiblePositionForTextMarker: (WebCoreTextMarker*)textMarker
-{
- return m_renderer->document()->axObjectCache()->visiblePositionForTextMarker(textMarker);
-}
-
-- (VisiblePosition) visiblePositionForStartOfTextMarkerRange: (WebCoreTextMarkerRange*)textMarkerRange
-{
- return [self visiblePositionForTextMarker:[[WebCoreViewFactory sharedFactory] startOfTextMarkerRange:textMarkerRange]];
-}
-
-- (VisiblePosition) visiblePositionForEndOfTextMarkerRange: (WebCoreTextMarkerRange*) textMarkerRange
-{
- return [self visiblePositionForTextMarker:[[WebCoreViewFactory sharedFactory] endOfTextMarkerRange:textMarkerRange]];
-}
-
-- (WebCoreTextMarkerRange*) textMarkerRangeFromVisiblePositions: (VisiblePosition) startPosition andEndPos: (VisiblePosition) endPosition
-{
- WebCoreTextMarker* startTextMarker = [self textMarkerForVisiblePosition: startPosition];
- WebCoreTextMarker* endTextMarker = [self textMarkerForVisiblePosition: endPosition];
- return [self textMarkerRangeFromMarkers: startTextMarker andEndMarker:endTextMarker];
-}
-
-- (WebCoreTextMarkerRange*)textMarkerRange
-{
- if (!m_renderer)
- return nil;
-
- // construct VisiblePositions for start and end
- Node* node = m_renderer->element();
- VisiblePosition visiblePos1 = VisiblePosition(node, 0, VP_DEFAULT_AFFINITY);
- VisiblePosition visiblePos2 = VisiblePosition(node, maxDeepOffset(node), VP_DEFAULT_AFFINITY);
-
- // the VisiblePositions are equal for nodes like buttons, so adjust for that
- if (visiblePos1 == visiblePos2) {
- visiblePos2 = visiblePos2.next();
- if (visiblePos2.isNull())
- visiblePos2 = visiblePos1;
- }
-
- WebCoreTextMarker* startTextMarker = [self textMarkerForVisiblePosition: visiblePos1];
- WebCoreTextMarker* endTextMarker = [self textMarkerForVisiblePosition: visiblePos2];
- return [self textMarkerRangeFromMarkers: startTextMarker andEndMarker:endTextMarker];
-}
-
-- (RenderObject*)topRenderer
-{
- return m_renderer->document()->topDocument()->renderer();
-}
-
-- (FrameView*)frameView
-{
- return m_renderer->document()->view();
-}
-
-- (FrameView*)topFrameView
-{
- return m_renderer->document()->topDocument()->renderer()->view()->frameView();
-}
-
-- (id)accessibilityAttributeValue:(NSString*)attributeName
-{
- if (!m_renderer)
- return nil;
-
- if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
- return [self role];
-
- if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
- return [self subrole];
-
- if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
- return [self roleDescription];
-
- if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
- if (m_renderer->isRenderView() && m_renderer->view() && m_renderer->view()->frameView())
- return m_renderer->view()->frameView()->getView();
- return [self parentObjectUnignored];
- }
-
- if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
- if (!m_children) {
- m_children = [NSMutableArray arrayWithCapacity: 8];
- [m_children retain];
- [self addChildrenToArray: m_children];
- }
- return m_children;
- }
-
- if ([self isWebArea]) {
- if ([attributeName isEqualToString: @"AXLinkUIElements"]) {
- NSMutableArray* links = [NSMutableArray arrayWithCapacity: 32];
- RefPtr<HTMLCollection> coll = m_renderer->document()->links();
- Node* curr = coll->firstItem();
- while (curr) {
- RenderObject* obj = curr->renderer();
- if (obj) {
- WebCoreAXObject* axobj = obj->document()->axObjectCache()->get(obj);
- ASSERT([[axobj role] isEqualToString:@"AXLink"]);
- if (![axobj accessibilityIsIgnored])
- [links addObject: axobj];
- }
- curr = coll->nextItem();
- }
- return links;
- }
- if ([attributeName isEqualToString: @"AXLoaded"])
- return [NSNumber numberWithBool: (!m_renderer->document()->tokenizer())];
- if ([attributeName isEqualToString: @"AXLayoutCount"])
- return [NSNumber numberWithInt: (static_cast<RenderView*>(m_renderer)->frameView()->layoutCount())];
- }
-
- if ([self isTextControl]) {
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
- if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute])
- return [self isPasswordField] ? nil : [NSNumber numberWithUnsignedInt: textControl->text().length()];
- if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
- if ([self isPasswordField])
- return nil;
- NSString* text = textControl->text();
- return [text substringWithRange: NSMakeRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart())];
- }
- if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute])
- return [self isPasswordField] ? nil : [NSValue valueWithRange: NSMakeRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart())];
- // TODO: Get actual visible range. <rdar://problem/4712101>
- if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
- return [self isPasswordField] ? nil : [NSValue valueWithRange: NSMakeRange(0, textControl->text().length())];
- if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
- if ([self isPasswordField] || textControl->selectionStart() != textControl->selectionEnd())
- return nil;
- NSNumber* index = [NSNumber numberWithInt: textControl->selectionStart()];
- return [self doAXLineForTextMarker: [self textMarkerForIndex: index lastIndexOK: YES]];
- }
- }
-
- if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
- if ([self isAnchor]) {
- HTMLAnchorElement* anchor = [self anchorElement];
- if (anchor) {
- DeprecatedString s = anchor->getAttribute(hrefAttr).deprecatedString();
- if (!s.isNull()) {
- s = anchor->document()->completeURL(s);
- return KURL(s).getNSURL();
- }
- }
- }
- else if (m_renderer->isImage() && m_renderer->element() && m_renderer->element()->hasTagName(imgTag)) {
- DeprecatedString src = static_cast<HTMLImageElement*>(m_renderer->element())->src().deprecatedString();
- if (!src.isNull())
- return KURL(src).getNSURL();
- }
- return nil;
- }
-
- if ([attributeName isEqualToString: @"AXVisited"])
- return [NSNumber numberWithBool: m_renderer->style()->pseudoState() == PseudoVisited];
-
- if ([attributeName isEqualToString: NSAccessibilityTitleAttribute])
- return [self title];
-
- if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute])
- return [self accessibilityDescription];
-
- if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
- return [self value];
-
- if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
- return [self helpText];
-
- if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
- return [NSNumber numberWithBool: (m_renderer->element() && m_renderer->document()->focusedNode() == m_renderer->element())];
-
- if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
- return [NSNumber numberWithBool: m_renderer->element() ? m_renderer->element()->isEnabled() : YES];
-
- if ([attributeName isEqualToString: NSAccessibilitySizeAttribute])
- return [self size];
-
- if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
- return [self position];
-
- if ([attributeName isEqualToString: NSAccessibilityWindowAttribute]) {
- if (m_renderer && m_renderer->view() && m_renderer->view()->frameView())
- return [m_renderer->view()->frameView()->getView() window];
-
- return nil;
- }
-
- if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {
- // get the selection from the document
- Selection selection = [self frameView]->frame()->selectionController()->selection();
- if (selection.isNone())
- return nil;
-
- return (id) [self textMarkerRangeFromVisiblePositions:selection.visibleStart() andEndPos:selection.visibleEnd()];
- }
-
- if ([attributeName isEqualToString: @"AXStartTextMarker"])
- return (id) [self textMarkerForVisiblePosition: startOfDocument(m_renderer->document())];
-
- if ([attributeName isEqualToString: @"AXEndTextMarker"])
- return (id) [self textMarkerForVisiblePosition: endOfDocument(m_renderer->document())];
-
- return nil;
-}
-
-- (NSArray* )accessibilityParameterizedAttributeNames
-{
- if ([self isAttachment])
- return nil;
-
- static NSArray* paramAttrs = nil;
- static NSArray* textParamAttrs = nil;
- if (paramAttrs == nil) {
- paramAttrs = [[NSArray alloc] initWithObjects:
- @"AXUIElementForTextMarker",
- @"AXTextMarkerRangeForUIElement",
- @"AXLineForTextMarker",
- @"AXTextMarkerRangeForLine",
- @"AXStringForTextMarkerRange",
- @"AXTextMarkerForPosition",
- @"AXBoundsForTextMarkerRange",
- @"AXAttributedStringForTextMarkerRange",
- @"AXTextMarkerRangeForUnorderedTextMarkers",
- @"AXNextTextMarkerForTextMarker",
- @"AXPreviousTextMarkerForTextMarker",
- @"AXLeftWordTextMarkerRangeForTextMarker",
- @"AXRightWordTextMarkerRangeForTextMarker",
- @"AXLeftLineTextMarkerRangeForTextMarker",
- @"AXRightLineTextMarkerRangeForTextMarker",
- @"AXSentenceTextMarkerRangeForTextMarker",
- @"AXParagraphTextMarkerRangeForTextMarker",
- @"AXNextWordEndTextMarkerForTextMarker",
- @"AXPreviousWordStartTextMarkerForTextMarker",
- @"AXNextLineEndTextMarkerForTextMarker",
- @"AXPreviousLineStartTextMarkerForTextMarker",
- @"AXNextSentenceEndTextMarkerForTextMarker",
- @"AXPreviousSentenceStartTextMarkerForTextMarker",
- @"AXNextParagraphEndTextMarkerForTextMarker",
- @"AXPreviousParagraphStartTextMarkerForTextMarker",
- @"AXStyleTextMarkerRangeForTextMarker",
- @"AXLengthForTextMarkerRange",
- nil];
- }
-
- if (textParamAttrs == nil) {
- NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
- [tempArray addObject: (NSString*)kAXLineForIndexParameterizedAttribute];
- [tempArray addObject: (NSString*)kAXRangeForLineParameterizedAttribute];
- [tempArray addObject: (NSString*)kAXStringForRangeParameterizedAttribute];
- [tempArray addObject: (NSString*)kAXRangeForPositionParameterizedAttribute];
- [tempArray addObject: (NSString*)kAXRangeForIndexParameterizedAttribute];
- [tempArray addObject: (NSString*)kAXBoundsForRangeParameterizedAttribute];
- [tempArray addObject: (NSString*)kAXRTFForRangeParameterizedAttribute];
- [tempArray addObject: (NSString*)kAXAttributedStringForRangeParameterizedAttribute];
- [tempArray addObject: (NSString*)kAXStyleRangeForIndexParameterizedAttribute];
- textParamAttrs = [[NSArray alloc] initWithArray:tempArray];
- [tempArray release];
- }
-
- if ([self isPasswordField])
- return [NSArray array];
-
- if (!m_renderer)
- return paramAttrs;
-
- if ([self isTextControl])
- return textParamAttrs;
-
- return paramAttrs;
-}
-
-- (id)doAXUIElementForTextMarker: (WebCoreTextMarker* ) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- RenderObject* obj = visiblePos.deepEquivalent().node()->renderer();
- if (!obj)
- return nil;
-
- return obj->document()->axObjectCache()->get(obj);
-}
-
-- (id)doAXTextMarkerRangeForUIElement: (id) uiElement
-{
- return (id)[uiElement textMarkerRange];
-}
-
-- (id)doAXLineForTextMarker: (WebCoreTextMarker* ) textMarker
-{
- unsigned int lineCount = 0;
- VisiblePosition savedVisiblePos;
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // move up until we get to the top
- // NOTE: BUG This only takes us to the top of the rootEditableElement, not the top of the
- // top document.
- while (visiblePos.isNotNull() && !(inSameLine(visiblePos, savedVisiblePos))) {
- lineCount += 1;
- savedVisiblePos = visiblePos;
- visiblePos = previousLinePosition(visiblePos, 0);
- }
-
- return [NSNumber numberWithUnsignedInt:(lineCount - 1)];
-}
-
-- (id)doAXTextMarkerRangeForLine: (NSNumber*) lineNumber
-{
- unsigned lineCount = [lineNumber unsignedIntValue];
- if (lineCount == 0 || !m_renderer)
- return nil;
-
- // iterate over the lines
- // NOTE: BUG this is wrong when lineNumber is lineCount+1, because nextLinePosition takes you to the
- // last offset of the last line
- VisiblePosition visiblePos = m_renderer->document()->renderer()->positionForCoordinates(0, 0);
- VisiblePosition savedVisiblePos;
- while (--lineCount != 0) {
- savedVisiblePos = visiblePos;
- visiblePos = nextLinePosition(visiblePos, 0);
- if (visiblePos.isNull() || visiblePos == savedVisiblePos)
- return nil;
- }
-
- // make a caret selection for the marker position, then extend it to the line
- // NOTE: ignores results of sel.modify because it returns false when
- // starting at an empty line. The resulting selection in that case
- // will be a caret at visiblePos.
- SelectionController selectionController;
- selectionController.setSelection(Selection(visiblePos));
- selectionController.modify(SelectionController::EXTEND, SelectionController::RIGHT, LineBoundary);
-
- // return a marker range for the selection start to end
- VisiblePosition startPosition = selectionController.selection().visibleStart();
- VisiblePosition endPosition = selectionController.selection().visibleEnd();
- return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-}
-
-static NSString *nsStringForReplacedNode(Node* replacedNode)
-{
- // we should always be given a rendered node and a replaced node, but be safe
- // replaced nodes are either attachments (widgets) or images
- if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {
- ASSERT_NOT_REACHED();
- return nil;
- }
-
- // create an AX object, but skip it if it is not supposed to be seen
- WebCoreAXObject* obj = replacedNode->renderer()->document()->axObjectCache()->get(replacedNode->renderer());
- if ([obj accessibilityIsIgnored])
- return nil;
-
- // use the attachmentCharacter to represent the replaced node
- const UniChar attachmentChar = NSAttachmentCharacter;
- return [NSString stringWithCharacters:&attachmentChar length:1];
-}
-
-- (id)doAXStringForTextMarkerRange: (WebCoreTextMarkerRange*) textMarkerRange
-{
- // extract the start and end VisiblePosition
- VisiblePosition startVisiblePosition = [self visiblePositionForStartOfTextMarkerRange: textMarkerRange];
- if (startVisiblePosition.isNull())
- return nil;
-
- VisiblePosition endVisiblePosition = [self visiblePositionForEndOfTextMarkerRange: textMarkerRange];
- if (endVisiblePosition.isNull())
- return nil;
-
- NSMutableString* resultString = [[[NSMutableString alloc] init] autorelease];
- TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
- while (!it.atEnd()) {
- // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
- if (it.length() != 0) {
- [resultString appendString:[NSString stringWithCharacters:it.characters() length:it.length()]];
- } else {
- // locate the node and starting offset for this replaced range
- int exception = 0;
- Node* node = it.range()->startContainer(exception);
- ASSERT(node == it.range()->endContainer(exception));
- int offset = it.range()->startOffset(exception);
- NSString* attachmentString = nsStringForReplacedNode(node->childNode(offset));
-
- // append the replacement string
- if (attachmentString)
- [resultString appendString:attachmentString];
- }
- it.advance();
- }
-
- return [resultString length] > 0 ? resultString : nil;
-}
-
-- (id)doAXTextMarkerForPosition: (NSPoint) point
-{
- // convert absolute point to view coordinates
- FrameView* frameView = [self topFrameView];
- NSView* view = frameView->getDocumentView();
- RenderObject* renderer = [self topRenderer];
- Node* innerNode = 0;
-
- // locate the node containing the point
- IntPoint pointResult;
- while (1) {
- // ask the document layer to hitTest
- NSPoint windowCoord = [[view window] convertScreenToBase: point];
- IntPoint ourpoint([view convertPoint:windowCoord fromView:nil]);
-
- HitTestRequest request(true, true);
- HitTestResult result(ourpoint);
- renderer->layer()->hitTest(request, result);
- innerNode = result.innerNode();
- if (!innerNode || !innerNode->renderer())
- return nil;
-
- pointResult = result.localPoint();
-
- // done if hit something other than a widget
- renderer = innerNode->renderer();
- if (!renderer->isWidget())
- break;
-
- // descend into widget (FRAME, IFRAME, OBJECT...)
- Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
- if (!widget || !widget->isFrameView())
- break;
- Frame* frame = static_cast<FrameView*>(widget)->frame();
- if (!frame)
- break;
- Document* document = frame->document();
- if (!document)
- break;
- renderer = document->renderer();
- frameView = static_cast<FrameView*>(widget);
- view = frameView->getDocumentView();
- }
-
- // get position within the node
- VisiblePosition pos = innerNode->renderer()->positionForPoint(pointResult);
- return (id) [self textMarkerForVisiblePosition:pos];
-}
-
-- (id)doAXBoundsForTextMarkerRange: (WebCoreTextMarkerRange*) textMarkerRange
-{
- // extract the start and end VisiblePosition
- VisiblePosition startVisiblePosition = [self visiblePositionForStartOfTextMarkerRange: textMarkerRange];
- if (startVisiblePosition.isNull())
- return nil;
-
- VisiblePosition endVisiblePosition = [self visiblePositionForEndOfTextMarkerRange: textMarkerRange];
- if (endVisiblePosition.isNull())
- return nil;
-
- IntRect rect1 = startVisiblePosition.caretRect();
- IntRect rect2 = endVisiblePosition.caretRect();
-
- // readjust for position at the edge of a line. This is to exclude line rect that doesn't need to be accounted in the range bounds
- if (rect2.y() != rect1.y()) {
- VisiblePosition endOfFirstLine = endOfLine(startVisiblePosition);
- if (startVisiblePosition == endOfFirstLine) {
- startVisiblePosition.setAffinity(DOWNSTREAM);
- rect1 = startVisiblePosition.caretRect();
- }
- if (endVisiblePosition == endOfFirstLine) {
- endVisiblePosition.setAffinity(UPSTREAM);
- rect2 = endVisiblePosition.caretRect();
- }
- }
-
- IntRect ourrect = rect1;
- ourrect.unite(rect2);
-
- // try to use the document view from the first position, so that nested WebAreas work,
- // but fall back to the top level doc if we do not find it easily
- RenderObject* renderer = startVisiblePosition.deepEquivalent().node()->renderer();
- FrameView* frameView = renderer ? renderer->document()->view() : 0;
- if (!frameView)
- frameView = [self frameView];
- NSView *view = frameView->getView();
-
- // if the rectangle spans lines and contains multiple text chars, use the range's bounding box intead
- if (rect1.bottom() != rect2.bottom()) {
- RefPtr<Range> dataRange = makeRange(startVisiblePosition, endVisiblePosition);
- IntRect boundingBox = dataRange->boundingBox();
- String rangeString = plainText(dataRange.get());
- if (rangeString.length() > 1 && !boundingBox.isEmpty())
- ourrect = boundingBox;
- }
-
- // convert our rectangle to screen coordinates
- NSRect rect = ourrect;
- rect = NSOffsetRect(rect, -frameView->contentsX(), -frameView->contentsY());
- rect = [view convertRect:rect toView:nil];
- rect.origin = [[view window] convertBaseToScreen:rect.origin];
-
- // return the converted rect
- return [NSValue valueWithRect:rect];
-}
-
-static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
-{
- // get color information assuming NSDeviceRGBColorSpace
- NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- if (rgbColor == nil)
- rgbColor = [NSColor blackColor];
- CGFloat components[4];
- [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
-
- // create a new CGColorRef to return
- CGColorSpaceRef cgColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
- CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
- CGColorSpaceRelease(cgColorSpace);
- CFMakeCollectable(cgColor);
-
- // check for match with existing color
- if (existingColor && CGColorEqualToColor(cgColor, existingColor))
- cgColor = nil;
-
- return cgColor;
-}
-
-static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
-{
- if (color) {
- CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
- CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
- if (cgColor) {
- [attrString addAttribute:attribute value:(id)cgColor range:range];
- CGColorRelease(cgColor);
- }
- } else
- [attrString removeAttribute:attribute range:range];
-}
-
-static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
-{
- if (number)
- [attrString addAttribute:attribute value:number range:range];
- else
- [attrString removeAttribute:attribute range:range];
-}
-
-static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
-{
- NSDictionary* dict;
-
- if (font) {
- dict = [NSDictionary dictionaryWithObjectsAndKeys:
- [font fontName] , NSAccessibilityFontNameKey,
- [font familyName] , NSAccessibilityFontFamilyKey,
- [font displayName] , NSAccessibilityVisibleNameKey,
- [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
- nil];
-
- [attrString addAttribute:attribute value:dict range:range];
- } else
- [attrString removeAttribute:attribute range:range];
-
-}
-
-static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
-{
- RenderStyle* style = renderer->style();
-
- // set basic font info
- AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range);
-
- // set basic colors
- AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->color()), range);
- AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->backgroundColor()), range);
-
- // set super/sub scripting
- EVerticalAlign alignment = style->verticalAlign();
- if (alignment == SUB)
- AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
- else if (alignment == SUPER)
- AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
- else
- [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
-
- // set shadow
- if (style->textShadow())
- AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
- else
- [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
-
- // set underline and strikethrough
- int decor = style->textDecorationsInEffect();
- if ((decor & UNDERLINE) == 0) {
- [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
- [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
- }
-
- if ((decor & LINE_THROUGH) == 0) {
- [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
- [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
- }
-
- if ((decor & (UNDERLINE | LINE_THROUGH)) != 0) {
- // find colors using quirk mode approach (strict mode would use current
- // color for all but the root line box, which would use getTextDecorationColors)
- Color underline, overline, linethrough;
- renderer->getTextDecorationColors(decor, underline, overline, linethrough);
-
- if ((decor & UNDERLINE) != 0) {
- AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
- AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range);
- }
-
- if ((decor & LINE_THROUGH) != 0) {
- AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
- AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range);
- }
- }
-}
-
-static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
-{
- int parentHeadingLevel = headingLevel(renderer->parent());
-
- if (parentHeadingLevel)
- [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
- else
- [attrString removeAttribute:@"AXHeadingLevel" range:range];
-}
-
-static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
-{
- int quoteLevel = blockquoteLevel(renderer);
-
- if (quoteLevel)
- [attrString addAttribute:@"AXBlockQuoteLevel" value:[NSNumber numberWithInt:quoteLevel] range:range];
- else
- [attrString removeAttribute:@"AXBlockQuoteLevel" range:range];
-}
-
-static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, id element, NSRange range)
-{
- if (element) {
- // make a serialiazable AX object
- AXUIElementRef axElement = [[WebCoreViewFactory sharedFactory] AXUIElementForElement:element];
- if (axElement) {
- [attrString addAttribute:attribute value:(id)axElement range:range];
- CFRelease(axElement);
- }
- } else
- [attrString removeAttribute:attribute range:range];
-}
-
-static WebCoreAXObject* AXLinkElementForNode (Node* node)
-{
- RenderObject* obj = node->renderer();
- if (!obj)
- return nil;
-
- WebCoreAXObject* axObj = obj->document()->axObjectCache()->get(obj);
- HTMLAnchorElement* anchor = [axObj anchorElement];
- if (!anchor || !anchor->renderer())
- return nil;
-
- return anchor->renderer()->document()->axObjectCache()->get(anchor->renderer());
-}
-
-static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, int offset, NSRange range)
-{
- Vector<DocumentMarker> markers = node->renderer()->document()->markersForNode(node);
- Vector<DocumentMarker>::iterator markerIt = markers.begin();
-
- unsigned endOffset = (unsigned)offset + range.length;
- for ( ; markerIt != markers.end(); markerIt++) {
- DocumentMarker marker = *markerIt;
-
- if (marker.type != DocumentMarker::Spelling)
- continue;
-
- if (marker.endOffset <= (unsigned)offset)
- continue;
-
- if (marker.startOffset > endOffset)
- break;
-
- // add misspelling attribute for the intersection of the marker and the range
- int rStart = range.location + (marker.startOffset - offset);
- int rLength = MIN(marker.endOffset, endOffset) - marker.startOffset;
- NSRange spellRange = NSMakeRange(rStart, rLength);
- AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
-
- if (marker.endOffset > endOffset + 1)
- break;
- }
-}
-
-static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, int offset, const UChar* chars, int length)
-{
- // skip invisible text
- if (!node->renderer())
- return;
-
- // easier to calculate the range before appending the string
- NSRange attrStringRange = NSMakeRange([attrString length], length);
-
- // append the string from this node
- [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]];
-
- // add new attributes and remove irrelevant inherited ones
- // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
- // identical colors. Workaround is to not replace an existing color attribute if it matches what we are adding. This also means
- // we can not just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
-
- // remove inherited attachment from prior AXAttributedStringAppendReplaced
- [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
-
- // set new attributes
- AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange);
- AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange);
- AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange);
- AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AXLinkElementForNode(node), attrStringRange);
-
- // do spelling last because it tends to break up the range
- AXAttributeStringSetSpelling(attrString, node, offset, attrStringRange);
-}
-
-- (id)doAXAttributedStringForTextMarkerRange: (WebCoreTextMarkerRange*) textMarkerRange
-{
- // extract the start and end VisiblePosition
- VisiblePosition startVisiblePosition = [self visiblePositionForStartOfTextMarkerRange: textMarkerRange];
- if (startVisiblePosition.isNull())
- return nil;
-
- VisiblePosition endVisiblePosition = [self visiblePositionForEndOfTextMarkerRange: textMarkerRange];
- if (endVisiblePosition.isNull())
- return nil;
-
- // iterate over the range to build the AX attributed string
- NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
- TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
- while (!it.atEnd()) {
- // locate the node and starting offset for this range
- int exception = 0;
- Node* node = it.range()->startContainer(exception);
- ASSERT(node == it.range()->endContainer(exception));
- int offset = it.range()->startOffset(exception);
-
- // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
- if (it.length() != 0) {
- AXAttributedStringAppendText(attrString, node, offset, it.characters(), it.length());
- } else {
- Node* replacedNode = node->childNode(offset);
- NSString *attachmentString = nsStringForReplacedNode(replacedNode);
- if (attachmentString) {
- NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
-
- // append the placeholder string
- [[attrString mutableString] appendString:attachmentString];
-
- // remove all inherited attributes
- [attrString setAttributes:nil range:attrStringRange];
-
- // add the attachment attribute
- WebCoreAXObject* obj = replacedNode->renderer()->document()->axObjectCache()->get(replacedNode->renderer());
- AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
- }
- }
- it.advance();
- }
-
- return [attrString autorelease];
-}
-
-- (id)doAXTextMarkerRangeForUnorderedTextMarkers: (NSArray*) markers
-{
- // get and validate the markers
- if ([markers count] < 2)
- return nil;
-
- WebCoreTextMarker* textMarker1 = (WebCoreTextMarker*) [markers objectAtIndex:0];
- WebCoreTextMarker* textMarker2 = (WebCoreTextMarker*) [markers objectAtIndex:1];
- if (![[WebCoreViewFactory sharedFactory] objectIsTextMarker:textMarker1] || ![[WebCoreViewFactory sharedFactory] objectIsTextMarker:textMarker2])
- return nil;
-
- // convert to VisiblePosition
- VisiblePosition visiblePos1 = [self visiblePositionForTextMarker:textMarker1];
- VisiblePosition visiblePos2 = [self visiblePositionForTextMarker:textMarker2];
- if (visiblePos1.isNull() || visiblePos2.isNull())
- return nil;
-
- WebCoreTextMarker* startTextMarker;
- WebCoreTextMarker* endTextMarker;
- bool alreadyInOrder;
-
- // upstream is ordered before downstream for the same position
- if (visiblePos1 == visiblePos2 && visiblePos2.affinity() == UPSTREAM)
- alreadyInOrder = false;
-
- // use selection order to see if the positions are in order
- else
- alreadyInOrder = Selection(visiblePos1, visiblePos2).isBaseFirst();
-
- if (alreadyInOrder) {
- startTextMarker = textMarker1;
- endTextMarker = textMarker2;
- } else {
- startTextMarker = textMarker2;
- endTextMarker = textMarker1;
- }
-
- return (id) [self textMarkerRangeFromMarkers: startTextMarker andEndMarker:endTextMarker];
-}
-
-- (id)doAXNextTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- VisiblePosition nextVisiblePos = visiblePos.next();
- if (nextVisiblePos.isNull())
- return nil;
-
- return (id) [self textMarkerForVisiblePosition:nextVisiblePos];
-}
-
-- (id)doAXPreviousTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- VisiblePosition previousVisiblePos = visiblePos.previous();
- if (previousVisiblePos.isNull())
- return nil;
-
- return (id) [self textMarkerForVisiblePosition:previousVisiblePos];
-}
-
-- (id)doAXLeftWordTextMarkerRangeForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- VisiblePosition startPosition = startOfWord(visiblePos, LeftWordIfOnBoundary);
- VisiblePosition endPosition = endOfWord(startPosition);
-
- return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-}
-
-- (id)doAXRightWordTextMarkerRangeForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- VisiblePosition startPosition = startOfWord(visiblePos, RightWordIfOnBoundary);
- VisiblePosition endPosition = endOfWord(startPosition);
-
- return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-}
-
-
-static VisiblePosition updateAXLineStartForVisiblePosition(const VisiblePosition& visiblePosition)
-{
- // A line in the accessibility sense should include floating objects, such as aligned image, as part of a line.
- // So let's update the position to include that.
- VisiblePosition tempPosition;
- VisiblePosition startPosition = visiblePosition;
- Position p;
- RenderObject* renderer;
- while (true) {
- tempPosition = startPosition.previous();
- if (tempPosition.isNull())
- break;
- p = tempPosition.deepEquivalent();
- if (!p.node())
- break;
- renderer = p.node()->renderer();
- if (!renderer || renderer->inlineBox(p.offset(), tempPosition.affinity()) || (renderer->isRenderBlock() && p.offset() == 0))
- break;
- startPosition = tempPosition;
- }
-
- return startPosition;
-}
-
-- (id)doAXLeftLineTextMarkerRangeForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // make a caret selection for the position before marker position (to make sure
- // we move off of a line start)
- VisiblePosition prevVisiblePos = visiblePos.previous();
- if (prevVisiblePos.isNull())
- return nil;
-
- VisiblePosition startPosition = startOfLine(prevVisiblePos);
-
- // keep searching for a valid line start position. Unless the textmarker is at the very beginning, there should
- // always be a valid line range. However, startOfLine will return null for position next to a floating object,
- // since floating object doesn't really belong to any line.
- // This check will reposition the marker before the floating object, to ensure we get a line start.
- if (startPosition.isNull()) {
- while (startPosition.isNull() && prevVisiblePos.isNotNull()) {
- prevVisiblePos = prevVisiblePos.previous();
- startPosition = startOfLine(prevVisiblePos);
- }
- } else
- startPosition = updateAXLineStartForVisiblePosition(startPosition);
-
- VisiblePosition endPosition = endOfLine(prevVisiblePos);
- return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-}
-
-- (id)doAXRightLineTextMarkerRangeForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // make sure we move off of a line end
- VisiblePosition nextVisiblePos = visiblePos.next();
- if (nextVisiblePos.isNull())
- return nil;
-
- VisiblePosition startPosition = startOfLine(nextVisiblePos);
-
- // fetch for a valid line start position
- if (startPosition.isNull() ) {
- startPosition = visiblePos;
- nextVisiblePos = nextVisiblePos.next();
- } else
- startPosition = updateAXLineStartForVisiblePosition(startPosition);
-
- VisiblePosition endPosition = endOfLine(nextVisiblePos);
-
- // as long as the position hasn't reached the end of the doc, keep searching for a valid line end position
- // Unless the textmarker is at the very end, there should always be a valid line range. However, endOfLine will
- // return null for position by a floating object, since floating object doesn't really belong to any line.
- // This check will reposition the marker after the floating object, to ensure we get a line end.
- while (endPosition.isNull() && nextVisiblePos.isNotNull()) {
- nextVisiblePos = nextVisiblePos.next();
- endPosition = endOfLine(nextVisiblePos);
- }
-
- return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-}
-
-- (id)doAXSentenceTextMarkerRangeForTextMarker: (WebCoreTextMarker*) textMarker
-{
- // NOTE: BUG FO 2 IMPLEMENT (currently returns incorrect answer)
- // Related? <rdar://problem/3927736> Text selection broken in 8A336
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- VisiblePosition startPosition = startOfSentence(visiblePos);
- VisiblePosition endPosition = endOfSentence(startPosition);
- return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-}
-
-- (id)doAXParagraphTextMarkerRangeForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- VisiblePosition startPosition = startOfParagraph(visiblePos);
- VisiblePosition endPosition = endOfParagraph(startPosition);
- return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-}
-
-- (id)doAXNextWordEndTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // make sure we move off of a word end
- visiblePos = visiblePos.next();
- if (visiblePos.isNull())
- return nil;
-
- VisiblePosition endPosition = endOfWord(visiblePos, LeftWordIfOnBoundary);
- return (id) [self textMarkerForVisiblePosition:endPosition];
-}
-
-- (id)doAXPreviousWordStartTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // make sure we move off of a word start
- visiblePos = visiblePos.previous();
- if (visiblePos.isNull())
- return nil;
-
- VisiblePosition startPosition = startOfWord(visiblePos, RightWordIfOnBoundary);
- return (id) [self textMarkerForVisiblePosition:startPosition];
-}
-
-- (id)doAXNextLineEndTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // to make sure we move off of a line end
- VisiblePosition nextVisiblePos = visiblePos.next();
- if (nextVisiblePos.isNull())
- return nil;
-
- VisiblePosition endPosition = endOfLine(nextVisiblePos);
-
- // as long as the position hasn't reached the end of the doc, keep searching for a valid line end position
- // There are cases like when the position is next to a floating object that'll return null for end of line. This code will avoid returning null.
- while (endPosition.isNull() && nextVisiblePos.isNotNull()) {
- nextVisiblePos = nextVisiblePos.next();
- endPosition = endOfLine(nextVisiblePos);
- }
-
- return (id) [self textMarkerForVisiblePosition: endPosition];
-}
-
-- (id)doAXPreviousLineStartTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // make sure we move off of a line start
- VisiblePosition prevVisiblePos = visiblePos.previous();
- if (prevVisiblePos.isNull())
- return nil;
-
- VisiblePosition startPosition = startOfLine(prevVisiblePos);
-
- // as long as the position hasn't reached the beginning of the doc, keep searching for a valid line start position
- // There are cases like when the position is next to a floating object that'll return null for start of line. This code will avoid returning null.
- if (startPosition.isNull()) {
- while (startPosition.isNull() && prevVisiblePos.isNotNull()) {
- prevVisiblePos = prevVisiblePos.previous();
- startPosition = startOfLine(prevVisiblePos);
- }
- } else
- startPosition = updateAXLineStartForVisiblePosition(startPosition);
-
- return (id) [self textMarkerForVisiblePosition: startPosition];
-}
-
-- (id)doAXNextSentenceEndTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- // NOTE: BUG FO 2 IMPLEMENT (currently returns incorrect answer)
- // Related? <rdar://problem/3927736> Text selection broken in 8A336
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // make sure we move off of a sentence end
- VisiblePosition nextVisiblePos = visiblePos.next();
- if (nextVisiblePos.isNull())
- return nil;
-
- // an empty line is considered a sentence. If it's skipped, then the sentence parser will not
- // see this empty line. Instead, return the end position of the empty line.
- VisiblePosition endPosition;
- String lineString = plainText(makeRange(startOfLine(visiblePos), endOfLine(visiblePos)).get());
- if (lineString.isEmpty())
- endPosition = nextVisiblePos;
- else
- endPosition = endOfSentence(nextVisiblePos);
-
- return (id) [self textMarkerForVisiblePosition: endPosition];
-}
-
-- (id)doAXPreviousSentenceStartTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- // NOTE: BUG FO 2 IMPLEMENT (currently returns incorrect answer)
- // Related? <rdar://problem/3927736> Text selection broken in 8A336
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // make sure we move off of a sentence start
- VisiblePosition previousVisiblePos = visiblePos.previous();
- if (previousVisiblePos.isNull())
- return nil;
-
- // treat empty line as a separate sentence.
- VisiblePosition startPosition;
- String lineString = plainText(makeRange(startOfLine(previousVisiblePos), endOfLine(previousVisiblePos)).get());
- if (lineString.isEmpty())
- startPosition = previousVisiblePos;
- else
- startPosition = startOfSentence(previousVisiblePos);
-
- return (id) [self textMarkerForVisiblePosition: startPosition];
-}
-
-- (id)doAXNextParagraphEndTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // make sure we move off of a paragraph end
- visiblePos = visiblePos.next();
- if (visiblePos.isNull())
- return nil;
-
- VisiblePosition endPosition = endOfParagraph(visiblePos);
- return (id) [self textMarkerForVisiblePosition: endPosition];
-}
-
-- (id)doAXPreviousParagraphStartTextMarkerForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- // make sure we move off of a paragraph start
- visiblePos = visiblePos.previous();
- if (visiblePos.isNull())
- return nil;
-
- VisiblePosition startPosition = startOfParagraph(visiblePos);
- return (id) [self textMarkerForVisiblePosition: startPosition];
-}
-
-static VisiblePosition startOfStyleRange (const VisiblePosition visiblePos)
-{
- RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer();
- RenderObject* startRenderer = renderer;
- RenderStyle* style = renderer->style();
-
- // traverse backward by renderer to look for style change
- for (RenderObject* r = renderer->previousInPreOrder(); r; r = r->previousInPreOrder()) {
- // skip non-leaf nodes
- if (r->firstChild())
- continue;
-
- // stop at style change
- if (r->style() != style)
- break;
-
- // remember match
- startRenderer = r;
- }
-
- return VisiblePosition(startRenderer->node(), 0, VP_DEFAULT_AFFINITY);
-}
-
-static VisiblePosition endOfStyleRange (const VisiblePosition visiblePos)
-{
- RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer();
- RenderObject* endRenderer = renderer;
- RenderStyle* style = renderer->style();
-
- // traverse forward by renderer to look for style change
- for (RenderObject* r = renderer->nextInPreOrder(); r; r = r->nextInPreOrder()) {
- // skip non-leaf nodes
- if (r->firstChild())
- continue;
-
- // stop at style change
- if (r->style() != style)
- break;
-
- // remember match
- endRenderer = r;
- }
-
- return VisiblePosition(endRenderer->node(), maxDeepOffset(endRenderer->node()), VP_DEFAULT_AFFINITY);
-}
-
-- (id)doAXStyleTextMarkerRangeForTextMarker: (WebCoreTextMarker*) textMarker
-{
- VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
- if (visiblePos.isNull())
- return nil;
-
- VisiblePosition startPosition = startOfStyleRange(visiblePos);
- VisiblePosition endPosition = endOfStyleRange(visiblePos);
- return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-}
-
-- (id)doAXLengthForTextMarkerRange: (WebCoreTextMarkerRange*) textMarkerRange
-{
- // NOTE: BUG Multi-byte support
- CFStringRef string = (CFStringRef) [self doAXStringForTextMarkerRange: textMarkerRange];
- if (!string)
- return nil;
-
- return [NSNumber numberWithInt:CFStringGetLength(string)];
-}
-
-// NOTE: Consider providing this utility method as AX API
-- (WebCoreTextMarker*)textMarkerForIndex: (NSNumber*) index lastIndexOK: (BOOL)lastIndexOK
-{
- ASSERT(m_renderer->isTextField() || m_renderer->isTextArea());
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
- unsigned int indexValue = [index unsignedIntValue];
-
- // lastIndexOK specifies whether the position after the last character is acceptable
- if (indexValue >= textControl->text().length()) {
- if (!lastIndexOK || indexValue > textControl->text().length())
- return nil;
- }
- VisiblePosition position = textControl->visiblePositionForIndex(indexValue);
- position.setAffinity(DOWNSTREAM);
- return [self textMarkerForVisiblePosition: position];
-}
-
-// NOTE: Consider providing this utility method as AX API
-- (NSNumber*)indexForTextMarker: (WebCoreTextMarker*) marker
-{
- ASSERT(m_renderer->isTextField() || m_renderer->isTextArea());
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
-
- VisiblePosition position = [self visiblePositionForTextMarker: marker];
- Node* node = position.deepEquivalent().node();
- if (!node)
- return nil;
-
- for (RenderObject* renderer = node->renderer(); renderer && renderer->element(); renderer = renderer->parent()) {
- if (renderer == textControl)
- return [NSNumber numberWithInt: textControl->indexForVisiblePosition(position)];
- }
-
- return nil;
-}
-
-// NOTE: Consider providing this utility method as AX API
-- (WebCoreTextMarkerRange*)textMarkerRangeForRange: (NSRange) range
-{
- ASSERT(m_renderer->isTextField() || m_renderer->isTextArea());
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
- if (range.location + range.length > textControl->text().length())
- return nil;
-
- VisiblePosition startPosition = textControl->visiblePositionForIndex(range.location);
- startPosition.setAffinity(DOWNSTREAM);
- VisiblePosition endPosition = textControl->visiblePositionForIndex(range.location + range.length);
- return [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-}
-
-// NOTE: Consider providing this utility method as AX API
-- (NSValue*)rangeForTextMarkerRange: (WebCoreTextMarkerRange*) textMarkerRange
-{
- WebCoreTextMarker* textMarker1 = [[WebCoreViewFactory sharedFactory] startOfTextMarkerRange:textMarkerRange];
- WebCoreTextMarker* textMarker2 = [[WebCoreViewFactory sharedFactory] endOfTextMarkerRange:textMarkerRange];
- NSNumber* index1 = [self indexForTextMarker: textMarker1];
- NSNumber* index2 = [self indexForTextMarker: textMarker2];
- if (!index1 || !index2 || [index1 unsignedIntValue] > [index2 unsignedIntValue])
- return nil;
-
- return [NSValue valueWithRange: NSMakeRange([index1 unsignedIntValue], [index2 unsignedIntValue] - [index1 unsignedIntValue])];
-}
-
-// Given an indexed character, the line number of the text associated with this accessibility
-// object that contains the character.
-- (id)doAXLineForIndex: (NSNumber*) index
-{
- return [self doAXLineForTextMarker: [self textMarkerForIndex: index lastIndexOK: NO]];
-}
-
-// Given a line number, the range of characters of the text associated with this accessibility
-// object that contains the line number.
-- (id)doAXRangeForLine: (NSNumber*) lineNumber
-{
- ASSERT(m_renderer->isTextField() || m_renderer->isTextArea());
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
-
- // iterate to the specified line
- VisiblePosition visiblePos = textControl->visiblePositionForIndex(0);
- VisiblePosition savedVisiblePos;
- for (unsigned lineCount = [lineNumber unsignedIntValue]; lineCount != 0; lineCount -= 1) {
- savedVisiblePos = visiblePos;
- visiblePos = nextLinePosition(visiblePos, 0);
- if (visiblePos.isNull() || visiblePos == savedVisiblePos)
- return nil;
- }
-
- // make a caret selection for the marker position, then extend it to the line
- // NOTE: ignores results of selectionController.modify because it returns false when
- // starting at an empty line. The resulting selection in that case
- // will be a caret at visiblePos.
- SelectionController selectionController;
- selectionController.setSelection(Selection(visiblePos));
- selectionController.modify(SelectionController::EXTEND, SelectionController::LEFT, LineBoundary);
- selectionController.modify(SelectionController::EXTEND, SelectionController::RIGHT, LineBoundary);
-
- // calculate the indices for the selection start and end
- VisiblePosition startPosition = selectionController.selection().visibleStart();
- VisiblePosition endPosition = selectionController.selection().visibleEnd();
- int index1 = textControl->indexForVisiblePosition(startPosition);
- int index2 = textControl->indexForVisiblePosition(endPosition);
-
- // add one to the end index for a line break not caused by soft line wrap (to match AppKit)
- if (endPosition.affinity() == DOWNSTREAM && endPosition.next().isNotNull())
- index2 += 1;
-
- // return nil rather than an zero-length range (to match AppKit)
- if (index1 == index2)
- return nil;
-
- return [NSValue valueWithRange: NSMakeRange(index1, index2 - index1)];
-}
-
-// A substring of the text associated with this accessibility object that is
-// specified by the given character range.
-- (id)doAXStringForRange: (NSRange) range
-{
- if ([self isPasswordField])
- return nil;
-
- if (range.length == 0)
- return @"";
-
- ASSERT(m_renderer->isTextField() || m_renderer->isTextArea());
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
- String text = textControl->text();
- if (range.location + range.length > text.length())
- return nil;
-
- return text.substring(range.location, range.length);
-}
-
-// The composed character range in the text associated with this accessibility object that
-// is specified by the given screen coordinates. This parameterized attribute returns the
-// complete range of characters (including surrogate pairs of multi-byte glyphs) at the given
-// screen coordinates.
-// NOTE: This varies from AppKit when the point is below the last line. AppKit returns an
-// an error in that case. We return textControl->text().length(), 1. Does this matter?
-- (id)doAXRangeForPosition: (NSPoint) point
-{
- NSNumber* index = [self indexForTextMarker: [self doAXTextMarkerForPosition: point]];
- if (!index)
- return nil;
-
- return [NSValue valueWithRange: NSMakeRange([index unsignedIntValue], 1)];
-}
-
-// The composed character range in the text associated with this accessibility object that
-// is specified by the given index value. This parameterized attribute returns the complete
-// range of characters (including surrogate pairs of multi-byte glyphs) at the given index.
-- (id)doAXRangeForIndex: (NSNumber*) number
-{
- ASSERT(m_renderer->isTextField() || m_renderer->isTextArea());
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
- String text = textControl->text();
- if (!text.length() || [number unsignedIntValue] > text.length() - 1)
- return nil;
-
- return [NSValue valueWithRange: NSMakeRange([number unsignedIntValue], 1)];
-}
-
-// The bounding rectangle of the text associated with this accessibility object that is
-// specified by the given range. This is the bounding rectangle a sighted user would see
-// on the display screen, in pixels.
-- (id)doAXBoundsForRange: (NSRange) range
-{
- return [self doAXBoundsForTextMarkerRange: [self textMarkerRangeForRange:range]];
-}
-
-// The CFAttributedStringType representation of the text associated with this accessibility
-// object that is specified by the given range.
-- (id)doAXAttributedStringForRange: (NSRange) range
-{
- return [self doAXAttributedStringForTextMarkerRange: [self textMarkerRangeForRange:range]];
-}
-
-// The RTF representation of the text associated with this accessibility object that is
-// specified by the given range.
-- (id)doAXRTFForRange: (NSRange) range
-{
- NSAttributedString* attrString = [self doAXAttributedStringForRange: range];
- return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil];
-}
-
-// Given a character index, the range of text associated with this accessibility object
-// over which the style in effect at that character index applies.
-- (id)doAXStyleRangeForIndex: (NSNumber*) index
-{
- WebCoreTextMarkerRange* textMarkerRange = [self doAXStyleTextMarkerRangeForTextMarker: [self textMarkerForIndex: index lastIndexOK: NO]];
- return [self rangeForTextMarkerRange: textMarkerRange];
-}
-
-- (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
-{
- WebCoreTextMarker* textMarker = nil;
- WebCoreTextMarkerRange* textMarkerRange = nil;
- NSNumber* number = nil;
- NSArray* array = nil;
- WebCoreAXObject* uiElement = nil;
- NSPoint point = NSZeroPoint;
- bool pointSet = false;
- NSRange range = {0, 0};
- bool rangeSet = false;
-
- // basic parameter validation
- if (!m_renderer || !attribute || !parameter)
- return nil;
-
- // common parameter type check/casting. Nil checks in handlers catch wrong type case.
- // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from
- // a parameter of the wrong type.
- if ([[WebCoreViewFactory sharedFactory] objectIsTextMarker:parameter])
- textMarker = (WebCoreTextMarker*) parameter;
-
- else if ([[WebCoreViewFactory sharedFactory] objectIsTextMarkerRange:parameter])
- textMarkerRange = (WebCoreTextMarkerRange*) parameter;
-
- else if ([parameter isKindOfClass:[WebCoreAXObject self]])
- uiElement = (WebCoreAXObject*) parameter;
-
- else if ([parameter isKindOfClass:[NSNumber self]])
- number = parameter;
-
- else if ([parameter isKindOfClass:[NSArray self]])
- array = parameter;
-
- else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) {
- pointSet = true;
- point = [(NSValue*)parameter pointValue];
-
- } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) {
- rangeSet = true;
- range = [(NSValue*)parameter rangeValue];
-
- } else {
- // got a parameter of a type we never use
- // NOTE: No ASSERT_NOT_REACHED because this can happen accidentally
- // while using accesstool (e.g.), forcing you to start over
- return nil;
- }
-
- // dispatch
- if ([attribute isEqualToString: @"AXUIElementForTextMarker"])
- return [self doAXUIElementForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXTextMarkerRangeForUIElement"])
- return [self doAXTextMarkerRangeForUIElement: uiElement];
-
- if ([attribute isEqualToString: @"AXLineForTextMarker"])
- return [self doAXLineForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXTextMarkerRangeForLine"])
- return [self doAXTextMarkerRangeForLine: number];
-
- if ([attribute isEqualToString: @"AXStringForTextMarkerRange"])
- return [self doAXStringForTextMarkerRange: textMarkerRange];
-
- if ([attribute isEqualToString: @"AXTextMarkerForPosition"])
- return pointSet ? [self doAXTextMarkerForPosition: point] : nil;
-
- if ([attribute isEqualToString: @"AXBoundsForTextMarkerRange"])
- return [self doAXBoundsForTextMarkerRange: textMarkerRange];
-
- if ([attribute isEqualToString: @"AXAttributedStringForTextMarkerRange"])
- return [self doAXAttributedStringForTextMarkerRange: textMarkerRange];
-
- if ([attribute isEqualToString: @"AXTextMarkerRangeForUnorderedTextMarkers"])
- return [self doAXTextMarkerRangeForUnorderedTextMarkers: array];
-
- if ([attribute isEqualToString: @"AXNextTextMarkerForTextMarker"])
- return [self doAXNextTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXPreviousTextMarkerForTextMarker"])
- return [self doAXPreviousTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXLeftWordTextMarkerRangeForTextMarker"])
- return [self doAXLeftWordTextMarkerRangeForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXRightWordTextMarkerRangeForTextMarker"])
- return [self doAXRightWordTextMarkerRangeForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXLeftLineTextMarkerRangeForTextMarker"])
- return [self doAXLeftLineTextMarkerRangeForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXRightLineTextMarkerRangeForTextMarker"])
- return [self doAXRightLineTextMarkerRangeForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXSentenceTextMarkerRangeForTextMarker"])
- return [self doAXSentenceTextMarkerRangeForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXParagraphTextMarkerRangeForTextMarker"])
- return [self doAXParagraphTextMarkerRangeForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXNextWordEndTextMarkerForTextMarker"])
- return [self doAXNextWordEndTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXPreviousWordStartTextMarkerForTextMarker"])
- return [self doAXPreviousWordStartTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXNextLineEndTextMarkerForTextMarker"])
- return [self doAXNextLineEndTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXPreviousLineStartTextMarkerForTextMarker"])
- return [self doAXPreviousLineStartTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXNextSentenceEndTextMarkerForTextMarker"])
- return [self doAXNextSentenceEndTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXPreviousSentenceStartTextMarkerForTextMarker"])
- return [self doAXPreviousSentenceStartTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXNextParagraphEndTextMarkerForTextMarker"])
- return [self doAXNextParagraphEndTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXPreviousParagraphStartTextMarkerForTextMarker"])
- return [self doAXPreviousParagraphStartTextMarkerForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXStyleTextMarkerRangeForTextMarker"])
- return [self doAXStyleTextMarkerRangeForTextMarker: textMarker];
-
- if ([attribute isEqualToString: @"AXLengthForTextMarkerRange"])
- return [self doAXLengthForTextMarkerRange: textMarkerRange];
-
- if ([self isTextControl]) {
- if ([attribute isEqualToString: (NSString*)kAXLineForIndexParameterizedAttribute])
- return [self doAXLineForIndex: number];
-
- if ([attribute isEqualToString: (NSString*)kAXRangeForLineParameterizedAttribute])
- return [self doAXRangeForLine: number];
-
- if ([attribute isEqualToString: (NSString*)kAXStringForRangeParameterizedAttribute])
- return rangeSet ? [self doAXStringForRange: range] : nil;
-
- if ([attribute isEqualToString: (NSString*)kAXRangeForPositionParameterizedAttribute])
- return pointSet ? [self doAXRangeForPosition: point] : nil;
-
- if ([attribute isEqualToString: (NSString*)kAXRangeForIndexParameterizedAttribute])
- return [self doAXRangeForIndex: number];
-
- if ([attribute isEqualToString: (NSString*)kAXBoundsForRangeParameterizedAttribute])
- return rangeSet ? [self doAXBoundsForRange: range] : nil;
-
- if ([attribute isEqualToString: (NSString*)kAXRTFForRangeParameterizedAttribute])
- return rangeSet ? [self doAXRTFForRange: range] : nil;
-
- if ([attribute isEqualToString: (NSString*)kAXAttributedStringForRangeParameterizedAttribute])
- return rangeSet ? [self doAXAttributedStringForRange: range] : nil;
-
- if ([attribute isEqualToString: (NSString*)kAXStyleRangeForIndexParameterizedAttribute])
- return [self doAXStyleRangeForIndex: number];
- }
-
- return nil;
-}
-
-- (id)accessibilityHitTest:(NSPoint)point
-{
- if (!m_renderer)
- return NSAccessibilityUnignoredAncestor(self);
-
- HitTestRequest request(true, true);
- HitTestResult result = HitTestResult(IntPoint(point));
- m_renderer->layer()->hitTest(request, result);
- if (!result.innerNode())
- return NSAccessibilityUnignoredAncestor(self);
- Node* node = result.innerNode()->shadowAncestorNode();
- RenderObject* obj = node->renderer();
- if (!obj)
- return NSAccessibilityUnignoredAncestor(self);
-
- return NSAccessibilityUnignoredAncestor(obj->document()->axObjectCache()->get(obj));
-}
-
-- (RenderObject*)rendererForView:(NSView*)view
-{
- // check for WebKit NSView that lets us find its bridge
- WebCoreFrameBridge* bridge = nil;
- if ([view conformsToProtocol:@protocol(WebCoreBridgeHolder)]) {
- NSView<WebCoreBridgeHolder>* bridgeHolder = (NSView<WebCoreBridgeHolder>*)view;
- bridge = [bridgeHolder webCoreBridge];
- }
-
- Frame* frame = [bridge _frame];
- if (!frame)
- return nil;
-
- Document* document = frame->document();
- if (!document)
- return nil;
-
- Node* node = document->ownerElement();
- if (!node)
- return nil;
-
- return node->renderer();
-}
-
-// _accessibilityParentForSubview is called by AppKit when moving up the tree
-// we override it so that we can return our WebCoreAXObject parent of an AppKit AX object
-- (id)_accessibilityParentForSubview:(NSView*)subview
-{
- RenderObject* renderer = [self rendererForView:subview];
- if (!renderer)
- return nil;
-
- WebCoreAXObject* obj = renderer->document()->axObjectCache()->get(renderer);
- return [obj parentObjectUnignored];
-}
-
-- (id)accessibilityFocusedUIElement
-{
- // get the focused node in the page
- Page* page = m_renderer->document()->page();
- if (!page)
- return nil;
-
- Document* focusedDocument = page->focusController()->focusedOrMainFrame()->document();
- Node* focusedNode = focusedDocument->focusedNode();
- if (!focusedNode || !focusedNode->renderer())
- focusedNode = focusedDocument;
-
- WebCoreAXObject* obj = focusedNode->renderer()->document()->axObjectCache()->get(focusedNode->renderer());
-
- // the HTML element, for example, is focusable but has an AX object that is ignored
- if ([obj accessibilityIsIgnored])
- obj = [obj parentObjectUnignored];
-
- return obj;
-}
-
-- (void)doSetAXSelectedTextMarkerRange: (WebCoreTextMarkerRange*)textMarkerRange
-{
- // extract the start and end VisiblePosition
- VisiblePosition startVisiblePosition = [self visiblePositionForStartOfTextMarkerRange: textMarkerRange];
- if (startVisiblePosition.isNull())
- return;
-
- VisiblePosition endVisiblePosition = [self visiblePositionForEndOfTextMarkerRange: textMarkerRange];
- if (endVisiblePosition.isNull())
- return;
-
- // make selection and tell the document to use it
- Selection newSelection = Selection(startVisiblePosition, endVisiblePosition);
- m_renderer->document()->frame()->selectionController()->setSelection(newSelection);
-}
-
-- (BOOL)canSetFocusAttribute
-{
- // NOTE: It would be more accurate to ask the document whether setFocusedNode() would
- // do anything. For example, it setFocusedNode() will do nothing if the current focused
- // node will not relinquish the focus.
- if (!m_renderer->element() || !m_renderer->element()->isEnabled())
- return NO;
-
- NSString* role = [self role];
- if ([role isEqualToString:@"AXLink"] ||
- [role isEqualToString:NSAccessibilityTextFieldRole] ||
- [role isEqualToString:NSAccessibilityTextAreaRole] ||
- [role isEqualToString:NSAccessibilityButtonRole] ||
- [role isEqualToString:NSAccessibilityPopUpButtonRole] ||
- [role isEqualToString:NSAccessibilityCheckBoxRole] ||
- [role isEqualToString:NSAccessibilityRadioButtonRole])
- return YES;
-
- return NO;
-}
-
-- (BOOL)canSetValueAttribute
-{
- return [self isTextControl];
-}
-
-- (BOOL)canSetTextRangeAttributes
-{
- return [self isTextControl];
-}
-
-- (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
-{
- if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
- return YES;
-
- if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
- return [self canSetFocusAttribute];
-
- if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
- return [self canSetValueAttribute];
-
- if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
- [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
- [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
- return [self canSetTextRangeAttributes];
-
- return NO;
-}
-
-- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
-{
- WebCoreTextMarkerRange* textMarkerRange = nil;
- NSNumber* number = nil;
- NSString* string = nil;
- NSRange range = {0, 0};
-
- // decode the parameter
- if ([[WebCoreViewFactory sharedFactory] objectIsTextMarkerRange:value])
- textMarkerRange = (WebCoreTextMarkerRange*) value;
-
- else if ([value isKindOfClass:[NSNumber self]])
- number = value;
-
- else if ([value isKindOfClass:[NSString self]])
- string = value;
-
- else if ([value isKindOfClass:[NSValue self]])
- range = [value rangeValue];
-
- // handle the command
- if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {
- ASSERT(textMarkerRange);
- [self doSetAXSelectedTextMarkerRange:textMarkerRange];
-
- } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {
- ASSERT(number);
- if ([self canSetFocusAttribute] && number) {
- if ([number intValue] == 0)
- m_renderer->document()->setFocusedNode(0);
- else {
- if (m_renderer->element()->isElementNode())
- static_cast<Element*>(m_renderer->element())->focus();
- else
- m_renderer->document()->setFocusedNode(m_renderer->element());
- }
- }
- } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
- if (!string)
- return;
- if (m_renderer->isTextField()) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
- input->setValue(string);
- } else if (m_renderer->isTextArea()) {
- HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(m_renderer->element());
- textArea->setValue(string);
- }
- } else if ([self isTextControl]) {
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
- if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
- // TODO: set selected text (ReplaceSelectionCommand). <rdar://problem/4712125>
- } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
- textControl->setSelectionRange(range.location, range.location + range.length);
- } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {
- // TODO: make range visible (scrollRectToVisible). <rdar://problem/4712101>
- }
- }
-}
-
-- (WebCoreAXObject*)observableObject
-{
- for (RenderObject* renderer = m_renderer; renderer && renderer->element(); renderer = renderer->parent()) {
- if (renderer->isTextField() || renderer->isTextArea())
- return renderer->document()->axObjectCache()->get(renderer);
- }
-
- return nil;
-}
-
-- (void)childrenChanged
-{
- [self clearChildren];
-
- if ([self accessibilityIsIgnored])
- [[self parentObject] childrenChanged];
-}
-
-- (void)clearChildren
-{
- [m_children release];
- m_children = nil;
-}
-
--(AXID)axObjectID
-{
- return m_id;
-}
-
--(void)setAXObjectID:(AXID) axObjectID
-{
- m_id = axObjectID;
-}
-
-- (void)removeAXObjectID
-{
- if (!m_id)
- return;
-
- m_renderer->document()->axObjectCache()->removeAXID(self);
-}
-
-@end
diff --git a/WebCore/bridge/mac/WebCoreScriptDebugger.h b/WebCore/bridge/mac/WebCoreScriptDebugger.h
deleted file mode 100644
index fd56632..0000000
--- a/WebCore/bridge/mac/WebCoreScriptDebugger.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-@class WebScriptObject; // from JavaScriptCore
-@class WebCoreScriptCallFrame; // below
-
-#ifdef __cplusplus
-class WebCoreScriptDebuggerImp;
-namespace KJS { class ExecState; }
-using KJS::ExecState;
-#else
-@class WebCoreScriptDebuggerImp;
-@class ExecState;
-#endif
-
-
-
-// "WebScriptDebugger" protocol - must be implemented by a delegate
-
-@protocol WebScriptDebugger
-
-- (WebScriptObject *)globalObject; // return the WebView's windowScriptObject
-- (id)newWrapperForFrame:(WebCoreScriptCallFrame *)frame; // return a (retained) stack-frame object
-
-// debugger callbacks
-- (void)parsedSource:(NSString *)source fromURL:(NSURL *)url sourceId:(int)sid startLine:(int)startLine errorLine:(int)errorLine errorMessage:(NSString *)errorMessage;
-- (void)enteredFrame:(WebCoreScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno;
-- (void)hitStatement:(WebCoreScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno;
-- (void)leavingFrame:(WebCoreScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno;
-- (void)exceptionRaised:(WebCoreScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno;
-
-@end
-
-
-
-@interface WebCoreScriptDebugger : NSObject
-{
-@private
- id<WebScriptDebugger> _delegate; // interface to WebKit (not retained)
- WebScriptObject *_globalObj; // the global object's proxy (not retained)
- WebCoreScriptCallFrame *_current; // top of stack
- WebCoreScriptDebuggerImp *_debugger; // [KJS::Debugger]
-}
-
-- (WebCoreScriptDebugger *)initWithDelegate:(id<WebScriptDebugger>)delegate;
-- (id<WebScriptDebugger>)delegate;
-
-@end
-
-
-
-@interface WebCoreScriptCallFrame : NSObject
-{
-@private
- id _wrapper; // WebKit's version of this object
- WebScriptObject *_globalObj; // the global object's proxy (not retained)
- WebCoreScriptCallFrame *_caller; // previous stack frame
- ExecState *_state; // [KJS::ExecState]
-}
-
-- (id)wrapper;
-- (WebCoreScriptCallFrame *)caller;
-
-- (NSArray *)scopeChain;
-- (NSString *)functionName;
-- (id)exception;
-- (id)evaluateWebScript:(NSString *)script;
-
-@end
diff --git a/WebCore/bridge/mac/WebCoreScriptDebugger.mm b/WebCore/bridge/mac/WebCoreScriptDebugger.mm
deleted file mode 100644
index 2f88e81..0000000
--- a/WebCore/bridge/mac/WebCoreScriptDebugger.mm
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "config.h"
-#import "WebCoreScriptDebugger.h"
-
-#import "DeprecatedString.h"
-#import "KURL.h"
-#import "PlatformString.h"
-#import "WebCoreObjCExtras.h"
-#import "WebScriptObjectPrivate.h"
-#import <JavaScriptCore/ExecState.h>
-#import <JavaScriptCore/JSGlobalObject.h>
-#import <JavaScriptCore/debugger.h>
-#import <JavaScriptCore/function.h>
-#import <JavaScriptCore/interpreter.h>
-
-using namespace KJS;
-using namespace WebCore;
-
-@interface WebCoreScriptDebugger (WebCoreScriptDebuggerInternal)
-
-- (WebCoreScriptCallFrame *)_enterFrame:(ExecState *)state;
-- (WebCoreScriptCallFrame *)_leaveFrame;
-
-@end
-
-@interface WebCoreScriptCallFrame (WebCoreScriptDebuggerInternal)
-
-- (WebCoreScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj caller:(WebCoreScriptCallFrame *)caller state:(ExecState *)state;
-- (void)_setWrapper:(id)wrapper;
-- (id)_convertValueToObjcValue:(JSValue *)value;
-
-@end
-
-// convert UString to NSString
-static NSString *toNSString(const UString &s)
-{
- if (s.isEmpty()) return nil;
- return [NSString stringWithCharacters:(const unichar *)s.data() length:s.size()];
-}
-
-// convert UString to NSURL
-static NSURL *toNSURL(const UString &s)
-{
- if (s.isEmpty()) return nil;
- return KURL(DeprecatedString(s)).getNSURL();
-}
-
-// C++ interface to KJS debugger callbacks
-
-class WebCoreScriptDebuggerImp : public KJS::Debugger {
-
- private:
- WebCoreScriptDebugger *_objc; // our ObjC half
- bool _nested; // true => this is a nested call
- WebCoreScriptCallFrame *_current; // top stack frame (copy of same field from ObjC side)
-
- public:
- // constructor
- WebCoreScriptDebuggerImp(WebCoreScriptDebugger *objc, JSGlobalObject* globalObject) : _objc(objc) {
- _nested = true;
- _current = [_objc _enterFrame:globalObject->globalExec()];
- attach(globalObject);
- [[_objc delegate] enteredFrame:_current sourceId:-1 line:-1];
- _nested = false;
- }
-
- // callbacks - relay to delegate
- virtual bool sourceParsed(ExecState *state, int sid, const UString &url, const UString &source, int lineNumber, int errorLine, const UString &errorMsg) {
- if (!_nested) {
- _nested = true;
- [[_objc delegate] parsedSource:toNSString(source) fromURL:toNSURL(url) sourceId:sid startLine:lineNumber errorLine:errorLine errorMessage:toNSString(errorMsg)];
- _nested = false;
- }
- return true;
- }
- virtual bool callEvent(ExecState *state, int sid, int lineno, JSObject *func, const List &args) {
- if (!_nested) {
- _nested = true;
- _current = [_objc _enterFrame:state];
- [[_objc delegate] enteredFrame:_current sourceId:sid line:lineno];
- _nested = false;
- }
- return true;
- }
- virtual bool atStatement(ExecState *state, int sid, int lineno, int lastLine) {
- if (!_nested) {
- _nested = true;
- [[_objc delegate] hitStatement:_current sourceId:sid line:lineno];
- _nested = false;
- }
- return true;
- }
- virtual bool returnEvent(ExecState *state, int sid, int lineno, JSObject *func) {
- if (!_nested) {
- _nested = true;
- [[_objc delegate] leavingFrame:_current sourceId:sid line:lineno];
- _current = [_objc _leaveFrame];
- _nested = false;
- }
- return true;
- }
- virtual bool exception(ExecState *state, int sid, int lineno, JSValue *exception) {
- if (!_nested) {
- _nested = true;
- [[_objc delegate] exceptionRaised:_current sourceId:sid line:lineno];
- _nested = false;
- }
- return true;
- }
-
-};
-
-
-
-// WebCoreScriptDebugger
-//
-// This is the main (behind-the-scenes) debugger class in WebCore.
-//
-// The WebCoreScriptDebugger has two faces, one for Objective-C (this class), and another (WebCoreScriptDebuggerImp)
-// for C++. The ObjC side creates the C++ side, which does the real work of attaching to the global object and
-// forwarding the KJS debugger callbacks to the delegate.
-
-@implementation WebCoreScriptDebugger
-
-#ifndef BUILDING_ON_TIGER
-+ (void)initialize
-{
- WebCoreObjCFinalizeOnMainThread(self);
-}
-#endif
-
-- (WebCoreScriptDebugger *)initWithDelegate:(id<WebScriptDebugger>)delegate
-{
- if ((self = [super init])) {
- _delegate = delegate;
- _globalObj = [_delegate globalObject];
- _debugger = new WebCoreScriptDebuggerImp(self, [_globalObj _rootObject]->globalObject());
- }
- return self;
-}
-
-- (void)dealloc
-{
- [_current release];
- delete _debugger;
- [super dealloc];
-}
-
-- (void)finalize
-{
- delete _debugger;
- [super finalize];
-}
-
-- (id<WebScriptDebugger>)delegate
-{
- return _delegate;
-}
-
-@end
-
-
-
-@implementation WebCoreScriptDebugger (WebCoreScriptDebuggerInternal)
-
-- (WebCoreScriptCallFrame *)_enterFrame:(ExecState *)state;
-{
- WebCoreScriptCallFrame *callee = [[WebCoreScriptCallFrame alloc] _initWithGlobalObject:_globalObj caller:_current state:state];
- [callee _setWrapper:[_delegate newWrapperForFrame:callee]];
- return _current = callee;
-}
-
-- (WebCoreScriptCallFrame *)_leaveFrame;
-{
- WebCoreScriptCallFrame *caller = [[_current caller] retain];
- [_current release];
- return _current = caller;
-}
-
-@end
-
-
-
-// WebCoreScriptCallFrame
-//
-// One of these is created to represent each stack frame. Additionally, there is a "global"
-// frame to represent the outermost scope. This global frame is always the last frame in
-// the chain of callers.
-//
-// The delegate can assign a "wrapper" to each frame object so it can relay calls through its
-// own exported interface. This class is private to WebCore (and the delegate).
-
-@implementation WebCoreScriptCallFrame (WebCoreScriptDebuggerInternal)
-
-- (WebCoreScriptCallFrame *)_initWithGlobalObject:(WebScriptObject *)globalObj caller:(WebCoreScriptCallFrame *)caller state:(ExecState *)state
-{
- if ((self = [super init])) {
- _globalObj = globalObj;
- _caller = caller; // (already retained)
- _state = state;
- }
- return self;
-}
-
-- (void)_setWrapper:(id)wrapper
-{
- _wrapper = wrapper; // (already retained)
-}
-
-- (id)_convertValueToObjcValue:(JSValue *)value
-{
- if (!value)
- return nil;
-
- if (value == [_globalObj _imp])
- return _globalObj;
-
- Bindings::RootObject* root1 = [_globalObj _originRootObject];
- if (!root1)
- return nil;
-
- Bindings::RootObject* root2 = [_globalObj _rootObject];
- if (!root2)
- return nil;
-
- return [WebScriptObject _convertValueToObjcValue:value originRootObject:root1 rootObject:root2];
-}
-
-@end
-
-
-
-@implementation WebCoreScriptCallFrame
-
-- (void)dealloc
-{
- [_wrapper release];
- [_caller release];
- [super dealloc];
-}
-
-- (id)wrapper
-{
- return _wrapper;
-}
-
-- (WebCoreScriptCallFrame *)caller
-{
- return _caller;
-}
-
-
-// Returns an array of scope objects (most local first).
-// The properties of each scope object are the variables for that scope.
-// Note that the last entry in the array will _always_ be the global object (windowScriptObject),
-// whose properties are the global variables.
-
-- (NSArray *)scopeChain
-{
- if (!_state->scopeNode()) { // global frame
- return [NSArray arrayWithObject:_globalObj];
- }
-
- ScopeChain chain = _state->scopeChain();
- NSMutableArray *scopes = [[NSMutableArray alloc] init];
-
- while (!chain.isEmpty()) {
- [scopes addObject:[self _convertValueToObjcValue:chain.top()]];
- chain.pop();
- }
-
- NSArray *result = [NSArray arrayWithArray:scopes];
- [scopes release];
- return result;
-}
-
-
-// Returns the name of the function for this frame, if available.
-// Returns nil for anonymous functions and for the global frame.
-
-- (NSString *)functionName
-{
- if (_state->scopeNode()) {
- FunctionImp *func = _state->function();
- if (func) {
- Identifier fn = func->functionName();
- return toNSString(fn.ustring());
- }
- }
- return nil;
-}
-
-
-// Returns the pending exception for this frame (nil if none).
-
-- (id)exception
-{
- if (!_state->hadException()) return nil;
- return [self _convertValueToObjcValue:_state->exception()];
-}
-
-
-// Evaluate some JavaScript code in the context of this frame.
-// The code is evaluated as if by "eval", and the result is returned.
-// If there is an (uncaught) exception, it is returned as though _it_ were the result.
-// Calling this method on the global frame is not quite the same as calling the WebScriptObject
-// method of the same name, due to the treatment of exceptions.
-
-// FIXME: If "script" contains var declarations, the machinery to handle local variables
-// efficiently in JavaScriptCore will not work properly. This could lead to crashes or
-// incorrect variable values. So this is not appropriate for evaluating arbitrary script.
-- (id)evaluateWebScript:(NSString *)script
-{
- JSLock lock;
-
- UString code = String(script);
-
- ExecState* state = _state;
- JSGlobalObject* globalObject = state->dynamicGlobalObject();
-
- // find "eval"
- JSObject *eval = NULL;
- if (state->scopeNode()) { // "eval" won't work without context (i.e. at global scope)
- JSValue *v = globalObject->get(state, "eval");
- if (v->isObject() && static_cast<JSObject *>(v)->implementsCall())
- eval = static_cast<JSObject *>(v);
- else
- // no "eval" - fallback operates on global exec state
- state = globalObject->globalExec();
- }
-
- JSValue *savedException = state->exception();
- state->clearException();
-
- // evaluate
- JSValue *result;
- if (eval) {
- List args;
- args.append(jsString(code));
- result = eval->call(state, NULL, args);
- } else
- // no "eval", or no context (i.e. global scope) - use global fallback
- result = Interpreter::evaluate(state, UString(), 0, code.data(), code.size(), globalObject).value();
-
- if (state->hadException())
- result = state->exception(); // (may be redundant depending on which eval path was used)
- state->setException(savedException);
-
- return [self _convertValueToObjcValue:result];
-}
-
-@end
diff --git a/WebCore/bridge/make_testbindings b/WebCore/bridge/make_testbindings
new file mode 100755
index 0000000..1f528fe
--- /dev/null
+++ b/WebCore/bridge/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/WebCore/bridge/npapi.h b/WebCore/bridge/npapi.h
new file mode 100644
index 0000000..84d266b
--- /dev/null
+++ b/WebCore/bridge/npapi.h
@@ -0,0 +1,838 @@
+/* ***** 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
+
+#if defined(XP_MACOSX) && defined(__LP64__)
+#define NP_NO_QUICKDRAW
+#define NP_NO_CARBON
+#endif
+
+#ifdef XP_MACOSX
+ #include <ApplicationServices/ApplicationServices.h>
+ #include <OpenGL/OpenGL.h>
+#ifndef NP_NO_CARBON
+ #include <Carbon/Carbon.h>
+#endif
+#endif
+
+#ifdef XP_UNIX
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ #include <stdio.h>
+#endif
+
+#ifdef XP_WIN
+ #include <windows.h>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* Plugin Version Constants */
+/*----------------------------------------------------------------------*/
+
+#define NP_VERSION_MAJOR 0
+#define NP_VERSION_MINOR 20
+
+
+
+/*----------------------------------------------------------------------*/
+/* 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 */
+
+ NPPVpluginUrlRequestsDisplayedBool = 17, /* Not implemented in WebKit */
+
+ /* Checks if the plugin is interested in receiving the http body of
+ * failed http requests (http status != 200).
+ */
+ NPPVpluginWantsAllNetworkStreams = 18,
+
+#ifdef XP_MACOSX
+ /* Used for negotiating drawing models */
+ NPPVpluginDrawingModel = 1000,
+ /* Used for negotiating event models */
+ NPPVpluginEventModel = 1001,
+ /* The plug-in text input vtable */
+ NPPVpluginTextInputFuncs = 1002,
+ /* In the NPDrawingModelCoreAnimation drawing model, the browser asks the plug-in for a Core Animation layer. */
+ NPPVpluginCoreAnimationLayer = 1003
+#endif
+
+#ifdef ANDROID
+ NPPFakeValueToForce32Bits = 0x7FFFFFFF
+#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 = 16,
+
+ NPNVSupportsWindowless = 17
+
+#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) */
+ , NPNVsupportsCoreAnimationBool = 2003 /* TRUE if the browser supports the CoreAnimation drawing model */
+
+#ifndef NP_NO_CARBON
+ , NPNVsupportsCarbonBool = 3000 /* TRUE if the browser supports the Carbon event model */
+#endif
+ , NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
+
+ , NPNVbrowserTextInputFuncs = 1002 /* The browser text input vtable */
+#endif /* XP_MACOSX */
+
+#ifdef ANDROID
+ , NPNFakeValueToForce32Bits = 0x7FFFFFFF
+#endif
+} 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,
+ NPDrawingModelCoreAnimation
+} NPDrawingModel;
+
+/*
+ * The event model for a Mac OS X plugin. These are the possible values for the NPNVpluginEventModel variable.
+ */
+
+typedef enum {
+#ifndef NP_NO_CARBON
+ NPEventModelCarbon = 0,
+#endif
+ NPEventModelCocoa = 1,
+} NPEventModel;
+
+typedef enum {
+ NPCocoaEventDrawRect = 1,
+ NPCocoaEventMouseDown,
+ NPCocoaEventMouseUp,
+ NPCocoaEventMouseMoved,
+ NPCocoaEventMouseEntered,
+ NPCocoaEventMouseExited,
+ NPCocoaEventMouseDragged,
+ NPCocoaEventKeyDown,
+ NPCocoaEventKeyUp,
+ NPCocoaEventFlagsChanged,
+ NPCocoaEventFocusChanged,
+ NPCocoaEventWindowFocusChanged,
+ NPCocoaEventScrollWheel,
+} NPCocoaEventType;
+
+typedef struct _NPNSString NPNSString;
+typedef struct _NPNSWindow NPNSWindow;
+typedef struct _NPNSMenu NPNSMenu;
+
+typedef struct _NPCocoaEvent {
+ NPCocoaEventType type;
+ uint32 version;
+
+ union {
+ struct {
+ uint32 modifierFlags;
+ double pluginX;
+ double pluginY;
+ int32 buttonNumber;
+ int32 clickCount;
+ double deltaX;
+ double deltaY;
+ double deltaZ;
+ } mouse;
+ struct {
+ uint32 modifierFlags;
+ NPNSString *characters;
+ NPNSString *charactersIgnoringModifiers;
+ NPBool isARepeat;
+ uint16 keyCode;
+ } key;
+ struct {
+ double x;
+ double y;
+ double width;
+ double height;
+ } draw;
+ struct {
+ NPBool hasFocus;
+ } focus;
+ } data;
+} NPCocoaEvent;
+
+#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;
+
+#ifdef XP_MACOSX
+typedef NPNSMenu NPMenu;
+#else
+typedef void * NPMenu;
+#endif
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+
+#ifndef NP_NO_CARBON
+typedef EventRecord NPEvent;
+#endif
+
+#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;
+#ifdef NP_NO_CARBON
+ NPNSWindow *window;
+#else
+ void *window; // Can be either an NSWindow or a WindowRef depending on the event model
+#endif
+} 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;
+#ifdef NP_NO_CARBON
+ NPNSWindow *window;
+#else
+ void *window; // Can be either an NSWindow or a WindowRef depending on the event model
+#endif
+} 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
+#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
+#define NPVERS_MACOSX_HAS_EVENT_MODELS 20
+
+/*----------------------------------------------------------------------*/
+/* 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);
+void NPN_PluginThreadAsyncCall(NPP instance, void (*func) (void *), void *userData);
+uint32 NPN_ScheduleTimer(NPP instance, uint32 interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32 timerID));
+void NPN_UnscheduleTimer(NPP instance, uint32 timerID);
+NPError NPN_PopUpContextMenu(NPP instance, NPMenu* menu);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* _NPAPI_H_ */
diff --git a/WebCore/bridge/npruntime.cpp b/WebCore/bridge/npruntime.cpp
new file mode 100644
index 0000000..bef3676
--- /dev/null
+++ b/WebCore/bridge/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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "npruntime_internal.h"
+#include "npruntime_impl.h"
+#include "npruntime_priv.h"
+
+#include "c_utility.h"
+#include <kjs/identifier.h>
+#include <runtime/JSLock.h>
+#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+
+using namespace JSC::Bindings;
+
+typedef HashMap<RefPtr<JSC::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;
+
+ JSC::JSLock lock(false);
+
+ 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 // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/WebCore/bridge/npruntime.h b/WebCore/bridge/npruntime.h
new file mode 100644
index 0000000..8a285be
--- /dev/null
+++ b/WebCore/bridge/npruntime.h
@@ -0,0 +1,357 @@
+/*
+ * 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"
+
+/*
+ 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);
+typedef bool (*NPConstructFunctionPtr)(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+
+/*
+ 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;
+ NPConstructFunctionPtr construct;
+};
+
+#define NP_CLASS_STRUCT_VERSION 3
+#define NP_CLASS_STRUCT_VERSION_ENUM 2
+#define NP_CLASS_STRUCT_VERSION_CTOR 3
+
+#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \
+ ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
+#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass) \
+ ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR)
+
+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);
+bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+
+/*
+ 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/WebCore/bridge/npruntime_impl.h b/WebCore/bridge/npruntime_impl.h
new file mode 100644
index 0000000..559f340
--- /dev/null
+++ b/WebCore/bridge/npruntime_impl.h
@@ -0,0 +1,66 @@
+/*
+ * 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 ENABLE(NETSCAPE_PLUGIN_API)
+
+#include "npruntime_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void _NPN_ReleaseVariantValue(NPVariant*);
+extern NPIdentifier _NPN_GetStringIdentifier(const NPUTF8*);
+extern void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers);
+extern NPIdentifier _NPN_GetIntIdentifier(int32_t);
+extern bool _NPN_IdentifierIsString(NPIdentifier);
+extern NPUTF8* _NPN_UTF8FromIdentifier(NPIdentifier);
+extern int32_t _NPN_IntFromIdentifier(NPIdentifier);
+extern NPObject* _NPN_CreateObject(NPP, NPClass*);
+extern NPObject* _NPN_RetainObject(NPObject*);
+extern void _NPN_ReleaseObject(NPObject*);
+extern void _NPN_DeallocateObject(NPObject*);
+extern bool _NPN_Invoke(NPP, NPObject*, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result);
+extern bool _NPN_InvokeDefault(NPP, NPObject*, const NPVariant* args, uint32_t argCount, NPVariant* result);
+extern bool _NPN_Evaluate(NPP, NPObject*, NPString*, NPVariant* result);
+extern bool _NPN_GetProperty(NPP, NPObject*, NPIdentifier, NPVariant* result);
+extern bool _NPN_SetProperty(NPP, NPObject*, NPIdentifier, const NPVariant*);
+extern bool _NPN_RemoveProperty(NPP, NPObject*, NPIdentifier);
+extern bool _NPN_HasProperty(NPP, NPObject*, NPIdentifier);
+extern bool _NPN_HasMethod(NPP, NPObject*, NPIdentifier);
+extern void _NPN_SetException(NPObject*, const NPUTF8*);
+extern bool _NPN_Enumerate(NPP, NPObject*, NPIdentifier**, uint32_t* count);
+extern bool _NPN_Construct(NPP, NPObject*, const NPVariant* args, uint32_t argCount, NPVariant *result);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+
+#endif
diff --git a/WebCore/bridge/npruntime_internal.h b/WebCore/bridge/npruntime_internal.h
new file mode 100644
index 0000000..5ccdecd
--- /dev/null
+++ b/WebCore/bridge/npruntime_internal.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007-2008 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 "npapi.h"
+#include "npfunctions.h"
+#include "npruntime.h"
+
+#ifdef XP_UNIX
+ #include <X11/Xresource.h>
+
+ #undef None
+ #undef Above
+ #undef Below
+ #undef Auto
+ #undef Complex
+ #undef Status
+ #undef CursorShape
+ #undef FocusIn
+ #undef FocusOut
+ #undef KeyPress
+ #undef KeyRelease
+ #undef Unsorted
+ #undef Bool
+ #undef FontChange
+ #undef GrayScale
+#endif
diff --git a/WebCore/bridge/GlobalHistory.h b/WebCore/bridge/npruntime_priv.h
index 4857f6f..301c163 100644
--- a/WebCore/bridge/GlobalHistory.h
+++ b/WebCore/bridge/npruntime_priv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -23,15 +23,19 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef GlobalHistory_h
-#define GlobalHistory_h
+#ifndef NP_RUNTIME_PRIV_H_
+#define NP_RUNTIME_PRIV_H_
-#include <wtf/unicode/Unicode.h>
+#if ENABLE(NETSCAPE_PLUGIN_API)
-namespace WebCore {
+#include "npruntime_internal.h"
- bool historyContains(const UChar* characters, unsigned length);
+/*
+ NPN_InitializeVariantWithStringCopy() will copy string data. The string data
+ will be deallocated by calls to NPReleaseVariantValue().
+*/
+void NPN_InitializeVariantWithStringCopy(NPVariant*, const NPString*);
-} // namespace WebCore
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
+#endif
-#endif // GlobalHistory_h
diff --git a/WebCore/bridge/mac/GlobalHistoryMac.mm b/WebCore/bridge/objc/WebScriptObject.h
index 466f60e..357d42a 100644
--- a/WebCore/bridge/mac/GlobalHistoryMac.mm
+++ b/WebCore/bridge/objc/WebScriptObject.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,17 +23,22 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import "config.h"
-#import "GlobalHistory.h"
+#import <Foundation/Foundation.h>
+#import "runtime_root.h"
-#import "WebCoreHistory.h"
+@class WebUndefined;
-namespace WebCore {
+@protocol WebScriptObject
++ (NSString *)webScriptNameForSelector:(SEL)aSelector;
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
++ (NSString *)webScriptNameForKey:(const char *)name;
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
-bool historyContains(const UChar* characters, unsigned length)
-{
- // the other side of the bridge is careful not to throw exceptions here
- return [[WebCoreHistory historyProvider] containsURL:characters length:length];
-}
++ (id)_convertValueToObjcValue:(JSC::JSValue*)value originRootObject:(JSC::Bindings::RootObject*)originRootObject rootObject:(JSC::Bindings::RootObject*)rootObject;
+- _initWithJSObject:(JSC::JSObject*)imp originRootObject:(PassRefPtr<JSC::Bindings::RootObject>)originRootObject rootObject:(PassRefPtr<JSC::Bindings::RootObject>)rootObject;
+- (JSC::JSObject *)_imp;
+@end
-} // namespace WebCore
+@protocol WebUndefined
++ (WebUndefined *)undefined;
+@end
diff --git a/WebCore/bridge/objc/objc_class.h b/WebCore/bridge/objc/objc_class.h
new file mode 100644
index 0000000..d96c604
--- /dev/null
+++ b/WebCore/bridge/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 "objc_runtime.h"
+
+namespace JSC {
+namespace Bindings {
+
+class ObjcClass : public Class
+{
+protected:
+ ObjcClass (ClassStructPtr aClass); // Use classForIsA to create an ObjcClass.
+
+public:
+ // Return the cached ObjC of the specified name.
+ static ObjcClass *classForIsA(ClassStructPtr);
+
+ virtual 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 JSC
+
+#endif
diff --git a/WebCore/bridge/objc/objc_class.mm b/WebCore/bridge/objc/objc_class.mm
new file mode 100644
index 0000000..79991c2
--- /dev/null
+++ b/WebCore/bridge/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 JSC {
+namespace Bindings {
+
+static void deleteMethod(CFAllocatorRef, const void* value)
+{
+ delete static_cast<const Method*>(value);
+}
+
+static void deleteField(CFAllocatorRef, const void* value)
+{
+ delete static_cast<const Field*>(value);
+}
+
+const CFDictionaryValueCallBacks MethodDictionaryValueCallBacks = { 0, 0, &deleteMethod, 0 , 0 };
+const CFDictionaryValueCallBacks FieldDictionaryValueCallBacks = { 0, 0, &deleteField, 0 , 0 };
+
+ObjcClass::ObjcClass(ClassStructPtr aClass)
+ : _isa(aClass)
+ , _methods(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &MethodDictionaryValueCallBacks))
+ , _fields(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &FieldDictionaryValueCallBacks))
+{
+}
+
+static CFMutableDictionaryRef classesByIsA = 0;
+
+static void _createClassesByIsAIfNecessary()
+{
+ if (!classesByIsA)
+ classesByIsA = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+}
+
+ObjcClass* ObjcClass::classForIsA(ClassStructPtr isa)
+{
+ _createClassesByIsAIfNecessary();
+
+ ObjcClass* aClass = (ObjcClass*)CFDictionaryGetValue(classesByIsA, isa);
+ if (!aClass) {
+ aClass = new ObjcClass(isa);
+ CFDictionaryAddValue(classesByIsA, isa, aClass);
+ }
+
+ return aClass;
+}
+
+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* exec, Instance* instance, const Identifier &propertyName)
+{
+ ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);
+ id targetObject = objcInstance->getObject();
+
+ if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return jsUndefined();
+ return new (exec) ObjcFallbackObjectImp(exec, objcInstance, propertyName);
+}
+
+}
+}
diff --git a/WebCore/bridge/win/FrameWin.h b/WebCore/bridge/objc/objc_header.h
index 405c7b2..07954a1 100644
--- a/WebCore/bridge/win/FrameWin.h
+++ b/WebCore/bridge/objc/objc_header.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -23,19 +23,31 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef FrameWin_H
-#define FrameWin_H
+#ifndef KJS_BINDINGS_OBJC_HEADER_H
+#define KJS_BINDINGS_OBJC_HEADER_H
-#include "Frame.h"
+#ifdef __OBJC__
-// Forward declared so we don't need wingdi.h.
-typedef struct HBITMAP__* HBITMAP;
+#include <objc/objc.h>
+#include <objc/objc-class.h>
+#include <objc/objc-runtime.h>
-namespace WebCore {
+typedef Class ClassStructPtr;
+typedef id ObjectStructPtr;
+typedef Method MethodStructPtr;
+typedef Ivar IvarStructPtr;
- HBITMAP imageFromSelection(Frame* frame, bool forceWhiteText);
- void computePageRectsForFrame(Frame*, const IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor,Vector<IntRect>& pages, int& pageHeight);
+@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/WebCore/bridge/objc/objc_instance.h b/WebCore/bridge/objc/objc_instance.h
new file mode 100644
index 0000000..dc7a362
--- /dev/null
+++ b/WebCore/bridge/objc/objc_instance.h
@@ -0,0 +1,90 @@
+/*
+ * 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 "objc_class.h"
+#include "objc_utility.h"
+
+namespace JSC {
+
+namespace Bindings {
+
+class ObjcClass;
+
+class ObjcInstance : public Instance {
+public:
+ static PassRefPtr<ObjcInstance> create(ObjectStructPtr instance, PassRefPtr<RootObject> rootObject)
+ {
+ return adoptRef(new ObjcInstance(instance, rootObject));
+ }
+
+ 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 JSValue* valueOf(ExecState*) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual JSValue* invokeMethod(ExecState*, const MethodList&, const ArgList&);
+ virtual bool supportsInvokeDefaultMethod() const;
+ virtual JSValue* invokeDefaultMethod(ExecState*, const ArgList&);
+
+ virtual bool supportsSetValueOfUndefinedField();
+ virtual void setValueOfUndefinedField(ExecState*, const Identifier&, JSValue*);
+
+ virtual JSValue* getValueOfUndefinedField(ExecState*, const Identifier& property) const;
+
+ ObjectStructPtr getObject() const { return _instance.get(); }
+
+ JSValue* stringValue(ExecState*) const;
+ JSValue* numberValue(ExecState*) const;
+ JSValue* booleanValue() const;
+
+ virtual BindingLanguage getBindingLanguage() const { return ObjectiveCLanguage; }
+
+protected:
+ virtual void virtualBegin();
+ virtual void virtualEnd();
+
+private:
+ static void moveGlobalExceptionToExecState(ExecState*);
+
+ ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject>);
+
+ RetainPtr<ObjectStructPtr> _instance;
+ mutable ObjcClass *_class;
+ ObjectStructPtr _pool;
+ int _beginCount;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif // BINDINGS_OBJC_INSTANCE_H_
diff --git a/WebCore/bridge/objc/objc_instance.mm b/WebCore/bridge/objc/objc_instance.mm
new file mode 100644
index 0000000..6a714b9
--- /dev/null
+++ b/WebCore/bridge/objc/objc_instance.mm
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2004, 2008 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 "FoundationExtras.h"
+#import "WebScriptObject.h"
+#include <runtime/Error.h>
+#include <runtime/JSLock.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 JSC::Bindings;
+using namespace JSC;
+
+static NSString* s_exception;
+static JSGlobalObject* s_exceptionEnvironment; // No need to protect this value, since we just use it for a pointer comparison.
+
+void ObjcInstance::setGlobalException(NSString* exception, JSGlobalObject* exceptionEnvironment)
+{
+ HardRelease(s_exception);
+ HardRetain(exception);
+ s_exception = exception;
+
+ s_exceptionEnvironment = exceptionEnvironment;
+}
+
+void ObjcInstance::moveGlobalExceptionToExecState(ExecState* exec)
+{
+ if (!s_exception) {
+ ASSERT(!s_exceptionEnvironment);
+ return;
+ }
+
+ if (!s_exceptionEnvironment || s_exceptionEnvironment == exec->dynamicGlobalObject()) {
+ JSLock lock(false);
+ throwError(exec, GeneralError, s_exception);
+ }
+
+ HardRelease(s_exception);
+ s_exception = 0;
+
+ s_exceptionEnvironment = 0;
+}
+
+ObjcInstance::ObjcInstance(ObjectStructPtr instance, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+ , _instance(instance)
+ , _class(0)
+ , _pool(0)
+ , _beginCount(0)
+{
+}
+
+ObjcInstance::~ObjcInstance()
+{
+ // -finalizeForWebScript and -dealloc/-finalize may require autorelease pools.
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ if ([_instance.get() respondsToSelector:@selector(finalizeForWebScript)])
+ [_instance.get() performSelector:@selector(finalizeForWebScript)];
+ _instance = 0;
+ [pool drain];
+}
+
+void ObjcInstance::virtualBegin()
+{
+ if (!_pool)
+ _pool = [[NSAutoreleasePool alloc] init];
+ _beginCount++;
+}
+
+void ObjcInstance::virtualEnd()
+{
+ _beginCount--;
+ ASSERT(_beginCount >= 0);
+ if (!_beginCount) {
+ [_pool drain];
+ _pool = 0;
+ }
+}
+
+Bindings::Class* ObjcInstance::getClass() const
+{
+ if (!_instance)
+ return 0;
+ if (!_class)
+ _class = ObjcClass::classForIsA(_instance->isa);
+ return static_cast<Bindings::Class*>(_class);
+}
+
+bool ObjcInstance::supportsInvokeDefaultMethod() const
+{
+ return [_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)];
+}
+
+JSValue* ObjcInstance::invokeMethod(ExecState* exec, const MethodList &methodList, const ArgList &args)
+{
+ JSValue* result = jsUndefined();
+
+ JSLock::DropAllLocks dropAllLocks(false); // Can't put this inside the @try scope because it unwinds incorrectly.
+
+ setGlobalException(nil);
+
+ // 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(exec, 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(exec, 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) {
+}
+ moveGlobalExceptionToExecState(exec);
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue*&>(result);
+}
+
+JSValue* ObjcInstance::invokeDefaultMethod(ExecState* exec, const ArgList &args)
+{
+ JSValue* result = jsUndefined();
+
+ JSLock::DropAllLocks dropAllLocks(false); // Can't put this inside the @try scope because it unwinds incorrectly.
+ setGlobalException(nil);
+
+@try {
+ if (![_instance.get() respondsToSelector:@selector(invokeDefaultMethodWithArguments:)])
+ return result;
+
+ NSMethodSignature* signature = [_instance.get() methodSignatureForSelector:@selector(invokeDefaultMethodWithArguments:)];
+ NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
+ [invocation setSelector:@selector(invokeDefaultMethodWithArguments:)];
+ [invocation setTarget:_instance.get()];
+
+ if (objcValueTypeForType([signature methodReturnType]) != ObjcObjectType) {
+ NSLog(@"Incorrect signature for invokeDefaultMethodWithArguments: -- return type must be object.");
+ return result;
+ }
+
+ NSMutableArray* objcArgs = [NSMutableArray array];
+ unsigned count = args.size();
+ for (unsigned i = 0; i < count; i++) {
+ ObjcValue value = convertValueToObjcValue(exec, args.at(exec, 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) {
+}
+ moveGlobalExceptionToExecState(exec);
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue*&>(result);
+}
+
+bool ObjcInstance::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(false); // 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:)]){
+ setGlobalException(nil);
+
+ 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:.
+ }
+
+ moveGlobalExceptionToExecState(exec);
+ }
+}
+
+JSValue* ObjcInstance::getValueOfUndefinedField(ExecState* exec, const Identifier& property) const
+{
+ JSValue* result = jsUndefined();
+
+ id targetObject = getObject();
+
+ JSLock::DropAllLocks dropAllLocks(false); // 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:)]){
+ setGlobalException(nil);
+
+ @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:.
+ }
+
+ moveGlobalExceptionToExecState(exec);
+ }
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue*&>(result);
+}
+
+JSValue* ObjcInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ if ([_instance.get() isKindOfClass:[NSString class]])
+ return stringValue(exec);
+ if ([_instance.get() isKindOfClass:[NSNumber class]])
+ return numberValue(exec);
+ return valueOf(exec);
+}
+
+JSValue* ObjcInstance::stringValue(ExecState* exec) const
+{
+ return convertNSStringToString(exec, [getObject() description]);
+}
+
+JSValue* ObjcInstance::numberValue(ExecState* exec) const
+{
+ // FIXME: Implement something sensible
+ return jsNumber(exec, 0);
+}
+
+JSValue* ObjcInstance::booleanValue() const
+{
+ // FIXME: Implement something sensible
+ return jsBoolean(false);
+}
+
+JSValue* ObjcInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
diff --git a/WebCore/bridge/objc/objc_runtime.h b/WebCore/bridge/objc/objc_runtime.h
new file mode 100644
index 0000000..5f0d8e2
--- /dev/null
+++ b/WebCore/bridge/objc/objc_runtime.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KJS_BINDINGS_OBJC_RUNTIME_H
+#define KJS_BINDINGS_OBJC_RUNTIME_H
+
+#include "objc_header.h"
+#include "runtime.h"
+#include <runtime/JSGlobalObject.h>
+#include <wtf/RetainPtr.h>
+
+namespace JSC {
+namespace Bindings {
+
+ClassStructPtr webScriptObjectClass();
+ClassStructPtr webUndefinedClass();
+
+class ObjcInstance;
+
+class ObjcField : public Field {
+public:
+ ObjcField(IvarStructPtr);
+ ObjcField(CFStringRef name);
+
+ virtual JSValue* valueFromInstance(ExecState*, const Instance*) const;
+ virtual void setValueToInstance(ExecState*, const Instance*, JSValue*) const;
+
+ 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(ExecState*, ObjcInstance*, const Identifier& propertyName);
+
+ static const ClassInfo s_info;
+
+ const Identifier& propertyName() const { return _item; }
+
+ static ObjectPrototype* createPrototype(ExecState* exec)
+ {
+ return exec->lexicalGlobalObject()->objectPrototype();
+ }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+private:
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ virtual CallType getCallData(CallData&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual bool toBoolean(ExecState*) const;
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ RefPtr<ObjcInstance> _instance;
+ Identifier _item;
+};
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif
diff --git a/WebCore/bridge/objc/objc_runtime.mm b/WebCore/bridge/objc/objc_runtime.mm
new file mode 100644
index 0000000..e6729a8
--- /dev/null
+++ b/WebCore/bridge/objc/objc_runtime.mm
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "objc_runtime.h"
+
+#include "JSDOMBinding.h"
+#include "WebScriptObject.h"
+#include "objc_instance.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include <runtime/Error.h>
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <runtime/ObjectPrototype.h>
+#include <wtf/RetainPtr.h>
+
+using namespace WebCore;
+
+namespace JSC {
+namespace Bindings {
+
+ClassStructPtr webScriptObjectClass()
+{
+ static ClassStructPtr<WebScriptObject> webScriptObjectClass = NSClassFromString(@"WebScriptObject");
+ return webScriptObjectClass;
+}
+
+ClassStructPtr webUndefinedClass()
+{
+ static ClassStructPtr<WebUndefined> webUndefinedClass = NSClassFromString(@"WebUndefined");
+ return webUndefinedClass;
+}
+
+// ---------------------- ObjcMethod ----------------------
+
+ObjcMethod::ObjcMethod(ClassStructPtr aClass, 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(false); // 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(false);
+ throwError(exec, GeneralError, [localException reason]);
+ JSLock::unlock(false);
+ }
+
+ // Work around problem in some versions of GCC where result gets marked volatile and
+ // it can't handle copying from a volatile to non-volatile.
+ return const_cast<JSValue*&>(result);
+}
+
+static id convertValueToObjcObject(ExecState* exec, JSValue* value)
+{
+ RefPtr<RootObject> rootObject = findRootObject(exec->dynamicGlobalObject());
+ if (!rootObject)
+ return nil;
+ return [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:rootObject.get() rootObject:rootObject.get()];
+}
+
+void ObjcField::setValueToInstance(ExecState* exec, const Instance* instance, JSValue* aValue) const
+{
+ id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();
+ id value = convertValueToObjcObject(exec, aValue);
+
+ JSLock::DropAllLocks dropAllLocks(false); // 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(false);
+ throwError(exec, GeneralError, [localException reason]);
+ JSLock::unlock(false);
+ }
+}
+
+// ---------------------- 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::s_info = { "ObjcFallbackObject", 0, 0, 0 };
+
+ObjcFallbackObjectImp::ObjcFallbackObjectImp(ExecState* exec, ObjcInstance* i, const Identifier& propertyName)
+ : JSObject(getDOMStructure<ObjcFallbackObjectImp>(exec))
+ , _instance(i)
+ , _item(propertyName)
+{
+}
+
+bool ObjcFallbackObjectImp::getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot& slot)
+{
+ // keep the prototype from getting called instead of just returning false
+ slot.setUndefined();
+ return true;
+}
+
+void ObjcFallbackObjectImp::put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&)
+{
+}
+
+static JSValue* callObjCFallbackObject(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&RuntimeObjectImp::s_info))
+ return throwError(exec, TypeError);
+
+ JSValue* result = jsUndefined();
+
+ RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(asObject(thisValue));
+ 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:)]){
+ ObjcClass* objcClass = static_cast<ObjcClass*>(instance->getClass());
+ OwnPtr<ObjcMethod> fallbackMethod(new ObjcMethod(objcClass->isa(), sel_getName(@selector(invokeUndefinedMethodFromWebScript:withArguments:))));
+ const Identifier& nameIdentifier = static_cast<ObjcFallbackObjectImp*>(function)->propertyName();
+ RetainPtr<CFStringRef> name(AdoptCF, CFStringCreateWithCharacters(0, nameIdentifier.data(), nameIdentifier.size()));
+ fallbackMethod->setJavaScriptName(name.get());
+ MethodList methodList;
+ methodList.append(fallbackMethod.get());
+ result = instance->invokeMethod(exec, methodList, args);
+ }
+
+ instance->end();
+
+ return result;
+}
+
+CallType ObjcFallbackObjectImp::getCallData(CallData& callData)
+{
+ id targetObject = _instance->getObject();
+ if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return CallTypeNone;
+ callData.native.function = callObjCFallbackObject;
+ return CallTypeHost;
+}
+
+bool ObjcFallbackObjectImp::deleteProperty(ExecState*, const Identifier&)
+{
+ return false;
+}
+
+JSValue* ObjcFallbackObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType) const
+{
+ return _instance->getValueOfUndefinedField(exec, _item);
+}
+
+bool ObjcFallbackObjectImp::toBoolean(ExecState *) const
+{
+ id targetObject = _instance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
+ return true;
+
+ return false;
+}
+
+}
+}
diff --git a/WebCore/bridge/objc/objc_utility.h b/WebCore/bridge/objc/objc_utility.h
new file mode 100644
index 0000000..304b0a2
--- /dev/null
+++ b/WebCore/bridge/objc/objc_utility.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KJS_BINDINGS_OBJC_UTILITY_H
+#define KJS_BINDINGS_OBJC_UTILITY_H
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "objc_header.h"
+#include <runtime/Error.h>
+#include <runtime/JSObject.h>
+
+#ifdef __OBJC__
+@class NSString;
+#else
+class NSString;
+#endif
+
+namespace JSC {
+namespace Bindings {
+
+typedef union {
+ ObjectStructPtr objectValue;
+ bool booleanValue;
+ char charValue;
+ short shortValue;
+ int intValue;
+ long longValue;
+ long long longLongValue;
+ float floatValue;
+ double doubleValue;
+} ObjcValue;
+
+typedef enum {
+ ObjcVoidType,
+ ObjcObjectType,
+ ObjcCharType,
+ ObjcUnsignedCharType,
+ ObjcShortType,
+ ObjcUnsignedShortType,
+ ObjcIntType,
+ ObjcUnsignedIntType,
+ ObjcLongType,
+ ObjcUnsignedLongType,
+ ObjcLongLongType,
+ ObjcUnsignedLongLongType,
+ ObjcFloatType,
+ ObjcDoubleType,
+ ObjcInvalidType
+} ObjcValueType;
+
+class RootObject;
+
+ObjcValue convertValueToObjcValue(ExecState*, JSValue*, ObjcValueType);
+JSValue* convertNSStringToString(ExecState* exec, NSString *nsstring);
+JSValue* convertObjcValueToValue(ExecState*, void* buffer, ObjcValueType, RootObject*);
+ObjcValueType objcValueTypeForType(const char *type);
+
+bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize);
+
+JSObject *throwError(ExecState *, ErrorType, NSString *message);
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif
diff --git a/WebCore/bridge/objc/objc_utility.mm b/WebCore/bridge/objc/objc_utility.mm
new file mode 100644
index 0000000..daab4fe
--- /dev/null
+++ b/WebCore/bridge/objc/objc_utility.mm
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "objc_utility.h"
+
+#include "objc_instance.h"
+#include "runtime_array.h"
+#include "runtime_object.h"
+#include "WebScriptObject.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#include <wtf/Assertions.h>
+
+#if !defined(_C_LNG_LNG)
+#define _C_LNG_LNG 'q'
+#endif
+
+#if !defined(_C_ULNG_LNG)
+#define _C_ULNG_LNG 'Q'
+#endif
+
+#if !defined(_C_CONST)
+#define _C_CONST 'r'
+#endif
+
+#if !defined(_C_BYCOPY)
+#define _C_BYCOPY 'O'
+#endif
+
+#if !defined(_C_BYREF)
+#define _C_BYREF 'R'
+#endif
+
+#if !defined(_C_ONEWAY)
+#define _C_ONEWAY 'V'
+#endif
+
+#if !defined(_C_GCINVISIBLE)
+#define _C_GCINVISIBLE '!'
+#endif
+
+namespace JSC {
+namespace Bindings {
+
+/*
+ By default, a JavaScript method name is produced by concatenating the
+ components of an ObjectiveC method name, replacing ':' with '_', and
+ escaping '_' and '$' with a leading '$', such that '_' becomes "$_" and
+ '$' becomes "$$". For example:
+
+ ObjectiveC name Default JavaScript name
+ moveTo:: moveTo__
+ moveTo_ moveTo$_
+ moveTo$_ moveTo$$$_
+
+ This function performs the inverse of that operation.
+
+ @result Fills 'buffer' with the ObjectiveC method name that corresponds to 'JSName'.
+ Returns true for success, false for failure. (Failure occurs when 'buffer'
+ is not big enough to hold the result.)
+*/
+bool convertJSMethodNameToObjc(const char *JSName, char *buffer, size_t bufferSize)
+{
+ ASSERT(JSName && buffer);
+
+ const char *sp = JSName; // source pointer
+ char *dp = buffer; // destination pointer
+
+ char *end = buffer + bufferSize;
+ while (dp < end) {
+ if (*sp == '$') {
+ ++sp;
+ *dp = *sp;
+ } else if (*sp == '_')
+ *dp = ':';
+ else
+ *dp = *sp;
+
+ // If a future coder puts funny ++ operators above, we might write off the end
+ // of the buffer in the middle of this loop. Let's make sure to check for that.
+ ASSERT(dp < end);
+
+ if (*sp == 0) { // We finished converting JSName
+ ASSERT(strlen(JSName) < bufferSize);
+ return true;
+ }
+
+ ++sp;
+ ++dp;
+ }
+
+ return false; // We ran out of buffer before converting JSName
+}
+
+/*
+
+ JavaScript to ObjC
+ Number coerced to char, short, int, long, float, double, or NSNumber, as appropriate
+ String NSString
+ wrapper id
+ Object WebScriptObject
+ null NSNull
+ [], other exception
+
+*/
+ObjcValue convertValueToObjcValue(ExecState* exec, JSValue* value, ObjcValueType type)
+{
+ ObjcValue result;
+ double d = 0;
+
+ if (value->isNumber() || value->isString() || value->isBoolean())
+ d = value->toNumber(exec);
+
+ switch (type) {
+ case ObjcObjectType: {
+ JSLock lock(false);
+
+ JSGlobalObject *originGlobalObject = exec->dynamicGlobalObject();
+ RootObject* originRootObject = findRootObject(originGlobalObject);
+
+ JSGlobalObject* globalObject = 0;
+ if (value->isObject() && asObject(value)->isGlobalObject())
+ globalObject = static_cast<JSGlobalObject*>(asObject(value));
+
+ if (!globalObject)
+ globalObject = originGlobalObject;
+
+ RootObject* rootObject = findRootObject(globalObject);
+ result.objectValue = rootObject
+ ? [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:originRootObject rootObject:rootObject]
+ : nil;
+ }
+ break;
+
+ case ObjcCharType:
+ case ObjcUnsignedCharType:
+ result.charValue = (char)d;
+ break;
+ case ObjcShortType:
+ case ObjcUnsignedShortType:
+ result.shortValue = (short)d;
+ break;
+ case ObjcIntType:
+ case ObjcUnsignedIntType:
+ result.intValue = (int)d;
+ break;
+ case ObjcLongType:
+ case ObjcUnsignedLongType:
+ result.longValue = (long)d;
+ break;
+ case ObjcLongLongType:
+ case ObjcUnsignedLongLongType:
+ result.longLongValue = (long long)d;
+ break;
+ case ObjcFloatType:
+ result.floatValue = (float)d;
+ break;
+ case ObjcDoubleType:
+ result.doubleValue = (double)d;
+ break;
+ case ObjcVoidType:
+ bzero(&result, sizeof(ObjcValue));
+ break;
+
+ case ObjcInvalidType:
+ default:
+ // FIXME: throw an exception?
+ break;
+ }
+
+ return result;
+}
+
+JSValue* convertNSStringToString(ExecState* exec, NSString *nsstring)
+{
+ JSLock lock(false);
+
+ unichar *chars;
+ unsigned int length = [nsstring length];
+ chars = (unichar *)malloc(sizeof(unichar)*length);
+ [nsstring getCharacters:chars];
+ UString u((const UChar*)chars, length);
+ JSValue* aValue = jsString(exec, u);
+ free((void *)chars);
+ return aValue;
+}
+
+/*
+ ObjC to JavaScript
+ ---- ----------
+ char number
+ short number
+ int number
+ long number
+ float number
+ double number
+ NSNumber boolean or number
+ NSString string
+ NSArray array
+ NSNull null
+ WebScriptObject underlying JavaScript object
+ WebUndefined undefined
+ id object wrapper
+ other should not happen
+*/
+JSValue* convertObjcValueToValue(ExecState* exec, void* buffer, ObjcValueType type, RootObject* rootObject)
+{
+ JSLock lock(false);
+
+ switch (type) {
+ case ObjcObjectType: {
+ id obj = *(id*)buffer;
+ if ([obj isKindOfClass:[NSString class]])
+ return convertNSStringToString(exec, (NSString *)obj);
+ if ([obj isKindOfClass:webUndefinedClass()])
+ return jsUndefined();
+ if ((CFBooleanRef)obj == kCFBooleanTrue)
+ return jsBoolean(true);
+ if ((CFBooleanRef)obj == kCFBooleanFalse)
+ return jsBoolean(false);
+ if ([obj isKindOfClass:[NSNumber class]])
+ return jsNumber(exec, [obj doubleValue]);
+ if ([obj isKindOfClass:[NSArray class]])
+ return new (exec) RuntimeArray(exec, new ObjcArray(obj, rootObject));
+ if ([obj isKindOfClass:webScriptObjectClass()]) {
+ JSObject* imp = [obj _imp];
+ return imp ? imp : jsUndefined();
+ }
+ if ([obj isKindOfClass:[NSNull class]])
+ return jsNull();
+ if (obj == 0)
+ return jsUndefined();
+ return Instance::createRuntimeObject(exec, ObjcInstance::create(obj, rootObject));
+ }
+ case ObjcCharType:
+ return jsNumber(exec, *(char*)buffer);
+ case ObjcUnsignedCharType:
+ return jsNumber(exec, *(unsigned char*)buffer);
+ case ObjcShortType:
+ return jsNumber(exec, *(short*)buffer);
+ case ObjcUnsignedShortType:
+ return jsNumber(exec, *(unsigned short*)buffer);
+ case ObjcIntType:
+ return jsNumber(exec, *(int*)buffer);
+ case ObjcUnsignedIntType:
+ return jsNumber(exec, *(unsigned int*)buffer);
+ case ObjcLongType:
+ return jsNumber(exec, *(long*)buffer);
+ case ObjcUnsignedLongType:
+ return jsNumber(exec, *(unsigned long*)buffer);
+ case ObjcLongLongType:
+ return jsNumber(exec, *(long long*)buffer);
+ case ObjcUnsignedLongLongType:
+ return jsNumber(exec, *(unsigned long long*)buffer);
+ case ObjcFloatType:
+ return jsNumber(exec, *(float*)buffer);
+ case ObjcDoubleType:
+ return jsNumber(exec, *(double*)buffer);
+ default:
+ // Should never get here. Argument types are filtered.
+ fprintf(stderr, "%s: invalid type (%d)\n", __PRETTY_FUNCTION__, (int)type);
+ ASSERT(false);
+ }
+
+ return jsUndefined();
+}
+
+ObjcValueType objcValueTypeForType(const char *type)
+{
+ int typeLength = strlen(type);
+ ObjcValueType objcValueType = ObjcInvalidType;
+
+ for (int i = 0; i < typeLength; ++i) {
+ char typeChar = type[i];
+ switch (typeChar) {
+ case _C_CONST:
+ case _C_BYCOPY:
+ case _C_BYREF:
+ case _C_ONEWAY:
+ case _C_GCINVISIBLE:
+ // skip these type modifiers
+ break;
+ case _C_ID:
+ objcValueType = ObjcObjectType;
+ break;
+ case _C_CHR:
+ objcValueType = ObjcCharType;
+ break;
+ case _C_UCHR:
+ objcValueType = ObjcUnsignedCharType;
+ break;
+ case _C_SHT:
+ objcValueType = ObjcShortType;
+ break;
+ case _C_USHT:
+ objcValueType = ObjcUnsignedShortType;
+ break;
+ case _C_INT:
+ objcValueType = ObjcIntType;
+ break;
+ case _C_UINT:
+ objcValueType = ObjcUnsignedIntType;
+ break;
+ case _C_LNG:
+ objcValueType = ObjcLongType;
+ break;
+ case _C_ULNG:
+ objcValueType = ObjcUnsignedLongType;
+ break;
+ case _C_LNG_LNG:
+ objcValueType = ObjcLongLongType;
+ break;
+ case _C_ULNG_LNG:
+ objcValueType = ObjcUnsignedLongLongType;
+ break;
+ case _C_FLT:
+ objcValueType = ObjcFloatType;
+ break;
+ case _C_DBL:
+ objcValueType = ObjcDoubleType;
+ break;
+ case _C_VOID:
+ objcValueType = ObjcVoidType;
+ break;
+ default:
+ // Unhandled type. We don't handle C structs, unions, etc.
+ // FIXME: throw an exception?
+ ASSERT(false);
+ }
+
+ if (objcValueType != ObjcInvalidType)
+ break;
+ }
+
+ return objcValueType;
+}
+
+JSObject *throwError(ExecState *exec, 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(buffer, length));
+ delete [] buffer;
+ return error;
+}
+
+}
+}
diff --git a/WebCore/bridge/qt/qt_class.cpp b/WebCore/bridge/qt/qt_class.cpp
new file mode 100644
index 0000000..3fe3f89
--- /dev/null
+++ b/WebCore/bridge/qt/qt_class.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 JSC {
+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 object and return the same object for the same
+// identifier.
+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
+ JSObject* 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) {
+ QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
+ 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) {
+ QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
+ 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/WebCore/bridge/qt/qt_class.h b/WebCore/bridge/qt/qt_class.h
new file mode 100644
index 0000000..449648d
--- /dev/null
+++ b/WebCore/bridge/qt/qt_class.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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"
+
+#include "qglobal.h"
+
+QT_BEGIN_NAMESPACE
+class QObject;
+class QMetaObject;
+QT_END_NAMESPACE
+
+namespace JSC {
+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 JSC
+
+#endif
diff --git a/WebCore/bridge/qt/qt_instance.cpp b/WebCore/bridge/qt/qt_instance.cpp
new file mode 100644
index 0000000..c15dbe3
--- /dev/null
+++ b/WebCore/bridge/qt/qt_instance.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 "ArgList.h"
+#include "JSDOMBinding.h"
+#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "qt_class.h"
+#include "qt_runtime.h"
+#include "PropertyNameArray.h"
+#include "runtime_object.h"
+#include "ObjectPrototype.h"
+#include "Error.h"
+
+#include <qmetaobject.h>
+#include <qdebug.h>
+#include <qmetatype.h>
+#include <qhash.h>
+
+namespace JSC {
+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(ExecState*, PassRefPtr<Instance>);
+ ~QtRuntimeObjectImp();
+ virtual void invalidate();
+
+ virtual void mark() {
+ QtInstance* instance = static_cast<QtInstance*>(getInternalInstance());
+ if (instance)
+ instance->mark();
+ RuntimeObjectImp::mark();
+ }
+
+ protected:
+ void removeFromCache();
+};
+
+QtRuntimeObjectImp::QtRuntimeObjectImp(ExecState* exec, PassRefPtr<Instance> instance)
+ : RuntimeObjectImp(exec, WebCore::getDOMStructure<QtRuntimeObjectImp>(exec), instance)
+{
+}
+
+QtRuntimeObjectImp::~QtRuntimeObjectImp()
+{
+ removeFromCache();
+}
+
+void QtRuntimeObjectImp::invalidate()
+{
+ removeFromCache();
+ RuntimeObjectImp::invalidate();
+}
+
+void QtRuntimeObjectImp::removeFromCache()
+{
+ JSLock lock(false);
+ QtInstance* key = cachedObjects.key(this);
+ if (key)
+ cachedObjects.remove(key);
+}
+
+// QtInstance
+QtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
+ : Instance(rootObject)
+ , m_class(0)
+ , m_object(o)
+ , m_hashkey(o)
+ , m_defaultMethod(0)
+{
+}
+
+QtInstance::~QtInstance()
+{
+ JSLock lock(false);
+
+ cachedObjects.remove(this);
+ cachedInstances.remove(m_hashkey);
+
+ // clean up (unprotect from gc) the JSValues we've created
+ m_methods.clear();
+
+ foreach(QtField* f, m_fields.values()) {
+ delete f;
+ }
+ m_fields.clear();
+}
+
+PassRefPtr<QtInstance> QtInstance::getQtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
+{
+ JSLock lock(false);
+
+ foreach(QtInstance* instance, cachedInstances.values(o)) {
+ if (instance->rootObject() == rootObject)
+ return instance;
+ }
+
+ RefPtr<QtInstance> ret = QtInstance::create(o, rootObject);
+ cachedInstances.insert(o, ret.get());
+
+ return ret.release();
+}
+
+RuntimeObjectImp* QtInstance::getRuntimeObject(ExecState* exec, PassRefPtr<QtInstance> instance)
+{
+ JSLock lock(false);
+ QtInstance* qtInstance = instance.get();
+ RuntimeObjectImp* ret = static_cast<RuntimeObjectImp*>(cachedObjects.value(qtInstance));
+ if (!ret) {
+ ret = new (exec) QtRuntimeObjectImp(exec, instance);
+ cachedObjects.insert(qtInstance, ret);
+ ret = static_cast<RuntimeObjectImp*>(cachedObjects.value(qtInstance));
+ }
+ return ret;
+}
+
+Class* QtInstance::getClass() const
+{
+ if (!m_class)
+ m_class = QtClass::classForObject(m_object);
+ return m_class;
+}
+
+void QtInstance::mark()
+{
+ if (m_defaultMethod)
+ m_defaultMethod->mark();
+ foreach(JSObject* val, m_methods.values()) {
+ if (val && !val->marked())
+ val->mark();
+ }
+ foreach(JSValue* val, m_children.values()) {
+ if (val && !val->marked())
+ val->mark();
+ }
+}
+
+void QtInstance::begin()
+{
+ // Do nothing.
+}
+
+void QtInstance::end()
+{
+ // Do nothing.
+}
+
+void QtInstance::getPropertyNames(ExecState* exec, 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(exec, prop.name()));
+ }
+ }
+
+ QList<QByteArray> dynProps = obj->dynamicPropertyNames();
+ foreach(QByteArray ba, dynProps) {
+ array.add(Identifier(exec, ba.constData()));
+ }
+
+ for (i=0; i < meta->methodCount(); i++) {
+ QMetaMethod method = meta->method(i);
+ if (method.access() != QMetaMethod::Private) {
+ array.add(Identifier(exec, method.signature()));
+ }
+ }
+ }
+}
+
+JSValue* QtInstance::invokeMethod(ExecState*, const MethodList&, const ArgList&)
+{
+ // Implemented via fallbackMethod & QtRuntimeMetaMethod::callAsFunction
+ return jsUndefined();
+}
+
+
+JSValue* QtInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (hint == PreferString)
+ return stringValue(exec);
+ if (hint == PreferNumber)
+ return numberValue(exec);
+ return valueOf(exec);
+}
+
+JSValue* QtInstance::stringValue(ExecState* exec) 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(exec, buf.constData());
+}
+
+JSValue* QtInstance::numberValue(ExecState* exec) const
+{
+ return jsNumber(exec, 0);
+}
+
+JSValue* QtInstance::booleanValue() const
+{
+ // ECMA 9.2
+ return jsBoolean(true);
+}
+
+JSValue* QtInstance::valueOf(ExecState* exec) const
+{
+ return stringValue(exec);
+}
+
+// In qt_runtime.cpp
+JSValue* convertQVariantToValue(ExecState*, PassRefPtr<RootObject> root, const QVariant& variant);
+QVariant convertValueToQVariant(ExecState*, JSValue*, 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);
+
+ JSValue* ret = convertQVariantToValue(exec, inst->rootObject(), val);
+
+ // Need to save children so we can mark them
+ if (m_type == ChildObject)
+ instance->m_children.insert(ret);
+
+ return ret;
+ } else {
+ QString msg = QString(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(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(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(name()));
+ throwError(exec, GeneralError, msg.toLatin1().constData());
+ }
+}
+
+
+}
+}
diff --git a/WebCore/bridge/qt/qt_instance.h b/WebCore/bridge/qt/qt_instance.h
new file mode 100644
index 0000000..d70e362
--- /dev/null
+++ b/WebCore/bridge/qt/qt_instance.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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>
+#include <qset.h>
+
+namespace JSC {
+
+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(ExecState*) const;
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual void mark(); // This isn't inherited
+
+ virtual JSValue* invokeMethod(ExecState*, const MethodList&, const ArgList&);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual BindingLanguage getBindingLanguage() const { return QtLanguage; }
+
+ JSValue* stringValue(ExecState* exec) const;
+ JSValue* numberValue(ExecState* exec) const;
+ JSValue* booleanValue() const;
+
+ QObject* getObject() const { return m_object; }
+
+ static PassRefPtr<QtInstance> getQtInstance(QObject*, PassRefPtr<RootObject>);
+ static RuntimeObjectImp* getRuntimeObject(ExecState* exec, PassRefPtr<QtInstance>);
+
+private:
+ static PassRefPtr<QtInstance> create(QObject *instance, PassRefPtr<RootObject> rootObject)
+ {
+ return adoptRef(new QtInstance(instance, rootObject));
+ }
+
+ friend class QtClass;
+ friend class QtField;
+ QtInstance(QObject*, PassRefPtr<RootObject>); // Factory produced only..
+ mutable QtClass* m_class;
+ QPointer<QObject> m_object;
+ QObject* m_hashkey;
+ mutable QHash<QByteArray, JSObject*> m_methods;
+ mutable QHash<QString, QtField*> m_fields;
+ mutable QSet<JSValue*> m_children;
+ mutable QtRuntimeMetaMethod* m_defaultMethod;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif
diff --git a/WebCore/bridge/qt/qt_runtime.cpp b/WebCore/bridge/qt/qt_runtime.cpp
new file mode 100644
index 0000000..d9a2c59
--- /dev/null
+++ b/WebCore/bridge/qt/qt_runtime.cpp
@@ -0,0 +1,1721 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 "DateInstance.h"
+#include "DateMath.h"
+#include "DatePrototype.h"
+#include "FunctionPrototype.h"
+#include "JSArray.h"
+#include "JSDOMBinding.h"
+#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "JSObject.h"
+#include "ObjectPrototype.h"
+#include "PropertyNameArray.h"
+#include "RegExpConstructor.h"
+#include "RegExpObject.h"
+#include "qdatetime.h"
+#include "qdebug.h"
+#include "qmetaobject.h"
+#include "qmetatype.h"
+#include "qobject.h"
+#include "qstringlist.h"
+#include "qt_instance.h"
+#include "qvarlengtharray.h"
+#include <JSFunction.h>
+#include <limits.h>
+#include <runtime.h>
+#include <runtime_array.h>
+#include <runtime_object.h>
+
+// QtScript has these
+Q_DECLARE_METATYPE(QObjectList);
+Q_DECLARE_METATYPE(QList<int>);
+Q_DECLARE_METATYPE(QVariant);
+
+using namespace WebCore;
+
+namespace JSC {
+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 = 0,
+ Number,
+ Boolean,
+ String,
+ Date,
+ RegExp,
+ Array,
+ QObj,
+ Object,
+ Null,
+ RTArray
+} JSRealType;
+
+#if defined(QTWK_RUNTIME_CONVERSION_DEBUG) || defined(QTWK_RUNTIME_MATCH_DEBUG)
+QDebug operator<<(QDebug dbg, const JSRealType &c)
+{
+ const char *map[] = { "Variant", "Number", "Boolean", "String", "Date",
+ "RegExp", "Array", "RTObject", "Object", "Null", "RTArray"};
+
+ dbg.nospace() << "JSType(" << ((int)c) << ", " << map[c] << ")";
+
+ return dbg.space();
+}
+#endif
+
+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(&RuntimeArray::s_info)) // RuntimeArray 'inherits' from Array, but not in C++
+ return RTArray;
+ else if (object->inherits(&JSArray::info))
+ return Array;
+ else if (object->inherits(&DateInstance::info))
+ return Date;
+ else if (object->inherits(&RegExpObject::info))
+ return RegExp;
+ else if (object->inherits(&RuntimeObjectImp::s_info))
+ return QObj;
+ return Object;
+ }
+
+ return String; // I don't know.
+}
+
+QVariant convertValueToQVariant(ExecState* exec, JSValue* value, QMetaType::Type hint, int *distance, HashSet<JSObject*>* visitedObjects)
+{
+ JSObject* object = 0;
+ if (value->isObject()) {
+ object = value->toObject(exec);
+ if (visitedObjects->contains(object))
+ return QVariant();
+
+ visitedObjects->add(object);
+ }
+
+ // check magic pointer values before dereferencing value
+ if (value == jsNaN(exec) || value == jsUndefined()) {
+ if (distance)
+ *distance = -1;
+ return QVariant();
+ }
+
+ JSLock lock(false);
+ 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 Object:
+ hint = QMetaType::QVariantMap;
+ break;
+ case QObj:
+ hint = QMetaType::QObjectStar;
+ break;
+ case Array:
+ case RTArray:
+ hint = QMetaType::QVariantList;
+ break;
+ }
+ }
+
+ qConvDebug() << "convertValueToQVariant: jstype is " << type << ", hint is" << hint;
+
+ 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 || type == RTArray) {
+ // Enumerate the contents of the object
+ PropertyNameArray properties(exec);
+ 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, visitedObjects);
+ 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 == RTArray) {
+ RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
+
+ QVariantList result;
+ int len = rtarray->getLength();
+ int objdist = 0;
+ qConvDebug() << "converting a " << len << " length Array";
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = rtarray->getConcreteArray()->valueAt(exec, i);
+ result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects));
+ if (objdist == -1) {
+ qConvDebug() << "Failed converting element at index " << i;
+ break; // Failed converting a list entry, so fail the array
+ }
+ }
+ if (objdist != -1) {
+ dist = 5;
+ ret = QVariant(result);
+ }
+ } else if (type == Array) {
+ JSArray* array = static_cast<JSArray*>(object);
+
+ QVariantList result;
+ int len = array->length();
+ int objdist = 0;
+ qConvDebug() << "converting a " << len << " length Array";
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = array->get(exec, i);
+ result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects));
+ if (objdist == -1) {
+ qConvDebug() << "Failed converting element at index " << i;
+ break; // Failed converting a list entry, so fail the array
+ }
+ }
+ if (objdist != -1) {
+ dist = 5;
+ ret = QVariant(result);
+ }
+ } else {
+ // Make a single length array
+ int objdist;
+ qConvDebug() << "making a single length variantlist";
+ QVariant var = convertValueToQVariant(exec, value, QMetaType::Void, &objdist, visitedObjects);
+ if (objdist != -1) {
+ QVariantList result;
+ result << var;
+ ret = QVariant(result);
+ dist = 10;
+ } else {
+ qConvDebug() << "failed making single length varlist";
+ }
+ }
+ break;
+
+ case QMetaType::QStringList: {
+ if (type == RTArray) {
+ RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
+
+ QStringList result;
+ int len = rtarray->getLength();
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = rtarray->getConcreteArray()->valueAt(exec, 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 if (type == Array) {
+ JSArray* array = static_cast<JSArray*>(object);
+
+ QStringList result;
+ int len = array->length();
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = array->get(exec, 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) {
+ 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) {
+/*
+ RegExpObject *re = static_cast<RegExpObject*>(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(QLatin1Char('/'));
+ int lastSlash = qstring.lastIndexOf(QLatin1Char('/'));
+ if (firstSlash >=0 && lastSlash > firstSlash) {
+ QRegExp realRe;
+
+ realRe.setPattern(qstring.mid(firstSlash + 1, lastSlash - firstSlash - 1));
+
+ if (qstring.mid(lastSlash + 1).contains(QLatin1Char('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) {
+ 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) {
+ 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 == RTArray) {
+ RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
+
+ QObjectList result;
+ int len = rtarray->getLength();
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = rtarray->getConcreteArray()->valueAt(exec, i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist, visitedObjects);
+ 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 if (type == Array) {
+ JSObject* object = value->toObject(exec);
+ JSArray* array = static_cast<JSArray *>(object);
+ QObjectList result;
+ int len = array->length();
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = array->get(exec, i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist, visitedObjects);
+ 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 {
+ // Make a single length array
+ QObjectList result;
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, value, QMetaType::QObjectStar, &itemdist, visitedObjects);
+ 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 == RTArray) {
+ RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
+
+ QList<int> result;
+ int len = rtarray->getLength();
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = rtarray->getConcreteArray()->valueAt(exec, i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist, visitedObjects);
+ 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 if (type == Array) {
+ JSArray* array = static_cast<JSArray *>(object);
+
+ QList<int> result;
+ int len = array->length();
+ for (int i = 0; i < len; ++i) {
+ JSValue* val = array->get(exec, i);
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist, visitedObjects);
+ 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 {
+ // Make a single length array
+ QList<int> result;
+ int itemdist = -1;
+ QVariant item = convertValueToQVariant(exec, value, QMetaType::Int, &itemdist, visitedObjects);
+ 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, visitedObjects);
+ dist = 10;
+ break;
+ }
+
+ dist = 10;
+ break;
+ }
+
+ if (!ret.isValid())
+ dist = -1;
+ if (distance)
+ *distance = dist;
+
+ return ret;
+}
+
+QVariant convertValueToQVariant(ExecState* exec, JSValue* value, QMetaType::Type hint, int *distance)
+{
+ HashSet<JSObject*> visitedObjects;
+ return convertValueToQVariant(exec, value, hint, distance, &visitedObjects);
+}
+
+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();
+
+ qConvDebug() << "convertQVariantToValue: metatype:" << type << ", isnull: " << variant.isNull();
+ if (variant.isNull() &&
+ type != QMetaType::QObjectStar &&
+ type != QMetaType::VoidStar &&
+ type != QMetaType::QWidgetStar &&
+ type != QMetaType::QString) {
+ return jsNull();
+ }
+
+ JSLock lock(false);
+
+ 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(exec, variant.toDouble());
+
+ if (type == QMetaType::QRegExp) {
+ QRegExp re = variant.value<QRegExp>();
+
+ if (re.isValid()) {
+ UString uflags;
+ if (re.caseSensitivity() == Qt::CaseInsensitive)
+ uflags = "i"; // ### Can't do g or m
+
+ UString pattern((UChar*)re.pattern().utf16(), re.pattern().length());
+
+ RefPtr<JSC::RegExp> regExp = JSC::RegExp::create(&exec->globalData(), pattern, uflags);
+ if (regExp->isValid())
+ return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
+ else
+ return jsNull();
+ }
+ }
+
+ if (type == QMetaType::QDateTime ||
+ type == QMetaType::QDate ||
+ type == QMetaType::QTime) {
+
+ 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)
+ GregorianDateTime dt;
+ dt.year = date.year() - 1900;
+ dt.month = date.month() - 1;
+ dt.monthDay = date.day();
+ dt.hour = time.hour();
+ dt.minute = time.minute();
+ dt.second = time.second();
+ dt.isDST = -1;
+ double ms = JSC::gregorianDateTimeToMS(dt, time.msec(), /*inputIsUTC*/ false);
+
+ DateInstance* instance = new (exec) DateInstance(exec->lexicalGlobalObject()->dateStructure());
+ instance->setInternalValue(jsNumber(exec, trunc(ms)));
+ return instance;
+ }
+
+ if (type == QMetaType::QByteArray) {
+ QByteArray ba = variant.value<QByteArray>();
+ UString ustring(ba.constData());
+ return jsString(exec, ustring);
+ }
+
+ if (type == QMetaType::QObjectStar || type == QMetaType::QWidgetStar) {
+ QObject* obj = variant.value<QObject*>();
+ return Instance::createRuntimeObject(exec, QtInstance::getQtInstance(obj, root));
+ }
+
+ if (type == QMetaType::QVariantMap) {
+ // create a new object, and stuff properties into it
+ JSObject* ret = constructEmptyObject(exec);
+ 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) {
+ PutPropertySlot slot;
+ ret->put(exec, Identifier(exec, (const UChar *)s.constData(), s.length()), val, slot);
+ // ### error case?
+ }
+ ++i;
+ }
+
+ return ret;
+ }
+
+ // List types
+ if (type == QMetaType::QVariantList) {
+ QVariantList vl = variant.toList();
+ qConvDebug() << "got a " << vl.count() << " length list:" << vl;
+ return new (exec) RuntimeArray(exec, new QtArray<QVariant>(vl, QMetaType::Void, root));
+ } else if (type == QMetaType::QStringList) {
+ QStringList sl = variant.value<QStringList>();
+ return new (exec) RuntimeArray(exec, new QtArray<QString>(sl, QMetaType::QString, root));
+ } else if (type == (QMetaType::Type) qMetaTypeId<QObjectList>()) {
+ QObjectList ol= variant.value<QObjectList>();
+ return new (exec) 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 (exec) 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((UChar*)string.utf16(), string.length());
+ return jsString(exec, ustring);
+}
+
+// ===============
+
+// Qt-like macros
+#define QW_D(Class) Class##Data* d = d_func()
+#define QW_DS(Class,Instance) Class##Data* d = Instance->d_func()
+
+const ClassInfo QtRuntimeMethod::s_info = { "QtRuntimeMethod", 0, 0, 0 };
+
+QtRuntimeMethod::QtRuntimeMethod(QtRuntimeMethodData* dd, ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst)
+ : InternalFunction(&exec->globalData(), getDOMStructure<QtRuntimeMethod>(exec), ident)
+ , d_ptr(dd)
+{
+ QW_D(QtRuntimeMethod);
+ d->m_instance = inst;
+}
+
+QtRuntimeMethod::~QtRuntimeMethod()
+{
+ delete d_ptr;
+}
+
+// ===============
+
+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 ArgList& 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.at(exec, 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::call(ExecState* exec, JSObject* functionObject, JSValue* thisValue, const ArgList& args)
+{
+ QtRuntimeMetaMethodData* d = static_cast<QtRuntimeMetaMethod *>(functionObject)->d_func();
+
+ // We're limited to 10 args
+ if (args.size() > 10)
+ return jsUndefined();
+
+ // We have to pick a method that matches..
+ JSLock lock(false);
+
+ 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();
+}
+
+CallType QtRuntimeMetaMethod::getCallData(CallData& callData)
+{
+ callData.native.function = call;
+ return CallTypeHost;
+}
+
+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* exec, const Identifier&, const PropertySlot&)
+{
+ // QtScript always returns 0
+ return jsNumber(exec, 0);
+}
+
+JSValue* QtRuntimeMetaMethod::connectGetter(ExecState* exec, const Identifier& ident, const PropertySlot& slot)
+{
+ QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(asObject(slot.slotBase()));
+ QW_DS(QtRuntimeMetaMethod, thisObj);
+
+ if (!d->m_connect)
+ d->m_connect = new (exec) QtRuntimeConnectionMethod(exec, ident, true, d->m_instance, d->m_index, d->m_signature);
+ return d->m_connect;
+}
+
+JSValue* QtRuntimeMetaMethod::disconnectGetter(ExecState* exec, const Identifier& ident, const PropertySlot& slot)
+{
+ QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(asObject(slot.slotBase()));
+ QW_DS(QtRuntimeMetaMethod, thisObj);
+
+ if (!d->m_disconnect)
+ d->m_disconnect = new (exec) 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::call(ExecState* exec, JSObject* functionObject, JSValue* thisValue, const ArgList& args)
+{
+ QtRuntimeConnectionMethodData* d = static_cast<QtRuntimeConnectionMethod *>(functionObject)->d_func();
+
+ JSLock lock(false);
+
+ 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.at(exec, 0)->toObject(exec);
+ CallData callData;
+ if (funcObject->getCallData(callData) == CallTypeNone) {
+ 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.at(exec, 0)->isObject()) {
+ thisObject = args.at(exec, 0)->toObject(exec);
+
+ // Get the actual function to call
+ JSObject *asObj = args.at(exec, 1)->toObject(exec);
+ CallData callData;
+ if (asObj->getCallData(callData) != CallTypeNone) {
+ // Function version
+ funcObject = asObj;
+ } else {
+ // Convert it to a string
+ UString funcName = args.at(exec, 1)->toString(exec);
+ Identifier funcIdent(exec, funcName);
+
+ // ### DropAllLocks
+ // This is resolved at this point in QtScript
+ JSValue* val = thisObject->get(exec, funcIdent);
+ JSObject* asFuncObj = val->toObject(exec);
+
+ if (asFuncObj->getCallData(callData) != CallTypeNone) {
+ 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(QLatin1String("QtMetaMethod.connect: failed to connect to %1::%2()"))
+ .arg(QLatin1String(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(QLatin1String("QtMetaMethod.disconnect: failed to disconnect from %1::%2()"))
+ .arg(QLatin1String(sender->metaObject()->className()))
+ .arg(QLatin1String(d->m_signature));
+ return throwError(exec, GeneralError, msg.toLatin1().constData());
+ }
+ }
+ } else {
+ QString msg = QString(QLatin1String("QtMetaMethod.%1: %2::%3() is not a signal"))
+ .arg(QLatin1String(d->m_isConnect ? "connect": "disconnect"))
+ .arg(QLatin1String(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();
+}
+
+CallType QtRuntimeConnectionMethod::getCallData(CallData& callData)
+{
+ callData.native.function = call;
+ return CallTypeHost;
+}
+
+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* exec, const Identifier&, const PropertySlot&)
+{
+ // we have one formal argument, and one optional
+ return jsNumber(exec, 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[] = {
+ "JSC::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(false);
+
+ // ### 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)
+ ArgList 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());
+ }
+ }
+ CallData callData;
+ CallType callType = m_funcObject->getCallData(callData);
+ // Stuff in the __qt_sender property, if we can
+ if (m_funcObject->inherits(&JSFunction::info)) {
+ JSFunction* fimp = static_cast<JSFunction*>(m_funcObject.get());
+
+ JSObject* qt_sender = Instance::createRuntimeObject(exec, QtInstance::getQtInstance(sender(), ro));
+ JSObject* wrapper = new (exec) JSObject(JSObject::createStructureID(jsNull()));
+ PutPropertySlot slot;
+ wrapper->put(exec, Identifier(exec, "__qt_sender__"), qt_sender, slot);
+ ScopeChain oldsc = fimp->scope();
+ ScopeChain sc = oldsc;
+ sc.push(wrapper);
+ fimp->setScope(sc);
+
+ call(exec, fimp, callType, callData, m_thisObject, l);
+ fimp->setScope(oldsc);
+ } else {
+ call(exec, m_funcObject, callType, callData, 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 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/WebCore/bridge/qt/qt_runtime.h b/WebCore/bridge/qt/qt_runtime.h
new file mode 100644
index 0000000..80248a2
--- /dev/null
+++ b/WebCore/bridge/qt/qt_runtime.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 "completion.h"
+#include "runtime.h"
+#include "runtime_method.h"
+#include "protect.h"
+
+#include <qbytearray.h>
+#include <qmetaobject.h>
+#include <qpointer.h>
+#include <qvariant.h>
+
+namespace JSC {
+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*, unsigned index, JSValue*) const;
+ virtual JSValue* valueAt(ExecState*, unsigned 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 InternalFunction {
+public:
+ virtual ~QtRuntimeMethod();
+
+ static const ClassInfo s_info;
+
+ static FunctionPrototype* createPrototype(ExecState* exec)
+ {
+ return exec->lexicalGlobalObject()->functionPrototype();
+ }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+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 void mark();
+
+protected:
+ QtRuntimeMetaMethodData* d_func() const {return reinterpret_cast<QtRuntimeMetaMethodData*>(d_ptr);}
+
+private:
+ virtual CallType getCallData(CallData&);
+ static JSValue* call(ExecState* exec, JSObject* functionObject, JSValue* thisValue, const ArgList& args);
+ static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue* connectGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue* disconnectGetter(ExecState*, 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&);
+
+protected:
+ QtRuntimeConnectionMethodData* d_func() const {return reinterpret_cast<QtRuntimeConnectionMethodData*>(d_ptr);}
+
+private:
+ virtual CallType getCallData(CallData&);
+ static JSValue* call(ExecState* exec, JSObject* functionObject, JSValue* thisValue, const ArgList& args);
+ static JSValue* lengthGetter(ExecState*, 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;
+};
+
+QVariant convertValueToQVariant(ExecState* exec, JSValue* value, QMetaType::Type hint, int *distance);
+
+} // namespace Bindings
+} // namespace JSC
+
+#endif
diff --git a/WebCore/bridge/runtime.cpp b/WebCore/bridge/runtime.cpp
new file mode 100644
index 0000000..3ca53ab
--- /dev/null
+++ b/WebCore/bridge/runtime.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "runtime.h"
+
+#include "runtime_object.h"
+#include "runtime_root.h"
+#include <runtime/JSLock.h>
+
+#if PLATFORM(QT)
+#include "qt_instance.h"
+#endif
+
+namespace JSC { namespace Bindings {
+
+Array::Array(PassRefPtr<RootObject> rootObject)
+ : _rootObject(rootObject)
+{
+ ASSERT(_rootObject);
+}
+
+Array::~Array()
+{
+}
+
+Instance::Instance(PassRefPtr<RootObject> rootObject)
+ : _rootObject(rootObject)
+{
+ ASSERT(_rootObject);
+}
+
+Instance::~Instance()
+{
+}
+
+static KJSDidExecuteFunctionPtr s_didExecuteFunction;
+
+void Instance::setDidExecuteFunction(KJSDidExecuteFunctionPtr func)
+{
+ s_didExecuteFunction = func;
+}
+
+KJSDidExecuteFunctionPtr Instance::didExecuteFunction()
+{
+ return s_didExecuteFunction;
+}
+
+void Instance::begin()
+{
+ virtualBegin();
+}
+
+void Instance::end()
+{
+ virtualEnd();
+}
+
+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);
+}
+
+RuntimeObjectImp* Instance::createRuntimeObject(ExecState* exec, PassRefPtr<Instance> instance)
+{
+#if PLATFORM(QT)
+ if (instance->getBindingLanguage() == QtLanguage)
+ return QtInstance::getRuntimeObject(exec, static_cast<QtInstance*>(instance.get()));
+#endif
+ JSLock lock(false);
+
+ return new (exec) RuntimeObjectImp(exec, instance);
+}
+
+Instance* Instance::getInstance(JSObject* object, BindingLanguage language)
+{
+ if (!object)
+ return 0;
+ if (!object->inherits(&RuntimeObjectImp::s_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 JSC::Bindings
diff --git a/WebCore/bridge/runtime.h b/WebCore/bridge/runtime.h
new file mode 100644
index 0000000..3c39121
--- /dev/null
+++ b/WebCore/bridge/runtime.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JAVASCRIPTCORE_BINDINGS_RUNTIME_H
+#define JAVASCRIPTCORE_BINDINGS_RUNTIME_H
+
+#include <runtime/JSString.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class ArgList;
+class Identifier;
+class JSGlobalObject;
+class PropertyNameArray;
+class RuntimeObjectImp;
+
+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 : public RefCounted<Instance> {
+public:
+ typedef enum {
+#if ENABLE(MAC_JAVA_BRIDGE)
+ JavaLanguage,
+#endif
+#if PLATFORM(MAC)
+ ObjectiveCLanguage,
+#endif
+ CLanguage
+#if PLATFORM(QT)
+ , QtLanguage
+#endif
+ } BindingLanguage;
+
+ Instance(PassRefPtr<RootObject>);
+
+ static void setDidExecuteFunction(KJSDidExecuteFunctionPtr func);
+ static KJSDidExecuteFunctionPtr didExecuteFunction();
+
+ static RuntimeObjectImp* createRuntimeObject(ExecState*, PassRefPtr<Instance>);
+ static Instance* getInstance(JSObject*, BindingLanguage);
+
+ // 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.
+ void begin();
+ void end();
+
+ virtual Class *getClass() const = 0;
+
+ virtual JSValue* getValueOfField(ExecState*, const Field*) const;
+ virtual JSValue* getValueOfUndefinedField(ExecState*, const Identifier&) const { return jsUndefined(); }
+ virtual void setValueOfField(ExecState*, const Field*, JSValue*) const;
+ virtual bool supportsSetValueOfUndefinedField() { return false; }
+ virtual void setValueOfUndefinedField(ExecState*, const Identifier&, JSValue*) {}
+
+ virtual JSValue* invokeMethod(ExecState*, const MethodList&, const ArgList& args) = 0;
+
+ virtual bool supportsInvokeDefaultMethod() const { return false; }
+ virtual JSValue* invokeDefaultMethod(ExecState*, const ArgList&) { return jsUndefined(); }
+
+ virtual bool supportsConstruct() const { return false; }
+ virtual JSValue* invokeConstruct(ExecState*, const ArgList&) { return 0; }
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&) { }
+
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const = 0;
+
+ virtual JSValue* valueOf(ExecState* exec) const { return jsString(exec, getClass()->name()); }
+
+ RootObject* rootObject() const;
+
+ virtual ~Instance();
+
+ virtual BindingLanguage getBindingLanguage() const = 0;
+
+protected:
+ virtual void virtualBegin() { }
+ virtual void virtualEnd() { }
+
+ RefPtr<RootObject> _rootObject;
+};
+
+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 ArgList&);
+
+typedef HashMap<RefPtr<UString::Rep>, MethodList*> MethodListMap;
+typedef HashMap<RefPtr<UString::Rep>, Method*> MethodMap;
+typedef HashMap<RefPtr<UString::Rep>, Field*> FieldMap;
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif
diff --git a/WebCore/bridge/runtime_array.cpp b/WebCore/bridge/runtime_array.cpp
new file mode 100644
index 0000000..c3912a9
--- /dev/null
+++ b/WebCore/bridge/runtime_array.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "runtime_array.h"
+
+#include <runtime/ArrayPrototype.h>
+#include <runtime/Error.h>
+#include "JSDOMBinding.h"
+
+using namespace WebCore;
+
+namespace JSC {
+
+const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &JSArray::info, 0, 0 };
+
+RuntimeArray::RuntimeArray(ExecState* exec, Bindings::Array* a)
+ : JSObject(getDOMStructure<RuntimeArray>(exec))
+ , _array(a)
+{
+}
+
+JSValue* RuntimeArray::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ RuntimeArray* thisObj = static_cast<RuntimeArray*>(asObject(slot.slotBase()));
+ return jsNumber(exec, thisObj->getLength());
+}
+
+JSValue* RuntimeArray::indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ RuntimeArray* thisObj = static_cast<RuntimeArray*>(asObject(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, PutPropertySlot& slot)
+{
+ 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, slot);
+}
+
+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/WebCore/bridge/runtime_array.h b/WebCore/bridge/runtime_array.h
new file mode 100644
index 0000000..22ad5f3
--- /dev/null
+++ b/WebCore/bridge/runtime_array.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RUNTIME_ARRAY_H_
+#define RUNTIME_ARRAY_H_
+
+#include "runtime.h"
+#include <runtime/JSGlobalObject.h>
+
+namespace JSC {
+
+class RuntimeArray : public JSObject {
+public:
+ RuntimeArray(ExecState*, Bindings::Array*);
+
+ virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState *, unsigned, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue*);
+
+ virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
+ virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
+
+ virtual const ClassInfo *classInfo() const { return &s_info; }
+
+ unsigned getLength() const { return getConcreteArray()->getLength(); }
+
+ Bindings::Array *getConcreteArray() const { return _array.get(); }
+
+ static const ClassInfo s_info;
+
+ static ArrayPrototype* createPrototype(ExecState* exec)
+ {
+ return exec->lexicalGlobalObject()->arrayPrototype();
+ }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+private:
+ static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue* indexGetter(ExecState*, const Identifier&, const PropertySlot&);
+
+ OwnPtr<Bindings::Array> _array;
+};
+
+} // namespace JSC
+
+#endif // RUNTIME_ARRAY_H_
diff --git a/WebCore/bridge/runtime_method.cpp b/WebCore/bridge/runtime_method.cpp
new file mode 100644
index 0000000..b855081
--- /dev/null
+++ b/WebCore/bridge/runtime_method.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "runtime_method.h"
+
+#include "JSDOMBinding.h"
+#include "runtime_object.h"
+#include <runtime/Error.h>
+#include <runtime/FunctionPrototype.h>
+
+using namespace WebCore;
+
+namespace JSC {
+
+using namespace Bindings;
+
+ASSERT_CLASS_FITS_IN_CELL(RuntimeMethod);
+
+const ClassInfo RuntimeMethod::s_info = { "RuntimeMethod", 0, 0, 0 };
+
+RuntimeMethod::RuntimeMethod(ExecState* exec, const Identifier& ident, Bindings::MethodList& m)
+ : InternalFunction(&exec->globalData(), getDOMStructure<RuntimeMethod>(exec), ident)
+ , _methodList(new MethodList(m))
+{
+}
+
+JSValue* RuntimeMethod::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ RuntimeMethod* thisObj = static_cast<RuntimeMethod*>(asObject(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(exec, 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 InternalFunction::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+static JSValue* callRuntimeMethod(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args)
+{
+ RuntimeMethod* method = static_cast<RuntimeMethod*>(function);
+
+ if (method->methods()->isEmpty())
+ return jsUndefined();
+
+ RuntimeObjectImp* imp;
+
+ if (thisValue->isObject(&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))
+ imp = static_cast<RuntimeObjectImp*>(asObject(value));
+ else
+ return throwError(exec, TypeError);
+ }
+
+ RefPtr<Instance> instance = imp->getInternalInstance();
+ if (!instance)
+ return RuntimeObjectImp::throwInvalidAccessError(exec);
+
+ instance->begin();
+ JSValue* result = instance->invokeMethod(exec, *method->methods(), args);
+ instance->end();
+ return result;
+}
+
+CallType RuntimeMethod::getCallData(CallData& callData)
+{
+ callData.native.function = callRuntimeMethod;
+ return CallTypeHost;
+}
+
+}
diff --git a/WebCore/bridge/runtime_method.h b/WebCore/bridge/runtime_method.h
new file mode 100644
index 0000000..adc68f6
--- /dev/null
+++ b/WebCore/bridge/runtime_method.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RUNTIME_FUNCTION_H_
+#define RUNTIME_FUNCTION_H_
+
+#include "runtime.h"
+#include <runtime/InternalFunction.h>
+#include <runtime/JSGlobalObject.h>
+#include <wtf/OwnPtr.h>
+
+namespace JSC {
+
+class RuntimeMethod : public InternalFunction {
+public:
+ RuntimeMethod(ExecState*, const Identifier& name, Bindings::MethodList&);
+ Bindings::MethodList* methods() const { return _methodList.get(); }
+
+ static const ClassInfo s_info;
+
+ static FunctionPrototype* createPrototype(ExecState* exec)
+ {
+ return exec->lexicalGlobalObject()->functionPrototype();
+ }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
+ }
+
+private:
+ static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual CallType getCallData(CallData&);
+
+ OwnPtr<Bindings::MethodList> _methodList;
+};
+
+} // namespace JSC
+
+#endif
diff --git a/WebCore/bridge/runtime_object.cpp b/WebCore/bridge/runtime_object.cpp
new file mode 100644
index 0000000..5bde348
--- /dev/null
+++ b/WebCore/bridge/runtime_object.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "runtime_object.h"
+
+#include "JSDOMBinding.h"
+#include "runtime_method.h"
+#include "runtime_root.h"
+#include <runtime/Error.h>
+#include <runtime/ObjectPrototype.h>
+
+using namespace WebCore;
+
+namespace JSC {
+
+using namespace Bindings;
+
+const ClassInfo RuntimeObjectImp::s_info = { "RuntimeObject", 0, 0, 0 };
+
+RuntimeObjectImp::RuntimeObjectImp(ExecState* exec, PassRefPtr<Instance> i)
+ : JSObject(getDOMStructure<RuntimeObjectImp>(exec))
+ , instance(i)
+{
+ instance->rootObject()->addRuntimeObject(this);
+}
+
+RuntimeObjectImp::RuntimeObjectImp(ExecState* exec, PassRefPtr<StructureID> structure, PassRefPtr<Instance> i)
+ : JSObject(structure)
+ , 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, const Identifier& propertyName, const PropertySlot& slot)
+{
+ RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase()));
+ RefPtr<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, const Identifier& propertyName, const PropertySlot& slot)
+{
+ RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase()));
+ RefPtr<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, const Identifier& propertyName, const PropertySlot& slot)
+{
+ RuntimeObjectImp* thisObj = static_cast<RuntimeObjectImp*>(asObject(slot.slotBase()));
+ RefPtr<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 (exec) 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();
+#if PLATFORM(QT)
+ // For Qt instances we call the baseclass implementation to allow
+ // runtime objects to have custom properties or a prototype
+ if (instance->getBindingLanguage() == Instance::QtLanguage)
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+#endif
+ // For other platforms and/or binding languages we don't allow
+ // runtime properties/prototypes
+ return false;
+}
+
+void RuntimeObjectImp::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ if (!instance) {
+ throwInvalidAccessError(exec);
+ return;
+ }
+
+ RefPtr<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);
+#if PLATFORM(QT)
+ else if (instance->getBindingLanguage() == Instance::QtLanguage)
+ JSObject::put(exec, propertyName, value, slot);
+#endif
+
+ instance->end();
+}
+
+bool RuntimeObjectImp::deleteProperty(ExecState*, const Identifier&)
+{
+ // Can never remove a property of a RuntimeObject.
+ return false;
+}
+
+JSValue* RuntimeObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ if (!instance)
+ return throwInvalidAccessError(exec);
+
+ RefPtr<Instance> protector(instance);
+ instance->begin();
+ JSValue* result = instance->defaultValue(exec, hint);
+ instance->end();
+ return result;
+}
+
+static JSValue* callRuntimeObject(ExecState* exec, JSObject* function, JSValue*, const ArgList& args)
+{
+ RefPtr<Instance> instance(static_cast<RuntimeObjectImp*>(function)->getInternalInstance());
+ instance->begin();
+ JSValue* result = instance->invokeDefaultMethod(exec, args);
+ instance->end();
+ return result;
+}
+
+CallType RuntimeObjectImp::getCallData(CallData& callData)
+{
+ if (!instance || !instance->supportsInvokeDefaultMethod())
+ return CallTypeNone;
+ callData.native.function = callRuntimeObject;
+ return CallTypeHost;
+}
+
+JSObject* callRuntimeConstructor(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ RefPtr<Instance> instance(static_cast<RuntimeObjectImp*>(constructor)->getInternalInstance());
+ instance->begin();
+ JSValue* result = instance->invokeConstruct(exec, args);
+ instance->end();
+
+ ASSERT(result);
+ return result->isObject() ? static_cast<JSObject*>(result) : constructor;
+}
+
+ConstructType RuntimeObjectImp::getConstructData(ConstructData& constructData)
+{
+ if (!instance || !instance->supportsConstruct())
+ return ConstructTypeNone;
+ constructData.native.function = callRuntimeConstructor;
+ return ConstructTypeHost;
+}
+
+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/WebCore/bridge/runtime_object.h b/WebCore/bridge/runtime_object.h
new file mode 100644
index 0000000..7e11273
--- /dev/null
+++ b/WebCore/bridge/runtime_object.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KJS_RUNTIME_OBJECT_H
+#define KJS_RUNTIME_OBJECT_H
+
+#include "runtime.h"
+#include <runtime/JSGlobalObject.h>
+
+namespace JSC {
+
+class RuntimeObjectImp : public JSObject {
+public:
+ virtual ~RuntimeObjectImp();
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ 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 invalidate();
+ Bindings::Instance* getInternalInstance() const { return instance.get(); }
+
+ static JSObject* throwInvalidAccessError(ExecState*);
+
+ static const ClassInfo s_info;
+
+ static ObjectPrototype* createPrototype(ExecState* exec)
+ {
+ return exec->lexicalGlobalObject()->objectPrototype();
+ }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+protected:
+ RuntimeObjectImp(ExecState*, PassRefPtr<StructureID>, PassRefPtr<Bindings::Instance>);
+
+private:
+ friend class Bindings::Instance;
+ RuntimeObjectImp(ExecState*, PassRefPtr<Bindings::Instance>);
+
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+
+ static JSValue* fallbackObjectGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue* fieldGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue* methodGetter(ExecState*, const Identifier&, const PropertySlot&);
+
+ RefPtr<Bindings::Instance> instance;
+};
+
+} // namespace
+
+#endif
diff --git a/WebCore/bridge/runtime_root.cpp b/WebCore/bridge/runtime_root.cpp
new file mode 100644
index 0000000..027d0c9
--- /dev/null
+++ b/WebCore/bridge/runtime_root.cpp
@@ -0,0 +1,173 @@
+/*
+ * 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 "runtime.h"
+#include "runtime_object.h"
+#include <runtime/JSGlobalObject.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
+
+namespace JSC { 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;
+}
+
+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)
+ JSC::gcUnprotect(it->first);
+ m_protectCountSet.clear();
+
+ rootObjectSet()->remove(this);
+}
+
+void RootObject::gcProtect(JSObject* jsObject)
+{
+ ASSERT(m_isValid);
+
+ if (!m_protectCountSet.contains(jsObject))
+ JSC::gcProtect(jsObject);
+ m_protectCountSet.add(jsObject);
+}
+
+void RootObject::gcUnprotect(JSObject* jsObject)
+{
+ ASSERT(m_isValid);
+
+ if (!jsObject)
+ return;
+
+ if (m_protectCountSet.count(jsObject) == 1)
+ JSC::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 JSC::Bindings
diff --git a/WebCore/bridge/runtime_root.h b/WebCore/bridge/runtime_root.h
new file mode 100644
index 0000000..a86096d
--- /dev/null
+++ b/WebCore/bridge/runtime_root.h
@@ -0,0 +1,89 @@
+/*
+ * 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 <kjs/protect.h>
+
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RefCounted.h>
+
+namespace JSC {
+
+class Interpreter;
+class JSGlobalObject;
+class RuntimeObjectImp;
+
+namespace Bindings {
+
+class RootObject;
+
+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;
+
+ 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;
+};
+
+} // namespace Bindings
+
+} // namespace JSC
+
+#endif
diff --git a/WebCore/bridge/test.js b/WebCore/bridge/test.js
new file mode 100644
index 0000000..5d4f79f
--- /dev/null
+++ b/WebCore/bridge/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/WebCore/bridge/testC.js b/WebCore/bridge/testC.js
new file mode 100644
index 0000000..44677c7
--- /dev/null
+++ b/WebCore/bridge/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/WebCore/bridge/testM.js b/WebCore/bridge/testM.js
new file mode 100644
index 0000000..7985d21
--- /dev/null
+++ b/WebCore/bridge/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/WebCore/bridge/testbindings.cpp b/WebCore/bridge/testbindings.cpp
new file mode 100644
index 0000000..fa61e2f
--- /dev/null
+++ b/WebCore/bridge/testbindings.cpp
@@ -0,0 +1,421 @@
+/*
+ * 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 "JSValue.h"
+#include "JSObject.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 JSC;
+using namespace JSC::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/WebCore/bridge/testbindings.mm b/WebCore/bridge/testbindings.mm
new file mode 100644
index 0000000..9215c48
--- /dev/null
+++ b/WebCore/bridge/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 "JSValue.h"
+#include "JSObject.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 JSC;
+using namespace JSC::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/WebCore/bridge/testbindings.pro b/WebCore/bridge/testbindings.pro
new file mode 100644
index 0000000..e6e0b9d
--- /dev/null
+++ b/WebCore/bridge/testbindings.pro
@@ -0,0 +1,8 @@
+QT -= gui
+
+include(../../WebKit.pri)
+INCLUDEPATH += .. ../kjs .
+qt-port:INCLUDEPATH += bindings/qt
+
+SOURCES += testqtbindings.cpp
+
diff --git a/WebCore/bridge/testqtbindings.cpp b/WebCore/bridge/testqtbindings.cpp
new file mode 100644
index 0000000..41a9a3a
--- /dev/null
+++ b/WebCore/bridge/testqtbindings.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 "JSValue.h"
+#include "JSObject.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 JSC;
+using namespace JSC::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"
diff --git a/WebCore/bridge/win/FrameCGWin.cpp b/WebCore/bridge/win/FrameCGWin.cpp
deleted file mode 100644
index eea6961..0000000
--- a/WebCore/bridge/win/FrameCGWin.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "FrameWin.h"
-
-#include <windows.h>
-
-#include "FrameView.h"
-#include "GraphicsContext.h"
-#include "Settings.h"
-
-#include <CoreGraphics/CoreGraphics.h>
-
-using std::min;
-
-namespace WebCore {
-
-static void drawRectIntoContext(IntRect rect, FrameView* view, GraphicsContext* gc)
-{
- IntSize offset = view->scrollOffset();
- rect.move(-offset.width(), -offset.height());
- rect = view->convertToContainingWindow(rect);
-
- gc->concatCTM(AffineTransform().translate(-rect.x(), -rect.y()));
-
- view->paint(gc, rect);
-}
-
-HBITMAP imageFromSelection(Frame* frame, bool forceBlackText)
-{
- frame->setPaintRestriction(forceBlackText ? PaintRestrictionSelectionOnlyBlackText : PaintRestrictionSelectionOnly);
- FloatRect fr = frame->selectionRect();
- IntRect ir(static_cast<int>(fr.x()), static_cast<int>(fr.y()),
- static_cast<int>(fr.width()), static_cast<int>(fr.height()));
-
- void* bits;
- HDC hdc = CreateCompatibleDC(0);
- int w = ir.width();
- int h = ir.height();
- BITMAPINFO bmp = { { sizeof(BITMAPINFOHEADER), w, h, 1, 32 } };
-
- HBITMAP hbmp = CreateDIBSection(0, &bmp, DIB_RGB_COLORS, static_cast<void**>(&bits), 0, 0);
- HBITMAP hbmpOld = static_cast<HBITMAP>(SelectObject(hdc, hbmp));
- CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
- CGContextRef context = CGBitmapContextCreate(static_cast<void*>(bits), w, h,
- 8, w * sizeof(RGBQUAD), deviceRGB, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
- CGColorSpaceRelease(deviceRGB);
- CGContextSaveGState(context);
-
- GraphicsContext gc(context);
-
- frame->document()->updateLayout();
- drawRectIntoContext(ir, frame->view(), &gc);
-
- CGContextRelease(context);
- SelectObject(hdc, hbmpOld);
- DeleteDC(hdc);
-
- frame->setPaintRestriction(PaintRestrictionNone);
-
- return hbmp;
-}
-
-} // namespace WebCore
diff --git a/WebCore/bridge/win/FrameWin.cpp b/WebCore/bridge/win/FrameWin.cpp
deleted file mode 100644
index 6599a88..0000000
--- a/WebCore/bridge/win/FrameWin.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "FrameWin.h"
-
-#include <winsock2.h>
-#include <windows.h>
-
-#include "AffineTransform.h"
-#include "FloatRect.h"
-#include "Document.h"
-#include "EditorClient.h"
-#include "FrameLoader.h"
-#include "FrameLoadRequest.h"
-#include "FramePrivate.h"
-#include "FrameView.h"
-#include "HTMLIFrameElement.h"
-#include "HTMLNames.h"
-#include "HTMLTableCellElement.h"
-#include "KeyboardEvent.h"
-#include "NP_jsobject.h"
-#include "NotImplemented.h"
-#include "Page.h"
-#include "Plugin.h"
-#include "PluginDatabase.h"
-#include "PluginView.h"
-#include "RegularExpression.h"
-#include "RenderFrame.h"
-#include "RenderTableCell.h"
-#include "RenderView.h"
-#include "ResourceHandle.h"
-#include "TextResourceDecoder.h"
-#include "kjs_proxy.h"
-#include "kjs_window.h"
-#include "npruntime_impl.h"
-#include "runtime_root.h"
-#include "GraphicsContext.h"
-#include "Settings.h"
-
-using std::min;
-using namespace KJS::Bindings;
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-void Frame::clearPlatformScriptObjects()
-{
-}
-
-KJS::Bindings::Instance* Frame::createScriptInstanceForWidget(Widget* widget)
-{
- // FIXME: Ideally we'd have an isPluginView() here but we can't add that to the open source tree right now.
- if (widget->isFrameView())
- return 0;
-
- return static_cast<PluginView*>(widget)->bindingInstance();
-}
-
-void computePageRectsForFrame(Frame* frame, const IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor,Vector<IntRect>& pages, int& outPageHeight)
-{
- ASSERT(frame);
-
- pages.clear();
- outPageHeight = 0;
-
- if (!frame->document() || !frame->view() || !frame->document()->renderer())
- return;
-
- RenderView* root = static_cast<RenderView *>(frame->document()->renderer());
-
- if (!root) {
- LOG_ERROR("document to be printed has no renderer");
- return;
- }
-
- if (userScaleFactor <= 0) {
- LOG_ERROR("userScaleFactor has bad value %.2f", userScaleFactor);
- return;
- }
-
- float ratio = static_cast<float>(printRect.height()) / static_cast<float>(printRect.width());
-
- float pageWidth = static_cast<float>(root->docWidth());
- float pageHeight = pageWidth * ratio;
- outPageHeight = static_cast<int>(pageHeight); // this is the height of the page adjusted by margins
- pageHeight -= (headerHeight + footerHeight);
-
- if (pageHeight <= 0) {
- LOG_ERROR("pageHeight has bad value %.2f", pageHeight);
- return;
- }
-
- float currPageHeight = pageHeight / userScaleFactor;
- float docHeight = root->layer()->height();
- float docWidth = root->layer()->width();
- float currPageWidth = pageWidth / userScaleFactor;
-
-
- // always return at least one page, since empty files should print a blank page
- float printedPagesHeight = 0.0f;
- do {
- float proposedBottom = min(docHeight, printedPagesHeight + pageHeight);
- frame->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight);
- currPageHeight = max(1.0f, proposedBottom - printedPagesHeight);
-
- pages.append(IntRect(0, printedPagesHeight, currPageWidth, currPageHeight));
- printedPagesHeight += currPageHeight;
- } while (printedPagesHeight < docHeight);
-}
-
-DragImageRef Frame::dragImageForSelection()
-{
- if (selectionController()->isRange())
- return imageFromSelection(this, false);
-
- return 0;
-}
-
-void Frame::dashboardRegionsChanged()
-{
-}
-
-} // namespace WebCore
diff --git a/WebCore/bridge/win/PageWin.cpp b/WebCore/bridge/win/PageWin.cpp
deleted file mode 100644
index f4c744a..0000000
--- a/WebCore/bridge/win/PageWin.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "Page.h"
-
-#include "Frame.h"
-#include "FrameView.h"
-#include "FloatRect.h"
-#include <windows.h>
-
-namespace WebCore {
-
-HINSTANCE Page::s_instanceHandle = 0;
-
-} // namespace WebCore