Bug 922681 - Add SetInnerHTML fast path for short strings with no markup. r=bz

This commit is contained in:
Jan de Mooij
2013-12-17 14:58:32 +01:00
parent bab09875ca
commit efb84633a2
12 changed files with 55 additions and 0 deletions

View File

@@ -1307,6 +1307,9 @@ private:
NodeHandlingClick, NodeHandlingClick,
// Set if the node has had :hover selectors matched against it // Set if the node has had :hover selectors matched against it
NodeHasRelevantHoverRules, NodeHasRelevantHoverRules,
// Set if the element has a parser insertion mode other than "in body",
// per the HTML5 "Parse state" section.
ElementHasWeirdParserInsertionMode,
// Guard value // Guard value
BooleanFlagCount BooleanFlagCount
}; };
@@ -1466,6 +1469,9 @@ protected:
void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); } void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
bool HasLockedStyleStates() const bool HasLockedStyleStates() const
{ return GetBoolFlag(ElementHasLockedStyleStates); } { return GetBoolFlag(ElementHasLockedStyleStates); }
void SetHasWeirdParserInsertionMode() { SetBoolFlag(ElementHasWeirdParserInsertionMode); }
bool HasWeirdParserInsertionMode() const
{ return GetBoolFlag(ElementHasWeirdParserInsertionMode); }
bool HandlingClick() const { return GetBoolFlag(NodeHandlingClick); } bool HandlingClick() const { return GetBoolFlag(NodeHandlingClick); }
void SetHandlingClick() { SetBoolFlag(NodeHandlingClick); } void SetHandlingClick() { SetBoolFlag(NodeHandlingClick); }
void ClearHandlingClick() { ClearBoolFlag(NodeHandlingClick); } void ClearHandlingClick() { ClearBoolFlag(NodeHandlingClick); }

View File

@@ -2613,6 +2613,28 @@ FragmentOrElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup)
} }
} }
static bool
ContainsMarkup(const nsAString& aStr)
{
// Note: we can't use FindCharInSet because null is one of the characters we
// want to search for.
const PRUnichar* start = aStr.BeginReading();
const PRUnichar* end = aStr.EndReading();
while (start != end) {
PRUnichar c = *start;
if (c == PRUnichar('<') ||
c == PRUnichar('&') ||
c == PRUnichar('\r') ||
c == PRUnichar('\0')) {
return true;
}
++start;
}
return false;
}
void void
FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError) FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError)
{ {
@@ -2625,6 +2647,19 @@ FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult
target = frag; target = frag;
} }
// Fast-path for strings with no markup. Limit this to short strings, to
// avoid ContainsMarkup taking too long. The choice for 100 is based on
// gut feeling.
//
// Don't do this for elements with a weird parser insertion mode, for
// instance setting innerHTML = "" on a <html> element should add the
// optional <head> and <body> elements.
if (!target->HasWeirdParserInsertionMode() &&
aInnerHTML.Length() < 100 && !ContainsMarkup(aInnerHTML)) {
aError = nsContentUtils::SetNodeTextContent(target, aInnerHTML, false);
return;
}
nsIDocument* doc = target->OwnerDoc(); nsIDocument* doc = target->OwnerDoc();
// Batch possible DOMSubtreeModified events. // Batch possible DOMSubtreeModified events.

View File

@@ -52,6 +52,7 @@ public:
mNumCols(0), mNumCols(0),
mCurrentRowColHint(NS_STYLE_HINT_REFLOW) mCurrentRowColHint(NS_STYLE_HINT_REFLOW)
{ {
SetHasWeirdParserInsertionMode();
} }
virtual ~HTMLFrameSetElement(); virtual ~HTMLFrameSetElement();

View File

@@ -116,6 +116,8 @@ HTMLSelectElement::HTMLSelectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
mOptGroupCount(0), mOptGroupCount(0),
mSelectedIndex(-1) mSelectedIndex(-1)
{ {
SetHasWeirdParserInsertionMode();
// DoneAddingChildren() will be called later if it's from the parser, // DoneAddingChildren() will be called later if it's from the parser,
// otherwise it is // otherwise it is

View File

@@ -32,6 +32,10 @@ public:
HTMLSharedElement(already_AddRefed<nsINodeInfo> aNodeInfo) HTMLSharedElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo) : nsGenericHTMLElement(aNodeInfo)
{ {
if (mNodeInfo->Equals(nsGkAtoms::head) ||
mNodeInfo->Equals(nsGkAtoms::html)) {
SetHasWeirdParserInsertionMode();
}
} }
virtual ~HTMLSharedElement(); virtual ~HTMLSharedElement();

View File

@@ -19,6 +19,7 @@ public:
HTMLTableCaptionElement(already_AddRefed<nsINodeInfo> aNodeInfo) HTMLTableCaptionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo) : nsGenericHTMLElement(aNodeInfo)
{ {
SetHasWeirdParserInsertionMode();
} }
virtual ~HTMLTableCaptionElement(); virtual ~HTMLTableCaptionElement();

View File

@@ -23,6 +23,7 @@ public:
HTMLTableCellElement(already_AddRefed<nsINodeInfo> aNodeInfo) HTMLTableCellElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo) : nsGenericHTMLElement(aNodeInfo)
{ {
SetHasWeirdParserInsertionMode();
} }
virtual ~HTMLTableCellElement(); virtual ~HTMLTableCellElement();

View File

@@ -17,6 +17,7 @@ public:
HTMLTableColElement(already_AddRefed<nsINodeInfo> aNodeInfo) HTMLTableColElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo) : nsGenericHTMLElement(aNodeInfo)
{ {
SetHasWeirdParserInsertionMode();
} }
virtual ~HTMLTableColElement(); virtual ~HTMLTableColElement();

View File

@@ -286,6 +286,7 @@ HTMLTableElement::HTMLTableElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo), : nsGenericHTMLElement(aNodeInfo),
mTableInheritedAttributes(TABLE_ATTRS_DIRTY) mTableInheritedAttributes(TABLE_ATTRS_DIRTY)
{ {
SetHasWeirdParserInsertionMode();
} }
HTMLTableElement::~HTMLTableElement() HTMLTableElement::~HTMLTableElement()

View File

@@ -22,6 +22,7 @@ public:
HTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo) HTMLTableRowElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo) : nsGenericHTMLElement(aNodeInfo)
{ {
SetHasWeirdParserInsertionMode();
} }
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLTableRowElement, tr) NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLTableRowElement, tr)

View File

@@ -18,6 +18,7 @@ public:
HTMLTableSectionElement(already_AddRefed<nsINodeInfo> aNodeInfo) HTMLTableSectionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo) : nsGenericHTMLElement(aNodeInfo)
{ {
SetHasWeirdParserInsertionMode();
} }
// nsISupports // nsISupports

View File

@@ -33,6 +33,7 @@ namespace dom {
HTMLTemplateElement::HTMLTemplateElement(already_AddRefed<nsINodeInfo> aNodeInfo) HTMLTemplateElement::HTMLTemplateElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo) : nsGenericHTMLElement(aNodeInfo)
{ {
SetHasWeirdParserInsertionMode();
} }
nsresult nsresult