mirror of
https://github.com/servo/servo.git
synced 2025-06-19 06:38:59 +01:00
Auto merge of #26398 - Eijebong:fast-path-set-inner-html, r=jdm
Add a fast path in Element::SetInnerHTML when the value is small and trivial text Inspired from gecko which has a similar fast path. This makes innerHTML more than 10 times faster for this case. Fixes #25892
This commit is contained in:
commit
271ff16028
13 changed files with 89 additions and 24 deletions
|
@ -2449,8 +2449,6 @@ impl ElementMethods for Element {
|
||||||
|
|
||||||
/// <https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML>
|
/// <https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML>
|
||||||
fn SetInnerHTML(&self, value: DOMString) -> ErrorResult {
|
fn SetInnerHTML(&self, value: DOMString) -> ErrorResult {
|
||||||
// Step 1.
|
|
||||||
let frag = self.parse_fragment(value)?;
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
// https://github.com/w3c/DOM-Parsing/issues/1
|
// https://github.com/w3c/DOM-Parsing/issues/1
|
||||||
let target = if let Some(template) = self.downcast::<HTMLTemplateElement>() {
|
let target = if let Some(template) = self.downcast::<HTMLTemplateElement>() {
|
||||||
|
@ -2458,6 +2456,23 @@ impl ElementMethods for Element {
|
||||||
} else {
|
} else {
|
||||||
DomRoot::from_ref(self.upcast())
|
DomRoot::from_ref(self.upcast())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Fast path for when the value is small, doesn't contain any markup and doesn't require
|
||||||
|
// extra work to set innerHTML.
|
||||||
|
if !self.node.has_weird_parser_insertion_mode() &&
|
||||||
|
value.len() < 100 &&
|
||||||
|
!value
|
||||||
|
.as_bytes()
|
||||||
|
.iter()
|
||||||
|
.any(|c| matches!(*c, b'&' | b'\0' | b'<' | b'\r'))
|
||||||
|
{
|
||||||
|
Node::SetTextContent(&target, Some(value));
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1.
|
||||||
|
let frag = self.parse_fragment(value)?;
|
||||||
|
|
||||||
Node::replace_all(Some(frag.upcast()), &target);
|
Node::replace_all(Some(frag.upcast()), &target);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::HTMLFrameSetElementBinding::HTMLFrameSetElementMethods;
|
use crate::dom::bindings::codegen::Bindings::HTMLFrameSetElementBinding::HTMLFrameSetElementMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
|
@ -33,12 +34,14 @@ impl HTMLFrameSetElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLFrameSetElement> {
|
) -> DomRoot<HTMLFrameSetElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLFrameSetElement::new_inherited(
|
Box::new(HTMLFrameSetElement::new_inherited(
|
||||||
local_name, prefix, document,
|
local_name, prefix, document,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,13 @@ impl HTMLHeadElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLHeadElement> {
|
) -> DomRoot<HTMLHeadElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLHeadElement::new_inherited(local_name, prefix, document)),
|
Box::new(HTMLHeadElement::new_inherited(local_name, prefix, document)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#meta-referrer>
|
/// <https://html.spec.whatwg.org/multipage/#meta-referrer>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
|
@ -32,9 +33,12 @@ impl HTMLHtmlElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLHtmlElement> {
|
) -> DomRoot<HTMLHtmlElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLHtmlElement::new_inherited(localName, prefix, document)),
|
Box::new(HTMLHtmlElement::new_inherited(localName, prefix, document)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,12 +93,15 @@ impl HTMLSelectElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLSelectElement> {
|
) -> DomRoot<HTMLSelectElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLSelectElement::new_inherited(
|
Box::new(HTMLSelectElement::new_inherited(
|
||||||
local_name, prefix, document,
|
local_name, prefix, document,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#concept-select-option-list
|
// https://html.spec.whatwg.org/multipage/#concept-select-option-list
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
|
@ -31,11 +32,14 @@ impl HTMLTableCaptionElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLTableCaptionElement> {
|
) -> DomRoot<HTMLTableCaptionElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLTableCaptionElement::new_inherited(
|
Box::new(HTMLTableCaptionElement::new_inherited(
|
||||||
local_name, prefix, document,
|
local_name, prefix, document,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,12 +45,15 @@ impl HTMLTableCellElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLTableCellElement> {
|
) -> DomRoot<HTMLTableCellElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLTableCellElement::new_inherited(
|
Box::new(HTMLTableCellElement::new_inherited(
|
||||||
local_name, prefix, document,
|
local_name, prefix, document,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
|
@ -31,11 +32,14 @@ impl HTMLTableColElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLTableColElement> {
|
) -> DomRoot<HTMLTableColElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLTableColElement::new_inherited(
|
Box::new(HTMLTableColElement::new_inherited(
|
||||||
local_name, prefix, document,
|
local_name, prefix, document,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,12 +70,15 @@ impl HTMLTableElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLTableElement> {
|
) -> DomRoot<HTMLTableElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLTableElement::new_inherited(
|
Box::new(HTMLTableElement::new_inherited(
|
||||||
local_name, prefix, document,
|
local_name, prefix, document,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_border(&self) -> Option<u32> {
|
pub fn get_border(&self) -> Option<u32> {
|
||||||
|
|
|
@ -57,12 +57,15 @@ impl HTMLTableRowElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLTableRowElement> {
|
) -> DomRoot<HTMLTableRowElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLTableRowElement::new_inherited(
|
Box::new(HTMLTableRowElement::new_inherited(
|
||||||
local_name, prefix, document,
|
local_name, prefix, document,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine the index for this `HTMLTableRowElement` within the given
|
/// Determine the index for this `HTMLTableRowElement` within the given
|
||||||
|
|
|
@ -42,12 +42,15 @@ impl HTMLTableSectionElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLTableSectionElement> {
|
) -> DomRoot<HTMLTableSectionElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLTableSectionElement::new_inherited(
|
Box::new(HTMLTableSectionElement::new_inherited(
|
||||||
local_name, prefix, document,
|
local_name, prefix, document,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,12 +41,15 @@ impl HTMLTemplateElement {
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
) -> DomRoot<HTMLTemplateElement> {
|
) -> DomRoot<HTMLTemplateElement> {
|
||||||
Node::reflect_node(
|
let n = Node::reflect_node(
|
||||||
Box::new(HTMLTemplateElement::new_inherited(
|
Box::new(HTMLTemplateElement::new_inherited(
|
||||||
local_name, prefix, document,
|
local_name, prefix, document,
|
||||||
)),
|
)),
|
||||||
document,
|
document,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
n.upcast::<Node>().set_weird_parser_insertion_mode();
|
||||||
|
n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,10 @@ bitflags! {
|
||||||
|
|
||||||
/// Specifies whether this node's shadow-including root is a document.
|
/// Specifies whether this node's shadow-including root is a document.
|
||||||
const IS_CONNECTED = 1 << 10;
|
const IS_CONNECTED = 1 << 10;
|
||||||
|
|
||||||
|
/// Whether this node has a weird parser insertion mode. i.e whether setting innerHTML
|
||||||
|
/// needs extra work or not
|
||||||
|
const HAS_WEIRD_PARSER_INSERTION_MODE = 1 << 11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,6 +558,16 @@ impl Node {
|
||||||
self.flags.get().contains(NodeFlags::IS_IN_SHADOW_TREE)
|
self.flags.get().contains(NodeFlags::IS_IN_SHADOW_TREE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_weird_parser_insertion_mode(&self) -> bool {
|
||||||
|
self.flags
|
||||||
|
.get()
|
||||||
|
.contains(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_weird_parser_insertion_mode(&self) {
|
||||||
|
self.set_flag(NodeFlags::HAS_WEIRD_PARSER_INSERTION_MODE, true)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_connected(&self) -> bool {
|
pub fn is_connected(&self) -> bool {
|
||||||
self.flags.get().contains(NodeFlags::IS_CONNECTED)
|
self.flags.get().contains(NodeFlags::IS_CONNECTED)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue