aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/wrapper.rs2
-rw-r--r--components/layout_2020/dom_traversal.rs14
-rw-r--r--components/layout_2020/flow/construct.rs8
-rw-r--r--components/layout_thread/dom_wrapper.rs8
-rw-r--r--components/layout_thread_2020/dom_wrapper.rs8
-rw-r--r--components/script/dom/attr.rs27
-rw-r--r--components/script/dom/characterdata.rs9
-rw-r--r--components/script/dom/element.rs10
-rwxr-xr-xcomponents/script/dom/htmlinputelement.rs55
-rwxr-xr-xcomponents/script/dom/htmltextareaelement.rs25
-rw-r--r--components/script/dom/node.rs13
-rw-r--r--components/script_layout_interface/wrapper_traits.rs3
12 files changed, 101 insertions, 81 deletions
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs
index af8d6b6a0c7..60eace1f16a 100644
--- a/components/layout/wrapper.rs
+++ b/components/layout/wrapper.rs
@@ -130,7 +130,7 @@ where
});
}
- TextContent::Text(self.node_text_content().into_boxed_str())
+ TextContent::Text(self.node_text_content().into_owned().into_boxed_str())
}
fn restyle_damage(self) -> RestyleDamage {
diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs
index 020282f50ff..ef4570a85bb 100644
--- a/components/layout_2020/dom_traversal.rs
+++ b/components/layout_2020/dom_traversal.rs
@@ -17,6 +17,7 @@ use script_layout_interface::wrapper_traits::{
};
use script_layout_interface::HTMLCanvasDataSource;
use servo_arc::Arc as ServoArc;
+use std::borrow::Cow;
use std::marker::PhantomData as marker;
use std::sync::{Arc, Mutex};
use style::dom::{OpaqueNode, TNode};
@@ -59,7 +60,12 @@ pub(super) trait TraversalHandler<'dom, Node>
where
Node: 'dom,
{
- fn handle_text(&mut self, node: Node, text: String, parent_style: &ServoArc<ComputedValues>);
+ fn handle_text(
+ &mut self,
+ node: Node,
+ text: Cow<'dom, str>,
+ parent_style: &ServoArc<ComputedValues>,
+ );
/// Or pseudo-element
fn handle_element(
@@ -166,7 +172,7 @@ fn traverse_pseudo_element_contents<'dom, Node>(
for item in items {
match item {
PseudoElementContentItem::Text(text) => {
- handler.handle_text(node, text, pseudo_element_style)
+ handler.handle_text(node, text.into(), pseudo_element_style)
},
PseudoElementContentItem::Replaced(contents) => {
let item_style = anonymous_style.get_or_insert_with(|| {
@@ -351,7 +357,7 @@ impl Drop for BoxSlot<'_> {
pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode<'dom> + Send + Sync {
fn is_element(self) -> bool;
- fn as_text(self) -> Option<String>;
+ fn as_text(self) -> Option<Cow<'dom, str>>;
/// Returns the image if it’s loaded, and its size in image pixels
/// adjusted for `image_density`.
@@ -378,7 +384,7 @@ where
self.to_threadsafe().as_element().is_some()
}
- fn as_text(self) -> Option<String> {
+ fn as_text(self) -> Option<Cow<'dom, str>> {
if self.is_text_node() {
Some(self.to_threadsafe().node_text_content())
} else {
diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs
index fe9465f775e..186a4b4d4ff 100644
--- a/components/layout_2020/flow/construct.rs
+++ b/components/layout_2020/flow/construct.rs
@@ -16,6 +16,7 @@ use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, D
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use rayon_croissant::ParallelIteratorExt;
use servo_arc::Arc;
+use std::borrow::Cow;
use std::convert::{TryFrom, TryInto};
use style::properties::ComputedValues;
use style::selector_parser::PseudoElement;
@@ -286,7 +287,12 @@ where
}
}
- fn handle_text(&mut self, node: Node, input: String, parent_style: &Arc<ComputedValues>) {
+ fn handle_text(
+ &mut self,
+ node: Node,
+ input: Cow<'dom, str>,
+ parent_style: &Arc<ComputedValues>,
+ ) {
let (leading_whitespace, mut input) = self.handle_leading_whitespace(&input);
if leading_whitespace || !input.is_empty() {
// This text node should be pushed either to the next ongoing
diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs
index f2ba0a6fafa..e3197c8e78a 100644
--- a/components/layout_thread/dom_wrapper.rs
+++ b/components/layout_thread/dom_wrapper.rs
@@ -67,6 +67,7 @@ use selectors::sink::Push;
use servo_arc::{Arc, ArcBorrow};
use servo_atoms::Atom;
use servo_url::ServoUrl;
+use std::borrow::Cow;
use std::fmt;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
@@ -828,7 +829,7 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
.dom_children()
.all(|node| match node.script_type_id() {
NodeTypeId::Element(..) => false,
- NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => unsafe {
+ NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
node.node.downcast().unwrap().data_for_layout().is_empty()
},
_ => true,
@@ -1110,9 +1111,8 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
self.node
}
- fn node_text_content(&self) -> String {
- let this = unsafe { self.get_jsmanaged() };
- return this.text_content();
+ fn node_text_content(self) -> Cow<'ln, str> {
+ unsafe { self.get_jsmanaged().text_content() }
}
fn selection(&self) -> Option<Range<ByteIndex>> {
diff --git a/components/layout_thread_2020/dom_wrapper.rs b/components/layout_thread_2020/dom_wrapper.rs
index d8aa7b05360..7d57d7f511e 100644
--- a/components/layout_thread_2020/dom_wrapper.rs
+++ b/components/layout_thread_2020/dom_wrapper.rs
@@ -67,6 +67,7 @@ use selectors::sink::Push;
use servo_arc::{Arc, ArcBorrow};
use servo_atoms::Atom;
use servo_url::ServoUrl;
+use std::borrow::Cow;
use std::fmt;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
@@ -835,7 +836,7 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
.dom_children()
.all(|node| match node.script_type_id() {
NodeTypeId::Element(..) => false,
- NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => unsafe {
+ NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text)) => {
node.node.downcast().unwrap().data_for_layout().is_empty()
},
_ => true,
@@ -1117,9 +1118,8 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
self.node
}
- fn node_text_content(&self) -> String {
- let this = unsafe { self.get_jsmanaged() };
- return this.text_content();
+ fn node_text_content(self) -> Cow<'ln, str> {
+ unsafe { self.get_jsmanaged().text_content() }
}
fn selection(&self) -> Option<Range<ByteIndex>> {
diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs
index cea5df2abf5..e2e8b79f9af 100644
--- a/components/script/dom/attr.rs
+++ b/components/script/dom/attr.rs
@@ -234,27 +234,27 @@ impl Attr {
#[allow(unsafe_code)]
pub trait AttrHelpersForLayout<'dom> {
- unsafe fn value(self) -> &'dom AttrValue;
- unsafe fn value_ref_forever(self) -> &'dom str;
- unsafe fn value_tokens(self) -> Option<&'dom [Atom]>;
- unsafe fn local_name_atom(self) -> LocalName;
+ fn value(self) -> &'dom AttrValue;
+ fn as_str(self) -> &'dom str;
+ fn as_tokens(self) -> Option<&'dom [Atom]>;
+ fn local_name(self) -> &'dom LocalName;
+ fn namespace(self) -> &'dom Namespace;
}
#[allow(unsafe_code)]
impl<'dom> AttrHelpersForLayout<'dom> for LayoutDom<'dom, Attr> {
#[inline]
- unsafe fn value(self) -> &'dom AttrValue {
- (*self.unsafe_get()).value.borrow_for_layout()
+ fn value(self) -> &'dom AttrValue {
+ unsafe { self.unsafe_get().value.borrow_for_layout() }
}
#[inline]
- unsafe fn value_ref_forever(self) -> &'dom str {
+ fn as_str(self) -> &'dom str {
&**self.value()
}
#[inline]
- unsafe fn value_tokens(self) -> Option<&'dom [Atom]> {
- // This transmute is used to cheat the lifetime restriction.
+ fn as_tokens(self) -> Option<&'dom [Atom]> {
match *self.value() {
AttrValue::TokenList(_, ref tokens) => Some(tokens),
_ => None,
@@ -262,7 +262,12 @@ impl<'dom> AttrHelpersForLayout<'dom> for LayoutDom<'dom, Attr> {
}
#[inline]
- unsafe fn local_name_atom(self) -> LocalName {
- (*self.unsafe_get()).identifier.local_name.clone()
+ fn local_name(self) -> &'dom LocalName {
+ unsafe { &self.unsafe_get().identifier.local_name }
+ }
+
+ #[inline]
+ fn namespace(self) -> &'dom Namespace {
+ unsafe { &self.unsafe_get().identifier.namespace }
}
}
diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs
index 4e0d32d4456..f8c5acb5a8f 100644
--- a/components/script/dom/characterdata.rs
+++ b/components/script/dom/characterdata.rs
@@ -280,16 +280,15 @@ impl CharacterDataMethods for CharacterData {
}
}
-#[allow(unsafe_code)]
pub trait LayoutCharacterDataHelpers<'dom> {
- unsafe fn data_for_layout(self) -> &'dom str;
+ fn data_for_layout(self) -> &'dom str;
}
-#[allow(unsafe_code)]
impl<'dom> LayoutCharacterDataHelpers<'dom> for LayoutDom<'dom, CharacterData> {
+ #[allow(unsafe_code)]
#[inline]
- unsafe fn data_for_layout(self) -> &'dom str {
- &(*self.unsafe_get()).data.borrow_for_layout()
+ fn data_for_layout(self) -> &'dom str {
+ unsafe { self.unsafe_get().data.borrow_for_layout() }
}
}
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 602cb148d7a..7d167bf2574 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -578,7 +578,7 @@ pub unsafe fn get_attr_for_layout<'dom>(
.iter()
.find(|attr| {
let attr = attr.to_layout();
- *name == attr.local_name_atom() && (*attr.unsafe_get()).namespace() == namespace
+ name == attr.local_name() && namespace == attr.namespace()
})
.map(|attr| attr.to_layout())
}
@@ -600,7 +600,7 @@ impl RawLayoutElementHelpers for Element {
namespace: &Namespace,
name: &LocalName,
) -> Option<&'a str> {
- get_attr_for_layout(self, namespace, name).map(|attr| attr.value_ref_forever())
+ get_attr_for_layout(self, namespace, name).map(|attr| attr.as_str())
}
#[inline]
@@ -610,7 +610,7 @@ impl RawLayoutElementHelpers for Element {
.iter()
.filter_map(|attr| {
let attr = attr.to_layout();
- if *name == attr.local_name_atom() {
+ if name == attr.local_name() {
Some(attr.value())
} else {
None
@@ -656,7 +656,7 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
get_attr_for_layout(&*self.unsafe_get(), &ns!(), &local_name!("class")).map_or(
false,
|attr| {
- attr.value_tokens()
+ attr.as_tokens()
.unwrap()
.iter()
.any(|atom| case_sensitivity.eq_atom(atom, name))
@@ -668,7 +668,7 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
#[inline]
unsafe fn get_classes_for_layout(self) -> Option<&'dom [Atom]> {
get_attr_for_layout(&*self.unsafe_get(), &ns!(), &local_name!("class"))
- .map(|attr| attr.value_tokens().unwrap())
+ .map(|attr| attr.as_tokens().unwrap())
}
#[allow(unsafe_code)]
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index 05eca7b35eb..5d7438ecc4a 100755
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -67,7 +67,7 @@ use profile_traits::ipc;
use script_layout_interface::rpc::TextIndexResponse;
use script_traits::ScriptToConstellationChan;
use servo_atoms::Atom;
-use std::borrow::ToOwned;
+use std::borrow::Cow;
use std::cell::Cell;
use std::ops::Range;
use std::ptr::NonNull;
@@ -705,9 +705,8 @@ impl HTMLInputElement {
}
}
-pub trait LayoutHTMLInputElementHelpers {
- #[allow(unsafe_code)]
- unsafe fn value_for_layout(self) -> String;
+pub trait LayoutHTMLInputElementHelpers<'dom> {
+ fn value_for_layout(self) -> Cow<'dom, str>;
#[allow(unsafe_code)]
unsafe fn size_for_layout(self) -> u32;
#[allow(unsafe_code)]
@@ -726,41 +725,47 @@ unsafe fn get_raw_textinput_value(input: LayoutDom<HTMLInputElement>) -> DOMStri
.get_content()
}
-impl LayoutHTMLInputElementHelpers for LayoutDom<'_, HTMLInputElement> {
+impl<'dom> LayoutHTMLInputElementHelpers<'dom> for LayoutDom<'dom, HTMLInputElement> {
#[allow(unsafe_code)]
- unsafe fn value_for_layout(self) -> String {
- #[allow(unsafe_code)]
- unsafe fn get_raw_attr_value(
- input: LayoutDom<'_, HTMLInputElement>,
- default: &str,
- ) -> String {
- let elem = input.upcast::<Element>();
- let value = (*elem.unsafe_get())
- .get_attr_val_for_layout(&ns!(), &local_name!("value"))
- .unwrap_or(default);
- String::from(value)
+ fn value_for_layout(self) -> Cow<'dom, str> {
+ fn get_raw_attr_value<'dom>(
+ input: LayoutDom<'dom, HTMLInputElement>,
+ default: &'static str,
+ ) -> Cow<'dom, str> {
+ unsafe {
+ input
+ .upcast::<Element>()
+ .unsafe_get()
+ .get_attr_val_for_layout(&ns!(), &local_name!("value"))
+ .unwrap_or(default)
+ .into()
+ }
}
- match (*self.unsafe_get()).input_type() {
- InputType::Checkbox | InputType::Radio => String::new(),
- InputType::File | InputType::Image => String::new(),
+ let placeholder = unsafe { &**self.unsafe_get().placeholder.borrow_for_layout() };
+ match unsafe { self.unsafe_get().input_type() } {
+ InputType::Checkbox | InputType::Radio => "".into(),
+ InputType::File | InputType::Image => "".into(),
InputType::Button => get_raw_attr_value(self, ""),
InputType::Submit => get_raw_attr_value(self, DEFAULT_SUBMIT_VALUE),
InputType::Reset => get_raw_attr_value(self, DEFAULT_RESET_VALUE),
InputType::Password => {
- let text = get_raw_textinput_value(self);
+ let text = unsafe { get_raw_textinput_value(self) };
if !text.is_empty() {
- text.chars().map(|_| PASSWORD_REPLACEMENT_CHAR).collect()
+ text.chars()
+ .map(|_| PASSWORD_REPLACEMENT_CHAR)
+ .collect::<String>()
+ .into()
} else {
- String::from((*self.unsafe_get()).placeholder.borrow_for_layout().clone())
+ placeholder.into()
}
},
_ => {
- let text = get_raw_textinput_value(self);
+ let text = unsafe { get_raw_textinput_value(self) };
if !text.is_empty() {
- String::from(text)
+ text.into()
} else {
- String::from((*self.unsafe_get()).placeholder.borrow_for_layout().clone())
+ placeholder.into()
}
},
}
diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs
index 8ee42bc2c86..e3721a78213 100755
--- a/components/script/dom/htmltextareaelement.rs
+++ b/components/script/dom/htmltextareaelement.rs
@@ -56,8 +56,7 @@ pub struct HTMLTextAreaElement {
}
pub trait LayoutHTMLTextAreaElementHelpers {
- #[allow(unsafe_code)]
- unsafe fn value_for_layout(self) -> String;
+ fn value_for_layout(self) -> String;
#[allow(unsafe_code)]
unsafe fn selection_for_layout(self) -> Option<Range<usize>>;
#[allow(unsafe_code)]
@@ -67,19 +66,19 @@ pub trait LayoutHTMLTextAreaElementHelpers {
}
impl LayoutHTMLTextAreaElementHelpers for LayoutDom<'_, HTMLTextAreaElement> {
- #[allow(unrooted_must_root)]
#[allow(unsafe_code)]
- unsafe fn value_for_layout(self) -> String {
- let text = (*self.unsafe_get())
- .textinput
- .borrow_for_layout()
- .get_content();
- if text.is_empty() {
- (*self.unsafe_get())
- .placeholder
+ fn value_for_layout(self) -> String {
+ let text = unsafe {
+ self.unsafe_get()
+ .textinput
.borrow_for_layout()
- .replace("\r\n", "\n")
- .replace("\r", "\n")
+ .get_content()
+ };
+ if text.is_empty() {
+ let placeholder = unsafe { self.unsafe_get().placeholder.borrow_for_layout() };
+ // FIXME(nox): Would be cool to not allocate a new string if the
+ // placeholder is single line, but that's an unimportant detail.
+ placeholder.replace("\r\n", "\n").replace("\r", "\n").into()
} else {
text.into()
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index d92e3b6a364..251f6fcab18 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -87,7 +87,7 @@ use servo_arc::Arc;
use servo_atoms::Atom;
use servo_url::ServoUrl;
use smallvec::SmallVec;
-use std::borrow::ToOwned;
+use std::borrow::Cow;
use std::cell::{Cell, UnsafeCell};
use std::cmp;
use std::default::Default;
@@ -1326,7 +1326,7 @@ pub trait LayoutNodeHelpers<'dom> {
unsafe fn init_style_and_layout_data(self, _: OpaqueStyleAndLayoutData);
unsafe fn take_style_and_layout_data(self) -> OpaqueStyleAndLayoutData;
- fn text_content(self) -> String;
+ fn text_content(self) -> Cow<'dom, str>;
fn selection(self) -> Option<Range<usize>>;
fn image_url(self) -> Option<ServoUrl>;
fn image_density(self) -> Option<f64>;
@@ -1456,18 +1456,17 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
val
}
- #[allow(unsafe_code)]
- fn text_content(self) -> String {
+ fn text_content(self) -> Cow<'dom, str> {
if let Some(text) = self.downcast::<Text>() {
- return unsafe { text.upcast().data_for_layout().to_owned() };
+ return text.upcast().data_for_layout().into();
}
if let Some(input) = self.downcast::<HTMLInputElement>() {
- return unsafe { input.value_for_layout() };
+ return input.value_for_layout();
}
if let Some(area) = self.downcast::<HTMLTextAreaElement>() {
- return unsafe { area.value_for_layout() };
+ return area.value_for_layout().into();
}
panic!("not text!")
diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs
index 67b107a86d7..462d11f2c7e 100644
--- a/components/script_layout_interface/wrapper_traits.rs
+++ b/components/script_layout_interface/wrapper_traits.rs
@@ -17,6 +17,7 @@ use net_traits::image::base::{Image, ImageMetadata};
use range::Range;
use servo_arc::Arc;
use servo_url::ServoUrl;
+use std::borrow::Cow;
use std::fmt::Debug;
use std::sync::Arc as StdArc;
use style::attr::AttrValue;
@@ -262,7 +263,7 @@ pub trait ThreadSafeLayoutNode<'dom>:
/// data flags, and we have this annoying trait separation between script and layout :-(
unsafe fn unsafe_get(self) -> Self::ConcreteNode;
- fn node_text_content(&self) -> String;
+ fn node_text_content(self) -> Cow<'dom, str>;
/// If the insertion point is within this node, returns it. Otherwise, returns `None`.
fn selection(&self) -> Option<Range<ByteIndex>>;