mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
merge from master
This commit is contained in:
commit
6e774ea6eb
1044 changed files with 46059 additions and 1506 deletions
|
@ -1203,6 +1203,21 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
for frame in self.current_frame_tree_iter(self.root_frame_id) {
|
for frame in self.current_frame_tree_iter(self.root_frame_id) {
|
||||||
let pipeline = self.pipeline(frame.current);
|
let pipeline = self.pipeline(frame.current);
|
||||||
|
|
||||||
|
// Check to see if there are any webfonts still loading.
|
||||||
|
//
|
||||||
|
// If GetWebFontLoadState returns false, either there are no
|
||||||
|
// webfonts loading, or there's a WebFontLoaded message waiting in
|
||||||
|
// script_chan's message queue. Therefore, we need to check this
|
||||||
|
// before we check whether the document is ready; otherwise,
|
||||||
|
// there's a race condition where a webfont has finished loading,
|
||||||
|
// but hasn't yet notified the document.
|
||||||
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
|
let msg = LayoutControlMsg::GetWebFontLoadState(sender);
|
||||||
|
pipeline.layout_chan.0.send(msg).unwrap();
|
||||||
|
if receiver.recv().unwrap() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Synchronously query the script task for this pipeline
|
// Synchronously query the script task for this pipeline
|
||||||
// to see if it is idle.
|
// to see if it is idle.
|
||||||
let (sender, receiver) = channel();
|
let (sender, receiver) = channel();
|
||||||
|
@ -1213,13 +1228,6 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
let msg = LayoutControlMsg::GetWebFontLoadState(sender);
|
|
||||||
pipeline.layout_chan.0.send(msg).unwrap();
|
|
||||||
if receiver.recv().unwrap() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the visible rectangle for this pipeline. If the constellation has received a
|
// Check the visible rectangle for this pipeline. If the constellation has received a
|
||||||
// size for the pipeline, then its painting should be up to date. If the constellation
|
// size for the pipeline, then its painting should be up to date. If the constellation
|
||||||
// *hasn't* received a size, it could be that the layer was hidden by script before the
|
// *hasn't* received a size, it could be that the layer was hidden by script before the
|
||||||
|
|
|
@ -340,6 +340,10 @@ impl CandidateBSizeIterator {
|
||||||
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => {
|
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => {
|
||||||
Some(block_container_block_size.scale_by(percent))
|
Some(block_container_block_size.scale_by(percent))
|
||||||
}
|
}
|
||||||
|
(LengthOrPercentageOrNone::Calc(calc), Some(block_container_block_size)) => {
|
||||||
|
Some(block_container_block_size.scale_by(calc.percentage()) + calc.length())
|
||||||
|
}
|
||||||
|
(LengthOrPercentageOrNone::Calc(_), _) |
|
||||||
(LengthOrPercentageOrNone::Percentage(_), None) |
|
(LengthOrPercentageOrNone::Percentage(_), None) |
|
||||||
(LengthOrPercentageOrNone::None, _) => None,
|
(LengthOrPercentageOrNone::None, _) => None,
|
||||||
(LengthOrPercentageOrNone::Length(length), _) => Some(length),
|
(LengthOrPercentageOrNone::Length(length), _) => Some(length),
|
||||||
|
@ -1024,18 +1028,13 @@ impl BlockFlow {
|
||||||
let mut candidate_block_size_iterator = CandidateBSizeIterator::new(
|
let mut candidate_block_size_iterator = CandidateBSizeIterator::new(
|
||||||
&self.fragment,
|
&self.fragment,
|
||||||
self.base.block_container_explicit_block_size);
|
self.base.block_container_explicit_block_size);
|
||||||
loop {
|
while let Some(candidate_block_size) = candidate_block_size_iterator.next() {
|
||||||
match candidate_block_size_iterator.next() {
|
|
||||||
Some(candidate_block_size) => {
|
|
||||||
candidate_block_size_iterator.candidate_value =
|
candidate_block_size_iterator.candidate_value =
|
||||||
match candidate_block_size {
|
match candidate_block_size {
|
||||||
MaybeAuto::Auto => block_size,
|
MaybeAuto::Auto => block_size,
|
||||||
MaybeAuto::Specified(value) => value
|
MaybeAuto::Specified(value) => value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust `cur_b` as necessary to account for the explicitly-specified block-size.
|
// Adjust `cur_b` as necessary to account for the explicitly-specified block-size.
|
||||||
block_size = candidate_block_size_iterator.candidate_value;
|
block_size = candidate_block_size_iterator.candidate_value;
|
||||||
|
|
|
@ -27,6 +27,7 @@ use std::{fmt, isize, mem};
|
||||||
use style::computed_values::{display, overflow_x, position, text_align, text_justify};
|
use style::computed_values::{display, overflow_x, position, text_align, text_justify};
|
||||||
use style::computed_values::{text_overflow, vertical_align, white_space};
|
use style::computed_values::{text_overflow, vertical_align, white_space};
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
use style::values::computed::LengthOrPercentage;
|
||||||
use text;
|
use text;
|
||||||
use unicode_bidi;
|
use unicode_bidi;
|
||||||
use util;
|
use util;
|
||||||
|
@ -953,15 +954,15 @@ impl InlineFlow {
|
||||||
offset_from_baseline = offset_from_baseline - *depth_below_baseline
|
offset_from_baseline = offset_from_baseline - *depth_below_baseline
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
vertical_align::T::Length(length) => {
|
vertical_align::T::LengthOrPercentage(LengthOrPercentage::Length(length)) => {
|
||||||
offset_from_baseline = offset_from_baseline - length
|
offset_from_baseline = offset_from_baseline - length
|
||||||
}
|
}
|
||||||
vertical_align::T::Percentage(p) => {
|
vertical_align::T::LengthOrPercentage(LengthOrPercentage::Percentage(p)) => {
|
||||||
let line_height = fragment.calculate_line_height(layout_context);
|
let line_height = fragment.calculate_line_height(layout_context);
|
||||||
let percent_offset = line_height.scale_by(p);
|
let percent_offset = line_height.scale_by(p);
|
||||||
offset_from_baseline = offset_from_baseline - percent_offset
|
offset_from_baseline = offset_from_baseline - percent_offset
|
||||||
}
|
}
|
||||||
vertical_align::T::Calc(calc) => {
|
vertical_align::T::LengthOrPercentage(LengthOrPercentage::Calc(calc)) => {
|
||||||
let line_height = fragment.calculate_line_height(layout_context);
|
let line_height = fragment.calculate_line_height(layout_context);
|
||||||
let percent_offset = line_height.scale_by(calc.percentage());
|
let percent_offset = line_height.scale_by(calc.percentage());
|
||||||
offset_from_baseline = offset_from_baseline - percent_offset - calc.length()
|
offset_from_baseline = offset_from_baseline - percent_offset - calc.length()
|
||||||
|
|
|
@ -51,9 +51,7 @@ use profile_traits::time::{self, ProfilerMetadata, profile};
|
||||||
use query::{LayoutRPCImpl, process_content_box_request, process_content_boxes_request};
|
use query::{LayoutRPCImpl, process_content_box_request, process_content_boxes_request};
|
||||||
use query::{MarginPadding, MarginRetrievingFragmentBorderBoxIterator, PositionProperty};
|
use query::{MarginPadding, MarginRetrievingFragmentBorderBoxIterator, PositionProperty};
|
||||||
use query::{PositionRetrievingFragmentBorderBoxIterator, Side};
|
use query::{PositionRetrievingFragmentBorderBoxIterator, Side};
|
||||||
use script::dom::bindings::js::LayoutJS;
|
use script::dom::node::LayoutData;
|
||||||
use script::dom::document::Document;
|
|
||||||
use script::dom::node::{LayoutData, Node};
|
|
||||||
use script::layout_interface::Animation;
|
use script::layout_interface::Animation;
|
||||||
use script::layout_interface::{LayoutChan, LayoutRPC, OffsetParentResponse};
|
use script::layout_interface::{LayoutChan, LayoutRPC, OffsetParentResponse};
|
||||||
use script::layout_interface::{Msg, NewLayoutTaskInfo, Reflow, ReflowGoal, ReflowQueryType};
|
use script::layout_interface::{Msg, NewLayoutTaskInfo, Reflow, ReflowGoal, ReflowQueryType};
|
||||||
|
@ -90,7 +88,7 @@ use util::opts;
|
||||||
use util::task::spawn_named_with_send_on_failure;
|
use util::task::spawn_named_with_send_on_failure;
|
||||||
use util::task_state;
|
use util::task_state;
|
||||||
use util::workqueue::WorkQueue;
|
use util::workqueue::WorkQueue;
|
||||||
use wrapper::{LayoutDocument, LayoutNode, ThreadSafeLayoutNode};
|
use wrapper::{LayoutNode, ThreadSafeLayoutNode};
|
||||||
|
|
||||||
/// The number of screens of data we're allowed to generate display lists for in each direction.
|
/// The number of screens of data we're allowed to generate display lists for in each direction.
|
||||||
pub const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;
|
pub const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;
|
||||||
|
@ -595,7 +593,7 @@ impl LayoutTask {
|
||||||
profile(time::ProfilerCategory::LayoutPerform,
|
profile(time::ProfilerCategory::LayoutPerform,
|
||||||
self.profiler_metadata(),
|
self.profiler_metadata(),
|
||||||
self.time_profiler_chan.clone(),
|
self.time_profiler_chan.clone(),
|
||||||
|| self.handle_reflow(&*data, possibly_locked_rw_data));
|
|| self.handle_reflow(&data, possibly_locked_rw_data));
|
||||||
},
|
},
|
||||||
Msg::TickAnimations => self.tick_all_animations(possibly_locked_rw_data),
|
Msg::TickAnimations => self.tick_all_animations(possibly_locked_rw_data),
|
||||||
Msg::ReflowWithNewlyLoadedWebFont => {
|
Msg::ReflowWithNewlyLoadedWebFont => {
|
||||||
|
@ -892,17 +890,9 @@ impl LayoutTask {
|
||||||
property: &Atom,
|
property: &Atom,
|
||||||
layout_root: &mut FlowRef)
|
layout_root: &mut FlowRef)
|
||||||
-> Option<String> {
|
-> Option<String> {
|
||||||
// FIXME: Isolate this transmutation into a "bridge" module.
|
let node = unsafe { LayoutNode::new(&requested_node) };
|
||||||
// FIXME(rust#16366): The following line had to be moved because of a
|
|
||||||
// rustc bug. It should be in the next unsafe block.
|
|
||||||
let node: LayoutJS<Node> = unsafe {
|
|
||||||
LayoutJS::from_trusted_node_address(requested_node)
|
|
||||||
};
|
|
||||||
let node: &LayoutNode = unsafe {
|
|
||||||
transmute(&node)
|
|
||||||
};
|
|
||||||
|
|
||||||
let layout_node = ThreadSafeLayoutNode::new(node);
|
let layout_node = ThreadSafeLayoutNode::new(&node);
|
||||||
let layout_node = match pseudo {
|
let layout_node = match pseudo {
|
||||||
&Some(PseudoElement::Before) => layout_node.get_before_pseudo(),
|
&Some(PseudoElement::Before) => layout_node.get_before_pseudo(),
|
||||||
&Some(PseudoElement::After) => layout_node.get_after_pseudo(),
|
&Some(PseudoElement::After) => layout_node.get_after_pseudo(),
|
||||||
|
@ -1133,15 +1123,9 @@ impl LayoutTask {
|
||||||
};
|
};
|
||||||
let _ajst = AutoJoinScriptTask { data: data };
|
let _ajst = AutoJoinScriptTask { data: data };
|
||||||
|
|
||||||
// FIXME: Isolate this transmutation into a "bridge" module.
|
let document = unsafe { LayoutNode::new(&data.document) };
|
||||||
let mut doc: LayoutJS<Document> = unsafe {
|
let document = document.as_document().unwrap();
|
||||||
LayoutJS::from_trusted_node_address(data.document).downcast::<Document>().unwrap()
|
let node: LayoutNode = match document.root_node() {
|
||||||
};
|
|
||||||
let doc: &mut LayoutDocument = unsafe {
|
|
||||||
transmute(&mut doc)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut node: LayoutNode = match doc.root_node() {
|
|
||||||
None => return,
|
None => return,
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
};
|
};
|
||||||
|
@ -1187,7 +1171,7 @@ impl LayoutTask {
|
||||||
let needs_reflow = screen_size_changed && !needs_dirtying;
|
let needs_reflow = screen_size_changed && !needs_dirtying;
|
||||||
unsafe {
|
unsafe {
|
||||||
if needs_dirtying {
|
if needs_dirtying {
|
||||||
LayoutTask::dirty_all_nodes(&mut node);
|
LayoutTask::dirty_all_nodes(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if needs_reflow {
|
if needs_reflow {
|
||||||
|
@ -1196,11 +1180,12 @@ impl LayoutTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let event_state_changes = doc.drain_event_state_changes();
|
let state_changes = document.drain_element_state_changes();
|
||||||
if !needs_dirtying {
|
if !needs_dirtying {
|
||||||
for &(el, state) in event_state_changes.iter() {
|
for &(el, state_change) in state_changes.iter() {
|
||||||
assert!(!state.is_empty());
|
debug_assert!(!state_change.is_empty());
|
||||||
el.note_event_state_change();
|
let hint = rw_data.stylist.restyle_hint_for_state_change(&el, el.get_state(), state_change);
|
||||||
|
el.note_restyle_hint(hint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1229,7 +1214,7 @@ impl LayoutTask {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Retrieve the (possibly rebuilt) root flow.
|
// Retrieve the (possibly rebuilt) root flow.
|
||||||
rw_data.root_flow = self.try_get_layout_root(node.clone());
|
rw_data.root_flow = self.try_get_layout_root(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send new canvas renderers to the paint task
|
// Send new canvas renderers to the paint task
|
||||||
|
@ -1459,7 +1444,7 @@ impl LayoutTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn dirty_all_nodes(node: &mut LayoutNode) {
|
unsafe fn dirty_all_nodes(node: LayoutNode) {
|
||||||
for node in node.traverse_preorder() {
|
for node in node.traverse_preorder() {
|
||||||
// TODO(cgaebel): mark nodes which are sensitive to media queries as
|
// TODO(cgaebel): mark nodes which are sensitive to media queries as
|
||||||
// "changed":
|
// "changed":
|
||||||
|
|
|
@ -47,7 +47,7 @@ extern crate net_traits;
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
extern crate script;
|
extern crate script;
|
||||||
extern crate script_traits;
|
extern crate script_traits;
|
||||||
extern crate selectors;
|
#[macro_use(state_pseudo_classes)] extern crate selectors;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate smallvec;
|
extern crate smallvec;
|
||||||
|
|
|
@ -411,6 +411,8 @@ pub fn specified_or_none(length: LengthOrPercentageOrNone, containing_length: Au
|
||||||
match length {
|
match length {
|
||||||
LengthOrPercentageOrNone::None => None,
|
LengthOrPercentageOrNone::None => None,
|
||||||
LengthOrPercentageOrNone::Percentage(percent) => Some(containing_length.scale_by(percent)),
|
LengthOrPercentageOrNone::Percentage(percent) => Some(containing_length.scale_by(percent)),
|
||||||
|
LengthOrPercentageOrNone::Calc(calc) =>
|
||||||
|
Some(containing_length.scale_by(calc.percentage()) + calc.length()),
|
||||||
LengthOrPercentageOrNone::Length(length) => Some(length),
|
LengthOrPercentageOrNone::Length(length) => Some(length),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,7 @@ use script::dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
|
||||||
use script::dom::bindings::js::LayoutJS;
|
use script::dom::bindings::js::LayoutJS;
|
||||||
use script::dom::characterdata::LayoutCharacterDataHelpers;
|
use script::dom::characterdata::LayoutCharacterDataHelpers;
|
||||||
use script::dom::document::{Document, LayoutDocumentHelpers};
|
use script::dom::document::{Document, LayoutDocumentHelpers};
|
||||||
use script::dom::element;
|
use script::dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
|
||||||
use script::dom::element::{Element, EventState, LayoutElementHelpers, RawLayoutElementHelpers};
|
|
||||||
use script::dom::htmlcanvaselement::{LayoutHTMLCanvasElementHelpers, HTMLCanvasData};
|
use script::dom::htmlcanvaselement::{LayoutHTMLCanvasElementHelpers, HTMLCanvasData};
|
||||||
use script::dom::htmliframeelement::HTMLIFrameElement;
|
use script::dom::htmliframeelement::HTMLIFrameElement;
|
||||||
use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers;
|
use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers;
|
||||||
|
@ -52,8 +51,10 @@ use script::dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaEl
|
||||||
use script::dom::node::{HAS_CHANGED, HAS_DIRTY_DESCENDANTS, IS_DIRTY};
|
use script::dom::node::{HAS_CHANGED, HAS_DIRTY_DESCENDANTS, IS_DIRTY};
|
||||||
use script::dom::node::{LayoutNodeHelpers, Node, SharedLayoutData};
|
use script::dom::node::{LayoutNodeHelpers, Node, SharedLayoutData};
|
||||||
use script::dom::text::Text;
|
use script::dom::text::Text;
|
||||||
|
use script::layout_interface::TrustedNodeAddress;
|
||||||
use selectors::matching::DeclarationBlock;
|
use selectors::matching::DeclarationBlock;
|
||||||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||||
|
use selectors::states::*;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::{Ref, RefMut};
|
use std::cell::{Ref, RefMut};
|
||||||
|
@ -68,6 +69,7 @@ use style::legacy::UnsignedIntegerAttribute;
|
||||||
use style::node::TElementAttributes;
|
use style::node::TElementAttributes;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
||||||
|
use style::restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::str::{is_whitespace, search_index};
|
use util::str::{is_whitespace, search_index};
|
||||||
|
|
||||||
|
@ -79,7 +81,7 @@ pub struct LayoutNode<'a> {
|
||||||
node: LayoutJS<Node>,
|
node: LayoutJS<Node>,
|
||||||
|
|
||||||
/// Being chained to a PhantomData prevents `LayoutNode`s from escaping.
|
/// Being chained to a PhantomData prevents `LayoutNode`s from escaping.
|
||||||
pub chain: PhantomData<&'a ()>,
|
chain: PhantomData<&'a ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PartialEq for LayoutNode<'a> {
|
impl<'a> PartialEq for LayoutNode<'a> {
|
||||||
|
@ -90,6 +92,14 @@ impl<'a> PartialEq for LayoutNode<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> LayoutNode<'ln> {
|
impl<'ln> LayoutNode<'ln> {
|
||||||
|
pub unsafe fn new(address: &TrustedNodeAddress) -> LayoutNode {
|
||||||
|
let node = LayoutJS::from_trusted_node_address(*address);
|
||||||
|
LayoutNode {
|
||||||
|
node: node,
|
||||||
|
chain: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new layout node with the same lifetime as this layout node.
|
/// Creates a new layout node with the same lifetime as this layout node.
|
||||||
pub unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> LayoutNode<'ln> {
|
pub unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> LayoutNode<'ln> {
|
||||||
LayoutNode {
|
LayoutNode {
|
||||||
|
@ -205,6 +215,15 @@ impl<'ln> LayoutNode<'ln> {
|
||||||
as_element(self.node)
|
as_element(self.node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_document(&self) -> Option<LayoutDocument<'ln>> {
|
||||||
|
self.node.downcast().map(|document| {
|
||||||
|
LayoutDocument {
|
||||||
|
document: document,
|
||||||
|
chain: PhantomData,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn parent_node(&self) -> Option<LayoutNode<'ln>> {
|
fn parent_node(&self) -> Option<LayoutNode<'ln>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
|
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||||
|
@ -353,16 +372,12 @@ impl<'le> LayoutDocument<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root_node(&self) -> Option<LayoutNode<'le>> {
|
pub fn root_node(&self) -> Option<LayoutNode<'le>> {
|
||||||
let mut node = self.as_node().first_child();
|
self.as_node().children().find(LayoutNode::is_element)
|
||||||
while node.is_some() && !node.unwrap().is_element() {
|
|
||||||
node = node.unwrap().next_sibling();
|
|
||||||
}
|
|
||||||
node
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drain_event_state_changes(&self) -> Vec<(LayoutElement, EventState)> {
|
pub fn drain_element_state_changes(&self) -> Vec<(LayoutElement, ElementState)> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let changes = self.document.drain_event_state_changes();
|
let changes = self.document.drain_element_state_changes();
|
||||||
Vec::from_iter(changes.iter().map(|&(el, state)|
|
Vec::from_iter(changes.iter().map(|&(el, state)|
|
||||||
(LayoutElement {
|
(LayoutElement {
|
||||||
element: el,
|
element: el,
|
||||||
|
@ -393,39 +408,58 @@ impl<'le> LayoutElement<'le> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Properly marks nodes as dirty in response to event state changes.
|
pub fn get_state(&self) -> ElementState {
|
||||||
///
|
self.element.get_state_for_layout()
|
||||||
/// Currently this implementation is very conservative, and basically mirrors node::dirty_impl.
|
}
|
||||||
/// With restyle hints, we can do less work here.
|
|
||||||
pub fn note_event_state_change(&self) {
|
/// Properly marks nodes as dirty in response to restyle hints.
|
||||||
|
pub fn note_restyle_hint(&self, hint: RestyleHint) {
|
||||||
|
// Bail early if there's no restyling to do.
|
||||||
|
if hint.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the restyle hint is non-empty, we need to restyle either this element
|
||||||
|
// or one of its siblings. Mark our ancestor chain as having dirty descendants.
|
||||||
let node = self.as_node();
|
let node = self.as_node();
|
||||||
|
|
||||||
// Bail out if we're already dirty. This won't be valid when we start doing more targeted
|
|
||||||
// dirtying with restyle hints.
|
|
||||||
if node.is_dirty() { return }
|
|
||||||
|
|
||||||
// Dirty descendants.
|
|
||||||
fn dirty_subtree(node: LayoutNode) {
|
|
||||||
// Stop if this subtree is already dirty. This won't be valid with restyle hints, see above.
|
|
||||||
if node.is_dirty() { return }
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
node.set_dirty(true);
|
|
||||||
node.set_dirty_descendants(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
for kid in node.children() {
|
|
||||||
dirty_subtree(kid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dirty_subtree(node);
|
|
||||||
|
|
||||||
let mut curr = node;
|
let mut curr = node;
|
||||||
while let Some(parent) = curr.parent_node() {
|
while let Some(parent) = curr.parent_node() {
|
||||||
if parent.has_dirty_descendants() { break }
|
if parent.has_dirty_descendants() { break }
|
||||||
unsafe { parent.set_dirty_descendants(true); }
|
unsafe { parent.set_dirty_descendants(true); }
|
||||||
curr = parent;
|
curr = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up our helpers.
|
||||||
|
fn dirty_node(node: &LayoutNode) {
|
||||||
|
unsafe {
|
||||||
|
node.set_dirty(true);
|
||||||
|
node.set_dirty_descendants(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn dirty_descendants(node: &LayoutNode) {
|
||||||
|
for ref child in node.children() {
|
||||||
|
dirty_node(child);
|
||||||
|
dirty_descendants(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process hints.
|
||||||
|
if hint.contains(RESTYLE_SELF) {
|
||||||
|
dirty_node(&node);
|
||||||
|
}
|
||||||
|
if hint.contains(RESTYLE_DESCENDANTS) {
|
||||||
|
unsafe { node.set_dirty_descendants(true); }
|
||||||
|
dirty_descendants(&node);
|
||||||
|
}
|
||||||
|
if hint.contains(RESTYLE_LATER_SIBLINGS) {
|
||||||
|
let mut next = ::selectors::Element::next_sibling_element(self);
|
||||||
|
while let Some(sib) = next {
|
||||||
|
let sib_node = sib.as_node();
|
||||||
|
dirty_node(&sib_node);
|
||||||
|
dirty_descendants(&sib_node);
|
||||||
|
next = ::selectors::Element::next_sibling_element(&sib);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,6 +472,15 @@ fn as_element<'le>(node: LayoutJS<Node>) -> Option<LayoutElement<'le>> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! state_getter {
|
||||||
|
($(
|
||||||
|
$(#[$Flag_attr: meta])*
|
||||||
|
state $css: expr => $variant: ident / $method: ident /
|
||||||
|
$flag: ident = $value: expr,
|
||||||
|
)+) => {
|
||||||
|
$( fn $method(&self) -> bool { self.element.get_state_for_layout().contains($flag) } )+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'le> ::selectors::Element for LayoutElement<'le> {
|
impl<'le> ::selectors::Element for LayoutElement<'le> {
|
||||||
fn parent_element(&self) -> Option<LayoutElement<'le>> {
|
fn parent_element(&self) -> Option<LayoutElement<'le>> {
|
||||||
|
@ -529,20 +572,7 @@ impl<'le> ::selectors::Element for LayoutElement<'le> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
state_pseudo_classes!(state_getter);
|
||||||
fn get_hover_state(&self) -> bool {
|
|
||||||
self.element.get_event_state_for_layout().contains(element::IN_HOVER_STATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_focus_state(&self) -> bool {
|
|
||||||
self.element.get_event_state_for_layout().contains(element::IN_FOCUS_STATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_active_state(&self) -> bool {
|
|
||||||
self.element.get_event_state_for_layout().contains(element::IN_ACTIVE_STATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_id(&self) -> Option<Atom> {
|
fn get_id(&self) -> Option<Atom> {
|
||||||
|
@ -551,26 +581,6 @@ impl<'le> ::selectors::Element for LayoutElement<'le> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_disabled_state(&self) -> bool {
|
|
||||||
self.element.get_event_state_for_layout().contains(element::IN_DISABLED_STATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_enabled_state(&self) -> bool {
|
|
||||||
self.element.get_event_state_for_layout().contains(element::IN_ENABLED_STATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_checked_state(&self) -> bool {
|
|
||||||
self.element.get_checked_state_for_layout()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get_indeterminate_state(&self) -> bool {
|
|
||||||
self.element.get_indeterminate_state_for_layout()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn has_class(&self, name: &Atom) -> bool {
|
fn has_class(&self, name: &Atom) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -16,6 +16,9 @@ path = "../util"
|
||||||
[dependencies.devtools_traits]
|
[dependencies.devtools_traits]
|
||||||
path = "../devtools_traits"
|
path = "../devtools_traits"
|
||||||
|
|
||||||
|
[dependencies.brotli]
|
||||||
|
git = "https://github.com/ende76/brotli-rs"
|
||||||
|
|
||||||
[dependencies.plugins]
|
[dependencies.plugins]
|
||||||
path = "../plugins"
|
path = "../plugins"
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||||
use mime_classifier::MIMEClassifier;
|
use mime_classifier::MIMEClassifier;
|
||||||
use net_traits::ProgressMsg::Done;
|
use net_traits::ProgressMsg::Done;
|
||||||
use net_traits::{LoadConsumer, LoadData, Metadata};
|
use net_traits::{LoadConsumer, LoadData, Metadata};
|
||||||
use resource_task::{send_error, start_sending};
|
use resource_task::{send_error, start_sending_sniffed_opt};
|
||||||
use std::fs::PathExt;
|
use std::fs::PathExt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -18,14 +18,16 @@ use util::resource_files::resources_dir_path;
|
||||||
pub fn factory(mut load_data: LoadData, start_chan: LoadConsumer, classifier: Arc<MIMEClassifier>) {
|
pub fn factory(mut load_data: LoadData, start_chan: LoadConsumer, classifier: Arc<MIMEClassifier>) {
|
||||||
match load_data.url.non_relative_scheme_data().unwrap() {
|
match load_data.url.non_relative_scheme_data().unwrap() {
|
||||||
"blank" => {
|
"blank" => {
|
||||||
let chan = start_sending(start_chan, Metadata {
|
let metadata = Metadata {
|
||||||
final_url: load_data.url,
|
final_url: load_data.url,
|
||||||
content_type: Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]))),
|
content_type: Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]))),
|
||||||
charset: Some("utf-8".to_owned()),
|
charset: Some("utf-8".to_owned()),
|
||||||
headers: None,
|
headers: None,
|
||||||
status: Some(RawStatus(200, "OK".into())),
|
status: Some(RawStatus(200, "OK".into())),
|
||||||
});
|
};
|
||||||
chan.send(Done(Ok(()))).unwrap();
|
if let Ok(chan) = start_sending_sniffed_opt(start_chan, metadata, classifier, &[]) {
|
||||||
|
let _ = chan.send(Done(Ok(())));
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
"crash" => panic!("Loading the about:crash URL."),
|
"crash" => panic!("Loading the about:crash URL."),
|
||||||
|
|
|
@ -6,21 +6,21 @@ use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
|
||||||
use mime_classifier::MIMEClassifier;
|
use mime_classifier::MIMEClassifier;
|
||||||
use net_traits::ProgressMsg::{Done, Payload};
|
use net_traits::ProgressMsg::{Done, Payload};
|
||||||
use net_traits::{LoadConsumer, LoadData, Metadata};
|
use net_traits::{LoadConsumer, LoadData, Metadata};
|
||||||
use resource_task::{send_error, start_sending};
|
use resource_task::{send_error, start_sending_sniffed_opt};
|
||||||
use rustc_serialize::base64::FromBase64;
|
use rustc_serialize::base64::FromBase64;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use url::SchemeData;
|
use url::SchemeData;
|
||||||
use url::percent_encoding::percent_decode;
|
use url::percent_encoding::percent_decode;
|
||||||
|
|
||||||
pub fn factory(load_data: LoadData, senders: LoadConsumer, _classifier: Arc<MIMEClassifier>) {
|
pub fn factory(load_data: LoadData, senders: LoadConsumer, classifier: Arc<MIMEClassifier>) {
|
||||||
// NB: we don't spawn a new task.
|
// NB: we don't spawn a new task.
|
||||||
// Hypothesis: data URLs are too small for parallel base64 etc. to be worth it.
|
// Hypothesis: data URLs are too small for parallel base64 etc. to be worth it.
|
||||||
// Should be tested at some point.
|
// Should be tested at some point.
|
||||||
// Left in separate function to allow easy moving to a task, if desired.
|
// Left in separate function to allow easy moving to a task, if desired.
|
||||||
load(load_data, senders)
|
load(load_data, senders, classifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(load_data: LoadData, start_chan: LoadConsumer) {
|
pub fn load(load_data: LoadData, start_chan: LoadConsumer, classifier: Arc<MIMEClassifier>) {
|
||||||
let url = load_data.url;
|
let url = load_data.url;
|
||||||
assert!(&*url.scheme == "data");
|
assert!(&*url.scheme == "data");
|
||||||
|
|
||||||
|
@ -62,27 +62,25 @@ pub fn load(load_data: LoadData, start_chan: LoadConsumer) {
|
||||||
content_type = Some(Mime(TopLevel::Text, SubLevel::Plain,
|
content_type = Some(Mime(TopLevel::Text, SubLevel::Plain,
|
||||||
vec!((Attr::Charset, Value::Ext("US-ASCII".to_owned())))));
|
vec!((Attr::Charset, Value::Ext("US-ASCII".to_owned())))));
|
||||||
}
|
}
|
||||||
let mut metadata = Metadata::default(url);
|
|
||||||
metadata.set_content_type(content_type.as_ref());
|
|
||||||
|
|
||||||
let progress_chan = start_sending(start_chan, metadata);
|
|
||||||
let bytes = percent_decode(parts[1].as_bytes());
|
let bytes = percent_decode(parts[1].as_bytes());
|
||||||
|
|
||||||
if is_base64 {
|
let bytes = if is_base64 {
|
||||||
// FIXME(#2909): It’s unclear what to do with non-alphabet characters,
|
// FIXME(#2909): It’s unclear what to do with non-alphabet characters,
|
||||||
// but Acid 3 apparently depends on spaces being ignored.
|
// but Acid 3 apparently depends on spaces being ignored.
|
||||||
let bytes = bytes.into_iter().filter(|&b| b != ' ' as u8).collect::<Vec<u8>>();
|
let bytes = bytes.into_iter().filter(|&b| b != ' ' as u8).collect::<Vec<u8>>();
|
||||||
match bytes.from_base64() {
|
match bytes.from_base64() {
|
||||||
Err(..) => {
|
Err(..) => return send_error(url, "non-base64 data uri".to_owned(), start_chan),
|
||||||
progress_chan.send(Done(Err("non-base64 data uri".to_owned()))).unwrap();
|
Ok(data) => data,
|
||||||
}
|
|
||||||
Ok(data) => {
|
|
||||||
progress_chan.send(Payload(data)).unwrap();
|
|
||||||
progress_chan.send(Done(Ok(()))).unwrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
progress_chan.send(Payload(bytes)).unwrap();
|
bytes
|
||||||
progress_chan.send(Done(Ok(()))).unwrap();
|
};
|
||||||
|
|
||||||
|
let mut metadata = Metadata::default(url);
|
||||||
|
metadata.set_content_type(content_type.as_ref());
|
||||||
|
if let Ok(chan) = start_sending_sniffed_opt(start_chan, metadata, classifier, &bytes) {
|
||||||
|
let _ = chan.send(Payload(bytes));
|
||||||
|
let _ = chan.send(Done(Ok(())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use mime_classifier::MIMEClassifier;
|
use mime_classifier::MIMEClassifier;
|
||||||
use net_traits::ProgressMsg::{Done, Payload};
|
use net_traits::ProgressMsg::{Done, Payload};
|
||||||
use net_traits::{LoadConsumer, LoadData, Metadata};
|
use net_traits::{LoadConsumer, LoadData, Metadata};
|
||||||
use resource_task::{ProgressSender, send_error, start_sending, start_sending_sniffed};
|
use resource_task::{ProgressSender, send_error, start_sending_sniffed, start_sending_sniffed_opt};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -52,19 +52,28 @@ pub fn factory(load_data: LoadData, senders: LoadConsumer, classifier: Arc<MIMEC
|
||||||
Ok(file_path) => {
|
Ok(file_path) => {
|
||||||
match File::open(&file_path) {
|
match File::open(&file_path) {
|
||||||
Ok(ref mut reader) => {
|
Ok(ref mut reader) => {
|
||||||
let metadata = Metadata::default(url);
|
match read_block(reader) {
|
||||||
let res = read_block(reader);
|
|
||||||
let (res, progress_chan) = match res {
|
|
||||||
Ok(ReadStatus::Partial(buf)) => {
|
Ok(ReadStatus::Partial(buf)) => {
|
||||||
|
let metadata = Metadata::default(url);
|
||||||
let progress_chan = start_sending_sniffed(senders, metadata,
|
let progress_chan = start_sending_sniffed(senders, metadata,
|
||||||
classifier, &buf);
|
classifier, &buf);
|
||||||
progress_chan.send(Payload(buf)).unwrap();
|
progress_chan.send(Payload(buf)).unwrap();
|
||||||
(read_all(reader, &progress_chan), progress_chan)
|
let res = read_all(reader, &progress_chan);
|
||||||
|
let _ = progress_chan.send(Done(res));
|
||||||
|
}
|
||||||
|
Ok(ReadStatus::EOF) => {
|
||||||
|
let metadata = Metadata::default(url);
|
||||||
|
if let Ok(chan) = start_sending_sniffed_opt(senders,
|
||||||
|
metadata,
|
||||||
|
classifier,
|
||||||
|
&[]) {
|
||||||
|
let _ = chan.send(Done(Ok(())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
send_error(url, e, senders);
|
||||||
}
|
}
|
||||||
Ok(ReadStatus::EOF) | Err(_) =>
|
|
||||||
(res.map(|_| ()), start_sending(senders, metadata)),
|
|
||||||
};
|
};
|
||||||
progress_chan.send(Done(res)).unwrap();
|
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
send_error(url, e.description().to_owned(), senders);
|
send_error(url, e.description().to_owned(), senders);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
|
||||||
|
use brotli::Decompressor;
|
||||||
use cookie;
|
use cookie;
|
||||||
use cookie_storage::CookieStorage;
|
use cookie_storage::CookieStorage;
|
||||||
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, HttpRequest as DevtoolsHttpRequest};
|
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, HttpRequest as DevtoolsHttpRequest};
|
||||||
|
@ -154,10 +155,9 @@ pub trait HttpResponse: Read {
|
||||||
Some(Encoding::Gzip)
|
Some(Encoding::Gzip)
|
||||||
} else if encodings.contains(&Encoding::Deflate) {
|
} else if encodings.contains(&Encoding::Deflate) {
|
||||||
Some(Encoding::Deflate)
|
Some(Encoding::Deflate)
|
||||||
} else {
|
} else if encodings.contains(&Encoding::EncodingExt("br".to_owned())) {
|
||||||
// TODO: Is this the correct behaviour?
|
Some(Encoding::EncodingExt("br".to_owned()))
|
||||||
None
|
} else { None }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -302,7 +302,8 @@ fn set_default_accept_encoding(headers: &mut Headers) {
|
||||||
|
|
||||||
headers.set(AcceptEncoding(vec![
|
headers.set(AcceptEncoding(vec![
|
||||||
qitem(Encoding::Gzip),
|
qitem(Encoding::Gzip),
|
||||||
qitem(Encoding::Deflate)
|
qitem(Encoding::Deflate),
|
||||||
|
qitem(Encoding::EncodingExt("br".to_owned()))
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,6 +395,7 @@ impl<R: HttpResponse> Read for StreamedResponse<R> {
|
||||||
match self.decoder {
|
match self.decoder {
|
||||||
Decoder::Gzip(ref mut d) => d.read(buf),
|
Decoder::Gzip(ref mut d) => d.read(buf),
|
||||||
Decoder::Deflate(ref mut d) => d.read(buf),
|
Decoder::Deflate(ref mut d) => d.read(buf),
|
||||||
|
Decoder::Brotli(ref mut d) => d.read(buf),
|
||||||
Decoder::Plain(ref mut d) => d.read(buf)
|
Decoder::Plain(ref mut d) => d.read(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,6 +423,10 @@ impl<R: HttpResponse> StreamedResponse<R> {
|
||||||
let response_decoding = DeflateDecoder::new(response);
|
let response_decoding = DeflateDecoder::new(response);
|
||||||
Ok(StreamedResponse::new(m, Decoder::Deflate(response_decoding)))
|
Ok(StreamedResponse::new(m, Decoder::Deflate(response_decoding)))
|
||||||
}
|
}
|
||||||
|
Some(Encoding::EncodingExt(ref ext)) if ext == "br" => {
|
||||||
|
let response_decoding = Decompressor::new(response);
|
||||||
|
Ok(StreamedResponse::new(m, Decoder::Brotli(response_decoding)))
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
Ok(StreamedResponse::new(m, Decoder::Plain(response)))
|
Ok(StreamedResponse::new(m, Decoder::Plain(response)))
|
||||||
}
|
}
|
||||||
|
@ -431,6 +437,7 @@ impl<R: HttpResponse> StreamedResponse<R> {
|
||||||
enum Decoder<R: Read> {
|
enum Decoder<R: Read> {
|
||||||
Gzip(GzDecoder<R>),
|
Gzip(GzDecoder<R>),
|
||||||
Deflate(DeflateDecoder<R>),
|
Deflate(DeflateDecoder<R>),
|
||||||
|
Brotli(Decompressor<R>),
|
||||||
Plain(R)
|
Plain(R)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ extern crate cookie as cookie_rs;
|
||||||
extern crate devtools_traits;
|
extern crate devtools_traits;
|
||||||
extern crate euclid;
|
extern crate euclid;
|
||||||
extern crate flate2;
|
extern crate flate2;
|
||||||
|
extern crate brotli;
|
||||||
extern crate hyper;
|
extern crate hyper;
|
||||||
extern crate ipc_channel;
|
extern crate ipc_channel;
|
||||||
extern crate net_traits;
|
extern crate net_traits;
|
||||||
|
|
|
@ -59,11 +59,6 @@ pub fn send_error(url: Url, err: String, start_chan: LoadConsumer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For use by loaders in responding to a Load message.
|
|
||||||
pub fn start_sending(start_chan: LoadConsumer, metadata: Metadata) -> ProgressSender {
|
|
||||||
start_sending_opt(start_chan, metadata).ok().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// For use by loaders in responding to a Load message that allows content sniffing.
|
/// For use by loaders in responding to a Load message that allows content sniffing.
|
||||||
pub fn start_sending_sniffed(start_chan: LoadConsumer, metadata: Metadata,
|
pub fn start_sending_sniffed(start_chan: LoadConsumer, metadata: Metadata,
|
||||||
classifier: Arc<MIMEClassifier>, partial_body: &[u8])
|
classifier: Arc<MIMEClassifier>, partial_body: &[u8])
|
||||||
|
@ -122,7 +117,7 @@ fn apache_bug_predicate(last_raw_content_type: &[u8]) -> ApacheBugFlag {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For use by loaders in responding to a Load message.
|
/// For use by loaders in responding to a Load message.
|
||||||
pub fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata) -> Result<ProgressSender, ()> {
|
fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata) -> Result<ProgressSender, ()> {
|
||||||
match start_chan {
|
match start_chan {
|
||||||
LoadConsumer::Channel(start_chan) => {
|
LoadConsumer::Channel(start_chan) => {
|
||||||
let (progress_chan, progress_port) = ipc::channel().unwrap();
|
let (progress_chan, progress_port) = ipc::channel().unwrap();
|
||||||
|
@ -253,8 +248,7 @@ impl ResourceManager {
|
||||||
"about" => from_factory(about_loader::factory),
|
"about" => from_factory(about_loader::factory),
|
||||||
_ => {
|
_ => {
|
||||||
debug!("resource_task: no loader for scheme {}", load_data.url.scheme);
|
debug!("resource_task: no loader for scheme {}", load_data.url.scheme);
|
||||||
start_sending(consumer, Metadata::default(load_data.url))
|
send_error(load_data.url, "no loader for scheme".to_owned(), consumer);
|
||||||
.send(ProgressMsg::Done(Err("no loader for scheme".to_owned()))).unwrap();
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,8 @@ use std::env::var_os;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::path::Path;
|
||||||
|
use util::opts;
|
||||||
|
|
||||||
|
|
||||||
static mut HBS: Option<*mut HashMap<ProfilerCategory, Heartbeat>> = None;
|
static mut HBS: Option<*mut HashMap<ProfilerCategory, Heartbeat>> = None;
|
||||||
|
@ -72,6 +74,7 @@ pub fn cleanup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if a heartbeat exists for the given category
|
||||||
pub fn is_heartbeat_enabled(category: &ProfilerCategory) -> bool {
|
pub fn is_heartbeat_enabled(category: &ProfilerCategory) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
HBS.map_or(false, |m| (*m).contains_key(category))
|
HBS.map_or(false, |m| (*m).contains_key(category))
|
||||||
|
@ -93,22 +96,51 @@ pub fn maybe_heartbeat(category: &ProfilerCategory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a heartbeat if the correct environment variable is set
|
// TODO(cimes): Android doesn't really do environment variables. Need a better way to configure dynamically.
|
||||||
fn maybe_create_heartbeat(hbs: &mut HashMap<ProfilerCategory, Heartbeat>,
|
|
||||||
category: ProfilerCategory) {
|
fn is_create_heartbeat(category: &ProfilerCategory) -> bool {
|
||||||
static WINDOW_SIZE_DEFAULT: usize = 20;
|
opts::get().profile_heartbeats || var_os(format!("SERVO_HEARTBEAT_ENABLE_{:?}", category)).is_some()
|
||||||
if let Some(_) = var_os(format!("SERVO_HEARTBEAT_ENABLE_{:?}", category)) {
|
}
|
||||||
// get optional log file
|
|
||||||
let logfile: Option<File> = var_os(format!("SERVO_HEARTBEAT_LOG_{:?}", category))
|
fn open_heartbeat_log<P: AsRef<Path>>(name: P) -> Option<File> {
|
||||||
.and_then(|name| File::create(name).ok());
|
match File::create(name) {
|
||||||
// get window size
|
Ok(f) => Some(f),
|
||||||
let window_size: usize = match var_os(format!("SERVO_HEARTBEAT_WINDOW_{:?}", category)) {
|
Err(e) => {
|
||||||
|
warn!("Failed to open heartbeat log: {}", Error::description(&e));
|
||||||
|
None
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
fn get_heartbeat_log(category: &ProfilerCategory) -> Option<File> {
|
||||||
|
open_heartbeat_log(format!("/sdcard/servo/heartbeat-{:?}.log", category))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
|
fn get_heartbeat_log(category: &ProfilerCategory) -> Option<File> {
|
||||||
|
var_os(format!("SERVO_HEARTBEAT_LOG_{:?}", category)).and_then(|name| open_heartbeat_log(&name))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_heartbeat_window_size(category: &ProfilerCategory) -> usize {
|
||||||
|
const WINDOW_SIZE_DEFAULT: usize = 1;
|
||||||
|
match var_os(format!("SERVO_HEARTBEAT_WINDOW_{:?}", category)) {
|
||||||
Some(w) => match w.into_string() {
|
Some(w) => match w.into_string() {
|
||||||
Ok(s) => s.parse::<usize>().unwrap_or(WINDOW_SIZE_DEFAULT),
|
Ok(s) => s.parse::<usize>().unwrap_or(WINDOW_SIZE_DEFAULT),
|
||||||
_ => WINDOW_SIZE_DEFAULT,
|
_ => WINDOW_SIZE_DEFAULT,
|
||||||
},
|
},
|
||||||
None => WINDOW_SIZE_DEFAULT,
|
None => WINDOW_SIZE_DEFAULT,
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Possibly create a heartbeat
|
||||||
|
fn maybe_create_heartbeat(hbs: &mut HashMap<ProfilerCategory, Heartbeat>,
|
||||||
|
category: ProfilerCategory) {
|
||||||
|
if is_create_heartbeat(&category) {
|
||||||
|
// get optional log file
|
||||||
|
let logfile: Option<File> = get_heartbeat_log(&category);
|
||||||
|
// window size
|
||||||
|
let window_size: usize = get_heartbeat_window_size(&category);
|
||||||
// create the heartbeat
|
// create the heartbeat
|
||||||
match Heartbeat::new(window_size, Some(heartbeat_window_callback), logfile) {
|
match Heartbeat::new(window_size, Some(heartbeat_window_callback), logfile) {
|
||||||
Ok(hb) => {
|
Ok(hb) => {
|
||||||
|
|
|
@ -19,7 +19,7 @@ features = [ "serde_serialization" ]
|
||||||
|
|
||||||
[dependencies.energymon]
|
[dependencies.energymon]
|
||||||
git = "https://github.com/energymon/energymon-rust.git"
|
git = "https://github.com/energymon/energymon-rust.git"
|
||||||
rev = "67f74732ac"
|
rev = "eba1d8a"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.energy-monitor]
|
[dependencies.energy-monitor]
|
||||||
|
|
|
@ -36,8 +36,8 @@ mod energymon {
|
||||||
|
|
||||||
static mut EM: Option<*mut EnergyMon> = None;
|
static mut EM: Option<*mut EnergyMon> = None;
|
||||||
|
|
||||||
/// Read energy from the energy monitor, otherwise return 0.
|
fn init() {
|
||||||
pub fn read_energy_uj() -> u64 {
|
// can't use lazy_static macro for EM (no Sync trait for EnergyMon)
|
||||||
static ONCE: Once = ONCE_INIT;
|
static ONCE: Once = ONCE_INIT;
|
||||||
ONCE.call_once(|| {
|
ONCE.call_once(|| {
|
||||||
if let Ok(em) = EnergyMon::new() {
|
if let Ok(em) = EnergyMon::new() {
|
||||||
|
@ -47,7 +47,11 @@ mod energymon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read energy from the energy monitor, otherwise return 0.
|
||||||
|
pub fn read_energy_uj() -> u64 {
|
||||||
|
init();
|
||||||
unsafe {
|
unsafe {
|
||||||
// EnergyMon implementations of EnergyMonitor always return a value
|
// EnergyMon implementations of EnergyMonitor always return a value
|
||||||
EM.map_or(0, |em| (*em).read_uj().unwrap())
|
EM.map_or(0, |em| (*em).read_uj().unwrap())
|
||||||
|
@ -55,6 +59,7 @@ mod energymon {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_min_interval_ms() -> u32 {
|
pub fn get_min_interval_ms() -> u32 {
|
||||||
|
init();
|
||||||
unsafe {
|
unsafe {
|
||||||
EM.map_or(0, |em| ((*em).interval_us() as f64 / 1000.0).ceil() as u32)
|
EM.map_or(0, |em| ((*em).interval_us() as f64 / 1000.0).ceil() as u32)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2000,6 +2000,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
|
||||||
'dom::bindings::conversions::StringificationBehavior',
|
'dom::bindings::conversions::StringificationBehavior',
|
||||||
'dom::bindings::error::throw_not_in_union',
|
'dom::bindings::error::throw_not_in_union',
|
||||||
'dom::bindings::js::Root',
|
'dom::bindings::js::Root',
|
||||||
|
'dom::bindings::str::USVString',
|
||||||
'dom::types::*',
|
'dom::types::*',
|
||||||
'js::jsapi::JSContext',
|
'js::jsapi::JSContext',
|
||||||
'js::jsapi::{HandleValue, MutableHandleValue}',
|
'js::jsapi::{HandleValue, MutableHandleValue}',
|
||||||
|
@ -3492,6 +3493,9 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
|
||||||
elif type.isDOMString():
|
elif type.isDOMString():
|
||||||
name = type.name
|
name = type.name
|
||||||
typeName = "DOMString"
|
typeName = "DOMString"
|
||||||
|
elif type.isUSVString():
|
||||||
|
name = type.name
|
||||||
|
typeName = "USVString"
|
||||||
elif type.isPrimitive():
|
elif type.isPrimitive():
|
||||||
name = type.name
|
name = type.name
|
||||||
typeName = builtinNames[type.tag()]
|
typeName = builtinNames[type.tag()]
|
||||||
|
|
|
@ -230,8 +230,8 @@ impl GlobalField {
|
||||||
/// Create a stack-bounded root for this reference.
|
/// Create a stack-bounded root for this reference.
|
||||||
pub fn root(&self) -> GlobalRoot {
|
pub fn root(&self) -> GlobalRoot {
|
||||||
match *self {
|
match *self {
|
||||||
GlobalField::Window(ref window) => GlobalRoot::Window(window.root()),
|
GlobalField::Window(ref window) => GlobalRoot::Window(Root::from_ref(window)),
|
||||||
GlobalField::Worker(ref worker) => GlobalRoot::Worker(worker.root()),
|
GlobalField::Worker(ref worker) => GlobalRoot::Worker(Root::from_ref(worker)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,10 +74,6 @@ impl<T> JS<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Reflectable> JS<T> {
|
impl<T: Reflectable> JS<T> {
|
||||||
/// Root this JS-owned value to prevent its collection as garbage.
|
|
||||||
pub fn root(&self) -> Root<T> {
|
|
||||||
Root::new(self.ptr)
|
|
||||||
}
|
|
||||||
/// Create a JS<T> from a Root<T>
|
/// Create a JS<T> from a Root<T>
|
||||||
/// XXX Not a great API. Should be a call on Root<T> instead
|
/// XXX Not a great API. Should be a call on Root<T> instead
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
|
@ -292,7 +288,7 @@ impl<T: Reflectable> MutHeap<JS<T>> {
|
||||||
pub fn get(&self) -> Root<T> {
|
pub fn get(&self) -> Root<T> {
|
||||||
debug_assert!(task_state::get().is_script());
|
debug_assert!(task_state::get().is_script());
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::read(self.val.get()).root()
|
Root::from_ref(&*ptr::read(self.val.get()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,7 +366,7 @@ impl<T: Reflectable> MutNullableHeap<JS<T>> {
|
||||||
pub fn get(&self) -> Option<Root<T>> {
|
pub fn get(&self) -> Option<Root<T>> {
|
||||||
debug_assert!(task_state::get().is_script());
|
debug_assert!(task_state::get().is_script());
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::read(self.ptr.get()).map(|o| o.root())
|
ptr::read(self.ptr.get()).map(|o| Root::from_ref(&*o))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
//! The `Finite<T>` struct.
|
//! The `Finite<T>` struct.
|
||||||
|
|
||||||
use core::nonzero::Zeroable;
|
|
||||||
use num::Float;
|
use num::Float;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
@ -12,8 +11,6 @@ use std::ops::Deref;
|
||||||
#[derive(JSTraceable, Clone, Copy, Eq, PartialEq)]
|
#[derive(JSTraceable, Clone, Copy, Eq, PartialEq)]
|
||||||
pub struct Finite<T: Float>(T);
|
pub struct Finite<T: Float>(T);
|
||||||
|
|
||||||
unsafe impl<T: Float> Zeroable for Finite<T> {}
|
|
||||||
|
|
||||||
impl<T: Float> Finite<T> {
|
impl<T: Float> Finite<T> {
|
||||||
/// Create a new `Finite<T: Float>` safely.
|
/// Create a new `Finite<T: Float>` safely.
|
||||||
pub fn new(value: T) -> Option<Finite<T>> {
|
pub fn new(value: T) -> Option<Finite<T>> {
|
||||||
|
|
|
@ -63,10 +63,11 @@ use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
||||||
use script_task::ScriptChan;
|
use script_task::ScriptChan;
|
||||||
use script_traits::{TimerEventChan, TimerEventId, TimerSource, UntrustedNodeAddress};
|
use script_traits::{TimerEventChan, TimerEventId, TimerSource, UntrustedNodeAddress};
|
||||||
use selectors::parser::PseudoElement;
|
use selectors::parser::PseudoElement;
|
||||||
|
use selectors::states::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::boxed::FnBox;
|
use std::boxed::FnBox;
|
||||||
use std::cell::{Cell, RefCell, UnsafeCell};
|
use std::cell::{Cell, UnsafeCell};
|
||||||
use std::collections::hash_state::HashState;
|
use std::collections::hash_state::HashState;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
@ -139,12 +140,6 @@ pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: &Heap<*mut JS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: JSTraceable> JSTraceable for RefCell<T> {
|
|
||||||
fn trace(&self, trc: *mut JSTracer) {
|
|
||||||
self.borrow().trace(trc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: JSTraceable> JSTraceable for Rc<T> {
|
impl<T: JSTraceable> JSTraceable for Rc<T> {
|
||||||
fn trace(&self, trc: *mut JSTracer) {
|
fn trace(&self, trc: *mut JSTracer) {
|
||||||
(**self).trace(trc)
|
(**self).trace(trc)
|
||||||
|
@ -157,26 +152,6 @@ impl<T: JSTraceable> JSTraceable for Box<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: JSTraceable> JSTraceable for *const T {
|
|
||||||
fn trace(&self, trc: *mut JSTracer) {
|
|
||||||
if !self.is_null() {
|
|
||||||
unsafe {
|
|
||||||
(**self).trace(trc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: JSTraceable> JSTraceable for *mut T {
|
|
||||||
fn trace(&self, trc: *mut JSTracer) {
|
|
||||||
if !self.is_null() {
|
|
||||||
unsafe {
|
|
||||||
(**self).trace(trc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: JSTraceable + Copy> JSTraceable for Cell<T> {
|
impl<T: JSTraceable + Copy> JSTraceable for Cell<T> {
|
||||||
fn trace(&self, trc: *mut JSTracer) {
|
fn trace(&self, trc: *mut JSTracer) {
|
||||||
self.get().trace(trc)
|
self.get().trace(trc)
|
||||||
|
@ -309,6 +284,7 @@ no_jsmanaged_fields!(TimeProfilerChan);
|
||||||
no_jsmanaged_fields!(MemProfilerChan);
|
no_jsmanaged_fields!(MemProfilerChan);
|
||||||
no_jsmanaged_fields!(PseudoElement);
|
no_jsmanaged_fields!(PseudoElement);
|
||||||
no_jsmanaged_fields!(Length);
|
no_jsmanaged_fields!(Length);
|
||||||
|
no_jsmanaged_fields!(ElementState);
|
||||||
|
|
||||||
impl JSTraceable for Box<ScriptChan + Send> {
|
impl JSTraceable for Box<ScriptChan + Send> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -8,6 +8,7 @@ use canvas_traits::{CompositionOrBlending, LineCapStyle, LineJoinStyle};
|
||||||
use canvas_traits::{FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle, RepetitionStyle};
|
use canvas_traits::{FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle, RepetitionStyle};
|
||||||
use cssparser::Color as CSSColor;
|
use cssparser::Color as CSSColor;
|
||||||
use cssparser::{Parser, RGBA};
|
use cssparser::{Parser, RGBA};
|
||||||
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding;
|
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding;
|
||||||
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
|
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
|
||||||
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasWindingRule;
|
use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasWindingRule;
|
||||||
|
@ -37,7 +38,6 @@ use net_traits::image::base::PixelFormat;
|
||||||
use net_traits::image_cache_task::ImageResponse;
|
use net_traits::image_cache_task::ImageResponse;
|
||||||
use num::{Float, ToPrimitive};
|
use num::{Float, ToPrimitive};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::{cmp, fmt};
|
use std::{cmp, fmt};
|
||||||
|
@ -63,8 +63,8 @@ pub struct CanvasRenderingContext2D {
|
||||||
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
||||||
ipc_renderer: IpcSender<CanvasMsg>,
|
ipc_renderer: IpcSender<CanvasMsg>,
|
||||||
canvas: JS<HTMLCanvasElement>,
|
canvas: JS<HTMLCanvasElement>,
|
||||||
state: RefCell<CanvasContextState>,
|
state: DOMRefCell<CanvasContextState>,
|
||||||
saved_states: RefCell<Vec<CanvasContextState>>,
|
saved_states: DOMRefCell<Vec<CanvasContextState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_root]
|
#[must_root]
|
||||||
|
@ -126,8 +126,8 @@ impl CanvasRenderingContext2D {
|
||||||
renderer_id: renderer_id,
|
renderer_id: renderer_id,
|
||||||
ipc_renderer: ipc_renderer,
|
ipc_renderer: ipc_renderer,
|
||||||
canvas: JS::from_ref(canvas),
|
canvas: JS::from_ref(canvas),
|
||||||
state: RefCell::new(CanvasContextState::new()),
|
state: DOMRefCell::new(CanvasContextState::new()),
|
||||||
saved_states: RefCell::new(Vec::new()),
|
saved_states: DOMRefCell::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ impl CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_as_dirty(&self) {
|
fn mark_as_dirty(&self) {
|
||||||
self.canvas.root().upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
self.canvas.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_transform(&self) {
|
fn update_transform(&self) {
|
||||||
|
@ -290,7 +290,7 @@ impl CanvasRenderingContext2D {
|
||||||
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
|
||||||
|
|
||||||
// If the source and target canvas are the same
|
// If the source and target canvas are the same
|
||||||
let msg = if self.canvas.root().r() == canvas {
|
let msg = if &*self.canvas == canvas {
|
||||||
CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled))
|
CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled))
|
||||||
} else { // Source and target canvases are different
|
} else { // Source and target canvases are different
|
||||||
let context = match canvas.get_or_init_2d_context() {
|
let context = match canvas.get_or_init_2d_context() {
|
||||||
|
@ -367,8 +367,7 @@ impl CanvasRenderingContext2D {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn request_image_from_cache(&self, url: Url) -> ImageResponse {
|
fn request_image_from_cache(&self, url: Url) -> ImageResponse {
|
||||||
let canvas = self.canvas.root();
|
let window = window_from_node(&*self.canvas);
|
||||||
let window = window_from_node(canvas.r());
|
|
||||||
canvas_utils::request_image_from_cache(window.r(), url)
|
canvas_utils::request_image_from_cache(window.r(), url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +421,7 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutJS<CanvasRenderingContext2D
|
||||||
impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas
|
||||||
fn Canvas(&self) -> Root<HTMLCanvasElement> {
|
fn Canvas(&self) -> Root<HTMLCanvasElement> {
|
||||||
self.canvas.root()
|
Root::from_ref(&*self.canvas)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-save
|
// https://html.spec.whatwg.org/multipage/#dom-context-2d-save
|
||||||
|
@ -764,7 +763,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
StringOrCanvasGradientOrCanvasPattern::eString(result)
|
StringOrCanvasGradientOrCanvasPattern::eString(result)
|
||||||
},
|
},
|
||||||
CanvasFillOrStrokeStyle::Gradient(ref gradient) => {
|
CanvasFillOrStrokeStyle::Gradient(ref gradient) => {
|
||||||
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient.root())
|
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(Root::from_ref(&*gradient))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -804,7 +803,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
StringOrCanvasGradientOrCanvasPattern::eString(result)
|
StringOrCanvasGradientOrCanvasPattern::eString(result)
|
||||||
},
|
},
|
||||||
CanvasFillOrStrokeStyle::Gradient(ref gradient) => {
|
CanvasFillOrStrokeStyle::Gradient(ref gradient) => {
|
||||||
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient.root())
|
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(Root::from_ref(&*gradient))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -881,7 +880,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
let (sender, receiver) = ipc::channel::<Vec<u8>>().unwrap();
|
let (sender, receiver) = ipc::channel::<Vec<u8>>().unwrap();
|
||||||
let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()),
|
let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()),
|
||||||
Size2D::new(sw as i32, sh as i32));
|
Size2D::new(sw as i32, sh as i32));
|
||||||
let canvas_size = self.canvas.root().r().get_size();
|
let canvas_size = self.canvas.get_size();
|
||||||
let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
|
let canvas_size = Size2D::new(canvas_size.width as f64, canvas_size.height as f64);
|
||||||
self.ipc_renderer
|
self.ipc_renderer
|
||||||
.send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender)))
|
.send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender)))
|
||||||
|
|
|
@ -60,8 +60,8 @@ impl CSSStyleDeclaration {
|
||||||
CSSStyleDeclaration {
|
CSSStyleDeclaration {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
owner: JS::from_ref(owner),
|
owner: JS::from_ref(owner),
|
||||||
pseudo: pseudo,
|
|
||||||
readonly: modification_access == CSSModificationAccess::Readonly,
|
readonly: modification_access == CSSModificationAccess::Readonly,
|
||||||
|
pseudo: pseudo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ use dom::customevent::CustomEvent;
|
||||||
use dom::documentfragment::DocumentFragment;
|
use dom::documentfragment::DocumentFragment;
|
||||||
use dom::documenttype::DocumentType;
|
use dom::documenttype::DocumentType;
|
||||||
use dom::domimplementation::DOMImplementation;
|
use dom::domimplementation::DOMImplementation;
|
||||||
use dom::element::{Element, ElementCreator, EventState};
|
use dom::element::{Element, ElementCreator};
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use dom::eventtarget::{EventTarget};
|
use dom::eventtarget::{EventTarget};
|
||||||
use dom::htmlanchorelement::HTMLAnchorElement;
|
use dom::htmlanchorelement::HTMLAnchorElement;
|
||||||
|
@ -84,10 +84,11 @@ use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
|
||||||
use num::ToPrimitive;
|
use num::ToPrimitive;
|
||||||
use script_task::{MainThreadScriptMsg, Runnable};
|
use script_task::{MainThreadScriptMsg, Runnable};
|
||||||
use script_traits::{MouseButton, UntrustedNodeAddress};
|
use script_traits::{MouseButton, UntrustedNodeAddress};
|
||||||
|
use selectors::states::*;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::boxed::FnBox;
|
use std::boxed::FnBox;
|
||||||
use std::cell::{Cell, Ref, RefCell, RefMut};
|
use std::cell::{Cell, Ref, RefMut};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
@ -161,7 +162,7 @@ pub struct Document {
|
||||||
/// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks
|
/// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks
|
||||||
/// List of animation frame callbacks
|
/// List of animation frame callbacks
|
||||||
#[ignore_heap_size_of = "closures are hard"]
|
#[ignore_heap_size_of = "closures are hard"]
|
||||||
animation_frame_list: RefCell<HashMap<u32, Box<FnBox(f64)>>>,
|
animation_frame_list: DOMRefCell<HashMap<u32, Box<FnBox(f64)>>>,
|
||||||
/// Tracks all outstanding loads related to this document.
|
/// Tracks all outstanding loads related to this document.
|
||||||
loader: DOMRefCell<DocumentLoader>,
|
loader: DOMRefCell<DocumentLoader>,
|
||||||
/// The current active HTML parser, to allow resuming after interruptions.
|
/// The current active HTML parser, to allow resuming after interruptions.
|
||||||
|
@ -173,8 +174,8 @@ pub struct Document {
|
||||||
/// This field is set to the document itself for inert documents.
|
/// This field is set to the document itself for inert documents.
|
||||||
/// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document
|
/// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document
|
||||||
appropriate_template_contents_owner_document: MutNullableHeap<JS<Document>>,
|
appropriate_template_contents_owner_document: MutNullableHeap<JS<Document>>,
|
||||||
// The collection of EventStates that have been changed since the last restyle.
|
// The collection of ElementStates that have been changed since the last restyle.
|
||||||
event_state_changes: DOMRefCell<HashMap<JS<Element>, EventState>>,
|
element_state_changes: DOMRefCell<HashMap<JS<Element>, ElementState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Document {
|
impl PartialEq for Document {
|
||||||
|
@ -304,7 +305,7 @@ impl Document {
|
||||||
|
|
||||||
pub fn needs_reflow(&self) -> bool {
|
pub fn needs_reflow(&self) -> bool {
|
||||||
self.GetDocumentElement().is_some() &&
|
self.GetDocumentElement().is_some() &&
|
||||||
(self.upcast::<Node>().get_has_dirty_descendants() || !self.event_state_changes.borrow().is_empty())
|
(self.upcast::<Node>().get_has_dirty_descendants() || !self.element_state_changes.borrow().is_empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the first `base` element in the DOM that has an `href` attribute.
|
/// Returns the first `base` element in the DOM that has an `href` attribute.
|
||||||
|
@ -389,8 +390,7 @@ impl Document {
|
||||||
None => false,
|
None => false,
|
||||||
Some(elements) => {
|
Some(elements) => {
|
||||||
let position = elements.iter()
|
let position = elements.iter()
|
||||||
.map(|elem| elem.root())
|
.position(|element| &**element == to_unregister)
|
||||||
.position(|element| element.r() == to_unregister)
|
|
||||||
.expect("This element should be in registered.");
|
.expect("This element should be in registered.");
|
||||||
elements.remove(position);
|
elements.remove(position);
|
||||||
elements.is_empty()
|
elements.is_empty()
|
||||||
|
@ -426,7 +426,7 @@ impl Document {
|
||||||
let root = root.upcast::<Node>();
|
let root = root.upcast::<Node>();
|
||||||
for node in root.traverse_preorder() {
|
for node in root.traverse_preorder() {
|
||||||
if let Some(elem) = node.downcast() {
|
if let Some(elem) = node.downcast() {
|
||||||
if (*elements)[head].root().r() == elem {
|
if &*(*elements)[head] == elem {
|
||||||
head += 1;
|
head += 1;
|
||||||
}
|
}
|
||||||
if new_node == node.r() || head == elements.len() {
|
if new_node == node.r() || head == elements.len() {
|
||||||
|
@ -670,21 +670,19 @@ impl Document {
|
||||||
prev_mouse_over_targets: &mut RootedVec<JS<Element>>) {
|
prev_mouse_over_targets: &mut RootedVec<JS<Element>>) {
|
||||||
// Build a list of elements that are currently under the mouse.
|
// Build a list of elements that are currently under the mouse.
|
||||||
let mouse_over_addresses = self.get_nodes_under_mouse(&point);
|
let mouse_over_addresses = self.get_nodes_under_mouse(&point);
|
||||||
let mut mouse_over_targets: RootedVec<JS<Element>> = RootedVec::new();
|
let mut mouse_over_targets = mouse_over_addresses.iter().map(|node_address| {
|
||||||
for node_address in &mouse_over_addresses {
|
node::from_untrusted_node_address(js_runtime, *node_address)
|
||||||
let node = node::from_untrusted_node_address(js_runtime, *node_address);
|
.inclusive_ancestors()
|
||||||
mouse_over_targets.push(node.r().inclusive_ancestors()
|
.filter_map(Root::downcast::<Element>)
|
||||||
.find(|node| node.is::<Element>())
|
.next()
|
||||||
.map(|node| JS::from_ref(node.downcast::<Element>().unwrap()))
|
.unwrap()
|
||||||
.unwrap());
|
}).collect::<RootedVec<JS<Element>>>();
|
||||||
};
|
|
||||||
|
|
||||||
// Remove hover from any elements in the previous list that are no longer
|
// Remove hover from any elements in the previous list that are no longer
|
||||||
// under the mouse.
|
// under the mouse.
|
||||||
for target in prev_mouse_over_targets.iter() {
|
for target in prev_mouse_over_targets.iter() {
|
||||||
if !mouse_over_targets.contains(target) {
|
if !mouse_over_targets.contains(target) {
|
||||||
let target = target.root();
|
let target_ref = &**target;
|
||||||
let target_ref = target.r();
|
|
||||||
if target_ref.get_hover_state() {
|
if target_ref.get_hover_state() {
|
||||||
target_ref.set_hover_state(false);
|
target_ref.set_hover_state(false);
|
||||||
|
|
||||||
|
@ -747,27 +745,27 @@ impl Document {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let target = el.upcast::<EventTarget>();
|
let target = el.upcast::<EventTarget>();
|
||||||
let window = self.window.root();
|
let window = &*self.window;
|
||||||
|
|
||||||
let client_x = Finite::wrap(point.x as f64);
|
let client_x = Finite::wrap(point.x as f64);
|
||||||
let client_y = Finite::wrap(point.y as f64);
|
let client_y = Finite::wrap(point.y as f64);
|
||||||
let page_x = Finite::wrap(point.x as f64 + window.PageXOffset() as f64);
|
let page_x = Finite::wrap(point.x as f64 + window.PageXOffset() as f64);
|
||||||
let page_y = Finite::wrap(point.y as f64 + window.PageYOffset() as f64);
|
let page_y = Finite::wrap(point.y as f64 + window.PageYOffset() as f64);
|
||||||
|
|
||||||
let touch = Touch::new(window.r(), identifier, target,
|
let touch = Touch::new(window, identifier, target,
|
||||||
client_x, client_y, // TODO: Get real screen coordinates?
|
client_x, client_y, // TODO: Get real screen coordinates?
|
||||||
client_x, client_y,
|
client_x, client_y,
|
||||||
page_x, page_y);
|
page_x, page_y);
|
||||||
|
|
||||||
let mut touches = RootedVec::new();
|
let mut touches = RootedVec::new();
|
||||||
touches.push(JS::from_rooted(&touch));
|
touches.push(JS::from_rooted(&touch));
|
||||||
let touches = TouchList::new(window.r(), touches.r());
|
let touches = TouchList::new(window, touches.r());
|
||||||
|
|
||||||
let event = TouchEvent::new(window.r(),
|
let event = TouchEvent::new(window,
|
||||||
event_name,
|
event_name,
|
||||||
EventBubbles::Bubbles,
|
EventBubbles::Bubbles,
|
||||||
EventCancelable::Cancelable,
|
EventCancelable::Cancelable,
|
||||||
Some(window.r()),
|
Some(window),
|
||||||
0i32,
|
0i32,
|
||||||
&touches, &touches, &touches,
|
&touches, &touches, &touches,
|
||||||
// FIXME: modifier keys
|
// FIXME: modifier keys
|
||||||
|
@ -775,7 +773,7 @@ impl Document {
|
||||||
let event = event.upcast::<Event>();
|
let event = event.upcast::<Event>();
|
||||||
let result = event.fire(target);
|
let result = event.fire(target);
|
||||||
|
|
||||||
window.r().reflow(ReflowGoal::ForDisplay,
|
window.reflow(ReflowGoal::ForDisplay,
|
||||||
ReflowQueryType::NoQuery,
|
ReflowQueryType::NoQuery,
|
||||||
ReflowReason::MouseEvent);
|
ReflowReason::MouseEvent);
|
||||||
result
|
result
|
||||||
|
@ -1087,13 +1085,15 @@ impl Document {
|
||||||
}
|
}
|
||||||
let mut deferred_scripts = self.deferred_scripts.borrow_mut();
|
let mut deferred_scripts = self.deferred_scripts.borrow_mut();
|
||||||
while !deferred_scripts.is_empty() {
|
while !deferred_scripts.is_empty() {
|
||||||
let script = deferred_scripts[0].root();
|
{
|
||||||
|
let script = &*deferred_scripts[0];
|
||||||
// Part of substep 1.
|
// Part of substep 1.
|
||||||
if !script.is_ready_to_be_executed() {
|
if !script.is_ready_to_be_executed() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Substep 2.
|
// Substep 2.
|
||||||
script.execute();
|
script.execute();
|
||||||
|
}
|
||||||
// Substep 3.
|
// Substep 3.
|
||||||
deferred_scripts.remove(0);
|
deferred_scripts.remove(0);
|
||||||
// Substep 4 (implicit).
|
// Substep 4 (implicit).
|
||||||
|
@ -1108,7 +1108,7 @@ impl Document {
|
||||||
// Execute the first in-order asap-executed script if it's ready, repeat as required.
|
// Execute the first in-order asap-executed script if it's ready, repeat as required.
|
||||||
// Re-borrowing the list for each step because it can also be borrowed under execute.
|
// Re-borrowing the list for each step because it can also be borrowed under execute.
|
||||||
while self.asap_in_order_scripts_list.borrow().len() > 0 {
|
while self.asap_in_order_scripts_list.borrow().len() > 0 {
|
||||||
let script = self.asap_in_order_scripts_list.borrow()[0].root();
|
let script = Root::from_ref(&*self.asap_in_order_scripts_list.borrow()[0]);
|
||||||
if !script.r().is_ready_to_be_executed() {
|
if !script.r().is_ready_to_be_executed() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1119,7 +1119,7 @@ impl Document {
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
// Re-borrowing the set for each step because it can also be borrowed under execute.
|
// Re-borrowing the set for each step because it can also be borrowed under execute.
|
||||||
while idx < self.asap_scripts_set.borrow().len() {
|
while idx < self.asap_scripts_set.borrow().len() {
|
||||||
let script = self.asap_scripts_set.borrow()[idx].root();
|
let script = Root::from_ref(&*self.asap_scripts_set.borrow()[idx]);
|
||||||
if !script.r().is_ready_to_be_executed() {
|
if !script.r().is_ready_to_be_executed() {
|
||||||
idx += 1;
|
idx += 1;
|
||||||
continue;
|
continue;
|
||||||
|
@ -1184,7 +1184,7 @@ pub enum DocumentSource {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub trait LayoutDocumentHelpers {
|
pub trait LayoutDocumentHelpers {
|
||||||
unsafe fn is_html_document_for_layout(&self) -> bool;
|
unsafe fn is_html_document_for_layout(&self) -> bool;
|
||||||
unsafe fn drain_event_state_changes(&self) -> Vec<(LayoutJS<Element>, EventState)>;
|
unsafe fn drain_element_state_changes(&self) -> Vec<(LayoutJS<Element>, ElementState)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -1196,8 +1196,8 @@ impl LayoutDocumentHelpers for LayoutJS<Document> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
unsafe fn drain_event_state_changes(&self) -> Vec<(LayoutJS<Element>, EventState)> {
|
unsafe fn drain_element_state_changes(&self) -> Vec<(LayoutJS<Element>, ElementState)> {
|
||||||
let mut changes = (*self.unsafe_get()).event_state_changes.borrow_mut_for_layout();
|
let mut changes = (*self.unsafe_get()).element_state_changes.borrow_mut_for_layout();
|
||||||
let drain = changes.drain();
|
let drain = changes.drain();
|
||||||
let layout_drain = drain.map(|(k, v)| (k.to_layout(), v));
|
let layout_drain = drain.map(|(k, v)| (k.to_layout(), v));
|
||||||
Vec::from_iter(layout_drain)
|
Vec::from_iter(layout_drain)
|
||||||
|
@ -1261,13 +1261,13 @@ impl Document {
|
||||||
asap_scripts_set: DOMRefCell::new(vec!()),
|
asap_scripts_set: DOMRefCell::new(vec!()),
|
||||||
scripting_enabled: Cell::new(true),
|
scripting_enabled: Cell::new(true),
|
||||||
animation_frame_ident: Cell::new(0),
|
animation_frame_ident: Cell::new(0),
|
||||||
animation_frame_list: RefCell::new(HashMap::new()),
|
animation_frame_list: DOMRefCell::new(HashMap::new()),
|
||||||
loader: DOMRefCell::new(doc_loader),
|
loader: DOMRefCell::new(doc_loader),
|
||||||
current_parser: Default::default(),
|
current_parser: Default::default(),
|
||||||
reflow_timeout: Cell::new(None),
|
reflow_timeout: Cell::new(None),
|
||||||
base_element: Default::default(),
|
base_element: Default::default(),
|
||||||
appropriate_template_contents_owner_document: Default::default(),
|
appropriate_template_contents_owner_document: Default::default(),
|
||||||
event_state_changes: DOMRefCell::new(HashMap::new()),
|
element_state_changes: DOMRefCell::new(HashMap::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1330,15 +1330,15 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_element_by_id(&self, id: &Atom) -> Option<Root<Element>> {
|
pub fn get_element_by_id(&self, id: &Atom) -> Option<Root<Element>> {
|
||||||
self.idmap.borrow().get(&id).map(|ref elements| (*elements)[0].root())
|
self.idmap.borrow().get(&id).map(|ref elements| Root::from_ref(&*(*elements)[0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_event_state_change(&self, el: &Element, which: EventState) {
|
pub fn record_element_state_change(&self, el: &Element, which: ElementState) {
|
||||||
let mut map = self.event_state_changes.borrow_mut();
|
let mut map = self.element_state_changes.borrow_mut();
|
||||||
let empty;
|
let empty;
|
||||||
{
|
{
|
||||||
let states = map.entry(JS::from_ref(el))
|
let states = map.entry(JS::from_ref(el))
|
||||||
.or_insert(EventState::empty());
|
.or_insert(ElementState::empty());
|
||||||
states.toggle(which);
|
states.toggle(which);
|
||||||
empty = states.is_empty();
|
empty = states.is_empty();
|
||||||
}
|
}
|
||||||
|
@ -1923,7 +1923,7 @@ impl DocumentMethods for Document {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-document-defaultview
|
// https://html.spec.whatwg.org/multipage/#dom-document-defaultview
|
||||||
fn DefaultView(&self) -> Root<Window> {
|
fn DefaultView(&self) -> Root<Window> {
|
||||||
self.window.root()
|
Root::from_ref(&*self.window)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-document-cookie
|
// https://html.spec.whatwg.org/multipage/#dom-document-cookie
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl DOMRectListMethods for DOMRectList {
|
||||||
fn Item(&self, index: u32) -> Option<Root<DOMRect>> {
|
fn Item(&self, index: u32) -> Option<Root<DOMRect>> {
|
||||||
let rects = &self.rects;
|
let rects = &self.rects;
|
||||||
if index < rects.len() as u32 {
|
if index < rects.len() as u32 {
|
||||||
Some(rects[index as usize].root())
|
Some(Root::from_ref(&*rects[index as usize]))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,6 @@ impl DOMStringMapMethods for DOMStringMap {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#the-domstringmap-interface:supported-property-names
|
// https://html.spec.whatwg.org/multipage/#the-domstringmap-interface:supported-property-names
|
||||||
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
|
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
|
||||||
// FIXME: unimplemented (https://github.com/servo/servo/issues/7273)
|
self.element.supported_prop_names_custom_attr().iter().cloned().collect()
|
||||||
vec![]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,14 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementM
|
||||||
use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
|
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
|
use dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId, NodeTypeId};
|
||||||
use dom::bindings::codegen::UnionTypes::NodeOrString;
|
use dom::bindings::codegen::UnionTypes::NodeOrString;
|
||||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||||
use dom::bindings::global::GlobalRef;
|
use dom::bindings::global::GlobalRef;
|
||||||
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
|
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
|
||||||
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
|
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
|
||||||
use dom::bindings::js::{Root, RootedReference};
|
use dom::bindings::js::{Root, RootedReference};
|
||||||
|
use dom::bindings::trace::JSTraceable;
|
||||||
use dom::bindings::xmlname::XMLName::InvalidXMLName;
|
use dom::bindings::xmlname::XMLName::InvalidXMLName;
|
||||||
use dom::bindings::xmlname::{namespace_from_domstring, validate_and_extract, xml_name_type};
|
use dom::bindings::xmlname::{namespace_from_domstring, validate_and_extract, xml_name_type};
|
||||||
use dom::characterdata::CharacterData;
|
use dom::characterdata::CharacterData;
|
||||||
|
@ -40,7 +42,8 @@ use dom::htmlcollection::HTMLCollection;
|
||||||
use dom::htmlfieldsetelement::HTMLFieldSetElement;
|
use dom::htmlfieldsetelement::HTMLFieldSetElement;
|
||||||
use dom::htmlfontelement::HTMLFontElement;
|
use dom::htmlfontelement::HTMLFontElement;
|
||||||
use dom::htmliframeelement::HTMLIFrameElement;
|
use dom::htmliframeelement::HTMLIFrameElement;
|
||||||
use dom::htmlinputelement::{HTMLInputElement, RawLayoutHTMLInputElementHelpers};
|
use dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers};
|
||||||
|
use dom::htmllabelelement::HTMLLabelElement;
|
||||||
use dom::htmllegendelement::HTMLLegendElement;
|
use dom::htmllegendelement::HTMLLegendElement;
|
||||||
use dom::htmloptgroupelement::HTMLOptGroupElement;
|
use dom::htmloptgroupelement::HTMLOptGroupElement;
|
||||||
use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementLayoutHelpers};
|
use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementLayoutHelpers};
|
||||||
|
@ -62,8 +65,8 @@ use html5ever::serialize::TraversalScope;
|
||||||
use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
|
use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
|
||||||
use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks};
|
use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks};
|
||||||
use selectors::matching::{DeclarationBlock, matches};
|
use selectors::matching::{DeclarationBlock, matches};
|
||||||
use selectors::parser::parse_author_origin_selector_list_from_str;
|
use selectors::parser::{AttrSelector, NamespaceConstraint, parse_author_origin_selector_list_from_str};
|
||||||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
use selectors::states::*;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::{Cow, ToOwned};
|
use std::borrow::{Cow, ToOwned};
|
||||||
|
@ -77,28 +80,14 @@ use style::properties::DeclaredValue;
|
||||||
use style::properties::longhands::{self, background_image, border_spacing, font_family, font_size};
|
use style::properties::longhands::{self, background_image, border_spacing, font_family, font_size};
|
||||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
|
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
|
||||||
use style::values::CSSFloat;
|
use style::values::CSSFloat;
|
||||||
use style::values::specified::{self, CSSColor, CSSRGBA};
|
use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage};
|
||||||
use url::UrlParser;
|
use url::UrlParser;
|
||||||
|
use util::mem::HeapSizeOf;
|
||||||
use util::str::{DOMString, LengthOrPercentageOrAuto};
|
use util::str::{DOMString, LengthOrPercentageOrAuto};
|
||||||
|
|
||||||
bitflags! {
|
// TODO: Update focus state when the top-level browsing context gains or loses system focus,
|
||||||
#[doc = "Element Event States."]
|
// and when the element enters or leaves a browsing context container.
|
||||||
#[derive(JSTraceable, HeapSizeOf)]
|
// https://html.spec.whatwg.org/multipage/#selector-focus
|
||||||
flags EventState: u8 {
|
|
||||||
#[doc = "The mouse is down on this element. \
|
|
||||||
(https://html.spec.whatwg.org/multipage/#selector-active). \
|
|
||||||
FIXME(#7333): set/unset this when appropriate"]
|
|
||||||
const IN_ACTIVE_STATE = 0x01,
|
|
||||||
#[doc = "This element has focus."]
|
|
||||||
const IN_FOCUS_STATE = 0x02,
|
|
||||||
#[doc = "The mouse is hovering over this element."]
|
|
||||||
const IN_HOVER_STATE = 0x04,
|
|
||||||
#[doc = "Content is enabled (and can be disabled)."]
|
|
||||||
const IN_ENABLED_STATE = 0x08,
|
|
||||||
#[doc = "Content is disabled."]
|
|
||||||
const IN_DISABLED_STATE = 0x10,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct Element {
|
pub struct Element {
|
||||||
|
@ -111,7 +100,7 @@ pub struct Element {
|
||||||
style_attribute: DOMRefCell<Option<PropertyDeclarationBlock>>,
|
style_attribute: DOMRefCell<Option<PropertyDeclarationBlock>>,
|
||||||
attr_list: MutNullableHeap<JS<NamedNodeMap>>,
|
attr_list: MutNullableHeap<JS<NamedNodeMap>>,
|
||||||
class_list: MutNullableHeap<JS<DOMTokenList>>,
|
class_list: MutNullableHeap<JS<DOMTokenList>>,
|
||||||
event_state: Cell<EventState>,
|
state: Cell<ElementState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Element {
|
impl PartialEq for Element {
|
||||||
|
@ -140,11 +129,11 @@ impl Element {
|
||||||
pub fn new_inherited(local_name: DOMString,
|
pub fn new_inherited(local_name: DOMString,
|
||||||
namespace: Namespace, prefix: Option<DOMString>,
|
namespace: Namespace, prefix: Option<DOMString>,
|
||||||
document: &Document) -> Element {
|
document: &Document) -> Element {
|
||||||
Element::new_inherited_with_state(EventState::empty(), local_name,
|
Element::new_inherited_with_state(ElementState::empty(), local_name,
|
||||||
namespace, prefix, document)
|
namespace, prefix, document)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_inherited_with_state(state: EventState, local_name: DOMString,
|
pub fn new_inherited_with_state(state: ElementState, local_name: DOMString,
|
||||||
namespace: Namespace, prefix: Option<DOMString>,
|
namespace: Namespace, prefix: Option<DOMString>,
|
||||||
document: &Document)
|
document: &Document)
|
||||||
-> Element {
|
-> Element {
|
||||||
|
@ -154,11 +143,11 @@ impl Element {
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
attrs: DOMRefCell::new(vec!()),
|
attrs: DOMRefCell::new(vec!()),
|
||||||
attr_list: Default::default(),
|
|
||||||
class_list: Default::default(),
|
|
||||||
id_attribute: DOMRefCell::new(None),
|
id_attribute: DOMRefCell::new(None),
|
||||||
style_attribute: DOMRefCell::new(None),
|
style_attribute: DOMRefCell::new(None),
|
||||||
event_state: Cell::new(state),
|
attr_list: Default::default(),
|
||||||
|
class_list: Default::default(),
|
||||||
|
state: Cell::new(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +177,7 @@ pub unsafe fn get_attr_for_layout<'a>(elem: &'a Element, namespace: &Namespace,
|
||||||
-> Option<LayoutJS<Attr>> {
|
-> Option<LayoutJS<Attr>> {
|
||||||
// cast to point to T in RefCell<T> directly
|
// cast to point to T in RefCell<T> directly
|
||||||
let attrs = elem.attrs.borrow_for_layout();
|
let attrs = elem.attrs.borrow_for_layout();
|
||||||
attrs.iter().find(|attr: & &JS<Attr>| {
|
attrs.iter().find(|attr| {
|
||||||
let attr = attr.to_layout();
|
let attr = attr.to_layout();
|
||||||
*name == attr.local_name_atom_forever() &&
|
*name == attr.local_name_atom_forever() &&
|
||||||
(*attr.unsafe_get()).namespace() == namespace
|
(*attr.unsafe_get()).namespace() == namespace
|
||||||
|
@ -215,7 +204,7 @@ impl RawLayoutElementHelpers for Element {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &Atom) -> Vec<&'a str> {
|
unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &Atom) -> Vec<&'a str> {
|
||||||
let attrs = self.attrs.borrow_for_layout();
|
let attrs = self.attrs.borrow_for_layout();
|
||||||
(*attrs).iter().filter_map(|attr: &JS<Attr>| {
|
attrs.iter().filter_map(|attr| {
|
||||||
let attr = attr.to_layout();
|
let attr = attr.to_layout();
|
||||||
if *name == attr.local_name_atom_forever() {
|
if *name == attr.local_name_atom_forever() {
|
||||||
Some(attr.value_ref_forever())
|
Some(attr.value_ref_forever())
|
||||||
|
@ -251,7 +240,7 @@ pub trait LayoutElementHelpers {
|
||||||
fn get_checked_state_for_layout(&self) -> bool;
|
fn get_checked_state_for_layout(&self) -> bool;
|
||||||
fn get_indeterminate_state_for_layout(&self) -> bool;
|
fn get_indeterminate_state_for_layout(&self) -> bool;
|
||||||
|
|
||||||
fn get_event_state_for_layout(&self) -> EventState;
|
fn get_state_for_layout(&self) -> ElementState;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutElementHelpers for LayoutJS<Element> {
|
impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
|
@ -358,7 +347,8 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
hints.push(from_declaration(
|
hints.push(from_declaration(
|
||||||
PropertyDeclaration::FontSize(
|
PropertyDeclaration::FontSize(
|
||||||
DeclaredValue::Value(
|
DeclaredValue::Value(
|
||||||
font_size::SpecifiedValue(font_size)))))
|
font_size::SpecifiedValue(
|
||||||
|
LengthOrPercentage::Length(font_size))))))
|
||||||
}
|
}
|
||||||
|
|
||||||
let cellspacing = if let Some(this) = self.downcast::<HTMLTableElement>() {
|
let cellspacing = if let Some(this) = self.downcast::<HTMLTableElement>() {
|
||||||
|
@ -384,7 +374,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
// a text field
|
// a text field
|
||||||
match (*self.unsafe_get()).get_attr_val_for_layout(&ns!(""), &atom!("type")) {
|
match (*self.unsafe_get()).get_attr_val_for_layout(&ns!(""), &atom!("type")) {
|
||||||
Some("text") | Some("password") => {
|
Some("text") | Some("password") => {
|
||||||
match (*this.unsafe_get()).get_size_for_layout() {
|
match this.get_size_for_layout() {
|
||||||
0 => None,
|
0 => None,
|
||||||
s => Some(s as i32),
|
s => Some(s as i32),
|
||||||
}
|
}
|
||||||
|
@ -584,7 +574,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
// TODO option and menuitem can also have a checked state.
|
// TODO option and menuitem can also have a checked state.
|
||||||
match self.downcast::<HTMLInputElement>() {
|
match self.downcast::<HTMLInputElement>() {
|
||||||
Some(input) => unsafe {
|
Some(input) => unsafe {
|
||||||
(*input.unsafe_get()).get_checked_state_for_layout()
|
input.get_checked_state_for_layout()
|
||||||
},
|
},
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
|
@ -596,7 +586,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
// TODO progress elements can also be matched with :indeterminate
|
// TODO progress elements can also be matched with :indeterminate
|
||||||
match self.downcast::<HTMLInputElement>() {
|
match self.downcast::<HTMLInputElement>() {
|
||||||
Some(input) => unsafe {
|
Some(input) => unsafe {
|
||||||
(*input.unsafe_get()).get_indeterminate_state_for_layout()
|
input.get_indeterminate_state_for_layout()
|
||||||
},
|
},
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
|
@ -604,9 +594,9 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn get_event_state_for_layout(&self) -> EventState {
|
fn get_state_for_layout(&self) -> ElementState {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.unsafe_get()).event_state.get()
|
(*self.unsafe_get()).state.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -886,16 +876,15 @@ impl Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_attribute(&self, namespace: &Namespace, local_name: &Atom) -> Option<Root<Attr>> {
|
pub fn get_attribute(&self, namespace: &Namespace, local_name: &Atom) -> Option<Root<Attr>> {
|
||||||
self.attrs.borrow().iter().map(JS::root).find(|attr| {
|
self.attrs.borrow().iter().find(|attr| {
|
||||||
attr.local_name() == local_name && attr.namespace() == namespace
|
attr.local_name() == local_name && attr.namespace() == namespace
|
||||||
})
|
}).map(|js| Root::from_ref(&**js))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
|
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
|
||||||
pub fn get_attribute_by_name(&self, name: DOMString) -> Option<Root<Attr>> {
|
pub fn get_attribute_by_name(&self, name: DOMString) -> Option<Root<Attr>> {
|
||||||
let name = &self.parsed_name(name);
|
let name = &self.parsed_name(name);
|
||||||
self.attrs.borrow().iter().map(JS::root)
|
self.attrs.borrow().iter().find(|a| a.name() == name).map(|js| Root::from_ref(&**js))
|
||||||
.find(|a| a.r().name() == name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_attribute_from_parser(&self,
|
pub fn set_attribute_from_parser(&self,
|
||||||
|
@ -903,8 +892,8 @@ impl Element {
|
||||||
value: DOMString,
|
value: DOMString,
|
||||||
prefix: Option<Atom>) {
|
prefix: Option<Atom>) {
|
||||||
// Don't set if the attribute already exists, so we can handle add_attrs_if_missing
|
// Don't set if the attribute already exists, so we can handle add_attrs_if_missing
|
||||||
if self.attrs.borrow().iter().map(JS::root)
|
if self.attrs.borrow().iter()
|
||||||
.any(|a| *a.r().local_name() == qname.local && *a.r().namespace() == qname.ns) {
|
.any(|a| *a.local_name() == qname.local && *a.namespace() == qname.ns) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,7 +943,8 @@ impl Element {
|
||||||
find: F)
|
find: F)
|
||||||
where F: Fn(&Attr)
|
where F: Fn(&Attr)
|
||||||
-> bool {
|
-> bool {
|
||||||
let attr = self.attrs.borrow().iter().map(JS::root).find(|attr| find(&attr));
|
let attr = self.attrs.borrow().iter()
|
||||||
|
.find(|attr| find(&attr)).map(|js| Root::from_ref(&**js));
|
||||||
if let Some(attr) = attr {
|
if let Some(attr) = attr {
|
||||||
attr.set_value(value, self);
|
attr.set_value(value, self);
|
||||||
} else {
|
} else {
|
||||||
|
@ -985,10 +975,10 @@ impl Element {
|
||||||
fn remove_first_matching_attribute<F>(&self, find: F) -> Option<Root<Attr>>
|
fn remove_first_matching_attribute<F>(&self, find: F) -> Option<Root<Attr>>
|
||||||
where F: Fn(&Attr) -> bool
|
where F: Fn(&Attr) -> bool
|
||||||
{
|
{
|
||||||
let idx = self.attrs.borrow().iter().map(JS::root).position(|attr| find(&attr));
|
let idx = self.attrs.borrow().iter().position(|attr| find(&attr));
|
||||||
|
|
||||||
idx.map(|idx| {
|
idx.map(|idx| {
|
||||||
let attr = (*self.attrs.borrow())[idx].root();
|
let attr = Root::from_ref(&*(*self.attrs.borrow())[idx]);
|
||||||
self.attrs.borrow_mut().remove(idx);
|
self.attrs.borrow_mut().remove(idx);
|
||||||
attr.set_owner(None);
|
attr.set_owner(None);
|
||||||
if attr.namespace() == &ns!("") {
|
if attr.namespace() == &ns!("") {
|
||||||
|
@ -1017,8 +1007,8 @@ impl Element {
|
||||||
|
|
||||||
pub fn has_attribute(&self, local_name: &Atom) -> bool {
|
pub fn has_attribute(&self, local_name: &Atom) -> bool {
|
||||||
assert!(local_name.bytes().all(|b| b.to_ascii_lowercase() == b));
|
assert!(local_name.bytes().all(|b| b.to_ascii_lowercase() == b));
|
||||||
self.attrs.borrow().iter().map(JS::root).any(|attr| {
|
self.attrs.borrow().iter().any(|attr| {
|
||||||
attr.r().local_name() == local_name && attr.r().namespace() == &ns!("")
|
attr.local_name() == local_name && attr.namespace() == &ns!("")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1582,6 +1572,16 @@ impl VirtualMethods for Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! state_getter {
|
||||||
|
($(
|
||||||
|
$(#[$Flag_attr: meta])*
|
||||||
|
state $css: expr => $variant: ident / $method: ident /
|
||||||
|
$flag: ident = $value: expr,
|
||||||
|
)+) => {
|
||||||
|
$( fn $method(&self) -> bool { Element::get_state(self).contains($flag) } )+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> ::selectors::Element for Root<Element> {
|
impl<'a> ::selectors::Element for Root<Element> {
|
||||||
fn parent_element(&self) -> Option<Root<Element>> {
|
fn parent_element(&self) -> Option<Root<Element>> {
|
||||||
self.upcast::<Node>().GetParentElement()
|
self.upcast::<Node>().GetParentElement()
|
||||||
|
@ -1648,42 +1648,11 @@ impl<'a> ::selectors::Element for Root<Element> {
|
||||||
self.namespace()
|
self.namespace()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_hover_state(&self) -> bool {
|
state_pseudo_classes!(state_getter);
|
||||||
Element::get_hover_state(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_active_state(&self) -> bool {
|
|
||||||
Element::get_active_state(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_focus_state(&self) -> bool {
|
|
||||||
// TODO: Also check whether the top-level browsing context has the system focus,
|
|
||||||
// and whether this element is a browsing context container.
|
|
||||||
// https://html.spec.whatwg.org/multipage/#selector-focus
|
|
||||||
Element::get_focus_state(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_id(&self) -> Option<Atom> {
|
fn get_id(&self) -> Option<Atom> {
|
||||||
self.id_attribute.borrow().clone()
|
self.id_attribute.borrow().clone()
|
||||||
}
|
}
|
||||||
fn get_disabled_state(&self) -> bool {
|
|
||||||
Element::get_disabled_state(self)
|
|
||||||
}
|
|
||||||
fn get_enabled_state(&self) -> bool {
|
|
||||||
Element::get_enabled_state(self)
|
|
||||||
}
|
|
||||||
fn get_checked_state(&self) -> bool {
|
|
||||||
match self.downcast::<HTMLInputElement>() {
|
|
||||||
Some(input) => input.Checked(),
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn get_indeterminate_state(&self) -> bool {
|
|
||||||
match self.downcast::<HTMLInputElement>() {
|
|
||||||
Some(input) => input.get_indeterminate_state(),
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn has_class(&self, name: &Atom) -> bool {
|
fn has_class(&self, name: &Atom) -> bool {
|
||||||
Element::has_class(&**self, name)
|
Element::has_class(&**self, name)
|
||||||
}
|
}
|
||||||
|
@ -1728,7 +1697,7 @@ impl<'a> ::selectors::Element for Root<Element> {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
NamespaceConstraint::Any => {
|
NamespaceConstraint::Any => {
|
||||||
self.attrs.borrow().iter().map(JS::root).any(|attr| {
|
self.attrs.borrow().iter().any(|attr| {
|
||||||
attr.local_name() == local_name && test(&attr.value())
|
attr.local_name() == local_name && test(&attr.value())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1752,6 +1721,10 @@ impl Element {
|
||||||
let element = self.downcast::<HTMLAnchorElement>().unwrap();
|
let element = self.downcast::<HTMLAnchorElement>().unwrap();
|
||||||
Some(element as &Activatable)
|
Some(element as &Activatable)
|
||||||
},
|
},
|
||||||
|
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLabelElement)) => {
|
||||||
|
let element = self.downcast::<HTMLLabelElement>().unwrap();
|
||||||
|
Some(element as &Activatable)
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1833,8 +1806,12 @@ impl Element {
|
||||||
self.set_click_in_progress(false);
|
self.set_click_in_progress(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_state(&self, which: EventState, value: bool) {
|
pub fn get_state(&self) -> ElementState {
|
||||||
let mut state = self.event_state.get();
|
self.state.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_state(&self, which: ElementState, value: bool) {
|
||||||
|
let mut state = self.state.get();
|
||||||
if state.contains(which) == value {
|
if state.contains(which) == value {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1842,14 +1819,14 @@ impl Element {
|
||||||
true => state.insert(which),
|
true => state.insert(which),
|
||||||
false => state.remove(which),
|
false => state.remove(which),
|
||||||
};
|
};
|
||||||
self.event_state.set(state);
|
self.state.set(state);
|
||||||
|
|
||||||
let node = self.upcast::<Node>();
|
let node = self.upcast::<Node>();
|
||||||
node.owner_doc().record_event_state_change(self, which);
|
node.owner_doc().record_element_state_change(self, which);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_active_state(&self) -> bool {
|
pub fn get_active_state(&self) -> bool {
|
||||||
self.event_state.get().contains(IN_ACTIVE_STATE)
|
self.state.get().contains(IN_ACTIVE_STATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_active_state(&self, value: bool) {
|
pub fn set_active_state(&self, value: bool) {
|
||||||
|
@ -1857,7 +1834,7 @@ impl Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_focus_state(&self) -> bool {
|
pub fn get_focus_state(&self) -> bool {
|
||||||
self.event_state.get().contains(IN_FOCUS_STATE)
|
self.state.get().contains(IN_FOCUS_STATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_focus_state(&self, value: bool) {
|
pub fn set_focus_state(&self, value: bool) {
|
||||||
|
@ -1865,7 +1842,7 @@ impl Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_hover_state(&self) -> bool {
|
pub fn get_hover_state(&self) -> bool {
|
||||||
self.event_state.get().contains(IN_HOVER_STATE)
|
self.state.get().contains(IN_HOVER_STATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_hover_state(&self, value: bool) {
|
pub fn set_hover_state(&self, value: bool) {
|
||||||
|
@ -1873,7 +1850,7 @@ impl Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_enabled_state(&self) -> bool {
|
pub fn get_enabled_state(&self) -> bool {
|
||||||
self.event_state.get().contains(IN_ENABLED_STATE)
|
self.state.get().contains(IN_ENABLED_STATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_enabled_state(&self, value: bool) {
|
pub fn set_enabled_state(&self, value: bool) {
|
||||||
|
@ -1881,7 +1858,7 @@ impl Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_disabled_state(&self) -> bool {
|
pub fn get_disabled_state(&self) -> bool {
|
||||||
self.event_state.get().contains(IN_DISABLED_STATE)
|
self.state.get().contains(IN_DISABLED_STATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_disabled_state(&self, value: bool) {
|
pub fn set_disabled_state(&self, value: bool) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ use dom::eventtarget::EventTarget;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use string_cache::Atom;
|
||||||
use time;
|
use time;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ pub struct Event {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
current_target: MutNullableHeap<JS<EventTarget>>,
|
current_target: MutNullableHeap<JS<EventTarget>>,
|
||||||
target: MutNullableHeap<JS<EventTarget>>,
|
target: MutNullableHeap<JS<EventTarget>>,
|
||||||
type_: DOMRefCell<DOMString>,
|
type_: DOMRefCell<Atom>,
|
||||||
phase: Cell<EventPhase>,
|
phase: Cell<EventPhase>,
|
||||||
canceled: Cell<bool>,
|
canceled: Cell<bool>,
|
||||||
stop_propagation: Cell<bool>,
|
stop_propagation: Cell<bool>,
|
||||||
|
@ -62,15 +63,15 @@ impl Event {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
current_target: Default::default(),
|
current_target: Default::default(),
|
||||||
target: Default::default(),
|
target: Default::default(),
|
||||||
|
type_: DOMRefCell::new(atom!("")),
|
||||||
phase: Cell::new(EventPhase::None),
|
phase: Cell::new(EventPhase::None),
|
||||||
type_: DOMRefCell::new("".to_owned()),
|
|
||||||
canceled: Cell::new(false),
|
canceled: Cell::new(false),
|
||||||
|
stop_propagation: Cell::new(false),
|
||||||
|
stop_immediate: Cell::new(false),
|
||||||
cancelable: Cell::new(false),
|
cancelable: Cell::new(false),
|
||||||
bubbles: Cell::new(false),
|
bubbles: Cell::new(false),
|
||||||
trusted: Cell::new(false),
|
trusted: Cell::new(false),
|
||||||
dispatching: Cell::new(false),
|
dispatching: Cell::new(false),
|
||||||
stop_propagation: Cell::new(false),
|
|
||||||
stop_immediate: Cell::new(false),
|
|
||||||
initialized: Cell::new(false),
|
initialized: Cell::new(false),
|
||||||
timestamp: time::get_time().sec as u64,
|
timestamp: time::get_time().sec as u64,
|
||||||
}
|
}
|
||||||
|
@ -153,6 +154,11 @@ impl Event {
|
||||||
pub fn initialized(&self) -> bool {
|
pub fn initialized(&self) -> bool {
|
||||||
self.initialized.get()
|
self.initialized.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn type_(&self) -> Atom {
|
||||||
|
self.type_.borrow().clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventMethods for Event {
|
impl EventMethods for Event {
|
||||||
|
@ -163,7 +169,7 @@ impl EventMethods for Event {
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-event-type
|
// https://dom.spec.whatwg.org/#dom-event-type
|
||||||
fn Type(&self) -> DOMString {
|
fn Type(&self) -> DOMString {
|
||||||
self.type_.borrow().clone()
|
(*self.type_()).to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-event-target
|
// https://dom.spec.whatwg.org/#dom-event-target
|
||||||
|
@ -229,7 +235,7 @@ impl EventMethods for Event {
|
||||||
self.canceled.set(false);
|
self.canceled.set(false);
|
||||||
self.trusted.set(false);
|
self.trusted.set(false);
|
||||||
self.target.set(None);
|
self.target.set(None);
|
||||||
*self.type_.borrow_mut() = type_;
|
*self.type_.borrow_mut() = Atom::from_slice(&type_);
|
||||||
self.bubbles.set(bubbles);
|
self.bubbles.set(bubbles);
|
||||||
self.cancelable.set(cancelable);
|
self.cancelable.set(cancelable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ fn dispatch_to_listeners(event: &Event, target: &EventTarget, chain: &[&EventTar
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let type_ = event.Type();
|
let type_ = event.type_();
|
||||||
|
|
||||||
/* capturing */
|
/* capturing */
|
||||||
event.set_phase(EventPhase::Capturing);
|
event.set_phase(EventPhase::Capturing);
|
||||||
|
|
|
@ -19,7 +19,6 @@ use js::jsapi::{HandleObject, JSContext, RootedFunction};
|
||||||
use js::jsapi::{JSAutoCompartment, JSAutoRequest};
|
use js::jsapi::{JSAutoCompartment, JSAutoRequest};
|
||||||
use js::rust::{AutoObjectVectorWrapper, CompileOptionsWrapper};
|
use js::rust::{AutoObjectVectorWrapper, CompileOptionsWrapper};
|
||||||
use libc::{c_char, size_t};
|
use libc::{c_char, size_t};
|
||||||
use std::borrow::ToOwned;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::collections::hash_state::DefaultState;
|
use std::collections::hash_state::DefaultState;
|
||||||
|
@ -27,6 +26,7 @@ use std::default::Default;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{intrinsics, ptr};
|
use std::{intrinsics, ptr};
|
||||||
|
use string_cache::Atom;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::mem::HeapSizeOf;
|
use util::mem::HeapSizeOf;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
@ -114,7 +114,7 @@ pub struct EventListenerEntry {
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct EventTarget {
|
pub struct EventTarget {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
handlers: DOMRefCell<HashMap<DOMString, Vec<EventListenerEntry>, DefaultState<FnvHasher>>>,
|
handlers: DOMRefCell<HashMap<Atom, Vec<EventListenerEntry>, DefaultState<FnvHasher>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventTarget {
|
impl EventTarget {
|
||||||
|
@ -125,13 +125,13 @@ impl EventTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_listeners(&self, type_: &str) -> Option<Vec<EventListenerType>> {
|
pub fn get_listeners(&self, type_: &Atom) -> Option<Vec<EventListenerType>> {
|
||||||
self.handlers.borrow().get(type_).map(|listeners| {
|
self.handlers.borrow().get(type_).map(|listeners| {
|
||||||
listeners.iter().map(|entry| entry.listener.clone()).collect()
|
listeners.iter().map(|entry| entry.listener.clone()).collect()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_listeners_for(&self, type_: &str, desired_phase: ListenerPhase)
|
pub fn get_listeners_for(&self, type_: &Atom, desired_phase: ListenerPhase)
|
||||||
-> Option<Vec<EventListenerType>> {
|
-> Option<Vec<EventListenerType>> {
|
||||||
self.handlers.borrow().get(type_).map(|listeners| {
|
self.handlers.borrow().get(type_).map(|listeners| {
|
||||||
let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase);
|
let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase);
|
||||||
|
@ -150,7 +150,7 @@ impl EventTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_inline_event_listener(&self,
|
pub fn set_inline_event_listener(&self,
|
||||||
ty: DOMString,
|
ty: Atom,
|
||||||
listener: Option<Rc<EventHandler>>) {
|
listener: Option<Rc<EventHandler>>) {
|
||||||
let mut handlers = self.handlers.borrow_mut();
|
let mut handlers = self.handlers.borrow_mut();
|
||||||
let entries = match handlers.entry(ty) {
|
let entries = match handlers.entry(ty) {
|
||||||
|
@ -185,9 +185,9 @@ impl EventTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_inline_event_listener(&self, ty: DOMString) -> Option<Rc<EventHandler>> {
|
pub fn get_inline_event_listener(&self, ty: &Atom) -> Option<Rc<EventHandler>> {
|
||||||
let handlers = self.handlers.borrow();
|
let handlers = self.handlers.borrow();
|
||||||
let entries = handlers.get(&ty);
|
let entries = handlers.get(ty);
|
||||||
entries.and_then(|entries| entries.iter().filter_map(|entry| {
|
entries.and_then(|entries| entries.iter().filter_map(|entry| {
|
||||||
match entry.listener {
|
match entry.listener {
|
||||||
EventListenerType::Inline(ref handler) => Some(handler.clone()),
|
EventListenerType::Inline(ref handler) => Some(handler.clone()),
|
||||||
|
@ -243,11 +243,11 @@ impl EventTarget {
|
||||||
{
|
{
|
||||||
let event_listener = listener.map(|listener|
|
let event_listener = listener.map(|listener|
|
||||||
EventHandlerNonNull::new(listener.callback()));
|
EventHandlerNonNull::new(listener.callback()));
|
||||||
self.set_inline_event_listener(ty.to_owned(), event_listener);
|
self.set_inline_event_listener(Atom::from_slice(ty), event_listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_event_handler_common<T: CallbackContainer>(&self, ty: &str) -> Option<Rc<T>> {
|
pub fn get_event_handler_common<T: CallbackContainer>(&self, ty: &str) -> Option<Rc<T>> {
|
||||||
let listener = self.get_inline_event_listener(ty.to_owned());
|
let listener = self.get_inline_event_listener(&Atom::from_slice(ty));
|
||||||
listener.map(|listener| CallbackContainer::new(listener.parent.callback()))
|
listener.map(|listener| CallbackContainer::new(listener.parent.callback()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ impl EventTargetMethods for EventTarget {
|
||||||
match listener {
|
match listener {
|
||||||
Some(listener) => {
|
Some(listener) => {
|
||||||
let mut handlers = self.handlers.borrow_mut();
|
let mut handlers = self.handlers.borrow_mut();
|
||||||
let entry = match handlers.entry(ty) {
|
let entry = match handlers.entry(Atom::from_slice(&ty)) {
|
||||||
Occupied(entry) => entry.into_mut(),
|
Occupied(entry) => entry.into_mut(),
|
||||||
Vacant(entry) => entry.insert(vec!()),
|
Vacant(entry) => entry.insert(vec!()),
|
||||||
};
|
};
|
||||||
|
@ -291,7 +291,7 @@ impl EventTargetMethods for EventTarget {
|
||||||
match listener {
|
match listener {
|
||||||
Some(ref listener) => {
|
Some(ref listener) => {
|
||||||
let mut handlers = self.handlers.borrow_mut();
|
let mut handlers = self.handlers.borrow_mut();
|
||||||
let entry = handlers.get_mut(&ty);
|
let entry = handlers.get_mut(&Atom::from_slice(&ty));
|
||||||
for entry in entry {
|
for entry in entry {
|
||||||
let phase = if capture { ListenerPhase::Capturing } else { ListenerPhase::Bubbling };
|
let phase = if capture { ListenerPhase::Capturing } else { ListenerPhase::Bubbling };
|
||||||
let old_entry = EventListenerEntry {
|
let old_entry = EventListenerEntry {
|
||||||
|
|
|
@ -40,7 +40,7 @@ impl FileListMethods for FileList {
|
||||||
|
|
||||||
// https://w3c.github.io/FileAPI/#dfn-item
|
// https://w3c.github.io/FileAPI/#dfn-item
|
||||||
fn Item(&self, index: u32) -> Option<Root<File>> {
|
fn Item(&self, index: u32) -> Option<Root<File>> {
|
||||||
Some(self.list[index as usize].root())
|
Some(Root::from_ref(&*(self.list[index as usize])))
|
||||||
}
|
}
|
||||||
|
|
||||||
// check-tidy: no specs after this line
|
// check-tidy: no specs after this line
|
||||||
|
|
|
@ -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 http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
|
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
|
||||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::FileReaderBinding::{self, FileReaderConstants, FileReaderMethods};
|
use dom::bindings::codegen::Bindings::FileReaderBinding::{self, FileReaderConstants, FileReaderMethods};
|
||||||
|
@ -23,7 +24,7 @@ use hyper::mime::{Attr, Mime};
|
||||||
use rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64};
|
use rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64};
|
||||||
use script_task::ScriptTaskEventCategory::FileRead;
|
use script_task::ScriptTaskEventCategory::FileRead;
|
||||||
use script_task::{CommonScriptMsg, Runnable, ScriptChan, ScriptPort};
|
use script_task::{CommonScriptMsg, Runnable, ScriptChan, ScriptPort};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::Cell;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
@ -72,7 +73,7 @@ pub struct FileReader {
|
||||||
global: GlobalField,
|
global: GlobalField,
|
||||||
ready_state: Cell<FileReaderReadyState>,
|
ready_state: Cell<FileReaderReadyState>,
|
||||||
error: MutNullableHeap<JS<DOMException>>,
|
error: MutNullableHeap<JS<DOMException>>,
|
||||||
result: RefCell<Option<DOMString>>,
|
result: DOMRefCell<Option<DOMString>>,
|
||||||
generation_id: Cell<GenerationId>,
|
generation_id: Cell<GenerationId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ impl FileReader {
|
||||||
global: GlobalField::from_rooted(&global),
|
global: GlobalField::from_rooted(&global),
|
||||||
ready_state: Cell::new(FileReaderReadyState::Empty),
|
ready_state: Cell::new(FileReaderReadyState::Empty),
|
||||||
error: MutNullableHeap::new(None),
|
error: MutNullableHeap::new(None),
|
||||||
result: RefCell::new(None),
|
result: DOMRefCell::new(None),
|
||||||
generation_id: Cell::new(GenerationId(0)),
|
generation_id: Cell::new(GenerationId(0)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ impl FormDataMethods for FormData {
|
||||||
.get(&name)
|
.get(&name)
|
||||||
.map(|entry| match entry[0] {
|
.map(|entry| match entry[0] {
|
||||||
FormDatum::StringData(ref s) => eString(s.clone()),
|
FormDatum::StringData(ref s) => eString(s.clone()),
|
||||||
FormDatum::FileData(ref f) => eFile(f.root()),
|
FormDatum::FileData(ref f) => eFile(Root::from_ref(&*f)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ impl HTMLBodyElementMethods for HTMLBodyElement {
|
||||||
fn SetText(&self, value: DOMString) {
|
fn SetText(&self, value: DOMString) {
|
||||||
let element = self.upcast::<Element>();
|
let element = self.upcast::<Element>();
|
||||||
let color = str::parse_legacy_color(&value).ok();
|
let color = str::parse_legacy_color(&value).ok();
|
||||||
element.set_attribute(&Atom::from_slice("text"), AttrValue::Color(value, color));
|
element.set_attribute(&atom!("text"), AttrValue::Color(value, color));
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#the-body-element
|
// https://html.spec.whatwg.org/multipage/#the-body-element
|
||||||
|
|
|
@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElemen
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE};
|
use dom::element::{AttributeMutation, Element};
|
||||||
use dom::event::Event;
|
use dom::event::Event;
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
|
@ -17,8 +17,10 @@ use dom::htmlfieldsetelement::HTMLFieldSetElement;
|
||||||
use dom::htmlformelement::{FormControl, FormSubmitter};
|
use dom::htmlformelement::{FormControl, FormSubmitter};
|
||||||
use dom::htmlformelement::{SubmittedFrom, HTMLFormElement};
|
use dom::htmlformelement::{SubmittedFrom, HTMLFormElement};
|
||||||
use dom::node::{Node, document_from_node, window_from_node};
|
use dom::node::{Node, document_from_node, window_from_node};
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::ValidityState;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
|
use selectors::states::*;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -81,15 +83,7 @@ impl HTMLButtonElementMethods for HTMLButtonElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-button-type
|
// https://html.spec.whatwg.org/multipage/#dom-button-type
|
||||||
fn Type(&self) -> DOMString {
|
make_enumerated_getter!(Type, "submit", ("reset") | ("button") | ("menu"));
|
||||||
let mut ty = self.upcast::<Element>().get_string_attribute(&atom!("type"));
|
|
||||||
ty.make_ascii_lowercase();
|
|
||||||
// https://html.spec.whatwg.org/multipage/#attr-button-type
|
|
||||||
match &*ty {
|
|
||||||
"reset" | "button" | "menu" => ty,
|
|
||||||
_ => "submit".to_owned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-button-type
|
// https://html.spec.whatwg.org/multipage/#dom-button-type
|
||||||
make_setter!(SetType, "type");
|
make_setter!(SetType, "type");
|
||||||
|
@ -130,6 +124,11 @@ impl HTMLButtonElementMethods for HTMLButtonElement {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-button-value
|
// https://html.spec.whatwg.org/multipage/#dom-button-value
|
||||||
make_setter!(SetValue, "value");
|
make_setter!(SetValue, "value");
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||||
|
fn Labels(&self) -> Root<NodeList> {
|
||||||
|
self.upcast::<HTMLElement>().labels()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLButtonElement {
|
impl VirtualMethods for HTMLButtonElement {
|
||||||
|
|
|
@ -153,7 +153,7 @@ impl HTMLCanvasElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
match *self.context.borrow().as_ref().unwrap() {
|
match *self.context.borrow().as_ref().unwrap() {
|
||||||
CanvasContext::Context2d(ref context) => Some(context.root()),
|
CanvasContext::Context2d(ref context) => Some(Root::from_ref(&*context)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ impl HTMLCanvasElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() {
|
if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() {
|
||||||
Some(context.root())
|
Some(Root::from_ref(&*context))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,7 +165,7 @@ impl HTMLCollection {
|
||||||
|
|
||||||
pub fn elements_iter(&self) -> HTMLCollectionElementsIter {
|
pub fn elements_iter(&self) -> HTMLCollectionElementsIter {
|
||||||
let ref filter = self.collection.1;
|
let ref filter = self.collection.1;
|
||||||
let root = self.collection.0.root();
|
let root = Root::from_ref(&*self.collection.0);
|
||||||
let mut node_iter = root.traverse_preorder();
|
let mut node_iter = root.traverse_preorder();
|
||||||
let _ = node_iter.next(); // skip the root node
|
let _ = node_iter.next(); // skip the root node
|
||||||
HTMLCollectionElementsIter {
|
HTMLCollectionElementsIter {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::attr::AttrValue;
|
use dom::attr::AttrValue;
|
||||||
|
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::HTMLElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
|
||||||
|
@ -12,21 +13,25 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::error::{Error, ErrorResult};
|
use dom::bindings::error::{Error, ErrorResult};
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::inheritance::{ElementTypeId, HTMLElementTypeId, NodeTypeId};
|
use dom::bindings::inheritance::{ElementTypeId, HTMLElementTypeId, NodeTypeId};
|
||||||
use dom::bindings::js::{JS, MutNullableHeap, Root};
|
use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference};
|
||||||
use dom::bindings::reflector::Reflectable;
|
use dom::bindings::reflector::Reflectable;
|
||||||
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
|
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::domstringmap::DOMStringMap;
|
use dom::domstringmap::DOMStringMap;
|
||||||
use dom::element::{AttributeMutation, Element, EventState};
|
use dom::element::{AttributeMutation, Element};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::htmlbodyelement::HTMLBodyElement;
|
use dom::htmlbodyelement::HTMLBodyElement;
|
||||||
use dom::htmlframesetelement::HTMLFrameSetElement;
|
use dom::htmlframesetelement::HTMLFrameSetElement;
|
||||||
use dom::htmlhtmlelement::HTMLHtmlElement;
|
use dom::htmlhtmlelement::HTMLHtmlElement;
|
||||||
use dom::htmlinputelement::HTMLInputElement;
|
use dom::htmlinputelement::HTMLInputElement;
|
||||||
|
use dom::htmllabelelement::HTMLLabelElement;
|
||||||
use dom::node::{Node, SEQUENTIALLY_FOCUSABLE};
|
use dom::node::{Node, SEQUENTIALLY_FOCUSABLE};
|
||||||
use dom::node::{document_from_node, window_from_node};
|
use dom::node::{document_from_node, window_from_node};
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use msg::constellation_msg::FocusType;
|
use msg::constellation_msg::FocusType;
|
||||||
|
use selectors::states::*;
|
||||||
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::intrinsics;
|
use std::intrinsics;
|
||||||
|
@ -50,10 +55,10 @@ impl PartialEq for HTMLElement {
|
||||||
impl HTMLElement {
|
impl HTMLElement {
|
||||||
pub fn new_inherited(tag_name: DOMString, prefix: Option<DOMString>,
|
pub fn new_inherited(tag_name: DOMString, prefix: Option<DOMString>,
|
||||||
document: &Document) -> HTMLElement {
|
document: &Document) -> HTMLElement {
|
||||||
HTMLElement::new_inherited_with_state(EventState::empty(), tag_name, prefix, document)
|
HTMLElement::new_inherited_with_state(ElementState::empty(), tag_name, prefix, document)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_inherited_with_state(state: EventState, tag_name: DOMString,
|
pub fn new_inherited_with_state(state: ElementState, tag_name: DOMString,
|
||||||
prefix: Option<DOMString>, document: &Document)
|
prefix: Option<DOMString>, document: &Document)
|
||||||
-> HTMLElement {
|
-> HTMLElement {
|
||||||
HTMLElement {
|
HTMLElement {
|
||||||
|
@ -275,6 +280,45 @@ fn to_snake_case(name: DOMString) -> DOMString {
|
||||||
attr_name
|
attr_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#attr-data-*
|
||||||
|
// if this attribute is in snake case with a data- prefix,
|
||||||
|
// this function returns a name converted to camel case
|
||||||
|
// without the data prefix.
|
||||||
|
|
||||||
|
fn to_camel_case(name: &str) -> Option<DOMString> {
|
||||||
|
if !name.starts_with("data-") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let name = &name[5..];
|
||||||
|
let has_uppercase = name.chars().any(|curr_char| {
|
||||||
|
curr_char.is_ascii() && curr_char.is_uppercase()
|
||||||
|
});
|
||||||
|
if has_uppercase {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut result = "".to_owned();
|
||||||
|
let mut name_chars = name.chars();
|
||||||
|
while let Some(curr_char) = name_chars.next() {
|
||||||
|
//check for hyphen followed by character
|
||||||
|
if curr_char == '\x2d' {
|
||||||
|
if let Some(next_char) = name_chars.next() {
|
||||||
|
if next_char.is_ascii() && next_char.is_lowercase() {
|
||||||
|
result.push(next_char.to_ascii_uppercase());
|
||||||
|
} else {
|
||||||
|
result.push(curr_char);
|
||||||
|
result.push(next_char);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push(curr_char);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push(curr_char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(result)
|
||||||
|
}
|
||||||
|
|
||||||
impl HTMLElement {
|
impl HTMLElement {
|
||||||
pub fn set_custom_attr(&self, name: DOMString, value: DOMString) -> ErrorResult {
|
pub fn set_custom_attr(&self, name: DOMString, value: DOMString) -> ErrorResult {
|
||||||
if name.chars()
|
if name.chars()
|
||||||
|
@ -316,6 +360,53 @@ impl HTMLElement {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn supported_prop_names_custom_attr(&self) -> Vec<DOMString> {
|
||||||
|
let element = self.upcast::<Element>();
|
||||||
|
element.attrs().iter().filter_map(|attr| {
|
||||||
|
let raw_name = attr.local_name();
|
||||||
|
to_camel_case(&raw_name)
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||||
|
pub fn labels(&self) -> Root<NodeList> {
|
||||||
|
debug_assert!(self.is_labelable_element());
|
||||||
|
|
||||||
|
let element = self.upcast::<Element>();
|
||||||
|
let window = window_from_node(element);
|
||||||
|
|
||||||
|
// Traverse ancestors for implicitly associated <label> elements
|
||||||
|
// https://html.spec.whatwg.org/multipage/#the-label-element:attr-label-for-4
|
||||||
|
let ancestors =
|
||||||
|
self.upcast::<Node>()
|
||||||
|
.ancestors()
|
||||||
|
.filter_map(Root::downcast::<HTMLElement>)
|
||||||
|
// If we reach a labelable element, we have a guarantee no ancestors above it
|
||||||
|
// will be a label for this HTMLElement
|
||||||
|
.take_while(|elem| !elem.is_labelable_element())
|
||||||
|
.filter_map(Root::downcast::<HTMLLabelElement>)
|
||||||
|
.filter(|elem| !elem.upcast::<Element>().has_attribute(&atom!("for")))
|
||||||
|
.filter(|elem| elem.first_labelable_descendant().r() == Some(self))
|
||||||
|
.map(Root::upcast::<Node>);
|
||||||
|
|
||||||
|
let id = element.Id();
|
||||||
|
let id = match &id as &str {
|
||||||
|
"" => return NodeList::new_simple_list(window.r(), ancestors),
|
||||||
|
id => id,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Traverse entire tree for <label> elements with `for` attribute matching `id`
|
||||||
|
let root_element = element.get_root_element();
|
||||||
|
let root_node = root_element.upcast::<Node>();
|
||||||
|
let children = root_node.traverse_preorder()
|
||||||
|
.filter_map(Root::downcast::<Element>)
|
||||||
|
.filter(|elem| elem.is::<HTMLLabelElement>())
|
||||||
|
.filter(|elem| elem.get_string_attribute(&atom!("for")) == id)
|
||||||
|
.map(Root::upcast::<Node>);
|
||||||
|
|
||||||
|
NodeList::new_simple_list(window.r(), children.chain(ancestors))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLElement {
|
impl VirtualMethods for HTMLElement {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetEl
|
||||||
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
|
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
|
||||||
use dom::bindings::js::{Root, RootedReference};
|
use dom::bindings::js::{Root, RootedReference};
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE};
|
use dom::element::{AttributeMutation, Element};
|
||||||
use dom::htmlcollection::{CollectionFilter, HTMLCollection};
|
use dom::htmlcollection::{CollectionFilter, HTMLCollection};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||||
|
@ -16,6 +16,7 @@ use dom::htmllegendelement::HTMLLegendElement;
|
||||||
use dom::node::{Node, window_from_node};
|
use dom::node::{Node, window_from_node};
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::ValidityState;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
|
use selectors::states::*;
|
||||||
use util::str::{DOMString, StaticStringVec};
|
use util::str::{DOMString, StaticStringVec};
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
use cssparser::RGBA;
|
use cssparser::RGBA;
|
||||||
use dom::attr::{Attr, AttrValue};
|
use dom::attr::{Attr, AttrValue};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
|
||||||
use dom::bindings::codegen::Bindings::HTMLFontElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLFontElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLFontElementBinding::HTMLFontElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLFontElementBinding::HTMLFontElementMethods;
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
|
@ -23,7 +22,6 @@ use util::str::{self, DOMString, parse_legacy_font_size};
|
||||||
pub struct HTMLFontElement {
|
pub struct HTMLFontElement {
|
||||||
htmlelement: HTMLElement,
|
htmlelement: HTMLElement,
|
||||||
color: Cell<Option<RGBA>>,
|
color: Cell<Option<RGBA>>,
|
||||||
face: DOMRefCell<Option<Atom>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +30,6 @@ impl HTMLFontElement {
|
||||||
HTMLFontElement {
|
HTMLFontElement {
|
||||||
htmlelement: HTMLElement::new_inherited(localName, prefix, document),
|
htmlelement: HTMLElement::new_inherited(localName, prefix, document),
|
||||||
color: Cell::new(None),
|
color: Cell::new(None),
|
||||||
face: DOMRefCell::new(None),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +62,7 @@ impl HTMLFontElementMethods for HTMLFontElement {
|
||||||
fn SetSize(&self, value: DOMString) {
|
fn SetSize(&self, value: DOMString) {
|
||||||
let element = self.upcast::<Element>();
|
let element = self.upcast::<Element>();
|
||||||
let length = parse_length(&value);
|
let length = parse_length(&value);
|
||||||
element.set_attribute(&Atom::from_slice("size"), AttrValue::Length(value, length));
|
element.set_attribute(&atom!("size"), AttrValue::Length(value, length));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +79,6 @@ impl VirtualMethods for HTMLFontElement {
|
||||||
str::parse_legacy_color(&value).ok()
|
str::parse_legacy_color(&value).ok()
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
&atom!(face) => {
|
|
||||||
*self.face.borrow_mut() =
|
|
||||||
mutation.new_value(attr)
|
|
||||||
.map(|value| value.as_atom().clone())
|
|
||||||
},
|
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,10 +103,11 @@ impl HTMLFontElement {
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn get_face(&self) -> Option<Atom> {
|
pub fn get_face(&self) -> Option<Atom> {
|
||||||
let face = unsafe { self.face.borrow_for_layout() };
|
unsafe {
|
||||||
match *face {
|
self.upcast::<Element>()
|
||||||
Some(ref s) => Some(s.clone()),
|
.get_attr_for_layout(&ns!(""), &atom!("face"))
|
||||||
None => None,
|
.map(AttrValue::as_atom)
|
||||||
|
.cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -305,7 +305,7 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
|
||||||
fn Mozbrowser(&self) -> bool {
|
fn Mozbrowser(&self) -> bool {
|
||||||
if mozbrowser_enabled() {
|
if mozbrowser_enabled() {
|
||||||
let element = self.upcast::<Element>();
|
let element = self.upcast::<Element>();
|
||||||
element.has_attribute(&Atom::from_slice("mozbrowser"))
|
element.has_attribute(&atom!("mozbrowser"))
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,7 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
|
||||||
fn SetMozbrowser(&self, value: bool) -> ErrorResult {
|
fn SetMozbrowser(&self, value: bool) -> ErrorResult {
|
||||||
if mozbrowser_enabled() {
|
if mozbrowser_enabled() {
|
||||||
let element = self.upcast::<Element>();
|
let element = self.upcast::<Element>();
|
||||||
element.set_bool_attribute(&Atom::from_slice("mozbrowser"), value);
|
element.set_bool_attribute(&atom!("mozbrowser"), value);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::{LayoutJS, Root};
|
use dom::bindings::js::{LayoutJS, Root};
|
||||||
use dom::bindings::refcounted::Trusted;
|
use dom::bindings::refcounted::Trusted;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, Element};
|
use dom::element::AttributeMutation;
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
|
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
|
||||||
|
@ -196,11 +196,8 @@ impl HTMLImageElementMethods for HTMLImageElement {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-img-ismap
|
// https://html.spec.whatwg.org/multipage/#dom-img-ismap
|
||||||
make_bool_getter!(IsMap);
|
make_bool_getter!(IsMap);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-img-ismap
|
// https://html.spec.whatwg.org/multipage/#dom-img-ismap
|
||||||
fn SetIsMap(&self, is_map: bool) {
|
make_bool_setter!(SetIsMap, "ismap");
|
||||||
self.upcast::<Element>().set_string_attribute(&atom!("ismap"), is_map.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-img-width
|
// https://html.spec.whatwg.org/multipage/#dom-img-width
|
||||||
fn Width(&self) -> u32 {
|
fn Width(&self) -> u32 {
|
||||||
|
@ -210,9 +207,7 @@ impl HTMLImageElementMethods for HTMLImageElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-img-width
|
// https://html.spec.whatwg.org/multipage/#dom-img-width
|
||||||
fn SetWidth(&self, width: u32) {
|
make_uint_setter!(SetWidth, "width");
|
||||||
self.upcast::<Element>().set_uint_attribute(&atom!("width"), width)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-img-height
|
// https://html.spec.whatwg.org/multipage/#dom-img-height
|
||||||
fn Height(&self) -> u32 {
|
fn Height(&self) -> u32 {
|
||||||
|
@ -222,9 +217,7 @@ impl HTMLImageElementMethods for HTMLImageElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-img-height
|
// https://html.spec.whatwg.org/multipage/#dom-img-height
|
||||||
fn SetHeight(&self, height: u32) {
|
make_uint_setter!(SetHeight, "height");
|
||||||
self.upcast::<Element>().set_uint_attribute(&atom!("height"), height)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-img-naturalwidth
|
// https://html.spec.whatwg.org/multipage/#dom-img-naturalwidth
|
||||||
fn NaturalWidth(&self) -> u32 {
|
fn NaturalWidth(&self) -> u32 {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use dom::bindings::global::GlobalRef;
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::{JS, LayoutJS, Root, RootedReference};
|
use dom::bindings::js::{JS, LayoutJS, Root, RootedReference};
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE, RawLayoutElementHelpers};
|
use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers, LayoutElementHelpers};
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
|
@ -25,8 +25,10 @@ use dom::htmlformelement::{ResetFrom, SubmittedFrom};
|
||||||
use dom::keyboardevent::KeyboardEvent;
|
use dom::keyboardevent::KeyboardEvent;
|
||||||
use dom::node::{Node, NodeDamage};
|
use dom::node::{Node, NodeDamage};
|
||||||
use dom::node::{document_from_node, window_from_node};
|
use dom::node::{document_from_node, window_from_node};
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use msg::constellation_msg::ConstellationChan;
|
use msg::constellation_msg::ConstellationChan;
|
||||||
|
use selectors::states::*;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
|
@ -57,10 +59,8 @@ enum InputType {
|
||||||
pub struct HTMLInputElement {
|
pub struct HTMLInputElement {
|
||||||
htmlelement: HTMLElement,
|
htmlelement: HTMLElement,
|
||||||
input_type: Cell<InputType>,
|
input_type: Cell<InputType>,
|
||||||
checked: Cell<bool>,
|
|
||||||
checked_changed: Cell<bool>,
|
checked_changed: Cell<bool>,
|
||||||
placeholder: DOMRefCell<DOMString>,
|
placeholder: DOMRefCell<DOMString>,
|
||||||
indeterminate: Cell<bool>,
|
|
||||||
value_changed: Cell<bool>,
|
value_changed: Cell<bool>,
|
||||||
size: Cell<u32>,
|
size: Cell<u32>,
|
||||||
#[ignore_heap_size_of = "#7193"]
|
#[ignore_heap_size_of = "#7193"]
|
||||||
|
@ -111,9 +111,7 @@ impl HTMLInputElement {
|
||||||
HTMLElement::new_inherited_with_state(IN_ENABLED_STATE,
|
HTMLElement::new_inherited_with_state(IN_ENABLED_STATE,
|
||||||
localName, prefix, document),
|
localName, prefix, document),
|
||||||
input_type: Cell::new(InputType::InputText),
|
input_type: Cell::new(InputType::InputText),
|
||||||
checked: Cell::new(false),
|
|
||||||
placeholder: DOMRefCell::new("".to_owned()),
|
placeholder: DOMRefCell::new("".to_owned()),
|
||||||
indeterminate: Cell::new(false),
|
|
||||||
checked_changed: Cell::new(false),
|
checked_changed: Cell::new(false),
|
||||||
value_changed: Cell::new(false),
|
value_changed: Cell::new(false),
|
||||||
size: Cell::new(DEFAULT_INPUT_SIZE),
|
size: Cell::new(DEFAULT_INPUT_SIZE),
|
||||||
|
@ -138,15 +136,10 @@ pub trait LayoutHTMLInputElementHelpers {
|
||||||
unsafe fn get_size_for_layout(self) -> u32;
|
unsafe fn get_size_for_layout(self) -> u32;
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn get_insertion_point_for_layout(self) -> Option<TextPoint>;
|
unsafe fn get_insertion_point_for_layout(self) -> Option<TextPoint>;
|
||||||
}
|
|
||||||
|
|
||||||
pub trait RawLayoutHTMLInputElementHelpers {
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn get_checked_state_for_layout(&self) -> bool;
|
unsafe fn get_checked_state_for_layout(self) -> bool;
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn get_indeterminate_state_for_layout(&self) -> bool;
|
unsafe fn get_indeterminate_state_for_layout(self) -> bool;
|
||||||
#[allow(unsafe_code)]
|
|
||||||
unsafe fn get_size_for_layout(&self) -> u32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> {
|
impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> {
|
||||||
|
@ -186,7 +179,7 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> {
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn get_size_for_layout(self) -> u32 {
|
unsafe fn get_size_for_layout(self) -> u32 {
|
||||||
(*self.unsafe_get()).get_size_for_layout()
|
(*self.unsafe_get()).size.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
|
@ -198,25 +191,17 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> {
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl RawLayoutHTMLInputElementHelpers for HTMLInputElement {
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn get_checked_state_for_layout(&self) -> bool {
|
unsafe fn get_checked_state_for_layout(self) -> bool {
|
||||||
self.checked.get()
|
self.upcast::<Element>().get_state_for_layout().contains(IN_CHECKED_STATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn get_indeterminate_state_for_layout(&self) -> bool {
|
unsafe fn get_indeterminate_state_for_layout(self) -> bool {
|
||||||
self.indeterminate.get()
|
self.upcast::<Element>().get_state_for_layout().contains(IN_INDETERMINATE_STATE)
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
unsafe fn get_size_for_layout(&self) -> u32 {
|
|
||||||
self.size.get()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +225,7 @@ impl HTMLInputElementMethods for HTMLInputElement {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-input-checked
|
// https://html.spec.whatwg.org/multipage/#dom-input-checked
|
||||||
fn Checked(&self) -> bool {
|
fn Checked(&self) -> bool {
|
||||||
self.checked.get()
|
self.upcast::<Element>().get_state().contains(IN_CHECKED_STATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-input-checked
|
// https://html.spec.whatwg.org/multipage/#dom-input-checked
|
||||||
|
@ -329,12 +314,22 @@ impl HTMLInputElementMethods for HTMLInputElement {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-input-indeterminate
|
// https://html.spec.whatwg.org/multipage/#dom-input-indeterminate
|
||||||
fn Indeterminate(&self) -> bool {
|
fn Indeterminate(&self) -> bool {
|
||||||
self.indeterminate.get()
|
self.upcast::<Element>().get_state().contains(IN_INDETERMINATE_STATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-input-indeterminate
|
// https://html.spec.whatwg.org/multipage/#dom-input-indeterminate
|
||||||
fn SetIndeterminate(&self, val: bool) {
|
fn SetIndeterminate(&self, val: bool) {
|
||||||
self.indeterminate.set(val)
|
self.upcast::<Element>().set_state(IN_INDETERMINATE_STATE, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||||
|
fn Labels(&self) -> Root<NodeList> {
|
||||||
|
if self.Type() == "hidden" {
|
||||||
|
let window = window_from_node(self);
|
||||||
|
NodeList::empty(&window)
|
||||||
|
} else {
|
||||||
|
self.upcast::<HTMLElement>().labels()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,7 +438,7 @@ impl HTMLInputElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_checked_state(&self, checked: bool, dirty: bool) {
|
fn update_checked_state(&self, checked: bool, dirty: bool) {
|
||||||
self.checked.set(checked);
|
self.upcast::<Element>().set_state(IN_CHECKED_STATE, checked);
|
||||||
|
|
||||||
if dirty {
|
if dirty {
|
||||||
self.checked_changed.set(true);
|
self.checked_changed.set(true);
|
||||||
|
@ -459,7 +454,7 @@ impl HTMLInputElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_indeterminate_state(&self) -> bool {
|
pub fn get_indeterminate_state(&self) -> bool {
|
||||||
self.indeterminate.get()
|
self.Indeterminate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#concept-fe-mutable
|
// https://html.spec.whatwg.org/multipage/#concept-fe-mutable
|
||||||
|
@ -610,7 +605,7 @@ impl VirtualMethods for HTMLInputElement {
|
||||||
s.handle_event(event);
|
s.handle_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
if &*event.Type() == "click" && !event.DefaultPrevented() {
|
if event.type_() == atom!("click") && !event.DefaultPrevented() {
|
||||||
match self.input_type.get() {
|
match self.input_type.get() {
|
||||||
InputType::InputRadio => self.update_checked_state(true, true),
|
InputType::InputRadio => self.update_checked_state(true, true),
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -622,7 +617,7 @@ impl VirtualMethods for HTMLInputElement {
|
||||||
//TODO: set the editing position for text inputs
|
//TODO: set the editing position for text inputs
|
||||||
|
|
||||||
document_from_node(self).request_focus(self.upcast());
|
document_from_node(self).request_focus(self.upcast());
|
||||||
} else if &*event.Type() == "keydown" && !event.DefaultPrevented() &&
|
} else if event.type_() == atom!("keydown") && !event.DefaultPrevented() &&
|
||||||
(self.input_type.get() == InputType::InputText ||
|
(self.input_type.get() == InputType::InputText ||
|
||||||
self.input_type.get() == InputType::InputPassword) {
|
self.input_type.get() == InputType::InputPassword) {
|
||||||
if let Some(keyevent) = event.downcast::<KeyboardEvent>() {
|
if let Some(keyevent) = event.downcast::<KeyboardEvent>() {
|
||||||
|
|
|
@ -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 http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::activation::Activatable;
|
||||||
use dom::attr::AttrValue;
|
use dom::attr::AttrValue;
|
||||||
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
|
||||||
|
@ -9,6 +10,8 @@ use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::Element;
|
use dom::element::Element;
|
||||||
|
use dom::event::Event;
|
||||||
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||||
use dom::node::{document_from_node, Node};
|
use dom::node::{document_from_node, Node};
|
||||||
|
@ -40,6 +43,40 @@ impl HTMLLabelElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Activatable for HTMLLabelElement {
|
||||||
|
fn as_element(&self) -> &Element {
|
||||||
|
self.upcast::<Element>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_instance_activatable(&self) -> bool {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#run-pre-click-activation-steps
|
||||||
|
// https://html.spec.whatwg.org/multipage/#the-button-element:activation-behavior
|
||||||
|
fn pre_click_activation(&self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#run-canceled-activation-steps
|
||||||
|
fn canceled_activation(&self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
|
||||||
|
fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
|
||||||
|
self.upcast::<Element>()
|
||||||
|
.as_maybe_activatable()
|
||||||
|
.map(|a| a.synthetic_click_activation(false, false, false, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#implicit-submission
|
||||||
|
fn implicit_submission(&self, _ctrlKey: bool, _shiftKey: bool, _altKey: bool, _metaKey: bool) {
|
||||||
|
//FIXME: Investigate and implement implicit submission for label elements
|
||||||
|
// Issue filed at https://github.com/servo/servo/issues/8263
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
impl HTMLLabelElementMethods for HTMLLabelElement {
|
impl HTMLLabelElementMethods for HTMLLabelElement {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-fae-form
|
// https://html.spec.whatwg.org/multipage/#dom-fae-form
|
||||||
fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
|
fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
|
||||||
|
@ -86,7 +123,7 @@ impl VirtualMethods for HTMLLabelElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLLabelElement {
|
impl HTMLLabelElement {
|
||||||
fn first_labelable_descendant(&self) -> Option<Root<HTMLElement>> {
|
pub fn first_labelable_descendant(&self) -> Option<Root<HTMLElement>> {
|
||||||
self.upcast::<Node>()
|
self.upcast::<Node>()
|
||||||
.traverse_preorder()
|
.traverse_preorder()
|
||||||
.filter_map(Root::downcast::<HTMLElement>)
|
.filter_map(Root::downcast::<HTMLElement>)
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
* 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 http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::bindings::codegen::Bindings::HTMLMeterElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLMeterElementBinding::{self, HTMLMeterElementMethods};
|
||||||
|
use dom::bindings::conversions::Castable;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::node::Node;
|
use dom::node::Node;
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
@ -31,3 +33,10 @@ impl HTMLMeterElement {
|
||||||
Node::reflect_node(box element, document, HTMLMeterElementBinding::Wrap)
|
Node::reflect_node(box element, document, HTMLMeterElementBinding::Wrap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HTMLMeterElementMethods for HTMLMeterElement {
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||||
|
fn Labels(&self) -> Root<NodeList> {
|
||||||
|
self.upcast::<HTMLElement>().labels()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,11 +8,12 @@ use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding::HTMLOptGroupEl
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE};
|
use dom::element::{AttributeMutation, Element};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmloptionelement::HTMLOptionElement;
|
use dom::htmloptionelement::HTMLOptionElement;
|
||||||
use dom::node::Node;
|
use dom::node::Node;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
|
use selectors::states::*;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
|
|
@ -11,13 +11,14 @@ use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::characterdata::CharacterData;
|
use dom::characterdata::CharacterData;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE};
|
use dom::element::{AttributeMutation, Element};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlscriptelement::HTMLScriptElement;
|
use dom::htmlscriptelement::HTMLScriptElement;
|
||||||
use dom::htmlselectelement::HTMLSelectElement;
|
use dom::htmlselectelement::HTMLSelectElement;
|
||||||
use dom::node::Node;
|
use dom::node::Node;
|
||||||
use dom::text::Text;
|
use dom::text::Text;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
|
use selectors::states::*;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use util::str::{DOMString, split_html_space_chars, str_join};
|
use util::str::{DOMString, split_html_space_chars, str_join};
|
||||||
|
|
||||||
|
@ -91,9 +92,7 @@ impl HTMLOptionElementMethods for HTMLOptionElement {
|
||||||
make_bool_getter!(Disabled);
|
make_bool_getter!(Disabled);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-option-disabled
|
// https://html.spec.whatwg.org/multipage/#dom-option-disabled
|
||||||
fn SetDisabled(&self, disabled: bool) {
|
make_bool_setter!(SetDisabled, "disabled");
|
||||||
self.upcast::<Element>().set_bool_attribute(&atom!("disabled"), disabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-option-text
|
// https://html.spec.whatwg.org/multipage/#dom-option-text
|
||||||
fn Text(&self) -> DOMString {
|
fn Text(&self) -> DOMString {
|
||||||
|
|
|
@ -4,11 +4,13 @@
|
||||||
|
|
||||||
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding::HTMLOutputElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding::HTMLOutputElementMethods;
|
||||||
|
use dom::bindings::conversions::Castable;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||||
use dom::node::{Node, window_from_node};
|
use dom::node::{Node, window_from_node};
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::ValidityState;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
|
||||||
|
@ -47,6 +49,11 @@ impl HTMLOutputElementMethods for HTMLOutputElement {
|
||||||
fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
|
fn GetForm(&self) -> Option<Root<HTMLFormElement>> {
|
||||||
self.form_owner()
|
self.form_owner()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||||
|
fn Labels(&self) -> Root<NodeList> {
|
||||||
|
self.upcast::<HTMLElement>().labels()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FormControl for HTMLOutputElement {}
|
impl FormControl for HTMLOutputElement {}
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
* 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 http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::bindings::codegen::Bindings::HTMLProgressElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLProgressElementBinding::{self, HTMLProgressElementMethods};
|
||||||
|
use dom::bindings::conversions::Castable;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::node::Node;
|
use dom::node::Node;
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
@ -32,3 +34,10 @@ impl HTMLProgressElement {
|
||||||
Node::reflect_node(box element, document, HTMLProgressElementBinding::Wrap)
|
Node::reflect_node(box element, document, HTMLProgressElementBinding::Wrap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HTMLProgressElementMethods for HTMLProgressElement {
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||||
|
fn Labels(&self) -> Root<NodeList> {
|
||||||
|
self.upcast::<HTMLElement>().labels()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ use network_listener::{NetworkListener, PreInvoke};
|
||||||
use script_task::ScriptTaskEventCategory::ScriptEvent;
|
use script_task::ScriptTaskEventCategory::ScriptEvent;
|
||||||
use script_task::{CommonScriptMsg, Runnable, ScriptChan};
|
use script_task::{CommonScriptMsg, Runnable, ScriptChan};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::Cell;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use url::{Url, UrlParser};
|
use url::{Url, UrlParser};
|
||||||
|
@ -65,7 +65,7 @@ pub struct HTMLScriptElement {
|
||||||
parser_document: JS<Document>,
|
parser_document: JS<Document>,
|
||||||
|
|
||||||
/// The source this script was loaded from
|
/// The source this script was loaded from
|
||||||
load: RefCell<Option<ScriptOrigin>>,
|
load: DOMRefCell<Option<ScriptOrigin>>,
|
||||||
|
|
||||||
#[ignore_heap_size_of = "Defined in rust-encoding"]
|
#[ignore_heap_size_of = "Defined in rust-encoding"]
|
||||||
/// https://html.spec.whatwg.org/multipage/#concept-script-encoding
|
/// https://html.spec.whatwg.org/multipage/#concept-script-encoding
|
||||||
|
@ -83,7 +83,7 @@ impl HTMLScriptElement {
|
||||||
non_blocking: Cell::new(creator != ElementCreator::ParserCreated),
|
non_blocking: Cell::new(creator != ElementCreator::ParserCreated),
|
||||||
ready_to_be_parser_executed: Cell::new(false),
|
ready_to_be_parser_executed: Cell::new(false),
|
||||||
parser_document: JS::from_ref(document),
|
parser_document: JS::from_ref(document),
|
||||||
load: RefCell::new(None),
|
load: DOMRefCell::new(None),
|
||||||
block_character_encoding: DOMRefCell::new(UTF_8 as EncodingRef),
|
block_character_encoding: DOMRefCell::new(UTF_8 as EncodingRef),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,7 +364,7 @@ impl HTMLScriptElement {
|
||||||
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
let doc = document_from_node(self);
|
let doc = document_from_node(self);
|
||||||
if self.parser_inserted.get() && doc.r() != self.parser_document.root().r() {
|
if self.parser_inserted.get() && &*doc != &*self.parser_document {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,8 +562,8 @@ impl VirtualMethods for HTMLScriptElement {
|
||||||
|
|
||||||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
||||||
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
||||||
match attr.local_name() {
|
match *attr.local_name() {
|
||||||
&atom!("src") => {
|
atom!("src") => {
|
||||||
if let AttributeMutation::Set(_) = mutation {
|
if let AttributeMutation::Set(_) = mutation {
|
||||||
if !self.parser_inserted.get() && self.upcast::<Node>().is_in_doc() {
|
if !self.parser_inserted.get() && self.upcast::<Node>().is_in_doc() {
|
||||||
self.prepare();
|
self.prepare();
|
||||||
|
|
|
@ -11,14 +11,16 @@ use dom::bindings::codegen::UnionTypes::HTMLOptionElementOrHTMLOptGroupElement;
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE};
|
use dom::element::{AttributeMutation, Element};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlfieldsetelement::HTMLFieldSetElement;
|
use dom::htmlfieldsetelement::HTMLFieldSetElement;
|
||||||
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||||
use dom::htmloptionelement::HTMLOptionElement;
|
use dom::htmloptionelement::HTMLOptionElement;
|
||||||
use dom::node::{Node, window_from_node};
|
use dom::node::{Node, window_from_node};
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use dom::validitystate::ValidityState;
|
use dom::validitystate::ValidityState;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
|
use selectors::states::*;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
@ -157,6 +159,11 @@ impl HTMLSelectElementMethods for HTMLSelectElement {
|
||||||
"select-one".to_owned()
|
"select-one".to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||||
|
fn Labels(&self) -> Root<NodeList> {
|
||||||
|
self.upcast::<HTMLElement>().labels()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLSelectElement {
|
impl VirtualMethods for HTMLSelectElement {
|
||||||
|
@ -205,8 +212,8 @@ impl VirtualMethods for HTMLSelectElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_plain_attribute(&self, local_name: &Atom, value: DOMString) -> AttrValue {
|
fn parse_plain_attribute(&self, local_name: &Atom, value: DOMString) -> AttrValue {
|
||||||
match local_name {
|
match *local_name {
|
||||||
&atom!("size") => AttrValue::from_u32(value, DEFAULT_SELECT_SIZE),
|
atom!("size") => AttrValue::from_u32(value, DEFAULT_SELECT_SIZE),
|
||||||
_ => self.super_type().unwrap().parse_plain_attribute(local_name, value),
|
_ => self.super_type().unwrap().parse_plain_attribute(local_name, value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl HTMLTableCellElementMethods for HTMLTableCellElement {
|
||||||
make_uint_getter!(ColSpan, "colspan", DEFAULT_COLSPAN);
|
make_uint_getter!(ColSpan, "colspan", DEFAULT_COLSPAN);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-tdth-colspan
|
// https://html.spec.whatwg.org/multipage/#dom-tdth-colspan
|
||||||
make_uint_setter!(SetColSpan, "colspan");
|
make_uint_setter!(SetColSpan, "colspan", DEFAULT_COLSPAN);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-tdth-cellindex
|
// https://html.spec.whatwg.org/multipage/#dom-tdth-cellindex
|
||||||
fn CellIndex(&self) -> i32 {
|
fn CellIndex(&self) -> i32 {
|
||||||
|
@ -107,18 +107,18 @@ impl VirtualMethods for HTMLTableCellElement {
|
||||||
|
|
||||||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
||||||
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
||||||
match attr.local_name() {
|
match *attr.local_name() {
|
||||||
&atom!(bgcolor) => {
|
atom!(bgcolor) => {
|
||||||
self.background_color.set(mutation.new_value(attr).and_then(|value| {
|
self.background_color.set(mutation.new_value(attr).and_then(|value| {
|
||||||
str::parse_legacy_color(&value).ok()
|
str::parse_legacy_color(&value).ok()
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
&atom!(colspan) => {
|
atom!(colspan) => {
|
||||||
self.colspan.set(mutation.new_value(attr).map(|value| {
|
self.colspan.set(mutation.new_value(attr).map(|value| {
|
||||||
max(DEFAULT_COLSPAN, value.as_uint())
|
max(DEFAULT_COLSPAN, value.as_uint())
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
&atom!(width) => {
|
atom!(width) => {
|
||||||
let width = mutation.new_value(attr).map(|value| {
|
let width = mutation.new_value(attr).map(|value| {
|
||||||
str::parse_length(&value)
|
str::parse_length(&value)
|
||||||
});
|
});
|
||||||
|
@ -129,8 +129,8 @@ impl VirtualMethods for HTMLTableCellElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_plain_attribute(&self, local_name: &Atom, value: DOMString) -> AttrValue {
|
fn parse_plain_attribute(&self, local_name: &Atom, value: DOMString) -> AttrValue {
|
||||||
match local_name {
|
match *local_name {
|
||||||
&atom!("colspan") => AttrValue::from_u32(value, DEFAULT_COLSPAN),
|
atom!("colspan") => AttrValue::from_u32(value, DEFAULT_COLSPAN),
|
||||||
_ => self.super_type().unwrap().parse_plain_attribute(local_name, value),
|
_ => self.super_type().unwrap().parse_plain_attribute(local_name, value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,24 +141,24 @@ impl VirtualMethods for HTMLTableElement {
|
||||||
|
|
||||||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
||||||
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
||||||
match attr.local_name() {
|
match *attr.local_name() {
|
||||||
&atom!(bgcolor) => {
|
atom!(bgcolor) => {
|
||||||
self.background_color.set(mutation.new_value(attr).and_then(|value| {
|
self.background_color.set(mutation.new_value(attr).and_then(|value| {
|
||||||
str::parse_legacy_color(&value).ok()
|
str::parse_legacy_color(&value).ok()
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
&atom!(border) => {
|
atom!(border) => {
|
||||||
// According to HTML5 § 14.3.9, invalid values map to 1px.
|
// According to HTML5 § 14.3.9, invalid values map to 1px.
|
||||||
self.border.set(mutation.new_value(attr).map(|value| {
|
self.border.set(mutation.new_value(attr).map(|value| {
|
||||||
str::parse_unsigned_integer(value.chars()).unwrap_or(1)
|
str::parse_unsigned_integer(value.chars()).unwrap_or(1)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
&atom!(cellspacing) => {
|
atom!(cellspacing) => {
|
||||||
self.cellspacing.set(mutation.new_value(attr).and_then(|value| {
|
self.cellspacing.set(mutation.new_value(attr).and_then(|value| {
|
||||||
str::parse_unsigned_integer(value.chars())
|
str::parse_unsigned_integer(value.chars())
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
&atom!(width) => {
|
atom!(width) => {
|
||||||
let width = mutation.new_value(attr).map(|value| {
|
let width = mutation.new_value(attr).map(|value| {
|
||||||
str::parse_length(&value)
|
str::parse_length(&value)
|
||||||
});
|
});
|
||||||
|
@ -169,8 +169,8 @@ impl VirtualMethods for HTMLTableElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_plain_attribute(&self, local_name: &Atom, value: DOMString) -> AttrValue {
|
fn parse_plain_attribute(&self, local_name: &Atom, value: DOMString) -> AttrValue {
|
||||||
match local_name {
|
match *local_name {
|
||||||
&atom!("border") => AttrValue::from_u32(value, 1),
|
atom!("border") => AttrValue::from_u32(value, 1),
|
||||||
_ => self.super_type().unwrap().parse_plain_attribute(local_name, value),
|
_ => self.super_type().unwrap().parse_plain_attribute(local_name, value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,8 +102,8 @@ impl VirtualMethods for HTMLTableRowElement {
|
||||||
|
|
||||||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
||||||
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
||||||
match attr.local_name() {
|
match *attr.local_name() {
|
||||||
&atom!(bgcolor) => {
|
atom!(bgcolor) => {
|
||||||
self.background_color.set(mutation.new_value(attr).and_then(|value| {
|
self.background_color.set(mutation.new_value(attr).and_then(|value| {
|
||||||
str::parse_legacy_color(&value).ok()
|
str::parse_legacy_color(&value).ok()
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -87,8 +87,8 @@ impl VirtualMethods for HTMLTableSectionElement {
|
||||||
|
|
||||||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
||||||
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
||||||
match attr.local_name() {
|
match *attr.local_name() {
|
||||||
&atom!(bgcolor) => {
|
atom!(bgcolor) => {
|
||||||
self.background_color.set(mutation.new_value(attr).and_then(|value| {
|
self.background_color.set(mutation.new_value(attr).and_then(|value| {
|
||||||
str::parse_legacy_color(&value).ok()
|
str::parse_legacy_color(&value).ok()
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -13,7 +13,7 @@ use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::{LayoutJS, Root};
|
use dom::bindings::js::{LayoutJS, Root};
|
||||||
use dom::bindings::refcounted::Trusted;
|
use dom::bindings::refcounted::Trusted;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, IN_ENABLED_STATE, Element};
|
use dom::element::{AttributeMutation, Element};
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
|
@ -22,10 +22,12 @@ use dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||||
use dom::keyboardevent::KeyboardEvent;
|
use dom::keyboardevent::KeyboardEvent;
|
||||||
use dom::node::{ChildrenMutation, Node, NodeDamage};
|
use dom::node::{ChildrenMutation, Node, NodeDamage};
|
||||||
use dom::node::{document_from_node, window_from_node};
|
use dom::node::{document_from_node, window_from_node};
|
||||||
|
use dom::nodelist::NodeList;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use msg::constellation_msg::ConstellationChan;
|
use msg::constellation_msg::ConstellationChan;
|
||||||
use script_task::ScriptTaskEventCategory::InputEvent;
|
use script_task::ScriptTaskEventCategory::InputEvent;
|
||||||
use script_task::{CommonScriptMsg, Runnable};
|
use script_task::{CommonScriptMsg, Runnable};
|
||||||
|
use selectors::states::*;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
|
@ -204,6 +206,11 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
|
||||||
|
|
||||||
self.force_relayout();
|
self.force_relayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-lfe-labels
|
||||||
|
fn Labels(&self) -> Root<NodeList> {
|
||||||
|
self.upcast::<HTMLElement>().labels()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -246,8 +253,8 @@ impl VirtualMethods for HTMLTextAreaElement {
|
||||||
|
|
||||||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
|
||||||
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
self.super_type().unwrap().attribute_mutated(attr, mutation);
|
||||||
match attr.local_name() {
|
match *attr.local_name() {
|
||||||
&atom!(disabled) => {
|
atom!(disabled) => {
|
||||||
let el = self.upcast::<Element>();
|
let el = self.upcast::<Element>();
|
||||||
match mutation {
|
match mutation {
|
||||||
AttributeMutation::Set(_) => {
|
AttributeMutation::Set(_) => {
|
||||||
|
@ -261,13 +268,13 @@ impl VirtualMethods for HTMLTextAreaElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&atom!(cols) => {
|
atom!(cols) => {
|
||||||
let cols = mutation.new_value(attr).map(|value| {
|
let cols = mutation.new_value(attr).map(|value| {
|
||||||
value.as_uint()
|
value.as_uint()
|
||||||
});
|
});
|
||||||
self.cols.set(cols.unwrap_or(DEFAULT_COLS));
|
self.cols.set(cols.unwrap_or(DEFAULT_COLS));
|
||||||
},
|
},
|
||||||
&atom!(rows) => {
|
atom!(rows) => {
|
||||||
let rows = mutation.new_value(attr).map(|value| {
|
let rows = mutation.new_value(attr).map(|value| {
|
||||||
value.as_uint()
|
value.as_uint()
|
||||||
});
|
});
|
||||||
|
@ -286,9 +293,9 @@ impl VirtualMethods for HTMLTextAreaElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
|
fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
|
||||||
match name {
|
match *name {
|
||||||
&atom!("cols") => AttrValue::from_limited_u32(value, DEFAULT_COLS),
|
atom!("cols") => AttrValue::from_limited_u32(value, DEFAULT_COLS),
|
||||||
&atom!("rows") => AttrValue::from_limited_u32(value, DEFAULT_ROWS),
|
atom!("rows") => AttrValue::from_limited_u32(value, DEFAULT_ROWS),
|
||||||
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
|
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,11 +329,11 @@ impl VirtualMethods for HTMLTextAreaElement {
|
||||||
s.handle_event(event);
|
s.handle_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
if &*event.Type() == "click" && !event.DefaultPrevented() {
|
if event.type_() == atom!("click") && !event.DefaultPrevented() {
|
||||||
//TODO: set the editing position for text inputs
|
//TODO: set the editing position for text inputs
|
||||||
|
|
||||||
document_from_node(self).request_focus(self.upcast());
|
document_from_node(self).request_focus(self.upcast());
|
||||||
} else if &*event.Type() == "keydown" && !event.DefaultPrevented() {
|
} else if event.type_() == atom!("keydown") && !event.DefaultPrevented() {
|
||||||
if let Some(kevent) = event.downcast::<KeyboardEvent>() {
|
if let Some(kevent) = event.downcast::<KeyboardEvent>() {
|
||||||
match self.textinput.borrow_mut().handle_keydown(kevent) {
|
match self.textinput.borrow_mut().handle_keydown(kevent) {
|
||||||
KeyReaction::TriggerDefaultAction => (),
|
KeyReaction::TriggerDefaultAction => (),
|
||||||
|
|
|
@ -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 http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::KeyboardEventBinding;
|
use dom::bindings::codegen::Bindings::KeyboardEventBinding;
|
||||||
use dom::bindings::codegen::Bindings::KeyboardEventBinding::{KeyboardEventConstants, KeyboardEventMethods};
|
use dom::bindings::codegen::Bindings::KeyboardEventBinding::{KeyboardEventConstants, KeyboardEventMethods};
|
||||||
use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
|
use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
|
||||||
|
@ -17,7 +18,7 @@ use msg::constellation_msg;
|
||||||
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
|
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
|
||||||
use msg::constellation_msg::{Key, KeyModifiers};
|
use msg::constellation_msg::{Key, KeyModifiers};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::Cell;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
|
||||||
no_jsmanaged_fields!(Key);
|
no_jsmanaged_fields!(Key);
|
||||||
|
@ -26,8 +27,8 @@ no_jsmanaged_fields!(Key);
|
||||||
pub struct KeyboardEvent {
|
pub struct KeyboardEvent {
|
||||||
uievent: UIEvent,
|
uievent: UIEvent,
|
||||||
key: Cell<Option<Key>>,
|
key: Cell<Option<Key>>,
|
||||||
key_string: RefCell<DOMString>,
|
key_string: DOMRefCell<DOMString>,
|
||||||
code: RefCell<DOMString>,
|
code: DOMRefCell<DOMString>,
|
||||||
location: Cell<u32>,
|
location: Cell<u32>,
|
||||||
ctrl: Cell<bool>,
|
ctrl: Cell<bool>,
|
||||||
alt: Cell<bool>,
|
alt: Cell<bool>,
|
||||||
|
@ -44,8 +45,8 @@ impl KeyboardEvent {
|
||||||
KeyboardEvent {
|
KeyboardEvent {
|
||||||
uievent: UIEvent::new_inherited(),
|
uievent: UIEvent::new_inherited(),
|
||||||
key: Cell::new(None),
|
key: Cell::new(None),
|
||||||
key_string: RefCell::new("".to_owned()),
|
key_string: DOMRefCell::new("".to_owned()),
|
||||||
code: RefCell::new("".to_owned()),
|
code: DOMRefCell::new("".to_owned()),
|
||||||
location: Cell::new(0),
|
location: Cell::new(0),
|
||||||
ctrl: Cell::new(false),
|
ctrl: Cell::new(false),
|
||||||
alt: Cell::new(false),
|
alt: Cell::new(false),
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl NamedNodeMapMethods for NamedNodeMap {
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-namednodemap-item
|
// https://dom.spec.whatwg.org/#dom-namednodemap-item
|
||||||
fn Item(&self, index: u32) -> Option<Root<Attr>> {
|
fn Item(&self, index: u32) -> Option<Root<Attr>> {
|
||||||
self.owner.attrs().get(index as usize).map(JS::root)
|
self.owner.attrs().get(index as usize).map(|js| Root::from_ref(&**js))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-namednodemap-getnameditem
|
// https://dom.spec.whatwg.org/#dom-namednodemap-getnameditem
|
||||||
|
@ -86,8 +86,10 @@ impl NamedNodeMapMethods for NamedNodeMap {
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://heycam.github.io/webidl/#dfn-supported-property-names
|
||||||
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
|
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
|
||||||
// FIXME: unimplemented (https://github.com/servo/servo/issues/7273)
|
self.owner.attrs().iter().map(|attr| {
|
||||||
vec![]
|
(**attr.name()).to_owned()
|
||||||
|
}).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -886,8 +886,8 @@ fn first_node_not_in<I>(mut nodes: I, not_in: &[NodeOrString]) -> Option<Root<No
|
||||||
{
|
{
|
||||||
nodes.find(|node| {
|
nodes.find(|node| {
|
||||||
not_in.iter().all(|n| {
|
not_in.iter().all(|n| {
|
||||||
match n {
|
match *n {
|
||||||
&NodeOrString::eNode(ref n) => n != node,
|
NodeOrString::eNode(ref n) => n != node,
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1649,7 +1649,7 @@ impl Node {
|
||||||
let node_elem = node.downcast::<Element>().unwrap();
|
let node_elem = node.downcast::<Element>().unwrap();
|
||||||
let copy_elem = copy.downcast::<Element>().unwrap();
|
let copy_elem = copy.downcast::<Element>().unwrap();
|
||||||
|
|
||||||
for attr in node_elem.attrs().iter().map(JS::root) {
|
for attr in node_elem.attrs().iter() {
|
||||||
copy_elem.push_new_attribute(attr.local_name().clone(),
|
copy_elem.push_new_attribute(attr.local_name().clone(),
|
||||||
attr.value().clone(),
|
attr.value().clone(),
|
||||||
attr.name().clone(),
|
attr.name().clone(),
|
||||||
|
@ -1720,12 +1720,10 @@ impl Node {
|
||||||
let prefix_atom = prefix.as_ref().map(|s| Atom::from_slice(s));
|
let prefix_atom = prefix.as_ref().map(|s| Atom::from_slice(s));
|
||||||
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
let namespace_attr =
|
let attrs = element.attrs();
|
||||||
element.attrs()
|
let namespace_attr = attrs.iter().find(|attr| {
|
||||||
.iter()
|
attr_defines_namespace(attr, &prefix_atom)
|
||||||
.map(|attr| attr.root())
|
});
|
||||||
.find(|attr| attr_defines_namespace(attr.r(),
|
|
||||||
&prefix_atom));
|
|
||||||
|
|
||||||
// Steps 2.1-2.
|
// Steps 2.1-2.
|
||||||
if let Some(attr) = namespace_attr {
|
if let Some(attr) = namespace_attr {
|
||||||
|
@ -2155,12 +2153,10 @@ impl NodeMethods for Node {
|
||||||
// FIXME(https://github.com/rust-lang/rust/issues/23338)
|
// FIXME(https://github.com/rust-lang/rust/issues/23338)
|
||||||
let attrs = element.attrs();
|
let attrs = element.attrs();
|
||||||
attrs.iter().all(|attr| {
|
attrs.iter().all(|attr| {
|
||||||
let attr = attr.root();
|
|
||||||
other_element.attrs().iter().any(|other_attr| {
|
other_element.attrs().iter().any(|other_attr| {
|
||||||
let other_attr = other_attr.root();
|
(*attr.namespace() == *other_attr.namespace()) &&
|
||||||
(*attr.r().namespace() == *other_attr.r().namespace()) &&
|
(attr.local_name() == other_attr.local_name()) &&
|
||||||
(attr.r().local_name() == other_attr.r().local_name()) &&
|
(**attr.value() == **other_attr.value())
|
||||||
(**attr.r().value() == **other_attr.r().value())
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ impl NodeIterator {
|
||||||
impl NodeIteratorMethods for NodeIterator {
|
impl NodeIteratorMethods for NodeIterator {
|
||||||
// https://dom.spec.whatwg.org/#dom-nodeiterator-root
|
// https://dom.spec.whatwg.org/#dom-nodeiterator-root
|
||||||
fn Root(&self) -> Root<Node> {
|
fn Root(&self) -> Root<Node> {
|
||||||
self.root_node.root()
|
Root::from_ref(&*self.root_node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-nodeiterator-whattoshow
|
// https://dom.spec.whatwg.org/#dom-nodeiterator-whattoshow
|
||||||
|
|
|
@ -51,6 +51,10 @@ impl NodeList {
|
||||||
pub fn new_child_list(window: &Window, node: &Node) -> Root<NodeList> {
|
pub fn new_child_list(window: &Window, node: &Node) -> Root<NodeList> {
|
||||||
NodeList::new(window, NodeListType::Children(ChildrenList::new(node)))
|
NodeList::new(window, NodeListType::Children(ChildrenList::new(node)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn empty(window: &Window) -> Root<NodeList> {
|
||||||
|
NodeList::new(window, NodeListType::Simple(vec![]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeListMethods for NodeList {
|
impl NodeListMethods for NodeList {
|
||||||
|
@ -66,7 +70,7 @@ impl NodeListMethods for NodeList {
|
||||||
fn Item(&self, index: u32) -> Option<Root<Node>> {
|
fn Item(&self, index: u32) -> Option<Root<Node>> {
|
||||||
match self.list_type {
|
match self.list_type {
|
||||||
NodeListType::Simple(ref elems) => {
|
NodeListType::Simple(ref elems) => {
|
||||||
elems.get(index as usize).map(|node| node.root())
|
elems.get(index as usize).map(|node| Root::from_ref(&**node))
|
||||||
},
|
},
|
||||||
NodeListType::Children(ref list) => list.item(index),
|
NodeListType::Children(ref list) => list.item(index),
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ impl Performance {
|
||||||
impl PerformanceMethods for Performance {
|
impl PerformanceMethods for Performance {
|
||||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#performance-timing-attribute
|
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#performance-timing-attribute
|
||||||
fn Timing(&self) -> Root<PerformanceTiming> {
|
fn Timing(&self) -> Root<PerformanceTiming> {
|
||||||
self.timing.root()
|
Root::from_ref(&*self.timing)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#dom-performance-now
|
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#dom-performance-now
|
||||||
|
|
|
@ -809,7 +809,7 @@ fn bp_position(a_node: &Node, a_offset: u32,
|
||||||
} else if position & NodeConstants::DOCUMENT_POSITION_CONTAINS != 0 {
|
} else if position & NodeConstants::DOCUMENT_POSITION_CONTAINS != 0 {
|
||||||
// Step 3-1, 3-2.
|
// Step 3-1, 3-2.
|
||||||
let mut b_ancestors = b_node.inclusive_ancestors();
|
let mut b_ancestors = b_node.inclusive_ancestors();
|
||||||
let ref child = b_ancestors.find(|child| {
|
let child = b_ancestors.find(|child| {
|
||||||
child.r().GetParentNode().unwrap().r() == a_node
|
child.r().GetParentNode().unwrap().r() == a_node
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
// Step 3-3.
|
// Step 3-3.
|
||||||
|
|
|
@ -45,7 +45,7 @@ impl Sink {
|
||||||
#[allow(unrooted_must_root)] // method is only run at parse time
|
#[allow(unrooted_must_root)] // method is only run at parse time
|
||||||
pub fn get_or_create(&self, child: NodeOrText<JS<Node>>) -> Root<Node> {
|
pub fn get_or_create(&self, child: NodeOrText<JS<Node>>) -> Root<Node> {
|
||||||
match child {
|
match child {
|
||||||
NodeOrText::AppendNode(n) => n.root(),
|
NodeOrText::AppendNode(n) => Root::from_ref(&*n),
|
||||||
NodeOrText::AppendText(t) => {
|
NodeOrText::AppendText(t) => {
|
||||||
let text = Text::new(t.into(), &self.document);
|
let text = Text::new(t.into(), &self.document);
|
||||||
Root::upcast(text)
|
Root::upcast(text)
|
||||||
|
@ -68,8 +68,8 @@ pub type Tokenizer = tokenizer::Tokenizer<TreeBuilder<JS<Node>, Sink>>;
|
||||||
pub struct ParserContext {
|
pub struct ParserContext {
|
||||||
/// The parser that initiated the request.
|
/// The parser that initiated the request.
|
||||||
parser: Option<Trusted<ServoHTMLParser>>,
|
parser: Option<Trusted<ServoHTMLParser>>,
|
||||||
/// Is this document a synthesized document for a single image?
|
/// Is this a synthesized document
|
||||||
is_image_document: bool,
|
is_synthesized_document: bool,
|
||||||
/// The pipeline associated with this document.
|
/// The pipeline associated with this document.
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
/// The subpage associated with this document.
|
/// The subpage associated with this document.
|
||||||
|
@ -85,7 +85,7 @@ impl ParserContext {
|
||||||
url: Url) -> ParserContext {
|
url: Url) -> ParserContext {
|
||||||
ParserContext {
|
ParserContext {
|
||||||
parser: None,
|
parser: None,
|
||||||
is_image_document: false,
|
is_synthesized_document: false,
|
||||||
id: id,
|
id: id,
|
||||||
subpage: subpage,
|
subpage: subpage,
|
||||||
script_chan: script_chan,
|
script_chan: script_chan,
|
||||||
|
@ -111,12 +111,12 @@ impl AsyncResponseListener for ParserContext {
|
||||||
|
|
||||||
match content_type {
|
match content_type {
|
||||||
Some(ContentType(Mime(TopLevel::Image, _, _))) => {
|
Some(ContentType(Mime(TopLevel::Image, _, _))) => {
|
||||||
self.is_image_document = true;
|
self.is_synthesized_document = true;
|
||||||
let page = format!("<html><body><img src='{}' /></body></html>",
|
let page = format!("<html><body><img src='{}' /></body></html>",
|
||||||
self.url.serialize());
|
self.url.serialize());
|
||||||
parser.pending_input.borrow_mut().push(page);
|
parser.pending_input.borrow_mut().push(page);
|
||||||
parser.parse_sync();
|
parser.parse_sync();
|
||||||
}
|
},
|
||||||
Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) => {
|
Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) => {
|
||||||
// FIXME: When servo/html5ever#109 is fixed remove <plaintext> usage and
|
// FIXME: When servo/html5ever#109 is fixed remove <plaintext> usage and
|
||||||
// replace with fix from that issue.
|
// replace with fix from that issue.
|
||||||
|
@ -130,12 +130,29 @@ impl AsyncResponseListener for ParserContext {
|
||||||
parser.pending_input.borrow_mut().push(page);
|
parser.pending_input.borrow_mut().push(page);
|
||||||
parser.parse_sync();
|
parser.parse_sync();
|
||||||
},
|
},
|
||||||
_ => {}
|
Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, _))) => {}, // Handle text/html
|
||||||
|
Some(ContentType(Mime(toplevel, sublevel, _))) => {
|
||||||
|
if toplevel.as_str() == "application" && sublevel.as_str() == "xhtml+xml" {
|
||||||
|
// Handle xhtml (application/xhtml+xml).
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show warning page for unknown mime types.
|
||||||
|
let page = format!("<html><body><p>Unknown content type ({}/{}).</p></body></html>",
|
||||||
|
toplevel.as_str(), sublevel.as_str());
|
||||||
|
self.is_synthesized_document = true;
|
||||||
|
parser.pending_input.borrow_mut().push(page);
|
||||||
|
parser.parse_sync();
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
// No content-type header.
|
||||||
|
// Merge with #4212 when fixed.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_available(&mut self, payload: Vec<u8>) {
|
fn data_available(&mut self, payload: Vec<u8>) {
|
||||||
if !self.is_image_document {
|
if !self.is_synthesized_document {
|
||||||
// FIXME: use Vec<u8> (html5ever #34)
|
// FIXME: use Vec<u8> (html5ever #34)
|
||||||
let data = UTF_8.decode(&payload, DecoderTrap::Replace).unwrap();
|
let data = UTF_8.decode(&payload, DecoderTrap::Replace).unwrap();
|
||||||
let parser = match self.parser.as_ref() {
|
let parser = match self.parser.as_ref() {
|
||||||
|
|
|
@ -12,6 +12,8 @@ use dom::bindings::codegen::Bindings::TestBindingBinding::TestEnum::_empty;
|
||||||
use dom::bindings::codegen::UnionTypes::BlobOrString;
|
use dom::bindings::codegen::UnionTypes::BlobOrString;
|
||||||
use dom::bindings::codegen::UnionTypes::EventOrString;
|
use dom::bindings::codegen::UnionTypes::EventOrString;
|
||||||
use dom::bindings::codegen::UnionTypes::EventOrString::eString;
|
use dom::bindings::codegen::UnionTypes::EventOrString::eString;
|
||||||
|
use dom::bindings::codegen::UnionTypes::EventOrUSVString;
|
||||||
|
use dom::bindings::codegen::UnionTypes::EventOrUSVString::eUSVString;
|
||||||
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong;
|
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong;
|
||||||
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong::eLong;
|
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong::eLong;
|
||||||
use dom::bindings::global::{GlobalField, GlobalRef};
|
use dom::bindings::global::{GlobalField, GlobalRef};
|
||||||
|
@ -77,6 +79,8 @@ impl TestBindingMethods for TestBinding {
|
||||||
fn SetUnionAttribute(&self, _: HTMLElementOrLong) {}
|
fn SetUnionAttribute(&self, _: HTMLElementOrLong) {}
|
||||||
fn Union2Attribute(&self) -> EventOrString { eString("".to_owned()) }
|
fn Union2Attribute(&self) -> EventOrString { eString("".to_owned()) }
|
||||||
fn SetUnion2Attribute(&self, _: EventOrString) {}
|
fn SetUnion2Attribute(&self, _: EventOrString) {}
|
||||||
|
fn Union3Attribute(&self) -> EventOrUSVString { eUSVString(USVString("".to_owned())) }
|
||||||
|
fn SetUnion3Attribute(&self, _: EventOrUSVString) {}
|
||||||
fn ArrayAttribute(&self, _: *mut JSContext) -> *mut JSObject { NullValue().to_object_or_null() }
|
fn ArrayAttribute(&self, _: *mut JSContext) -> *mut JSObject { NullValue().to_object_or_null() }
|
||||||
fn AnyAttribute(&self, _: *mut JSContext) -> JSVal { NullValue() }
|
fn AnyAttribute(&self, _: *mut JSContext) -> JSVal { NullValue() }
|
||||||
fn SetAnyAttribute(&self, _: *mut JSContext, _: HandleValue) {}
|
fn SetAnyAttribute(&self, _: *mut JSContext, _: HandleValue) {}
|
||||||
|
|
|
@ -22,22 +22,20 @@ use util::str::DOMString;
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct TextEncoder {
|
pub struct TextEncoder {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
encoding: DOMString,
|
|
||||||
#[ignore_heap_size_of = "Defined in rust-encoding"]
|
#[ignore_heap_size_of = "Defined in rust-encoding"]
|
||||||
encoder: EncodingRef,
|
encoder: EncodingRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextEncoder {
|
impl TextEncoder {
|
||||||
fn new_inherited(encoding: DOMString, encoder: EncodingRef) -> TextEncoder {
|
fn new_inherited(encoder: EncodingRef) -> TextEncoder {
|
||||||
TextEncoder {
|
TextEncoder {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
encoding: encoding,
|
|
||||||
encoder: encoder,
|
encoder: encoder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(global: GlobalRef, encoding: DOMString, encoder: EncodingRef) -> Root<TextEncoder> {
|
pub fn new(global: GlobalRef, encoder: EncodingRef) -> Root<TextEncoder> {
|
||||||
reflect_dom_object(box TextEncoder::new_inherited(encoding, encoder),
|
reflect_dom_object(box TextEncoder::new_inherited(encoder),
|
||||||
global,
|
global,
|
||||||
TextEncoderBinding::Wrap)
|
TextEncoderBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
@ -55,7 +53,7 @@ impl TextEncoder {
|
||||||
|
|
||||||
match encoding.name() {
|
match encoding.name() {
|
||||||
"utf-8" | "utf-16be" | "utf-16le" => {
|
"utf-8" | "utf-16be" | "utf-16le" => {
|
||||||
Ok(TextEncoder::new(global, encoding.name().to_owned(), encoding))
|
Ok(TextEncoder::new(global, encoding))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
debug!("Encoding Not UTF");
|
debug!("Encoding Not UTF");
|
||||||
|
@ -68,7 +66,7 @@ impl TextEncoder {
|
||||||
impl TextEncoderMethods for TextEncoder {
|
impl TextEncoderMethods for TextEncoder {
|
||||||
// https://encoding.spec.whatwg.org/#dom-textencoder-encoding
|
// https://encoding.spec.whatwg.org/#dom-textencoder-encoding
|
||||||
fn Encoding(&self) -> DOMString {
|
fn Encoding(&self) -> DOMString {
|
||||||
self.encoding.clone()
|
self.encoder.name().to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
|
|
@ -38,7 +38,7 @@ impl TouchListMethods for TouchList {
|
||||||
|
|
||||||
/// https://w3c.github.io/touch-events/#widl-TouchList-item-getter-Touch-unsigned-long-index
|
/// https://w3c.github.io/touch-events/#widl-TouchList-item-getter-Touch-unsigned-long-index
|
||||||
fn Item(&self, index: u32) -> Option<Root<Touch>> {
|
fn Item(&self, index: u32) -> Option<Root<Touch>> {
|
||||||
self.touches.get(index as usize).map(JS::root)
|
self.touches.get(index as usize).map(|js| Root::from_ref(&**js))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://w3c.github.io/touch-events/#widl-TouchList-item-getter-Touch-unsigned-long-index
|
/// https://w3c.github.io/touch-events/#widl-TouchList-item-getter-Touch-unsigned-long-index
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl TreeWalker {
|
||||||
impl TreeWalkerMethods for TreeWalker {
|
impl TreeWalkerMethods for TreeWalker {
|
||||||
// https://dom.spec.whatwg.org/#dom-treewalker-root
|
// https://dom.spec.whatwg.org/#dom-treewalker-root
|
||||||
fn Root(&self) -> Root<Node> {
|
fn Root(&self) -> Root<Node> {
|
||||||
self.root_node.root()
|
Root::from_ref(&*self.root_node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-treewalker-whattoshow
|
// https://dom.spec.whatwg.org/#dom-treewalker-whattoshow
|
||||||
|
|
|
@ -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 http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::URLBinding::{self, URLMethods};
|
use dom::bindings::codegen::Bindings::URLBinding::{self, URLMethods};
|
||||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||||
use dom::bindings::global::GlobalRef;
|
use dom::bindings::global::GlobalRef;
|
||||||
|
@ -10,7 +11,6 @@ use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||||
use dom::bindings::str::USVString;
|
use dom::bindings::str::USVString;
|
||||||
use dom::urlhelper::UrlHelper;
|
use dom::urlhelper::UrlHelper;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::RefCell;
|
|
||||||
use url::{Host, ParseResult, Url, UrlParser};
|
use url::{Host, ParseResult, Url, UrlParser};
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ pub struct URL {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
|
|
||||||
// https://url.spec.whatwg.org/#concept-urlutils-url
|
// https://url.spec.whatwg.org/#concept-urlutils-url
|
||||||
url: RefCell<Url>,
|
url: DOMRefCell<Url>,
|
||||||
|
|
||||||
// https://url.spec.whatwg.org/#concept-urlutils-get-the-base
|
// https://url.spec.whatwg.org/#concept-urlutils-get-the-base
|
||||||
base: Option<Url>,
|
base: Option<Url>,
|
||||||
|
@ -30,7 +30,7 @@ impl URL {
|
||||||
fn new_inherited(url: Url, base: Option<Url>) -> URL {
|
fn new_inherited(url: Url, base: Option<Url>) -> URL {
|
||||||
URL {
|
URL {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
url: RefCell::new(url),
|
url: DOMRefCell::new(url),
|
||||||
base: base,
|
base: base,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::URLSearchParamsBinding;
|
use dom::bindings::codegen::Bindings::URLSearchParamsBinding;
|
||||||
use dom::bindings::codegen::Bindings::URLSearchParamsBinding::URLSearchParamsMethods;
|
use dom::bindings::codegen::Bindings::URLSearchParamsBinding::URLSearchParamsMethods;
|
||||||
use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams;
|
use dom::bindings::codegen::UnionTypes::USVStringOrURLSearchParams;
|
||||||
use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams::{eString, eURLSearchParams};
|
use dom::bindings::codegen::UnionTypes::USVStringOrURLSearchParams::{eUSVString, eURLSearchParams};
|
||||||
use dom::bindings::error::Fallible;
|
use dom::bindings::error::Fallible;
|
||||||
use dom::bindings::global::GlobalRef;
|
use dom::bindings::global::GlobalRef;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
|
use dom::bindings::str::USVString;
|
||||||
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||||
use encoding::types::EncodingRef;
|
use encoding::types::EncodingRef;
|
||||||
use url::form_urlencoded::{parse, serialize_with_encoding};
|
use url::form_urlencoded::{parse, serialize_with_encoding};
|
||||||
|
@ -20,7 +21,7 @@ use util::str::DOMString;
|
||||||
pub struct URLSearchParams {
|
pub struct URLSearchParams {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
// https://url.spec.whatwg.org/#concept-urlsearchparams-list
|
// https://url.spec.whatwg.org/#concept-urlsearchparams-list
|
||||||
list: DOMRefCell<Vec<(DOMString, DOMString)>>,
|
list: DOMRefCell<Vec<(String, String)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl URLSearchParams {
|
impl URLSearchParams {
|
||||||
|
@ -37,14 +38,14 @@ impl URLSearchParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams
|
// https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams
|
||||||
pub fn Constructor(global: GlobalRef, init: Option<StringOrURLSearchParams>) ->
|
pub fn Constructor(global: GlobalRef, init: Option<USVStringOrURLSearchParams>) ->
|
||||||
Fallible<Root<URLSearchParams>> {
|
Fallible<Root<URLSearchParams>> {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
let query = URLSearchParams::new(global);
|
let query = URLSearchParams::new(global);
|
||||||
match init {
|
match init {
|
||||||
Some(eString(init)) => {
|
Some(eUSVString(init)) => {
|
||||||
// Step 2.
|
// Step 2.
|
||||||
*query.r().list.borrow_mut() = parse(init.as_bytes());
|
*query.r().list.borrow_mut() = parse(init.0.as_bytes());
|
||||||
},
|
},
|
||||||
Some(eURLSearchParams(init)) => {
|
Some(eURLSearchParams(init)) => {
|
||||||
// Step 3.
|
// Step 3.
|
||||||
|
@ -59,27 +60,27 @@ impl URLSearchParams {
|
||||||
|
|
||||||
impl URLSearchParamsMethods for URLSearchParams {
|
impl URLSearchParamsMethods for URLSearchParams {
|
||||||
// https://url.spec.whatwg.org/#dom-urlsearchparams-append
|
// https://url.spec.whatwg.org/#dom-urlsearchparams-append
|
||||||
fn Append(&self, name: DOMString, value: DOMString) {
|
fn Append(&self, name: USVString, value: USVString) {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
self.list.borrow_mut().push((name, value));
|
self.list.borrow_mut().push((name.0, value.0));
|
||||||
// Step 2.
|
// Step 2.
|
||||||
self.update_steps();
|
self.update_steps();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://url.spec.whatwg.org/#dom-urlsearchparams-delete
|
// https://url.spec.whatwg.org/#dom-urlsearchparams-delete
|
||||||
fn Delete(&self, name: DOMString) {
|
fn Delete(&self, name: USVString) {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
self.list.borrow_mut().retain(|&(ref k, _)| k != &name);
|
self.list.borrow_mut().retain(|&(ref k, _)| k != &name.0);
|
||||||
// Step 2.
|
// Step 2.
|
||||||
self.update_steps();
|
self.update_steps();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://url.spec.whatwg.org/#dom-urlsearchparams-get
|
// https://url.spec.whatwg.org/#dom-urlsearchparams-get
|
||||||
fn Get(&self, name: DOMString) -> Option<DOMString> {
|
fn Get(&self, name: USVString) -> Option<USVString> {
|
||||||
let list = self.list.borrow();
|
let list = self.list.borrow();
|
||||||
list.iter().filter_map(|&(ref k, ref v)| {
|
list.iter().filter_map(|&(ref k, ref v)| {
|
||||||
if k == &name {
|
if k == &name.0 {
|
||||||
Some(v.clone())
|
Some(USVString(v.clone()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -87,31 +88,31 @@ impl URLSearchParamsMethods for URLSearchParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://url.spec.whatwg.org/#dom-urlsearchparams-has
|
// https://url.spec.whatwg.org/#dom-urlsearchparams-has
|
||||||
fn Has(&self, name: DOMString) -> bool {
|
fn Has(&self, name: USVString) -> bool {
|
||||||
let list = self.list.borrow();
|
let list = self.list.borrow();
|
||||||
list.iter().find(|&&(ref k, _)| k == &name).is_some()
|
list.iter().any(|&(ref k, _)| k == &name.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://url.spec.whatwg.org/#dom-urlsearchparams-set
|
// https://url.spec.whatwg.org/#dom-urlsearchparams-set
|
||||||
fn Set(&self, name: DOMString, value: DOMString) {
|
fn Set(&self, name: USVString, value: USVString) {
|
||||||
let mut list = self.list.borrow_mut();
|
let mut list = self.list.borrow_mut();
|
||||||
let mut index = None;
|
let mut index = None;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
list.retain(|&(ref k, _)| {
|
list.retain(|&(ref k, _)| {
|
||||||
if index.is_none() {
|
if index.is_none() {
|
||||||
if k == &name {
|
if k == &name.0 {
|
||||||
index = Some(i);
|
index = Some(i);
|
||||||
} else {
|
} else {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
k != &name
|
k != &name.0
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
match index {
|
match index {
|
||||||
Some(index) => list[index].1 = value,
|
Some(index) => list[index].1 = value.0,
|
||||||
None => list.push((name, value)),
|
None => list.push((name.0, value.0)),
|
||||||
};
|
};
|
||||||
self.update_steps();
|
self.update_steps();
|
||||||
}
|
}
|
||||||
|
@ -125,7 +126,7 @@ impl URLSearchParamsMethods for URLSearchParams {
|
||||||
|
|
||||||
impl URLSearchParams {
|
impl URLSearchParams {
|
||||||
// https://url.spec.whatwg.org/#concept-urlencoded-serializer
|
// https://url.spec.whatwg.org/#concept-urlencoded-serializer
|
||||||
pub fn serialize(&self, encoding: Option<EncodingRef>) -> DOMString {
|
pub fn serialize(&self, encoding: Option<EncodingRef>) -> String {
|
||||||
let list = self.list.borrow();
|
let list = self.list.borrow();
|
||||||
serialize_with_encoding(list.iter(), encoding)
|
serialize_with_encoding(list.iter(), encoding)
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,13 @@ impl WebGLBuffer {
|
||||||
pub fn delete(&self) {
|
pub fn delete(&self) {
|
||||||
if !self.is_deleted.get() {
|
if !self.is_deleted.get() {
|
||||||
self.is_deleted.set(true);
|
self.is_deleted.set(true);
|
||||||
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteBuffer(self.id))).unwrap();
|
let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteBuffer(self.id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for WebGLBuffer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -60,7 +60,13 @@ impl WebGLFramebuffer {
|
||||||
pub fn delete(&self) {
|
pub fn delete(&self) {
|
||||||
if !self.is_deleted.get() {
|
if !self.is_deleted.get() {
|
||||||
self.is_deleted.set(true);
|
self.is_deleted.set(true);
|
||||||
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteFramebuffer(self.id))).unwrap();
|
let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteFramebuffer(self.id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for WebGLFramebuffer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ impl WebGLProgram {
|
||||||
pub fn delete(&self) {
|
pub fn delete(&self) {
|
||||||
if !self.is_deleted.get() {
|
if !self.is_deleted.get() {
|
||||||
self.is_deleted.set(true);
|
self.is_deleted.set(true);
|
||||||
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteProgram(self.id))).unwrap();
|
let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteProgram(self.id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,3 +125,9 @@ impl WebGLProgram {
|
||||||
Ok(receiver.recv().unwrap())
|
Ok(receiver.recv().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for WebGLProgram {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ impl WebGLRenderbuffer {
|
||||||
pub fn delete(&self) {
|
pub fn delete(&self) {
|
||||||
if !self.is_deleted.get() {
|
if !self.is_deleted.get() {
|
||||||
self.is_deleted.set(true);
|
self.is_deleted.set(true);
|
||||||
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteRenderbuffer(self.id))).unwrap();
|
let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteRenderbuffer(self.id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl WebGLRenderingContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_as_dirty(&self) {
|
fn mark_as_dirty(&self) {
|
||||||
self.canvas.root().upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
self.canvas.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ impl Drop for WebGLRenderingContext {
|
||||||
impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1
|
||||||
fn Canvas(&self) -> Root<HTMLCanvasElement> {
|
fn Canvas(&self) -> Root<HTMLCanvasElement> {
|
||||||
self.canvas.root()
|
Root::from_ref(&*self.canvas)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1
|
||||||
|
@ -849,8 +849,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let canvas = self.canvas.root();
|
let window = window_from_node(&*self.canvas);
|
||||||
let window = window_from_node(canvas.r());
|
|
||||||
|
|
||||||
let img = match canvas_utils::request_image_from_cache(window.r(), img_url) {
|
let img = match canvas_utils::request_image_from_cache(window.r(), img_url) {
|
||||||
ImageResponse::Loaded(img) => img,
|
ImageResponse::Loaded(img) => img,
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
|
||||||
use angle::hl::{BuiltInResources, Output, ShaderValidator};
|
use angle::hl::{BuiltInResources, Output, ShaderValidator};
|
||||||
use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLError, WebGLResult, WebGLShaderParameter};
|
use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLError, WebGLResult, WebGLShaderParameter};
|
||||||
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||||
use dom::bindings::codegen::Bindings::WebGLShaderBinding;
|
use dom::bindings::codegen::Bindings::WebGLShaderBinding;
|
||||||
use dom::bindings::global::GlobalRef;
|
use dom::bindings::global::GlobalRef;
|
||||||
|
@ -12,7 +13,7 @@ use dom::bindings::js::Root;
|
||||||
use dom::bindings::reflector::reflect_dom_object;
|
use dom::bindings::reflector::reflect_dom_object;
|
||||||
use dom::webglobject::WebGLObject;
|
use dom::webglobject::WebGLObject;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::Cell;
|
||||||
use std::sync::{ONCE_INIT, Once};
|
use std::sync::{ONCE_INIT, Once};
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Debug, JSTraceable, HeapSizeOf)]
|
#[derive(Clone, Copy, PartialEq, Debug, JSTraceable, HeapSizeOf)]
|
||||||
|
@ -27,8 +28,8 @@ pub struct WebGLShader {
|
||||||
webgl_object: WebGLObject,
|
webgl_object: WebGLObject,
|
||||||
id: u32,
|
id: u32,
|
||||||
gl_type: u32,
|
gl_type: u32,
|
||||||
source: RefCell<Option<String>>,
|
source: DOMRefCell<Option<String>>,
|
||||||
info_log: RefCell<Option<String>>,
|
info_log: DOMRefCell<Option<String>>,
|
||||||
is_deleted: Cell<bool>,
|
is_deleted: Cell<bool>,
|
||||||
compilation_status: Cell<ShaderCompilationStatus>,
|
compilation_status: Cell<ShaderCompilationStatus>,
|
||||||
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
||||||
|
@ -50,8 +51,8 @@ impl WebGLShader {
|
||||||
webgl_object: WebGLObject::new_inherited(),
|
webgl_object: WebGLObject::new_inherited(),
|
||||||
id: id,
|
id: id,
|
||||||
gl_type: shader_type,
|
gl_type: shader_type,
|
||||||
source: RefCell::new(None),
|
source: DOMRefCell::new(None),
|
||||||
info_log: RefCell::new(None),
|
info_log: DOMRefCell::new(None),
|
||||||
is_deleted: Cell::new(false),
|
is_deleted: Cell::new(false),
|
||||||
compilation_status: Cell::new(ShaderCompilationStatus::NotCompiled),
|
compilation_status: Cell::new(ShaderCompilationStatus::NotCompiled),
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
|
@ -121,7 +122,7 @@ impl WebGLShader {
|
||||||
pub fn delete(&self) {
|
pub fn delete(&self) {
|
||||||
if !self.is_deleted.get() {
|
if !self.is_deleted.get() {
|
||||||
self.is_deleted.set(true);
|
self.is_deleted.set(true);
|
||||||
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteShader(self.id))).unwrap()
|
let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteShader(self.id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,3 +153,9 @@ impl WebGLShader {
|
||||||
*self.source.borrow_mut() = Some(source);
|
*self.source.borrow_mut() = Some(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for WebGLShader {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ impl WebGLTexture {
|
||||||
pub fn delete(&self) {
|
pub fn delete(&self) {
|
||||||
if !self.is_deleted.get() {
|
if !self.is_deleted.get() {
|
||||||
self.is_deleted.set(true);
|
self.is_deleted.set(true);
|
||||||
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteTexture(self.id))).unwrap();
|
let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteTexture(self.id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,3 +145,9 @@ impl WebGLTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for WebGLTexture {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,5 +25,5 @@ interface HTMLButtonElement : HTMLElement {
|
||||||
//boolean reportValidity();
|
//boolean reportValidity();
|
||||||
//void setCustomValidity(DOMString error);
|
//void setCustomValidity(DOMString error);
|
||||||
|
|
||||||
//readonly attribute NodeList labels;
|
readonly attribute NodeList labels;
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,7 +57,7 @@ interface HTMLInputElement : HTMLElement {
|
||||||
//boolean reportValidity();
|
//boolean reportValidity();
|
||||||
//void setCustomValidity(DOMString error);
|
//void setCustomValidity(DOMString error);
|
||||||
|
|
||||||
//readonly attribute NodeList labels;
|
readonly attribute NodeList labels;
|
||||||
|
|
||||||
//void select();
|
//void select();
|
||||||
// attribute unsigned long selectionStart;
|
// attribute unsigned long selectionStart;
|
||||||
|
|
|
@ -11,5 +11,5 @@ interface HTMLMeterElement : HTMLElement {
|
||||||
// attribute double low;
|
// attribute double low;
|
||||||
// attribute double high;
|
// attribute double high;
|
||||||
// attribute double optimum;
|
// attribute double optimum;
|
||||||
//readonly attribute NodeList labels;
|
readonly attribute NodeList labels;
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,5 +20,5 @@ interface HTMLOutputElement : HTMLElement {
|
||||||
//boolean reportValidity();
|
//boolean reportValidity();
|
||||||
//void setCustomValidity(DOMString error);
|
//void setCustomValidity(DOMString error);
|
||||||
|
|
||||||
//readonly attribute NodeList labels;
|
readonly attribute NodeList labels;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,5 +8,5 @@ interface HTMLProgressElement : HTMLElement {
|
||||||
// attribute double value;
|
// attribute double value;
|
||||||
// attribute double max;
|
// attribute double max;
|
||||||
//readonly attribute double position;
|
//readonly attribute double position;
|
||||||
//readonly attribute NodeList labels;
|
readonly attribute NodeList labels;
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,5 +36,5 @@ interface HTMLSelectElement : HTMLElement {
|
||||||
//boolean reportValidity();
|
//boolean reportValidity();
|
||||||
//void setCustomValidity(DOMString error);
|
//void setCustomValidity(DOMString error);
|
||||||
|
|
||||||
//readonly attribute NodeList labels;
|
readonly attribute NodeList labels;
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,7 @@ interface HTMLTextAreaElement : HTMLElement {
|
||||||
//boolean reportValidity();
|
//boolean reportValidity();
|
||||||
//void setCustomValidity(DOMString error);
|
//void setCustomValidity(DOMString error);
|
||||||
|
|
||||||
//readonly attribute NodeList labels;
|
readonly attribute NodeList labels;
|
||||||
|
|
||||||
//void select();
|
//void select();
|
||||||
// attribute unsigned long selectionStart;
|
// attribute unsigned long selectionStart;
|
||||||
|
|
|
@ -89,6 +89,7 @@ interface TestBinding {
|
||||||
attribute Blob interfaceAttribute;
|
attribute Blob interfaceAttribute;
|
||||||
attribute (HTMLElement or long) unionAttribute;
|
attribute (HTMLElement or long) unionAttribute;
|
||||||
attribute (Event or DOMString) union2Attribute;
|
attribute (Event or DOMString) union2Attribute;
|
||||||
|
attribute (Event or USVString) union3Attribute;
|
||||||
readonly attribute Uint8ClampedArray arrayAttribute;
|
readonly attribute Uint8ClampedArray arrayAttribute;
|
||||||
attribute any anyAttribute;
|
attribute any anyAttribute;
|
||||||
attribute object objectAttribute;
|
attribute object objectAttribute;
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
* https://url.spec.whatwg.org/#interface-urlsearchparams
|
* https://url.spec.whatwg.org/#interface-urlsearchparams
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Constructor(optional (DOMString or URLSearchParams) init/* = ""*/)]
|
[Constructor(optional (USVString or URLSearchParams) init/* = ""*/)]
|
||||||
interface URLSearchParams {
|
interface URLSearchParams {
|
||||||
void append(DOMString name, DOMString value);
|
void append(USVString name, USVString value);
|
||||||
void delete(DOMString name);
|
void delete(USVString name);
|
||||||
DOMString? get(DOMString name);
|
USVString? get(USVString name);
|
||||||
// sequence<DOMString> getAll(DOMString name);
|
// sequence<USVString> getAll(USVString name);
|
||||||
boolean has(DOMString name);
|
boolean has(USVString name);
|
||||||
void set(DOMString name, DOMString value);
|
void set(USVString name, USVString value);
|
||||||
// iterable<USVString, USVString>;
|
// iterable<USVString, USVString>;
|
||||||
stringifier;
|
stringifier;
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,7 +29,7 @@ use net_traits::hosts::replace_hosts;
|
||||||
use script_task::ScriptTaskEventCategory::WebSocketEvent;
|
use script_task::ScriptTaskEventCategory::WebSocketEvent;
|
||||||
use script_task::{CommonScriptMsg, Runnable};
|
use script_task::{CommonScriptMsg, Runnable};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::Cell;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::{ptr, slice};
|
use std::{ptr, slice};
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
@ -134,7 +134,7 @@ pub struct WebSocket {
|
||||||
buffered_amount: Cell<u32>,
|
buffered_amount: Cell<u32>,
|
||||||
clearing_buffer: Cell<bool>, //Flag to tell if there is a running task to clear buffered_amount
|
clearing_buffer: Cell<bool>, //Flag to tell if there is a running task to clear buffered_amount
|
||||||
#[ignore_heap_size_of = "Defined in std"]
|
#[ignore_heap_size_of = "Defined in std"]
|
||||||
sender: RefCell<Option<Arc<Mutex<Sender<WebSocketStream>>>>>,
|
sender: DOMRefCell<Option<Arc<Mutex<Sender<WebSocketStream>>>>>,
|
||||||
failed: Cell<bool>, //Flag to tell if websocket was closed due to failure
|
failed: Cell<bool>, //Flag to tell if websocket was closed due to failure
|
||||||
full: Cell<bool>, //Flag to tell if websocket queue is full
|
full: Cell<bool>, //Flag to tell if websocket queue is full
|
||||||
clean_close: Cell<bool>, //Flag to tell if the websocket closed cleanly (not due to full or fail)
|
clean_close: Cell<bool>, //Flag to tell if the websocket closed cleanly (not due to full or fail)
|
||||||
|
@ -176,7 +176,7 @@ impl WebSocket {
|
||||||
buffered_amount: Cell::new(0),
|
buffered_amount: Cell::new(0),
|
||||||
clearing_buffer: Cell::new(false),
|
clearing_buffer: Cell::new(false),
|
||||||
failed: Cell::new(false),
|
failed: Cell::new(false),
|
||||||
sender: RefCell::new(None),
|
sender: DOMRefCell::new(None),
|
||||||
full: Cell::new(false),
|
full: Cell::new(false),
|
||||||
clean_close: Cell::new(true),
|
clean_close: Cell::new(true),
|
||||||
code: Cell::new(0),
|
code: Cell::new(0),
|
||||||
|
|
|
@ -59,7 +59,7 @@ use script_traits::{ConstellationControlMsg, TimerEventChan, TimerEventId, Timer
|
||||||
use selectors::parser::PseudoElement;
|
use selectors::parser::PseudoElement;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::{Cell, Ref, RefCell};
|
use std::cell::{Cell, Ref};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
@ -145,9 +145,9 @@ pub struct Window {
|
||||||
/// For sending timeline markers. Will be ignored if
|
/// For sending timeline markers. Will be ignored if
|
||||||
/// no devtools server
|
/// no devtools server
|
||||||
#[ignore_heap_size_of = "TODO(#6909) need to measure HashSet"]
|
#[ignore_heap_size_of = "TODO(#6909) need to measure HashSet"]
|
||||||
devtools_markers: RefCell<HashSet<TimelineMarkerType>>,
|
devtools_markers: DOMRefCell<HashSet<TimelineMarkerType>>,
|
||||||
#[ignore_heap_size_of = "channels are hard"]
|
#[ignore_heap_size_of = "channels are hard"]
|
||||||
devtools_marker_sender: RefCell<Option<IpcSender<TimelineMarker>>>,
|
devtools_marker_sender: DOMRefCell<Option<IpcSender<TimelineMarker>>>,
|
||||||
|
|
||||||
/// A flag to indicate whether the developer tools have requested live updates of
|
/// A flag to indicate whether the developer tools have requested live updates of
|
||||||
/// page changes.
|
/// page changes.
|
||||||
|
@ -209,7 +209,7 @@ pub struct Window {
|
||||||
|
|
||||||
/// A channel for communicating results of async scripts back to the webdriver server
|
/// A channel for communicating results of async scripts back to the webdriver server
|
||||||
#[ignore_heap_size_of = "channels are hard"]
|
#[ignore_heap_size_of = "channels are hard"]
|
||||||
webdriver_script_chan: RefCell<Option<IpcSender<WebDriverJSResult>>>,
|
webdriver_script_chan: DOMRefCell<Option<IpcSender<WebDriverJSResult>>>,
|
||||||
|
|
||||||
/// The current state of the window object
|
/// The current state of the window object
|
||||||
current_state: Cell<WindowState>,
|
current_state: Cell<WindowState>,
|
||||||
|
@ -911,7 +911,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send new document and relevant styles to layout.
|
// Send new document and relevant styles to layout.
|
||||||
let reflow = box ScriptReflow {
|
let reflow = ScriptReflow {
|
||||||
reflow_info: Reflow {
|
reflow_info: Reflow {
|
||||||
goal: goal,
|
goal: goal,
|
||||||
page_clip_rect: self.page_clip_rect.get(),
|
page_clip_rect: self.page_clip_rect.get(),
|
||||||
|
@ -1277,10 +1277,10 @@ impl Window {
|
||||||
pending_reflow_count: Cell::new(0),
|
pending_reflow_count: Cell::new(0),
|
||||||
current_state: Cell::new(WindowState::Alive),
|
current_state: Cell::new(WindowState::Alive),
|
||||||
|
|
||||||
devtools_marker_sender: RefCell::new(None),
|
devtools_marker_sender: DOMRefCell::new(None),
|
||||||
devtools_markers: RefCell::new(HashSet::new()),
|
devtools_markers: DOMRefCell::new(HashSet::new()),
|
||||||
devtools_wants_updates: Cell::new(false),
|
devtools_wants_updates: Cell::new(false),
|
||||||
webdriver_script_chan: RefCell::new(None),
|
webdriver_script_chan: DOMRefCell::new(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
WindowBinding::Wrap(runtime.cx(), win)
|
WindowBinding::Wrap(runtime.cx(), win)
|
||||||
|
|
|
@ -164,10 +164,9 @@ impl XMLHttpRequest {
|
||||||
request_headers: DOMRefCell::new(Headers::new()),
|
request_headers: DOMRefCell::new(Headers::new()),
|
||||||
request_body_len: Cell::new(0),
|
request_body_len: Cell::new(0),
|
||||||
sync: Cell::new(false),
|
sync: Cell::new(false),
|
||||||
send_flag: Cell::new(false),
|
|
||||||
|
|
||||||
upload_complete: Cell::new(false),
|
upload_complete: Cell::new(false),
|
||||||
upload_events: Cell::new(false),
|
upload_events: Cell::new(false),
|
||||||
|
send_flag: Cell::new(false),
|
||||||
|
|
||||||
global: GlobalField::from_rooted(&global),
|
global: GlobalField::from_rooted(&global),
|
||||||
timeout_cancel: DOMRefCell::new(None),
|
timeout_cancel: DOMRefCell::new(None),
|
||||||
|
@ -467,7 +466,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
||||||
|
|
||||||
// https://xhr.spec.whatwg.org/#the-upload-attribute
|
// https://xhr.spec.whatwg.org/#the-upload-attribute
|
||||||
fn Upload(&self) -> Root<XMLHttpRequestUpload> {
|
fn Upload(&self) -> Root<XMLHttpRequestUpload> {
|
||||||
self.upload.root()
|
Root::from_ref(&*self.upload)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://xhr.spec.whatwg.org/#the-send()-method
|
// https://xhr.spec.whatwg.org/#the-send()-method
|
||||||
|
@ -882,7 +881,7 @@ impl XMLHttpRequest {
|
||||||
_ => "error",
|
_ => "error",
|
||||||
};
|
};
|
||||||
|
|
||||||
let upload_complete: &Cell<bool> = &self.upload_complete;
|
let upload_complete = &self.upload_complete;
|
||||||
if !upload_complete.get() {
|
if !upload_complete.get() {
|
||||||
upload_complete.set(true);
|
upload_complete.set(true);
|
||||||
self.dispatch_upload_progress_event("progress".to_owned(), None);
|
self.dispatch_upload_progress_event("progress".to_owned(), None);
|
||||||
|
@ -1111,7 +1110,7 @@ impl Extractable for SendParam {
|
||||||
},
|
},
|
||||||
eURLSearchParams(ref usp) => {
|
eURLSearchParams(ref usp) => {
|
||||||
// Default encoding is UTF-8.
|
// Default encoding is UTF-8.
|
||||||
usp.r().serialize(None).as_bytes().to_owned()
|
usp.r().serialize(None).into_bytes()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ pub enum Msg {
|
||||||
SetQuirksMode,
|
SetQuirksMode,
|
||||||
|
|
||||||
/// Requests a reflow.
|
/// Requests a reflow.
|
||||||
Reflow(Box<ScriptReflow>),
|
Reflow(ScriptReflow),
|
||||||
|
|
||||||
/// Get an RPC interface.
|
/// Get an RPC interface.
|
||||||
GetRPC(Sender<Box<LayoutRPC + Send>>),
|
GetRPC(Sender<Box<LayoutRPC + Send>>),
|
||||||
|
|
|
@ -70,7 +70,7 @@ extern crate rand;
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
extern crate rustc_unicode;
|
extern crate rustc_unicode;
|
||||||
extern crate script_traits;
|
extern crate script_traits;
|
||||||
extern crate selectors;
|
#[macro_use(state_pseudo_classes)] extern crate selectors;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate smallvec;
|
extern crate smallvec;
|
||||||
extern crate string_cache;
|
extern crate string_cache;
|
||||||
|
|
|
@ -68,11 +68,11 @@ impl Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window(&self) -> Root<Window> {
|
pub fn window(&self) -> Root<Window> {
|
||||||
self.frame.borrow().as_ref().unwrap().window.root()
|
Root::from_ref(&*self.frame.borrow().as_ref().unwrap().window)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn document(&self) -> Root<Document> {
|
pub fn document(&self) -> Root<Document> {
|
||||||
self.frame.borrow().as_ref().unwrap().document.root()
|
Root::from_ref(&*self.frame.borrow().as_ref().unwrap().document)
|
||||||
}
|
}
|
||||||
|
|
||||||
// must handle root case separately
|
// must handle root case separately
|
||||||
|
|
|
@ -9,8 +9,8 @@ use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||||
use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
use dom::bindings::inheritance::{Castable, CharacterDataTypeId, NodeTypeId};
|
use dom::bindings::inheritance::{Castable, CharacterDataTypeId, NodeTypeId};
|
||||||
use dom::bindings::js::{JS, Root};
|
|
||||||
use dom::bindings::js::{RootedReference};
|
use dom::bindings::js::{JS, RootedReference};
|
||||||
use dom::characterdata::CharacterData;
|
use dom::characterdata::CharacterData;
|
||||||
use dom::comment::Comment;
|
use dom::comment::Comment;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
|
@ -44,11 +44,10 @@ impl<'a> TreeSink for servohtmlparser::Sink {
|
||||||
type Handle = JS<Node>;
|
type Handle = JS<Node>;
|
||||||
|
|
||||||
fn get_document(&mut self) -> JS<Node> {
|
fn get_document(&mut self) -> JS<Node> {
|
||||||
JS::from_ref(self.document.root().upcast())
|
JS::from_ref(self.document.upcast())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_template_contents(&self, target: JS<Node>) -> JS<Node> {
|
fn get_template_contents(&self, target: JS<Node>) -> JS<Node> {
|
||||||
let target = target.root();
|
|
||||||
let template = target.downcast::<HTMLTemplateElement>()
|
let template = target.downcast::<HTMLTemplateElement>()
|
||||||
.expect("tried to get template contents of non-HTMLTemplateElement in HTML parsing");
|
.expect("tried to get template contents of non-HTMLTemplateElement in HTML parsing");
|
||||||
JS::from_ref(template.Content().upcast())
|
JS::from_ref(template.Content().upcast())
|
||||||
|
@ -59,8 +58,7 @@ impl<'a> TreeSink for servohtmlparser::Sink {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn elem_name(&self, target: JS<Node>) -> QualName {
|
fn elem_name(&self, target: JS<Node>) -> QualName {
|
||||||
let node: Root<Node> = target.root();
|
let elem = target.downcast::<Element>()
|
||||||
let elem = node.downcast::<Element>()
|
|
||||||
.expect("tried to get name of non-Element in HTML parsing");
|
.expect("tried to get name of non-Element in HTML parsing");
|
||||||
QualName {
|
QualName {
|
||||||
ns: elem.namespace().clone(),
|
ns: elem.namespace().clone(),
|
||||||
|
@ -70,8 +68,7 @@ impl<'a> TreeSink for servohtmlparser::Sink {
|
||||||
|
|
||||||
fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>)
|
fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>)
|
||||||
-> JS<Node> {
|
-> JS<Node> {
|
||||||
let doc = self.document.root();
|
let elem = Element::create(name, None, &*self.document,
|
||||||
let elem = Element::create(name, None, doc.r(),
|
|
||||||
ElementCreator::ParserCreated);
|
ElementCreator::ParserCreated);
|
||||||
|
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
|
@ -82,8 +79,7 @@ impl<'a> TreeSink for servohtmlparser::Sink {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_comment(&mut self, text: StrTendril) -> JS<Node> {
|
fn create_comment(&mut self, text: StrTendril) -> JS<Node> {
|
||||||
let doc = self.document.root();
|
let comment = Comment::new(text.into(), &*self.document);
|
||||||
let comment = Comment::new(text.into(), doc.r());
|
|
||||||
JS::from_ref(comment.upcast())
|
JS::from_ref(comment.upcast())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,14 +87,13 @@ impl<'a> TreeSink for servohtmlparser::Sink {
|
||||||
sibling: JS<Node>,
|
sibling: JS<Node>,
|
||||||
new_node: NodeOrText<JS<Node>>) -> Result<(), NodeOrText<JS<Node>>> {
|
new_node: NodeOrText<JS<Node>>) -> Result<(), NodeOrText<JS<Node>>> {
|
||||||
// If there is no parent, return the node to the parser.
|
// If there is no parent, return the node to the parser.
|
||||||
let sibling: Root<Node> = sibling.root();
|
let parent = match sibling.GetParentNode() {
|
||||||
let parent = match sibling.r().GetParentNode() {
|
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => return Err(new_node),
|
None => return Err(new_node),
|
||||||
};
|
};
|
||||||
|
|
||||||
let child = self.get_or_create(new_node);
|
let child = self.get_or_create(new_node);
|
||||||
assert!(parent.r().InsertBefore(child.r(), Some(sibling.r())).is_ok());
|
assert!(parent.r().InsertBefore(child.r(), Some(&*sibling)).is_ok());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,29 +102,26 @@ impl<'a> TreeSink for servohtmlparser::Sink {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_quirks_mode(&mut self, mode: QuirksMode) {
|
fn set_quirks_mode(&mut self, mode: QuirksMode) {
|
||||||
let doc = self.document.root();
|
self.document.set_quirks_mode(mode);
|
||||||
doc.r().set_quirks_mode(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append(&mut self, parent: JS<Node>, child: NodeOrText<JS<Node>>) {
|
fn append(&mut self, parent: JS<Node>, child: NodeOrText<JS<Node>>) {
|
||||||
let parent: Root<Node> = parent.root();
|
|
||||||
let child = self.get_or_create(child);
|
let child = self.get_or_create(child);
|
||||||
|
|
||||||
// FIXME(#3701): Use a simpler algorithm and merge adjacent text nodes
|
// FIXME(#3701): Use a simpler algorithm and merge adjacent text nodes
|
||||||
assert!(parent.r().AppendChild(child.r()).is_ok());
|
assert!(parent.AppendChild(child.r()).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril,
|
fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril,
|
||||||
system_id: StrTendril) {
|
system_id: StrTendril) {
|
||||||
let doc = self.document.root();
|
let doc = &*self.document;
|
||||||
let doctype = DocumentType::new(
|
let doctype = DocumentType::new(
|
||||||
name.into(), Some(public_id.into()), Some(system_id.into()), doc.r());
|
name.into(), Some(public_id.into()), Some(system_id.into()), doc);
|
||||||
doc.upcast::<Node>().AppendChild(doctype.upcast()).expect("Appending failed");
|
doc.upcast::<Node>().AppendChild(doctype.upcast()).expect("Appending failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_attrs_if_missing(&mut self, target: JS<Node>, attrs: Vec<Attribute>) {
|
fn add_attrs_if_missing(&mut self, target: JS<Node>, attrs: Vec<Attribute>) {
|
||||||
let node: Root<Node> = target.root();
|
let elem = target.downcast::<Element>()
|
||||||
let elem = node.downcast::<Element>()
|
|
||||||
.expect("tried to set attrs on non-Element in HTML parsing");
|
.expect("tried to set attrs on non-Element in HTML parsing");
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
elem.set_attribute_from_parser(attr.name, attr.value.into(), None);
|
elem.set_attribute_from_parser(attr.name, attr.value.into(), None);
|
||||||
|
@ -137,20 +129,17 @@ impl<'a> TreeSink for servohtmlparser::Sink {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_from_parent(&mut self, target: JS<Node>) {
|
fn remove_from_parent(&mut self, target: JS<Node>) {
|
||||||
let node = target.root();
|
if let Some(ref parent) = target.GetParentNode() {
|
||||||
if let Some(ref parent) = node.r().GetParentNode() {
|
parent.r().RemoveChild(&*target).unwrap();
|
||||||
parent.r().RemoveChild(node.r()).unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_script_already_started(&mut self, node: JS<Node>) {
|
fn mark_script_already_started(&mut self, node: JS<Node>) {
|
||||||
let node: Root<Node> = node.root();
|
|
||||||
let script = node.downcast::<HTMLScriptElement>();
|
let script = node.downcast::<HTMLScriptElement>();
|
||||||
script.map(|script| script.mark_already_started());
|
script.map(|script| script.mark_already_started());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_script(&mut self, node: JS<Node>) -> NextParserState {
|
fn complete_script(&mut self, node: JS<Node>) -> NextParserState {
|
||||||
let node: Root<Node> = node.root();
|
|
||||||
let script = node.downcast::<HTMLScriptElement>();
|
let script = node.downcast::<HTMLScriptElement>();
|
||||||
if let Some(script) = script {
|
if let Some(script) = script {
|
||||||
return script.prepare();
|
return script.prepare();
|
||||||
|
@ -159,11 +148,7 @@ impl<'a> TreeSink for servohtmlparser::Sink {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reparent_children(&mut self, node: JS<Node>, new_parent: JS<Node>) {
|
fn reparent_children(&mut self, node: JS<Node>, new_parent: JS<Node>) {
|
||||||
let new_parent = new_parent.root();
|
while let Some(ref child) = node.GetFirstChild() {
|
||||||
let new_parent = new_parent.r();
|
|
||||||
let old_parent = node.root();
|
|
||||||
let old_parent = old_parent.r();
|
|
||||||
while let Some(ref child) = old_parent.GetFirstChild() {
|
|
||||||
new_parent.AppendChild(child.r()).unwrap();
|
new_parent.AppendChild(child.r()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,11 +165,10 @@ impl<'a> Serializable for &'a Node {
|
||||||
let name = QualName::new(elem.namespace().clone(),
|
let name = QualName::new(elem.namespace().clone(),
|
||||||
elem.local_name().clone());
|
elem.local_name().clone());
|
||||||
if traversal_scope == IncludeNode {
|
if traversal_scope == IncludeNode {
|
||||||
let attrs = elem.attrs().iter().map(|at| {
|
let attrs = elem.attrs().iter().map(|attr| {
|
||||||
let attr = at.root();
|
let qname = QualName::new(attr.namespace().clone(),
|
||||||
let qname = QualName::new(attr.r().namespace().clone(),
|
attr.local_name().clone());
|
||||||
attr.r().local_name().clone());
|
let value = attr.value().clone();
|
||||||
let value = attr.r().value().clone();
|
|
||||||
(qname, value)
|
(qname, value)
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
let attr_refs = attrs.iter().map(|&(ref qname, ref value)| {
|
let attr_refs = attrs.iter().map(|&(ref qname, ref value)| {
|
||||||
|
|
|
@ -415,7 +415,7 @@ pub struct ScriptTask {
|
||||||
mouse_over_targets: DOMRefCell<Vec<JS<Element>>>,
|
mouse_over_targets: DOMRefCell<Vec<JS<Element>>>,
|
||||||
|
|
||||||
/// List of pipelines that have been owned and closed by this script task.
|
/// List of pipelines that have been owned and closed by this script task.
|
||||||
closed_pipelines: RefCell<HashSet<PipelineId>>,
|
closed_pipelines: DOMRefCell<HashSet<PipelineId>>,
|
||||||
|
|
||||||
scheduler_chan: Sender<TimerEventRequest>,
|
scheduler_chan: Sender<TimerEventRequest>,
|
||||||
timer_event_chan: Sender<TimerEvent>,
|
timer_event_chan: Sender<TimerEvent>,
|
||||||
|
@ -644,7 +644,7 @@ impl ScriptTask {
|
||||||
|
|
||||||
js_runtime: Rc::new(runtime),
|
js_runtime: Rc::new(runtime),
|
||||||
mouse_over_targets: DOMRefCell::new(vec!()),
|
mouse_over_targets: DOMRefCell::new(vec!()),
|
||||||
closed_pipelines: RefCell::new(HashSet::new()),
|
closed_pipelines: DOMRefCell::new(HashSet::new()),
|
||||||
|
|
||||||
scheduler_chan: state.scheduler_chan,
|
scheduler_chan: state.scheduler_chan,
|
||||||
timer_event_chan: timer_event_chan,
|
timer_event_chan: timer_event_chan,
|
||||||
|
@ -1657,9 +1657,7 @@ impl ScriptTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn notify_devtools(&self, title: DOMString, url: Url, ids: (PipelineId, Option<WorkerId>)) {
|
fn notify_devtools(&self, title: DOMString, url: Url, ids: (PipelineId, Option<WorkerId>)) {
|
||||||
match self.devtools_chan {
|
if let Some(ref chan) = self.devtools_chan {
|
||||||
None => {}
|
|
||||||
Some(ref chan) => {
|
|
||||||
let page_info = DevtoolsPageInfo {
|
let page_info = DevtoolsPageInfo {
|
||||||
title: title,
|
title: title,
|
||||||
url: url,
|
url: url,
|
||||||
|
@ -1670,15 +1668,23 @@ impl ScriptTask {
|
||||||
page_info)).unwrap();
|
page_info)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn scroll_fragment_point(&self, pipeline_id: PipelineId, element: &Element) {
|
fn scroll_fragment_point(&self, pipeline_id: PipelineId, element: &Element) {
|
||||||
let rect = element.upcast::<Node>().get_bounding_content_box();
|
// FIXME(#8275, pcwalton): This is pretty bogus when multiple layers are involved.
|
||||||
let point = Point2D::new(rect.origin.x.to_f32_px(), rect.origin.y.to_f32_px());
|
|
||||||
// FIXME(#2003, pcwalton): This is pretty bogus when multiple layers are involved.
|
|
||||||
// Really what needs to happen is that this needs to go through layout to ask which
|
// Really what needs to happen is that this needs to go through layout to ask which
|
||||||
// layer the element belongs to, and have it send the scroll message to the
|
// layer the element belongs to, and have it send the scroll message to the
|
||||||
// compositor.
|
// compositor.
|
||||||
|
let rect = element.upcast::<Node>().get_bounding_content_box();
|
||||||
|
|
||||||
|
// In order to align with element edges, we snap to unscaled pixel boundaries, since the
|
||||||
|
// paint task currently does the same for drawing elements. This is important for pages
|
||||||
|
// that require pixel perfect scroll positioning for proper display (like Acid2). Since we
|
||||||
|
// don't have the device pixel ratio here, this might not be accurate, but should work as
|
||||||
|
// long as the ratio is a whole number. Once #8275 is fixed this should actually take into
|
||||||
|
// account the real device pixel ratio.
|
||||||
|
let point = Point2D::new(rect.origin.x.to_nearest_px() as f32,
|
||||||
|
rect.origin.y.to_nearest_px() as f32);
|
||||||
|
|
||||||
self.compositor.borrow_mut().send(ScriptToCompositorMsg::ScrollFragmentPoint(
|
self.compositor.borrow_mut().send(ScriptToCompositorMsg::ScrollFragmentPoint(
|
||||||
pipeline_id, LayerId::null(), point, false)).unwrap();
|
pipeline_id, LayerId::null(), point, false)).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1742,9 +1748,8 @@ impl ScriptTask {
|
||||||
|
|
||||||
// Notify Constellation about the topmost anchor mouse over target.
|
// Notify Constellation about the topmost anchor mouse over target.
|
||||||
for target in &*mouse_over_targets {
|
for target in &*mouse_over_targets {
|
||||||
let target = target.root();
|
|
||||||
if target.upcast::<Node>().is_anchor_element() {
|
if target.upcast::<Node>().is_anchor_element() {
|
||||||
let status = target.r().get_attribute(&ns!(""), &atom!("href"))
|
let status = target.get_attribute(&ns!(""), &atom!("href"))
|
||||||
.and_then(|href| {
|
.and_then(|href| {
|
||||||
let value = href.value();
|
let value = href.value();
|
||||||
let url = document.r().url();
|
let url = document.r().url();
|
||||||
|
|
|
@ -78,7 +78,7 @@ impl Ord for Timer {
|
||||||
fn cmp(&self, other: &Timer) -> Ordering {
|
fn cmp(&self, other: &Timer) -> Ordering {
|
||||||
match self.next_call.cmp(&other.next_call).reverse() {
|
match self.next_call.cmp(&other.next_call).reverse() {
|
||||||
Ordering::Equal => self.handle.cmp(&other.handle).reverse(),
|
Ordering::Equal => self.handle.cmp(&other.handle).reverse(),
|
||||||
res @ _ => res
|
res => res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ pub fn handle_get_frame_id(page: &Rc<Page>,
|
||||||
|
|
||||||
pub fn handle_find_element_css(page: &Rc<Page>, _pipeline: PipelineId, selector: String,
|
pub fn handle_find_element_css(page: &Rc<Page>, _pipeline: PipelineId, selector: String,
|
||||||
reply: IpcSender<Result<Option<String>, ()>>) {
|
reply: IpcSender<Result<Option<String>, ()>>) {
|
||||||
reply.send(match page.document().r().QuerySelector(selector.clone()) {
|
reply.send(match page.document().r().QuerySelector(selector) {
|
||||||
Ok(node) => {
|
Ok(node) => {
|
||||||
Ok(node.map(|x| x.upcast::<Node>().get_unique_id()))
|
Ok(node.map(|x| x.upcast::<Node>().get_unique_id()))
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ pub fn handle_find_elements_css(page: &Rc<Page>,
|
||||||
_pipeline: PipelineId,
|
_pipeline: PipelineId,
|
||||||
selector: String,
|
selector: String,
|
||||||
reply: IpcSender<Result<Vec<String>, ()>>) {
|
reply: IpcSender<Result<Vec<String>, ()>>) {
|
||||||
reply.send(match page.document().r().QuerySelectorAll(selector.clone()) {
|
reply.send(match page.document().r().QuerySelectorAll(selector) {
|
||||||
Ok(ref nodes) => {
|
Ok(ref nodes) => {
|
||||||
let mut result = Vec::with_capacity(nodes.r().Length() as usize);
|
let mut result = Vec::with_capacity(nodes.r().Length() as usize);
|
||||||
for i in 0..nodes.r().Length() {
|
for i in 0..nodes.r().Length() {
|
||||||
|
|
68
components/servo/Cargo.lock
generated
68
components/servo/Cargo.lock
generated
|
@ -24,6 +24,7 @@ dependencies = [
|
||||||
"net 0.0.1",
|
"net 0.0.1",
|
||||||
"net_tests 0.0.1",
|
"net_tests 0.0.1",
|
||||||
"net_traits 0.0.1",
|
"net_traits 0.0.1",
|
||||||
|
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||||
"profile 0.0.1",
|
"profile 0.0.1",
|
||||||
"profile_traits 0.0.1",
|
"profile_traits 0.0.1",
|
||||||
"script 0.0.1",
|
"script 0.0.1",
|
||||||
|
@ -138,6 +139,11 @@ dependencies = [
|
||||||
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "brotli"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "git+https://github.com/ende76/brotli-rs#4a8c42cce771ded65fe64d6816f5d7303006b2ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "0.3.13"
|
version = "0.3.13"
|
||||||
|
@ -474,18 +480,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "energymon"
|
name = "energymon"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/energymon/energymon-rust.git?rev=67f74732ac#67f74732ac0acc682659f7e81836155a32188fd0"
|
source = "git+https://github.com/energymon/energymon-rust.git?rev=eba1d8a#eba1d8a7256b710230ea2c1b26525b88bfcb529d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"energy-monitor 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"energy-monitor 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"energymon-default-sys 0.1.0 (git+https://github.com/energymon/energymon-default-sys.git)",
|
"energymon-default-sys 0.1.0 (git+https://github.com/energymon/energymon-sys.git)",
|
||||||
"energymon-sys 0.1.0 (git+https://github.com/energymon/energymon-sys.git)",
|
|
||||||
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "energymon-default-sys"
|
name = "energymon-default-sys"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/energymon/energymon-default-sys.git#82dd2f6762b492ced15d8446b70569778200c287"
|
source = "git+https://github.com/energymon/energymon-sys.git#82756eee725db3ccb658f14857947a0260743d4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"energymon-sys 0.1.0 (git+https://github.com/energymon/energymon-sys.git)",
|
"energymon-sys 0.1.0 (git+https://github.com/energymon/energymon-sys.git)",
|
||||||
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -495,7 +500,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "energymon-sys"
|
name = "energymon-sys"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/energymon/energymon-sys.git#6306f70e5d5c824fa168e43521385798fd1b890b"
|
source = "git+https://github.com/energymon/energymon-sys.git#82756eee725db3ccb658f14857947a0260743d4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -750,36 +755,6 @@ dependencies = [
|
||||||
"x11-dl 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"x11-dl 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "glutin"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"android_glue 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cocoa 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"core-graphics 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"dwmapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"gl_common 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"gl_generator 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"khronos_api 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"objc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"osmesa-sys 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"shared_library 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"user32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"wayland-client 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"wayland-kbd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"wayland-window 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"x11-dl 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glutin_app"
|
name = "glutin_app"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -1040,7 +1015,7 @@ dependencies = [
|
||||||
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"script 0.0.1",
|
"script 0.0.1",
|
||||||
"script_traits 0.0.1",
|
"script_traits 0.0.1",
|
||||||
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
"selectors 0.2.0 (git+https://github.com/servo/rust-selectors)",
|
||||||
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1201,6 +1176,7 @@ dependencies = [
|
||||||
name = "net"
|
name = "net"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"brotli 0.3.17 (git+https://github.com/ende76/brotli-rs)",
|
||||||
"cookie 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cookie 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"devtools_traits 0.0.1",
|
"devtools_traits 0.0.1",
|
||||||
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1304,14 +1280,14 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "offscreen_gl_context"
|
name = "offscreen_gl_context"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/ecoal95/rust-offscreen-rendering-context#a33af19355dfdd0076a3f2836dc66e0fea44bcab"
|
source = "git+https://github.com/ecoal95/rust-offscreen-rendering-context#aae6e57969c553973c43ce5e4246831ccc2868f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gl_generator 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gl_generator 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glutin 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"glutin 0.4.0 (git+https://github.com/servo/glutin?branch=servo)",
|
||||||
"khronos_api 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"khronos_api 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
|
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
|
||||||
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1436,7 +1412,7 @@ name = "profile_traits"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"energy-monitor 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"energy-monitor 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"energymon 0.1.0 (git+https://github.com/energymon/energymon-rust.git?rev=67f74732ac)",
|
"energymon 0.1.0 (git+https://github.com/energymon/energymon-rust.git?rev=eba1d8a)",
|
||||||
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
|
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
|
||||||
"plugins 0.0.1",
|
"plugins 0.0.1",
|
||||||
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1549,7 +1525,7 @@ dependencies = [
|
||||||
"rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"script_traits 0.0.1",
|
"script_traits 0.0.1",
|
||||||
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
"selectors 0.2.0 (git+https://github.com/servo/rust-selectors)",
|
||||||
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1594,8 +1570,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "selectors"
|
name = "selectors"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/servo/rust-selectors#1e1e44c2f4090e8beb95a8d27f184aefcf91a362"
|
source = "git+https://github.com/servo/rust-selectors#53f5e09a37684f6a42eb894d7a6fd0b14380a1c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1752,7 +1728,7 @@ dependencies = [
|
||||||
"num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"plugins 0.0.1",
|
"plugins 0.0.1",
|
||||||
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
"selectors 0.2.0 (git+https://github.com/servo/rust-selectors)",
|
||||||
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1770,7 +1746,7 @@ dependencies = [
|
||||||
"app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
"selectors 0.2.0 (git+https://github.com/servo/rust-selectors)",
|
||||||
"string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"style 0.0.1",
|
"style 0.0.1",
|
||||||
|
@ -1790,7 +1766,7 @@ dependencies = [
|
||||||
"num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"plugins 0.0.1",
|
"plugins 0.0.1",
|
||||||
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
"selectors 0.2.0 (git+https://github.com/servo/rust-selectors)",
|
||||||
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1935,7 +1911,7 @@ dependencies = [
|
||||||
"plugins 0.0.1",
|
"plugins 0.0.1",
|
||||||
"rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
"selectors 0.2.0 (git+https://github.com/servo/rust-selectors)",
|
||||||
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -133,6 +133,9 @@ features = ["plugins"]
|
||||||
[dependencies.gleam]
|
[dependencies.gleam]
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
|
|
||||||
|
[dependencies.offscreen_gl_context]
|
||||||
|
git = "https://github.com/ecoal95/rust-offscreen-rendering-context"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.3"
|
env_logger = "0.3"
|
||||||
time = "0.1.12"
|
time = "0.1.12"
|
||||||
|
|
|
@ -23,18 +23,31 @@ extern crate android_glue;
|
||||||
// The window backed by glutin
|
// The window backed by glutin
|
||||||
extern crate glutin_app as app;
|
extern crate glutin_app as app;
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
// The Servo engine
|
// The Servo engine
|
||||||
extern crate servo;
|
extern crate servo;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
|
||||||
|
extern crate gleam;
|
||||||
|
extern crate offscreen_gl_context;
|
||||||
|
|
||||||
|
use gleam::gl;
|
||||||
|
use offscreen_gl_context::GLContext;
|
||||||
use servo::Browser;
|
use servo::Browser;
|
||||||
use servo::compositing::windowing::WindowEvent;
|
use servo::compositing::windowing::WindowEvent;
|
||||||
use servo::net_traits::hosts;
|
use servo::net_traits::hosts;
|
||||||
use servo::util::opts;
|
use servo::util::opts;
|
||||||
#[cfg(target_os = "android")]
|
|
||||||
use std::borrow::ToOwned;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
|
fn load_gl_when_headless() {
|
||||||
|
gl::load_with(|addr| GLContext::get_proc_address(addr) as *const _);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
fn load_gl_when_headless() {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init().unwrap();
|
env_logger::init().unwrap();
|
||||||
|
|
||||||
|
@ -47,6 +60,9 @@ fn main() {
|
||||||
hosts::global_init();
|
hosts::global_init();
|
||||||
|
|
||||||
let window = if opts::get().headless {
|
let window = if opts::get().headless {
|
||||||
|
// Load gl functions even when in headless mode,
|
||||||
|
// to avoid crashing with webgl
|
||||||
|
load_gl_when_headless();
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(app::create_window(std::ptr::null_mut()))
|
Some(app::create_window(std::ptr::null_mut()))
|
||||||
|
@ -130,11 +146,39 @@ fn setup_logging() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
|
/// Attempt to read parameters from a file since they are not passed to us in Android environments.
|
||||||
|
/// The first line should be the "servo" argument and the last should be the URL to load.
|
||||||
|
/// Blank lines and those beginning with a '#' are ignored.
|
||||||
|
/// Each line should be a separate parameter as would be parsed by the shell.
|
||||||
|
/// For example, "servo -p 10 http://en.wikipedia.org/wiki/Rust" would take 4 lines.
|
||||||
fn args() -> Vec<String> {
|
fn args() -> Vec<String> {
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
|
|
||||||
|
const PARAMS_FILE: &'static str = "/sdcard/servo/android_params";
|
||||||
|
match File::open(PARAMS_FILE) {
|
||||||
|
Ok(f) => {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
let file = BufReader::new(&f);
|
||||||
|
for line in file.lines() {
|
||||||
|
let l = line.unwrap().trim().to_owned();
|
||||||
|
// ignore blank lines and those that start with a '#'
|
||||||
|
match l.is_empty() || l.as_bytes()[0] == b'#' {
|
||||||
|
true => (),
|
||||||
|
false => vec.push(l),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
debug!("Failed to open params file '{}': {}", PARAMS_FILE, Error::description(&e));
|
||||||
vec![
|
vec![
|
||||||
"servo".to_owned(),
|
"servo".to_owned(),
|
||||||
"http://en.wikipedia.org/wiki/Rust".to_owned()
|
"http://en.wikipedia.org/wiki/Rust".to_owned()
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue