2008-05-29 Maciej Stachowiak <mjs@apple.com>
Reviewed by Dave Hyatt.
- speed up DHTML using lazy style resolution and rendere creation
This change introduces the concept of "lazy attach" - when a node
is lazy attached, then instead of resolving style and creating a
renderer right away, we just mark it as needing a style recalc.
The patch makes use of this mechanism when inserting nodes directly
using DOM APIs from script. For now this is only done for the
JavaScript language binding but could also be done for other
bindings in the future.
Lazy attach helps some common DHTML patterns - when a node is
added to the DOM, and then subsequently changed in a
style-affecting way, this causes an extra style recalc. This is a
fairly common pattern so it is better to be lazy.
* bindings/js/JSNodeCustom.cpp:
(WebCore::JSNode::insertBefore): Request lazy attach.
(WebCore::JSNode::replaceChild): ditto
(WebCore::JSNode::appendChild): ditto
* dom/ContainerNode.cpp:
(WebCore::ContainerNode::insertBefore): Support lazy attach.
(WebCore::ContainerNode::replaceChild): ditto
(WebCore::ContainerNode::appendChild): ditto
(WebCore::ContainerNode::detach): Clear "changed child" bit if still set.
* dom/ContainerNode.h:
* dom/Element.cpp:
(WebCore::Element::recalcStyle): Adjusted to properly reattach a
lazy-attached node.
* dom/Node.cpp:
(WebCore::Node::insertBefore): Extra parameter for lazy attach
(still doesn't do anything).
(WebCore::Node::replaceChild): ditto
(WebCore::Node::appendChild): ditto
(WebCore::Node::setChanged): Unrelated but obvious optimization -
stop marking ancestor as having a changed child once we already reach
an ancestor so marked.
(WebCore::outermostLazyAttachedAncestor): Helper function for lazyAttach.
(WebCore::Node::lazyAttach): Implement lazy attach.
(WebCore::Node::canLazyAttach): Virtual method - true for most nodes.
* dom/Node.h:
* dom/Text.cpp:
(WebCore::Text::recalcStyle): Properly handle the case of a reattached node.
* html/HTMLEmbedElement.h:
(WebCore::HTMLEmbedElement::canLazyAttach): Refuse lazy attach, since
plugins and frames do important work at rederer creation time.
* html/HTMLFrameElementBase.h:
(WebCore::HTMLFrameElementBase::canLazyAttach): Refuse lazy attach, since
plugins and frames do important work at rederer creation time.
* html/HTMLFrameSetElement.cpp:
(WebCore::HTMLFrameSetElement::recalcStyle): Change order so that
reattach works properly.
* html/HTMLObjectElement.h:
(WebCore::HTMLObjectElement::canLazyAttach): Refuse lazy attach, since
plugins and frames do important work at rederer creation time.
* html/HTMLOptGroupElement.cpp:
(WebCore::HTMLOptGroupElement::insertBefore): Pass along extra param.
(WebCore::HTMLOptGroupElement::replaceChild): ditto
(WebCore::HTMLOptGroupElement::appendChild): ditto
* html/HTMLOptGroupElement.h:
* html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::insertBefore): Pass along extra param.
(WebCore::HTMLSelectElement::replaceChild): ditto
(WebCore::HTMLSelectElement::appendChild): ditto
* html/HTMLSelectElement.h:
* svg/SVGLocatable.cpp:
(WebCore::SVGLocatable::getBBox): Add missing updateLayout call.
* svg/SVGTextContentElement.cpp:
(WebCore::SVGTextContentElement::getNumberOfChars): ditto
(WebCore::SVGTextContentElement::getComputedTextLength): ditto
(WebCore::SVGTextContentElement::getSubStringLength): ditto
(WebCore::SVGTextContentElement::getStartPositionOfChar): ditto
(WebCore::SVGTextContentElement::getEndPositionOfChar): ditto
(WebCore::SVGTextContentElement::getExtentOfChar): ditto
(WebCore::SVGTextContentElement::getRotationOfChar): ditto
(WebCore::SVGTextContentElement::getCharNumAtPosition): ditto
LayoutTests:
2008-05-29 Maciej Stachowiak <mjs@apple.com>
Reviewed by Dave Hyatt.
- Test cases for this change: "speed up DHTML using lazy style resolution and rendere creation"
* http/tests/misc/acid3-expected.txt:
* platform/mac/fast/dynamic/insert-before-table-part-in-continuation-expected.checksum:
* platform/mac/fast/dynamic/insert-before-table-part-in-continuation-expected.png:
* platform/mac/fast/dynamic/insert-before-table-part-in-continuation-expected.txt:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@34193
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2008-05-29 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Dave Hyatt.
+
+ - Test cases for this change: "speed up DHTML using lazy style resolution and rendere creation"
+
+ * http/tests/misc/acid3-expected.txt:
+ * platform/mac/fast/dynamic/insert-before-table-part-in-continuation-expected.checksum:
+ * platform/mac/fast/dynamic/insert-before-table-part-in-continuation-expected.png:
+ * platform/mac/fast/dynamic/insert-before-table-part-in-continuation-expected.txt:
+
2008-05-28 Oliver Hunt <oliver@apple.com>
Reviewed by Anders.
RenderBlock {H1} at (41,41) size 562x120
RenderText {#text} at (0,4) size 273x112
text run at (0,4) width 273: "Acid3"
- RenderBlock (anonymous) at (41,121) size 562x0
RenderBlock {DIV} at (41,121) size 562x312
RenderBlock {P} at (7,80) size 54x42 [bgcolor=#FF0000] [border: (1px solid #000000)]
RenderBlock {P} at (70,64) size 64x50 [bgcolor=#FFA500] [border: (1px solid #000000)]
-b848821df77004913ca9911a4295871d
\ No newline at end of file
+4cff5283c5881787befeab5eccf5c139
\ No newline at end of file
-layer at (0,0) size 785x742
+layer at (0,0) size 785x678
RenderView at (0,0) size 785x600
-layer at (0,0) size 785x742
- RenderBlock {HTML} at (0,0) size 785x742
- RenderBody {BODY} at (8,8) size 769x726
+layer at (0,0) size 785x678
+ RenderBlock {HTML} at (0,0) size 785x678
+ RenderBody {BODY} at (8,8) size 769x662
RenderBlock {P} at (0,0) size 769x18
RenderText {#text} at (0,0) size 53x18
text run at (0,0) width 53: "Test for "
text run at (0,54) width 122: "parent was a block."
RenderBlock {DIV} at (0,122) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
- RenderInline {SPAN} at (0,0) size 41x18
+ RenderInline {SPAN} at (0,0) size 128x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 41: "Text..."
+ RenderText {#text} at (41,0) size 87x18
+ text run at (41,0) width 87: "goes here and"
RenderBlock (anonymous) at (0,18) size 769x18
- RenderTable at (0,0) size 190x18
- RenderTableSection (anonymous) at (0,0) size 190x18
- RenderTableRow (anonymous) at (0,0) size 190x18
- RenderTableCell (anonymous) at (0,0) size 87x18 [r=0 c=0 rs=1 cs=1]
- RenderText {#text} at (0,0) size 87x18
- text run at (0,0) width 87: "goes here and"
- RenderTableCell {DIV} at (87,0) size 103x18 [r=0 c=1 rs=1 cs=1]
+ RenderTable at (0,0) size 103x18
+ RenderTableSection (anonymous) at (0,0) size 103x18
+ RenderTableRow (anonymous) at (0,0) size 103x18
+ RenderTableCell {DIV} at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (0,0) size 103x18
text run at (0,0) width 103: "...continues here"
RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 41x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 41: "Text..."
+ RenderInline {SPAN} at (0,0) size 0x18
RenderBlock (anonymous) at (0,18) size 769x18
- RenderTable at (0,0) size 104x18
- RenderTableSection (anonymous) at (0,0) size 104x18
- RenderTableRow (anonymous) at (0,0) size 104x18
- RenderTableCell (anonymous) at (0,0) size 1x0 [r=0 c=0 rs=1 cs=1]
- RenderInline {SPAN} at (0,0) size 0x0
- RenderTableCell {DIV} at (1,0) size 103x18 [r=0 c=1 rs=1 cs=1]
+ RenderTable at (0,0) size 103x18
+ RenderTableSection (anonymous) at (0,0) size 103x18
+ RenderTableRow (anonymous) at (0,0) size 103x18
+ RenderTableCell {DIV} at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (0,0) size 103x18
text run at (0,0) width 103: "...continues here"
RenderBlock (anonymous) at (0,36) size 769x0
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 41: "Text..."
RenderBlock (anonymous) at (0,18) size 769x18
- RenderTable at (0,0) size 104x18
- RenderTableSection (anonymous) at (0,0) size 104x18
- RenderTableRow (anonymous) at (0,0) size 104x18
- RenderTableCell (anonymous) at (0,14) size 1x0 [r=0 c=0 rs=1 cs=1]
- RenderBlock {DIV} at (0,0) size 1x0
- RenderTableCell {DIV} at (1,0) size 103x18 [r=0 c=1 rs=1 cs=1]
+ RenderTable at (0,0) size 103x18
+ RenderTableSection (anonymous) at (0,0) size 103x18
+ RenderTableRow (anonymous) at (0,0) size 103x18
+ RenderTableCell {DIV} at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (0,0) size 103x18
text run at (0,0) width 103: "...continues here"
+ RenderBlock {DIV} at (0,18) size 769x0
RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,302) size 769x54
+ RenderBlock {DIV} at (0,302) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
- RenderInline {SPAN} at (0,0) size 41x18
+ RenderInline {SPAN} at (0,0) size 128x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 41: "Text..."
- RenderBlock (anonymous) at (0,18) size 769x36
- RenderTable at (0,0) size 103x36
- RenderTableSection (anonymous) at (0,0) size 103x36
- RenderTableRow (anonymous) at (0,0) size 103x18
+ RenderText {#text} at (41,0) size 87x18
+ text run at (41,0) width 87: "goes here and"
+ RenderBlock (anonymous) at (0,18) size 769x18
+ RenderTable at (0,0) size 103x18
+ RenderTableSection (anonymous) at (0,0) size 103x18
+ RenderTableRow {DIV} at (0,0) size 103x18
RenderTableCell (anonymous) at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
- RenderText {#text} at (0,0) size 87x18
- text run at (0,0) width 87: "goes here and"
- RenderTableRow {DIV} at (0,18) size 103x18
- RenderTableCell (anonymous) at (0,18) size 103x18 [r=1 c=0 rs=1 cs=1]
RenderText {#text} at (0,0) size 103x18
text run at (0,0) width 103: "...continues here"
- RenderBlock (anonymous) at (0,54) size 769x0
+ RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,356) size 769x36
+ RenderBlock {DIV} at (0,338) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
RenderInline {SPAN} at (0,0) size 41x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 103: "...continues here"
RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,392) size 769x36
+ RenderBlock {DIV} at (0,374) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
RenderInline {SPAN} at (0,0) size 41x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 103: "...continues here"
RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,428) size 769x50
+ RenderBlock {DIV} at (0,410) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
RenderInline {SPAN} at (0,0) size 41x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 41: "Text..."
- RenderBlock (anonymous) at (0,18) size 769x32
- RenderTable at (0,0) size 103x32
- RenderTableSection (anonymous) at (0,0) size 103x32
- RenderTableRow (anonymous) at (0,0) size 103x14
- RenderTableCell (anonymous) at (0,0) size 103x0 [r=0 c=0 rs=1 cs=1]
- RenderInline {SPAN} at (0,0) size 0x0
- RenderTableRow {DIV} at (0,14) size 103x18
- RenderTableCell (anonymous) at (0,14) size 103x18 [r=1 c=0 rs=1 cs=1]
+ RenderInline {SPAN} at (0,0) size 0x18
+ RenderBlock (anonymous) at (0,18) size 769x18
+ RenderTable at (0,0) size 103x18
+ RenderTableSection (anonymous) at (0,0) size 103x18
+ RenderTableRow {DIV} at (0,0) size 103x18
+ RenderTableCell (anonymous) at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (0,0) size 103x18
text run at (0,0) width 103: "...continues here"
- RenderBlock (anonymous) at (0,50) size 769x0
+ RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,478) size 769x36
+ RenderBlock {DIV} at (0,446) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
RenderInline {SPAN} at (0,0) size 41x18
RenderText {#text} at (0,0) size 41x18
RenderBlock (anonymous) at (0,18) size 769x18
RenderTable at (0,0) size 103x18
RenderTableSection (anonymous) at (0,0) size 103x18
- RenderTableRow (anonymous) at (0,0) size 103x0
- RenderTableCell (anonymous) at (0,0) size 103x0 [r=0 c=0 rs=1 cs=1]
- RenderBlock {DIV} at (0,0) size 103x0
RenderTableRow {DIV} at (0,0) size 103x18
- RenderTableCell (anonymous) at (0,0) size 103x18 [r=1 c=0 rs=1 cs=1]
+ RenderTableCell (anonymous) at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (0,0) size 103x18
text run at (0,0) width 103: "...continues here"
+ RenderBlock {DIV} at (0,18) size 769x0
RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,514) size 769x54
+ RenderBlock {DIV} at (0,482) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
- RenderInline {SPAN} at (0,0) size 41x18
+ RenderInline {SPAN} at (0,0) size 128x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 41: "Text..."
- RenderBlock (anonymous) at (0,18) size 769x36
- RenderTable at (0,0) size 103x36
- RenderTableSection (anonymous) at (0,0) size 103x18
- RenderTableRow (anonymous) at (0,0) size 103x18
- RenderTableCell (anonymous) at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
- RenderText {#text} at (0,0) size 87x18
- text run at (0,0) width 87: "goes here and"
- RenderTableSection {DIV} at (0,18) size 103x18
+ RenderText {#text} at (41,0) size 87x18
+ text run at (41,0) width 87: "goes here and"
+ RenderBlock (anonymous) at (0,18) size 769x18
+ RenderTable at (0,0) size 103x18
+ RenderTableSection {DIV} at (0,0) size 103x18
RenderTableRow (anonymous) at (0,0) size 103x18
RenderTableCell (anonymous) at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (0,0) size 103x18
text run at (0,0) width 103: "...continues here"
- RenderBlock (anonymous) at (0,54) size 769x0
+ RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,568) size 769x36
+ RenderBlock {DIV} at (0,518) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
RenderInline {SPAN} at (0,0) size 41x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 103: "...continues here"
RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,604) size 769x36
+ RenderBlock {DIV} at (0,554) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
RenderInline {SPAN} at (0,0) size 41x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 103: "...continues here"
RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,640) size 769x50
+ RenderBlock {DIV} at (0,590) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
RenderInline {SPAN} at (0,0) size 41x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 41: "Text..."
- RenderBlock (anonymous) at (0,18) size 769x32
- RenderTable at (0,0) size 103x32
- RenderTableSection (anonymous) at (0,0) size 103x14
- RenderTableRow (anonymous) at (0,0) size 103x14
- RenderTableCell (anonymous) at (0,0) size 103x0 [r=0 c=0 rs=1 cs=1]
- RenderInline {SPAN} at (0,0) size 0x0
- RenderTableSection {DIV} at (0,14) size 103x18
+ RenderInline {SPAN} at (0,0) size 0x18
+ RenderBlock (anonymous) at (0,18) size 769x18
+ RenderTable at (0,0) size 103x18
+ RenderTableSection {DIV} at (0,0) size 103x18
RenderTableRow (anonymous) at (0,0) size 103x18
RenderTableCell (anonymous) at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (0,0) size 103x18
text run at (0,0) width 103: "...continues here"
- RenderBlock (anonymous) at (0,50) size 769x0
+ RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
- RenderBlock {DIV} at (0,690) size 769x36
+ RenderBlock {DIV} at (0,626) size 769x36
RenderBlock (anonymous) at (0,0) size 769x18
RenderInline {SPAN} at (0,0) size 41x18
RenderText {#text} at (0,0) size 41x18
text run at (0,0) width 41: "Text..."
RenderBlock (anonymous) at (0,18) size 769x18
RenderTable at (0,0) size 103x18
- RenderTableSection (anonymous) at (0,0) size 103x0
- RenderTableRow (anonymous) at (0,0) size 103x0
- RenderTableCell (anonymous) at (0,0) size 103x0 [r=0 c=0 rs=1 cs=1]
- RenderBlock {DIV} at (0,0) size 103x0
RenderTableSection {DIV} at (0,0) size 103x18
RenderTableRow (anonymous) at (0,0) size 103x18
RenderTableCell (anonymous) at (0,0) size 103x18 [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (0,0) size 103x18
text run at (0,0) width 103: "...continues here"
+ RenderBlock {DIV} at (0,18) size 769x0
RenderBlock (anonymous) at (0,36) size 769x0
RenderInline {SPAN} at (0,0) size 0x0
+2008-05-29 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Dave Hyatt.
+
+ - speed up DHTML using lazy style resolution and rendere creation
+
+ This change introduces the concept of "lazy attach" - when a node
+ is lazy attached, then instead of resolving style and creating a
+ renderer right away, we just mark it as needing a style recalc.
+
+ The patch makes use of this mechanism when inserting nodes directly
+ using DOM APIs from script. For now this is only done for the
+ JavaScript language binding but could also be done for other
+ bindings in the future.
+
+ Lazy attach helps some common DHTML patterns - when a node is
+ added to the DOM, and then subsequently changed in a
+ style-affecting way, this causes an extra style recalc. This is a
+ fairly common pattern so it is better to be lazy.
+
+ * bindings/js/JSNodeCustom.cpp:
+ (WebCore::JSNode::insertBefore): Request lazy attach.
+ (WebCore::JSNode::replaceChild): ditto
+ (WebCore::JSNode::appendChild): ditto
+ * dom/ContainerNode.cpp:
+ (WebCore::ContainerNode::insertBefore): Support lazy attach.
+ (WebCore::ContainerNode::replaceChild): ditto
+ (WebCore::ContainerNode::appendChild): ditto
+ (WebCore::ContainerNode::detach): Clear "changed child" bit if still set.
+ * dom/ContainerNode.h:
+ * dom/Element.cpp:
+ (WebCore::Element::recalcStyle): Adjusted to properly reattach a
+ lazy-attached node.
+ * dom/Node.cpp:
+ (WebCore::Node::insertBefore): Extra parameter for lazy attach
+ (still doesn't do anything).
+ (WebCore::Node::replaceChild): ditto
+ (WebCore::Node::appendChild): ditto
+ (WebCore::Node::setChanged): Unrelated but obvious optimization -
+ stop marking ancestor as having a changed child once we already reach
+ an ancestor so marked.
+ (WebCore::outermostLazyAttachedAncestor): Helper function for lazyAttach.
+ (WebCore::Node::lazyAttach): Implement lazy attach.
+ (WebCore::Node::canLazyAttach): Virtual method - true for most nodes.
+ * dom/Node.h:
+ * dom/Text.cpp:
+ (WebCore::Text::recalcStyle): Properly handle the case of a reattached node.
+ * html/HTMLEmbedElement.h:
+ (WebCore::HTMLEmbedElement::canLazyAttach): Refuse lazy attach, since
+ plugins and frames do important work at rederer creation time.
+ * html/HTMLFrameElementBase.h:
+ (WebCore::HTMLFrameElementBase::canLazyAttach): Refuse lazy attach, since
+ plugins and frames do important work at rederer creation time.
+ * html/HTMLFrameSetElement.cpp:
+ (WebCore::HTMLFrameSetElement::recalcStyle): Change order so that
+ reattach works properly.
+ * html/HTMLObjectElement.h:
+ (WebCore::HTMLObjectElement::canLazyAttach): Refuse lazy attach, since
+ plugins and frames do important work at rederer creation time.
+ * html/HTMLOptGroupElement.cpp:
+ (WebCore::HTMLOptGroupElement::insertBefore): Pass along extra param.
+ (WebCore::HTMLOptGroupElement::replaceChild): ditto
+ (WebCore::HTMLOptGroupElement::appendChild): ditto
+ * html/HTMLOptGroupElement.h:
+ * html/HTMLSelectElement.cpp:
+ (WebCore::HTMLSelectElement::insertBefore): Pass along extra param.
+ (WebCore::HTMLSelectElement::replaceChild): ditto
+ (WebCore::HTMLSelectElement::appendChild): ditto
+ * html/HTMLSelectElement.h:
+ * svg/SVGLocatable.cpp:
+ (WebCore::SVGLocatable::getBBox): Add missing updateLayout call.
+ * svg/SVGTextContentElement.cpp:
+ (WebCore::SVGTextContentElement::getNumberOfChars): ditto
+ (WebCore::SVGTextContentElement::getComputedTextLength): ditto
+ (WebCore::SVGTextContentElement::getSubStringLength): ditto
+ (WebCore::SVGTextContentElement::getStartPositionOfChar): ditto
+ (WebCore::SVGTextContentElement::getEndPositionOfChar): ditto
+ (WebCore::SVGTextContentElement::getExtentOfChar): ditto
+ (WebCore::SVGTextContentElement::getRotationOfChar): ditto
+ (WebCore::SVGTextContentElement::getCharNumAtPosition): ditto
+
2008-05-28 Ada Chan <adachan@apple.com>
<rdar://problem/5957036> REGRESSION (r31960): 20-30% slowdown in i-Bench JavaScript test on XP Home
JSValue* JSNode::insertBefore(ExecState* exec, const List& args)
{
ExceptionCode ec = 0;
- bool ok = impl()->insertBefore(toNode(args[0]), toNode(args[1]), ec);
+ bool ok = impl()->insertBefore(toNode(args[0]), toNode(args[1]), ec, true);
setDOMException(exec, ec);
if (ok)
return args[0];
JSValue* JSNode::replaceChild(ExecState* exec, const List& args)
{
ExceptionCode ec = 0;
- bool ok = impl()->replaceChild(toNode(args[0]), toNode(args[1]), ec);
+ bool ok = impl()->replaceChild(toNode(args[0]), toNode(args[1]), ec, true);
setDOMException(exec, ec);
if (ok)
return args[1];
JSValue* JSNode::appendChild(ExecState* exec, const List& args)
{
ExceptionCode ec = 0;
- bool ok = impl()->appendChild(toNode(args[0]), ec);
+ bool ok = impl()->appendChild(toNode(args[0]), ec, true);
setDOMException(exec, ec);
if (ok)
return args[0];
return m_lastChild;
}
-bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec)
+bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
{
// Check that this node is not "floating".
// If it is, it can be deleted as a side effect of sending mutation events.
// insertBefore(node, 0) is equivalent to appendChild(node)
if (!refChild)
- return appendChild(newChild, ec);
+ return appendChild(newChild, ec, shouldLazyAttach);
// Make sure adding the new child is OK.
checkAddChild(newChild.get(), ec);
dispatchChildInsertionEvents(child.get(), ec);
// Add child to the rendering tree.
- if (attached() && !child->attached() && child->parent() == this)
- child->attach();
+ if (attached() && !child->attached() && child->parent() == this) {
+ if (shouldLazyAttach)
+ child->lazyAttach();
+ else
+ child->attach();
+ }
child = nextChild.release();
}
return true;
}
-bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec)
+bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach)
{
// Check that this node is not "floating".
// If it is, it can be deleted as a side effect of sending mutation events.
dispatchChildInsertionEvents(child.get(), ec);
// Add child to the rendering tree
- if (attached() && !child->attached() && child->parent() == this)
- child->attach();
+ if (attached() && !child->attached() && child->parent() == this) {
+ if (shouldLazyAttach)
+ child->lazyAttach();
+ else
+ child->attach();
+ }
prev = child;
child = nextChild.release();
return true;
}
-bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec)
+bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
{
// Check that this node is not "floating".
// If it is, it can be deleted as a side effect of sending mutation events.
dispatchChildInsertionEvents(child.get(), ec);
// Add child to the rendering tree
- if (attached() && !child->attached() && child->parent() == this)
- child->attach();
+ if (attached() && !child->attached() && child->parent() == this) {
+ if (shouldLazyAttach)
+ child->lazyAttach();
+ else
+ child->attach();
+ }
child = nextChild.release();
}
{
for (Node* child = m_firstChild; child; child = child->nextSibling())
child->detach();
+ setHasChangedChild(false);
EventTargetNode::detach();
}
Node* firstChild() const { return m_firstChild; }
Node* lastChild() const { return m_lastChild; }
- virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&);
- virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&);
+ virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&, bool shouldLazyAttach = false);
+ virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&, bool shouldLazyAttach = false);
virtual bool removeChild(Node* child, ExceptionCode&);
- virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&);
+ virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&, bool shouldLazyAttach = false);
virtual ContainerNode* addChild(PassRefPtr<Node>);
bool hasChildNodes() const { return m_firstChild; }
if (hasParentStyle && (change >= Inherit || changed())) {
RenderStyle *newStyle = document()->styleSelector()->styleForElement(this);
StyleChange ch = diff(currentStyle, newStyle);
- if (ch == Detach) {
+ if (ch == Detach || !currentStyle) {
if (attached())
detach();
// ### Suboptimal. Style gets calculated again.
return n;
}
-bool Node::insertBefore(PassRefPtr<Node>, Node*, ExceptionCode& ec)
+bool Node::insertBefore(PassRefPtr<Node>, Node*, ExceptionCode& ec, bool)
{
ec = HIERARCHY_REQUEST_ERR;
return false;
}
-bool Node::replaceChild(PassRefPtr<Node>, Node*, ExceptionCode& ec)
+bool Node::replaceChild(PassRefPtr<Node>, Node*, ExceptionCode& ec, bool)
{
ec = HIERARCHY_REQUEST_ERR;
return false;
return false;
}
-bool Node::appendChild(PassRefPtr<Node>, ExceptionCode& ec)
+bool Node::appendChild(PassRefPtr<Node>, ExceptionCode& ec, bool)
{
ec = HIERARCHY_REQUEST_ERR;
return false;
m_styleChange = changeType;
if (m_styleChange != NoStyleChange) {
- for (Node* p = parentNode(); p; p = p->parentNode())
+ for (Node* p = parentNode(); p && !p->hasChangedChild(); p = p->parentNode())
p->setHasChangedChild(true);
document()->setDocumentChanged(true);
}
}
+static Node* outermostLazyAttachedAncestor(Node* start)
+{
+ Node* p = start;
+ for (Node* next = p->parentNode(); !next->renderer(); p = next, next = next->parentNode()) {}
+ return p;
+}
+
+void Node::lazyAttach()
+{
+ bool mustDoFullAttach = false;
+
+ for (Node* n = this; n; n = n->traverseNextNode(this)) {
+ if (!n->canLazyAttach()) {
+ mustDoFullAttach = true;
+ break;
+ }
+
+ if (n->firstChild())
+ n->setHasChangedChild(true);
+ n->m_styleChange = FullStyleChange;
+ n->m_attached = true;
+ }
+
+ if (mustDoFullAttach) {
+ Node* lazyAttachedAncestor = outermostLazyAttachedAncestor(this);
+ if (lazyAttachedAncestor->attached())
+ lazyAttachedAncestor->detach();
+ lazyAttachedAncestor->attach();
+ } else {
+ for (Node* p = parentNode(); p && !p->hasChangedChild(); p = p->parentNode())
+ p->setHasChangedChild(true);
+ document()->setDocumentChanged(true);
+ }
+}
+
+bool Node::canLazyAttach()
+{
+ return shadowAncestorNode() == this;
+}
+
bool Node::isFocusable() const
{
return m_tabIndexSetExplicitly;
// These should all actually return a node, but this is only important for language bindings,
// which will already know and hold a ref on the right node to return. Returning bool allows
// these methods to be more efficient since they don't need to return a ref
- virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&);
- virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&);
+ virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&, bool shouldLazyAttach = false);
+ virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&, bool shouldLazyAttach = false);
virtual bool removeChild(Node* child, ExceptionCode&);
- virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&);
+ virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&, bool shouldLazyAttach = false);
virtual void remove(ExceptionCode&);
bool hasChildNodes() const { return firstChild(); }
void setInActiveChain(bool b = true) { m_inActiveChain = b; }
void setChanged(StyleChangeType changeType = FullStyleChange);
+ void lazyAttach();
+ virtual bool canLazyAttach();
+
virtual void setFocus(bool b = true) { m_focused = b; }
virtual void setActive(bool b = true, bool pause=false) { m_active = b; }
virtual void setHovered(bool b = true) { m_hovered = b; }
if (renderer())
renderer()->setStyle(parentNode()->renderer()->style());
}
- if (changed() && renderer() && renderer()->isText())
- static_cast<RenderText*>(renderer())->setText(m_data);
+ if (changed()) {
+ if (renderer()) {
+ if (renderer()->isText())
+ static_cast<RenderText*>(renderer())->setText(m_data);
+ } else {
+ if (attached())
+ detach();
+ attach();
+ }
+ }
setChanged(NoStyleChange);
}
virtual void parseMappedAttribute(MappedAttribute*);
virtual void attach();
+ virtual bool canLazyAttach() { return false; }
virtual void detach();
virtual bool rendererIsNeeded(RenderStyle*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual void removedFromDocument();
virtual void attach();
+ virtual bool canLazyAttach() { return false; }
KURL location() const;
void setLocation(const String&);
void HTMLFrameSetElement::recalcStyle(StyleChange ch)
{
+ HTMLElement::recalcStyle(ch);
if (changed() && renderer()) {
renderer()->setNeedsLayout(true);
setChanged(NoStyleChange);
}
- HTMLElement::recalcStyle(ch);
}
String HTMLFrameSetElement::cols() const
virtual void parseMappedAttribute(MappedAttribute*);
virtual void attach();
+ virtual bool canLazyAttach() { return false; }
virtual bool rendererIsNeeded(RenderStyle*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual void finishParsingChildren();
return optgroup;
}
-bool HTMLOptGroupElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec)
+bool HTMLOptGroupElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
{
- bool result = HTMLGenericFormElement::insertBefore(newChild, refChild, ec);
+ bool result = HTMLGenericFormElement::insertBefore(newChild, refChild, ec, shouldLazyAttach);
if (result)
recalcSelectOptions();
return result;
}
-bool HTMLOptGroupElement::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec)
+bool HTMLOptGroupElement::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach)
{
- bool result = HTMLGenericFormElement::replaceChild(newChild, oldChild, ec);
+ bool result = HTMLGenericFormElement::replaceChild(newChild, oldChild, ec, shouldLazyAttach);
if (result)
recalcSelectOptions();
return result;
return result;
}
-bool HTMLOptGroupElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec)
+bool HTMLOptGroupElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
{
- bool result = HTMLGenericFormElement::appendChild(newChild, ec);
+ bool result = HTMLGenericFormElement::appendChild(newChild, ec, shouldLazyAttach);
if (result)
recalcSelectOptions();
return result;
virtual RenderStyle* renderStyle() const { return m_style; }
virtual void setRenderStyle(RenderStyle*);
- virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&);
- virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&);
+ virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&, bool shouldLazyAttach = false);
+ virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&, bool shouldLazyAttach = false);
virtual bool removeChild(Node* child, ExceptionCode&);
- virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&);
+ virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&, bool shouldLazyAttach = false);
virtual bool removeChildren();
virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
setChanged();
}
-bool HTMLSelectElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec)
+bool HTMLSelectElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
{
- bool result = HTMLFormControlElementWithState::insertBefore(newChild, refChild, ec);
+ bool result = HTMLFormControlElementWithState::insertBefore(newChild, refChild, ec, shouldLazyAttach);
if (result)
setRecalcListItems();
return result;
}
-bool HTMLSelectElement::replaceChild(PassRefPtr<Node> newChild, Node *oldChild, ExceptionCode& ec)
+bool HTMLSelectElement::replaceChild(PassRefPtr<Node> newChild, Node *oldChild, ExceptionCode& ec, bool shouldLazyAttach)
{
- bool result = HTMLFormControlElementWithState::replaceChild(newChild, oldChild, ec);
+ bool result = HTMLFormControlElementWithState::replaceChild(newChild, oldChild, ec, shouldLazyAttach);
if (result)
setRecalcListItems();
return result;
return result;
}
-bool HTMLSelectElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec)
+bool HTMLSelectElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
{
- bool result = HTMLFormControlElementWithState::appendChild(newChild, ec);
+ bool result = HTMLFormControlElementWithState::appendChild(newChild, ec, shouldLazyAttach);
if (result)
setRecalcListItems();
return result;
virtual bool saveState(String& value) const;
virtual void restoreState(const String&);
- virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&);
- virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&);
+ virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&, bool shouldLazyAttach = false);
+ virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&, bool shouldLazyAttach = false);
virtual bool removeChild(Node* child, ExceptionCode&);
- virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&);
+ virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&, bool shouldLazyAttach = false);
virtual bool removeChildren();
virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
{
FloatRect bboxRect;
+ e->document()->updateLayoutIgnorePendingStylesheets();
+
if (e && e->renderer()) {
// Need this to make sure we have render object dimensions.
// See bug 11686.
- e->document()->updateLayoutIgnorePendingStylesheets();
bboxRect = e->renderer()->relativeBBox(false);
}
long SVGTextContentElement::getNumberOfChars() const
{
+ document()->updateLayoutIgnorePendingStylesheets();
+
return executeTextQuery(this, SVGInlineTextBoxQueryWalker::NumberOfCharacters).longResult();
}
float SVGTextContentElement::getComputedTextLength() const
{
+ document()->updateLayoutIgnorePendingStylesheets();
+
return executeTextQuery(this, SVGInlineTextBoxQueryWalker::TextLength).floatResult();
}
float SVGTextContentElement::getSubStringLength(long charnum, long nchars, ExceptionCode& ec) const
{
+ document()->updateLayoutIgnorePendingStylesheets();
+
// Differences to SVG 1.1 spec, as the spec is clearly wrong. TODO: Raise SVG WG issue!
// #1: We accept a 'long nchars' parameter instead of 'unsigned long nchars' to be able
// to catch cases where someone called us with a negative 'nchars' value - in those
FloatPoint SVGTextContentElement::getStartPositionOfChar(long charnum, ExceptionCode& ec) const
{
+ document()->updateLayoutIgnorePendingStylesheets();
+
if (charnum < 0 || charnum > getNumberOfChars()) {
ec = INDEX_SIZE_ERR;
return FloatPoint();
FloatPoint SVGTextContentElement::getEndPositionOfChar(long charnum, ExceptionCode& ec) const
{
+ document()->updateLayoutIgnorePendingStylesheets();
+
if (charnum < 0 || charnum > getNumberOfChars()) {
ec = INDEX_SIZE_ERR;
return FloatPoint();
FloatRect SVGTextContentElement::getExtentOfChar(long charnum, ExceptionCode& ec) const
{
+ document()->updateLayoutIgnorePendingStylesheets();
+
if (charnum < 0 || charnum > getNumberOfChars()) {
ec = INDEX_SIZE_ERR;
return FloatRect();
float SVGTextContentElement::getRotationOfChar(long charnum, ExceptionCode& ec) const
{
+ document()->updateLayoutIgnorePendingStylesheets();
+
if (charnum < 0 || charnum > getNumberOfChars()) {
ec = INDEX_SIZE_ERR;
return 0.0f;
long SVGTextContentElement::getCharNumAtPosition(const FloatPoint& point) const
{
+ document()->updateLayoutIgnorePendingStylesheets();
+
return executeTextQuery(this, SVGInlineTextBoxQueryWalker::CharacterNumberAtPosition, 0.0f, 0.0f, point).longResult();
}