[CSS Regions] Fix the lifecycle for the flow objects and their renderers
https://bugs.webkit.org/show_bug.cgi?id=89000

Patch by Andrei Bucur <abucur@adobe.com> on 2012-07-13
Reviewed by Eric Seidel.

Source/WebCore:

This patch adds the concept of a NamedFlowCollection, owned by the document, that keeps track of
all the named flows that exist in the Document. This collection contains a ListHashSet of weak references to
all the existing NamedFlows in the document. This is not a managed set because the CREATED flows are referenced from the renderer and
the NULL flows are only cached, they should be destructible.
Two named flows are considered to be equal if they have the same name.
I've changed the NamedFlow state to depend on the existence of its renderer. A flow thread that has a renderer will also have a NamedFlow object.
A flow thread without a renderer can have a NamedFlow object, but only in the NULL state. It's possible for a NamedFlow object to jump from the
NULL state to the CREATED state if it was not destroyed (e.g. it was referenced from JS). Keeping track of the NULL state flows that have listeners will be important
so when they go back to the CREATED state, the listeners would still be there.

Link to spec: http://www.w3.org/TR/2012/WD-css3-regions-20120503/

Tests: The old tests have been modified to take into account the new behavior

* CMakeLists.txt:
* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* dom/DOMAllInOne.cpp:
* dom/Document.cpp:
(WebCore::Document::~Document):
(WebCore):
(WebCore::Document::webkitGetFlowByName):
(WebCore::Document::namedFlows):
* dom/Document.h:
(WebCore):
(Document):
* dom/WebKitNamedFlow.cpp:
(WebCore::WebKitNamedFlow::WebKitNamedFlow):
(WebCore::WebKitNamedFlow::~WebKitNamedFlow):
(WebCore::WebKitNamedFlow::create):
(WebCore):
(WebCore::WebKitNamedFlow::name):
(WebCore::WebKitNamedFlow::overset):
(WebCore::nodeInFlowThread):
(WebCore::WebKitNamedFlow::getRegionsByContentNode):
(WebCore::WebKitNamedFlow::getContent):
(WebCore::WebKitNamedFlow::setRenderer):
* dom/WebKitNamedFlow.h:
(WebCore):
(WebKitNamedFlow):
(WebCore::WebKitNamedFlow::getFlowState):
(WebCore::WebKitNamedFlow::switchFlowState):
* dom/WebKitNamedFlowCollection.cpp: Added.
(WebCore):
(WebCore::WebKitNamedFlowCollection::WebKitNamedFlowCollection):
(WebCore::WebKitNamedFlowCollection::length): An O(1) operation
(WebCore::WebKitNamedFlowCollection::item): An O(N) operation
(WebCore::WebKitNamedFlowCollection::flowByName): An O(1) operation
(WebCore::WebKitNamedFlowCollection::ensureNamedFlowInCreatedState): An O(1) operation
(WebCore::WebKitNamedFlowCollection::moveNamedFlowToNullState): An O(1) operation
(WebCore::WebKitNamedFlowCollection::discardNamedFlow): An O(1) operation
(WebCore::WebKitNamedFlowCollection::documentDestroyed):
(WebCore::WebKitNamedFlowCollection::NamedFlowHashFunctions::hash):
(WebCore::WebKitNamedFlowCollection::NamedFlowHashFunctions::equal):
(WebKitNamedFlowCollection::NamedFlowHashFunctions):
(WebCore::WebKitNamedFlowCollection::NamedFlowHashTranslator::hash):
(WebCore::WebKitNamedFlowCollection::NamedFlowHashTranslator::equal):
* dom/WebKitNamedFlowCollection.h: Copied from Source/WebCore/dom/WebKitNamedFlow.h.
(WebCore):
(WebKitNamedFlowCollection):
(WebCore::WebKitNamedFlowCollection::create):
(WebCore::WebKitNamedFlowCollection::document):
* rendering/FlowThreadController.cpp:
(WebCore::FlowThreadController::ensureRenderFlowThreadWithName):
(WebCore::FlowThreadController::removeFlowThread):
(WebCore):
* rendering/FlowThreadController.h:
(FlowThreadController):
* rendering/RenderNamedFlowThread.cpp:
(WebCore::RenderNamedFlowThread::RenderNamedFlowThread):
(WebCore):
(WebCore::RenderNamedFlowThread::~RenderNamedFlowThread):
(WebCore::RenderNamedFlowThread::removeRegionFromThread):
(WebCore::RenderNamedFlowThread::unregisterNamedFlowContentNode):
(WebCore::RenderNamedFlowThread::flowThreadName):
(WebCore::RenderNamedFlowThread::willBeDestroyed):
* rendering/RenderNamedFlowThread.h:
(RenderNamedFlowThread):
(WebCore::RenderNamedFlowThread::contentNodes):
(WebCore::RenderNamedFlowThread::canBeDestroyed):

LayoutTests:

These tests expected getFlowByName() to return a valid object even for the NULL flows. They've been modified to
reflect the new behavior.

* fast/regions/get-regions-by-content-node2-expected.txt:
* fast/regions/get-regions-by-content-node2.html:
* fast/regions/webkit-named-flow-flow-added.html:
* fast/regions/webkit-named-flow-get-content-expected.txt:
* fast/regions/webkit-named-flow-get-content.html:
* fast/regions/webkit-named-flow-invalid-name.html:
* fast/regions/webkit-named-flow-modified-flow.html:
* fast/regions/webkit-named-flow-non-existing-flow.html:
* fast/regions/webkit-named-flow-removed-flow.html:
* platform/chromium-win/fast/regions/region-style-block-background-color2-expected.txt:
* platform/mac/fast/regions/region-style-block-background-color2-expected.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@122556 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt
index c02b211..ccf3242 100644
--- a/Source/WebCore/CMakeLists.txt
+++ b/Source/WebCore/CMakeLists.txt
@@ -674,6 +674,7 @@
     dom/ViewportArguments.cpp
     dom/WebKitAnimationEvent.cpp
     dom/WebKitNamedFlow.cpp
+    dom/WebKitNamedFlowCollection.cpp
     dom/WebKitTransitionEvent.cpp
     dom/WheelEvent.cpp
     dom/WindowEventContext.cpp
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index bf16444..b4395ae 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,94 @@
+2012-07-13  Andrei Bucur  <abucur@adobe.com>
+
+        [CSS Regions] Fix the lifecycle for the flow objects and their renderers
+        https://bugs.webkit.org/show_bug.cgi?id=89000
+
+        Reviewed by Eric Seidel.
+
+        This patch adds the concept of a NamedFlowCollection, owned by the document, that keeps track of
+        all the named flows that exist in the Document. This collection contains a ListHashSet of weak references to
+        all the existing NamedFlows in the document. This is not a managed set because the CREATED flows are referenced from the renderer and
+        the NULL flows are only cached, they should be destructible.
+        Two named flows are considered to be equal if they have the same name.
+        I've changed the NamedFlow state to depend on the existence of its renderer. A flow thread that has a renderer will also have a NamedFlow object.
+        A flow thread without a renderer can have a NamedFlow object, but only in the NULL state. It's possible for a NamedFlow object to jump from the
+        NULL state to the CREATED state if it was not destroyed (e.g. it was referenced from JS). Keeping track of the NULL state flows that have listeners will be important
+        so when they go back to the CREATED state, the listeners would still be there.
+
+        Link to spec: http://www.w3.org/TR/2012/WD-css3-regions-20120503/
+
+        Tests: The old tests have been modified to take into account the new behavior
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/DOMAllInOne.cpp:
+        * dom/Document.cpp:
+        (WebCore::Document::~Document):
+        (WebCore):
+        (WebCore::Document::webkitGetFlowByName):
+        (WebCore::Document::namedFlows):
+        * dom/Document.h:
+        (WebCore):
+        (Document):
+        * dom/WebKitNamedFlow.cpp:
+        (WebCore::WebKitNamedFlow::WebKitNamedFlow):
+        (WebCore::WebKitNamedFlow::~WebKitNamedFlow):
+        (WebCore::WebKitNamedFlow::create):
+        (WebCore):
+        (WebCore::WebKitNamedFlow::name):
+        (WebCore::WebKitNamedFlow::overset):
+        (WebCore::nodeInFlowThread):
+        (WebCore::WebKitNamedFlow::getRegionsByContentNode):
+        (WebCore::WebKitNamedFlow::getContent):
+        (WebCore::WebKitNamedFlow::setRenderer):
+        * dom/WebKitNamedFlow.h:
+        (WebCore):
+        (WebKitNamedFlow):
+        (WebCore::WebKitNamedFlow::getFlowState):
+        (WebCore::WebKitNamedFlow::switchFlowState):
+        * dom/WebKitNamedFlowCollection.cpp: Added.
+        (WebCore):
+        (WebCore::WebKitNamedFlowCollection::WebKitNamedFlowCollection):
+        (WebCore::WebKitNamedFlowCollection::length): An O(1) operation
+        (WebCore::WebKitNamedFlowCollection::item): An O(N) operation
+        (WebCore::WebKitNamedFlowCollection::flowByName): An O(1) operation
+        (WebCore::WebKitNamedFlowCollection::ensureNamedFlowInCreatedState): An O(1) operation
+        (WebCore::WebKitNamedFlowCollection::moveNamedFlowToNullState): An O(1) operation
+        (WebCore::WebKitNamedFlowCollection::discardNamedFlow): An O(1) operation
+        (WebCore::WebKitNamedFlowCollection::documentDestroyed):
+        (WebCore::WebKitNamedFlowCollection::NamedFlowHashFunctions::hash):
+        (WebCore::WebKitNamedFlowCollection::NamedFlowHashFunctions::equal):
+        (WebKitNamedFlowCollection::NamedFlowHashFunctions):
+        (WebCore::WebKitNamedFlowCollection::NamedFlowHashTranslator::hash):
+        (WebCore::WebKitNamedFlowCollection::NamedFlowHashTranslator::equal):
+        * dom/WebKitNamedFlowCollection.h: Copied from Source/WebCore/dom/WebKitNamedFlow.h.
+        (WebCore):
+        (WebKitNamedFlowCollection):
+        (WebCore::WebKitNamedFlowCollection::create):
+        (WebCore::WebKitNamedFlowCollection::document):
+        * rendering/FlowThreadController.cpp:
+        (WebCore::FlowThreadController::ensureRenderFlowThreadWithName):
+        (WebCore::FlowThreadController::removeFlowThread):
+        (WebCore):
+        * rendering/FlowThreadController.h:
+        (FlowThreadController):
+        * rendering/RenderNamedFlowThread.cpp:
+        (WebCore::RenderNamedFlowThread::RenderNamedFlowThread):
+        (WebCore):
+        (WebCore::RenderNamedFlowThread::~RenderNamedFlowThread):
+        (WebCore::RenderNamedFlowThread::removeRegionFromThread):
+        (WebCore::RenderNamedFlowThread::unregisterNamedFlowContentNode):
+        (WebCore::RenderNamedFlowThread::flowThreadName):
+        (WebCore::RenderNamedFlowThread::willBeDestroyed):
+        * rendering/RenderNamedFlowThread.h:
+        (RenderNamedFlowThread):
+        (WebCore::RenderNamedFlowThread::contentNodes):
+        (WebCore::RenderNamedFlowThread::canBeDestroyed):
+
 2012-07-13  Vineet Chaudhary  <rgf748@motorola.com>
 
         [V8Bindings] Implement generalised method to validates that the passed object is a sequence type.
diff --git a/Source/WebCore/GNUmakefile.list.am b/Source/WebCore/GNUmakefile.list.am
index 63b170a..827828d 100644
--- a/Source/WebCore/GNUmakefile.list.am
+++ b/Source/WebCore/GNUmakefile.list.am
@@ -2077,6 +2077,8 @@
 	Source/WebCore/dom/WebKitAnimationEvent.h \
 	Source/WebCore/dom/WebKitNamedFlow.cpp \
 	Source/WebCore/dom/WebKitNamedFlow.h \
+	Source/WebCore/dom/WebKitNamedFlowCollection.cpp \
+	Source/WebCore/dom/WebKitNamedFlowCollection.h \
 	Source/WebCore/dom/WebKitTransitionEvent.cpp \
 	Source/WebCore/dom/WebKitTransitionEvent.h \
 	Source/WebCore/dom/WheelEvent.cpp \
diff --git a/Source/WebCore/Target.pri b/Source/WebCore/Target.pri
index 11a5525..ff681ea 100644
--- a/Source/WebCore/Target.pri
+++ b/Source/WebCore/Target.pri
@@ -638,6 +638,7 @@
     dom/ViewportArguments.cpp \
     dom/WebKitAnimationEvent.cpp \
     dom/WebKitNamedFlow.cpp \
+    dom/WebKitNamedFlowCollection.cpp \
     dom/WebKitTransitionEvent.cpp \
     dom/WheelEvent.cpp \
     dom/WindowEventContext.cpp \
@@ -1820,6 +1821,7 @@
     dom/ViewportArguments.h \
     dom/WebKitAnimationEvent.h \
     dom/WebKitNamedFlow.h \
+    dom/WebKitNamedFlowCollection.h \
     dom/WebKitTransitionEvent.h \
     dom/WheelEvent.h \
     editing/AlternativeTextController.h \
diff --git a/Source/WebCore/WebCore.gypi b/Source/WebCore/WebCore.gypi
index e1b0204..62c5ea1 100644
--- a/Source/WebCore/WebCore.gypi
+++ b/Source/WebCore/WebCore.gypi
@@ -5298,6 +5298,8 @@
             'dom/WebKitAnimationEvent.h',
             'dom/WebKitNamedFlow.cpp',
             'dom/WebKitNamedFlow.h',
+            'dom/WebKitNamedFlowCollection.cpp',
+            'dom/WebKitNamedFlowCollection.h',
             'dom/WebKitTransitionEvent.cpp',
             'dom/WebKitTransitionEvent.h',
             'dom/WheelEvent.cpp',
diff --git a/Source/WebCore/WebCore.vcproj/WebCore.vcproj b/Source/WebCore/WebCore.vcproj/WebCore.vcproj
index 95118dc..bcf7ea6 100755
--- a/Source/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/Source/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -54510,6 +54510,62 @@
 				RelativePath="..\dom\WebKitNamedFlow.h"
 				>
 			</File>
+		    <File
+				RelativePath="..\dom\WebKitNamedFlowCollection.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_Cairo_CFLite|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release_Cairo_CFLite|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_All|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Production|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\dom\WebKitNamedFlowCollection.h"
+				>
+			</File>
 			<File
 				RelativePath="..\dom\WebKitTransitionEvent.cpp"
 				>
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 3b3bb2d..701a20c 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -281,6 +281,8 @@
 		0FF50271102BA96A0066F39A /* StyleMedia.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF5026E102BA9660066F39A /* StyleMedia.cpp */; };
 		0FF50272102BA96A0066F39A /* StyleMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF5026F102BA96A0066F39A /* StyleMedia.h */; };
 		10FB084B14E15C7E00A3DB98 /* PublicURLManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 10FB084A14E15C7E00A3DB98 /* PublicURLManager.h */; };
+		12F35EB6158745A40035CB63 /* WebKitNamedFlowCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 12F35EB4158745A40035CB63 /* WebKitNamedFlowCollection.h */; };
+		12F35EB7158745A40035CB63 /* WebKitNamedFlowCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 12F35EB5158745A40035CB63 /* WebKitNamedFlowCollection.cpp */; };
 		1402645E0AFDC19B005919E2 /* LoggingMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1402645D0AFDC19B005919E2 /* LoggingMac.mm */; };
 		1403B99709EB13AF00797C7F /* DOMWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 1403B99509EB13AF00797C7F /* DOMWindow.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		1403B99809EB13AF00797C7F /* DOMWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1403B99609EB13AF00797C7F /* DOMWindow.cpp */; };
@@ -7233,6 +7235,8 @@
 		0FF5026F102BA96A0066F39A /* StyleMedia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleMedia.h; sourceTree = "<group>"; };
 		0FF50270102BA96A0066F39A /* StyleMedia.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = StyleMedia.idl; sourceTree = "<group>"; };
 		10FB084A14E15C7E00A3DB98 /* PublicURLManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PublicURLManager.h; sourceTree = "<group>"; };
+		12F35EB4158745A40035CB63 /* WebKitNamedFlowCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitNamedFlowCollection.h; sourceTree = "<group>"; };
+		12F35EB5158745A40035CB63 /* WebKitNamedFlowCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitNamedFlowCollection.cpp; sourceTree = "<group>"; };
 		1402645D0AFDC19B005919E2 /* LoggingMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = LoggingMac.mm; sourceTree = "<group>"; };
 		1403B90C09EB124500797C7F /* DOMWindow.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DOMWindow.idl; sourceTree = "<group>"; };
 		1403B99509EB13AF00797C7F /* DOMWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMWindow.h; sourceTree = "<group>"; };
@@ -21630,6 +21634,8 @@
 				93EEC1F709C2877700C515D1 /* WheelEvent.idl */,
 				4123E568127B3041000FEEA7 /* WindowEventContext.cpp */,
 				4123E567127B3041000FEEA7 /* WindowEventContext.h */,
+				12F35EB4158745A40035CB63 /* WebKitNamedFlowCollection.h */,
+				12F35EB5158745A40035CB63 /* WebKitNamedFlowCollection.cpp */,
 			);
 			path = dom;
 			sourceTree = "<group>";
@@ -25090,6 +25096,7 @@
 				0562F9471573ECEB0031CA16 /* WebKitCSSSVGDocumentValue.h in Headers */,
 				BC9ADD230CC4032600098C4C /* WebKitCSSTransformValue.h in Headers */,
 				89878566122CA064003AABDA /* WebKitFlags.h in Headers */,
+				12F35EB6158745A40035CB63 /* WebKitNamedFlowCollection.h in Headers */,
 				494BD7950F55C8EE00747828 /* WebKitPoint.h in Headers */,
 				31C0FF250E4CEB6E007D6FE5 /* WebKitTransitionEvent.h in Headers */,
 				0FCF332F0F2B9A25004B6795 /* WebLayer.h in Headers */,
@@ -28159,6 +28166,7 @@
 				BC9ADD800CC4092200098C4C /* WebKitCSSTransformValue.cpp in Sources */,
 				1A1414B513A0F0500019996C /* WebKitFontFamilyNames.cpp in Sources */,
 				D7613A501474F13F00DB8606 /* WebKitNamedFlow.cpp in Sources */,
+				12F35EB7158745A40035CB63 /* WebKitNamedFlowCollection.cpp in Sources */,
 				31C0FF240E4CEB6E007D6FE5 /* WebKitTransitionEvent.cpp in Sources */,
 				0FCF332E0F2B9A25004B6795 /* WebLayer.mm in Sources */,
 				E1A3162E134BC32D007C9A4F /* WebNSAttributedStringExtras.mm in Sources */,
diff --git a/Source/WebCore/dom/DOMAllInOne.cpp b/Source/WebCore/dom/DOMAllInOne.cpp
index 592d729..16dc323 100644
--- a/Source/WebCore/dom/DOMAllInOne.cpp
+++ b/Source/WebCore/dom/DOMAllInOne.cpp
@@ -144,6 +144,7 @@
 #include "ViewportArguments.cpp"
 #include "WebKitAnimationEvent.cpp"
 #include "WebKitNamedFlow.cpp"
+#include "WebKitNamedFlowCollection.cpp"
 #include "WebKitTransitionEvent.cpp"
 #include "WheelEvent.cpp"
 #include "WindowEventContext.cpp"
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index 4fcd6c7..2906f4e 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -157,6 +157,7 @@
 #include "UndoManager.h"
 #include "UserContentURLPattern.h"
 #include "WebKitNamedFlow.h"
+#include "WebKitNamedFlowCollection.h"
 #include "XMLDocumentParser.h"
 #include "XMLHttpRequest.h"
 #include "XMLNSNames.h"
@@ -618,6 +619,9 @@
     if (m_styleSheets)
         m_styleSheets->documentDestroyed();
 
+    if (m_namedFlows)
+        m_namedFlows->documentDestroyed();
+
     if (m_elemSheet)
         m_elemSheet->clearOwnerNode();
     if (m_pageUserSheet)
@@ -1126,44 +1130,26 @@
 
 #if ENABLE(CSS_REGIONS)
 
-static bool validFlowName(const String& flowName)
-{
-    if (equalIgnoringCase(flowName, "auto")
-        || equalIgnoringCase(flowName, "default")
-        || equalIgnoringCase(flowName, "inherit")
-        || equalIgnoringCase(flowName, "initial")
-        || equalIgnoringCase(flowName, "none"))
-        return false;
-    return true;
-}
-
 PassRefPtr<WebKitNamedFlow> Document::webkitGetFlowByName(const String& flowName)
 {
-    return webkitGetFlowByName(flowName, CheckFlowNameForInvalidValues);
-}
-
-PassRefPtr<WebKitNamedFlow> Document::webkitGetFlowByName(const String& flowName, FlowNameCheck flowNameCheck)
-{
     if (!cssRegionsEnabled() || !renderer())
         return 0;
 
-    if (flowNameCheck == CheckFlowNameForInvalidValues) {
-        if (flowName.isEmpty() || !validFlowName(flowName))
-            return 0;
+    // It's possible to have pending styles not applied that affect the existing flows.
+    updateStyleIfNeeded();
 
-        // Make a slower check for invalid flow name.
-        CSSParser parser(document());
-        if (!parser.parseFlowThread(flowName))
-            return 0;
-    }
-
-    if (RenderView* view = renderer()->view())
-        return view->flowThreadController()->ensureRenderFlowThreadWithName(flowName)->ensureNamedFlow();
-    return 0;
+    return namedFlows()->flowByName(flowName);
 }
-
 #endif
 
+WebKitNamedFlowCollection* Document::namedFlows()
+{
+    if (!m_namedFlows)
+        m_namedFlows = WebKitNamedFlowCollection::create(this);
+
+    return m_namedFlows.get();
+}
+
 PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec)
 {
     String prefix, localName;
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index bda2a98..7636fe3 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -137,6 +137,7 @@
 class TreeWalker;
 class UndoManager;
 class WebKitNamedFlow;
+class WebKitNamedFlowCollection;
 class XMLHttpRequest;
 class XPathEvaluator;
 class XPathExpression;
@@ -347,14 +348,11 @@
 
     bool cssRegionsEnabled() const;
 #if ENABLE(CSS_REGIONS)
-    enum FlowNameCheck {
-        CheckFlowNameForInvalidValues,
-        DoNotCheckFlowNameForInvalidValues
-    };
     PassRefPtr<WebKitNamedFlow> webkitGetFlowByName(const String&);
-    PassRefPtr<WebKitNamedFlow> webkitGetFlowByName(const String&, FlowNameCheck);
 #endif
 
+    WebKitNamedFlowCollection* namedFlows();
+
     bool regionBasedColumnsEnabled() const;
 
     bool cssGridLayoutEnabled() const;
@@ -1533,6 +1531,8 @@
     bool m_visualUpdatesAllowed;
     Timer<Document> m_visualUpdatesSuppressionTimer;
 
+    RefPtr<WebKitNamedFlowCollection> m_namedFlows;
+
 #ifndef NDEBUG
     bool m_didDispatchViewportPropertiesChanged;
 #endif
diff --git a/Source/WebCore/dom/WebKitNamedFlow.cpp b/Source/WebCore/dom/WebKitNamedFlow.cpp
index 0ffb703..e50caa7 100644
--- a/Source/WebCore/dom/WebKitNamedFlow.cpp
+++ b/Source/WebCore/dom/WebKitNamedFlow.cpp
@@ -33,32 +33,56 @@
 #include "RenderNamedFlowThread.h"
 #include "RenderRegion.h"
 #include "StaticNodeList.h"
+#include "WebKitNamedFlowCollection.h"
 
 namespace WebCore {
 
-WebKitNamedFlow::WebKitNamedFlow(RenderNamedFlowThread* parentFlowThread)
-: m_parentFlowThread(parentFlowThread)
+WebKitNamedFlow::WebKitNamedFlow(PassRefPtr<WebKitNamedFlowCollection> manager, const AtomicString& flowThreadName)
+    : m_flowThreadName(flowThreadName)
+    , m_flowManager(manager)
+    , m_parentFlowThread(0)
+    , m_state(FlowStateCreated)
 {
 }
 
 WebKitNamedFlow::~WebKitNamedFlow()
 {
+    // The named flow is not "strong" referenced from anywhere at this time so it shouldn't be reused if the named flow is recreated.
+    m_flowManager->discardNamedFlow(this);
 }
 
-String WebKitNamedFlow::name() const
+PassRefPtr<WebKitNamedFlow> WebKitNamedFlow::create(PassRefPtr<WebKitNamedFlowCollection> manager, const AtomicString& flowThreadName)
 {
-    return m_parentFlowThread->flowThreadName();
+    return adoptRef(new WebKitNamedFlow(manager, flowThreadName));
+}
+
+const AtomicString& WebKitNamedFlow::name() const
+{
+    return m_flowThreadName;
 }
 
 bool WebKitNamedFlow::overset() const
 {
-    m_parentFlowThread->document()->updateLayoutIgnorePendingStylesheets();
-    return m_parentFlowThread->overset();
+    if (m_flowManager->document())
+        m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
+
+    // The renderer may be destroyed or created after the style update.
+    // Because this is called from JS, where the wrapper keeps a reference to the NamedFlow, no guard is necessary.
+    return m_parentFlowThread ? m_parentFlowThread->overset() : true;
+}
+
+static inline bool nodeInFlowThread(Node* contentNode, RenderNamedFlowThread* flowThread)
+{
+    return contentNode->renderer() && contentNode->renderer()->inRenderFlowThread() && flowThread == contentNode->renderer()->enclosingRenderFlowThread();
 }
 
 int WebKitNamedFlow::firstEmptyRegionIndex() const
 {
-    m_parentFlowThread->document()->updateLayoutIgnorePendingStylesheets();
+    if (m_flowManager->document())
+        m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
+
+    if (!m_parentFlowThread)
+        return -1;
 
     const RenderRegionList& regionList = m_parentFlowThread->renderRegionList();
     if (regionList.isEmpty())
@@ -74,15 +98,20 @@
 
 PassRefPtr<NodeList> WebKitNamedFlow::getRegionsByContent(Node* contentNode)
 {
-    if (!contentNode)
-        return 0;
-
-    m_parentFlowThread->document()->updateLayoutIgnorePendingStylesheets();
-
     Vector<RefPtr<Node> > regionNodes;
-    if (contentNode->renderer()
-        && contentNode->renderer()->inRenderFlowThread()
-        && m_parentFlowThread == contentNode->renderer()->enclosingRenderFlowThread()) {
+
+    if (!contentNode)
+        return StaticNodeList::adopt(regionNodes);
+
+    if (m_flowManager->document())
+        m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
+
+    // The renderer may be destroyed or created after the style update.
+    // Because this is called from JS, where the wrapper keeps a reference to the NamedFlow, no guard is necessary.
+    if (!m_parentFlowThread)
+        return StaticNodeList::adopt(regionNodes);
+
+    if (nodeInFlowThread(contentNode, m_parentFlowThread)) {
         const RenderRegionList& regionList = m_parentFlowThread->renderRegionList();
         for (RenderRegionList::const_iterator iter = regionList.begin(); iter != regionList.end(); ++iter) {
             const RenderRegion* renderRegion = *iter;
@@ -92,16 +121,25 @@
                 regionNodes.append(renderRegion->node());
         }
     }
+
     return StaticNodeList::adopt(regionNodes);
 }
 
 PassRefPtr<NodeList> WebKitNamedFlow::getContent()
 {
-    m_parentFlowThread->document()->updateLayoutIgnorePendingStylesheets();
-
     Vector<RefPtr<Node> > contentNodes;
-    for (NamedFlowContentNodes::const_iterator it = m_parentFlowThread->contentNodes().begin(); it != m_parentFlowThread->contentNodes().end(); ++it) {
-        Node* node = const_cast<Node*>(*it);
+
+    if (m_flowManager->document())
+        m_flowManager->document()->updateLayoutIgnorePendingStylesheets();
+
+    // The renderer may be destroyed or created after the style update.
+    // Because this is called from JS, where the wrapper keeps a reference to the NamedFlow, no guard is necessary.
+    if (!m_parentFlowThread)
+        return StaticNodeList::adopt(contentNodes);
+
+    const NamedFlowContentNodes& contentNodesList = m_parentFlowThread->contentNodes();
+    for (NamedFlowContentNodes::const_iterator it = contentNodesList.begin(); it != contentNodesList.end(); ++it) {
+        Node* node = *it;
         ASSERT(node->computedStyle()->flowThread() == m_parentFlowThread->flowThreadName());
         contentNodes.append(node);
     }
@@ -109,5 +147,14 @@
     return StaticNodeList::adopt(contentNodes);
 }
 
+void WebKitNamedFlow::setRenderer(RenderNamedFlowThread* parentFlowThread)
+{
+    // The named flow can either go from a no_renderer->renderer or renderer->no_renderer state; anything else could indicate a bug.
+    ASSERT((!m_parentFlowThread && parentFlowThread) || (m_parentFlowThread && !parentFlowThread));
+
+    // If parentFlowThread is 0, the flow thread will move in the "NULL" state"
+    m_parentFlowThread = parentFlowThread;
+}
+
 } // namespace WebCore
 
diff --git a/Source/WebCore/dom/WebKitNamedFlow.h b/Source/WebCore/dom/WebKitNamedFlow.h
index f0c6a12..6167d42 100644
--- a/Source/WebCore/dom/WebKitNamedFlow.h
+++ b/Source/WebCore/dom/WebKitNamedFlow.h
@@ -39,26 +39,39 @@
 
 class NodeList;
 class RenderNamedFlowThread;
+class WebKitNamedFlowCollection;
 
 class WebKitNamedFlow : public RefCounted<WebKitNamedFlow> {
 public:
-    static PassRefPtr<WebKitNamedFlow> create(RenderNamedFlowThread* parentFlowThread)
-    {
-        return adoptRef(new WebKitNamedFlow(parentFlowThread));
-    }
+    static PassRefPtr<WebKitNamedFlow> create(PassRefPtr<WebKitNamedFlowCollection> manager, const AtomicString& flowThreadName);
 
     ~WebKitNamedFlow();
 
-    String name() const;
+    const AtomicString& name() const;
     bool overset() const;
     int firstEmptyRegionIndex() const;
     PassRefPtr<NodeList> getRegionsByContent(Node*);
     PassRefPtr<NodeList> getContent();
 
-private:
-    WebKitNamedFlow(RenderNamedFlowThread*);
+    void setRenderer(RenderNamedFlowThread* parentFlowThread);
 
+    enum FlowState {
+        FlowStateCreated,
+        FlowStateNull
+    };
+
+    FlowState flowState() const { return m_parentFlowThread ? FlowStateCreated : FlowStateNull; }
+
+private:
+    WebKitNamedFlow(PassRefPtr<WebKitNamedFlowCollection>, const AtomicString&);
+
+    // The name of the flow thread as specified in CSS.
+    AtomicString m_flowThreadName;
+
+    RefPtr<WebKitNamedFlowCollection> m_flowManager;
     RenderNamedFlowThread* m_parentFlowThread;
+
+    FlowState m_state;
 };
 
 }
diff --git a/Source/WebCore/dom/WebKitNamedFlowCollection.cpp b/Source/WebCore/dom/WebKitNamedFlowCollection.cpp
new file mode 100644
index 0000000..b0cff11
--- /dev/null
+++ b/Source/WebCore/dom/WebKitNamedFlowCollection.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebKitNamedFlowCollection.h"
+
+#include "Document.h"
+#include "WebKitNamedFlow.h"
+
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+WebKitNamedFlowCollection::WebKitNamedFlowCollection(Document* doc)
+    : m_document(doc)
+{
+}
+
+WebKitNamedFlow* WebKitNamedFlowCollection::flowByName(const String& flowName)
+{
+    NamedFlowSet::iterator it = m_namedFlows.find<String, NamedFlowHashTranslator>(flowName);
+    if (it == m_namedFlows.end() || (*it)->flowState() == WebKitNamedFlow::FlowStateNull)
+        return 0;
+
+    return *it;
+}
+
+PassRefPtr<WebKitNamedFlow> WebKitNamedFlowCollection::ensureFlowWithName(const String& flowName)
+{
+    NamedFlowSet::iterator it = m_namedFlows.find<String, NamedFlowHashTranslator>(flowName);
+    if (it != m_namedFlows.end()) {
+        WebKitNamedFlow* namedFlow = *it;
+        ASSERT(namedFlow->flowState() == WebKitNamedFlow::FlowStateNull);
+
+        return namedFlow;
+    }
+
+    RefPtr<WebKitNamedFlow> newFlow = WebKitNamedFlow::create(this, flowName);
+    m_namedFlows.add(newFlow.get());
+
+    return newFlow.release();
+}
+
+void WebKitNamedFlowCollection::discardNamedFlow(WebKitNamedFlow* namedFlow)
+{
+    // The document is not valid anymore so the collection will be destroyed anyway.
+    if (!m_document)
+        return;
+
+    ASSERT(namedFlow->flowState() == WebKitNamedFlow::FlowStateNull);
+    ASSERT(m_namedFlows.contains(namedFlow));
+
+    m_namedFlows.remove(namedFlow);
+}
+
+void WebKitNamedFlowCollection::documentDestroyed()
+{
+    m_document = 0;
+}
+
+// The HashFunctions object used by the HashSet to compare between NamedFlows.
+// It is safe to set safeToCompareToEmptyOrDeleted because the HashSet will never contain null pointers or deleted values.
+struct WebKitNamedFlowCollection::NamedFlowHashFunctions {
+    static unsigned hash(WebKitNamedFlow* key) { return DefaultHash<String>::Hash::hash(key->name()); }
+    static bool equal(WebKitNamedFlow* a, WebKitNamedFlow* b) { return a->name() == b->name(); }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+// The HashTranslator is used to lookup a NamedFlow in the set using a name.
+struct WebKitNamedFlowCollection::NamedFlowHashTranslator {
+    static unsigned hash(const String& key) { return DefaultHash<String>::Hash::hash(key); }
+    static bool equal(WebKitNamedFlow* a, const String& b) { return a->name() == b; }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/WebKitNamedFlowCollection.h b/Source/WebCore/dom/WebKitNamedFlowCollection.h
new file mode 100644
index 0000000..130c6c8f
--- /dev/null
+++ b/Source/WebCore/dom/WebKitNamedFlowCollection.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef WebKitNamedFlowCollection_h
+#define WebKitNamedFlowCollection_h
+
+#include <wtf/Forward.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Document;
+class WebKitNamedFlow;
+
+class WebKitNamedFlowCollection : public RefCounted<WebKitNamedFlowCollection> {
+public:
+    static PassRefPtr<WebKitNamedFlowCollection> create(Document* doc) { return adoptRef(new WebKitNamedFlowCollection(doc)); }
+
+    WebKitNamedFlow* flowByName(const String&);
+    PassRefPtr<WebKitNamedFlow> ensureFlowWithName(const String&);
+
+    void discardNamedFlow(WebKitNamedFlow*);
+
+    void documentDestroyed();
+
+    Document* document() const { return m_document; }
+
+private:
+    WebKitNamedFlowCollection(Document*);
+
+    Document* m_document;
+
+    struct NamedFlowHashFunctions;
+    struct NamedFlowHashTranslator;
+
+    typedef ListHashSet<WebKitNamedFlow*, 1, NamedFlowHashFunctions> NamedFlowSet;
+
+    NamedFlowSet m_namedFlows;
+};
+
+} // namespace WebCore
+
+#endif // WebKitNamedFlowCollection_h
diff --git a/Source/WebCore/rendering/FlowThreadController.cpp b/Source/WebCore/rendering/FlowThreadController.cpp
index cf2207f..dc9432c 100644
--- a/Source/WebCore/rendering/FlowThreadController.cpp
+++ b/Source/WebCore/rendering/FlowThreadController.cpp
@@ -33,6 +33,8 @@
 
 #include "RenderFlowThread.h"
 #include "RenderNamedFlowThread.h"
+#include "WebKitNamedFlow.h"
+#include "WebKitNamedFlowCollection.h"
 #include <wtf/text/AtomicString.h>
 
 namespace WebCore {
@@ -65,7 +67,12 @@
         }
     }
 
-    RenderNamedFlowThread* flowRenderer = new (m_view->renderArena()) RenderNamedFlowThread(m_view->document(), name);
+    WebKitNamedFlowCollection* namedFlows = m_view->document()->namedFlows();
+
+    // Sanity check for the absence of a named flow in the "CREATED" state with the same name.
+    ASSERT(!namedFlows->flowByName(name));
+
+    RenderNamedFlowThread* flowRenderer = new (m_view->renderArena()) RenderNamedFlowThread(m_view->document(), namedFlows->ensureFlowWithName(name));
     flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(m_view->style()));
     m_renderNamedFlowThreadList->add(flowRenderer);
 
@@ -122,4 +129,10 @@
     m_mapNamedFlowContentNodes.remove(contentNode);
 }
 
+void FlowThreadController::removeFlowThread(RenderNamedFlowThread* flowThread)
+{
+    m_renderNamedFlowThreadList->remove(flowThread);
+    setIsRenderNamedFlowThreadOrderDirty(true);
+}
+
 } // namespace WebCore
diff --git a/Source/WebCore/rendering/FlowThreadController.h b/Source/WebCore/rendering/FlowThreadController.h
index 0c31769..d48c879 100644
--- a/Source/WebCore/rendering/FlowThreadController.h
+++ b/Source/WebCore/rendering/FlowThreadController.h
@@ -64,6 +64,8 @@
 
     void registerNamedFlowContentNode(Node*, RenderNamedFlowThread*);
     void unregisterNamedFlowContentNode(Node*);
+    
+    void removeFlowThread(RenderNamedFlowThread*);
 
 protected:
     FlowThreadController(RenderView*);
diff --git a/Source/WebCore/rendering/RenderNamedFlowThread.cpp b/Source/WebCore/rendering/RenderNamedFlowThread.cpp
index 088b872..227af7d 100644
--- a/Source/WebCore/rendering/RenderNamedFlowThread.cpp
+++ b/Source/WebCore/rendering/RenderNamedFlowThread.cpp
@@ -33,10 +33,16 @@
 
 namespace WebCore {
 
-RenderNamedFlowThread::RenderNamedFlowThread(Node* node, const AtomicString& name)
+RenderNamedFlowThread::RenderNamedFlowThread(Node* node, PassRefPtr<WebKitNamedFlow> namedFlow)
     : RenderFlowThread(node)
-    , m_flowThreadName(name)
+    , m_namedFlow(namedFlow)
 {
+    m_namedFlow->setRenderer(this);
+}
+
+RenderNamedFlowThread::~RenderNamedFlowThread()
+{
+    m_namedFlow->setRenderer(0);
 }
 
 const char* RenderNamedFlowThread::renderName() const
@@ -44,7 +50,6 @@
     return "RenderNamedFlowThread";
 }
 
-
 RenderObject* RenderNamedFlowThread::nextRendererForNode(Node* node) const
 {
     FlowThreadChildList::const_iterator it = m_flowThreadChildList.begin();
@@ -182,10 +187,14 @@
         removeDependencyOnFlowThread(renderRegion->parentNamedFlowThread());
     }
 
+    if (canBeDestroyed()) {
+        destroy();
+        return;
+    }
+
     invalidateRegions();
 }
 
-
 void RenderNamedFlowThread::checkInvalidRegions()
 {
     for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
@@ -245,14 +254,6 @@
     }
 }
 
-WebKitNamedFlow* RenderNamedFlowThread::ensureNamedFlow()
-{
-    if (!m_namedFlow)
-        m_namedFlow = WebKitNamedFlow::create(this);
-
-    return m_namedFlow.get();
-}
-
 // The content nodes list contains those nodes with -webkit-flow-into: flow.
 // An element with display:none should also be listed among those nodes.
 // The list of nodes is ordered.
@@ -283,6 +284,21 @@
     contentNode->clearInNamedFlow();
     m_contentNodes.remove(contentNode);
 
+    if (canBeDestroyed())
+        destroy();
+}
+
+const AtomicString& RenderNamedFlowThread::flowThreadName() const
+{
+    return m_namedFlow->name();
+}
+
+void RenderNamedFlowThread::willBeDestroyed()
+{
+    if (!documentBeingDestroyed())
+        view()->flowThreadController()->removeFlowThread(this);
+
+    RenderFlowThread::willBeDestroyed();
 }
 
 }
diff --git a/Source/WebCore/rendering/RenderNamedFlowThread.h b/Source/WebCore/rendering/RenderNamedFlowThread.h
index d0c8ca0..5e0d962 100644
--- a/Source/WebCore/rendering/RenderNamedFlowThread.h
+++ b/Source/WebCore/rendering/RenderNamedFlowThread.h
@@ -44,9 +44,10 @@
 
 class RenderNamedFlowThread : public RenderFlowThread {
 public:
-    RenderNamedFlowThread(Node*, const AtomicString&);
+    RenderNamedFlowThread(Node*, PassRefPtr<WebKitNamedFlow>);
+    virtual ~RenderNamedFlowThread();
 
-    AtomicString flowThreadName() const { return m_flowThreadName; }
+    const AtomicString& flowThreadName() const;
 
     RenderObject* nextRendererForNode(Node*) const;
     RenderObject* previousRendererForNode(Node*) const;
@@ -63,12 +64,14 @@
     virtual void addRegionToThread(RenderRegion*) OVERRIDE;
     virtual void removeRegionFromThread(RenderRegion*) OVERRIDE;
 
-    WebKitNamedFlow* ensureNamedFlow();
     void registerNamedFlowContentNode(Node*);
     void unregisterNamedFlowContentNode(Node*);
     const NamedFlowContentNodes& contentNodes() const { return m_contentNodes; }
     bool hasContentNode(Node* contentNode) const { ASSERT(contentNode); return m_contentNodes.contains(contentNode); }
 
+protected:
+    virtual void willBeDestroyed() OVERRIDE;
+
 private:
     virtual const char* renderName() const OVERRIDE;
     virtual bool isRenderNamedFlowThread() const OVERRIDE { return true; }
@@ -77,11 +80,9 @@
     void addDependencyOnFlowThread(RenderNamedFlowThread*);
     void removeDependencyOnFlowThread(RenderNamedFlowThread*);
     void checkInvalidRegions();
+    bool canBeDestroyed() const { return m_regionList.isEmpty() && m_contentNodes.isEmpty(); }
 
 private:
-    // The name of the flow thread as specified in CSS.
-    AtomicString m_flowThreadName;
-
     // Observer flow threads have invalid regions that depend on the state of this thread
     // to re-validate their regions. Keeping a set of observer threads make it easy
     // to notify them when a region was removed from this flow.