summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfqian@google.com <fqian@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-10 04:09:48 +0000
committerfqian@google.com <fqian@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-10 04:09:48 +0000
commit564eee25d576db623bd6b648b28b9b649e2a1b8b (patch)
treec80ce94a65a351febd62d23c9a63fe1d0d0ae128
parentefecec54fc5177976a766d94b4e8be2e444078c1 (diff)
downloadchromium_src-564eee25d576db623bd6b648b28b9b649e2a1b8b.zip
chromium_src-564eee25d576db623bd6b648b28b9b649e2a1b8b.tar.gz
chromium_src-564eee25d576db623bd6b648b28b9b649e2a1b8b.tar.bz2
Patch for bug 1994:
Make sure that customized properties set on window.location and window.navigator survive GC. Matches Safari and Firefox's behaviors. Review URL: http://codereview.chromium.org/1884 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1973 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--webkit/data/layout_tests/chrome/fast/dom/Window/customized-property-survives-gc-expected.txt12
-rw-r--r--webkit/data/layout_tests/chrome/fast/dom/Window/customized-property-survives-gc.html50
-rw-r--r--webkit/port/bindings/v8/v8_custom.h21
-rw-r--r--webkit/port/bindings/v8/v8_proxy.cpp40
-rw-r--r--webkit/port/bindings/v8/v8_proxy.h5
-rw-r--r--webkit/port/page/Navigator.h2
6 files changed, 121 insertions, 9 deletions
diff --git a/webkit/data/layout_tests/chrome/fast/dom/Window/customized-property-survives-gc-expected.txt b/webkit/data/layout_tests/chrome/fast/dom/Window/customized-property-survives-gc-expected.txt
new file mode 100644
index 0000000..7eef580
--- /dev/null
+++ b/webkit/data/layout_tests/chrome/fast/dom/Window/customized-property-survives-gc-expected.txt
@@ -0,0 +1,12 @@
+This tests that customized properties on window.location and window.navigator won't get lost after a GC.
+TEST running.
+screen.myProp did not survive GC.
+history.myProp did not survive GC.
+locationbar.myProp did not survive GC.
+menubar.myProp did not survive GC.
+personalbar.myProp did not survive GC.
+scrollbars.myProp did not survive GC.
+statusbar.myProp did not survive GC.
+toolbar.myProp did not survive GC.
+location.myProp survived GC.
+navigator.myProp survived GC.
diff --git a/webkit/data/layout_tests/chrome/fast/dom/Window/customized-property-survives-gc.html b/webkit/data/layout_tests/chrome/fast/dom/Window/customized-property-survives-gc.html
new file mode 100644
index 0000000..5dc2d1f
--- /dev/null
+++ b/webkit/data/layout_tests/chrome/fast/dom/Window/customized-property-survives-gc.html
@@ -0,0 +1,50 @@
+<html>
+<script>
+if (window.layoutTestController)
+ layoutTestController.dumpAsText();
+
+function CollectGarbage() {
+ if (window.gc) {
+ // Chrome code
+ window.gc();
+ } else {
+ // Safari hack
+ for (var i = 0; i < 50000; i++)
+ new Object();
+ }
+}
+
+
+function check(name) {
+ if (!window[name]) return;
+
+ window[name].myProp = 10;
+ CollectGarbage();
+ var r = document.getElementById("result");
+ if (window[name].myProp) {
+ r.innerHTML += name + ".myProp survived GC.<br>";
+ } else {
+ r.innerHTML += name + ".myProp did not survive GC.<br>";
+ }
+}
+
+function runTest() {
+ check("screen");
+ check("history");
+ check("locationbar");
+ check("menubar");
+ check("personalbar");
+ check("scrollbars");
+ check("statusbar");
+ check("toolbar");
+ check("location");
+ check("navigator");
+}
+</script>
+
+<body onload="runTest()">
+This tests that customized properties on window.location and window.navigator
+won't get lost after a GC.
+<div id="result">TEST running.<br></div>
+</body>
+</html>
diff --git a/webkit/port/bindings/v8/v8_custom.h b/webkit/port/bindings/v8/v8_custom.h
index b22854f..d501362 100644
--- a/webkit/port/bindings/v8/v8_custom.h
+++ b/webkit/port/bindings/v8/v8_custom.h
@@ -22,26 +22,31 @@ class V8Custom {
// Constants.
static const int kDOMWrapperObjectIndex = 0;
static const int kDOMWrapperTypeIndex = 1;
- static const int kDefaultWrapperInternalFieldCount =
- kDOMWrapperTypeIndex + 1;
+ static const int kDefaultWrapperInternalFieldCount = 2;
- static const int kDocumentMinimumInternalFieldCount =
- kDefaultWrapperInternalFieldCount + 1;
static const int kDocumentImplementationIndex =
kDefaultWrapperInternalFieldCount + 0;
+ static const int kDocumentMinimumInternalFieldCount =
+ kDefaultWrapperInternalFieldCount + 1;
- static const int kHTMLDocumentInternalFieldCount =
- kDocumentMinimumInternalFieldCount + 2;
static const int kHTMLDocumentMarkerIndex =
kDocumentMinimumInternalFieldCount + 0;
static const int kHTMLDocumentShadowIndex =
kDocumentMinimumInternalFieldCount + 1;
+ static const int kHTMLDocumentInternalFieldCount =
+ kDocumentMinimumInternalFieldCount + 2;
- static const int kXMLHttpRequestInternalFieldCount =
- kDefaultWrapperInternalFieldCount + 1;
static const int kXMLHttpRequestCacheIndex =
kDefaultWrapperInternalFieldCount + 0;
+ static const int kXMLHttpRequestInternalFieldCount =
+ kDefaultWrapperInternalFieldCount + 1;
+ static const int kDOMWindowLocationIndex =
+ kDefaultWrapperInternalFieldCount + 0;
+ static const int kDOMWindowNavigatorIndex =
+ kDefaultWrapperInternalFieldCount + 1;
+ static const int kDOMWindowInternalFieldCount =
+ kDefaultWrapperInternalFieldCount + 2;
#define DECLARE_PROPERTY_ACCESSOR_GETTER(NAME) \
static v8::Handle<v8::Value> v8##NAME##AccessorGetter(\
diff --git a/webkit/port/bindings/v8/v8_proxy.cpp b/webkit/port/bindings/v8/v8_proxy.cpp
index d9152ed..184063e 100644
--- a/webkit/port/bindings/v8/v8_proxy.cpp
+++ b/webkit/port/bindings/v8/v8_proxy.cpp
@@ -55,6 +55,7 @@
#include "HTMLOptionsCollection.h"
#include "Page.h"
#include "DOMWindow.h"
+#include "Location.h"
#include "Navigator.h" // for MimeTypeArray
#include "V8DOMWindow.h"
#include "V8HTMLElement.h"
@@ -1245,7 +1246,12 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate(
default_signature),
v8::None);
desc->SetHiddenPrototype(true);
-
+
+ // Reserve spaces for references to location and navigator objects.
+ v8::Local<v8::ObjectTemplate> instance_template =
+ desc->InstanceTemplate();
+ instance_template->SetInternalFieldCount(
+ V8Custom::kDOMWindowInternalFieldCount);
break;
}
case V8ClassIndex::LOCATION: {
@@ -1834,12 +1840,44 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type,
if (!v8obj.IsEmpty()) {
result = v8::Persistent<v8::Object>::New(v8obj);
dom_object_map().set(obj, result);
+
+ // Special case for Location and Navigator. Both Safari and FF let
+ // Location and Navigator JS wrappers survive GC. To mimic their
+ // behaviors, V8 creates hidden references from the DOMWindow to
+ // location and navigator objects. These references get cleared
+ // when the DOMWindow is reused by a new page.
+ if (type == V8ClassIndex::LOCATION) {
+ SetHiddenWindowReference(static_cast<Location*>(imp)->frame(),
+ V8Custom::kDOMWindowLocationIndex, result);
+ } else if (type == V8ClassIndex::NAVIGATOR) {
+ SetHiddenWindowReference(static_cast<Navigator*>(imp)->frame(),
+ V8Custom::kDOMWindowNavigatorIndex, result);
+ }
}
}
return result;
}
+void V8Proxy::SetHiddenWindowReference(Frame* frame,
+ const int internal_index,
+ v8::Handle<v8::Object> jsobj) {
+ // Get DOMWindow
+ if (!frame) return; // Object might be detached from window
+ v8::Handle<v8::Context> context = GetContext(frame);
+ if (context.IsEmpty()) return;
+
+ ASSERT(internal_index < V8Custom::kDOMWindowInternalFieldCount);
+
+ v8::Handle<v8::Object> global = context->Global();
+ ASSERT(!global.IsEmpty());
+ // Look for real DOM wrapper.
+ global = LookupDOMWrapper(V8ClassIndex::DOMWINDOW, global);
+ ASSERT(global->GetInternalField(internal_index)->IsUndefined());
+ global->SetInternalField(internal_index, jsobj);
+}
+
+
V8ClassIndex::V8WrapperType V8Proxy::GetDOMWrapperType(
v8::Handle<v8::Object> object) {
if (!MaybeDOMWrapper(object)) {
diff --git a/webkit/port/bindings/v8/v8_proxy.h b/webkit/port/bindings/v8/v8_proxy.h
index 23d1f95..e426cc7 100644
--- a/webkit/port/bindings/v8/v8_proxy.h
+++ b/webkit/port/bindings/v8/v8_proxy.h
@@ -437,6 +437,11 @@ class V8Proxy {
Peerable* object, V8ClassIndex::V8WrapperType type);
#endif
+ // Set hidden references in a DOMWindow object of a frame.
+ static void SetHiddenWindowReference(Frame* frame,
+ const int internal_index,
+ v8::Handle<v8::Object> jsobj);
+
static V8ClassIndex::V8WrapperType GetHTMLElementType(HTMLElement* elm);
static v8::Local<v8::Object> InstantiateV8Object(
diff --git a/webkit/port/page/Navigator.h b/webkit/port/page/Navigator.h
index 90660a7..983daea 100644
--- a/webkit/port/page/Navigator.h
+++ b/webkit/port/page/Navigator.h
@@ -243,6 +243,8 @@ class Navigator : public RefCounted<Navigator> {
return m_frame->settings()->isJavaEnabled();
}
+ Frame* frame() { return m_frame; }
+
void disconnectFrame() { m_frame = NULL; }
private: