Ignore:
Timestamp:
Jan 26, 2007, 8:50:17 PM (18 years ago)
Author:
ggaren
Message:

JavaScriptCore:

Reviewed by Maciej Stachowiak.


Fixed <rdar://problem/4608404> WebScriptObject's _rootObject lack
of ownership policy causes crashes (e.g., in Dashcode)


The old model for RootObject ownership was either to (1) leak them or (2) assign
them to a single owner -- the WebCore::Frame -- which would destroy them
when it believed that all of its plug-ins had unloaded.


This model was broken because of (1) and also because plug-ins are not the only
RootObject clients. All Bindings clients are RootObjects clients, including
applications, which outlive any particular WebCore::Frame.


The new model for RootObject ownership is to reference-count them, with a
throw-back to the old model: The WebCore::Frame tracks the RootObjects
it creates, and invalidates them when it believes that all of its plug-ins
have unloaded.


We maintain this throw-back to avoid plug-in leaks, particularly from Java.
Java is completely broken when it comes to releasing JavaScript objects.
Comments in our code allege that Java does not always call finalize when
collecting objects. Moreoever, my own testing reveals that, when Java does
notify JavaScript of a finalize, the data it provides is totally bogus.


This setup is far from ideal, but I don't think we can do better without
completely rewriting the bindings code, and possibly part of the Java
plug-in / VM.


Layout tests pass. No additional leaks reported. WebCore/manual-tests/*liveconnect*
and a few LiveConnect demos on the web also run without a hitch.


const RootObject* => RootObject*, since we need to ref/deref


  • bindings/NP_jsobject.cpp: (jsDeallocate): deref our RootObjects. Also unprotect or JSObject, instead of just relying on the RootObject to do it for us when it's invalidated. (_isSafeScript): Check RootObject validity. (_NPN_CreateScriptObject): ditto (_NPN_Invoke): ditto (_NPN_Evaluate): ditto (_NPN_GetProperty): ditto (_NPN_SetProperty): ditto (_NPN_RemoveProperty): ditto (_NPN_HasProperty): ditto (_NPN_HasMethod): ditto (_NPN_SetException): ditto
  • bindings/runtime_root.cpp: Revived bit-rotted LIAR LIAR LIAR comment.


LOOK: Added support for invalidating RootObjects without deleting them,
which is the main goal of this patch.

Moved protect counting into the RootObject class, to emphasize that
the RootObject protects the JSObject, and unprotects it upon being invalidated.

addNativeReference => RootObject::gcProtect
removeNativeReference => RootObject::gcUnprotect
ProtectCountSet::contains => RootObject::gcIsProtected


I know we'll all be sad to see the word "native" go.


  • bindings/runtime_root.h: Added ref-counting support to RootObject, with all the standard accoutrements.
  • bindings/c/c_utility.cpp: (KJS::Bindings::convertValueToNPVariant): If we can't find a valid RootObject, return void instead of just leaking.
  • bindings/jni/jni_instance.cpp: (JavaInstance::JavaInstance): Don't take a RootObject in our constructor; be like other Instances and require the caller to call setRootObject. This reduces the number of ownership code paths. (JavaInstance::invokeMethod): Check RootObject for validity.
  • bindings/jni/jni_instance.h: Removed private no-arg constructor. Having an arg constructor accomplishes the same thing.
  • bindings/jni/jni_jsobject.cpp: (JavaJSObject::invoke): No need to call findProtectCountSet, because finalize() checks for RootObject validity. (JavaJSObject::JavaJSObject): check RootObject for validity (JavaJSObject::call): ditto (JavaJSObject::eval): ditto (JavaJSObject::getMember): ditto (JavaJSObject::setMember): ditto (JavaJSObject::removeMember): ditto (JavaJSObject::getSlot): ditto (JavaJSObject::setSlot): ditto (JavaJSObject::toString): ditto (JavaJSObject::finalize): ditto (JavaJSObject::createNative): No need to tell the RootObject to protect the global object, since the RootObject already owns the interpreter.
  • bindings/jni/jni_runtime.cpp: (JavaArray::JavaArray): Removed copy construcutor becaue it was unused. Dead code is dangerous code.
  • bindings/objc/objc_runtime.mm: Added WebUndefined protocol. Previous use of WebScriptObject was bogus, because WebUndefined is not a subclass of WebScriptObject. (convertValueToObjcObject): If we can't find a valid RootObject, return nil instead of just leaking.
  • bindings/objc/objc_utility.mm: (KJS::Bindings::convertValueToObjcValue): If we can't find a valid RootObject, return nil instead of just leaking.

LayoutTests:

Reviewed by Maciej Stachowiak.


Added test for <rdar://problem/4608404> WebScriptObject's _rootObject lack
of ownership policy causes crashes (e.g., in Dashcode)


No test for Java or NPP versions of this bug because there's no reliable way to
make Java and NPP objects outlive their RootObjects (although Java objects
sometimes do).

  • plugins/root-object-premature-delete-crash-expected.txt: Added.
  • plugins/root-object-premature-delete-crash.html: Added.

WebCore:

Reviewed by Maciej Stachowiak.


Fixed <rdar://problem/4608404> WebScriptObject's _executionContext lack
of ownership policy causes crashes (e.g., in Dashcode)

Added RootObject ref-counting goodness.

  • page/mac/FrameMac.h:
  • page/mac/FrameMac.mm: (WebCore::FrameMac::cleanupPluginObjects): Invalidate our RootObjects instead of detroying them. Track _bindingRootObject separately from the rest of our RootObjects, since it has its own variable.
  • page/mac/WebCoreFrameBridge.mm: (createRootObject): Use the Frame's new, more encapsulated function to create a RootObject.
  • bindings/objc/WebScriptObject.mm: Nixed rootObject setters, since they were unused and they complicated reference-counting.

WebKitTools:

Reviewed by Maciej Stachowiak.


Added support for test for <rdar://problem/4608404> WebScriptObject's
_rootObject lack of ownership policy causes crashes (e.g., in Dashcode)


  • DumpRenderTree/DumpRenderTree.m: (+[LayoutTestController isSelectorExcludedFromWebScript:]): (+[LayoutTestController webScriptNameForSelector:]): (-[LayoutTestController storeWebScriptObject:]): (-[LayoutTestController accessStoredWebScriptObject]): (-[LayoutTestController dealloc]):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/bindings/objc/WebScriptObject.h

    r18461 r19183  
    2929#include "runtime_root.h"
    3030
     31@class WebUndefined;
     32
    3133@protocol WebScriptObject
    3234+ (NSString *)webScriptNameForSelector:(SEL)aSelector;
     
    3537+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
    3638
    37 + (id)_convertValueToObjcValue:(KJS::JSValue *)value originRootObject:(const KJS::Bindings::RootObject*)originRootObject rootObject:(const KJS::Bindings::RootObject *)rootObject;
    38 - _initWithJSObject:(KJS::JSObject *)imp originRootObject:(const KJS::Bindings::RootObject*)originRootObject rootObject:(const KJS::Bindings::RootObject*)rootObject;
     39+ (id)_convertValueToObjcValue:(KJS::JSValue *)value originRootObject:(KJS::Bindings::RootObject*)originRootObject rootObject:(KJS::Bindings::RootObject*)rootObject;
     40- _initWithJSObject:(KJS::JSObject*)imp originRootObject:(PassRefPtr<KJS::Bindings::RootObject>)originRootObject rootObject:(PassRefPtr<KJS::Bindings::RootObject>)rootObject;
    3941- (KJS::JSObject *)_imp;
    4042@end
     43
     44@protocol WebUndefined
     45+ (WebUndefined *)undefined;
     46@end
Note: See TracChangeset for help on using the changeset viewer.