diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index 2dfca7dce313770046bb80eb1c26d3262732f4bb..17670007555c57c78ff4b7f340998ff4ed1e91e1 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,13 @@ +2007-07-11 Sam Weinig + + Reviewed by Maciej. + + Test for + Calling window.closed on a closed window causes Safari to crash + + * fast/dom/Window/window-closed-crash-expected.txt: Added. + * fast/dom/Window/window-closed-crash.html: Added. + 2007-07-12 Mitz Pettel Reviewed by Mark Rowe. diff --git a/LayoutTests/fast/dom/Window/window-closed-crash-expected.txt b/LayoutTests/fast/dom/Window/window-closed-crash-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..a7afe4661af35c700bd3e48eed17cf6b3d5ea278 --- /dev/null +++ b/LayoutTests/fast/dom/Window/window-closed-crash-expected.txt @@ -0,0 +1,4 @@ +This tests that window.closed on a closed window, or window without a frame, does not crash the browser. See rdar://problem/5329841 + +Passed! + diff --git a/LayoutTests/fast/dom/Window/window-closed-crash.html b/LayoutTests/fast/dom/Window/window-closed-crash.html new file mode 100644 index 0000000000000000000000000000000000000000..984949816a449ad3fae72a14fec2f690eec132cd --- /dev/null +++ b/LayoutTests/fast/dom/Window/window-closed-crash.html @@ -0,0 +1,26 @@ + + + + + + +

This tests that window.closed on a closed window, or window without a frame, does not crash the browser. See rdar://problem/5329841

+

+    
+    
+
+
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 291de1f40394b2d0f249186e507d07de452aad74..71b950184d6ba065d1d5daebf2434fe5c38e640f 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,58 @@
+2007-07-11  Sam Weinig  
+
+        Reviewed by Maciej.
+
+        Patch for 
+        Calling window.closed on a closed window causes Safari to crash
+
+        - Replaces the Frame member variable in KJS::Window for more appropriate DOMWindow
+        - Adds additional new null checks as necessary
+        - Removes bogus toBoolean method
+        - Removes unused scheduleClose method
+
+        Test: fast/dom/Window/window-closed-crash.html
+
+        * bindings/js/JSCustomXPathNSResolver.cpp:
+        (WebCore::JSCustomXPathNSResolver::create):
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::customGetOwnPropertySlot):
+        (WebCore::JSDOMWindow::customPut):
+        * bindings/js/JSXMLHttpRequest.cpp:
+        (KJS::JSXMLHttpRequestPrototypeFunction::callAsFunction):
+        * bindings/js/kjs_events.cpp:
+        (WebCore::JSAbstractEventListener::handleEvent):
+        (WebCore::JSLazyEventListener::parseCode):
+        * bindings/js/kjs_window.cpp:
+        (KJS::Window::Window):
+        (KJS::Window::impl):
+        (KJS::Window::interpreter):
+        (KJS::Window::location):
+        (KJS::Window::find):
+        (KJS::allowPopUp):
+        (KJS::createWindow):
+        (KJS::canShowModalDialog):
+        (KJS::canShowModalDialogNow):
+        (KJS::showModalDialog):
+        (KJS::Window::getValueProperty):
+        (KJS::Window::childFrameGetter):
+        (KJS::Window::indexGetter):
+        (KJS::Window::namedItemGetter):
+        (KJS::Window::getOwnPropertySlot):
+        (KJS::Window::put):
+        (KJS::Window::isSafeScript):
+        (KJS::Window::setListener):
+        (KJS::Window::getListener):
+        (KJS::Window::clear):
+        (KJS::WindowFunc::callAsFunction):
+        (KJS::Window::updateLayout):
+        (KJS::ScheduledAction::execute):
+        (KJS::Window::disconnectFrame):
+        (KJS::Location::put):
+        (KJS::LocationFunc::callAsFunction):
+        * bindings/js/kjs_window.h:
+        * page/mac/WebCoreFrameBridge.mm:
+        (updateRenderingForBindings):
+
 2007-07-12  Mark Rowe  
 
         Reviewed by Ada.
diff --git a/WebCore/bindings/js/JSCustomXPathNSResolver.cpp b/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
index 7b02bcd3e4dd5b5e8409914dc526a3674dd4eb44..53640555da97d71478a0cd653466db2853381ae9 100644
--- a/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
+++ b/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
@@ -29,6 +29,7 @@
 #if ENABLE(XPATH)
 
 #include "CString.h"
+#include "DOMWindow.h"
 #include "Document.h"
 #include "ExceptionCode.h"
 #include "Frame.h"
@@ -53,7 +54,7 @@ PassRefPtr JSCustomXPathNSResolver::create(KJS::ExecSta
         return 0;
     }
     
-    return new JSCustomXPathNSResolver(resolverObject, KJS::Window::retrieveActive(exec)->frame());
+    return new JSCustomXPathNSResolver(resolverObject, KJS::Window::retrieveActive(exec)->impl()->frame());
 }
 
 JSCustomXPathNSResolver::JSCustomXPathNSResolver(JSObject* customResolver, Frame* frame)
diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp
index 2495ac217c572640cfbdc63f71c21896321dd68c..e0b591f1a9bb8a7ad48f644b4f0cc6abd2d191b1 100644
--- a/WebCore/bindings/js/JSDOMWindowCustom.cpp
+++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp
@@ -21,13 +21,14 @@
 #include "JSDOMWindow.h"
 
 #include "kjs_window.h"
+#include "DOMWindow.h"
 
 namespace WebCore {
 
 bool JSDOMWindow::customGetOwnPropertySlot(KJS::ExecState* exec, const KJS::Identifier& propertyName, KJS::PropertySlot& slot)
 {
     // we don't want any properties other than "closed" on a closed window
-    if (!frame()) {
+    if (!impl()->frame()) {
         if (propertyName == "closed") {
             const KJS::HashEntry* entry = KJS::Lookup::findEntry(classInfo()->propHashTable, propertyName);
             ASSERT(entry);
@@ -91,7 +92,7 @@ bool JSDOMWindow::customGetOwnPropertySlot(KJS::ExecState* exec, const KJS::Iden
 
 bool JSDOMWindow::customPut(KJS::ExecState* exec, const KJS::Identifier& propertyName, KJS::JSValue* value, int attr)
 {
-    if (!frame())
+    if (!impl()->frame())
         return true;
 
     // Called by an internal KJS call or if we have a local override (e.g. "var location")
diff --git a/WebCore/bindings/js/JSXMLHttpRequest.cpp b/WebCore/bindings/js/JSXMLHttpRequest.cpp
index 4d42db97213ab4f1816ca1ac3a603e06aee8730a..cedcbadb5fe2180a416be72270dcca13b12965cd 100644
--- a/WebCore/bindings/js/JSXMLHttpRequest.cpp
+++ b/WebCore/bindings/js/JSXMLHttpRequest.cpp
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "JSXMLHttpRequest.h"
 
+#include "DOMWindow.h"
 #include "Event.h"
 #include "Frame.h"
 #include "FrameLoader.h"
@@ -218,7 +219,10 @@ JSValue* JSXMLHttpRequestPrototypeFunction::callAsFunction(ExecState* exec, JSOb
                 return throwError(exec, SyntaxError, "Not enough arguments");
 
             String method = args[0]->toString(exec);
-            KURL url = Window::retrieveActive(exec)->frame()->loader()->completeURL(DeprecatedString(args[1]->toString(exec)));
+            Frame* frame = Window::retrieveActive(exec)->impl()->frame();
+            if (!frame)
+                return jsUndefined();
+            KURL url = frame->loader()->completeURL(DeprecatedString(args[1]->toString(exec)));
 
             bool async = true;
             if (args.size() >= 3)
diff --git a/WebCore/bindings/js/kjs_events.cpp b/WebCore/bindings/js/kjs_events.cpp
index a9dd498309d72764677f977f6294e6255a0fe19f..5fc6c4495848757070a7bb0159bfff7c37a7233d 100644
--- a/WebCore/bindings/js/kjs_events.cpp
+++ b/WebCore/bindings/js/kjs_events.cpp
@@ -25,6 +25,7 @@
 #include "Chrome.h"
 #include "Clipboard.h"
 #include "ClipboardEvent.h"
+#include "DOMWindow.h"
 #include "Document.h"
 #include "Event.h"
 #include "EventNames.h"
@@ -70,7 +71,7 @@ void JSAbstractEventListener::handleEvent(Event* ele, bool isWindowEvent)
     // xmlhttprequest objects. See http://bugs.webkit.org/show_bug.cgi?id=13275
     if (!window)
         return;
-    Frame *frame = window->frame();
+    Frame *frame = window->impl()->frame();
     if (!frame)
         return;
     KJSProxy* proxy = frame->scriptProxy();
@@ -290,7 +291,7 @@ void JSLazyEventListener::parseCode() const
         return;
     m_parsed = true;
 
-    Frame* frame = windowObj()->frame();
+    Frame* frame = windowObj()->impl()->frame();
     KJSProxy* proxy = 0;
     if (frame)
         proxy = frame->scriptProxy();
diff --git a/WebCore/bindings/js/kjs_window.cpp b/WebCore/bindings/js/kjs_window.cpp
index 265328b7e682ecc4438bdb3496941086d6a76616..822ed14ba4ffc4a641b682376712b0ef5ba32a74 100644
--- a/WebCore/bindings/js/kjs_window.cpp
+++ b/WebCore/bindings/js/kjs_window.cpp
@@ -222,7 +222,7 @@ const ClassInfo Window::info = { "Window", 0, &WindowTable, 0 };
 */
 
 Window::Window(DOMWindow* window)
-  : m_frame(window->frame())
+  : m_impl(window)
   , d(new WindowPrivate)
 {
 }
@@ -254,12 +254,16 @@ Window::~Window()
 
 DOMWindow* Window::impl() const
 {
-     return m_frame->domWindow();
+     return m_impl.get();
 }
 
-ScriptInterpreter *Window::interpreter() const
+ScriptInterpreter* Window::interpreter() const
 {
-    return m_frame->scriptProxy()->interpreter();
+    Frame* frame = impl()->frame();
+    if (!frame)
+        return 0;
+
+    return frame->scriptProxy()->interpreter();
 }
 
 Window *Window::retrieveWindow(Frame *f)
@@ -289,14 +293,18 @@ JSValue *Window::retrieve(Frame *p)
 Location *Window::location() const
 {
   if (!d->loc)
-    d->loc = new Location(m_frame);
+    d->loc = new Location(impl()->frame());
   return d->loc;
 }
 
 bool Window::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool wholeWord, bool searchInFrames, bool showDialog) const
 {
     // FIXME (13016): Support wholeWord, searchInFrames and showDialog
-    return m_frame->findString(string, !backwards, caseSensitive, wrap, false);
+    Frame* frame = impl()->frame();
+    if (!frame)
+        return false;
+
+    return frame->findString(string, !backwards, caseSensitive, wrap, false);
 }
 
 // reference our special objects during garbage collection
@@ -309,11 +317,12 @@ void Window::mark()
 
 static bool allowPopUp(ExecState *exec, Window *window)
 {
-    if (!window->frame())
+    Frame* frame = window->impl()->frame();
+    if (!frame)
         return false;
     if (static_cast(exec->dynamicInterpreter())->wasRunByUserGesture())
         return true;
-    Settings* settings = window->frame()->settings();
+    Settings* settings = frame->settings();
     return settings && settings->JavaScriptCanOpenWindowsAutomatically();
 }
 
@@ -378,7 +387,7 @@ static float floatFeature(const HashMap &features, const char *k
 static Frame* createWindow(ExecState* exec, Frame* openerFrame, const String& url,
     const String& frameName, const WindowFeatures& windowFeatures, JSValue* dialogArgs)
 {
-    Frame* activeFrame = Window::retrieveActive(exec)->frame();
+    Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();
     
     ResourceRequest request;
     if (activeFrame)
@@ -424,16 +433,20 @@ static Frame* createWindow(ExecState* exec, Frame* openerFrame, const String& ur
 
 static bool canShowModalDialog(const Window *window)
 {
-    if (Frame* frame = window->frame())
-        return frame->page()->chrome()->canRunModal();
-    return false;
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return false;
+
+    return frame->page()->chrome()->canRunModal();
 }
 
 static bool canShowModalDialogNow(const Window *window)
 {
-    if (Frame* frame = window->frame())
-        return frame->page()->chrome()->canRunModalNow();
-    return false;
+    Frame* frame = window->impl()->frame();
+    if (!frame)
+        return false;
+
+    return frame->page()->chrome()->canRunModalNow();
 }
 
 static JSValue* showModalDialog(ExecState* exec, Window* openerWindow, const List& args)
@@ -454,8 +467,11 @@ static JSValue* showModalDialog(ExecState* exec, Window* openerWindow, const Lis
     // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print
     // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)
     // - unadorned: trusted && boolFeature(features, "unadorned");
+    Frame* frame = openerWindow->impl()->frame();
+    if (!frame)
+        return jsUndefined();
 
-    FloatRect screenRect = screenAvailableRect(openerWindow->frame()->view());
+    FloatRect screenRect = screenAvailableRect(frame->view());
 
     wargs.width = floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE
     wargs.widthSet = true;
@@ -487,7 +503,7 @@ static JSValue* showModalDialog(ExecState* exec, Window* openerWindow, const Lis
     wargs.locationBarVisible = false;
     wargs.fullscreen = false;
     
-    Frame* dialogFrame = createWindow(exec, openerWindow->frame(), valueToStringWithUndefinedOrNullCheck(exec, args[0]), "", wargs, args[1]);
+    Frame* dialogFrame = createWindow(exec, frame, valueToStringWithUndefinedOrNullCheck(exec, args[0]), "", wargs, args[1]);
     if (!dialogFrame)
         return jsUndefined();
 
@@ -511,7 +527,7 @@ static JSValue* showModalDialog(ExecState* exec, Window* openerWindow, const Lis
 
 JSValue *Window::getValueProperty(ExecState *exec, int token) const
 {
-   ASSERT(m_frame);
+   ASSERT(impl()->frame());
 
    switch (token) {
    case Crypto:
@@ -523,7 +539,7 @@ JSValue *Window::getValueProperty(ExecState *exec, int token) const
         return jsUndefined();
       return getDOMExceptionConstructor(exec);
     case Frames:
-      return retrieve(m_frame);
+      return retrieve(impl()->frame());
     case Event_:
       if (!isSafeScript(exec))
         return jsUndefined();
@@ -537,7 +553,7 @@ JSValue *Window::getValueProperty(ExecState *exec, int token) const
       if (!isSafeScript(exec))
         return jsUndefined();
       // Store the navigator in the object so we get the same one each time.
-      Navigator *n = new Navigator(exec, m_frame);
+      Navigator *n = new Navigator(exec, impl()->frame());
       // FIXME: this will make the "navigator" object accessible from windows that fail
       // the security check the first time, but not subsequent times, seems weird.
       const_cast(this)->putDirect("navigator", n, DontDelete|ReadOnly);
@@ -545,30 +561,30 @@ JSValue *Window::getValueProperty(ExecState *exec, int token) const
       return n;
     }
     case Opener:
-      if (m_frame->loader()->opener())
-        return retrieve(m_frame->loader()->opener());
+      if (impl()->frame()->loader()->opener())
+        return retrieve(impl()->frame()->loader()->opener());
       return jsNull();
     case Parent:
-      return retrieve(m_frame->tree()->parent() ? m_frame->tree()->parent() : m_frame);
+      return retrieve(impl()->frame()->tree()->parent() ? impl()->frame()->tree()->parent() : impl()->frame());
     case Self:
     case Window_:
-      return retrieve(m_frame);
+      return retrieve(impl()->frame());
     case Top:
-      return retrieve(m_frame->page()->mainFrame());
+      return retrieve(impl()->frame()->page()->mainFrame());
     case Image:
       if (!isSafeScript(exec))
         return jsUndefined();
       // FIXME: this property (and the few below) probably shouldn't create a new object every
       // time
-      return new ImageConstructorImp(exec, m_frame->document());
+      return new ImageConstructorImp(exec, impl()->frame()->document());
     case Option:
       if (!isSafeScript(exec))
         return jsUndefined();
-      return new JSHTMLOptionElementConstructor(exec, m_frame->document());
+      return new JSHTMLOptionElementConstructor(exec, impl()->frame()->document());
     case XMLHttpRequest:
       if (!isSafeScript(exec))
         return jsUndefined();
-      return new JSXMLHttpRequestConstructorImp(exec, m_frame->document());
+      return new JSXMLHttpRequestConstructorImp(exec, impl()->frame()->document());
 #if ENABLE(XSLT)
     case XSLTProcessor_:
       if (!isSafeScript(exec))
@@ -581,7 +597,7 @@ JSValue *Window::getValueProperty(ExecState *exec, int token) const
     case FrameElement:
       if (!isSafeScript(exec))
         return jsUndefined();
-      if (Document* doc = m_frame->document())
+      if (Document* doc = impl()->frame()->document())
         if (Element* fe = doc->ownerElement())
           if (checkNodeSecurity(exec, fe))
             return toJS(exec, fe);
@@ -649,18 +665,18 @@ JSValue *Window::getValueProperty(ExecState *exec, int token) const
 
 JSValue* Window::childFrameGetter(ExecState*, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
 {
-    return retrieve(static_cast(slot.slotBase())->m_frame->tree()->child(AtomicString(propertyName)));
+    return retrieve(static_cast(slot.slotBase())->impl()->frame()->tree()->child(AtomicString(propertyName)));
 }
 
 JSValue* Window::indexGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
 {
-    return retrieve(static_cast(slot.slotBase())->m_frame->tree()->child(slot.index()));
+    return retrieve(static_cast(slot.slotBase())->impl()->frame()->tree()->child(slot.index()));
 }
 
 JSValue *Window::namedItemGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
 {
   Window *thisObj = static_cast(slot.slotBase());
-  Document *doc = thisObj->m_frame->document();
+  Document *doc = thisObj->impl()->frame()->document();
   ASSERT(thisObj->isSafeScript(exec) && doc && doc->isHTMLDocument());
 
   String name = propertyName;
@@ -677,7 +693,7 @@ bool Window::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName,
   // naming frames things that conflict with window properties that
   // are in Moz but not IE. Since we have some of these, we have to do
   // it the Moz way.
-  if (frame()->tree()->child(propertyName)) {
+  if (impl()->frame()->tree()->child(propertyName)) {
     slot.setCustom(this, childFrameGetter);
     return true;
   }
@@ -707,13 +723,13 @@ bool Window::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName,
   // allow window[1] or parent[1] etc. (#56983)
   bool ok;
   unsigned i = propertyName.toArrayIndex(&ok);
-  if (ok && i < m_frame->tree()->childCount()) {
+  if (ok && i < impl()->frame()->tree()->childCount()) {
     slot.setCustomIndex(this, i, indexGetter);
     return true;
   }
 
   // allow shortcuts like 'Image1' instead of document.images.Image1
-  Document *doc = m_frame->document();
+  Document *doc = impl()->frame()->document();
   if (isSafeScript(exec) && doc && doc->isHTMLDocument()) {
     AtomicString atomicPropertyName = propertyName;
     if (static_cast(doc)->hasNamedItem(atomicPropertyName) || doc->getElementById(atomicPropertyName)) {
@@ -740,13 +756,13 @@ void Window::put(ExecState* exec, const Identifier& propertyName, JSValue* value
 
     switch (entry->value) {
     case Location_: {
-      Frame* p = Window::retrieveActive(exec)->m_frame;
+      Frame* p = Window::retrieveActive(exec)->impl()->frame();
       if (p) {
         DeprecatedString dstUrl = p->loader()->completeURL(DeprecatedString(value->toString(exec))).url();
         if (!dstUrl.startsWith("javascript:", false) || isSafeScript(exec)) {
           bool userGesture = static_cast(exec->dynamicInterpreter())->wasRunByUserGesture();
           // We want a new history item if this JS was called via a user gesture
-          m_frame->loader()->scheduleLocationChange(dstUrl, p->loader()->outgoingReferrer(), !userGesture, userGesture);
+          impl()->frame()->loader()->scheduleLocationChange(dstUrl, p->loader()->outgoingReferrer(), !userGesture, userGesture);
         }
       }
       return;
@@ -859,16 +875,6 @@ void Window::put(ExecState* exec, const Identifier& propertyName, JSValue* value
     JSObject::put(exec, propertyName, value, attr);
 }
 
-bool Window::toBoolean(ExecState *) const
-{
-  return m_frame;
-}
-
-void Window::scheduleClose()
-{
-  m_frame->scheduleClose();
-}
-
 static bool shouldLoadAsEmptyDocument(const KURL &url)
 {
   return url.protocol().lower() == "about" || url.isEmpty();
@@ -931,21 +937,22 @@ bool Window::isSafeScript(const ScriptInterpreter *origin, const ScriptInterpret
 
 bool Window::isSafeScript(ExecState *exec) const
 {
-  if (!m_frame) // frame deleted ? can't grant access
+  Frame* frame = impl()->frame();
+  if (!frame) // frame deleted ? can't grant access
     return false;
   Frame* activeFrame = static_cast(exec->dynamicInterpreter())->frame();
   if (!activeFrame)
     return false;
-  if (activeFrame == m_frame) // Not calling from another frame, no problem.
+  if (activeFrame == frame) // Not calling from another frame, no problem.
     return true;
 
   // JS may be attempting to access the "window" object, which should be valid,
   // even if the document hasn't been constructed yet.  If the document doesn't
   // exist yet allow JS to access the window object.
-  if (!m_frame->document())
+  if (!frame->document())
       return true;
 
-  WebCore::Document* thisDocument = m_frame->document();
+  WebCore::Document* thisDocument = frame->document();
   WebCore::Document* actDocument = activeFrame->document();
 
   WebCore::String actDomain;
@@ -965,9 +972,9 @@ bool Window::isSafeScript(ExecState *exec) const
   // if this document is being initially loaded as empty by its parent
   // or opener, allow access from any document in the same domain as
   // the parent or opener.
-  if (shouldLoadAsEmptyDocument(m_frame->loader()->url())) {
-    Frame* ancestorFrame = m_frame->loader()->opener()
-        ? m_frame->loader()->opener() : m_frame->tree()->parent();
+  if (shouldLoadAsEmptyDocument(frame->loader()->url())) {
+    Frame* ancestorFrame = impl()->frame()->loader()->opener()
+        ? frame->loader()->opener() : frame->tree()->parent();
     while (ancestorFrame && shouldLoadAsEmptyDocument(ancestorFrame->loader()->url()))
       ancestorFrame = ancestorFrame->tree()->parent();
     if (ancestorFrame)
@@ -984,7 +991,7 @@ bool Window::isSafeScript(ExecState *exec) const
   }
   String message = String::format("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
                   thisDocument->URL().latin1(), actDocument->URL().latin1());
-  if (Page* page = m_frame->page())
+  if (Page* page = frame->page())
       page->chrome()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, message, 1, String());
   
   return false;
@@ -994,7 +1001,10 @@ void Window::setListener(ExecState *exec, const AtomicString &eventType, JSValue
 {
   if (!isSafeScript(exec))
     return;
-  WebCore::Document *doc = m_frame->document();
+  Frame* frame = impl()->frame();
+  if (!frame)
+    return;
+  Document* doc = frame->document();
   if (!doc)
     return;
 
@@ -1005,7 +1015,10 @@ JSValue *Window::getListener(ExecState *exec, const AtomicString &eventType) con
 {
   if (!isSafeScript(exec))
     return jsUndefined();
-  WebCore::Document *doc = m_frame->document();
+  Frame* frame = impl()->frame();
+  if (!frame)
+    return jsUndefined();
+  Document* doc = frame->document();
   if (!doc)
     return jsUndefined();
 
@@ -1082,8 +1095,8 @@ void Window::clear()
 
   // Now recreate a working global object for the next URL that will use us; but only if we haven't been
   // disconnected yet
-  if (m_frame)
-    interpreter()->initGlobalObject();
+  if (Frame* frame = impl()->frame())
+    frame->scriptProxy()->interpreter()->initGlobalObject();
 
   // there's likely to be lots of garbage now
   Collector::collect();
@@ -1249,7 +1262,7 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
   if (!thisObj->inherits(&Window::info))
     return throwError(exec, TypeError);
   Window *window = static_cast(thisObj);
-  Frame *frame = window->m_frame;
+  Frame *frame = window->impl()->frame();
   if (!frame)
     return jsUndefined();
 
@@ -1330,7 +1343,7 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
       // In those cases, we can schedule a location change right now and return early
       if (frameName == "_top" || frameName == "_parent") {
           String completedURL;
-          Frame* activeFrame = Window::retrieveActive(exec)->m_frame;
+          Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();
           if (!urlString.isEmpty() && activeFrame)
               completedURL = activeFrame->document()->completeURL(urlString);
 
@@ -1503,7 +1516,10 @@ JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const Li
 
 void Window::updateLayout() const
 {
-  WebCore::Document* docimpl = m_frame->document();
+  Frame* frame = impl()->frame();
+  if (!frame)
+    return;
+  WebCore::Document* docimpl = frame->document();
   if (docimpl)
     docimpl->updateLayoutIgnorePendingStylesheets();
 }
@@ -1517,7 +1533,7 @@ void Window::setReturnValueSlot(JSValue **slot)
 
 void ScheduledAction::execute(Window* window)
 {
-    RefPtr frame = window->m_frame;
+    RefPtr frame = window->impl()->frame();
     if (!frame)
         return;
 
@@ -1680,7 +1696,6 @@ void Window::timerFired(DOMWindowTimer* timer)
 void Window::disconnectFrame()
 {
     clearAllTimeouts();
-    m_frame = 0;
     if (d->loc)
         d->loc->m_frame = 0;
 }
@@ -1792,7 +1807,7 @@ void Location::put(ExecState *exec, const Identifier &p, JSValue *v, int attr)
   if (entry)
     switch (entry->value) {
     case Href: {
-      Frame* p = Window::retrieveActive(exec)->frame();
+      Frame* p = Window::retrieveActive(exec)->impl()->frame();
       if ( p )
         url = p->loader()->completeURL(str).url();
       else
@@ -1842,7 +1857,7 @@ void Location::put(ExecState *exec, const Identifier &p, JSValue *v, int attr)
   }
 
   const Window* window = Window::retrieveWindow(m_frame);
-  Frame* activeFrame = Window::retrieveActive(exec)->frame();
+  Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();
   if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
     bool userGesture = static_cast(exec->dynamicInterpreter())->wasRunByUserGesture();
     // We want a new history item if this JS was called via a user gesture
@@ -1866,7 +1881,7 @@ JSValue *LocationFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const
     case Location::Replace:
     {
       DeprecatedString str = args[0]->toString(exec);
-      Frame* p = Window::retrieveActive(exec)->frame();
+      Frame* p = Window::retrieveActive(exec)->impl()->frame();
       if ( p ) {
         const Window* window = Window::retrieveWindow(frame);
         if (!str.startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
@@ -1887,7 +1902,7 @@ JSValue *LocationFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const
     }
     case Location::Assign:
     {
-        Frame *p = Window::retrieveActive(exec)->frame();
+        Frame *p = Window::retrieveActive(exec)->impl()->frame();
         if (p) {
             const Window *window = Window::retrieveWindow(frame);
             DeprecatedString dstUrl = p->loader()->completeURL(DeprecatedString(args[0]->toString(exec))).url();
diff --git a/WebCore/bindings/js/kjs_window.h b/WebCore/bindings/js/kjs_window.h
index ae9825ff4abe9e2dc008e94ba787ab4995ebc4de..8f9e06c63b48b75a29275134210a4a45c5add3fd 100644
--- a/WebCore/bindings/js/kjs_window.h
+++ b/WebCore/bindings/js/kjs_window.h
@@ -90,12 +90,10 @@ namespace KJS {
      * was called from.
      */
     static Window* retrieveActive(ExecState*);
-    WebCore::Frame* frame() const { return m_frame; }
     virtual void mark();
     virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     JSValue *getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
-    virtual bool toBoolean(ExecState*) const;
 
     int installTimeout(const UString& handler, int t, bool singleShot);
     int installTimeout(JSValue* function, const List& args, int t, bool singleShot);
@@ -106,8 +104,6 @@ namespace KJS {
     void timerFired(DOMWindowTimer*);
     
     KJS::ScriptInterpreter *interpreter() const;
-
-    void scheduleClose();
         
     bool isSafeScript(ExecState*) const;
     static bool isSafeScript(const ScriptInterpreter *origin, const ScriptInterpreter *target);
@@ -190,7 +186,7 @@ namespace KJS {
     void clearAllTimeouts();
     int installTimeout(ScheduledAction*, int interval, bool singleShot);
 
-    WebCore::Frame* m_frame;
+    RefPtr m_impl;
     OwnPtr d;
   };
 
diff --git a/WebCore/page/mac/WebCoreFrameBridge.mm b/WebCore/page/mac/WebCoreFrameBridge.mm
index 0ba11d6ce998fa0930f2b1383de9a75031484e1f..2ba1f1fb02f6e4b4b414c808cae507daaaa92589 100644
--- a/WebCore/page/mac/WebCoreFrameBridge.mm
+++ b/WebCore/page/mac/WebCoreFrameBridge.mm
@@ -33,6 +33,7 @@
 #import "ClipboardMac.h"
 #import "DOMImplementation.h"
 #import "DOMInternal.h"
+#import "DOMWindow.h"
 #import "TextResourceDecoder.h"
 #import "DeleteSelectionCommand.h"
 #import "DocLoader.h"
@@ -142,9 +143,10 @@ static void updateRenderingForBindings(ExecState* exec, JSObject* rootObject)
     Window* window = static_cast(rootObject);
     if (!window)
         return;
-        
-    if (Document* doc = window->frame()->document())
-        doc->updateRendering();
+
+    if (Frame* frame = window->impl()->frame())
+        if (Document* doc = frame->document())
+            doc->updateRendering();
 }
 
 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue* jsValue)