diff options
author | fqian@google.com <fqian@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-04 01:14:38 +0000 |
---|---|---|
committer | fqian@google.com <fqian@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-04 01:14:38 +0000 |
commit | 2ecc3274a76dd709e2aaf74d385f57b499d843b5 (patch) | |
tree | 08f5e57ba44140fb4cb8ee8bb426904b0205b533 /webkit/port | |
parent | 3878d08262a721fd785844c56e3e7c0617647101 (diff) | |
download | chromium_src-2ecc3274a76dd709e2aaf74d385f57b499d843b5.zip chromium_src-2ecc3274a76dd709e2aaf74d385f57b499d843b5.tar.gz chromium_src-2ecc3274a76dd709e2aaf74d385f57b499d843b5.tar.bz2 |
De-peerable part 2. Lot of changes on the binding side.
The binding code relies on the type id to cast 'void*' to the right C++ type in order
to call ref() and deref().
Bump third_party/WebKit to 6342 to include depeered RefCounted files and etc.
Review URL: http://codereview.chromium.org/12903
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6343 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/port')
-rw-r--r-- | webkit/port/bindings/scripts/CodeGeneratorV8.pm | 3 | ||||
-rw-r--r-- | webkit/port/bindings/v8/ScriptController.cpp | 12 | ||||
-rw-r--r-- | webkit/port/bindings/v8/V8SVGPODTypeWrapper.h | 4 | ||||
-rw-r--r-- | webkit/port/bindings/v8/V8XMLHttpRequestCustom.cpp | 3 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_custom.cpp | 62 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_custom.h | 4 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_events.h | 2 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_index.h | 125 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_proxy.cpp | 682 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_proxy.h | 26 |
10 files changed, 537 insertions, 386 deletions
diff --git a/webkit/port/bindings/scripts/CodeGeneratorV8.pm b/webkit/port/bindings/scripts/CodeGeneratorV8.pm index 835bd83..44947c8 100644 --- a/webkit/port/bindings/scripts/CodeGeneratorV8.pm +++ b/webkit/port/bindings/scripts/CodeGeneratorV8.pm @@ -571,7 +571,7 @@ END } } - push(@implContentDecls, " Peerable* wrapper = $wrapper;\n"); + push(@implContentDecls, " void* wrapper = $wrapper;\n"); } elsif ($nativeType ne "RGBColor") { push(@implContentDecls, " $nativeType v = "); @@ -1858,6 +1858,7 @@ sub IsDOMNodeType return 1 if $type eq 'Node'; return 1 if $type eq 'ProcessingInstruction'; return 1 if $type eq 'SVGElement'; + return 1 if $type eq 'SVGDocument'; return 1 if $type eq 'SVGSVGElement'; return 1 if $type eq 'SVGUseElement'; return 1 if $type eq 'Text'; diff --git a/webkit/port/bindings/v8/ScriptController.cpp b/webkit/port/bindings/v8/ScriptController.cpp index 2d45354..90ca327 100644 --- a/webkit/port/bindings/v8/ScriptController.cpp +++ b/webkit/port/bindings/v8/ScriptController.cpp @@ -100,12 +100,12 @@ bool ScriptController::isSafeScript(Frame* target) void ScriptController::gcProtectJSWrapper(void* dom_object) { - V8Proxy::GCProtect(static_cast<Peerable*>(dom_object)); + V8Proxy::GCProtect(dom_object); } void ScriptController::gcUnprotectJSWrapper(void* dom_object) { - V8Proxy::GCUnprotect(static_cast<Peerable*>(dom_object)); + V8Proxy::GCUnprotect(dom_object); } void ScriptController::entangleMessagePorts(MessagePort *port1, @@ -130,7 +130,7 @@ void ScriptController::entangleMessagePorts(MessagePort *port1, void ScriptController::unentangleMessagePort(MessagePort *port) { // Remove the wrapper entanglement when a port is unentangled. - if (port->peer() != NULL) { + if (V8Proxy::DOMObjectHasJSWrapper(port)) { v8::Handle<v8::Value> wrapper = V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, port); ASSERT(wrapper->IsObject()); @@ -377,9 +377,9 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge // Frame Memory Management for NPObjects // ------------------------------------- // NPObjects are treated differently than other objects wrapped by JS. - // NPObjects are not Peerable, and cannot be made peerable, since NPObjects - // can be created either by the browser (e.g. the main window object) or by - // the plugin (the main plugin object for a HTMLEmbedElement). Further, + // NPObjects can be created either by the browser (e.g. the main + // window object) or by the plugin (the main plugin object + // for a HTMLEmbedElement). Further, // unlike most DOM Objects, the frame is especially careful to ensure // NPObjects terminate at frame teardown because if a plugin leaks a // reference, it could leak its objects (or the browser's objects). diff --git a/webkit/port/bindings/v8/V8SVGPODTypeWrapper.h b/webkit/port/bindings/v8/V8SVGPODTypeWrapper.h index 2638b79..3c66901 100644 --- a/webkit/port/bindings/v8/V8SVGPODTypeWrapper.h +++ b/webkit/port/bindings/v8/V8SVGPODTypeWrapper.h @@ -42,9 +42,7 @@ namespace WebCore { template<typename PODType> class V8SVGPODTypeWrapper : public RefCounted<V8SVGPODTypeWrapper<PODType> > { public: - // Start with a refcount of 0 because the only reference to this - // object will be the JavaScript peer created for it. - V8SVGPODTypeWrapper() : RefCounted<V8SVGPODTypeWrapper<PODType> >(0) { } + V8SVGPODTypeWrapper() { } virtual ~V8SVGPODTypeWrapper() { } virtual operator PODType() = 0; virtual void commitChange(PODType, SVGElement*) = 0; diff --git a/webkit/port/bindings/v8/V8XMLHttpRequestCustom.cpp b/webkit/port/bindings/v8/V8XMLHttpRequestCustom.cpp index 91b048bd..6044cb9 100644 --- a/webkit/port/bindings/v8/V8XMLHttpRequestCustom.cpp +++ b/webkit/port/bindings/v8/V8XMLHttpRequestCustom.cpp @@ -58,7 +58,8 @@ CALLBACK_FUNC_DECL(XMLHttpRequestConstructor) { RefPtr<XMLHttpRequest> xhr = XMLHttpRequest::create(doc); V8Proxy::SetDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xhr.get()); - // Set object as the peer. + // Add object to the wrapper map. + xhr->ref(); V8Proxy::SetJSWrapperForActiveDOMObject(xhr.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); diff --git a/webkit/port/bindings/v8/v8_custom.cpp b/webkit/port/bindings/v8/v8_custom.cpp index c5cdc34..281ae7c 100644 --- a/webkit/port/bindings/v8/v8_custom.cpp +++ b/webkit/port/bindings/v8/v8_custom.cpp @@ -281,17 +281,17 @@ CALLBACK_FUNC_DECL(MessageChannelConstructor) { // Create wrappers for the two associated MessagePorts. v8::Handle<v8::Value> port1_wrapper = - V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, - static_cast<Peerable*>(obj->port1())); + V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, obj->port1()); v8::Handle<v8::Value> port2_wrapper = - V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, - static_cast<Peerable*>(obj->port2())); + V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, obj->port2()); v8::Handle<v8::Object> wrapper_object = args.Holder(); // Setup the standard wrapper object internal fields. V8Proxy::SetDOMWrapper( wrapper_object, V8ClassIndex::MESSAGECHANNEL, obj.get()); + + obj->ref(); V8Proxy::SetJSWrapperForDOMObject( obj.get(), v8::Persistent<v8::Object>::New(wrapper_object)); @@ -435,13 +435,16 @@ CALLBACK_FUNC_DECL(XSLTProcessorRemoveParameter) { // ---- Canvas support ---- -static v8::Handle<v8::Value> CanvasStyleToV8Object(CanvasStyle* style) -{ - if (style->canvasGradient()) - return V8Proxy::ToV8Object(V8ClassIndex::CANVASGRADIENT, static_cast<Peerable*>(style->canvasGradient())); - if (style->canvasPattern()) - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, static_cast<Peerable*>(style->canvasPattern())); - return v8String(style->color()); +static v8::Handle<v8::Value> CanvasStyleToV8Object(CanvasStyle* style) { + if (style->canvasGradient()) { + return V8Proxy::ToV8Object(V8ClassIndex::CANVASGRADIENT, + style->canvasGradient()); + } + if (style->canvasPattern()) { + return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, + style->canvasPattern()); + } + return v8String(style->color()); } static PassRefPtr<CanvasStyle> V8ObjectToCanvasStyle(v8::Handle<v8::Value> value) @@ -528,8 +531,7 @@ ACCESSOR_GETTER(DocumentLocation) { return v8::Null(); DOMWindow* window = imp->frame()->domWindow(); - return V8Proxy::ToV8Object(V8ClassIndex::LOCATION, - static_cast<Peerable*>(window->location())); + return V8Proxy::ToV8Object(V8ClassIndex::LOCATION, window->location()); } @@ -638,8 +640,7 @@ static v8::Handle<v8::Value> HTMLCollectionGetNamedItems( return V8Proxy::NodeToV8Object(namedItems.at(0).get()); default: NodeList* list = new V8VectorNodeList(namedItems); - return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, - static_cast<Peerable*>(list)); + return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, list); } } @@ -1393,8 +1394,7 @@ NAMED_PROPERTY_GETTER(DOMWindow) { if (items->length() == 1) { return V8Proxy::NodeToV8Object(items->firstItem()); } else { - return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, - static_cast<Peerable*>(items.get())); + return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION,items.get()); } } } @@ -1451,7 +1451,7 @@ NAMED_PROPERTY_GETTER(HTMLDocument) return value; } - HTMLDocument* imp = V8Proxy::DOMWrapperToNode<HTMLDocument>(info.Holder()); + HTMLDocument* imp = V8Proxy::DOMWrapperToNode<HTMLDocument>(info.Holder()); // Fast case for named elements that are not there. if (!imp->hasNamedItem(key.impl()) && !imp->hasExtraNamedItem(key.impl())) @@ -1463,12 +1463,12 @@ NAMED_PROPERTY_GETTER(HTMLDocument) if (items->length() == 1) { Node* node = items->firstItem(); Frame* frame = 0; - if (node->hasTagName(HTMLNames::iframeTag) && (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame())) + if (node->hasTagName(HTMLNames::iframeTag) && + (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame())) return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); - return V8Proxy::NodeToV8Object(node); + return V8Proxy::NodeToV8Object(node); } - return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, - static_cast<Peerable*>(items.get())); + return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, items.get()); } @@ -1516,8 +1516,7 @@ NAMED_PROPERTY_GETTER(HTMLFormElement) { return V8Proxy::NodeToV8Object(elements.at(0).get()); } else { NodeList* collection = new V8VectorNodeList(elements); - return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, - static_cast<Peerable*>(collection)); + return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, collection); } } @@ -2173,8 +2172,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DCreatePattern) { V8Proxy::SetDOMException(ec); return v8::Handle<v8::Value>(); } - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, - static_cast<Peerable*>(pattern.get())); + return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, pattern.get()); } if (V8HTMLCanvasElement::HasInstance(arg)) { @@ -2187,8 +2185,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DCreatePattern) { V8Proxy::SetDOMException(ec); return v8::Handle<v8::Value>(); } - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, - static_cast<Peerable*>(pattern.get())); + return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, pattern.get()); } V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); @@ -2888,8 +2885,7 @@ CALLBACK_FUNC_DECL(DocumentEvaluate) { V8Proxy::SetDOMException(ec); return v8::Handle<v8::Value>(); } - return V8Proxy::ToV8Object(V8ClassIndex::XPATHRESULT, - static_cast<Peerable*>(result.get())); + return V8Proxy::ToV8Object(V8ClassIndex::XPATHRESULT, result.get()); } // DOMWindow ------------------------------------------------------------------- @@ -3408,9 +3404,8 @@ CALLBACK_FUNC_DECL(SVGMatrixInverse) { return v8::Handle<v8::Value>(); } - Peerable* peer = static_cast<Peerable*>( + return V8Proxy::ToV8Object(V8ClassIndex::SVGMATRIX, new V8SVGStaticPODTypeWrapper<AffineTransform>(result)); - return V8Proxy::ToV8Object(V8ClassIndex::SVGMATRIX, peer); } CALLBACK_FUNC_DECL(SVGMatrixRotateFromVector) { @@ -3431,9 +3426,8 @@ CALLBACK_FUNC_DECL(SVGMatrixRotateFromVector) { return v8::Handle<v8::Value>(); } - Peerable* peer = static_cast<Peerable*>( + return V8Proxy::ToV8Object(V8ClassIndex::SVGMATRIX, new V8SVGStaticPODTypeWrapper<AffineTransform>(result)); - return V8Proxy::ToV8Object(V8ClassIndex::SVGMATRIX, peer); } CALLBACK_FUNC_DECL(SVGElementInstanceAddEventListener) { diff --git a/webkit/port/bindings/v8/v8_custom.h b/webkit/port/bindings/v8/v8_custom.h index c93fdf9..64a2351 100644 --- a/webkit/port/bindings/v8/v8_custom.h +++ b/webkit/port/bindings/v8/v8_custom.h @@ -33,8 +33,8 @@ class V8Custom { public: // Constants. - static const int kDOMWrapperObjectIndex = 0; - static const int kDOMWrapperTypeIndex = 1; + static const int kDOMWrapperTypeIndex = 0; + static const int kDOMWrapperObjectIndex = 1; static const int kDefaultWrapperInternalFieldCount = 2; static const int kDocumentImplementationIndex = diff --git a/webkit/port/bindings/v8/v8_events.h b/webkit/port/bindings/v8/v8_events.h index 72ed31c..93acdc1 100644 --- a/webkit/port/bindings/v8/v8_events.h +++ b/webkit/port/bindings/v8/v8_events.h @@ -61,7 +61,7 @@ class V8AbstractEventListener : public EventListener { // the event listener is deleted. Fix this! Frame* m_frame; - // Listener object, avoid using peer because it can keep this object alive. + // Listener object. v8::Persistent<v8::Object> m_listener; // Flags this is a HTML type listener. diff --git a/webkit/port/bindings/v8/v8_index.h b/webkit/port/bindings/v8/v8_index.h index e192291..fd5849c 100644 --- a/webkit/port/bindings/v8/v8_index.h +++ b/webkit/port/bindings/v8/v8_index.h @@ -10,9 +10,6 @@ namespace WebCore { -class Node; -class XMLHttpRequest; - typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #if ENABLE(VIDEO) @@ -21,15 +18,15 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(HTMLMEDIAELEMENT, HTMLMediaElement) \ V(HTMLSOURCEELEMENT, HTMLSourceElement) \ V(HTMLVIDEOELEMENT, HTMLVideoElement) -#define VIDEO_NONNODE_WRAPPER_TYPES(V) \ +#define VIDEO_NONNODE_TYPES(V) \ V(MEDIAERROR, MediaError) \ V(TIMERANGES, TimeRanges) #else #define VIDEO_HTMLELEMENT_TYPES(V) -#define VIDEO_NONNODE_WRAPPER_TYPES(V) +#define VIDEO_NONNODE_TYPES(V) #endif -#define NODE_WRAPPER_TYPES(V) \ +#define DOM_NODE_TYPES(V) \ V(ATTR, Attr) \ V(CHARACTERDATA, CharacterData) \ V(CDATASECTION, CDATASection) \ @@ -45,9 +42,8 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(NODE, Node) \ V(NOTATION, Notation) \ V(PROCESSINGINSTRUCTION, ProcessingInstruction) \ - V(TEXT, Text) - -#define HTMLELEMENT_TYPES(V) \ + V(TEXT, Text) \ + \ V(HTMLANCHORELEMENT, HTMLAnchorElement) \ V(HTMLAPPLETELEMENT, HTMLAppletElement) \ V(HTMLAREAELEMENT, HTMLAreaElement) \ @@ -175,7 +171,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #endif #if ENABLE(SVG) -#define SVGELEMENT_TYPES(V) \ +#define SVG_NODE_TYPES(V) \ SVG_ANIMATION_ELEMENT_TYPES(V) \ SVG_FILTERS_ELEMENT_TYPES(V) \ SVG_FONTS_ELEMENT_TYPES(V) \ @@ -190,7 +186,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(SVGDESCELEMENT, SVGDescElement) \ V(SVGELLIPSEELEMENT, SVGEllipseElement) \ V(SVGGELEMENT, SVGGElement) \ - V(SVGGLYPHELEMENT, SVGGlyphElement) \ + V(SVGGLYPHELEMENT, SVGGlyphElement) \ V(SVGGRADIENTELEMENT, SVGGradientElement) \ V(SVGIMAGEELEMENT, SVGImageElement) \ V(SVGLINEARGRADIENTELEMENT, SVGLinearGradientElement) \ @@ -218,13 +214,23 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(SVGTREFELEMENT, SVGTRefElement) \ V(SVGTSPANELEMENT, SVGTSpanElement) \ V(SVGVIEWELEMENT, SVGViewElement) \ - V(SVGELEMENT, SVGElement) -#endif + V(SVGELEMENT, SVGElement) \ + \ + V(SVGDOCUMENT, SVGDocument) +#endif // SVG + -// NOTE: NONNODE_WRAPPER_TYPES is split into two halves because +// ACTIVE_DOM_OBJECT_TYPES are DOM_OBJECT_TYPES that need special treatement +// during GC. +#define ACTIVE_DOM_OBJECT_TYPES(V) \ + V(MESSAGEPORT, MessagePort) \ + V(XMLHTTPREQUEST, XMLHttpRequest) + +// NOTE: DOM_OBJECT_TYPES is split into two halves because // Visual Studio's Intellinonsense crashes when macros get // too large. 10-29-08 -#define NONNODE_WRAPPER_TYPES(V) \ +// DOM_OBJECT_TYPES are non-node DOM types. +#define DOM_OBJECT_TYPES_1(V) \ V(BARINFO, BarInfo) \ V(CANVASGRADIENT, CanvasGradient) \ V(CANVASPATTERN, CanvasPattern) \ @@ -267,10 +273,9 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(LOCATION, Location) \ V(MEDIALIST, MediaList) -#define NONNODE_WRAPPER_TYPES_2(V) \ +#define DOM_OBJECT_TYPES_2(V) \ V(MESSAGECHANNEL, MessageChannel) \ V(MESSAGEEVENT, MessageEvent) \ - V(MESSAGEPORT, MessagePort) \ V(MIMETYPE, MimeType) \ V(MIMETYPEARRAY, MimeTypeArray) \ V(MOUSEEVENT, MouseEvent) \ @@ -301,7 +306,6 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(WEBKITCSSTRANSFORMVALUE, WebKitCSSTransformValue) \ V(WEBKITTRANSITIONEVENT, WebKitTransitionEvent) \ V(WHEELEVENT, WheelEvent) \ - V(XMLHTTPREQUEST, XMLHttpRequest) \ V(XMLHTTPREQUESTUPLOAD, XMLHttpRequestUpload) \ V(XMLHTTPREQUESTEXCEPTION, XMLHttpRequestException) \ V(XMLHTTPREQUESTPROGRESSEVENT, XMLHttpRequestProgressEvent) \ @@ -312,13 +316,18 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(XPATHNSRESOLVER, XPathNSResolver) \ V(XPATHRESULT, XPathResult) \ V(XSLTPROCESSOR, XSLTProcessor) \ - VIDEO_NONNODE_WRAPPER_TYPES(V) + ACTIVE_DOM_OBJECT_TYPES(V) \ + VIDEO_NONNODE_TYPES(V) + + +#define DOM_OBJECT_TYPES(V) \ + DOM_OBJECT_TYPES_1(V) \ + DOM_OBJECT_TYPES_2(V) -#if ENABLE(SVG) -#define SVGNODE_WRAPPER_TYPES(V) \ - V(SVGDOCUMENT, SVGDocument) -#define SVGNONNODE_WRAPPER_TYPES(V) \ +#if ENABLE(SVG) +// SVG_OBJECT_TYPES are svg non-node, non-pod types. +#define SVG_OBJECT_TYPES(V) \ V(SVGANGLE, SVGAngle) \ V(SVGANIMATEDANGLE, SVGAnimatedAngle) \ V(SVGANIMATEDBOOLEAN, SVGAnimatedBoolean) \ @@ -328,7 +337,6 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(SVGANIMATEDLENGTHLIST, SVGAnimatedLengthList) \ V(SVGANIMATEDNUMBER, SVGAnimatedNumber) \ V(SVGANIMATEDNUMBERLIST, SVGAnimatedNumberList) \ - V(SVGANIMATEDPOINTS, SVGAnimatedPoints) \ V(SVGANIMATEDPRESERVEASPECTRATIO, SVGAnimatedPreserveAspectRatio) \ V(SVGANIMATEDRECT, SVGAnimatedRect) \ V(SVGANIMATEDSTRING, SVGAnimatedString) \ @@ -337,10 +345,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(SVGELEMENTINSTANCE, SVGElementInstance) \ V(SVGELEMENTINSTANCELIST, SVGElementInstanceList) \ V(SVGEXCEPTION, SVGException) \ - V(SVGLENGTH, SVGLength) \ V(SVGLENGTHLIST, SVGLengthList) \ - V(SVGMATRIX, SVGMatrix) \ - V(SVGNUMBER, SVGNumber) \ V(SVGNUMBERLIST, SVGNumberList) \ V(SVGPAINT, SVGPaint) \ V(SVGPATHSEG, SVGPathSeg) \ @@ -364,41 +369,66 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(SVGPATHSEGLIST, SVGPathSegList) \ V(SVGPATHSEGMOVETOABS, SVGPathSegMovetoAbs) \ V(SVGPATHSEGMOVETOREL, SVGPathSegMovetoRel) \ - V(SVGPOINT, SVGPoint) \ V(SVGPOINTLIST, SVGPointList) \ V(SVGPRESERVEASPECTRATIO, SVGPreserveAspectRatio) \ - V(SVGRECT, SVGRect) \ V(SVGRENDERINGINTENT, SVGRenderingIntent) \ V(SVGSTRINGLIST, SVGStringList) \ - V(SVGTRANSFORM, SVGTransform) \ V(SVGTRANSFORMLIST, SVGTransformList) \ V(SVGUNITTYPES, SVGUnitTypes) \ - V(SVGURIREFERENCE, SVGURIReference) \ V(SVGZOOMEVENT, SVGZoomEvent) -#endif + +// SVG POD types shoud list all types whose IDL has PODType declaration. +#define SVG_POD_TYPES(V) \ + V(SVGLENGTH, SVGLength) \ + V(SVGTRANSFORM, SVGTransform) \ + V(SVGMATRIX, SVGMatrix) \ + V(SVGNUMBER, SVGNumber) \ + V(SVGPOINT, SVGPoint) \ + V(SVGRECT, SVGRect) + +// POD types can have different implementation names, see CodeGenerateV8.pm. +#define SVG_POD_NATIVE_TYPES(V) \ + V(SVGLENGTH, SVGLength) \ + V(SVGTRANSFORM, SVGTransform) \ + V(SVGMATRIX, AffineTransform) \ + V(SVGNUMBER, float) \ + V(SVGPOINT, FloatPoint) \ + V(SVGRECT, FloatRect) + +// Shouldn't generate code for these two types. +#define SVG_NO_WRAPPER_TYPES(V) \ + V(SVGURIREFERENCE, SVGURIReference) \ + V(SVGANIMATEDPOINTS, SVGAnimatedPoints) + +// SVG_NONNODE_TYPES are SVG non-node object types, pod typs and +// numerical types. +#define SVG_NONNODE_TYPES(V) \ + SVG_OBJECT_TYPES(V) \ + SVG_POD_TYPES(V) +#endif // SVG // EVENTTARGET, EVENTLISTENER, and NPOBJECT do not have V8 wrappers. -#define NO_WRAPPER_TYPES(V) \ +#define DOM_NO_WRAPPER_TYPES(V) \ V(EVENTTARGET, EventTarget) \ V(EVENTLISTENER, EventListener) \ V(NPOBJECT, NPObject) #if ENABLE(SVG) #define WRAPPER_TYPES(V) \ - NODE_WRAPPER_TYPES(V) \ - HTMLELEMENT_TYPES(V) \ - NONNODE_WRAPPER_TYPES(V) \ - NONNODE_WRAPPER_TYPES_2(V) \ - SVGNODE_WRAPPER_TYPES(V) \ - SVGELEMENT_TYPES(V) \ - SVGNONNODE_WRAPPER_TYPES(V) -#else + DOM_NODE_TYPES(V) \ + DOM_OBJECT_TYPES(V) \ + SVG_NODE_TYPES(V) \ + SVG_NONNODE_TYPES(V) +#define NO_WRAPPER_TYPES(V) \ + DOM_NO_WRAPPER_TYPES(V) \ + SVG_NO_WRAPPER_TYPES(V) +#else // SVG #define WRAPPER_TYPES(V) \ - NODE_WRAPPER_TYPES(V) \ - HTMLELEMENT_TYPES(V) \ - NONNODE_WRAPPER_TYPES(V) \ - NONNODE_WRAPPER_TYPES_2(V) -#endif + DOM_NODE_TYPES(V) \ + DOM_OBJECT_TYPES(V) +#define NO_WRAPPER_TYPES(V) \ + DOM_NO_WRAPPER_TYPES(V) +#endif // SVG #define ALL_WRAPPER_TYPES(V) \ WRAPPER_TYPES(V) \ @@ -410,7 +440,7 @@ class V8ClassIndex { enum V8WrapperType { INVALID_CLASS_INDEX = 0, #define DEFINE_ENUM(name, type) name, -ALL_WRAPPER_TYPES(DEFINE_ENUM) + ALL_WRAPPER_TYPES(DEFINE_ENUM) #undef DEFINE_ENUM CLASSINDEX_END, }; @@ -426,6 +456,7 @@ ALL_WRAPPER_TYPES(DEFINE_ENUM) // Returns a field to be used as cache for the template for the given type static v8::Persistent<v8::FunctionTemplate>* GetCache(V8WrapperType type); }; + } #endif // V8_INDEX_H__ diff --git a/webkit/port/bindings/v8/v8_proxy.cpp b/webkit/port/bindings/v8/v8_proxy.cpp index 0559972..faaf678 100644 --- a/webkit/port/bindings/v8/v8_proxy.cpp +++ b/webkit/port/bindings/v8/v8_proxy.cpp @@ -41,70 +41,147 @@ #include "v8_nodefilter.h" #include "V8DOMWindow.h" -#include "RefCounted.h" // for Peerable - #include "ChromiumBridge.h" + +#include "BarInfo.h" +#include "CanvasGradient.h" +#include "CanvasPattern.h" +#include "CanvasPixelArray.h" +#include "CanvasRenderingContext2D.h" +#include "CanvasStyle.h" +#include "CharacterData.h" +#include "Clipboard.h" +#include "Console.h" +#include "Counter.h" +#include "CSSCharsetRule.h" +#include "CSSFontFaceRule.h" +#include "CSSImportRule.h" +#include "CSSMediaRule.h" +#include "CSSPageRule.h" +#include "CSSRule.h" +#include "CSSRuleList.h" +#include "CSSValueList.h" +#include "CSSStyleRule.h" +#include "CSSStyleSheet.h" +#include "CSSVariablesDeclaration.h" +#include "CSSVariablesRule.h" +#include "DocumentType.h" +#include "DocumentFragment.h" #include "DOMCoreException.h" +#include "DOMImplementation.h" +#include "DOMParser.h" +#include "DOMSelection.h" +#include "DOMWindow.h" +#include "Entity.h" +#include "EventListener.h" +#include "EventTargetNode.h" +#include "EventTarget.h" +#include "Event.h" #include "EventException.h" #include "ExceptionCode.h" +#include "File.h" +#include "FileList.h" #include "Frame.h" +#include "FrameLoader.h" +#include "FrameTree.h" +#include "History.h" #include "HTMLNames.h" #include "HTMLDocument.h" #include "HTMLElement.h" #include "HTMLImageElement.h" +#include "HTMLInputElement.h" #include "HTMLSelectElement.h" #include "HTMLOptionsCollection.h" -#include "Page.h" -#include "DOMWindow.h" +#include "ImageData.h" +#include "InspectorController.h" +#include "KeyboardEvent.h" #include "Location.h" -#include "Navigator.h" // for MimeTypeArray -#include "V8DOMWindow.h" -#include "V8HTMLElement.h" -#include "Entity.h" #include "MediaList.h" -#include "NodeList.h" -#include "Notation.h" -#include "Text.h" -#include "ProcessingInstruction.h" -#include "Console.h" -#include "CharacterData.h" -#include "DocumentType.h" -#include "DocumentFragment.h" -#include "EventListener.h" -#include "EventTargetNode.h" -#include "EventTarget.h" -#include "Event.h" -#include "HTMLInputElement.h" -#include "CSSRule.h" -#include "CSSRuleList.h" -#include "CSSValueList.h" -#include "CSSVariablesDeclaration.h" -#include "FrameLoader.h" -#include "FrameTree.h" +#include "MessageChannel.h" +#include "MessageEvent.h" #include "MessagePort.h" #include "MimeTypeArray.h" +#include "MouseEvent.h" +#include "MutationEvent.h" +#include "Navigator.h" // for MimeTypeArray #include "NodeFilter.h" +#include "Notation.h" +#include "NodeList.h" +#include "NodeIterator.h" +#include "OverflowEvent.h" +#include "Page.h" #include "Plugin.h" #include "PluginArray.h" +#include "ProcessingInstruction.h" +#include "ProgressEvent.h" +#include "Range.h" #include "RangeException.h" -#include "ScriptController.h" +#include "Rect.h" +#include "RGBColor.h" +#include "Screen.h" #include "ScriptExecutionContext.h" #include "SecurityOrigin.h" #include "Settings.h" #include "StyleSheet.h" #include "StyleSheetList.h" +#include "TextEvent.h" +#include "TextMetrics.h" +#include "TreeWalker.h" #include "WebKitCSSTransformValue.h" #include "XMLHttpRequest.h" #include "XMLHttpRequestUpload.h" #include "XMLHttpRequestException.h" +#include "XMLSerializer.h" #include "XPathException.h" +#include "XPathExpression.h" +#include "XPathNSResolver.h" +#include "XPathResult.h" +#include "XSLTProcessor.h" +#include "WebKitAnimationEvent.h" +#include "WebKitCSSKeyframeRule.h" +#include "WebKitCSSKeyframesRule.h" +#include "WebKitTransitionEvent.h" +#include "WheelEvent.h" +#include "XMLHttpRequestProgressEvent.h" + +#include "V8DOMWindow.h" +#include "V8HTMLElement.h" + +#include "ScriptController.h" #if ENABLE(SVG) +#include "SVGAngle.h" +#include "SVGAnimatedPoints.h" #include "SVGElement.h" #include "SVGElementInstance.h" +#include "SVGElementInstanceList.h" #include "SVGException.h" +#include "SVGLength.h" +#include "SVGLengthList.h" +#include "SVGNumberList.h" +#include "SVGPathSeg.h" +#include "SVGPathSegArc.h" +#include "SVGPathSegClosePath.h" +#include "SVGPathSegCurvetoCubic.h" +#include "SVGPathSegCurvetoCubicSmooth.h" +#include "SVGPathSegCurvetoQuadratic.h" +#include "SVGPathSegCurvetoQuadraticSmooth.h" +#include "SVGPathSegLineto.h" +#include "SVGPathSegLinetoHorizontal.h" +#include "SVGPathSegLinetoVertical.h" +#include "SVGPathSegList.h" +#include "SVGPathSegMoveto.h" +#include "SVGPointList.h" +#include "SVGPreserveAspectRatio.h" +#include "SVGRenderingIntent.h" +#include "SVGStringList.h" +#include "SVGTransform.h" +#include "SVGTransformList.h" +#include "SVGUnitTypes.h" +#include "SVGURIReference.h" #include "SVGZoomEvent.h" -#endif +#include "V8SVGPODTypeWrapper.h" +#endif // SVG #if ENABLE(XPATH) #include "XPathEvaluator.h" @@ -119,7 +196,7 @@ namespace WebCore { // 1. DOM tree nodes, such as Document, HTMLElement, ... // there classes implements TreeShared<T> interface; // 2. Non-node DOM objects, such as CSSRule, Location, etc. -// these classes implements RefCounted<T> interface. +// these classes implement a ref-counted scheme. // // A DOM object may have a JS wrapper object. If a tree node // is alive, its JS wrapper must be kept alive even it is not @@ -140,6 +217,10 @@ namespace WebCore { // collector will remove these groups after each GC. +// A helper class for undetectable document.all +class UndetectableHTMLCollection : public HTMLCollection { +}; + #ifndef NDEBUG // Keeps track of global handles created (not JS wrappers // of DOM objects). Often these global handles are source @@ -241,43 +322,33 @@ void BatchConfigureConstants(v8::Handle<v8::FunctionTemplate> desc, } } +typedef HashMap<Node*, v8::Object*> DOMNodeMap; +typedef HashMap<void*, v8::Object*> DOMObjectMap; -typedef HashMap<Node*, v8::Object*> NodeMap; -typedef HashMap<Peerable*, v8::Object*> PeerableMap; - -// Type T must implement Peerable interface. -template<class T> -class DOMPeerableWrapperMap : public DOMWrapperMap<T> { - public: - explicit DOMPeerableWrapperMap(v8::WeakReferenceCallback callback) : - DOMWrapperMap<T>(callback) { } - - // Get the JS wrapper object of an object. - v8::Persistent<v8::Object> get(T* obj) - { - v8::Object* peer = static_cast<v8::Object*>(obj->peer()); - ASSERT(peer == this->map_.get(obj)); - return peer ? v8::Persistent<v8::Object>(peer) - : v8::Persistent<v8::Object>(); +#ifndef NDEBUG +static void EnumerateDOMObjectMap(DOMObjectMap& wrapper_map) +{ + for (DOMObjectMap::iterator it = wrapper_map.begin(), end = wrapper_map.end(); + it != end; ++it) { + v8::Persistent<v8::Object> wrapper(it->second); + V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(wrapper); + void* obj = it->first; + USE_VAR(type); + USE_VAR(obj); } +} - void set(T* obj, v8::Persistent<v8::Object> peer_handle) - { - ASSERT(obj->peer() == 0); - obj->setPeer(*peer_handle); - DOMWrapperMap<T>::set(obj, peer_handle); - } - void forget(T* obj) - { - v8::Object* peer = static_cast<v8::Object*>(obj->peer()); - ASSERT(peer == this->map_.get(obj)); - if (peer) - obj->setPeer(0); - DOMWrapperMap<T>::forget(obj); +static void EnumerateDOMNodeMap(DOMNodeMap& node_map) +{ + for (DOMNodeMap::iterator it = node_map.begin(), end = node_map.end(); + it != end; ++it) { + Node* node = it->first; + USE_VAR(node); + ASSERT(v8::Persistent<v8::Object>(it->second).IsWeak()); } -}; - +} +#endif // NDEBUG static void WeakDOMObjectCallback(v8::Persistent<v8::Value> obj, void* para); static void WeakActiveDOMObjectCallback(v8::Persistent<v8::Value> obj, @@ -286,25 +357,26 @@ static void WeakNodeCallback(v8::Persistent<v8::Value> obj, void* para); // A map from DOM node to its JS wrapper. static DOMWrapperMap<Node>& dom_node_map() { - static DOMPeerableWrapperMap<Node> static_dom_node_map(&WeakNodeCallback); + static DOMWrapperMap<Node> static_dom_node_map(&WeakNodeCallback); return static_dom_node_map; } -// A map from a non-DOM node (peerable) to its JS wrapper. This map does not -// contain the DOM objects which can have pending activity. -static DOMWrapperMap<Peerable>& dom_object_map() +// A map from a DOM object (non-node) to its JS wrapper. This map does not +// contain the DOM objects which can have pending activity (active dom objects). +static DOMWrapperMap<void>& dom_object_map() { - static DOMPeerableWrapperMap<Peerable> + static DOMWrapperMap<void> static_dom_object_map(&WeakDOMObjectCallback); return static_dom_object_map; } -// A map from a non-DOM node (peerable) to its JS wrapper for DOM objects which + +// A map from a DOM object to its JS wrapper for DOM objects which // can have pending activity. -static DOMWrapperMap<Peerable>& active_dom_object_map() +static DOMWrapperMap<void>& active_dom_object_map() { - static DOMPeerableWrapperMap<Peerable> + static DOMWrapperMap<void> static_active_dom_object_map(&WeakActiveDOMObjectCallback); return static_active_dom_object_map; } @@ -313,7 +385,7 @@ static DOMWrapperMap<Peerable>& active_dom_object_map() static void WeakSVGElementInstanceCallback(v8::Persistent<v8::Value> obj, void* param); -// A map for SVGElementInstances, which are not peerable +// A map for SVGElementInstances. static DOMWrapperMap<SVGElementInstance>& dom_svg_element_instance_map() { static DOMWrapperMap<SVGElementInstance> @@ -356,15 +428,15 @@ v8::Handle<v8::Value> V8Proxy::SVGElementInstanceToV8Object( return result; } + // SVG non-node elements may have a reference to a context node which // should be notified when the element is change static void WeakSVGObjectWithContext(v8::Persistent<v8::Value> obj, - void* param); + void* dom_obj); // Map of SVG objects with contexts to V8 objects -static DOMWrapperMap<Peerable>& dom_svg_object_with_context_map() -{ - static DOMPeerableWrapperMap<Peerable> +static DOMWrapperMap<void>& dom_svg_object_with_context_map() { + static DOMWrapperMap<void> static_dom_svg_object_with_context_map(&WeakSVGObjectWithContext); return static_dom_svg_object_with_context_map; } @@ -377,43 +449,67 @@ static HashMap<void*, SVGElement*>& svg_object_to_context_map() } v8::Handle<v8::Value> V8Proxy::SVGObjectWithContextToV8Object( - Peerable* object, V8ClassIndex::V8WrapperType type) + V8ClassIndex::V8WrapperType type, void* object) { if (!object) return v8::Null(); + v8::Persistent<v8::Object> result = + dom_svg_object_with_context_map().get(object); + if (!result.IsEmpty()) return result; + // Special case: SVGPathSegs need to be downcast to their real type if (type == V8ClassIndex::SVGPATHSEG) type = V8Custom::DowncastSVGPathSeg(object); - v8::Persistent<v8::Object> result = - dom_svg_object_with_context_map().get(object); - if (result.IsEmpty()) { - v8::Local<v8::Object> v8obj = InstantiateV8Object(type, type, object); - if (!v8obj.IsEmpty()) { - result = v8::Persistent<v8::Object>::New(v8obj); - dom_svg_object_with_context_map().set(object, result); + v8::Local<v8::Object> v8obj = InstantiateV8Object(type, type, object); + if (!v8obj.IsEmpty()) { + result = v8::Persistent<v8::Object>::New(v8obj); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(object)->ref(); break; +SVG_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: \ + static_cast<V8SVGPODTypeWrapper<NAME>*>(object)->ref(); break; +SVG_POD_NATIVE_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT(false); } + dom_svg_object_with_context_map().set(object, result); } return result; } static void WeakSVGObjectWithContext(v8::Persistent<v8::Value> obj, - void* param) + void* dom_obj) { - Peerable* dom_obj = static_cast<Peerable*>(param); + v8::HandleScope handle_scope; ASSERT(dom_svg_object_with_context_map().contains(dom_obj)); + ASSERT(obj->IsObject()); - // Release the reference to the context if it exists - if (svg_object_to_context_map().contains(dom_obj)) { - svg_object_to_context_map().get(dom_obj)->deref(); - svg_object_to_context_map().remove(dom_obj); - } - - // forget function removes object from the map, - // disposes the wrapper and clears the peer. + // Forget function removes object from the map and dispose the wrapper. dom_svg_object_with_context_map().forget(dom_obj); + + V8ClassIndex::V8WrapperType type = + V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj)); + + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(dom_obj)->deref(); break; +SVG_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: \ + static_cast<V8SVGPODTypeWrapper<NAME>*>(dom_obj)->deref(); break; +SVG_POD_NATIVE_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT(false); + } } void V8Proxy::SetSVGContext(void* obj, SVGElement* context) @@ -443,25 +539,48 @@ SVGElement* V8Proxy::GetSVGContext(void* obj) // Called when obj is near death (not reachable from JS roots) // It is time to remove the entry from the table and dispose // the handle. -static void WeakDOMObjectCallback(v8::Persistent<v8::Value> obj, void* para) -{ - Peerable* dom_obj = static_cast<Peerable*>(para); +static void WeakDOMObjectCallback(v8::Persistent<v8::Value> obj, + void* dom_obj) { + v8::HandleScope scope; ASSERT(dom_object_map().contains(dom_obj)); + ASSERT(obj->IsObject()); - // forget function removes object from the map, - // disposes the wrapper and clears the peer. + // Forget function removes object from the map and dispose the wrapper. dom_object_map().forget(dom_obj); + + V8ClassIndex::V8WrapperType type = + V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj)); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(dom_obj)->deref(); break; + DOM_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT(false); + } } + static void WeakActiveDOMObjectCallback(v8::Persistent<v8::Value> obj, - void* para) + void* dom_obj) { - Peerable* dom_obj = static_cast<Peerable*>(para); + v8::HandleScope scope; ASSERT(active_dom_object_map().contains(dom_obj)); + ASSERT(obj->IsObject()); - // forget function removes object from the map, - // disposes the wrapper and clears the peer. + // Forget function removes object from the map and dispose the wrapper. active_dom_object_map().forget(dom_obj); + + V8ClassIndex::V8WrapperType type = + V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(obj)); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(dom_obj)->deref(); break; + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT(false); + } } static void WeakNodeCallback(v8::Persistent<v8::Value> obj, void* param) @@ -470,54 +589,90 @@ static void WeakNodeCallback(v8::Persistent<v8::Value> obj, void* param) ASSERT(dom_node_map().contains(node)); dom_node_map().forget(node); + node->deref(); +} + + +// A map from a DOM node to its JS wrapper, the wrapper +// is kept as a strong reference to survive GCs. +static DOMObjectMap& gc_protected_map() { + static DOMObjectMap static_gc_protected_map; + return static_gc_protected_map; +} + +// static +void V8Proxy::GCProtect(void* dom_object) +{ + if (!dom_object) + return; + if (gc_protected_map().contains(dom_object)) + return; + if (!dom_object_map().contains(dom_object)) + return; + + // Create a new (strong) persistent handle for the object. + v8::Persistent<v8::Object> wrapper = dom_object_map().get(dom_object); + if (wrapper.IsEmpty()) return; + + gc_protected_map().set(dom_object, *v8::Persistent<v8::Object>::New(wrapper)); +} + + +// static +void V8Proxy::GCUnprotect(void* dom_object) +{ + if (!dom_object) + return; + if (!gc_protected_map().contains(dom_object)) + return; + + // Dispose the strong reference. + v8::Persistent<v8::Object> wrapper(gc_protected_map().take(dom_object)); + wrapper.Dispose(); } + // Create object groups for DOM tree nodes. static void GCPrologue() { v8::HandleScope scope; #ifndef NDEBUG - // Check that all references in the map are weak. - PeerableMap peer_map = dom_object_map().impl(); - for (PeerableMap::iterator it = peer_map.begin(), end = peer_map.end(); - it != end; ++it) { - Peerable* obj = it->first; - ASSERT(v8::Persistent<v8::Object>(it->second).IsWeak()); - USE_VAR(obj); - } + EnumerateDOMObjectMap(dom_object_map().impl()); #endif // Run through all objects with possible pending activity making their // wrappers non weak if there is pending activity. - PeerableMap active_map = active_dom_object_map().impl(); - for (PeerableMap::iterator it = active_map.begin(), end = active_map.end(); + DOMObjectMap active_map = active_dom_object_map().impl(); + for (DOMObjectMap::iterator it = active_map.begin(), end = active_map.end(); it != end; ++it) { - Peerable* obj = it->first; + void* obj = it->first; v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>(it->second); ASSERT(wrapper.IsWeak()); V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(wrapper); - if (type == V8ClassIndex::XMLHTTPREQUEST) { - XMLHttpRequest* xhr = static_cast<XMLHttpRequest*>(obj); - if (xhr->hasPendingActivity()) { - wrapper.ClearWeak(); - } - } else if (type == V8ClassIndex::MESSAGEPORT) { - MessagePort* message_port = static_cast<MessagePort*>(obj); - if (message_port->hasPendingActivity()) { - wrapper.ClearWeak(); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: { \ + NAME* impl = static_cast<NAME*>(obj); \ + if (impl->hasPendingActivity()) \ + wrapper.ClearWeak(); \ + break; \ } +ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + default: + ASSERT(false); +#undef MAKE_CASE } } // Create object groups. - NodeMap node_map = dom_node_map().impl(); - for (NodeMap::iterator it = node_map.begin(), end = node_map.end(); + DOMNodeMap node_map = dom_node_map().impl(); + for (DOMNodeMap::iterator it = node_map.begin(), end = node_map.end(); it != end; ++it) { Node* node = it->first; // If the node is in document, put it in the ownerDocument's - // object group. + // object group. Otherwise, skip it. // // If an image element was created by JavaScript "new Image", // it is not in a document. However, if the load event has not @@ -530,6 +685,7 @@ static void GCPrologue() (node->hasTagName(HTMLNames::imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent()) ) { group_id = node->document(); + } else { Node* root = node; while (root->parent()) { @@ -550,91 +706,38 @@ static void GCEpilogue() // Run through all objects with pending activity making their wrappers weak // again. - PeerableMap active_map = active_dom_object_map().impl(); - for (PeerableMap::iterator it = active_map.begin(), end = active_map.end(); + DOMObjectMap active_map = active_dom_object_map().impl(); + for (DOMObjectMap::iterator it = active_map.begin(), end = active_map.end(); it != end; ++it) { - Peerable* obj = it->first; + void* obj = it->first; v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>(it->second); + ASSERT(!wrapper.IsWeak()); V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(wrapper); - if (type == V8ClassIndex::XMLHTTPREQUEST) { - XMLHttpRequest* xhr = static_cast<XMLHttpRequest*>(obj); - if (xhr->hasPendingActivity()) { - ASSERT(!wrapper.IsWeak()); - wrapper.MakeWeak(xhr, &WeakActiveDOMObjectCallback); - } - } else if (type == V8ClassIndex::MESSAGEPORT) { - MessagePort* message_port = static_cast<MessagePort*>(obj); - if (message_port->hasPendingActivity()) { - ASSERT(!wrapper.IsWeak()); - wrapper.MakeWeak(message_port, &WeakActiveDOMObjectCallback); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: { \ + NAME* impl = static_cast<NAME*>(obj); \ + if (impl->hasPendingActivity()) \ + wrapper.MakeWeak(impl, &WeakActiveDOMObjectCallback); \ + break; \ } +ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + default: + ASSERT(false); +#undef MAKE_CASE } - ASSERT(wrapper.IsWeak()); } #ifndef NDEBUG // Check all survivals are weak. - PeerableMap peer_map = dom_object_map().impl(); - for (PeerableMap::iterator it = peer_map.begin(), end = peer_map.end(); - it != end; ++it) { - Peerable* obj = it->first; - USE_VAR(obj); - ASSERT(v8::Persistent<v8::Object>(it->second).IsWeak()); - } - - NodeMap node_map = dom_node_map().impl(); - for (NodeMap::iterator it = node_map.begin(), end = node_map.end(); - it != end; ++it) { - Node* node = it->first; - USE_VAR(node); - ASSERT(v8::Persistent<v8::Object>(it->second).IsWeak()); - } - + EnumerateDOMObjectMap(dom_object_map().impl()); + EnumerateDOMNodeMap(dom_node_map().impl()); + EnumerateDOMObjectMap(gc_protected_map()); EnumerateGlobalHandles(); - #undef USE_VAR #endif } -// A map from a peerable node to its JS wrapper, the wrapper -// is kept as a strong reference to survive GCs. -static PeerableMap& gc_protected_map() -{ - static PeerableMap static_gc_protected_map; - return static_gc_protected_map; -} - -// static -void V8Proxy::GCProtect(Peerable* dom_object) -{ - if (!dom_object) - return; - if (gc_protected_map().contains(dom_object)) - return; - if (!dom_object->peer()) - return; - - // Create a new (strong) persistent handle for the peer. - v8::Persistent<v8::Object> - wrapper(static_cast<v8::Object*>(dom_object->peer())); - - gc_protected_map().set(dom_object, *v8::Persistent<v8::Object>::New(wrapper)); -} - - -// static -void V8Proxy::GCUnprotect(Peerable* dom_object) -{ - if (!dom_object) - return; - if (!gc_protected_map().contains(dom_object)) - return; - - // Dispose the strong reference. - v8::Persistent<v8::Object> wrapper(gc_protected_map().take(dom_object)); - wrapper.Dispose(); -} - typedef HashMap<int, v8::FunctionTemplate*> FunctionTemplateMap; @@ -888,28 +991,46 @@ void V8Proxy::DestroyGlobal() } } -void V8Proxy::SetJSWrapperForDOMObject(Peerable* obj, v8::Persistent<v8::Object> wrapper) + +bool V8Proxy::DOMObjectHasJSWrapper(void* obj) { + return dom_object_map().contains(obj) || + active_dom_object_map().contains(obj); +} + + +// The caller must have increased obj's ref count. +void V8Proxy::SetJSWrapperForDOMObject(void* obj, v8::Persistent<v8::Object> wrapper) { ASSERT(MaybeDOMWrapper(wrapper)); #ifndef NDEBUG V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(wrapper); - ASSERT(type != V8ClassIndex::XMLHTTPREQUEST && - type != V8ClassIndex::MESSAGEPORT); + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: +ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + ASSERT(false); +#undef MAKE_CASE + } #endif dom_object_map().set(obj, wrapper); } -void V8Proxy::SetJSWrapperForActiveDOMObject(Peerable* obj, v8::Persistent<v8::Object> wrapper) +// The caller must have increased obj's ref count. +void V8Proxy::SetJSWrapperForActiveDOMObject(void* obj, v8::Persistent<v8::Object> wrapper) { ASSERT(MaybeDOMWrapper(wrapper)); #ifndef NDEBUG V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(wrapper); - ASSERT(type == V8ClassIndex::XMLHTTPREQUEST || - type == V8ClassIndex::MESSAGEPORT); + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break; +ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + default: ASSERT(false); +#undef MAKE_CASE + } #endif active_dom_object_map().set(obj, wrapper); } +// The caller must have increased node's ref count. void V8Proxy::SetJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper) { ASSERT(MaybeDOMWrapper(wrapper)); @@ -997,7 +1118,7 @@ PassRefPtr<V8EventListener> V8Proxy::FindOrCreateV8EventListener(v8::Local<v8::V // wrapper. So we can create a hidden reference from the JS wrapper to // to its JS function. // -// (peer) +// (map) // XHR <---------- JS_wrapper // | (hidden) : ^ // V V : (may reachable by closure) @@ -1328,8 +1449,10 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate( V8Custom::kHTMLDocumentInternalFieldCount); break; } - case V8ClassIndex::DOCUMENT: - case V8ClassIndex::SVGDOCUMENT: { +#if ENABLE(SVG) + case V8ClassIndex::SVGDOCUMENT: // fall through +#endif + case V8ClassIndex::DOCUMENT: { // We add an extra internal field to all Document wrappers for // storing a per document DOMImplementation wrapper. v8::Local<v8::ObjectTemplate> instance_template = @@ -1975,23 +2098,25 @@ void V8Proxy::initContextIfNeeded() // shadow global object. v8::Persistent<v8::FunctionTemplate> window_descriptor = GetTemplate(V8ClassIndex::DOMWINDOW); - v8::Local<v8::Object> window_peer = + v8::Local<v8::Object> js_window = SafeAllocation::NewInstance(window_descriptor->GetFunction()); - if (window_peer.IsEmpty()) + if (js_window.IsEmpty()) return; DOMWindow* window = m_frame->domWindow(); // Wrap the window. - SetDOMWrapper(window_peer, + SetDOMWrapper(js_window, V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); - // Setup the peer object for the DOM window. + + window->ref(); V8Proxy::SetJSWrapperForDOMObject(window, - v8::Persistent<v8::Object>::New(window_peer)); + v8::Persistent<v8::Object>::New(js_window)); + // Insert the window instance as the prototype of the shadow object. v8::Handle<v8::Object> v8_global = context->Global(); - v8_global->Set(v8::String::New("__proto__"), window_peer); + v8_global->Set(v8::String::New("__proto__"), js_window); SetSecurityToken(); @@ -2105,14 +2230,12 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, void ASSERT(type != V8ClassIndex::EVENTTARGET); ASSERT(type != V8ClassIndex::EVENT); -#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: - + bool is_active_dom_object = false; switch (type) { - NODE_WRAPPER_TYPES(MAKE_CASE) - HTMLELEMENT_TYPES(MAKE_CASE) +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: + DOM_NODE_TYPES(MAKE_CASE) #if ENABLE(SVG) - SVGNODE_WRAPPER_TYPES(MAKE_CASE) - SVGELEMENT_TYPES(MAKE_CASE) + SVG_NODE_TYPES(MAKE_CASE) #endif return NodeToV8Object(static_cast<Node*>(imp)); case V8ClassIndex::CSSVALUE: @@ -2123,15 +2246,16 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, void return StyleSheetToV8Object(static_cast<StyleSheet*>(imp)); case V8ClassIndex::DOMWINDOW: return WindowToV8Object(static_cast<DOMWindow*>(imp)); - case V8ClassIndex::XMLHTTPREQUEST: - case V8ClassIndex::MESSAGEPORT: - return ActiveDOMObjectToV8Object(type, static_cast<Peerable*>(imp)); #if ENABLE(SVG) - SVGNONNODE_WRAPPER_TYPES(MAKE_CASE) + SVG_NONNODE_TYPES(MAKE_CASE) if (type == V8ClassIndex::SVGELEMENTINSTANCE) return SVGElementInstanceToV8Object(static_cast<SVGElementInstance*>(imp)); - return SVGObjectWithContextToV8Object(static_cast<Peerable*>(imp), type); + return SVGObjectWithContextToV8Object(type, imp); #endif + + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + is_active_dom_object = true; + break; default: break; } @@ -2141,13 +2265,27 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, void if (!imp) return v8::Null(); // Non DOM node - Peerable* obj = static_cast<Peerable*>(imp); - v8::Persistent<v8::Object> result = dom_object_map().get(obj); + v8::Persistent<v8::Object> result = is_active_dom_object ? + active_dom_object_map().get(imp) : + dom_object_map().get(imp); if (result.IsEmpty()) { v8::Local<v8::Object> v8obj = InstantiateV8Object(type, type, imp); if (!v8obj.IsEmpty()) { + // Go through big switch statement, it has some duplications + // that were handled by code above (such as CSSVALUE, CSSRULE, etc). + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(imp)->ref(); break; + DOM_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT(false); + } result = v8::Persistent<v8::Object>::New(v8obj); - SetJSWrapperForDOMObject(obj, result); + if (is_active_dom_object) + SetJSWrapperForActiveDOMObject(imp, result); + else + SetJSWrapperForDOMObject(imp, result); // Special case for Location and Navigator. Both Safari and FF let // Location and Navigator JS wrappers survive GC. To mimic their @@ -2208,11 +2346,9 @@ void* V8Proxy::ToNativeObjectImpl(V8ClassIndex::V8WrapperType type, switch (type) { #define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: - NODE_WRAPPER_TYPES(MAKE_CASE) - HTMLELEMENT_TYPES(MAKE_CASE) + DOM_NODE_TYPES(MAKE_CASE) #if ENABLE(SVG) - SVGNODE_WRAPPER_TYPES(MAKE_CASE) - SVGELEMENT_TYPES(MAKE_CASE) + SVG_NODE_TYPES(MAKE_CASE) #endif ASSERT(false); return NULL; @@ -2227,7 +2363,7 @@ void* V8Proxy::ToNativeObjectImpl(V8ClassIndex::V8WrapperType type, } #undef MAKE_CASE - return DOMWrapperToNative<Peerable>(object); + return DOMWrapperToNative<void>(object); } v8::Handle<v8::Object> V8Proxy::LookupDOMWrapper( @@ -2257,7 +2393,7 @@ PassRefPtr<NodeFilter> V8Proxy::ToNativeNodeFilter(v8::Handle<v8::Value> filter) // NodeFilter is passed to NodeIterator that has a ref counted pointer // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition. // In NodeFilterCondition, filter object is persisted in its constructor, - // and disposed in its destructor. No need to use peer field in this case. + // and disposed in its destructor. if (!filter->IsFunction()) return 0; @@ -2352,7 +2488,7 @@ bool V8Proxy::IsWrapperOfType(v8::Handle<v8::Value> value, ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); v8::Handle<v8::Value> type = - obj->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + obj->GetInternalField(V8Custom::kDOMWrapperTypeIndex); ASSERT(type->IsInt32()); ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); @@ -2592,9 +2728,9 @@ v8::Handle<v8::Value> V8Proxy::EventToV8Object(Event* event) if (!event) return v8::Null(); - v8::Handle<v8::Object> peer = dom_object_map().get(event); - if (!peer.IsEmpty()) - return peer; + v8::Handle<v8::Object> wrapper = dom_object_map().get(event); + if (!wrapper.IsEmpty()) + return wrapper; V8ClassIndex::V8WrapperType type = V8ClassIndex::EVENT; @@ -2630,7 +2766,6 @@ v8::Handle<v8::Value> V8Proxy::EventToV8Object(Event* event) type = V8ClassIndex::WEBKITTRANSITIONEVENT; - // Set the peer object for future access. v8::Handle<v8::Object> result = InstantiateV8Object(type, V8ClassIndex::EVENT, event); if (result.IsEmpty()) { @@ -2640,6 +2775,7 @@ v8::Handle<v8::Value> V8Proxy::EventToV8Object(Event* event) return v8::Null(); } + event->ref(); // fast ref SetJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result)); return result; @@ -2651,9 +2787,9 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) { if (!node) return v8::Null(); - v8::Handle<v8::Object> peer = dom_node_map().get(node); - if (!peer.IsEmpty()) - return peer; + v8::Handle<v8::Object> wrapper = dom_node_map().get(node); + if (!wrapper.IsEmpty()) + return wrapper; bool is_document = false; // document type node has special handling V8ClassIndex::V8WrapperType type; @@ -2728,8 +2864,6 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) context->Enter(); } - // Set the peer object for future access. - // InstantiateV8Object automatically casts node to Peerable*. v8::Local<v8::Object> result = InstantiateV8Object(type, V8ClassIndex::NODE, node); @@ -2746,7 +2880,8 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) return result; } - dom_node_map().set(node, v8::Persistent<v8::Object>::New(result)); + node->ref(); + SetJSWrapperForDOMNode(node, v8::Persistent<v8::Object>::New(result)); if (is_document) { Document* doc = static_cast<Document*>(node); @@ -2793,24 +2928,24 @@ v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target) // XMLHttpRequest is created within its JS counterpart. XMLHttpRequest* xhr = target->toXMLHttpRequest(); if (xhr) { - v8::Handle<v8::Object> peer = active_dom_object_map().get(xhr); - ASSERT(!peer.IsEmpty()); - return peer; + v8::Handle<v8::Object> wrapper = active_dom_object_map().get(xhr); + ASSERT(!wrapper.IsEmpty()); + return wrapper; } // MessagePort is created within its JS counterpart MessagePort* port = target->toMessagePort(); if (port) { - v8::Handle<v8::Object> peer = active_dom_object_map().get(port); - ASSERT(!peer.IsEmpty()); - return peer; + v8::Handle<v8::Object> wrapper = active_dom_object_map().get(port); + ASSERT(!wrapper.IsEmpty()); + return wrapper; } XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload(); if (upload) { - v8::Handle<v8::Object> peer = dom_object_map().get(upload); - ASSERT(!peer.IsEmpty()); - return peer; + v8::Handle<v8::Object> wrapper = dom_object_map().get(upload); + ASSERT(!wrapper.IsEmpty()); + return wrapper; } ASSERT(0); @@ -2850,9 +2985,9 @@ v8::Handle<v8::Value> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet) { if (!sheet) return v8::Null(); - v8::Handle<v8::Object> peer = dom_object_map().get(sheet); - if (!peer.IsEmpty()) - return peer; + v8::Handle<v8::Object> wrapper = dom_object_map().get(sheet); + if (!wrapper.IsEmpty()) + return wrapper; V8ClassIndex::V8WrapperType type = V8ClassIndex::STYLESHEET; if (sheet->isCSSStyleSheet()) @@ -2862,6 +2997,7 @@ v8::Handle<v8::Value> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet) InstantiateV8Object(type, V8ClassIndex::STYLESHEET, sheet); if (!result.IsEmpty()) { // Only update the DOM object map if the result is non-empty. + sheet->ref(); SetJSWrapperForDOMObject(sheet, v8::Persistent<v8::Object>::New(result)); } @@ -2881,9 +3017,9 @@ v8::Handle<v8::Value> V8Proxy::CSSValueToV8Object(CSSValue* value) { if (!value) return v8::Null(); - v8::Handle<v8::Object> peer = dom_object_map().get(value); - if (!peer.IsEmpty()) - return peer; + v8::Handle<v8::Object> wrapper = dom_object_map().get(value); + if (!wrapper.IsEmpty()) + return wrapper; V8ClassIndex::V8WrapperType type; @@ -2904,9 +3040,12 @@ v8::Handle<v8::Value> V8Proxy::CSSValueToV8Object(CSSValue* value) v8::Handle<v8::Object> result = InstantiateV8Object(type, V8ClassIndex::CSSVALUE, value); - if (!result.IsEmpty()) + if (!result.IsEmpty()) { // Only update the DOM object map if the result is non-empty. + value->ref(); SetJSWrapperForDOMObject(value, v8::Persistent<v8::Object>::New(result)); + } + return result; } @@ -2915,9 +3054,9 @@ v8::Handle<v8::Value> V8Proxy::CSSRuleToV8Object(CSSRule* rule) { if (!rule) return v8::Null(); - v8::Handle<v8::Object> peer = dom_object_map().get(rule); - if (!peer.IsEmpty()) - return peer; + v8::Handle<v8::Object> wrapper = dom_object_map().get(rule); + if (!wrapper.IsEmpty()) + return wrapper; V8ClassIndex::V8WrapperType type; @@ -2954,12 +3093,13 @@ v8::Handle<v8::Value> V8Proxy::CSSRuleToV8Object(CSSRule* rule) break; } - // Set the peer object for future access. v8::Handle<v8::Object> result = InstantiateV8Object(type, V8ClassIndex::CSSRULE, rule); - if (!result.IsEmpty()) + if (!result.IsEmpty()) { // Only update the DOM object map if the result is non-empty. + rule->ref(); SetJSWrapperForDOMObject(rule, v8::Persistent<v8::Object>::New(result)); + } return result; } @@ -2981,22 +3121,6 @@ v8::Handle<v8::Value> V8Proxy::WindowToV8Object(DOMWindow* window) return global; } -v8::Handle<v8::Value> V8Proxy::ActiveDOMObjectToV8Object( - V8ClassIndex::V8WrapperType type, Peerable* obj) -{ - v8::Handle<v8::Object> result = active_dom_object_map().get(obj); - if (!result.IsEmpty()) - return result; - - // Set the peer object for future access. - result = InstantiateV8Object(type, type, obj); - if (!result.IsEmpty()) - // Only update the DOM object map if the result is non-empty. - SetJSWrapperForActiveDOMObject(obj, - v8::Persistent<v8::Object>::New(result)); - return result; -} - void V8Proxy::BindJSObjectToWindow(Frame* frame, const char* name, int type, diff --git a/webkit/port/bindings/v8/v8_proxy.h b/webkit/port/bindings/v8/v8_proxy.h index c63dbf4..f2a2275 100644 --- a/webkit/port/bindings/v8/v8_proxy.h +++ b/webkit/port/bindings/v8/v8_proxy.h @@ -205,8 +205,8 @@ class V8Proxy { void RemoveObjectEventListener(V8ObjectEventListener* listener); // Protect/Unprotect JS wrappers of a DOM object. - static void GCProtect(Peerable* dom_object); - static void GCUnprotect(Peerable* dom_object); + static void GCProtect(void* dom_object); + static void GCUnprotect(void* dom_object); // Create a lazy event listener. PassRefPtr<EventListener> createInlineEventListener( @@ -312,8 +312,10 @@ class V8Proxy { template <class C> static C* DOMWrapperToNative(v8::Handle<v8::Value> object) { ASSERT(MaybeDOMWrapper(object)); - return ExtractCPointer<C>( - v8::Handle<v8::Object>::Cast(object)->GetInternalField(0)); + v8::Handle<v8::Value> ptr = + v8::Handle<v8::Object>::Cast(object)->GetInternalField( + V8Custom::kDOMWrapperObjectIndex); + return ExtractCPointer<C>(ptr); } // A help function extract a node type pointer from a DOM wrapper. @@ -377,8 +379,7 @@ class V8Proxy { // DOMImplementation is a singleton and it is handled in a special // way. A wrapper is generated per document and stored in an - // internal field of the document. When wrapping the - // DOMImplementation object, the peer field is not set. + // internal field of the document. static v8::Handle<v8::Value> DOMImplementationToV8Object( DOMImplementation* impl); @@ -391,10 +392,12 @@ class V8Proxy { template <int tag, typename T> static v8::Handle<v8::Value> ConstructDOMObject(const v8::Arguments& args); - // Set JS wrapper of a DOM object - static void SetJSWrapperForDOMObject(Peerable* obj, + // Checks whether a DOM object has a JS wrapper. + static bool DOMObjectHasJSWrapper(void* obj); + // Set JS wrapper of a DOM object, the caller in charge of increase ref. + static void SetJSWrapperForDOMObject(void* obj, v8::Persistent<v8::Object> wrapper); - static void SetJSWrapperForActiveDOMObject(Peerable* obj, + static void SetJSWrapperForActiveDOMObject(void* obj, v8::Persistent<v8::Object> wrapper); static void SetJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper); @@ -447,14 +450,12 @@ class V8Proxy { // Returns the JS wrapper of a window object, initializes the environment // of the window frame if needed. static v8::Handle<v8::Value> WindowToV8Object(DOMWindow* window); - static v8::Handle<v8::Value> ActiveDOMObjectToV8Object( - V8ClassIndex::V8WrapperType type, Peerable* obj); #if ENABLE(SVG) static v8::Handle<v8::Value> SVGElementInstanceToV8Object( SVGElementInstance* instance); static v8::Handle<v8::Value> SVGObjectWithContextToV8Object( - Peerable* object, V8ClassIndex::V8WrapperType type); + V8ClassIndex::V8WrapperType type, void* object); #endif // Set hidden references in a DOMWindow object of a frame. @@ -537,6 +538,7 @@ v8::Handle<v8::Value> V8Proxy::ConstructDOMObject(const v8::Arguments& args) { // SetDOMWrapper(), which effectively holds a reference to obj. RefPtr<T> obj = T::create(); V8Proxy::SetDOMWrapper(args.Holder(), tag, obj.get()); + obj->ref(); V8Proxy::SetJSWrapperForDOMObject( obj.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); |