mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
This reverts commit 5580704438
.
Let's re-land that fix when a working solution is found. Keeping that
regression makes it hard to evaluate other potential improvements.
Signed-off-by: webbeef <me@webbeef.org>
This commit is contained in:
parent
aff2a85372
commit
a1f43ab06d
24 changed files with 36 additions and 635 deletions
|
@ -59,14 +59,8 @@ impl<'dom> NodeAndStyleInfo<'dom> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Whether this is a container for the editable text within a single-line text input.
|
||||
/// This is used to solve the special case of line height for a text editor.
|
||||
/// <https://html.spec.whatwg.org/multipage/#the-input-element-as-a-text-entry-widget>
|
||||
// FIXME(stevennovaryo): Now, this would also refer to HTMLInputElement, to handle input
|
||||
// elements without shadow DOM.
|
||||
pub(crate) fn is_single_line_text_input(&self) -> bool {
|
||||
self.node.type_id() == LayoutNodeType::Element(LayoutElementType::HTMLInputElement) ||
|
||||
self.node.is_text_control_inner_editor()
|
||||
self.node.type_id() == LayoutNodeType::Element(LayoutElementType::HTMLInputElement)
|
||||
}
|
||||
|
||||
pub(crate) fn pseudo(
|
||||
|
|
|
@ -1556,14 +1556,11 @@ impl Document {
|
|||
return;
|
||||
}
|
||||
|
||||
// For a node within a text input UA shadow DOM, delegate the focus target into its shadow host.
|
||||
// TODO: This focus delegation should be done with shadow DOM delegateFocus attribute.
|
||||
let target_el = el.find_focusable_shadow_host_if_necessary();
|
||||
|
||||
self.begin_focus_transaction();
|
||||
// Try to focus `el`. If it's not focusable, focus the document instead.
|
||||
// Try to focus `el`. If it's not focusable, focus the document
|
||||
// instead.
|
||||
self.request_focus(None, FocusInitiator::Local, can_gc);
|
||||
self.request_focus(target_el.as_deref(), FocusInitiator::Local, can_gc);
|
||||
self.request_focus(Some(&*el), FocusInitiator::Local, can_gc);
|
||||
}
|
||||
|
||||
let dom_event = DomRoot::upcast::<Event>(MouseEvent::for_platform_mouse_event(
|
||||
|
|
|
@ -1703,27 +1703,6 @@ impl Element {
|
|||
)
|
||||
}
|
||||
|
||||
/// Returns the focusable shadow host if this is a text control inner editor.
|
||||
/// This is a workaround for the focus delegation of shadow DOM and should be
|
||||
/// used only to delegate focusable inner editor of [HTMLInputElement] and
|
||||
/// [HTMLTextAreaElement].
|
||||
pub(crate) fn find_focusable_shadow_host_if_necessary(&self) -> Option<DomRoot<Element>> {
|
||||
if self.is_focusable_area() {
|
||||
Some(DomRoot::from_ref(self))
|
||||
} else if self.upcast::<Node>().is_text_control_inner_editor() {
|
||||
let containing_shadow_host = self.containing_shadow_root().map(|root| root.Host());
|
||||
assert!(
|
||||
containing_shadow_host
|
||||
.as_ref()
|
||||
.is_some_and(|e| e.is_focusable_area()),
|
||||
"Containing shadow host is not focusable"
|
||||
);
|
||||
containing_shadow_host
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_actually_disabled(&self) -> bool {
|
||||
let node = self.upcast::<Node>();
|
||||
match node.type_id() {
|
||||
|
|
|
@ -101,29 +101,6 @@ const DEFAULT_RESET_VALUE: &str = "Reset";
|
|||
const PASSWORD_REPLACEMENT_CHAR: char = '●';
|
||||
const DEFAULT_FILE_INPUT_VALUE: &str = "No file chosen";
|
||||
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
/// Contains reference to text control inner editor and placeholder container element in the UA
|
||||
/// shadow tree for `<input type=text>`. The following is the structure of the shadow tree.
|
||||
///
|
||||
/// ```
|
||||
/// <input type="text">
|
||||
/// #shadow-root
|
||||
/// <div id="inner-container">
|
||||
/// <div id="input-editor"></div>
|
||||
/// <div id="input-placeholder"></div>
|
||||
/// </div>
|
||||
/// </input>
|
||||
/// ```
|
||||
// TODO(stevennovaryo): We are trying to use CSS to mimic Chrome and Firefox's layout for the <input> element.
|
||||
// But, this could be slower in performance and does have some discrepancies. For example,
|
||||
// they would try to vertically align <input> text baseline with the baseline of other
|
||||
// TextNode within an inline flow. Another example is the horizontal scroll.
|
||||
struct InputTypeTextShadowTree {
|
||||
text_container: Dom<HTMLDivElement>,
|
||||
placeholder_container: Dom<HTMLDivElement>,
|
||||
}
|
||||
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
/// Contains references to the elements in the shadow tree for `<input type=range>`.
|
||||
|
@ -134,49 +111,10 @@ struct InputTypeColorShadowTree {
|
|||
color_value: Dom<HTMLDivElement>,
|
||||
}
|
||||
|
||||
// FIXME: These styles should be inside UA stylesheet, but it is not possible without internal pseudo element support.
|
||||
const TEXT_TREE_STYLE: &str = "
|
||||
#input-editor::selection {
|
||||
background: rgba(176, 214, 255, 1.0);
|
||||
color: black;
|
||||
}
|
||||
|
||||
:host:not(:placeholder-shown) #input-placeholder {
|
||||
visibility: hidden !important
|
||||
}
|
||||
|
||||
#input-editor {
|
||||
overflow-wrap: normal;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#input-container {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#input-editor, #input-placeholder {
|
||||
white-space: pre;
|
||||
margin-block: auto !important;
|
||||
inset-block: 0 !important;
|
||||
block-size: fit-content !important;
|
||||
}
|
||||
|
||||
#input-placeholder {
|
||||
overflow: hidden !important;
|
||||
position: absolute !important;
|
||||
color: grey;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
";
|
||||
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
#[non_exhaustive]
|
||||
enum ShadowTree {
|
||||
Text(InputTypeTextShadowTree),
|
||||
Color(InputTypeColorShadowTree),
|
||||
// TODO: Add shadow trees for other input types (range etc) here
|
||||
}
|
||||
|
@ -1133,7 +1071,7 @@ impl HTMLInputElement {
|
|||
ShadowRootMode::Closed,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
SlotAssignmentMode::Manual,
|
||||
can_gc,
|
||||
)
|
||||
|
@ -1141,92 +1079,6 @@ impl HTMLInputElement {
|
|||
})
|
||||
}
|
||||
|
||||
fn create_text_shadow_tree(&self, can_gc: CanGc) {
|
||||
let document = self.owner_document();
|
||||
let shadow_root = self.shadow_root(can_gc);
|
||||
Node::replace_all(None, shadow_root.upcast::<Node>(), can_gc);
|
||||
|
||||
let inner_container =
|
||||
HTMLDivElement::new(local_name!("div"), None, &document, None, can_gc);
|
||||
inner_container
|
||||
.upcast::<Element>()
|
||||
.SetId(DOMString::from("input-container"), can_gc);
|
||||
shadow_root
|
||||
.upcast::<Node>()
|
||||
.AppendChild(inner_container.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
let placeholder_container =
|
||||
HTMLDivElement::new(local_name!("div"), None, &document, None, can_gc);
|
||||
placeholder_container
|
||||
.upcast::<Element>()
|
||||
.SetId(DOMString::from("input-placeholder"), can_gc);
|
||||
inner_container
|
||||
.upcast::<Node>()
|
||||
.AppendChild(placeholder_container.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
let text_container = HTMLDivElement::new(local_name!("div"), None, &document, None, can_gc);
|
||||
text_container
|
||||
.upcast::<Element>()
|
||||
.SetId(DOMString::from("input-editor"), can_gc);
|
||||
text_container
|
||||
.upcast::<Node>()
|
||||
.set_text_control_inner_editor();
|
||||
inner_container
|
||||
.upcast::<Node>()
|
||||
.AppendChild(text_container.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
let style = HTMLStyleElement::new(
|
||||
local_name!("style"),
|
||||
None,
|
||||
&document,
|
||||
None,
|
||||
ElementCreator::ScriptCreated,
|
||||
can_gc,
|
||||
);
|
||||
// TODO(stevennovaryo): Either use UA stylesheet with internal pseudo element or preemptively parse
|
||||
// the stylesheet to reduce the costly operation and avoid CSP related error.
|
||||
style
|
||||
.upcast::<Node>()
|
||||
.SetTextContent(Some(DOMString::from(TEXT_TREE_STYLE)), can_gc);
|
||||
shadow_root
|
||||
.upcast::<Node>()
|
||||
.AppendChild(style.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
let _ = self
|
||||
.shadow_tree
|
||||
.borrow_mut()
|
||||
.insert(ShadowTree::Text(InputTypeTextShadowTree {
|
||||
text_container: text_container.as_traced(),
|
||||
placeholder_container: placeholder_container.as_traced(),
|
||||
}));
|
||||
}
|
||||
|
||||
fn text_shadow_tree(&self, can_gc: CanGc) -> Ref<InputTypeTextShadowTree> {
|
||||
let has_text_shadow_tree = self
|
||||
.shadow_tree
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.is_some_and(|shadow_tree| matches!(shadow_tree, ShadowTree::Text(_)));
|
||||
if !has_text_shadow_tree {
|
||||
self.create_text_shadow_tree(can_gc);
|
||||
}
|
||||
|
||||
let shadow_tree = self.shadow_tree.borrow();
|
||||
Ref::filter_map(shadow_tree, |shadow_tree| {
|
||||
let shadow_tree = shadow_tree.as_ref()?;
|
||||
match shadow_tree {
|
||||
ShadowTree::Text(text_tree) => Some(text_tree),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.ok()
|
||||
.expect("UA shadow tree was not created")
|
||||
}
|
||||
|
||||
fn create_color_shadow_tree(&self, can_gc: CanGc) {
|
||||
let document = self.owner_document();
|
||||
let shadow_root = self.shadow_root(can_gc);
|
||||
|
@ -1284,53 +1136,27 @@ impl HTMLInputElement {
|
|||
let shadow_tree = self.shadow_tree.borrow();
|
||||
Ref::filter_map(shadow_tree, |shadow_tree| {
|
||||
let shadow_tree = shadow_tree.as_ref()?;
|
||||
match shadow_tree {
|
||||
ShadowTree::Color(color_tree) => Some(color_tree),
|
||||
_ => None,
|
||||
}
|
||||
let ShadowTree::Color(color_tree) = shadow_tree;
|
||||
Some(color_tree)
|
||||
})
|
||||
.ok()
|
||||
.expect("UA shadow tree was not created")
|
||||
}
|
||||
|
||||
fn update_shadow_tree_if_needed(&self, can_gc: CanGc) {
|
||||
match self.input_type() {
|
||||
InputType::Text => {
|
||||
let text_shadow_tree = self.text_shadow_tree(can_gc);
|
||||
let value = self.Value();
|
||||
|
||||
// The addition of zero-width space here forces the text input to have an inline formatting
|
||||
// context that might otherwise be trimmed if there's no text. This is important to ensure
|
||||
// that the input element is at least as tall as the line gap of the caret:
|
||||
// <https://drafts.csswg.org/css-ui/#element-with-default-preferred-size>.
|
||||
//
|
||||
// This is also used to ensure that the caret will still be rendered when the input is empty.
|
||||
// TODO: Is there a less hacky way to do this?
|
||||
let value_text = match value.is_empty() {
|
||||
false => value,
|
||||
true => "\u{200B}".into(),
|
||||
};
|
||||
|
||||
text_shadow_tree
|
||||
.text_container
|
||||
.upcast::<Node>()
|
||||
.SetTextContent(Some(value_text), can_gc);
|
||||
},
|
||||
InputType::Color => {
|
||||
let color_shadow_tree = self.color_shadow_tree(can_gc);
|
||||
let mut value = self.Value();
|
||||
if value.str().is_valid_simple_color_string() {
|
||||
value.make_ascii_lowercase();
|
||||
} else {
|
||||
value = DOMString::from("#000000");
|
||||
}
|
||||
let style = format!("background-color: {value}");
|
||||
color_shadow_tree
|
||||
.color_value
|
||||
.upcast::<Element>()
|
||||
.set_string_attribute(&local_name!("style"), style.into(), can_gc);
|
||||
},
|
||||
_ => {},
|
||||
if self.input_type() == InputType::Color {
|
||||
let color_shadow_tree = self.color_shadow_tree(can_gc);
|
||||
let mut value = self.Value();
|
||||
if value.str().is_valid_simple_color_string() {
|
||||
value.make_ascii_lowercase();
|
||||
} else {
|
||||
value = DOMString::from("#000000");
|
||||
}
|
||||
let style = format!("background-color: {value}");
|
||||
color_shadow_tree
|
||||
.color_value
|
||||
.upcast::<Element>()
|
||||
.set_string_attribute(&local_name!("style"), style.into(), can_gc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1639,29 +1465,22 @@ impl HTMLInputElementMethods<crate::DomTypeHolder> for HTMLInputElement {
|
|||
fn SetValue(&self, mut value: DOMString, can_gc: CanGc) -> ErrorResult {
|
||||
match self.value_mode() {
|
||||
ValueMode::Value => {
|
||||
{
|
||||
// Step 3.
|
||||
self.value_dirty.set(true);
|
||||
// Step 3.
|
||||
self.value_dirty.set(true);
|
||||
|
||||
// Step 4.
|
||||
self.sanitize_value(&mut value);
|
||||
// Step 4.
|
||||
self.sanitize_value(&mut value);
|
||||
|
||||
let mut textinput = self.textinput.borrow_mut();
|
||||
let mut textinput = self.textinput.borrow_mut();
|
||||
|
||||
// Step 5.
|
||||
if *textinput.single_line_content() != value {
|
||||
// Steps 1-2
|
||||
textinput.set_content(value);
|
||||
|
||||
// Step 5.
|
||||
if *textinput.single_line_content() != value {
|
||||
// Steps 1-2
|
||||
textinput.set_content(value);
|
||||
|
||||
// Step 5.
|
||||
textinput.clear_selection_to_limit(Direction::Forward);
|
||||
}
|
||||
textinput.clear_selection_to_limit(Direction::Forward);
|
||||
}
|
||||
|
||||
// Additionaly, update the placeholder shown state. This is
|
||||
// normally being done in the attributed mutated. And, being
|
||||
// done in another scope to prevent borrow checker issues.
|
||||
self.update_placeholder_shown_state();
|
||||
},
|
||||
ValueMode::Default | ValueMode::DefaultOn => {
|
||||
self.upcast::<Element>()
|
||||
|
@ -2244,19 +2063,6 @@ impl HTMLInputElement {
|
|||
el.set_placeholder_shown_state(has_placeholder && !has_value);
|
||||
}
|
||||
|
||||
// Update the placeholder text in the text shadow tree.
|
||||
// To increase the performance, we would only do this when it is necessary.
|
||||
fn update_text_shadow_tree_placeholder(&self, can_gc: CanGc) {
|
||||
if self.input_type() != InputType::Text {
|
||||
return;
|
||||
}
|
||||
|
||||
self.text_shadow_tree(can_gc)
|
||||
.placeholder_container
|
||||
.upcast::<Node>()
|
||||
.SetTextContent(Some(self.placeholder.borrow().clone()), can_gc);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#file-upload-state-(type=file)
|
||||
// Select files by invoking UI or by passed in argument
|
||||
fn select_files(&self, opt_test_paths: Option<Vec<DOMString>>, can_gc: CanGc) {
|
||||
|
@ -2882,11 +2688,8 @@ impl VirtualMethods for HTMLInputElement {
|
|||
},
|
||||
}
|
||||
|
||||
self.update_text_shadow_tree_placeholder(can_gc);
|
||||
self.update_placeholder_shown_state();
|
||||
},
|
||||
// FIXME(stevennovaryo): This is only reachable by Default and DefaultOn value mode. While others
|
||||
// are being handled in [Self::SetValue]. Should we merge this two together?
|
||||
local_name!("value") if !self.value_dirty.get() => {
|
||||
let value = mutation.new_value(attr).map(|value| (**value).to_owned());
|
||||
let mut value = value.map_or(DOMString::new(), DOMString::from);
|
||||
|
@ -2935,7 +2738,6 @@ impl VirtualMethods for HTMLInputElement {
|
|||
.extend(attr.value().chars().filter(|&c| c != '\n' && c != '\r'));
|
||||
}
|
||||
}
|
||||
self.update_text_shadow_tree_placeholder(can_gc);
|
||||
self.update_placeholder_shown_state();
|
||||
},
|
||||
local_name!("readonly") => {
|
||||
|
|
|
@ -230,10 +230,6 @@ bitflags! {
|
|||
/// 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;
|
||||
|
||||
/// Whether this node serves as the text container for editable content of
|
||||
/// <input> or <textarea> element.
|
||||
const IS_TEXT_CONTROL_INNER_EDITOR = 1 << 12;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -701,16 +697,6 @@ impl Node {
|
|||
self.flags.get().contains(NodeFlags::IS_CONNECTED)
|
||||
}
|
||||
|
||||
pub(crate) fn set_text_control_inner_editor(&self) {
|
||||
self.set_flag(NodeFlags::IS_TEXT_CONTROL_INNER_EDITOR, true)
|
||||
}
|
||||
|
||||
pub(crate) fn is_text_control_inner_editor(&self) -> bool {
|
||||
self.flags
|
||||
.get()
|
||||
.contains(NodeFlags::IS_TEXT_CONTROL_INNER_EDITOR)
|
||||
}
|
||||
|
||||
/// Returns the type ID of this node.
|
||||
pub(crate) fn type_id(&self) -> NodeTypeId {
|
||||
match *self.eventtarget.type_id() {
|
||||
|
@ -1608,7 +1594,6 @@ pub(crate) trait LayoutNodeHelpers<'dom> {
|
|||
fn assigned_slot_for_layout(self) -> Option<LayoutDom<'dom, HTMLSlotElement>>;
|
||||
|
||||
fn is_element_for_layout(&self) -> bool;
|
||||
fn is_text_node_for_layout(&self) -> bool;
|
||||
unsafe fn get_flag(self, flag: NodeFlags) -> bool;
|
||||
unsafe fn set_flag(self, flag: NodeFlags, value: bool);
|
||||
|
||||
|
@ -1644,9 +1629,6 @@ pub(crate) trait LayoutNodeHelpers<'dom> {
|
|||
|
||||
/// Whether this element is a `<input>` rendered as text or a `<textarea>`.
|
||||
fn is_text_input(&self) -> bool;
|
||||
|
||||
/// Whether this element serve as a container of editable text for a text input.
|
||||
fn is_text_control_inner_editor(&self) -> bool;
|
||||
fn text_content(self) -> Cow<'dom, str>;
|
||||
fn selection(self) -> Option<Range<usize>>;
|
||||
fn image_url(self) -> Option<ServoUrl>;
|
||||
|
@ -1679,11 +1661,6 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
|||
(*self).is::<Element>()
|
||||
}
|
||||
|
||||
fn is_text_node_for_layout(&self) -> bool {
|
||||
self.type_id_for_layout() ==
|
||||
NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
|
||||
let parent = self.parent_node_ref();
|
||||
|
@ -1825,8 +1802,8 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
|||
{
|
||||
let input = self.unsafe_get().downcast::<HTMLInputElement>().unwrap();
|
||||
|
||||
// FIXME: All the non-color and non-text input types currently render as text
|
||||
!matches!(input.input_type(), InputType::Color | InputType::Text)
|
||||
// FIXME: All the non-color input types currently render as text
|
||||
input.input_type() != InputType::Color
|
||||
} else {
|
||||
type_id ==
|
||||
NodeTypeId::Element(ElementTypeId::HTMLElement(
|
||||
|
@ -1835,10 +1812,6 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_text_control_inner_editor(&self) -> bool {
|
||||
self.unsafe_get().is_text_control_inner_editor()
|
||||
}
|
||||
|
||||
fn text_content(self) -> Cow<'dom, str> {
|
||||
if let Some(text) = self.downcast::<Text>() {
|
||||
return text.upcast().data_for_layout().into();
|
||||
|
@ -1856,25 +1829,6 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
|||
}
|
||||
|
||||
fn selection(self) -> Option<Range<usize>> {
|
||||
// This node is a text node of a text control inner editor in a <input> or <textarea> element.
|
||||
// So we should find those corresponding element, and get its selection.
|
||||
if self.is_text_node_for_layout() &&
|
||||
self.parent_node_ref()
|
||||
.is_some_and(|parent| parent.is_text_control_inner_editor())
|
||||
{
|
||||
let shadow_root = self.containing_shadow_root_for_layout();
|
||||
if let Some(containing_shadow_host) = shadow_root.map(|root| root.get_host_for_layout())
|
||||
{
|
||||
if let Some(area) = containing_shadow_host.downcast::<HTMLTextAreaElement>() {
|
||||
return area.selection_for_layout();
|
||||
}
|
||||
|
||||
if let Some(input) = containing_shadow_host.downcast::<HTMLInputElement>() {
|
||||
return input.selection_for_layout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(area) = self.downcast::<HTMLTextAreaElement>() {
|
||||
return area.selection_for_layout();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ use style::selector_parser::PseudoElement;
|
|||
use super::{
|
||||
ServoLayoutDocument, ServoLayoutElement, ServoShadowRoot, ServoThreadSafeLayoutElement,
|
||||
};
|
||||
use crate::dom::bindings::inheritance::NodeTypeId;
|
||||
use crate::dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId, TextTypeId};
|
||||
use crate::dom::bindings::root::LayoutDom;
|
||||
use crate::dom::element::{Element, LayoutElementHelpers};
|
||||
use crate::dom::node::{LayoutNodeHelpers, Node, NodeFlags, NodeTypeIdWrapper};
|
||||
|
@ -100,10 +100,6 @@ impl<'dom> ServoLayoutNode<'dom> {
|
|||
pub fn is_text_input(&self) -> bool {
|
||||
self.node.is_text_input()
|
||||
}
|
||||
|
||||
pub fn is_text_control_inner_editor(&self) -> bool {
|
||||
self.node.is_text_control_inner_editor()
|
||||
}
|
||||
}
|
||||
|
||||
impl style::dom::NodeInfo for ServoLayoutNode<'_> {
|
||||
|
@ -112,7 +108,8 @@ impl style::dom::NodeInfo for ServoLayoutNode<'_> {
|
|||
}
|
||||
|
||||
fn is_text_node(&self) -> bool {
|
||||
self.node.is_text_node_for_layout()
|
||||
self.script_type_id() ==
|
||||
NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[form-action-src-default-ignored.sub.html]
|
||||
[Expecting logs: ["PASS","TEST COMPLETE"\]]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[spelling-markers-009.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[spelling-markers-010.html]
|
||||
expected: FAIL
|
112
tests/wpt/mozilla/meta/MANIFEST.json
vendored
112
tests/wpt/mozilla/meta/MANIFEST.json
vendored
|
@ -91,86 +91,6 @@
|
|||
}
|
||||
},
|
||||
"reftest": {
|
||||
"appearance": {
|
||||
"input-text-definite-width.html": [
|
||||
"fda46f8af9c14cef3911ec809054624204848b9d",
|
||||
[
|
||||
"appearance/input-text-definite-width.html",
|
||||
[
|
||||
[
|
||||
"/_mozilla/appearance/input-text-definite-width-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"input-text-empty.html": [
|
||||
"bd5f5f5a21ec0ce028922a6764de41dc904a1eb1",
|
||||
[
|
||||
"appearance/input-text-empty.html",
|
||||
[
|
||||
[
|
||||
"/_mozilla/appearance/input-text-empty-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"input-text-nonempty-placeholder.html": [
|
||||
"e075663cb6ae708b313b3cd5cd69f78c51b4bc1f",
|
||||
[
|
||||
"appearance/input-text-nonempty-placeholder.html",
|
||||
[
|
||||
[
|
||||
"/_mozilla/appearance/input-text-nonempty-placeholder-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"input-text-overflow.html": [
|
||||
"52db07c0f0274d2b7b086d7017982145c25918da",
|
||||
[
|
||||
"appearance/input-text-overflow.html",
|
||||
[
|
||||
[
|
||||
"/_mozilla/appearance/input-text-overflow-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"input-text-placeholder-overflow.html": [
|
||||
"c4d77ae2a22a5b7972f2798b8ca78742b81bacc4",
|
||||
[
|
||||
"appearance/input-text-placeholder-overflow.html",
|
||||
[
|
||||
[
|
||||
"/_mozilla/appearance/input-text-placeholder-overflow-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"input-text-placeholder.html": [
|
||||
"d75acade78038b14529135b1d63c0ac5a168a87b",
|
||||
[
|
||||
"appearance/input-text-placeholder.html",
|
||||
[
|
||||
[
|
||||
"/_mozilla/appearance/input-text-placeholder-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
]
|
||||
},
|
||||
"css": {
|
||||
"abs-overflow-stackingcontext.html": [
|
||||
"264df01aa64e0abe9ea3a75e57452c27d53a904f",
|
||||
|
@ -8155,38 +8075,6 @@
|
|||
"b485d435a63ada28eabe976b49a8a580725e7508",
|
||||
[]
|
||||
],
|
||||
"appearance": {
|
||||
"input-text-definite-width-ref.html": [
|
||||
"86f7937755750261ed3b06dfe11e78a251b9d175",
|
||||
[]
|
||||
],
|
||||
"input-text-empty-ref.html": [
|
||||
"437c9988a13e094d870f67c8de0dd0becdeece76",
|
||||
[]
|
||||
],
|
||||
"input-text-nonempty-placeholder-ref.html": [
|
||||
"5415dfb2a4a88dc3bfed6ad04e23f288534351e4",
|
||||
[]
|
||||
],
|
||||
"input-text-overflow-ref.html": [
|
||||
"4cece657a2a09cfe3f1d91d49f0c9d76f5714516",
|
||||
[]
|
||||
],
|
||||
"input-text-placeholder-overflow-ref.html": [
|
||||
"0cccfff638c0d8687a3582310c73233b7d883b1a",
|
||||
[]
|
||||
],
|
||||
"input-text-placeholder-ref.html": [
|
||||
"fa5b60bdabdf2b9b818ebe66bfc7f2711173b88b",
|
||||
[]
|
||||
],
|
||||
"supports": {
|
||||
"input-text-ref.css": [
|
||||
"8cf00d493138285e50aa510273abae98c099ae8b",
|
||||
[]
|
||||
]
|
||||
}
|
||||
},
|
||||
"bluetooth": {
|
||||
"bluetooth-helpers.js": [
|
||||
"16a280cca298bcaa5796b36b48d331bfd15baae8",
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[input_placeholder.html]
|
||||
expected: FAIL
|
|
@ -1,15 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Input type=text With a Definite Width</title>
|
||||
<link rel="stylesheet" href="./supports/input-text-ref.css">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<div id="input" class="definite-width">
|
||||
Foo
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Input type=text With a Definite Width</title>
|
||||
<link rel="match" href="input-text-definite-width-ref.html">
|
||||
<link rel="help" href="https://github.com/servo/servo/pull/37065">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<input type="text" value="Foo" style="font-size: 1em !important; width: 100px;"></input>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,15 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Empty Input type=text With a Definite Width</title>
|
||||
<link rel="stylesheet" href="./supports/input-text-ref.css">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<div id="input" class="definite-width">
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Empty Input type=text With a Definite Width</title>
|
||||
<link rel="match" href="input-text-empty-ref.html">
|
||||
<link rel="help" href="https://github.com/servo/servo/pull/37065">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<input type="text" style="font-size: 1em !important; width: 100px;"></input>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,15 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of a Non-empty Input type=text With a Definite Width and a Placeholder</title>
|
||||
<link rel="stylesheet" href="./supports/input-text-ref.css">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<div id="input" class="definite-width">
|
||||
Foo
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of a Non-empty Input type=text With a Definite Width and a Placeholder</title>
|
||||
<link rel="match" href="input-text-nonempty-placeholder-ref.html">
|
||||
<link rel="help" href="https://github.com/servo/servo/pull/37065">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<input type="text" value="Foo" placeholder="Bar" style="font-size: 1em !important; width: 100px;"></input>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,15 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Overflowing Input type=text With a Definite Width</title>
|
||||
<link rel="stylesheet" href="./supports/input-text-ref.css">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<div id="input" class="definite-width">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Overflowing Input type=text With a Definite Width</title>
|
||||
<link rel="match" href="input-text-overflow-ref.html">
|
||||
<link rel="help" href="https://github.com/servo/servo/pull/37065">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<input type="text" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." style="font-size: 1em !important; width: 100px;"></input>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,15 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Input type=text With a Definite Width and an Overflowing Placeholder</title>
|
||||
<link rel="stylesheet" href="./supports/input-text-ref.css">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<div id="input" class="definite-width placeholder-color">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Input type=text With a Definite Width and an Overflowing Placeholder</title>
|
||||
<link rel="match" href="input-text-placeholder-overflow-ref.html">
|
||||
<link rel="help" href="https://github.com/servo/servo/pull/37065">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<input type="text" placeholder="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." style="font-size: 1em !important; width: 100px;"></input>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,15 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Input type=text With a Definite Width and a Placeholder</title>
|
||||
<link rel="stylesheet" href="./supports/input-text-ref.css">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<div id="input" class="definite-width placeholder-color">
|
||||
Bar
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Appearance of an Input type=text With a Definite Width and a Placeholder</title>
|
||||
<link rel="match" href="input-text-placeholder-ref.html">
|
||||
<link rel="help" href="https://github.com/servo/servo/pull/37065">
|
||||
</head>
|
||||
<body>
|
||||
Display of an input type=text should match the display generated by the CSS reference.
|
||||
<div>
|
||||
<input type="text" placeholder="Bar" style="font-size: 1em !important; width: 100px;"></input>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,27 +0,0 @@
|
|||
/* Minimal stylesheet to mimic the appearence of an input type=text specific to Servo.
|
||||
* This stylesheet is expected to be modified following the development of the
|
||||
* Shadow DOM input type=text in Servo.
|
||||
*/
|
||||
|
||||
#input {
|
||||
display: inline-block;
|
||||
background: white;
|
||||
border: solid lightgrey 1px;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em; /* We are using 1em here to reduce the effect of inconsistencies in layout */
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* We are using definite width for most of the test to reduce the effect if calculating inline
|
||||
* size of the input element. Which, will depends on the average character width of a font.
|
||||
*
|
||||
* <https://html.spec.whatwg.org/#converting-a-character-width-to-pixels>
|
||||
*/
|
||||
.definite-width {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.placeholder-color {
|
||||
color: grey;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue