Bug 21054: Construction of certain DOM objects is heavily regressed by r36675
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Sep 2008 11:53:40 +0000 (11:53 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Sep 2008 11:53:40 +0000 (11:53 +0000)
<https://bugs.webkit.org/show_bug.cgi?id=21054>

Reviewed by Maciej Stachowiak

This performance regression is actually just a symptom of a correctness
bug.  The constructor objects for a number of properties that have security
checks on access were returning new objects each time.  The most obvious
symptom of this bug is that window.Image != window.Image, etc.

The solution to this is to make sure we cache these constructors
in the same way as all the other DOM constructors.  To achieve this
without causing any refcount cycles it is necessary to replace the
refcounted document pointer in the Image, MessageChannel, Option,
XMLHttpRequest, and Audio constructor objects with a reference to
the document's JS wrapper.

Tests: fast/dom/constructors-cached-navigate.html
       fast/dom/constructors-cached.html

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

20 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/constructors-cached-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/constructors-cached-navigate-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/constructors-cached-navigate.html [new file with mode: 0644]
LayoutTests/fast/dom/constructors-cached.html [new file with mode: 0644]
LayoutTests/fast/dom/resources/constructors-cached-navigate.js [new file with mode: 0644]
LayoutTests/fast/dom/resources/constructors-cached.js [new file with mode: 0644]
WebCore/ChangeLog
WebCore/bindings/js/JSAudioConstructor.cpp
WebCore/bindings/js/JSAudioConstructor.h
WebCore/bindings/js/JSDOMWindowBase.cpp
WebCore/bindings/js/JSDOMWindowBase.h
WebCore/bindings/js/JSHTMLOptionElementConstructor.cpp
WebCore/bindings/js/JSHTMLOptionElementConstructor.h
WebCore/bindings/js/JSImageConstructor.cpp
WebCore/bindings/js/JSImageConstructor.h
WebCore/bindings/js/JSMessageChannelConstructor.cpp
WebCore/bindings/js/JSMessageChannelConstructor.h
WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp
WebCore/bindings/js/JSXMLHttpRequestConstructor.h

index a6f0b8f..6bfcdf6 100644 (file)
@@ -1,3 +1,22 @@
+2008-09-26  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Maciej Stachowiak.
+
+        Bug 21054: Construction of certain DOM objects is heavily regressed by r36675
+        <https://bugs.webkit.org/show_bug.cgi?id=21054>
+
+        Tests to ensure that we correctly only have single instances of the
+        special cased Image, MessageChannel, Option, XMLHttpRequest, and Audio
+        constructors.  We also test that we don't expose the cached objects
+        to subsequent documents as navigation occurs.
+
+        * fast/dom/constructors-cached-expected.txt: Added.
+        * fast/dom/constructors-cached-navigate-expected.txt: Added.
+        * fast/dom/constructors-cached-navigate.html: Added.
+        * fast/dom/constructors-cached.html: Added.
+        * fast/dom/resources/constructors-cached-navigate.js: Added.
+        * fast/dom/resources/constructors-cached.js: Added.
+
 2008-09-25  Feng Qian <feng@chromium.org>
 
         Test for: https://bugs.webkit.org/show_bug.cgi?id=21032
diff --git a/LayoutTests/fast/dom/constructors-cached-expected.txt b/LayoutTests/fast/dom/constructors-cached-expected.txt
new file mode 100644 (file)
index 0000000..9e9da1a
--- /dev/null
@@ -0,0 +1,19 @@
+This test ensures that objects with security restrictions are cached correctly
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Image is Image
+PASS Image.testProperty is "property set successfully"
+PASS MessageChannel is MessageChannel
+PASS MessageChannel.testProperty is "property set successfully"
+PASS Option is Option
+PASS Option.testProperty is "property set successfully"
+PASS XMLHttpRequest is XMLHttpRequest
+PASS XMLHttpRequest.testProperty is "property set successfully"
+PASS Audio is Audio
+PASS Audio.testProperty is "property set successfully"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/dom/constructors-cached-navigate-expected.txt b/LayoutTests/fast/dom/constructors-cached-navigate-expected.txt
new file mode 100644 (file)
index 0000000..27af114
--- /dev/null
@@ -0,0 +1,50 @@
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS testFrame.contentWindow.Image is testFrame.contentWindow.Image
+PASS testFrame.contentWindow.Image !== window.Image is true
+PASS testFrame.contentWindow.Image.testProperty is "property set successfully"
+PASS testFrame.contentWindow.MessageChannel is testFrame.contentWindow.MessageChannel
+PASS testFrame.contentWindow.MessageChannel !== window.MessageChannel is true
+PASS testFrame.contentWindow.MessageChannel.testProperty is "property set successfully"
+PASS testFrame.contentWindow.Option is testFrame.contentWindow.Option
+PASS testFrame.contentWindow.Option !== window.Option is true
+PASS testFrame.contentWindow.Option.testProperty is "property set successfully"
+PASS testFrame.contentWindow.XMLHttpRequest is testFrame.contentWindow.XMLHttpRequest
+PASS testFrame.contentWindow.XMLHttpRequest !== window.XMLHttpRequest is true
+PASS testFrame.contentWindow.XMLHttpRequest.testProperty is "property set successfully"
+PASS testFrame.contentWindow.Audio is testFrame.contentWindow.Audio
+PASS testFrame.contentWindow.Audio !== window.Audio is true
+PASS testFrame.contentWindow.Audio.testProperty is "property set successfully"
+PASS testFrame.contentWindow.Image is testFrame.contentWindow.Image
+PASS testFrame.contentWindow.Image !== window.Image is true
+PASS testFrame.contentWindow.Image !== storedConstructors.Image is true
+PASS storedConstructors.Image.testProperty is "property set successfully"
+PASS testFrame.contentWindow.Image.testProperty is undefined.
+PASS testFrame.contentWindow.Image.cachedOnOwnerDocument is true
+PASS testFrame.contentWindow.MessageChannel is testFrame.contentWindow.MessageChannel
+PASS testFrame.contentWindow.MessageChannel !== window.MessageChannel is true
+PASS testFrame.contentWindow.MessageChannel !== storedConstructors.MessageChannel is true
+PASS storedConstructors.MessageChannel.testProperty is "property set successfully"
+PASS testFrame.contentWindow.MessageChannel.testProperty is undefined.
+PASS testFrame.contentWindow.MessageChannel.cachedOnOwnerDocument is true
+PASS testFrame.contentWindow.Option is testFrame.contentWindow.Option
+PASS testFrame.contentWindow.Option !== window.Option is true
+PASS testFrame.contentWindow.Option !== storedConstructors.Option is true
+PASS storedConstructors.Option.testProperty is "property set successfully"
+PASS testFrame.contentWindow.Option.testProperty is undefined.
+PASS testFrame.contentWindow.Option.cachedOnOwnerDocument is true
+PASS testFrame.contentWindow.XMLHttpRequest is testFrame.contentWindow.XMLHttpRequest
+PASS testFrame.contentWindow.XMLHttpRequest !== window.XMLHttpRequest is true
+PASS testFrame.contentWindow.XMLHttpRequest !== storedConstructors.XMLHttpRequest is true
+PASS storedConstructors.XMLHttpRequest.testProperty is "property set successfully"
+PASS testFrame.contentWindow.XMLHttpRequest.testProperty is undefined.
+PASS testFrame.contentWindow.XMLHttpRequest.cachedOnOwnerDocument is true
+PASS testFrame.contentWindow.Audio is testFrame.contentWindow.Audio
+PASS testFrame.contentWindow.Audio !== window.Audio is true
+PASS testFrame.contentWindow.Audio !== storedConstructors.Audio is true
+PASS storedConstructors.Audio.testProperty is "property set successfully"
+PASS testFrame.contentWindow.Audio.testProperty is undefined.
+PASS testFrame.contentWindow.Audio.cachedOnOwnerDocument is true
+
diff --git a/LayoutTests/fast/dom/constructors-cached-navigate.html b/LayoutTests/fast/dom/constructors-cached-navigate.html
new file mode 100644 (file)
index 0000000..c4af69a
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<iframe id="testFrame"></iframe>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/constructors-cached-navigate.js"></script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/dom/constructors-cached.html b/LayoutTests/fast/dom/constructors-cached.html
new file mode 100644 (file)
index 0000000..a295ff9
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/constructors-cached.js"></script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/dom/resources/constructors-cached-navigate.js b/LayoutTests/fast/dom/resources/constructors-cached-navigate.js
new file mode 100644 (file)
index 0000000..0826bdd
--- /dev/null
@@ -0,0 +1,55 @@
+if (window.layoutTestController)
+    layoutTestController.waitUntilDone();
+
+var constructors = ["Image", "MessageChannel", "Option", "XMLHttpRequest", "Audio"];
+
+window.onload = function () {
+    testFrame = document.getElementById("testFrame");
+    storedConstructors = [];
+    // Identity checks
+    for (var i = 0; i < constructors.length; i++) {
+        var constructor = constructors[i];
+        try {
+            shouldBe("testFrame.contentWindow." + constructor, "testFrame.contentWindow."+constructor);
+            shouldBeTrue("testFrame.contentWindow." + constructor + " !== window." + constructor);
+            testFrame.contentWindow[constructor].testProperty = "property set successfully";
+            shouldBe("testFrame.contentWindow." + constructor + ".testProperty", '"property set successfully"');
+            storedConstructors[constructor] = testFrame.contentWindow[constructor];
+        } catch (e) {
+            testFailed("Testing " + constructor + " threw " + e);
+        }
+    }
+    testFrame.onload = function() {
+        if (window.GCController)
+            GCController.collect();
+
+        // Test properties after load
+        for (var i = 0; i < constructors.length; i++) {
+            var constructor = constructors[i];
+            try {
+                // Repeat the identity checks to be safe
+                shouldBe("testFrame.contentWindow." + constructor, "testFrame.contentWindow."+constructor);
+                shouldBeTrue("testFrame.contentWindow." + constructor + " !== window." + constructor);
+                
+                // Make sure that we haven't reused the constructors from the old document
+                shouldBeTrue("testFrame.contentWindow." + constructor + " !== storedConstructors." + constructor);
+                shouldBe("storedConstructors." + constructor + ".testProperty", '"property set successfully"');
+
+                // Make sure we haven't kept anything over from the original document
+                shouldBeUndefined("testFrame.contentWindow." + constructor + ".testProperty");
+                // Make sure we're getting the same constructor as the frame does internally
+                shouldBeTrue("testFrame.contentWindow." + constructor + ".cachedOnOwnerDocument");
+            } catch (e) {
+                testFailed("Testing " + constructor + " threw " + e);
+            }
+        }
+        
+        if (window.layoutTestController)
+            layoutTestController.notifyDone();
+    };
+    testFrame.src = 'data:text/html,<script>var constructors = ["Image", "MessageChannel", "Option", "XMLHttpRequest", "Audio"];'
+                  + 'for(var i = 0; i < constructors.length; i++) if(window[constructors[i]])'
+                  + 'window[constructors[i]].cachedOnOwnerDocument = true;</script>';
+}
+
+successfullyParsed = true;
diff --git a/LayoutTests/fast/dom/resources/constructors-cached.js b/LayoutTests/fast/dom/resources/constructors-cached.js
new file mode 100644 (file)
index 0000000..4f2c699
--- /dev/null
@@ -0,0 +1,20 @@
+description("This test ensures that objects with security restrictions are cached correctly");
+
+var constructors = ["Image", "MessageChannel", "Option", "XMLHttpRequest", "Audio"];
+
+for (var i = 0; i < constructors.length; i++) {
+    var constructor = constructors[i];
+    try {
+        // Test retrieving the object twice results in the same object
+        shouldBe(constructor, constructor);
+
+        // Be paranoid -- make sure that setting a property results in that property
+        // stays
+        this[constructor].testProperty = "property set successfully";
+        shouldBe(constructor + ".testProperty", '"property set successfully"');
+    } catch (e) {
+        testFailed("Testing " + constructor + " threw " + e);
+    }
+}
+
+successfullyParsed = true;
index ae1ae21..bbe950a 100644 (file)
@@ -1,3 +1,47 @@
+2008-09-26  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Maciej Stachowiak.
+
+        Bug 21054: Construction of certain DOM objects is heavily regressed by r36675
+        <https://bugs.webkit.org/show_bug.cgi?id=21054>
+
+        This performance regression is actually just a symptom of a correctness
+        bug.  The constructor objects for a number of properties that have security
+        checks on access were returning new objects each time.  The most obvious
+        symptom of this bug is that window.Image != window.Image, etc.
+
+        The solution to this is to make sure we cache these constructors
+        in the same way as all the other DOM constructors.  To achieve this
+        without causing any refcount cycles it is necessary to replace the
+        refcounted document pointer in the Image, MessageChannel, Option, 
+        XMLHttpRequest, and Audio constructor objects with a reference to 
+        the document's JS wrapper.
+
+        Tests: fast/dom/constructors-cached-navigate.html
+               fast/dom/constructors-cached.html
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSAudioConstructor.cpp:
+        (WebCore::JSAudioConstructor::mark):
+        * bindings/js/JSAudioConstructor.h:
+        (WebCore::JSAudioConstructor::document):
+        * bindings/js/JSDOMWindowBase.cpp:
+        (WebCore::getDOMConstructor):
+        (WebCore::JSDOMWindowBase::getValueProperty):
+        * bindings/js/JSDOMWindowBase.h:
+        * bindings/js/JSHTMLOptionElementConstructor.cpp:
+        (WebCore::JSHTMLOptionElementConstructor::mark):
+        * bindings/js/JSHTMLOptionElementConstructor.h:
+        (WebCore::JSHTMLOptionElementConstructor::document):
+        * bindings/js/JSImageConstructor.cpp:
+        (WebCore::JSImageConstructor::mark):
+        * bindings/js/JSImageConstructor.h:
+        (WebCore::JSImageConstructor::document):
+        * bindings/js/JSXMLHttpRequestConstructor.cpp:
+        (WebCore::JSXMLHttpRequestConstructor::mark):
+        * bindings/js/JSXMLHttpRequestConstructor.h:
+        (WebCore::JSXMLHttpRequestConstructor::document):
+
 2008-09-26  Simon Hausmann  <hausmann@webkit.org>
 
         Unreviewed one-liner build fix for the Qt/Windows build.
index 157b19c..2b834d1 100644 (file)
@@ -42,7 +42,7 @@ const ClassInfo JSAudioConstructor::s_info = { "AudioConstructor", 0, 0, 0 };
 
 JSAudioConstructor::JSAudioConstructor(ExecState* exec, Document* document)
     : DOMObject(JSAudioConstructor::createStructureID(exec->lexicalGlobalObject()->objectPrototype()))
-    , m_document(document)
+    , m_document(static_cast<JSDocument*>(toJS(exec, document)))
 {
     putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly|DontDelete|DontEnum);
 }
@@ -65,6 +65,13 @@ ConstructType JSAudioConstructor::getConstructData(ConstructData& constructData)
     return ConstructTypeHost;
 }
 
+void JSAudioConstructor::mark()
+{
+    DOMObject::mark();
+    if (!m_document->marked())
+        m_document->mark();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(VIDEO)
index 014be71..038b8a2 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(VIDEO)
 
 #include "JSDOMBinding.h"
+#include "JSDocument.h"
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
@@ -37,16 +38,17 @@ namespace WebCore {
     public:
         JSAudioConstructor(JSC::ExecState*, Document*);
 
-        Document* document() const { return m_document.get(); }
+        Document* document() const { return m_document->impl(); }
 
         static const JSC::ClassInfo s_info;
 
+        virtual void mark();
     private:
         virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
 
         virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
 
-        RefPtr<Document> m_document;
+        JSDocument* m_document;
     };
 
 } // namespace WebCore
index b6ca22d..0003e82 100644 (file)
@@ -433,6 +433,16 @@ static JSValue* showModalDialog(ExecState* exec, Frame* frame, const String& url
     return returnValue ? returnValue : jsUndefined();
 }
 
+template<class ConstructorClass> static JSC::JSObject* getDOMConstructor(JSC::ExecState* exec, const JSDOMWindowBase* window)
+{
+    if (JSC::JSObject* constructor = window->constructors().get(&ConstructorClass::s_info))
+        return constructor;
+    JSC::JSObject* constructor = new (exec) ConstructorClass(exec, window->impl()->document());
+    ASSERT(!window->constructors().contains(&ConstructorClass::s_info));
+    window->constructors().set(&ConstructorClass::s_info, constructor);
+    return constructor;
+}
+
 JSValue *JSDOMWindowBase::getValueProperty(ExecState *exec, int token) const
 {
     ASSERT(impl()->frame());
@@ -449,28 +459,26 @@ JSValue *JSDOMWindowBase::getValueProperty(ExecState *exec, int token) const
     case Image:
         if (!allowsAccessFrom(exec))
             return jsUndefined();
-        // FIXME: this property (and the few below) probably shouldn't create a new object every
-        // time
-        return new (exec) JSImageConstructor(exec, impl()->frame()->document());
+        return getDOMConstructor<JSImageConstructor>(exec, this);
     case MessageChannel:
         if (!allowsAccessFrom(exec))
             return jsUndefined();
-        return new (exec) JSMessageChannelConstructor(exec, impl()->frame()->document());
+        return getDOMConstructor<JSMessageChannelConstructor>(exec, this);
     case Option:
         if (!allowsAccessFrom(exec))
             return jsUndefined();
-        return new (exec) JSHTMLOptionElementConstructor(exec, impl()->frame()->document());
+        return getDOMConstructor<JSHTMLOptionElementConstructor>(exec, this);
     case XMLHttpRequest:
         if (!allowsAccessFrom(exec))
             return jsUndefined();
-        return new (exec) JSXMLHttpRequestConstructor(exec, impl()->frame()->document());
+        return getDOMConstructor<JSXMLHttpRequestConstructor>(exec, this);
     case Audio:
 #if ENABLE(VIDEO)
         if (!allowsAccessFrom(exec))
             return jsUndefined();
         if (!MediaPlayer::isAvailable())
             return jsUndefined();
-        return new (exec) JSAudioConstructor(exec, impl()->frame()->document());
+        return getDOMConstructor<JSAudioConstructor>(exec, this);
 #else
         return jsUndefined();
 #endif
@@ -478,7 +486,7 @@ JSValue *JSDOMWindowBase::getValueProperty(ExecState *exec, int token) const
 #if ENABLE(XSLT)
         if (!allowsAccessFrom(exec))
             return jsUndefined();
-        return new (exec) JSXSLTProcessorConstructor(exec);
+        return getDOMConstructor<JSXSLTProcessorConstructor>(exec);
 #else
         return jsUndefined();
 #endif
index 708a6bf..c7564d3 100644 (file)
@@ -129,7 +129,7 @@ namespace WebCore {
         void clearAllTimeouts();
 
         JSDOMStructureMap& structures() { return d()->structures; }
-        JSDOMConstructorMap& constructors() { return d()->constructors; }
+        JSDOMConstructorMap& constructors() const { return d()->constructors; }
 
         enum {
             // Attributes
index 132a253..d00f923 100644 (file)
@@ -35,7 +35,7 @@ const ClassInfo JSHTMLOptionElementConstructor::s_info = { "OptionConstructor",
 
 JSHTMLOptionElementConstructor::JSHTMLOptionElementConstructor(ExecState* exec, Document* document)
     : DOMObject(JSHTMLOptionElementConstructor::createStructureID(exec->lexicalGlobalObject()->objectPrototype()))
-    , m_document(document)
+    , m_document(static_cast<JSDocument*>(toJS(exec, document)))
 {
     putDirect(exec->propertyNames().length, jsNumber(exec, 4), ReadOnly|DontDelete|DontEnum);
 }
@@ -75,4 +75,11 @@ ConstructType JSHTMLOptionElementConstructor::getConstructData(ConstructData& co
     return ConstructTypeHost;
 }
 
+void JSHTMLOptionElementConstructor::mark()
+{
+    DOMObject::mark();
+    if (!m_document->marked())
+        m_document->mark();
+}
+
 } // namespace WebCore
index 0d0539e..27b7916 100644 (file)
@@ -21,6 +21,7 @@
 #define JSHTMLOptionElementConstructor_h
 
 #include "JSDOMBinding.h"
+#include "JSDocument.h"
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
@@ -28,15 +29,16 @@ namespace WebCore {
     class JSHTMLOptionElementConstructor : public DOMObject {
     public:
         JSHTMLOptionElementConstructor(JSC::ExecState*, Document*);
-        Document* document() const { return m_document.get(); }
+        Document* document() const { return m_document->impl(); }
 
         static const JSC::ClassInfo s_info;
-
+        
+        virtual void mark();
     private:
         virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
         virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
 
-        RefPtr<Document> m_document;
+        JSDocument* m_document;
     };
 
 } // namespace WebCore
index cf9e588..7057060 100644 (file)
@@ -34,7 +34,7 @@ const ClassInfo JSImageConstructor::s_info = { "ImageConstructor", 0, 0, 0 };
 
 JSImageConstructor::JSImageConstructor(ExecState* exec, Document* document)
     : DOMObject(JSImageConstructor::createStructureID(exec->lexicalGlobalObject()->objectPrototype()))
-    , m_document(document)
+    , m_document(static_cast<JSDocument*>(toJS(exec, document)))
 {
 }
 
@@ -74,4 +74,11 @@ ConstructType JSImageConstructor::getConstructData(ConstructData& constructData)
     return ConstructTypeHost;
 }
 
+void JSImageConstructor::mark()
+{
+    DOMObject::mark();
+    if (!m_document->marked())
+        m_document->mark();
+}
+
 } // namespace WebCore
index f8df7d9..7bbd939 100644 (file)
@@ -21,6 +21,7 @@
 #define JSImageConstructor_h
 
 #include "JSDOMBinding.h"
+#include "JSDocument.h"
 
 namespace WebCore {
 
@@ -29,15 +30,16 @@ namespace WebCore {
     class JSImageConstructor : public DOMObject {
     public:
         JSImageConstructor(JSC::ExecState*, Document*);
-        Document* document() const { return m_document.get(); }
+        Document* document() const { return m_document->impl(); }
 
         static const JSC::ClassInfo s_info;
-
+        
+        virtual void mark();
     private:
         virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
         virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
 
-        RefPtr<Document> m_document;
+        JSDocument* m_document;
     };
 
 } // namespace WebCore
index 8b61dc4..1a87a0a 100644 (file)
@@ -38,7 +38,7 @@ const ClassInfo JSMessageChannelConstructor::s_info = { "MessageChannelConstruct
 
 JSMessageChannelConstructor::JSMessageChannelConstructor(ExecState* exec, Document* document)
     : DOMObject(JSMessageChannelConstructor::createStructureID(exec->lexicalGlobalObject()->objectPrototype()))
-    , m_document(document)
+    , m_document(static_cast<JSDocument*>(toJS(exec, document)))
 {
     putDirect(exec->propertyNames().prototype, JSMessageChannelPrototype::self(exec), None);
 }
@@ -55,7 +55,14 @@ ConstructType JSMessageChannelConstructor::getConstructData(ConstructData& const
 
 JSObject* JSMessageChannelConstructor::construct(ExecState* exec, JSObject* constructor, const ArgList&)
 {
-    return static_cast<JSObject*>(toJS(exec, MessageChannel::create(static_cast<JSMessageChannelConstructor*>(constructor)->m_document.get())));
+    return static_cast<JSObject*>(toJS(exec, MessageChannel::create(static_cast<JSMessageChannelConstructor*>(constructor)->document())));
+}
+
+void JSMessageChannelConstructor::mark()
+{
+    DOMObject::mark();
+    if (!m_document->marked())
+        m_document->mark();
 }
 
 } // namespace WebCore
index 5c15dbd..281c454 100644 (file)
@@ -27,6 +27,7 @@
 #define JSMessageChannelConstructor_h
 
 #include "JSDOMBinding.h"
+#include "JSDocument.h"
 
 namespace WebCore {
 
@@ -39,12 +40,15 @@ namespace WebCore {
         virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
         static const JSC::ClassInfo s_info;
 
+        Document* document() const { return m_document->impl(); }
+
         virtual bool implementsHasInstance() const { return true; }
         static JSC::JSObject* construct(JSC::ExecState*, JSC::JSObject*, const JSC::ArgList&);
         virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
 
+        virtual void mark();
     private:
-        RefPtr<Document> m_document;
+        JSDocument* m_document;
     };
 
 } // namespace WebCore
index c0a8e58..0180c1c 100644 (file)
@@ -34,7 +34,7 @@ const ClassInfo JSXMLHttpRequestConstructor::s_info = { "XMLHttpRequestConstruct
 
 JSXMLHttpRequestConstructor::JSXMLHttpRequestConstructor(ExecState* exec, Document* document)
     : DOMObject(JSXMLHttpRequestConstructor::createStructureID(exec->lexicalGlobalObject()->objectPrototype()))
-    , m_document(document)
+    , m_document(static_cast<JSDocument*>(toJS(exec, document)))
 {
     putDirect(exec->propertyNames().prototype, JSXMLHttpRequestPrototype::self(exec), None);
 }
@@ -51,4 +51,11 @@ ConstructType JSXMLHttpRequestConstructor::getConstructData(ConstructData& const
     return ConstructTypeHost;
 }
 
+void JSXMLHttpRequestConstructor::mark()
+{
+    DOMObject::mark();
+    if (!m_document->marked())
+        m_document->mark();
+}
+
 } // namespace WebCore
index efd2124..91c8cc9 100644 (file)
@@ -21,6 +21,7 @@
 #define JSXMLHttpRequestConstructor_h
 
 #include "JSDOMBinding.h"
+#include "JSDocument.h"
 
 namespace WebCore {
 
@@ -29,14 +30,15 @@ class Document;
 class JSXMLHttpRequestConstructor : public DOMObject {
 public:
     JSXMLHttpRequestConstructor(JSC::ExecState*, Document*);
-    Document* document() const { return m_document.get(); }
+    Document* document() const { return m_document->impl(); }
     static const JSC::ClassInfo s_info;
 
+    virtual void mark();
 private:
     virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
     virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
 
-    RefPtr<Document> m_document;
+    JSDocument* m_document;
 };
 
 } // namespace WebCore