From 5366713790de7b5f8daec43d76588ebf98f08f2e Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 31 Jan 2010 15:07:23 -0800 Subject: [PATCH] Closes #429. Doesn't necessarily address the root cause however. The problem stems from a bug in Safari which is allowing callbacks to interrupt running code (which should be impossible in JavaScript). The change essentially makes it so that in the case where this happens, which is rare, we'll end up accidentally creating an extra iframe. This isn't ideal, but it also isn't harmful, versus the current situation where code will simply break. --- AppKit/Platform/DOM/CPPlatform.j | 5 +++ AppKit/Platform/DOM/CPPlatformString.j | 52 ++++++++++++++++++-------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/AppKit/Platform/DOM/CPPlatform.j b/AppKit/Platform/DOM/CPPlatform.j index 47af4b175..60ac59129 100644 --- a/AppKit/Platform/DOM/CPPlatform.j +++ b/AppKit/Platform/DOM/CPPlatform.j @@ -21,6 +21,7 @@ */ CPPlatformDidClearBodyElementNotification = @"CPPlatformDidClearBodyElementNotification"; +CPPlatformWillClearBodyElementNotification = @"CPPlatformWillClearBodyElementNotification"; var screenNeedsInitialization = NO, mainBodyElement = nil; @@ -91,6 +92,10 @@ var screenNeedsInitialization = NO, screenNeedsInitialization = NO; + [[CPNotificationCenter defaultCenter] + postNotificationName:CPPlatformWillClearBodyElementNotification + object:self]; + var bodyElement = [self mainBodyElement]; // Get rid of any of the original contents of the page. diff --git a/AppKit/Platform/DOM/CPPlatformString.j b/AppKit/Platform/DOM/CPPlatformString.j index e0431b0d4..1beb80c6f 100644 --- a/AppKit/Platform/DOM/CPPlatformString.j +++ b/AppKit/Platform/DOM/CPPlatformString.j @@ -22,8 +22,8 @@ #include "../CoreGraphics/CGGeometry.h" - var DOMSpanElement = nil, + DOMIFrameElement = nil, DefaultFont = nil; @implementation CPPlatformString : CPBasePlatformString @@ -39,11 +39,20 @@ var DOMSpanElement = nil, selector:@selector(platformDidClearBodyElement:) name:CPPlatformDidClearBodyElementNotification object:CPPlatform]; + + [[CPNotificationCenter defaultCenter] + addObserver:self + selector:@selector(platformWillClearBodyElement:) + name:CPPlatformWillClearBodyElementNotification + object:CPPlatform]; } + (void)createDOMElements { - var DOMIFrameElement = document.createElement("iframe"); + if (DOMIFrameElement) + return; + + DOMIFrameElement = document.createElement("iframe"); // necessary for Safari caching bug: DOMIFrameElement.name = "iframe_" + FLOOR(RAND() * 10000); DOMIFrameElement.style.position = "absolute"; @@ -80,11 +89,27 @@ var DOMSpanElement = nil, DOMDivElement.appendChild(DOMSpanElement); } ++ (void)removeDOMElements +{ + var iframe = DOMIFrameElement, + bodyElement = [CPPlatform mainBodyElement]; + + DOMSpanElement = nil; + DOMIFrameElement = nil; + + bodyElement.removeChild(iframe); +} + + (void)platformDidClearBodyElement:(CPNotification)aNotification { [self createDOMElements]; } ++ (void)platformWillClearBodyElement:(CPNotification)aNotification +{ + [self removeDOMElements]; +} + + (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth { if (!aFont) @@ -95,35 +120,30 @@ var DOMSpanElement = nil, aFont = DefaultFont; } + if (!DOMIFrameElement) + [self createDOMElements]; + var style = DOMSpanElement.style; - if (aWidth === NULL) + if (!aWidth) { style.width = ""; style.whiteSpace = "pre"; } - else { style.width = ROUND(aWidth) + "px"; - - if (document.attachEvent) - style.wordWrap = "break-word"; - - else - { - style.whiteSpace = "-o-pre-wrap"; - style.whiteSpace = "-pre-wrap"; - style.whiteSpace = "-moz-pre-wrap"; - style.whiteSpace = "pre-wrap"; - } + style.wordWrap = "break-word"; + style.whiteSpace = "-o-pre-wrap"; + style.whiteSpace = "-pre-wrap"; + style.whiteSpace = "-moz-pre-wrap"; + style.whiteSpace = "pre-wrap"; } style.font = [aFont cssString]; if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature)) DOMSpanElement.innerText = aString; - else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature)) DOMSpanElement.textContent = aString;