WebKit:
authorrjw <rjw@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 May 2004 22:13:48 +0000 (22:13 +0000)
committerrjw <rjw@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 May 2004 22:13:48 +0000 (22:13 +0000)
Fixed typo in header comment.

        Reviewed by Ken.

        * Plugins.subproj/WebScriptObject.h:

WebCore:
Implemented WebScriptObject/DOM wrapper voodoo.  DOM wrappers
can now be referenced like any other WebScriptObject, meaning
you can do JS operations on them.

All added implementation of finalizeForWebScript.

        Reviewed by Ken.

        * kwq/DOM.mm:
        (-[DOMObject _init]):
        * kwq/DOMInternal.mm:
        (-[WebScriptObject _init]):
        (-[WebScriptObject _initializeScriptDOMNodeImp]):
        * kwq/KWQKHTMLPart.h:
        * kwq/KWQKHTMLPart.mm:
        (KWQKHTMLPart::KWQKHTMLPart):
        (KWQKHTMLPart::bindingRootObject):
        (KWQKHTMLPart::windowScriptObject):

JavaScriptCore:
Implemented WebScriptObject/DOM wrapper voodoo.  DOM wrappers
can now be referenced like any other WebScriptObject, meaning
you can do JS operations on them.

All added implementation of finalizeForWebScript.

        Reviewed by Ken.

        * bindings/objc/WebScriptObject.h:
        * bindings/objc/WebScriptObject.mm:
        (-[WebScriptObject _initializeWithObjectImp:KJS::root:Bindings::]):
        (-[WebScriptObject _initWithObjectImp:KJS::root:Bindings::]):
        (-[WebScriptObject KJS::]):
        (-[WebScriptObject dealloc]):
        (-[WebScriptObject callWebScriptMethod:withArguments:]):
        (-[WebScriptObject evaluateWebScript:]):
        (-[WebScriptObject setValue:forKey:]):
        (-[WebScriptObject valueForKey:]):
        (-[WebScriptObject stringRepresentation]):
        * bindings/objc/WebScriptObjectPrivate.h:
        * bindings/objc/objc_instance.mm:
        (ObjcInstance::~ObjcInstance):

WebBrowser:
Added some debugging for WebScriptObject, disabled by default.

        Reviewed by Ken.

        * LocationChangeHandler.m:
        (-[LocationChangeHandler webView:windowScriptObjectAvailable:]):
        (-[LocationChangeHandler webView:locationChangeDone:forDataSource:]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@6650 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/bindings/objc/WebScriptObject.h
JavaScriptCore/bindings/objc/WebScriptObject.mm
JavaScriptCore/bindings/objc/WebScriptObjectPrivate.h
JavaScriptCore/bindings/objc/objc_instance.mm
WebCore/ChangeLog-2005-08-23
WebCore/kwq/DOM.mm
WebCore/kwq/DOMInternal.mm
WebCore/kwq/KWQKHTMLPart.h
WebCore/kwq/KWQKHTMLPart.mm
WebKit/ChangeLog
WebKit/Plugins.subproj/WebScriptObject.h

index de3e8b9f1c4303adeee1964e2b405d089e03f971..95030d7e77722fc48b524b5734d81c9b75d898d8 100644 (file)
@@ -1,3 +1,28 @@
+2004-05-20  Richard Williamson   <rjw@apple.com>
+
+       Implemented WebScriptObject/DOM wrapper voodoo.  DOM wrappers
+       can now be referenced like any other WebScriptObject, meaning
+       you can do JS operations on them.
+
+       All added implementation of finalizeForWebScript.
+
+        Reviewed by Ken.
+
+        * bindings/objc/WebScriptObject.h:
+        * bindings/objc/WebScriptObject.mm:
+        (-[WebScriptObject _initializeWithObjectImp:KJS::root:Bindings::]):
+        (-[WebScriptObject _initWithObjectImp:KJS::root:Bindings::]):
+        (-[WebScriptObject KJS::]):
+        (-[WebScriptObject dealloc]):
+        (-[WebScriptObject callWebScriptMethod:withArguments:]):
+        (-[WebScriptObject evaluateWebScript:]):
+        (-[WebScriptObject setValue:forKey:]):
+        (-[WebScriptObject valueForKey:]):
+        (-[WebScriptObject stringRepresentation]):
+        * bindings/objc/WebScriptObjectPrivate.h:
+        * bindings/objc/objc_instance.mm:
+        (ObjcInstance::~ObjcInstance):
+
 2004-05-19  Richard Williamson   <rjw@apple.com>
 
        Removed extraneous tabs that were added (by XCode?).
index 1d5145251589411a5e9d7e93354125e4e4bd90bb..f581d75ce7a08009e8f7b7b80d52b0cd3ca4829e 100644 (file)
 /*!
     @method finalizeForWebScript
     @discussion finalizeForScript is called on objects exposed to the script
-    environment just before the script environment is reset.  After calls to
-    finalizeForScript the object will no longer be referenced by the script environment.
-    Further any references to WebScriptObjects made by the exposed object will
+    environment just before the script environment releases the object.  After calls to
+    finalizeForWebScript the object will no longer be referenced by the script environment.
+    Further, any references to WebScriptObjects made by the exposed object will
     be invalid and have undefined consequences.
 */
 - (void)finalizeForWebScript;
index 3bf919a84aec387fd737f710f34ce34e69778489..77bd951ef8c227f344a992ec69ac155268c43d1c 100644 (file)
@@ -42,16 +42,15 @@ using namespace KJS::Bindings;
     if (Interpreter::shouldPrintExceptions()) \
         NSLog (@"%s:%d:  JavaScript exception:  %s\n", __FILE__, __LINE__, exec->exception().toObject(exec).get(exec, messagePropertyName).toString(exec).ascii());
 
-@interface WebScriptObjectPrivate : NSObject
+@implementation WebScriptObjectPrivate
+- (void)dealloc
 {
-    KJS::ObjectImp *imp;
-    const Bindings::RootObject *root;
+    removeNativeReference (imp);
+    
+    [super dealloc];
 }
 @end
 
-@implementation WebScriptObjectPrivate
-@end
-
 @implementation WebScriptObject
 
 static void _didExecute(WebScriptObject *obj)
@@ -62,6 +61,14 @@ static void _didExecute(WebScriptObject *obj)
         func (exec, static_cast<KJS::ObjectImp*>(obj->_private->root->rootObjectImp()));
 }
 
+- (void)_initializeWithObjectImp:(KJS::ObjectImp *)imp root:(const Bindings::RootObject *)root
+{
+    _private->imp = imp;
+    _private->root = root;    
+
+    addNativeReference (root, imp);
+}
+
 - _initWithObjectImp:(KJS::ObjectImp *)imp root:(const Bindings::RootObject *)root
 {
     assert (imp != 0);
@@ -70,24 +77,26 @@ static void _didExecute(WebScriptObject *obj)
     self = [super init];
 
     _private = [[WebScriptObjectPrivate alloc] init];
-    _private->imp = imp;
-    _private->root = root;    
 
-    addNativeReference (root, imp);
+    [self _initializeWithObjectImp:imp root:root];
     
     return self;
 }
 
 - (KJS::ObjectImp *)_imp
 {
+    if (!_private->imp && _private->isCreatedByDOMWrapper) {
+        // Associate the WebScriptObject with the JS wrapper for the ObjC DOM
+        // wrapper.  This is done on lazily, on demand.
+        [self _initializeScriptDOMNodeImp];
+    }
     return _private->imp;
 }
 
 - (void)dealloc
 {
-    if (_private)
-        removeNativeReference (_private->imp);
     [_private release];
+        
     [super dealloc];
 }
 
@@ -117,7 +126,7 @@ static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
     
     Value v = convertObjcValueToValue(exec, &name, ObjcObjectType);
     Identifier identifier(v.toString(exec));
-    Value func = _private->imp->get (exec, identifier);
+    Value func = [self _imp]->get (exec, identifier);
     Interpreter::unlock();
     if (func.isNull() || func.type() == UndefinedType) {
         // Maybe throw an exception here?
@@ -127,7 +136,7 @@ static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
     // Call the function object.    
     Interpreter::lock();
     ObjectImp *funcImp = static_cast<ObjectImp*>(func.imp());
-    Object thisObj = Object(const_cast<ObjectImp*>(_private->imp));
+    Object thisObj = Object(const_cast<ObjectImp*>([self _imp]));
     List argList = listFromNSArray(exec, args);
     Value result = funcImp->call (exec, thisObj, argList);
     Interpreter::unlock();
@@ -148,7 +157,7 @@ static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
 - (id)evaluateWebScript:(NSString *)script
 {
     ExecState *exec = _private->root->interpreter()->globalExec();
-    Object thisObj = Object(const_cast<ObjectImp*>(_private->imp));
+    Object thisObj = Object(const_cast<ObjectImp*>([self _imp]));
     Interpreter::lock();
     Value v = convertObjcValueToValue(exec, &script, ObjcObjectType);
     KJS::Value result = _private->root->interpreter()->evaluate(v.toString(exec)).value();
@@ -171,7 +180,7 @@ static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
     ExecState *exec = _private->root->interpreter()->globalExec();
     Interpreter::lock();
     Value v = convertObjcValueToValue(exec, &key, ObjcObjectType);
-   _private->imp->put (exec, Identifier (v.toString(exec)), (convertObjcValueToValue(exec, &value, ObjcObjectType)));
+    [self _imp]->put (exec, Identifier (v.toString(exec)), (convertObjcValueToValue(exec, &value, ObjcObjectType)));
     Interpreter::unlock();
 
     if (exec->hadException()) {
@@ -186,7 +195,7 @@ static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
     ExecState *exec = _private->root->interpreter()->globalExec();
     Interpreter::lock();
     Value v = convertObjcValueToValue(exec, &key, ObjcObjectType);
-    Value result = _private->imp->get (exec, Identifier (v.toString(exec)));
+    Value result = [self _imp]->get (exec, Identifier (v.toString(exec)));
     Interpreter::unlock();
     
     if (exec->hadException()) {
@@ -206,7 +215,7 @@ static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
     ExecState *exec = _private->root->interpreter()->globalExec();
     Interpreter::lock();
     Value v = convertObjcValueToValue(exec, &key, ObjcObjectType);
-    _private->imp->deleteProperty (exec, Identifier (v.toString(exec)));
+    [self _imp]->deleteProperty (exec, Identifier (v.toString(exec)));
     Interpreter::unlock();
 
     if (exec->hadException()) {
@@ -219,7 +228,7 @@ static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
 - (NSString *)stringRepresentation
 {
     Interpreter::lock();
-    Object thisObj = Object(const_cast<ObjectImp*>(_private->imp));
+    Object thisObj = Object(const_cast<ObjectImp*>([self _imp]));
     ExecState *exec = _private->root->interpreter()->globalExec();
     
     id result = convertValueToObjcValue(exec, thisObj, ObjcObjectType).objectValue;
@@ -237,7 +246,7 @@ static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
 {
     ExecState *exec = _private->root->interpreter()->globalExec();
     Interpreter::lock();
-    Value result = _private->imp->get (exec, (unsigned)index);
+    Value result = [self _imp]->get (exec, (unsigned)index);
     Interpreter::unlock();
 
     if (exec->hadException()) {
@@ -256,7 +265,7 @@ static KJS::List listFromNSArray(ExecState *exec, NSArray *array)
 {
     ExecState *exec = _private->root->interpreter()->globalExec();
     Interpreter::lock();
-    _private->imp->put (exec, (unsigned)index, (convertObjcValueToValue(exec, &value, ObjcObjectType)));
+    [self _imp]->put (exec, (unsigned)index, (convertObjcValueToValue(exec, &value, ObjcObjectType)));
     Interpreter::unlock();
 
     if (exec->hadException()) {
index 480aecc754e822c05b8c6bbba5853ce817eeb807..e72b708cc44debef9a793db3954282989cfd2af5 100644 (file)
 
 @interface WebScriptObject (Private)
 + (id)_convertValueToObjcValue:(KJS::Value)value root:(const KJS::Bindings::RootObject *)root;
+- _init;
 - _initWithObjectImp:(KJS::ObjectImp *)imp root:(const KJS::Bindings::RootObject *)root;
+- (void)_initializeWithObjectImp:(KJS::ObjectImp *)imp root:(const KJS::Bindings::RootObject *)root;
+- (void)_initializeScriptDOMNodeImp;
 - (KJS::ObjectImp *)_imp;
 @end
 
+@interface WebScriptObjectPrivate : NSObject
+{
+    KJS::ObjectImp *imp;
+    const KJS::Bindings::RootObject *root;
+    BOOL isCreatedByDOMWrapper;
+}
+@end
+
+
 #endif
index adac3063ed0f9d68fdb902481cef2ddd5a319b82..afb88d027d5133abe0efbc74f2c291aca5984141 100644 (file)
  * (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 <Foundation/Foundation.h>
+#import <Foundation/Foundation.h>
 
-#include <objc_instance.h>
+#import <JavaScriptCore/objc_instance.h>
+#import <JavaScriptCore/WebScriptObject.h>
 
 #ifdef NDEBUG
 #define OBJC_LOG(formatAndArgs...) ((void)0)
@@ -48,6 +49,8 @@ ObjcInstance::ObjcInstance (ObjectStructPtr instance)
 
 ObjcInstance::~ObjcInstance () 
 {
+    if ([_instance respondsToSelector:@selector(finalizeForWebScript)])
+        [_instance finalizeForWebScript];
     [_instance release];
 }
 
index a84a338014dfbb247496a1d0a79c94a58b42788a..0f52ea8c7a66d553ee4eb9234546678e64678cd4 100644 (file)
@@ -1,3 +1,18 @@
+2004-05-20  Richard Williamson   <rjw@apple.com>
+
+        Reviewed by NOBODY (OOPS!).
+
+        * kwq/DOM.mm:
+        (-[DOMObject _init]):
+        * kwq/DOMInternal.mm:
+        (-[WebScriptObject _init]):
+        (-[WebScriptObject _initializeScriptDOMNodeImp]):
+        * kwq/KWQKHTMLPart.h:
+        * kwq/KWQKHTMLPart.mm:
+        (KWQKHTMLPart::KWQKHTMLPart):
+        (KWQKHTMLPart::bindingRootObject):
+        (KWQKHTMLPart::windowScriptObject):
+
 2004-05-20  Darin Adler  <darin@apple.com>
 
         Reviewed by Ken.
index c1e9e19be6a801a16f733a360b380940df772c20..63e50ceadd4ea2eecb616ceb3c83b6ba10b0b9f6 100644 (file)
@@ -47,6 +47,8 @@
 #import <xml/dom2_rangeimpl.h>
 #import <xml/dom2_viewsimpl.h>
 
+#import <JavaScriptCore/WebScriptObjectPrivate.h>
+
 #import "DOMHTML.h"
 #import "DOMInternal.h"
 #import "KWQAssertions.h"
@@ -161,7 +163,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 
 - (id)_init
 {
-    return [super init];
+    return [super _init];
 }
 
 @end
index 968e7cffd805595895d702662e528e4ebc88ed37..4674f009a27d756225d17320d181010bb269d27d 100644 (file)
 #import <dom/dom2_range.h>
 #import <dom/dom_exception.h>
 #import <dom/dom_string.h>
+#import <xml/dom_docimpl.h>
 #import <xml/dom_stringimpl.h>
 
+#import "kjs_proxy.h"
+
 #import "KWQAssertions.h"
+#import "KWQKHTMLPart.h"
+
+#import <JavaScriptCore/interpreter.h>
+#import <JavaScriptCore/runtime_root.h>
+#import <JavaScriptCore/WebScriptObjectPrivate.h>
+
+//#import "kjs_dom.h"
+// We can't include kjs_dom.h here because of ObjC and C++ namespace compiler craziness.
+// kjs_dom.h:169: error: statically allocated instance of Objective-C class `DOMImplementation'
+// Declaring getDOMNode directly instead.
+namespace KJS {
+    Value getDOMNode(ExecState *exec, const DOM::Node &n);
+}
 
 using DOM::DOMString;
 using DOM::DOMStringImpl;
@@ -123,3 +139,50 @@ DOMString::DOMString(NSString *str)
 
 //------------------------------------------------------------------------------------------
 
+@implementation WebScriptObject (WebScriptObjectInternal)
+
+// Only called by DOMObject subclass.
+- _init
+{
+    self = [super init];
+
+    if (![self isKindOfClass:[DOMObject class]]) {
+        [NSException raise:NSGenericException format:@"+%@: _init is an internal initializer", [self class]];
+        return nil;
+    }
+
+    _private = [[WebScriptObjectPrivate alloc] init];
+    _private->isCreatedByDOMWrapper = YES;
+    
+    return self;
+}
+
+- (void)_initializeScriptDOMNodeImp
+{
+    assert (_private->isCreatedByDOMWrapper);
+    
+    if (![self isKindOfClass:[DOMNode class]]) {
+        // DOMObject can't map back to a document, and thus an interpreter,
+        // so for now only create wrappers for DOMNodes.
+        NSLog (@"%s:%d:  We don't know how to create ObjC JS wrappers from DOMObjects yet.", __FILE__, __LINE__);
+        return;
+    }
+    
+    // Extract the DOM::NodeImpl from the ObjectiveC wrapper.
+    DOMNode *n = (DOMNode *)self;
+    DOM::NodeImpl *nodeImpl = [n _nodeImpl];
+
+    // Dig up Interpreter and ExecState.
+    KHTMLPart *part = nodeImpl->getDocument()->part();
+    KJS::Interpreter *interpreter = KJSProxy::proxy(part)->interpreter();
+    KJS::ExecState *exec = interpreter->globalExec();
+    
+    // Get (or create) a cached JS object for the DOM node.
+    KJS::ObjectImp *scriptImp = static_cast<KJS::ObjectImp *>(KJS::getDOMNode (exec, DOM::Node (nodeImpl)).imp());
+
+    [self _initializeWithObjectImp:scriptImp root:KWQ(part)->bindingRootObject()];
+}
+
+@end
+
+
index f0a748a5d3e78316469a6df1663a9e999150af43..b8a2930faf22f3f2af205c26f668f844792f0b0d 100644 (file)
@@ -285,6 +285,8 @@ public:
     void postDidChangeNotification();
     bool isContentEditable() const;
 
+    KJS::Bindings::RootObject *bindingRootObject();
+    
     WebScriptObject *windowScriptObject();
     void bindObject(void *object, QString name);
     
@@ -342,6 +344,8 @@ private:
 
     friend class KHTMLPart;
 
+    KJS::Bindings::RootObject *_bindingRoot;  // The root object used for objects
+                                            // bound outside the context of a plugin.
     QPtrList<KJS::Bindings::RootObject> rootObjects;
     WebScriptObject *_windowScriptObject;
 };
index 8235c6fd57fc3794b223ee07d804bf8be9286420..947fe283c9f5cda8fc885ab9d43dfea4c4f99a4b 100644 (file)
@@ -176,6 +176,7 @@ KWQKHTMLPart::KWQKHTMLPart()
     , _windowWidget(NULL)
     , _usesInactiveTextBackgroundColor(false)
     , _showsFirstResponder(true)
+    , _bindingRoot(0)
     , _windowScriptObject(0)
 {
     // Must init the cache before connecting to any signals
@@ -1135,15 +1136,23 @@ bool KWQKHTMLPart::tabsToAllControls() const
         return KWQKHTMLPart::currentEventIsKeyboardOptionTab();
 }
 
+KJS::Bindings::RootObject *KWQKHTMLPart::bindingRootObject()
+{
+    if (!_bindingRoot) {
+        _bindingRoot = new KJS::Bindings::RootObject(0);    // The root gets deleted by JavaScriptCore.
+        KJS::ObjectImp *win = static_cast<KJS::ObjectImp *>(KJS::Window::retrieveWindow(this));
+        _bindingRoot->setRootObjectImp (win);
+        _bindingRoot->setInterpreter (KJSProxy::proxy(this)->interpreter());
+        addPluginRootObject (_bindingRoot);
+    }
+    return _bindingRoot;
+}
+
 WebScriptObject *KWQKHTMLPart::windowScriptObject()
 {
     if (!_windowScriptObject) {
-        KJS::Bindings::RootObject *root = new KJS::Bindings::RootObject(0);    // The root gets deleted by JavaScriptCore.
         KJS::ObjectImp *win = static_cast<KJS::ObjectImp *>(KJS::Window::retrieveWindow(this));
-        root->setRootObjectImp (win);
-        root->setInterpreter (KJSProxy::proxy(this)->interpreter());
-        addPluginRootObject (root);
-        _windowScriptObject = [[WebScriptObject alloc] _initWithObjectImp:win root:root];
+        _windowScriptObject = [[WebScriptObject alloc] _initWithObjectImp:win root:bindingRootObject()];
     }
 
     return _windowScriptObject;
index 852fdddc94ea571a52bd9a5a4d688ada00d4068b..049420dadfcef9ffc29fc78ca2877e656a8171d7 100644 (file)
@@ -1,3 +1,11 @@
+2004-05-20  Richard Williamson   <rjw@apple.com>
+
+               Fixed typo in header comment.
+               
+        Reviewed by Ken.
+
+        * Plugins.subproj/WebScriptObject.h:
+
 2004-05-19  Chris Blumenberg  <cblu@apple.com>
 
        Fixed: <rdar://problem/3462627>: (API: Need a way to disable/customize dragging)
index 1d5145251589411a5e9d7e93354125e4e4bd90bb..f581d75ce7a08009e8f7b7b80d52b0cd3ca4829e 100644 (file)
 /*!
     @method finalizeForWebScript
     @discussion finalizeForScript is called on objects exposed to the script
-    environment just before the script environment is reset.  After calls to
-    finalizeForScript the object will no longer be referenced by the script environment.
-    Further any references to WebScriptObjects made by the exposed object will
+    environment just before the script environment releases the object.  After calls to
+    finalizeForWebScript the object will no longer be referenced by the script environment.
+    Further, any references to WebScriptObjects made by the exposed object will
     be invalid and have undefined consequences.
 */
 - (void)finalizeForWebScript;