summaryrefslogtreecommitdiffstats
path: root/webkit/port
diff options
context:
space:
mode:
authorfqian@google.com <fqian@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-04 01:14:38 +0000
committerfqian@google.com <fqian@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-04 01:14:38 +0000
commit2ecc3274a76dd709e2aaf74d385f57b499d843b5 (patch)
tree08f5e57ba44140fb4cb8ee8bb426904b0205b533 /webkit/port
parent3878d08262a721fd785844c56e3e7c0617647101 (diff)
downloadchromium_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.pm3
-rw-r--r--webkit/port/bindings/v8/ScriptController.cpp12
-rw-r--r--webkit/port/bindings/v8/V8SVGPODTypeWrapper.h4
-rw-r--r--webkit/port/bindings/v8/V8XMLHttpRequestCustom.cpp3
-rw-r--r--webkit/port/bindings/v8/v8_custom.cpp62
-rw-r--r--webkit/port/bindings/v8/v8_custom.h4
-rw-r--r--webkit/port/bindings/v8/v8_events.h2
-rw-r--r--webkit/port/bindings/v8/v8_index.h125
-rw-r--r--webkit/port/bindings/v8/v8_proxy.cpp682
-rw-r--r--webkit/port/bindings/v8/v8_proxy.h26
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();