aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/Cargo.toml3
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py1
-rw-r--r--components/script/dom/bindings/trace.rs4
-rw-r--r--components/script/dom/blob.rs12
-rw-r--r--components/script/dom/canvasrenderingcontext2d.rs4
-rw-r--r--components/script/dom/css.rs12
-rw-r--r--components/script/dom/csskeyframesrule.rs22
-rw-r--r--components/script/dom/cssmediarule.rs13
-rw-r--r--components/script/dom/cssrule.rs1
-rw-r--r--components/script/dom/cssrulelist.rs18
-rw-r--r--components/script/dom/cssstyledeclaration.rs10
-rw-r--r--components/script/dom/csssupportsrule.rs9
-rw-r--r--components/script/dom/dissimilaroriginlocation.rs6
-rw-r--r--components/script/dom/dissimilaroriginwindow.rs9
-rw-r--r--components/script/dom/document.rs20
-rw-r--r--components/script/dom/dommatrixreadonly.rs2
-rw-r--r--components/script/dom/domrectlist.rs58
-rw-r--r--components/script/dom/element.rs35
-rw-r--r--components/script/dom/gamepad.rs206
-rw-r--r--components/script/dom/gamepadbutton.rs61
-rw-r--r--components/script/dom/gamepadbuttonlist.rs63
-rw-r--r--components/script/dom/gamepadevent.rs92
-rw-r--r--components/script/dom/gamepadlist.rs61
-rw-r--r--components/script/dom/globalscope.rs14
-rw-r--r--components/script/dom/htmlimageelement.rs5
-rwxr-xr-xcomponents/script/dom/htmlinputelement.rs2
-rw-r--r--components/script/dom/htmllinkelement.rs20
-rw-r--r--components/script/dom/htmlmetaelement.rs4
-rw-r--r--components/script/dom/htmlscriptelement.rs53
-rw-r--r--components/script/dom/htmlstyleelement.rs23
-rw-r--r--components/script/dom/location.rs7
-rw-r--r--components/script/dom/medialist.rs35
-rw-r--r--components/script/dom/mediaquerylist.rs2
-rw-r--r--components/script/dom/mod.rs6
-rw-r--r--components/script/dom/navigator.rs22
-rw-r--r--components/script/dom/node.rs8
-rw-r--r--components/script/dom/nodelist.rs6
-rw-r--r--components/script/dom/treewalker.rs2
-rw-r--r--components/script/dom/vr.rs134
-rw-r--r--components/script/dom/vrdisplay.rs16
-rw-r--r--components/script/dom/vrpose.rs4
-rw-r--r--components/script/dom/webglrenderingcontext.rs137
-rw-r--r--components/script/dom/webglshader.rs4
-rw-r--r--components/script/dom/webidls/CSSStyleDeclaration.webidl4
-rw-r--r--components/script/dom/webidls/Element.webidl3
-rw-r--r--components/script/dom/webidls/Gamepad.webidl26
-rw-r--r--components/script/dom/webidls/GamepadButton.webidl11
-rw-r--r--components/script/dom/webidls/GamepadButtonList.webidl (renamed from components/script/dom/webidls/DOMRectList.webidl)9
-rw-r--r--components/script/dom/webidls/GamepadEvent.webidl13
-rw-r--r--components/script/dom/webidls/GamepadList.webidl10
-rw-r--r--components/script/dom/webidls/Navigator.webidl5
-rw-r--r--components/script/dom/webidls/Range.webidl3
-rw-r--r--components/script/dom/webidls/WebGLRenderingContext.webidl2
-rw-r--r--components/script/dom/window.rs57
-rw-r--r--components/script/dom/workerglobalscope.rs6
-rw-r--r--components/script/layout_wrapper.rs21
-rw-r--r--components/script/lib.rs2
-rw-r--r--components/script/script_thread.rs15
-rw-r--r--components/script/stylesheet_loader.rs16
-rw-r--r--components/script/textinput.rs208
60 files changed, 1348 insertions, 289 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index b7f7f37fbd4..f145e8f65b0 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -35,7 +35,7 @@ byteorder = "1.0"
canvas_traits = {path = "../canvas_traits"}
caseless = "0.1.0"
cookie = "0.6"
-cssparser = "0.12.1"
+cssparser = "0.13"
deny_public_fields = {path = "../deny_public_fields"}
devtools_traits = {path = "../devtools_traits"}
dom_struct = {path = "../dom_struct"}
@@ -85,6 +85,7 @@ smallvec = "0.3"
style = {path = "../style"}
style_traits = {path = "../style_traits"}
time = "0.1.12"
+unicode-segmentation = "1.1.0"
url = {version = "1.2", features = ["heap_size", "query_encoding"]}
uuid = {version = "0.4", features = ["v4"]}
xml5ever = {version = "0.5", features = ["unstable"]}
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index a54ea0c3c97..e7a0541c4da 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -1850,6 +1850,7 @@ class CGImports(CGWrapper):
'unused_imports',
'unused_variables',
'unused_assignments',
+ 'unused_mut',
]
def componentTypes(type):
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 890074974d3..1bc9c165fb1 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -107,6 +107,7 @@ use time::Duration;
use uuid::Uuid;
use webrender_traits::{WebGLBufferId, WebGLError, WebGLFramebufferId, WebGLProgramId};
use webrender_traits::{WebGLRenderbufferId, WebGLShaderId, WebGLTextureId};
+use webvr_traits::WebVRGamepadHand;
/// A trait to allow tracing (only) DOM objects.
pub unsafe trait JSTraceable {
@@ -381,6 +382,7 @@ unsafe_no_jsmanaged_fields!(WebGLRenderbufferId);
unsafe_no_jsmanaged_fields!(WebGLShaderId);
unsafe_no_jsmanaged_fields!(WebGLTextureId);
unsafe_no_jsmanaged_fields!(MediaList);
+unsafe_no_jsmanaged_fields!(WebVRGamepadHand);
unsafe impl<'a> JSTraceable for &'a str {
#[inline]
@@ -726,7 +728,7 @@ impl<T: JSTraceable> RootableVec<T> {
RootableVec {
v: vec![],
}
- }
+ }
}
/// A vector of items that are rooted for the lifetime 'a.
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs
index cb61ced9e3a..c076282dcc1 100644
--- a/components/script/dom/blob.rs
+++ b/components/script/dom/blob.rs
@@ -353,12 +353,12 @@ pub fn blob_parts_to_bytes(blobparts: Vec<BlobOrString>) -> Result<Vec<u8>, ()>
impl BlobMethods for Blob {
// https://w3c.github.io/FileAPI/#dfn-size
fn Size(&self) -> u64 {
- match *self.blob_impl.borrow() {
- BlobImpl::File(ref f) => f.size,
- BlobImpl::Memory(ref v) => v.len() as u64,
- BlobImpl::Sliced(ref parent, ref rel_pos) =>
- rel_pos.to_abs_range(parent.Size() as usize).len() as u64,
- }
+ match *self.blob_impl.borrow() {
+ BlobImpl::File(ref f) => f.size,
+ BlobImpl::Memory(ref v) => v.len() as u64,
+ BlobImpl::Sliced(ref parent, ref rel_pos) =>
+ rel_pos.to_abs_range(parent.Size() as usize).len() as u64,
+ }
}
// https://w3c.github.io/FileAPI/#dfn-type
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs
index 432dbe800aa..a5ec8d233b6 100644
--- a/components/script/dom/canvasrenderingcontext2d.rs
+++ b/components/script/dom/canvasrenderingcontext2d.rs
@@ -350,7 +350,7 @@ impl CanvasRenderingContext2D {
dh);
if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) {
- return Err(Error::IndexSize);
+ return Ok(());
}
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
@@ -407,7 +407,7 @@ impl CanvasRenderingContext2D {
dh);
if !is_rect_valid(source_rect) || !is_rect_valid(dest_rect) {
- return Err(Error::IndexSize);
+ return Ok(());
}
let smoothing_enabled = self.state.borrow().image_smoothing_enabled;
diff --git a/components/script/dom/css.rs b/components/script/dom/css.rs
index 92c15a10067..72cdbfa5be6 100644
--- a/components/script/dom/css.rs
+++ b/components/script/dom/css.rs
@@ -9,7 +9,9 @@ use dom::bindings::reflector::Reflector;
use dom::bindings::str::DOMString;
use dom::window::Window;
use dom_struct::dom_struct;
-use style::parser::ParserContext;
+use style::context::QuirksMode;
+use style::parser::{LengthParsingMode, ParserContext};
+use style::stylesheets::CssRuleType;
use style::supports::{Declaration, parse_condition_or_declaration};
#[dom_struct]
@@ -29,7 +31,9 @@ impl CSS {
pub fn Supports(win: &Window, property: DOMString, value: DOMString) -> bool {
let decl = Declaration { prop: property.into(), val: value.into() };
let url = win.Document().url();
- let context = ParserContext::new_for_cssom(&url, win.css_error_reporter());
+ let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports),
+ LengthParsingMode::Default,
+ QuirksMode::NoQuirks);
decl.eval(&context)
}
@@ -39,7 +43,9 @@ impl CSS {
let cond = parse_condition_or_declaration(&mut input);
if let Ok(cond) = cond {
let url = win.Document().url();
- let context = ParserContext::new_for_cssom(&url, win.css_error_reporter());
+ let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports),
+ LengthParsingMode::Default,
+ QuirksMode::NoQuirks);
cond.eval(&context)
} else {
false
diff --git a/components/script/dom/csskeyframesrule.rs b/components/script/dom/csskeyframesrule.rs
index 281ccd972a7..a3715e914ed 100644
--- a/components/script/dom/csskeyframesrule.rs
+++ b/components/script/dom/csskeyframesrule.rs
@@ -5,7 +5,7 @@
use cssparser::Parser;
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding;
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding::CSSKeyframesRuleMethods;
-use dom::bindings::error::{Error, ErrorResult};
+use dom::bindings::error::ErrorResult;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::reflector::{DomObject, reflect_dom_object};
@@ -16,11 +16,11 @@ use dom::cssrulelist::{CSSRuleList, RulesSource};
use dom::cssstylesheet::CSSStyleSheet;
use dom::window::Window;
use dom_struct::dom_struct;
-use servo_atoms::Atom;
use std::sync::Arc;
use style::keyframes::{Keyframe, KeyframeSelector};
use style::shared_lock::{Locked, ToCssWithGuard};
use style::stylesheets::KeyframesRule;
+use style::values::KeyframesName;
#[dom_struct]
pub struct CSSKeyframesRule {
@@ -107,23 +107,17 @@ impl CSSKeyframesRuleMethods for CSSKeyframesRule {
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name
fn Name(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
- DOMString::from(&*self.keyframesrule.read_with(&guard).name)
+ DOMString::from(&**self.keyframesrule.read_with(&guard).name.as_atom())
}
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name
fn SetName(&self, value: DOMString) -> ErrorResult {
- // https://github.com/w3c/csswg-drafts/issues/801
- // Setting this property to a CSS-wide keyword or `none` will
- // throw a Syntax Error.
- match_ignore_ascii_case! { &value,
- "initial" => return Err(Error::Syntax),
- "inherit" => return Err(Error::Syntax),
- "unset" => return Err(Error::Syntax),
- "none" => return Err(Error::Syntax),
- _ => ()
- }
+ // Spec deviation: https://github.com/w3c/csswg-drafts/issues/801
+ // Setting this property to a CSS-wide keyword or `none` does not throw,
+ // it stores a value that serializes as a quoted string.
+ let name = KeyframesName::from_ident(value.into());
let mut guard = self.cssrule.shared_lock().write();
- self.keyframesrule.write_with(&mut guard).name = Atom::from(value);
+ self.keyframesrule.write_with(&mut guard).name = name;
Ok(())
}
}
diff --git a/components/script/dom/cssmediarule.rs b/components/script/dom/cssmediarule.rs
index 2a07471679e..45bf65b1adf 100644
--- a/components/script/dom/cssmediarule.rs
+++ b/components/script/dom/cssmediarule.rs
@@ -5,6 +5,7 @@
use cssparser::Parser;
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding;
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding::CSSMediaRuleMethods;
+use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::reflector::{DomObject, reflect_dom_object};
use dom::bindings::str::DOMString;
@@ -16,8 +17,9 @@ use dom::window::Window;
use dom_struct::dom_struct;
use std::sync::Arc;
use style::media_queries::parse_media_query_list;
+use style::parser::{LengthParsingMode, ParserContext};
use style::shared_lock::{Locked, ToCssWithGuard};
-use style::stylesheets::MediaRule;
+use style::stylesheets::{CssRuleType, MediaRule};
use style_traits::ToCss;
#[dom_struct]
@@ -68,7 +70,14 @@ impl CSSMediaRule {
/// https://drafts.csswg.org/css-conditional-3/#the-cssmediarule-interface
pub fn set_condition_text(&self, text: DOMString) {
let mut input = Parser::new(&text);
- let new_medialist = parse_media_query_list(&mut input);
+ let global = self.global();
+ let win = global.as_window();
+ let url = win.get_url();
+ let quirks_mode = win.Document().quirks_mode();
+ let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media),
+ LengthParsingMode::Default,
+ quirks_mode);
+ let new_medialist = parse_media_query_list(&context, &mut input);
let mut guard = self.cssconditionrule.shared_lock().write();
// Clone an Arc because we can’t borrow `guard` twice at the same time.
diff --git a/components/script/dom/cssrule.rs b/components/script/dom/cssrule.rs
index 1a24d5839bf..6bfe057d6d9 100644
--- a/components/script/dom/cssrule.rs
+++ b/components/script/dom/cssrule.rs
@@ -78,6 +78,7 @@ impl CSSRule {
StyleCssRule::Import(s) => Root::upcast(CSSImportRule::new(window, parent_stylesheet, s)),
StyleCssRule::Style(s) => Root::upcast(CSSStyleRule::new(window, parent_stylesheet, s)),
StyleCssRule::FontFace(s) => Root::upcast(CSSFontFaceRule::new(window, parent_stylesheet, s)),
+ StyleCssRule::CounterStyle(_) => unimplemented!(),
StyleCssRule::Keyframes(s) => Root::upcast(CSSKeyframesRule::new(window, parent_stylesheet, s)),
StyleCssRule::Media(s) => Root::upcast(CSSMediaRule::new(window, parent_stylesheet, s)),
StyleCssRule::Namespace(s) => Root::upcast(CSSNamespaceRule::new(window, parent_stylesheet, s)),
diff --git a/components/script/dom/cssrulelist.rs b/components/script/dom/cssrulelist.rs
index 4587659dfec..67eac2beda2 100644
--- a/components/script/dom/cssrulelist.rs
+++ b/components/script/dom/cssrulelist.rs
@@ -15,7 +15,7 @@ use dom::window::Window;
use dom_struct::dom_struct;
use std::sync::Arc;
use style::shared_lock::Locked;
-use style::stylesheets::{CssRules, KeyframesRule, RulesMutateError};
+use style::stylesheets::{CssRules, CssRulesHelpers, KeyframesRule, RulesMutateError};
#[allow(unsafe_code)]
unsafe_no_jsmanaged_fields!(RulesSource);
@@ -90,15 +90,13 @@ impl CSSRuleList {
let index = idx as usize;
let parent_stylesheet = self.parent_stylesheet.style_stylesheet();
- let new_rule = {
- let mut guard = parent_stylesheet.shared_lock.write();
- // FIXME We should probably pass in a proper StylesheetLoader.
- // See servo/servo#16240
- css_rules.write_with(&mut guard).insert_rule(rule, parent_stylesheet,
- index, nested, None)?
- // Drop `guard` here,
- // CSSRule::new_specific re-acquires the lock for @support and @media.
- };
+ let new_rule =
+ css_rules.insert_rule(&parent_stylesheet.shared_lock,
+ rule,
+ parent_stylesheet,
+ index,
+ nested,
+ None)?;
let parent_stylesheet = &*self.parent_stylesheet;
let dom_rule = CSSRule::new_specific(&window, parent_stylesheet, new_rule);
diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs
index 25b99479b7a..d0996f04567 100644
--- a/components/script/dom/cssstyledeclaration.rs
+++ b/components/script/dom/cssstyledeclaration.rs
@@ -18,6 +18,7 @@ use servo_url::ServoUrl;
use std::ascii::AsciiExt;
use std::sync::Arc;
use style::attr::AttrValue;
+use style::parser::LengthParsingMode;
use style::properties::{Importance, PropertyDeclarationBlock, PropertyId, LonghandId, ShorthandId};
use style::properties::{parse_one_declaration, parse_style_attribute};
use style::selector_parser::PseudoElement;
@@ -255,9 +256,12 @@ impl CSSStyleDeclaration {
// Step 6
let window = self.owner.window();
+ let quirks_mode = window.Document().quirks_mode();
let result =
parse_one_declaration(id, &value, &self.owner.base_url(),
- window.css_error_reporter());
+ window.css_error_reporter(),
+ LengthParsingMode::Default,
+ quirks_mode);
// Step 7
let parsed = match result {
@@ -433,11 +437,13 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
return Err(Error::NoModificationAllowed);
}
+ let quirks_mode = window.Document().quirks_mode();
self.owner.mutate_associated_block(|mut pdb, mut _changed| {
// Step 3
*pdb = parse_style_attribute(&value,
&self.owner.base_url(),
- window.css_error_reporter());
+ window.css_error_reporter(),
+ quirks_mode);
});
Ok(())
diff --git a/components/script/dom/csssupportsrule.rs b/components/script/dom/csssupportsrule.rs
index 7ba3a24d038..86aedf10864 100644
--- a/components/script/dom/csssupportsrule.rs
+++ b/components/script/dom/csssupportsrule.rs
@@ -14,9 +14,9 @@ use dom::cssstylesheet::CSSStyleSheet;
use dom::window::Window;
use dom_struct::dom_struct;
use std::sync::Arc;
-use style::parser::ParserContext;
+use style::parser::{LengthParsingMode, ParserContext};
use style::shared_lock::{Locked, ToCssWithGuard};
-use style::stylesheets::SupportsRule;
+use style::stylesheets::{CssRuleType, SupportsRule};
use style::supports::SupportsCondition;
use style_traits::ToCss;
@@ -61,7 +61,10 @@ impl CSSSupportsRule {
let global = self.global();
let win = global.as_window();
let url = win.Document().url();
- let context = ParserContext::new_for_cssom(&url, win.css_error_reporter());
+ let quirks_mode = win.Document().quirks_mode();
+ let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports),
+ LengthParsingMode::Default,
+ quirks_mode);
let enabled = cond.eval(&context);
let mut guard = self.cssconditionrule.shared_lock().write();
let rule = self.supportsrule.write_with(&mut guard);
diff --git a/components/script/dom/dissimilaroriginlocation.rs b/components/script/dom/dissimilaroriginlocation.rs
index b4cd2d84e5d..7ea2e3efc3c 100644
--- a/components/script/dom/dissimilaroriginlocation.rs
+++ b/components/script/dom/dissimilaroriginlocation.rs
@@ -12,6 +12,7 @@ use dom::bindings::str::DOMString;
use dom::bindings::str::USVString;
use dom::dissimilaroriginwindow::DissimilarOriginWindow;
use dom_struct::dom_struct;
+use servo_url::MutableOrigin;
/// Represents a dissimilar-origin `Location` that exists in another script thread.
///
@@ -43,6 +44,11 @@ impl DissimilarOriginLocation {
window,
DissimilarOriginLocationBinding::Wrap)
}
+
+ #[allow(dead_code)]
+ pub fn origin(&self) -> &MutableOrigin {
+ self.window.origin()
+ }
}
impl DissimilarOriginLocationMethods for DissimilarOriginLocation {
diff --git a/components/script/dom/dissimilaroriginwindow.rs b/components/script/dom/dissimilaroriginwindow.rs
index 0f3cbd06df0..4188f51f0e5 100644
--- a/components/script/dom/dissimilaroriginwindow.rs
+++ b/components/script/dom/dissimilaroriginwindow.rs
@@ -19,6 +19,7 @@ use js::jsval::{JSVal, UndefinedValue};
use msg::constellation_msg::PipelineId;
use script_traits::ScriptMsg as ConstellationMsg;
use servo_url::ImmutableOrigin;
+use servo_url::MutableOrigin;
use servo_url::ServoUrl;
/// Represents a dissimilar-origin `Window` that exists in another script thread.
@@ -56,12 +57,18 @@ impl DissimilarOriginWindow {
global_to_clone_from.constellation_chan().clone(),
global_to_clone_from.scheduler_chan().clone(),
global_to_clone_from.resource_threads().clone(),
- timer_event_chan),
+ timer_event_chan,
+ global_to_clone_from.origin().clone()),
browsing_context: JS::from_ref(browsing_context),
location: MutNullableJS::new(None),
};
unsafe { DissimilarOriginWindowBinding::Wrap(cx, win) }
}
+
+ #[allow(dead_code)]
+ pub fn origin(&self) -> &MutableOrigin {
+ self.globalscope.origin()
+ }
}
impl DissimilarOriginWindowMethods for DissimilarOriginWindow {
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index ee79d710563..06b8f7596cf 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -93,7 +93,6 @@ use dom_struct::dom_struct;
use encoding::EncodingRef;
use encoding::all::UTF_8;
use euclid::point::Point2D;
-use gfx_traits::ScrollRootId;
use html5ever_atoms::{LocalName, QualName};
use hyper::header::{Header, SetCookie};
use hyper_serde::Serde;
@@ -143,6 +142,7 @@ use time;
use timers::OneshotTimerCallback;
use url::Host;
use url::percent_encoding::percent_decode;
+use webrender_traits::ClipId;
/// The number of times we are allowed to see spurious `requestAnimationFrame()` calls before
/// falling back to fake ones.
@@ -492,6 +492,7 @@ impl Document {
// FIXME: This should check the dirty bit on the document,
// not the document element. Needs some layout changes to make
// that workable.
+ self.stylesheets_changed_since_reflow.get() ||
match self.GetDocumentElement() {
Some(root) => {
root.upcast::<Node>().has_dirty_descendants() ||
@@ -541,7 +542,7 @@ impl Document {
self.quirks_mode.set(mode);
if mode == QuirksMode::Quirks {
- self.window.layout_chan().send(Msg::SetQuirksMode).unwrap();
+ self.window.layout_chan().send(Msg::SetQuirksMode(mode)).unwrap();
}
}
@@ -699,9 +700,11 @@ impl Document {
if let Some((x, y)) = point {
// Step 3
+ let global_scope = self.window.upcast::<GlobalScope>();
+ let webrender_pipeline_id = global_scope.pipeline_id().to_webrender();
self.window.perform_a_scroll(x,
y,
- ScrollRootId::root(),
+ ClipId::root_scroll_node(webrender_pipeline_id),
ScrollBehavior::Instant,
target.r());
}
@@ -2360,7 +2363,7 @@ impl Document {
if attr.local_name() == &local_name!("width") ||
attr.local_name() == &local_name!("height") {
entry.hint |= RESTYLE_SELF;
- }
+ }
let mut snapshot = entry.snapshot.as_mut().unwrap();
if snapshot.attrs.is_none() {
@@ -2772,7 +2775,14 @@ impl DocumentMethods for Document {
if self.is_html_document {
local_name.make_ascii_lowercase();
}
- let name = QualName::new(ns!(html), LocalName::from(local_name));
+
+ let ns = if self.is_html_document || self.content_type == "application/xhtml+xml" {
+ ns!(html)
+ } else {
+ ns!()
+ };
+
+ let name = QualName::new(ns, LocalName::from(local_name));
Ok(Element::create(name, None, self, ElementCreator::ScriptCreated))
}
diff --git a/components/script/dom/dommatrixreadonly.rs b/components/script/dom/dommatrixreadonly.rs
index 4f6331e0dd7..875e8e6f42c 100644
--- a/components/script/dom/dommatrixreadonly.rs
+++ b/components/script/dom/dommatrixreadonly.rs
@@ -37,7 +37,7 @@ impl DOMMatrixReadOnly {
reflector_: Reflector::new(),
matrix: DOMRefCell::new(matrix),
is2D: Cell::new(is2D),
- }
+ }
}
// https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-dommatrixreadonly
diff --git a/components/script/dom/domrectlist.rs b/components/script/dom/domrectlist.rs
deleted file mode 100644
index a7d99b99448..00000000000
--- a/components/script/dom/domrectlist.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-use dom::bindings::codegen::Bindings::DOMRectListBinding;
-use dom::bindings::codegen::Bindings::DOMRectListBinding::DOMRectListMethods;
-use dom::bindings::js::{JS, Root};
-use dom::bindings::reflector::{Reflector, reflect_dom_object};
-use dom::domrect::DOMRect;
-use dom::window::Window;
-use dom_struct::dom_struct;
-
-#[dom_struct]
-pub struct DOMRectList {
- reflector_: Reflector,
- rects: Vec<JS<DOMRect>>,
-}
-
-impl DOMRectList {
- fn new_inherited<T>(rects: T) -> DOMRectList
- where T: Iterator<Item = Root<DOMRect>>
- {
- DOMRectList {
- reflector_: Reflector::new(),
- rects: rects.map(|r| JS::from_ref(&*r)).collect(),
- }
- }
-
- pub fn new<T>(window: &Window, rects: T) -> Root<DOMRectList>
- where T: Iterator<Item = Root<DOMRect>>
- {
- reflect_dom_object(box DOMRectList::new_inherited(rects),
- window,
- DOMRectListBinding::Wrap)
- }
-}
-
-impl DOMRectListMethods for DOMRectList {
- // https://drafts.fxtf.org/geometry/#dom-domrectlist-length
- fn Length(&self) -> u32 {
- self.rects.len() as u32
- }
-
- // https://drafts.fxtf.org/geometry/#dom-domrectlist-item
- fn Item(&self, index: u32) -> Option<Root<DOMRect>> {
- let rects = &self.rects;
- if index < rects.len() as u32 {
- Some(Root::from_ref(&*rects[index as usize]))
- } else {
- None
- }
- }
-
- // check-tidy: no specs after this line
- fn IndexedGetter(&self, index: u32) -> Option<Root<DOMRect>> {
- self.Item(index)
- }
-}
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 4b3a6010a9a..d6974fb9075 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -34,7 +34,6 @@ use dom::create::create_element;
use dom::document::{Document, LayoutDocumentHelpers};
use dom::documentfragment::DocumentFragment;
use dom::domrect::DOMRect;
-use dom::domrectlist::DOMRectList;
use dom::domtokenlist::DOMTokenList;
use dom::event::Event;
use dom::eventtarget::EventTarget;
@@ -86,7 +85,7 @@ use net_traits::request::CorsSettings;
use ref_filter_map::ref_filter_map;
use script_layout_interface::message::ReflowQueryType;
use script_thread::Runnable;
-use selectors::matching::{ElementSelectorFlags, StyleRelations, matches};
+use selectors::matching::{ElementSelectorFlags, StyleRelations, matches_selector_list};
use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
use selectors::parser::{AttrSelector, NamespaceConstraint};
use servo_atoms::Atom;
@@ -468,7 +467,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::FontFamily(
- font_family::computed_value::T(vec![
+ font_family::SpecifiedValue::Values(vec![
font_family::computed_value::FontFamily::from_atom(
font_family)]))));
}
@@ -561,7 +560,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
}
LengthOrPercentageOrAuto::Length(length) => {
let width_value = specified::LengthOrPercentageOrAuto::Length(
- specified::NoCalcLength::Absolute(length));
+ specified::NoCalcLength::Absolute(specified::AbsoluteLength::Px(length.to_f32_px())));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Width(width_value)));
@@ -590,7 +589,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
}
LengthOrPercentageOrAuto::Length(length) => {
let height_value = specified::LengthOrPercentageOrAuto::Length(
- specified::NoCalcLength::Absolute(length));
+ specified::NoCalcLength::Absolute(specified::AbsoluteLength::Px(length.to_f32_px())));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Height(height_value)));
@@ -649,16 +648,16 @@ impl LayoutElementHelpers for LayoutJS<Element> {
let width_value = specified::BorderWidth::from_length(specified::Length::from_px(border as f32));
hints.push(from_declaration(
shared_lock,
- PropertyDeclaration::BorderTopWidth(Box::new(width_value.clone()))));
+ PropertyDeclaration::BorderTopWidth(width_value.clone())));
hints.push(from_declaration(
shared_lock,
- PropertyDeclaration::BorderLeftWidth(Box::new(width_value.clone()))));
+ PropertyDeclaration::BorderLeftWidth(width_value.clone())));
hints.push(from_declaration(
shared_lock,
- PropertyDeclaration::BorderBottomWidth(Box::new(width_value.clone()))));
+ PropertyDeclaration::BorderBottomWidth(width_value.clone())));
hints.push(from_declaration(
shared_lock,
- PropertyDeclaration::BorderRightWidth(Box::new(width_value))));
+ PropertyDeclaration::BorderRightWidth(width_value)));
}
}
@@ -780,7 +779,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
#[inline]
#[allow(unsafe_code)]
fn insert_selector_flags(&self, flags: ElementSelectorFlags) {
- debug_assert!(thread_state::get() == thread_state::LAYOUT);
+ debug_assert!(thread_state::get().is_layout());
unsafe {
let f = &(*self.unsafe_get()).selector_flags;
f.set(f.get() | flags);
@@ -1632,17 +1631,16 @@ impl ElementMethods for Element {
}
// https://drafts.csswg.org/cssom-view/#dom-element-getclientrects
- fn GetClientRects(&self) -> Root<DOMRectList> {
+ fn GetClientRects(&self) -> Vec<Root<DOMRect>> {
let win = window_from_node(self);
let raw_rects = self.upcast::<Node>().content_boxes();
- let rects = raw_rects.iter().map(|rect| {
+ raw_rects.iter().map(|rect| {
DOMRect::new(win.upcast(),
rect.origin.x.to_f64_px(),
rect.origin.y.to_f64_px(),
rect.size.width.to_f64_px(),
rect.size.height.to_f64_px())
- });
- DOMRectList::new(&win, rects)
+ }).collect()
}
// https://drafts.csswg.org/cssom-view/#dom-element-getboundingclientrect
@@ -2050,7 +2048,7 @@ impl ElementMethods for Element {
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
Err(()) => Err(Error::Syntax),
Ok(selectors) => {
- Ok(matches(&selectors.0, &Root::from_ref(self), None))
+ Ok(matches_selector_list(&selectors.0, &Root::from_ref(self), None))
}
}
}
@@ -2068,7 +2066,7 @@ impl ElementMethods for Element {
let root = self.upcast::<Node>();
for element in root.inclusive_ancestors() {
if let Some(element) = Root::downcast::<Element>(element) {
- if matches(&selectors.0, &element, None)
+ if matches_selector_list(&selectors.0, &element, None)
{
return Ok(Some(element));
}
@@ -2198,7 +2196,8 @@ impl VirtualMethods for Element {
Arc::new(doc.style_shared_lock().wrap(parse_style_attribute(
&attr.value(),
&doc.base_url(),
- win.css_error_reporter())))
+ win.css_error_reporter(),
+ doc.quirks_mode())))
};
Some(block)
@@ -2599,7 +2598,7 @@ impl Element {
self.has_attribute(&local_name!("href"))
},
_ => false,
- }
+ }
}
/// Please call this method *only* for real click events
diff --git a/components/script/dom/gamepad.rs b/components/script/dom/gamepad.rs
new file mode 100644
index 00000000000..f9f28fc8c51
--- /dev/null
+++ b/components/script/dom/gamepad.rs
@@ -0,0 +1,206 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+use core::nonzero::NonZero;
+use dom::bindings::codegen::Bindings::GamepadBinding;
+use dom::bindings::codegen::Bindings::GamepadBinding::GamepadMethods;
+use dom::bindings::inheritance::Castable;
+use dom::bindings::js::{JS, Root};
+use dom::bindings::num::Finite;
+use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
+use dom::bindings::str::DOMString;
+use dom::event::Event;
+use dom::eventtarget::EventTarget;
+use dom::gamepadbuttonlist::GamepadButtonList;
+use dom::gamepadevent::{GamepadEvent, GamepadEventType};
+use dom::globalscope::GlobalScope;
+use dom::vrpose::VRPose;
+use dom_struct::dom_struct;
+use js::jsapi::{Heap, JSContext, JSObject};
+use js::typedarray::{Float64Array, CreateWith};
+use std::cell::Cell;
+use std::ptr;
+use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
+
+#[dom_struct]
+pub struct Gamepad {
+ reflector_: Reflector,
+ gamepad_id: u32,
+ id: String,
+ index: Cell<i32>,
+ connected: Cell<bool>,
+ timestamp: Cell<f64>,
+ mapping_type: String,
+ axes: Heap<*mut JSObject>,
+ buttons: JS<GamepadButtonList>,
+ pose: Option<JS<VRPose>>,
+ #[ignore_heap_size_of = "Defined in rust-webvr"]
+ hand: WebVRGamepadHand,
+ display_id: u32
+}
+
+impl Gamepad {
+ fn new_inherited(gamepad_id: u32,
+ id: String,
+ index: i32,
+ connected: bool,
+ timestamp: f64,
+ mapping_type: String,
+ axes: *mut JSObject,
+ buttons: &GamepadButtonList,
+ pose: Option<&VRPose>,
+ hand: WebVRGamepadHand,
+ display_id: u32) -> Gamepad {
+ Self {
+ reflector_: Reflector::new(),
+ gamepad_id: gamepad_id,
+ id: id,
+ index: Cell::new(index),
+ connected: Cell::new(connected),
+ timestamp: Cell::new(timestamp),
+ mapping_type: mapping_type,
+ axes: Heap::new(axes),
+ buttons: JS::from_ref(buttons),
+ pose: pose.map(JS::from_ref),
+ hand: hand,
+ display_id: display_id
+ }
+ }
+
+ #[allow(unsafe_code)]
+ pub fn new_from_vr(global: &GlobalScope,
+ index: i32,
+ data: &WebVRGamepadData,
+ state: &WebVRGamepadState) -> Root<Gamepad> {
+ let buttons = GamepadButtonList::new_from_vr(&global, &state.buttons);
+ let pose = VRPose::new(&global, &state.pose);
+ let cx = global.get_cx();
+ rooted!(in (cx) let mut axes = ptr::null_mut());
+ unsafe {
+ let _ = Float64Array::create(cx,
+ CreateWith::Slice(&state.axes),
+ axes.handle_mut());
+ }
+
+ reflect_dom_object(box Gamepad::new_inherited(state.gamepad_id,
+ data.name.clone(),
+ index,
+ state.connected,
+ state.timestamp,
+ "".into(),
+ axes.get(),
+ &buttons,
+ Some(&pose),
+ data.hand.clone(),
+ data.display_id),
+ global,
+ GamepadBinding::Wrap)
+
+ }
+}
+
+impl GamepadMethods for Gamepad {
+ // https://w3c.github.io/gamepad/#dom-gamepad-id
+ fn Id(&self) -> DOMString {
+ DOMString::from(self.id.clone())
+ }
+
+ // https://w3c.github.io/gamepad/#dom-gamepad-index
+ fn Index(&self) -> i32 {
+ self.index.get()
+ }
+
+ // https://w3c.github.io/gamepad/#dom-gamepad-connected
+ fn Connected(&self) -> bool {
+ self.connected.get()
+ }
+
+ // https://w3c.github.io/gamepad/#dom-gamepad-timestamp
+ fn Timestamp(&self) -> Finite<f64> {
+ Finite::wrap(self.timestamp.get())
+ }
+
+ // https://w3c.github.io/gamepad/#dom-gamepad-mapping
+ fn Mapping(&self) -> DOMString {
+ DOMString::from(self.mapping_type.clone())
+ }
+
+ #[allow(unsafe_code)]
+ // https://w3c.github.io/gamepad/#dom-gamepad-axes
+ unsafe fn Axes(&self, _cx: *mut JSContext) -> NonZero<*mut JSObject> {
+ NonZero::new(self.axes.get())
+ }
+
+ // https://w3c.github.io/gamepad/#dom-gamepad-buttons
+ fn Buttons(&self) -> Root<GamepadButtonList> {
+ Root::from_ref(&*self.buttons)
+ }
+
+ // https://w3c.github.io/gamepad/extensions.html#gamepadhand-enum
+ fn Hand(&self) -> DOMString {
+ let value = match self.hand {
+ WebVRGamepadHand::Unknown => "",
+ WebVRGamepadHand::Left => "left",
+ WebVRGamepadHand::Right => "right"
+ };
+ value.into()
+ }
+
+ // https://w3c.github.io/gamepad/extensions.html#dom-gamepad-pose
+ fn GetPose(&self) -> Option<Root<VRPose>> {
+ self.pose.as_ref().map(|p| Root::from_ref(&**p))
+ }
+
+ // https://w3c.github.io/webvr/spec/1.1/#gamepad-getvrdisplays-attribute
+ fn DisplayId(&self) -> u32 {
+ self.display_id
+ }
+}
+
+impl Gamepad {
+ #[allow(unsafe_code)]
+ pub fn update_from_vr(&self, state: &WebVRGamepadState) {
+ self.timestamp.set(state.timestamp);
+ unsafe {
+ let cx = self.global().get_cx();
+ typedarray!(in(cx) let axes: Float64Array = self.axes.get());
+ if let Ok(mut array) = axes {
+ array.update(&state.axes);
+ }
+ }
+ self.buttons.sync_from_vr(&state.buttons);
+ if let Some(ref pose) = self.pose {
+ pose.update(&state.pose);
+ }
+ self.update_connected(state.connected);
+ }
+
+ pub fn gamepad_id(&self) -> u32 {
+ self.gamepad_id
+ }
+
+ pub fn update_connected(&self, connected: bool) {
+ if self.connected.get() == connected {
+ return;
+ }
+ self.connected.set(connected);
+
+ let event_type = if connected {
+ GamepadEventType::Connected
+ } else {
+ GamepadEventType::Disconnected
+ };
+
+ self.notify_event(event_type);
+ }
+
+ pub fn update_index(&self, index: i32) {
+ self.index.set(index);
+ }
+
+ pub fn notify_event(&self, event_type: GamepadEventType) {
+ let event = GamepadEvent::new_with_type(&self.global(), event_type, &self);
+ event.upcast::<Event>().fire(self.global().as_window().upcast::<EventTarget>());
+ }
+}
diff --git a/components/script/dom/gamepadbutton.rs b/components/script/dom/gamepadbutton.rs
new file mode 100644
index 00000000000..ff0c7271e5b
--- /dev/null
+++ b/components/script/dom/gamepadbutton.rs
@@ -0,0 +1,61 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+use dom::bindings::codegen::Bindings::GamepadButtonBinding;
+use dom::bindings::codegen::Bindings::GamepadButtonBinding::GamepadButtonMethods;
+use dom::bindings::js::Root;
+use dom::bindings::num::Finite;
+use dom::bindings::reflector::{Reflector, reflect_dom_object};
+use dom::globalscope::GlobalScope;
+use dom_struct::dom_struct;
+use std::cell::Cell;
+
+#[dom_struct]
+pub struct GamepadButton {
+ reflector_: Reflector,
+ pressed: Cell<bool>,
+ touched: Cell<bool>,
+ value: Cell<f64>,
+}
+
+impl GamepadButton {
+ pub fn new_inherited(pressed: bool, touched: bool) -> GamepadButton {
+ Self {
+ reflector_: Reflector::new(),
+ pressed: Cell::new(pressed),
+ touched: Cell::new(touched),
+ value: Cell::new(0.0),
+ }
+ }
+
+ pub fn new(global: &GlobalScope, pressed: bool, touched: bool) -> Root<GamepadButton> {
+ reflect_dom_object(box GamepadButton::new_inherited(pressed, touched),
+ global,
+ GamepadButtonBinding::Wrap)
+ }
+}
+
+impl GamepadButtonMethods for GamepadButton {
+ // https://www.w3.org/TR/gamepad/#widl-GamepadButton-pressed
+ fn Pressed(&self) -> bool {
+ self.pressed.get()
+ }
+
+ // https://www.w3.org/TR/gamepad/#widl-GamepadButton-touched
+ fn Touched(&self) -> bool {
+ self.touched.get()
+ }
+
+ // https://www.w3.org/TR/gamepad/#widl-GamepadButton-value
+ fn Value(&self) -> Finite<f64> {
+ Finite::wrap(self.value.get())
+ }
+}
+
+impl GamepadButton {
+ pub fn update(&self, pressed: bool, touched: bool) {
+ self.pressed.set(pressed);
+ self.touched.set(touched);
+ }
+}
diff --git a/components/script/dom/gamepadbuttonlist.rs b/components/script/dom/gamepadbuttonlist.rs
new file mode 100644
index 00000000000..5ac25504009
--- /dev/null
+++ b/components/script/dom/gamepadbuttonlist.rs
@@ -0,0 +1,63 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+use dom::bindings::codegen::Bindings::GamepadButtonListBinding;
+use dom::bindings::codegen::Bindings::GamepadButtonListBinding::GamepadButtonListMethods;
+use dom::bindings::js::{JS, Root, RootedReference};
+use dom::bindings::reflector::{Reflector, reflect_dom_object};
+use dom::gamepadbutton::GamepadButton;
+use dom::globalscope::GlobalScope;
+use dom_struct::dom_struct;
+use webvr_traits::WebVRGamepadButton;
+
+// https://w3c.github.io/gamepad/#gamepadbutton-interface
+#[dom_struct]
+pub struct GamepadButtonList {
+ reflector_: Reflector,
+ list: Vec<JS<GamepadButton>>
+}
+
+impl GamepadButtonList {
+ #[allow(unrooted_must_root)]
+ fn new_inherited(list: &[&GamepadButton]) -> GamepadButtonList {
+ GamepadButtonList {
+ reflector_: Reflector::new(),
+ list: list.iter().map(|button| JS::from_ref(*button)).collect(),
+ }
+ }
+
+ pub fn new_from_vr(global: &GlobalScope, buttons: &[WebVRGamepadButton]) -> Root<GamepadButtonList> {
+ rooted_vec!(let list <- buttons.iter()
+ .map(|btn| GamepadButton::new(&global, btn.pressed, btn.touched)));
+
+ reflect_dom_object(box GamepadButtonList::new_inherited(list.r()),
+ global,
+ GamepadButtonListBinding::Wrap)
+ }
+
+ pub fn sync_from_vr(&self, vr_buttons: &[WebVRGamepadButton]) {
+ let mut index = 0;
+ for btn in vr_buttons {
+ self.list.get(index).as_ref().unwrap().update(btn.pressed, btn.touched);
+ index += 1;
+ }
+ }
+}
+
+impl GamepadButtonListMethods for GamepadButtonList {
+ // https://w3c.github.io/gamepad/#dom-gamepad-buttons
+ fn Length(&self) -> u32 {
+ self.list.len() as u32
+ }
+
+ // https://w3c.github.io/gamepad/#dom-gamepad-buttons
+ fn Item(&self, index: u32) -> Option<Root<GamepadButton>> {
+ self.list.get(index as usize).map(|button| Root::from_ref(&**button))
+ }
+
+ // https://w3c.github.io/gamepad/#dom-gamepad-buttons
+ fn IndexedGetter(&self, index: u32) -> Option<Root<GamepadButton>> {
+ self.Item(index)
+ }
+}
diff --git a/components/script/dom/gamepadevent.rs b/components/script/dom/gamepadevent.rs
new file mode 100644
index 00000000000..f6690981a57
--- /dev/null
+++ b/components/script/dom/gamepadevent.rs
@@ -0,0 +1,92 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+use dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMethods;
+use dom::bindings::codegen::Bindings::GamepadEventBinding;
+use dom::bindings::codegen::Bindings::GamepadEventBinding::GamepadEventMethods;
+use dom::bindings::error::Fallible;
+use dom::bindings::inheritance::Castable;
+use dom::bindings::js::{JS, Root};
+use dom::bindings::reflector::{DomObject, reflect_dom_object};
+use dom::bindings::str::DOMString;
+use dom::event::Event;
+use dom::gamepad::Gamepad;
+use dom::globalscope::GlobalScope;
+use dom::window::Window;
+use dom_struct::dom_struct;
+use servo_atoms::Atom;
+
+#[dom_struct]
+pub struct GamepadEvent {
+ event: Event,
+ gamepad: JS<Gamepad>,
+}
+
+pub enum GamepadEventType {
+ Connected,
+ Disconnected
+}
+
+impl GamepadEvent {
+ fn new_inherited(gamepad: &Gamepad) -> GamepadEvent {
+ GamepadEvent {
+ event: Event::new_inherited(),
+ gamepad: JS::from_ref(gamepad),
+ }
+ }
+
+ pub fn new(global: &GlobalScope,
+ type_: Atom,
+ bubbles: bool,
+ cancelable: bool,
+ gamepad: &Gamepad)
+ -> Root<GamepadEvent> {
+ let ev = reflect_dom_object(box GamepadEvent::new_inherited(&gamepad),
+ global,
+ GamepadEventBinding::Wrap);
+ {
+ let event = ev.upcast::<Event>();
+ event.init_event(type_, bubbles, cancelable);
+ }
+ ev
+ }
+
+ pub fn new_with_type(global: &GlobalScope, event_type: GamepadEventType, gamepad: &Gamepad)
+ -> Root<GamepadEvent> {
+ let name = match event_type {
+ GamepadEventType::Connected => "gamepadconnected",
+ GamepadEventType::Disconnected => "gamepaddisconnected"
+ };
+
+ GamepadEvent::new(&global,
+ name.into(),
+ false,
+ false,
+ &gamepad)
+ }
+
+ // https://w3c.github.io/gamepad/#gamepadevent-interface
+ pub fn Constructor(window: &Window,
+ type_: DOMString,
+ init: &GamepadEventBinding::GamepadEventInit)
+ -> Fallible<Root<GamepadEvent>> {
+ Ok(GamepadEvent::new(&window.global(),
+ Atom::from(type_),
+ init.parent.bubbles,
+ init.parent.cancelable,
+ &init.gamepad))
+ }
+}
+
+impl GamepadEventMethods for GamepadEvent {
+ // https://w3c.github.io/gamepad/#gamepadevent-interface
+ fn Gamepad(&self) -> Root<Gamepad> {
+ Root::from_ref(&*self.gamepad)
+ }
+
+ // https://dom.spec.whatwg.org/#dom-event-istrusted
+ fn IsTrusted(&self) -> bool {
+ self.event.IsTrusted()
+ }
+}
diff --git a/components/script/dom/gamepadlist.rs b/components/script/dom/gamepadlist.rs
new file mode 100644
index 00000000000..dd5bdd757d9
--- /dev/null
+++ b/components/script/dom/gamepadlist.rs
@@ -0,0 +1,61 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+use dom::bindings::cell::DOMRefCell;
+use dom::bindings::codegen::Bindings::GamepadListBinding;
+use dom::bindings::codegen::Bindings::GamepadListBinding::GamepadListMethods;
+use dom::bindings::js::{JS, Root};
+use dom::bindings::reflector::{Reflector, reflect_dom_object};
+use dom::gamepad::Gamepad;
+use dom::globalscope::GlobalScope;
+use dom_struct::dom_struct;
+
+// https://www.w3.org/TR/gamepad/
+#[dom_struct]
+pub struct GamepadList {
+ reflector_: Reflector,
+ list: DOMRefCell<Vec<JS<Gamepad>>>
+}
+
+impl GamepadList {
+ fn new_inherited(list: &[&Gamepad]) -> GamepadList {
+ GamepadList {
+ reflector_: Reflector::new(),
+ list: DOMRefCell::new(list.iter().map(|g| JS::from_ref(&**g)).collect())
+ }
+ }
+
+ pub fn new(global: &GlobalScope, list: &[&Gamepad]) -> Root<GamepadList> {
+ reflect_dom_object(box GamepadList::new_inherited(list),
+ global,
+ GamepadListBinding::Wrap)
+ }
+
+ pub fn add_if_not_exists(&self, gamepads: &[Root<Gamepad>]) {
+ for gamepad in gamepads {
+ if !self.list.borrow().iter().any(|g| g.gamepad_id() == gamepad.gamepad_id()) {
+ self.list.borrow_mut().push(JS::from_ref(&*gamepad));
+ // Ensure that the gamepad has the correct index
+ gamepad.update_index(self.list.borrow().len() as i32 - 1);
+ }
+ }
+ }
+}
+
+impl GamepadListMethods for GamepadList {
+ // https://w3c.github.io/gamepad/#dom-navigator-getgamepads
+ fn Length(&self) -> u32 {
+ self.list.borrow().len() as u32
+ }
+
+ // https://w3c.github.io/gamepad/#dom-navigator-getgamepads
+ fn Item(&self, index: u32) -> Option<Root<Gamepad>> {
+ self.list.borrow().get(index as usize).map(|gamepad| Root::from_ref(&**gamepad))
+ }
+
+ // https://w3c.github.io/gamepad/#dom-navigator-getgamepads
+ fn IndexedGetter(&self, index: u32) -> Option<Root<Gamepad>> {
+ self.Item(index)
+ }
+}
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index 73ba61e4557..931d1f576aa 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -38,7 +38,7 @@ use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use script_thread::{MainThreadScriptChan, RunnableWrapper, ScriptThread};
use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEvent};
use script_traits::{TimerEventId, TimerSchedulerMsg, TimerSource};
-use servo_url::ServoUrl;
+use servo_url::{MutableOrigin, ServoUrl};
use std::cell::Cell;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
@@ -92,6 +92,9 @@ pub struct GlobalScope {
resource_threads: ResourceThreads,
timers: OneshotTimers,
+
+ /// The origin of the globalscope
+ origin: MutableOrigin,
}
impl GlobalScope {
@@ -103,7 +106,8 @@ impl GlobalScope {
constellation_chan: IpcSender<ConstellationMsg>,
scheduler_chan: IpcSender<TimerSchedulerMsg>,
resource_threads: ResourceThreads,
- timer_event_chan: IpcSender<TimerEvent>)
+ timer_event_chan: IpcSender<TimerEvent>,
+ origin: MutableOrigin)
-> Self {
GlobalScope {
eventtarget: EventTarget::new_inherited(),
@@ -120,6 +124,7 @@ impl GlobalScope {
in_error_reporting_mode: Default::default(),
resource_threads: resource_threads,
timers: OneshotTimers::new(timer_event_chan, scheduler_chan),
+ origin: origin,
}
}
@@ -238,6 +243,11 @@ impl GlobalScope {
self.pipeline_id
}
+ /// Get the origin for this global scope
+ pub fn origin(&self) -> &MutableOrigin {
+ &self.origin
+ }
+
/// Get the [base url](https://html.spec.whatwg.org/multipage/#api-base-url)
/// for this global scope.
pub fn api_base_url(&self) -> ServoUrl {
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index 7cebebade0a..389cd87b064 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -423,6 +423,11 @@ impl HTMLImageElement {
};
let value = usemap_attr.value();
+
+ if value.len() == 0 || !value.is_char_boundary(1) {
+ return None
+ }
+
let (first, last) = value.split_at(1);
if first != "#" || last.len() == 0 {
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index db26905b3b4..baff4983504 100755
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -1117,7 +1117,7 @@ impl VirtualMethods for HTMLInputElement {
translated_y
);
if let Some(i) = index {
- self.textinput.borrow_mut().edit_point.index = i as usize;
+ self.textinput.borrow_mut().set_edit_point_index(i as usize);
// trigger redraw
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
event.PreventDefault();
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index d29a94a11f0..bf36d28b29d 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -24,6 +24,7 @@ use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use html5ever_atoms::LocalName;
use net_traits::ReferrerPolicy;
+use script_layout_interface::message::Msg;
use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg};
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
@@ -32,8 +33,9 @@ use std::default::Default;
use std::sync::Arc;
use style::attr::AttrValue;
use style::media_queries::parse_media_query_list;
+use style::parser::{LengthParsingMode, ParserContext as CssParserContext};
use style::str::HTML_SPACE_CHARACTERS;
-use style::stylesheets::Stylesheet;
+use style::stylesheets::{CssRuleType, Stylesheet};
use stylesheet_loader::{StylesheetLoader, StylesheetContextSource, StylesheetOwner};
unsafe_no_jsmanaged_fields!(Stylesheet);
@@ -96,8 +98,9 @@ impl HTMLLinkElement {
}
pub fn set_stylesheet(&self, s: Arc<Stylesheet>) {
- assert!(self.stylesheet.borrow().is_none()); // Useful for catching timing issues.
- *self.stylesheet.borrow_mut() = Some(s);
+ *self.stylesheet.borrow_mut() = Some(s.clone());
+ window_from_node(self).layout_chan().send(Msg::AddStylesheet(s)).unwrap();
+ document_from_node(self).invalidate_stylesheets();
}
pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
@@ -255,7 +258,7 @@ impl HTMLLinkElement {
}
// Step 2.
- let url = match document.base_url().join(href) {
+ let link_url = match document.base_url().join(href) {
Ok(url) => url,
Err(e) => {
debug!("Parsing url {} failed: {}", href, e);
@@ -276,7 +279,12 @@ impl HTMLLinkElement {
};
let mut css_parser = CssParser::new(&mq_str);
- let media = parse_media_query_list(&mut css_parser);
+ let win = document.window();
+ let doc_url = document.url();
+ let context = CssParserContext::new_for_cssom(&doc_url, win.css_error_reporter(), Some(CssRuleType::Media),
+ LengthParsingMode::Default,
+ document.quirks_mode());
+ let media = parse_media_query_list(&context, &mut css_parser);
let im_attribute = element.get_attribute(&ns!(), &local_name!("integrity"));
let integrity_val = im_attribute.r().map(|a| a.value());
@@ -292,7 +300,7 @@ impl HTMLLinkElement {
let loader = StylesheetLoader::for_element(self.upcast());
loader.load(StylesheetContextSource::LinkElement {
media: Some(media),
- }, url, cors_setting, integrity_metadata.to_owned());
+ }, link_url, cors_setting, integrity_metadata.to_owned());
}
fn handle_favicon_url(&self, rel: &str, href: &str, sizes: &Option<String>) {
diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs
index 8613f4c8cb0..62d7215e3df 100644
--- a/components/script/dom/htmlmetaelement.rs
+++ b/components/script/dom/htmlmetaelement.rs
@@ -24,6 +24,7 @@ use std::ascii::AsciiExt;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use style::attr::AttrValue;
+use style::media_queries::MediaList;
use style::str::HTML_SPACE_CHARACTERS;
use style::stylesheets::{Stylesheet, CssRule, CssRules, Origin};
use style::viewport::ViewportRule;
@@ -107,11 +108,12 @@ impl HTMLMetaElement {
shared_lock: shared_lock.clone(),
url_data: window_from_node(self).get_url(),
namespaces: Default::default(),
- media: Arc::new(shared_lock.wrap(Default::default())),
+ media: Arc::new(shared_lock.wrap(MediaList::empty())),
// Viewport constraints are always recomputed on resize; they don't need to
// force all styles to be recomputed.
dirty_on_viewport_size_change: AtomicBool::new(false),
disabled: AtomicBool::new(false),
+ quirks_mode: document.quirks_mode(),
}));
let doc = document_from_node(self);
doc.invalidate_stylesheets();
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index f13c0224b1a..d6679c5168c 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -34,11 +34,17 @@ use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode, Type as RequestType};
use network_listener::{NetworkListener, PreInvoke};
use servo_atoms::Atom;
+use servo_config::opts;
use servo_url::ServoUrl;
use std::ascii::AsciiExt;
use std::cell::Cell;
+use std::fs::File;
+use std::io::{Read, Write};
+use std::path::PathBuf;
+use std::process::{Command, Stdio};
use std::sync::{Arc, Mutex};
use style::str::{HTML_SPACE_CHARACTERS, StaticStringVec};
+use uuid::Uuid;
#[dom_struct]
pub struct HTMLScriptElement {
@@ -450,6 +456,49 @@ impl HTMLScriptElement {
}
}
+ fn unminify_js(&self, script: &mut ClassicScript) {
+ if !opts::get().unminify_js {
+ return;
+ }
+
+ match Command::new("js-beautify")
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .spawn() {
+ Err(_) => {
+ warn!("Failed to execute js-beautify. Will store unmodified script");
+ },
+ Ok(process) => {
+ let mut script_content = String::from(script.text.clone());
+ let _ = process.stdin.unwrap().write_all(script_content.as_bytes());
+ script_content.clear();
+ let _ = process.stdout.unwrap().read_to_string(&mut script_content);
+
+ script.text = DOMString::from(script_content);
+ },
+ }
+
+ let path = PathBuf::from(window_from_node(self).unminified_js_dir().unwrap());
+ let path = if script.external {
+ // External script.
+ let path_parts = script.url.path_segments().unwrap();
+ match path_parts.last() {
+ Some(script_name) => path.join(script_name),
+ None => path.join(Uuid::new_v4().to_string()),
+ }
+ } else {
+ // Inline script.
+ path.join(Uuid::new_v4().to_string())
+ };
+
+ debug!("script will be stored in {:?}", path);
+
+ match File::create(&path) {
+ Ok(mut file) => file.write_all(script.text.as_bytes()).unwrap(),
+ Err(why) => warn!("Could not store script {:?}", why),
+ }
+ }
+
/// https://html.spec.whatwg.org/multipage/#execute-the-script-block
pub fn execute(&self, result: Result<ClassicScript, NetworkError>) {
// Step 1.
@@ -458,7 +507,7 @@ impl HTMLScriptElement {
return;
}
- let script = match result {
+ let mut script = match result {
// Step 2.
Err(e) => {
warn!("error loading script {:?}", e);
@@ -469,6 +518,8 @@ impl HTMLScriptElement {
Ok(script) => script,
};
+ self.unminify_js(&mut script);
+
// Step 3.
let neutralized_doc = if script.external {
debug!("loading external script, url = {}", script.url);
diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs
index c3ef5767f2b..8905c3baa65 100644
--- a/components/script/dom/htmlstyleelement.rs
+++ b/components/script/dom/htmlstyleelement.rs
@@ -25,7 +25,8 @@ use script_layout_interface::message::Msg;
use std::cell::Cell;
use std::sync::Arc;
use style::media_queries::parse_media_query_list;
-use style::stylesheets::{Stylesheet, Origin};
+use style::parser::{LengthParsingMode, ParserContext as CssParserContext};
+use style::stylesheets::{CssRuleType, Stylesheet, Origin};
use stylesheet_loader::{StylesheetLoader, StylesheetOwner};
#[dom_struct]
@@ -39,6 +40,7 @@ pub struct HTMLStyleElement {
in_stack_of_open_elements: Cell<bool>,
pending_loads: Cell<u32>,
any_failed_load: Cell<bool>,
+ line_number: u64,
}
impl HTMLStyleElement {
@@ -54,6 +56,7 @@ impl HTMLStyleElement {
in_stack_of_open_elements: Cell::new(creator.is_parser_created()),
pending_loads: Cell::new(0),
any_failed_load: Cell::new(false),
+ line_number: creator.return_line_number(),
}
}
@@ -73,7 +76,7 @@ impl HTMLStyleElement {
assert!(node.is_in_doc());
let win = window_from_node(node);
- let url = win.get_url();
+ let doc = document_from_node(self);
let mq_attribute = element.get_attribute(&ns!(), &local_name!("media"));
let mq_str = match mq_attribute {
@@ -82,12 +85,21 @@ impl HTMLStyleElement {
};
let data = node.GetTextContent().expect("Element.textContent must be a string");
- let mq = parse_media_query_list(&mut CssParser::new(&mq_str));
+ let url = win.get_url();
+ let context = CssParserContext::new_for_cssom(&url,
+ win.css_error_reporter(),
+ Some(CssRuleType::Media),
+ LengthParsingMode::Default,
+ doc.quirks_mode());
let shared_lock = node.owner_doc().style_shared_lock().clone();
+ let mq = Arc::new(shared_lock.wrap(
+ parse_media_query_list(&context, &mut CssParser::new(&mq_str))));
let loader = StylesheetLoader::for_element(self.upcast());
- let sheet = Stylesheet::from_str(&data, url, Origin::Author, mq,
+ let sheet = Stylesheet::from_str(&data, win.get_url(), Origin::Author, mq,
shared_lock, Some(&loader),
- win.css_error_reporter());
+ win.css_error_reporter(),
+ doc.quirks_mode(),
+ self.line_number);
let sheet = Arc::new(sheet);
@@ -98,7 +110,6 @@ impl HTMLStyleElement {
win.layout_chan().send(Msg::AddStylesheet(sheet.clone())).unwrap();
*self.stylesheet.borrow_mut() = Some(sheet);
- let doc = document_from_node(self);
doc.invalidate_stylesheets();
}
diff --git a/components/script/dom/location.rs b/components/script/dom/location.rs
index 399e3748722..cac2322be82 100644
--- a/components/script/dom/location.rs
+++ b/components/script/dom/location.rs
@@ -13,7 +13,7 @@ use dom::globalscope::GlobalScope;
use dom::urlhelper::UrlHelper;
use dom::window::Window;
use dom_struct::dom_struct;
-use servo_url::ServoUrl;
+use servo_url::{MutableOrigin, ServoUrl};
#[dom_struct]
pub struct Location {
@@ -60,6 +60,11 @@ impl Location {
pub fn reload_without_origin_check(&self) {
self.window.load_url(self.get_url(), true, true, None);
}
+
+ #[allow(dead_code)]
+ pub fn origin(&self) -> &MutableOrigin {
+ self.window.origin()
+ }
}
impl LocationMethods for Location {
diff --git a/components/script/dom/medialist.rs b/components/script/dom/medialist.rs
index b403200983e..f2a2299d169 100644
--- a/components/script/dom/medialist.rs
+++ b/components/script/dom/medialist.rs
@@ -2,12 +2,12 @@
* 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/. */
-use core::default::Default;
use cssparser::Parser;
use dom::bindings::codegen::Bindings::MediaListBinding;
use dom::bindings::codegen::Bindings::MediaListBinding::MediaListMethods;
+use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use dom::bindings::js::{JS, Root};
-use dom::bindings::reflector::{Reflector, reflect_dom_object};
+use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::cssstylesheet::CSSStyleSheet;
use dom::window::Window;
@@ -15,7 +15,9 @@ use dom_struct::dom_struct;
use std::sync::Arc;
use style::media_queries::{MediaQuery, parse_media_query_list};
use style::media_queries::MediaList as StyleMediaList;
+use style::parser::{LengthParsingMode, ParserContext};
use style::shared_lock::{SharedRwLock, Locked};
+use style::stylesheets::CssRuleType;
use style_traits::ToCss;
#[dom_struct]
@@ -65,12 +67,19 @@ impl MediaListMethods for MediaList {
// Step 2
if value.is_empty() {
// Step 1
- *media_queries = StyleMediaList::default();
+ *media_queries = StyleMediaList::empty();
return;
}
// Step 3
let mut parser = Parser::new(&value);
- *media_queries = parse_media_query_list(&mut parser);
+ let global = self.global();
+ let win = global.as_window();
+ let url = win.get_url();
+ let quirks_mode = win.Document().quirks_mode();
+ let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media),
+ LengthParsingMode::Default,
+ quirks_mode);
+ *media_queries = parse_media_query_list(&context, &mut parser);
}
// https://drafts.csswg.org/cssom/#dom-medialist-length
@@ -99,7 +108,14 @@ impl MediaListMethods for MediaList {
fn AppendMedium(&self, medium: DOMString) {
// Step 1
let mut parser = Parser::new(&medium);
- let m = MediaQuery::parse(&mut parser);
+ let global = self.global();
+ let win = global.as_window();
+ let url = win.get_url();
+ let quirks_mode = win.Document().quirks_mode();
+ let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media),
+ LengthParsingMode::Default,
+ quirks_mode);
+ let m = MediaQuery::parse(&context, &mut parser);
// Step 2
if let Err(_) = m {
return;
@@ -120,7 +136,14 @@ impl MediaListMethods for MediaList {
fn DeleteMedium(&self, medium: DOMString) {
// Step 1
let mut parser = Parser::new(&medium);
- let m = MediaQuery::parse(&mut parser);
+ let global = self.global();
+ let win = global.as_window();
+ let url = win.get_url();
+ let quirks_mode = win.Document().quirks_mode();
+ let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media),
+ LengthParsingMode::Default,
+ quirks_mode);
+ let m = MediaQuery::parse(&context, &mut parser);
// Step 2
if let Err(_) = m {
return;
diff --git a/components/script/dom/mediaquerylist.rs b/components/script/dom/mediaquerylist.rs
index dafc7602794..b25e041f4ef 100644
--- a/components/script/dom/mediaquerylist.rs
+++ b/components/script/dom/mediaquerylist.rs
@@ -77,7 +77,7 @@ impl MediaQueryList {
if let Some(window_size) = self.document.window().window_size() {
let viewport_size = window_size.initial_viewport;
let device = Device::new(MediaType::Screen, viewport_size);
- self.media_query_list.evaluate(&device)
+ self.media_query_list.evaluate(&device, self.document.quirks_mode())
} else {
false
}
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 2cfcfc894ea..70d1f30bd4a 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -272,7 +272,6 @@ pub mod dompoint;
pub mod dompointreadonly;
pub mod domquad;
pub mod domrect;
-pub mod domrectlist;
pub mod domrectreadonly;
pub mod domstringmap;
pub mod domtokenlist;
@@ -290,6 +289,11 @@ pub mod filereadersync;
pub mod focusevent;
pub mod forcetouchevent;
pub mod formdata;
+pub mod gamepad;
+pub mod gamepadbutton;
+pub mod gamepadbuttonlist;
+pub mod gamepadevent;
+pub mod gamepadlist;
pub mod globalscope;
pub mod hashchangeevent;
pub mod headers;
diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs
index 118f53ac49b..32dd2900e17 100644
--- a/components/script/dom/navigator.rs
+++ b/components/script/dom/navigator.rs
@@ -8,6 +8,7 @@ use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::reflector::{Reflector, DomObject, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::bluetooth::Bluetooth;
+use dom::gamepadlist::GamepadList;
use dom::mimetypearray::MimeTypeArray;
use dom::navigatorinfo;
use dom::permissions::Permissions;
@@ -16,7 +17,6 @@ use dom::serviceworkercontainer::ServiceWorkerContainer;
use dom::vr::VR;
use dom::window::Window;
use dom_struct::dom_struct;
-use script_traits::WebVREventMsg;
#[dom_struct]
pub struct Navigator {
@@ -26,6 +26,7 @@ pub struct Navigator {
mime_types: MutNullableJS<MimeTypeArray>,
service_worker: MutNullableJS<ServiceWorkerContainer>,
vr: MutNullableJS<VR>,
+ gamepads: MutNullableJS<GamepadList>,
permissions: MutNullableJS<Permissions>,
}
@@ -38,6 +39,7 @@ impl Navigator {
mime_types: Default::default(),
service_worker: Default::default(),
vr: Default::default(),
+ gamepads: Default::default(),
permissions: Default::default(),
}
}
@@ -128,15 +130,19 @@ impl NavigatorMethods for Navigator {
self.vr.or_init(|| VR::new(&self.global()))
}
+ // https://www.w3.org/TR/gamepad/#navigator-interface-extension
+ fn GetGamepads(&self) -> Root<GamepadList> {
+ let root = self.gamepads.or_init(|| {
+ GamepadList::new(&self.global(), &[])
+ });
+
+ let vr_gamepads = self.Vr().get_gamepads();
+ root.add_if_not_exists(&vr_gamepads);
+ // TODO: Add not VR related gamepads
+ root
+ }
// https://w3c.github.io/permissions/#navigator-and-workernavigator-extension
fn Permissions(&self) -> Root<Permissions> {
self.permissions.or_init(|| Permissions::new(&self.global()))
}
}
-
-impl Navigator {
- pub fn handle_webvr_event(&self, event: WebVREventMsg) {
- self.vr.get().expect("Shouldn't arrive here with an empty VR instance")
- .handle_webvr_event(event);
- }
-}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index e21dfa2bee0..0384c4ed19d 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -68,7 +68,7 @@ use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddr
use script_layout_interface::message::Msg;
use script_traits::DocumentActivity;
use script_traits::UntrustedNodeAddress;
-use selectors::matching::matches;
+use selectors::matching::matches_selector_list;
use selectors::parser::SelectorList;
use servo_url::ServoUrl;
use std::borrow::ToOwned;
@@ -332,7 +332,7 @@ impl<'a> Iterator for QuerySelectorIterator {
// (instead of passing `None`)? Probably.
self.iterator.by_ref().filter_map(|node| {
if let Some(element) = Root::downcast(node) {
- if matches(selectors, &element, None) {
+ if matches_selector_list(selectors, &element, None) {
return Some(Root::upcast(element));
}
}
@@ -695,7 +695,7 @@ impl Node {
// Step 3.
Ok(selectors) => {
Ok(self.traverse_preorder().filter_map(Root::downcast).find(|element| {
- matches(&selectors.0, element, None)
+ matches_selector_list(&selectors.0, element, None)
}))
}
}
@@ -2383,7 +2383,7 @@ impl NodeMethods for Node {
// Step 2.
Node::namespace_to_string(Node::locate_namespace(self, prefix))
- }
+ }
// https://dom.spec.whatwg.org/#dom-node-isdefaultnamespace
fn IsDefaultNamespace(&self, namespace: Option<DOMString>) -> bool {
diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs
index 5c0983ccaa3..fae181f7d81 100644
--- a/components/script/dom/nodelist.rs
+++ b/components/script/dom/nodelist.rs
@@ -223,9 +223,9 @@ impl ChildrenList {
// by ChildrenMutation::replace().
unreachable!()
},
- (_, &[node, ..], _) => node,
- (_, &[], Some(next)) => next,
- (Some(prev), &[], None) => {
+ (_, added, _) if !added.is_empty() => added[0],
+ (_, _, Some(next)) => next,
+ (Some(prev), _, None) => {
list.last_index.set(index - 1u32);
prev
},
diff --git a/components/script/dom/treewalker.rs b/components/script/dom/treewalker.rs
index 24925b9f0d9..2409d65af4f 100644
--- a/components/script/dom/treewalker.rs
+++ b/components/script/dom/treewalker.rs
@@ -457,7 +457,7 @@ impl<'a> Iterator for &'a TreeWalker {
// will probably be using a native Rust filter,
// which cannot produce an Err result.
unreachable!()
- }
+ }
}
}
diff --git a/components/script/dom/vr.rs b/components/script/dom/vr.rs
index aea8230ac0e..9497405e8c9 100644
--- a/components/script/dom/vr.rs
+++ b/components/script/dom/vr.rs
@@ -5,12 +5,15 @@
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::VRBinding;
use dom::bindings::codegen::Bindings::VRBinding::VRMethods;
+use dom::bindings::codegen::Bindings::VRDisplayBinding::VRDisplayMethods;
use dom::bindings::error::Error;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::{DomObject, reflect_dom_object};
use dom::event::Event;
use dom::eventtarget::EventTarget;
+use dom::gamepad::Gamepad;
+use dom::gamepadevent::GamepadEventType;
use dom::globalscope::GlobalScope;
use dom::promise::Promise;
use dom::vrdisplay::VRDisplay;
@@ -18,22 +21,23 @@ use dom::vrdisplayevent::VRDisplayEvent;
use dom_struct::dom_struct;
use ipc_channel::ipc;
use ipc_channel::ipc::IpcSender;
-use script_traits::WebVREventMsg;
use std::rc::Rc;
-use webvr_traits::WebVRMsg;
-use webvr_traits::webvr;
+use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg};
+use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState};
#[dom_struct]
pub struct VR {
eventtarget: EventTarget,
- displays: DOMRefCell<Vec<JS<VRDisplay>>>
+ displays: DOMRefCell<Vec<JS<VRDisplay>>>,
+ gamepads: DOMRefCell<Vec<JS<Gamepad>>>
}
impl VR {
fn new_inherited() -> VR {
VR {
eventtarget: EventTarget::new_inherited(),
- displays: DOMRefCell::new(Vec::new())
+ displays: DOMRefCell::new(Vec::new()),
+ gamepads: DOMRefCell::new(Vec::new()),
}
}
@@ -95,10 +99,10 @@ impl VR {
self.global().as_window().webvr_thread()
}
- fn find_display(&self, display_id: u64) -> Option<Root<VRDisplay>> {
+ fn find_display(&self, display_id: u32) -> Option<Root<VRDisplay>> {
self.displays.borrow()
.iter()
- .find(|d| d.get_display_id() == display_id)
+ .find(|d| d.DisplayId() == display_id)
.map(|d| Root::from_ref(&**d))
}
@@ -116,7 +120,7 @@ impl VR {
}
}
- fn sync_display(&self, display: &webvr::VRDisplayData) -> Root<VRDisplay> {
+ fn sync_display(&self, display: &WebVRDisplayData) -> Root<VRDisplay> {
if let Some(existing) = self.find_display(display.display_id) {
existing.update_display(&display);
existing
@@ -127,35 +131,121 @@ impl VR {
}
}
- pub fn handle_webvr_event(&self, event: WebVREventMsg) {
- let WebVREventMsg::DisplayEvent(event) = event;
- match &event {
- &webvr::VRDisplayEvent::Connect(ref display) => {
+ fn handle_display_event(&self, event: WebVRDisplayEvent) {
+ match event {
+ WebVRDisplayEvent::Connect(ref display) => {
let display = self.sync_display(&display);
display.handle_webvr_event(&event);
- self.notify_event(&display, &event);
+ self.notify_display_event(&display, &event);
},
- &webvr::VRDisplayEvent::Disconnect(id) => {
+ WebVRDisplayEvent::Disconnect(id) => {
if let Some(display) = self.find_display(id) {
display.handle_webvr_event(&event);
- self.notify_event(&display, &event);
+ self.notify_display_event(&display, &event);
}
},
- &webvr::VRDisplayEvent::Activate(ref display, _) |
- &webvr::VRDisplayEvent::Deactivate(ref display, _) |
- &webvr::VRDisplayEvent::Blur(ref display) |
- &webvr::VRDisplayEvent::Focus(ref display) |
- &webvr::VRDisplayEvent::PresentChange(ref display, _) |
- &webvr::VRDisplayEvent::Change(ref display) => {
+ WebVRDisplayEvent::Activate(ref display, _) |
+ WebVRDisplayEvent::Deactivate(ref display, _) |
+ WebVRDisplayEvent::Blur(ref display) |
+ WebVRDisplayEvent::Focus(ref display) |
+ WebVRDisplayEvent::PresentChange(ref display, _) |
+ WebVRDisplayEvent::Change(ref display) => {
let display = self.sync_display(&display);
display.handle_webvr_event(&event);
}
};
}
- fn notify_event(&self, display: &VRDisplay, event: &webvr::VRDisplayEvent) {
+ fn handle_gamepad_event(&self, event: WebVRGamepadEvent) {
+ match event {
+ WebVRGamepadEvent::Connect(data, state) => {
+ if let Some(gamepad) = self.find_gamepad(state.gamepad_id) {
+ gamepad.update_from_vr(&state);
+ } else {
+ // new gamepad
+ self.sync_gamepad(Some(data), &state);
+ }
+ },
+ WebVRGamepadEvent::Disconnect(id) => {
+ if let Some(gamepad) = self.find_gamepad(id) {
+ gamepad.update_connected(false);
+ }
+ }
+ };
+ }
+
+ pub fn handle_webvr_event(&self, event: WebVREvent) {
+ match event {
+ WebVREvent::Display(event) => {
+ self.handle_display_event(event);
+ },
+ WebVREvent::Gamepad(event) => {
+ self.handle_gamepad_event(event);
+ }
+ };
+ }
+
+ pub fn handle_webvr_events(&self, events: Vec<WebVREvent>) {
+ for event in events {
+ self.handle_webvr_event(event);
+ }
+ }
+
+ fn notify_display_event(&self, display: &VRDisplay, event: &WebVRDisplayEvent) {
let event = VRDisplayEvent::new_from_webvr(&self.global(), &display, &event);
event.upcast::<Event>().fire(self.upcast());
}
}
+// Gamepad
+impl VR {
+ fn find_gamepad(&self, gamepad_id: u32) -> Option<Root<Gamepad>> {
+ self.gamepads.borrow()
+ .iter()
+ .find(|g| g.gamepad_id() == gamepad_id)
+ .map(|g| Root::from_ref(&**g))
+ }
+
+ fn sync_gamepad(&self, data: Option<WebVRGamepadData>, state: &WebVRGamepadState) {
+ if let Some(existing) = self.find_gamepad(state.gamepad_id) {
+ existing.update_from_vr(&state);
+ } else {
+ let index = self.gamepads.borrow().len();
+ let data = data.unwrap_or_default();
+ let root = Gamepad::new_from_vr(&self.global(),
+ index as i32,
+ &data,
+ &state);
+ self.gamepads.borrow_mut().push(JS::from_ref(&*root));
+ if state.connected {
+ root.notify_event(GamepadEventType::Connected);
+ }
+ }
+ }
+
+ // Gamepads are synced immediately in response to the API call.
+ // The current approach allows the to sample gamepad state multiple times per frame. This
+ // guarantees that the gamepads always have a valid state and can be very useful for
+ // motion capture or drawing applications.
+ pub fn get_gamepads(&self) -> Vec<Root<Gamepad>> {
+ if let Some(wevbr_sender) = self.webvr_thread() {
+ let (sender, receiver) = ipc::channel().unwrap();
+ let synced_ids = self.gamepads.borrow().iter().map(|g| g.gamepad_id()).collect();
+ wevbr_sender.send(WebVRMsg::GetGamepads(synced_ids, sender)).unwrap();
+ match receiver.recv().unwrap() {
+ Ok(gamepads) => {
+ // Sync displays
+ for gamepad in gamepads {
+ self.sync_gamepad(gamepad.0, &gamepad.1);
+ }
+ },
+ Err(_) => {}
+ }
+ }
+
+ // We can add other not VR related gamepad providers here
+ self.gamepads.borrow().iter()
+ .map(|g| Root::from_ref(&**g))
+ .collect()
+ }
+}
diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs
index c05276c2349..b9b65264c44 100644
--- a/components/script/dom/vrdisplay.rs
+++ b/components/script/dom/vrdisplay.rs
@@ -161,7 +161,7 @@ impl VRDisplayMethods for VRDisplay {
// https://w3c.github.io/webvr/#dom-vrdisplay-displayid
fn DisplayId(&self) -> u32 {
- self.display.borrow().display_id as u32
+ self.display.borrow().display_id
}
// https://w3c.github.io/webvr/#dom-vrdisplay-displayname
@@ -188,7 +188,7 @@ impl VRDisplayMethods for VRDisplay {
// If not presenting we fetch inmediante VRFrameData
let (sender, receiver) = ipc::channel().unwrap();
self.webvr_thread().send(WebVRMsg::GetFrameData(self.global().pipeline_id(),
- self.get_display_id(),
+ self.DisplayId(),
self.depth_near.get(),
self.depth_far.get(),
sender)).unwrap();
@@ -213,7 +213,7 @@ impl VRDisplayMethods for VRDisplay {
fn ResetPose(&self) {
let (sender, receiver) = ipc::channel().unwrap();
self.webvr_thread().send(WebVRMsg::ResetPose(self.global().pipeline_id(),
- self.get_display_id(),
+ self.DisplayId(),
sender)).unwrap();
if let Ok(data) = receiver.recv().unwrap() {
// Some VRDisplay data might change after calling ResetPose()
@@ -378,7 +378,7 @@ impl VRDisplayMethods for VRDisplay {
}
let api_sender = self.layer_ctx.get().unwrap().ipc_renderer();
- let display_id = self.display.borrow().display_id;
+ let display_id = self.display.borrow().display_id as u64;
let layer = self.layer.borrow();
let msg = VRCompositorCommand::SubmitFrame(display_id, layer.left_bounds, layer.right_bounds);
api_sender.send(CanvasMsg::WebVR(msg)).unwrap();
@@ -390,10 +390,6 @@ impl VRDisplay {
self.global().as_window().webvr_thread().expect("Shouldn't arrive here with WebVR disabled")
}
- pub fn get_display_id(&self) -> u64 {
- self.display.borrow().display_id
- }
-
pub fn update_display(&self, display: &WebVRDisplayData) {
*self.display.borrow_mut() = display.clone();
if let Some(ref stage) = display.stage_parameters {
@@ -447,7 +443,7 @@ impl VRDisplay {
let (sync_sender, sync_receiver) = ipc::channel().unwrap();
*self.frame_data_receiver.borrow_mut() = Some(sync_receiver);
- let display_id = self.display.borrow().display_id;
+ let display_id = self.display.borrow().display_id as u64;
let api_sender = self.layer_ctx.get().unwrap().ipc_renderer();
let js_sender = self.global().script_chan();
let address = Trusted::new(&*self);
@@ -497,7 +493,7 @@ impl VRDisplay {
*self.frame_data_receiver.borrow_mut() = None;
let api_sender = self.layer_ctx.get().unwrap().ipc_renderer();
- let display_id = self.display.borrow().display_id;
+ let display_id = self.display.borrow().display_id as u64;
let msg = VRCompositorCommand::Release(display_id);
api_sender.send(CanvasMsg::WebVR(msg)).unwrap();
}
diff --git a/components/script/dom/vrpose.rs b/components/script/dom/vrpose.rs
index 542059ca799..ee035e2a0f1 100644
--- a/components/script/dom/vrpose.rs
+++ b/components/script/dom/vrpose.rs
@@ -32,7 +32,9 @@ unsafe fn update_or_create_typed_array(cx: *mut JSContext,
match src {
Some(data) => {
if dst.get().is_null() {
- let _ = Float32Array::create(cx, CreateWith::Slice(data), dst.handle_mut());
+ rooted!(in (cx) let mut array = ptr::null_mut());
+ let _ = Float32Array::create(cx, CreateWith::Slice(data), array.handle_mut());
+ (*dst).set(array.get());
} else {
typedarray!(in(cx) let array: Float32Array = dst.get());
if let Ok(mut array) = array {
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index f13f7f02d9b..1826a877331 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -31,6 +31,7 @@ use dom::webglframebuffer::WebGLFramebuffer;
use dom::webglprogram::WebGLProgram;
use dom::webglrenderbuffer::WebGLRenderbuffer;
use dom::webglshader::WebGLShader;
+use dom::webglshaderprecisionformat::WebGLShaderPrecisionFormat;
use dom::webgltexture::{TexParameterValue, WebGLTexture};
use dom::webgluniformlocation::WebGLUniformLocation;
use dom::window::Window;
@@ -50,7 +51,7 @@ use webrender_traits;
use webrender_traits::{WebGLCommand, WebGLError, WebGLFramebufferBindingRequest, WebGLParameter};
use webrender_traits::WebGLError::*;
-type ImagePixelResult = Result<(Vec<u8>, Size2D<i32>), ()>;
+type ImagePixelResult = Result<(Vec<u8>, Size2D<i32>, bool), ()>;
pub const MAX_UNIFORM_AND_ATTRIBUTE_LEN: usize = 256;
macro_rules! handle_potential_webgl_error {
@@ -388,8 +389,17 @@ impl WebGLRenderingContext {
match (format, data_type) {
(TexFormat::RGBA, TexDataType::UnsignedByte) => pixels,
- (TexFormat::RGB, TexDataType::UnsignedByte) => pixels,
-
+ (TexFormat::RGB, TexDataType::UnsignedByte) => {
+ // Remove alpha channel
+ let pixel_count = pixels.len() / 4;
+ let mut rgb8 = Vec::<u8>::with_capacity(pixel_count * 3);
+ for rgba8 in pixels.chunks(4) {
+ rgb8.push(rgba8[0]);
+ rgb8.push(rgba8[1]);
+ rgb8.push(rgba8[2]);
+ }
+ rgb8
+ },
(TexFormat::RGBA, TexDataType::UnsignedShort4444) => {
let mut rgba4 = Vec::<u8>::with_capacity(pixel_count * 2);
for rgba8 in pixels.chunks(4) {
@@ -442,9 +452,9 @@ impl WebGLRenderingContext {
//
// Nontheless, since it's the error case, I'm not totally sure the
// complexity is worth it.
- let (pixels, size) = match source {
+ let (pixels, size, premultiplied) = match source {
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::ImageData(image_data) => {
- (image_data.get_data_array(), image_data.get_size())
+ (image_data.get_data_array(), image_data.get_size(), false)
},
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLImageElement(image) => {
let img_url = match image.get_url() {
@@ -471,7 +481,7 @@ impl WebGLRenderingContext {
byte_swap(&mut data);
- (data, size)
+ (data, size, false)
},
// TODO(emilio): Getting canvas data is implemented in CanvasRenderingContext2D,
// but we need to refactor it moving it to `HTMLCanvasElement` and support
@@ -479,7 +489,8 @@ impl WebGLRenderingContext {
ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLCanvasElement(canvas) => {
if let Some((mut data, size)) = canvas.fetch_all_data() {
byte_swap(&mut data);
- (data, size)
+ // Pixels got from Canvas have already alpha premultiplied
+ (data, size, true)
} else {
return Err(());
}
@@ -488,7 +499,7 @@ impl WebGLRenderingContext {
=> unimplemented!(),
};
- return Ok((pixels, size));
+ return Ok((pixels, size, premultiplied));
}
// TODO(emilio): Move this logic to a validator.
@@ -643,6 +654,51 @@ impl WebGLRenderingContext {
}
}
+ // Remove premultiplied alpha.
+ // This is only called when texImage2D is called using a canvas2d source and
+ // UNPACK_PREMULTIPLY_ALPHA_WEBGL is disabled. Pixels got from a canvas2D source
+ // are always RGBA8 with premultiplied alpha, so we don't have to worry about
+ // additional formats as happens in the premultiply_pixels method.
+ fn remove_premultiplied_alpha(&self, mut pixels: Vec<u8>) -> Vec<u8> {
+ for rgba in pixels.chunks_mut(4) {
+ let a = (rgba[3] as f32) / 255.0;
+ rgba[0] = (rgba[0] as f32 / a) as u8;
+ rgba[1] = (rgba[1] as f32 / a) as u8;
+ rgba[2] = (rgba[2] as f32 / a) as u8;
+ }
+ pixels
+ }
+
+ fn prepare_pixels(&self,
+ internal_format: TexFormat,
+ data_type: TexDataType,
+ width: u32,
+ height: u32,
+ unpacking_alignment: u32,
+ source_premultiplied: bool,
+ source_from_image_or_canvas: bool,
+ mut pixels: Vec<u8>) -> Vec<u8> {
+ let dest_premultiply = self.texture_unpacking_settings.get().contains(PREMULTIPLY_ALPHA);
+ if !source_premultiplied && dest_premultiply {
+ if source_from_image_or_canvas {
+ // When the pixels come from image or canvas or imagedata, use RGBA8 format
+ pixels = self.premultiply_pixels(TexFormat::RGBA, TexDataType::UnsignedByte, pixels);
+ } else {
+ pixels = self.premultiply_pixels(internal_format, data_type, pixels);
+ }
+ } else if source_premultiplied && !dest_premultiply {
+ pixels = self.remove_premultiplied_alpha(pixels);
+ }
+
+ if source_from_image_or_canvas {
+ pixels = self.rgba8_image_to_tex_image_data(internal_format, data_type, pixels);
+ }
+
+ // FINISHME: Consider doing premultiply and flip in a single mutable Vec.
+ self.flip_teximage_y(pixels, internal_format, data_type,
+ width as usize, height as usize, unpacking_alignment as usize)
+ }
+
fn tex_image_2d(&self,
texture: Root<WebGLTexture>,
target: TexImageTarget,
@@ -654,11 +710,6 @@ impl WebGLRenderingContext {
_border: u32,
unpacking_alignment: u32,
pixels: Vec<u8>) { // NB: pixels should NOT be premultipied
- // FINISHME: Consider doing premultiply and flip in a single mutable Vec.
- let pixels = self.premultiply_pixels(internal_format, data_type, pixels);
-
- let pixels = self.flip_teximage_y(pixels, internal_format, data_type,
- width as usize, height as usize, unpacking_alignment as usize);
// TexImage2D depth is always equal to 1
handle_potential_webgl_error!(self, texture.initialize(target,
@@ -704,7 +755,7 @@ impl WebGLRenderingContext {
format: TexFormat,
data_type: TexDataType,
unpacking_alignment: u32,
- pixels: Vec<u8>) { // NB: pixels should NOT be premultipied
+ pixels: Vec<u8>) {
// We have already validated level
let image_info = texture.image_info_for_target(&target, level);
@@ -723,12 +774,6 @@ impl WebGLRenderingContext {
return self.webgl_error(InvalidOperation);
}
- // FINISHME: Consider doing premultiply and flip in a single mutable Vec.
- let pixels = self.premultiply_pixels(format, data_type, pixels);
-
- let pixels = self.flip_teximage_y(pixels, format, data_type,
- width as usize, height as usize, unpacking_alignment as usize);
-
// Set the unpack alignment. For textures coming from arrays,
// this will be the current value of the context's
// GL_UNPACK_ALIGNMENT, while for textures from images or
@@ -1795,7 +1840,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// WebGl conformance expects error with null programs. Check tests in get-active-test.html
self.webgl_error(InvalidValue);
return None;
- }
+ }
};
match program.get_active_uniform(index) {
@@ -1822,7 +1867,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// WebGl conformance expects error with null programs. Check tests in get-active-test.html
self.webgl_error(InvalidValue);
return None;
- }
+ }
};
match program.get_active_attrib(index) {
@@ -1902,6 +1947,27 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
}
}
+ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
+ fn GetShaderPrecisionFormat(&self,
+ shader_type: u32,
+ precision_type: u32)
+ -> Option<Root<WebGLShaderPrecisionFormat>> {
+ let (sender, receiver) = webrender_traits::channel::msg_channel().unwrap();
+ self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::GetShaderPrecisionFormat(shader_type,
+ precision_type,
+ sender)))
+ .unwrap();
+ match receiver.recv().unwrap() {
+ Ok((range_min, range_max, precision)) => {
+ Some(WebGLShaderPrecisionFormat::new(self.global().as_window(), range_min, range_max, precision))
+ },
+ Err(error) => {
+ self.webgl_error(error);
+ None
+ }
+ }
+ }
+
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
fn GetUniformLocation(&self,
program: Option<&WebGLProgram>,
@@ -2819,8 +2885,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return Ok(self.webgl_error(InvalidOperation));
}
+ let pixels = self.prepare_pixels(format, data_type, width, height,
+ unpacking_alignment, false, false, buff);
+
self.tex_image_2d(texture, target, data_type, format,
- level, width, height, border, unpacking_alignment, buff);
+ level, width, height, border, unpacking_alignment, pixels);
Ok(())
}
@@ -2834,8 +2903,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
data_type: u32,
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>) -> Fallible<()> {
// Get pixels from image source
- let (pixels, size) = match self.get_image_pixels(source) {
- Ok((pixels, size)) => (pixels, size),
+ let (pixels, size, premultiplied) = match self.get_image_pixels(source) {
+ Ok((pixels, size, premultiplied)) => (pixels, size, premultiplied),
Err(_) => return Ok(()),
};
@@ -2858,7 +2927,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Err(_) => return Ok(()), // NB: The validator sets the correct error for us.
};
- let pixels = self.rgba8_image_to_tex_image_data(format, data_type, pixels);
+ let unpacking_alignment = 1;
+ let pixels = self.prepare_pixels(format, data_type, width, height,
+ unpacking_alignment, premultiplied, true, pixels);
self.tex_image_2d(texture, target, data_type, format,
level, width, height, border, 1, pixels);
@@ -2929,8 +3000,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return Ok(self.webgl_error(InvalidOperation));
}
+ let unpacking_alignment = self.texture_unpacking_alignment.get();
+ let pixels = self.prepare_pixels(format, data_type, width, height,
+ unpacking_alignment, false, false, buff);
+
self.tex_sub_image_2d(texture, target, level, xoffset, yoffset,
- width, height, format, data_type, unpacking_alignment, buff);
+ width, height, format, data_type, unpacking_alignment, pixels);
Ok(())
}
@@ -2944,8 +3019,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
data_type: u32,
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>)
-> Fallible<()> {
- let (pixels, size) = match self.get_image_pixels(source) {
- Ok((pixels, size)) => (pixels, size),
+ let (pixels, size, premultiplied) = match self.get_image_pixels(source) {
+ Ok((pixels, size, premultiplied)) => (pixels, size, premultiplied),
Err(_) => return Ok(()),
};
@@ -2966,7 +3041,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Err(_) => return Ok(()), // NB: The validator sets the correct error for us.
};
- let pixels = self.rgba8_image_to_tex_image_data(format, data_type, pixels);
+ let unpacking_alignment = 1;
+ let pixels = self.prepare_pixels(format, data_type, width, height,
+ unpacking_alignment, premultiplied, true, pixels);
self.tex_sub_image_2d(texture, target, level, xoffset, yoffset,
width, height, format, data_type, 1, pixels);
diff --git a/components/script/dom/webglshader.rs b/components/script/dom/webglshader.rs
index 1526b5303f7..b66151bf353 100644
--- a/components/script/dom/webglshader.rs
+++ b/components/script/dom/webglshader.rs
@@ -106,9 +106,11 @@ impl WebGLShader {
}
if let Some(ref source) = *self.source.borrow() {
+ let mut params = BuiltInResources::default();
+ params.FragmentPrecisionHigh = 1;
let validator = ShaderValidator::for_webgl(self.gl_type,
SHADER_OUTPUT_FORMAT,
- &BuiltInResources::default()).unwrap();
+ &params).unwrap();
match validator.compile_and_translate(&[source]) {
Ok(translated_source) => {
debug!("Shader translated: {}", translated_source);
diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl
index 498d4a634d4..efe1d57b038 100644
--- a/components/script/dom/webidls/CSSStyleDeclaration.webidl
+++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl
@@ -33,6 +33,8 @@ interface CSSStyleDeclaration {
};
partial interface CSSStyleDeclaration {
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString all;
+
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString background;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundColor;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-color;
@@ -281,6 +283,8 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontVariant;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-variant;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontVariantCaps;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-variant-caps;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontWeight;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-weight;
diff --git a/components/script/dom/webidls/Element.webidl b/components/script/dom/webidls/Element.webidl
index 1662dda36d6..c099b2a04ae 100644
--- a/components/script/dom/webidls/Element.webidl
+++ b/components/script/dom/webidls/Element.webidl
@@ -81,7 +81,8 @@ interface Element : Node {
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-element-interface
partial interface Element {
- DOMRectList getClientRects();
+ sequence<DOMRect> getClientRects();
+ [NewObject]
DOMRect getBoundingClientRect();
void scroll(optional ScrollToOptions options);
diff --git a/components/script/dom/webidls/Gamepad.webidl b/components/script/dom/webidls/Gamepad.webidl
new file mode 100644
index 00000000000..0f666a495cf
--- /dev/null
+++ b/components/script/dom/webidls/Gamepad.webidl
@@ -0,0 +1,26 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+// https://w3c.github.io/gamepad/#gamepad-interface
+[Pref="dom.gamepad.enabled"]
+interface Gamepad {
+ readonly attribute DOMString id;
+ readonly attribute long index;
+ readonly attribute boolean connected;
+ readonly attribute DOMHighResTimeStamp timestamp;
+ readonly attribute DOMString mapping;
+ readonly attribute Float64Array axes;
+ [SameObject] readonly attribute GamepadButtonList buttons;
+};
+
+// https://w3c.github.io/gamepad/extensions.html#dom-gamepad
+partial interface Gamepad {
+ readonly attribute DOMString hand;
+ readonly attribute VRPose? pose;
+};
+
+// https://w3c.github.io/webvr/spec/1.1/#interface-gamepad
+partial interface Gamepad {
+ readonly attribute unsigned long displayId;
+};
diff --git a/components/script/dom/webidls/GamepadButton.webidl b/components/script/dom/webidls/GamepadButton.webidl
new file mode 100644
index 00000000000..2fa04c8ba3c
--- /dev/null
+++ b/components/script/dom/webidls/GamepadButton.webidl
@@ -0,0 +1,11 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+// https://w3c.github.io/gamepad/#gamepadbutton-interface
+[Pref="dom.gamepad.enabled"]
+interface GamepadButton {
+ readonly attribute boolean pressed;
+ readonly attribute boolean touched;
+ readonly attribute double value;
+};
diff --git a/components/script/dom/webidls/DOMRectList.webidl b/components/script/dom/webidls/GamepadButtonList.webidl
index dfb33639c93..c8fb75a4350 100644
--- a/components/script/dom/webidls/DOMRectList.webidl
+++ b/components/script/dom/webidls/GamepadButtonList.webidl
@@ -2,10 +2,9 @@
* 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/. */
-// http://dev.w3.org/fxtf/geometry/#DOMRectList
-[NoInterfaceObject, Exposed=(Window,Worker)]
-//[ArrayClass]
-interface DOMRectList {
+// https://w3c.github.io/gamepad/#dom-gamepad-buttons
+[Pref="dom.gamepad.enabled"]
+interface GamepadButtonList {
+ getter GamepadButton? item(unsigned long index);
readonly attribute unsigned long length;
- getter DOMRect? item(unsigned long index);
};
diff --git a/components/script/dom/webidls/GamepadEvent.webidl b/components/script/dom/webidls/GamepadEvent.webidl
new file mode 100644
index 00000000000..ea40fd4261c
--- /dev/null
+++ b/components/script/dom/webidls/GamepadEvent.webidl
@@ -0,0 +1,13 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+// https://w3c.github.io/gamepad/#gamepadevent-interface
+[Pref="dom.gamepad.enabled", Constructor(DOMString type, GamepadEventInit eventInitDict)]
+interface GamepadEvent : Event {
+ readonly attribute Gamepad gamepad;
+};
+
+dictionary GamepadEventInit : EventInit {
+ required Gamepad gamepad;
+};
diff --git a/components/script/dom/webidls/GamepadList.webidl b/components/script/dom/webidls/GamepadList.webidl
new file mode 100644
index 00000000000..2d99e4e8f3c
--- /dev/null
+++ b/components/script/dom/webidls/GamepadList.webidl
@@ -0,0 +1,10 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+// https://w3c.github.io/gamepad/#navigator-interface-extension
+[Pref="dom.gamepad.enabled"]
+interface GamepadList {
+ getter Gamepad? item(unsigned long index);
+ readonly attribute unsigned long length;
+};
diff --git a/components/script/dom/webidls/Navigator.webidl b/components/script/dom/webidls/Navigator.webidl
index e04616ef40f..338753d6261 100644
--- a/components/script/dom/webidls/Navigator.webidl
+++ b/components/script/dom/webidls/Navigator.webidl
@@ -68,3 +68,8 @@ partial interface Navigator {
partial interface Navigator {
[Pref="dom.permissions.enabled"] readonly attribute Permissions permissions;
};
+
+// https://w3c.github.io/gamepad/#navigator-interface-extension
+partial interface Navigator {
+ [Pref="dom.gamepad.enabled"] GamepadList getGamepads();
+};
diff --git a/components/script/dom/webidls/Range.webidl b/components/script/dom/webidls/Range.webidl
index c40f2ecb161..1daf2d8182f 100644
--- a/components/script/dom/webidls/Range.webidl
+++ b/components/script/dom/webidls/Range.webidl
@@ -82,6 +82,7 @@ partial interface Range {
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-range-interface
partial interface Range {
- // DOMRectList? getClientRects();
+ // sequence<DOMRect> getClientRects();
+ // [NewObject]
// DOMRect getBoundingClientRect();
};
diff --git a/components/script/dom/webidls/WebGLRenderingContext.webidl b/components/script/dom/webidls/WebGLRenderingContext.webidl
index ef0be0f9465..0d4c14a05df 100644
--- a/components/script/dom/webidls/WebGLRenderingContext.webidl
+++ b/components/script/dom/webidls/WebGLRenderingContext.webidl
@@ -595,7 +595,7 @@ interface WebGLRenderingContextBase
DOMString? getProgramInfoLog(WebGLProgram? program);
//any getRenderbufferParameter(GLenum target, GLenum pname);
any getShaderParameter(WebGLShader? shader, GLenum pname);
- //WebGLShaderPrecisionFormat? getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
+ WebGLShaderPrecisionFormat? getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
DOMString? getShaderInfoLog(WebGLShader? shader);
DOMString? getShaderSource(WebGLShader? shader);
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 6a264c86d6b..6b8857b81b1 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -52,7 +52,6 @@ use dom::testrunner::TestRunner;
use dom_struct::dom_struct;
use euclid::{Point2D, Rect, Size2D};
use fetch;
-use gfx_traits::ScrollRootId;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use js::jsapi::{HandleObject, HandleValue, JSAutoCompartment, JSContext};
@@ -86,13 +85,15 @@ use servo_atoms::Atom;
use servo_config::opts;
use servo_config::prefs::PREFS;
use servo_geometry::{f32_rect_to_au_rect, max_rect};
-use servo_url::{ImmutableOrigin, ServoUrl};
+use servo_url::{Host, MutableOrigin, ImmutableOrigin, ServoUrl};
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::Cell;
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry;
use std::default::Default;
+use std::env;
+use std::fs;
use std::io::{Write, stderr, stdout};
use std::mem;
use std::rc::Rc;
@@ -103,10 +104,12 @@ use std::sync::mpsc::TryRecvError::{Disconnected, Empty};
use style::context::ReflowGoal;
use style::error_reporting::ParseErrorReporter;
use style::media_queries;
+use style::parser::{LengthParsingMode, ParserContext as CssParserContext};
use style::properties::PropertyId;
use style::properties::longhands::overflow_x;
use style::selector_parser::PseudoElement;
use style::str::HTML_SPACE_CHARACTERS;
+use style::stylesheets::CssRuleType;
use task_source::dom_manipulation::DOMManipulationTaskSource;
use task_source::file_reading::FileReadingTaskSource;
use task_source::history_traversal::HistoryTraversalTaskSource;
@@ -118,6 +121,7 @@ use timers::{IsInterval, TimerCallback};
use tinyfiledialogs::{self, MessageBoxIcon};
use url::Position;
use webdriver_handlers::jsval_to_webdriver;
+use webrender_traits::ClipId;
use webvr_traits::WebVRMsg;
/// Current state of the window object
@@ -265,6 +269,10 @@ pub struct Window {
/// to ensure that the element can be marked dirty when the image data becomes
/// available at some point in the future.
pending_layout_images: DOMRefCell<HashMap<PendingImageId, Vec<JS<Node>>>>,
+
+ /// Directory to store unminified scripts for this window if unminify-js
+ /// opt is enabled.
+ unminified_js_dir: DOMRefCell<Option<String>>,
}
impl Window {
@@ -278,6 +286,10 @@ impl Window {
}
}
+ pub fn origin(&self) -> &MutableOrigin {
+ self.globalscope.origin()
+ }
+
pub fn get_cx(&self) -> *mut JSContext {
self.js_runtime.borrow().as_ref().unwrap().cx()
}
@@ -963,7 +975,12 @@ impl WindowMethods for Window {
// https://drafts.csswg.org/cssom-view/#dom-window-matchmedia
fn MatchMedia(&self, query: DOMString) -> Root<MediaQueryList> {
let mut parser = Parser::new(&query);
- let media_query_list = media_queries::parse_media_query_list(&mut parser);
+ let url = self.get_url();
+ let quirks_mode = self.Document().quirks_mode();
+ let context = CssParserContext::new_for_cssom(&url, self.css_error_reporter(), Some(CssRuleType::Media),
+ LengthParsingMode::Default,
+ quirks_mode);
+ let media_query_list = media_queries::parse_media_query_list(&context, &mut parser);
let document = self.Document();
let mql = MediaQueryList::new(&document, media_query_list);
self.media_query_lists.push(&*mql);
@@ -1066,9 +1083,10 @@ impl Window {
//TODO Step 11
//let document = self.Document();
// Step 12
+ let global_scope = self.upcast::<GlobalScope>();
self.perform_a_scroll(x.to_f32().unwrap_or(0.0f32),
y.to_f32().unwrap_or(0.0f32),
- ScrollRootId::root(),
+ global_scope.pipeline_id().root_scroll_node(),
behavior,
None);
}
@@ -1077,7 +1095,7 @@ impl Window {
pub fn perform_a_scroll(&self,
x: f32,
y: f32,
- scroll_root_id: ScrollRootId,
+ scroll_root_id: ClipId,
behavior: ScrollBehavior,
element: Option<&Element>) {
//TODO Step 1
@@ -1097,8 +1115,7 @@ impl Window {
self.update_viewport_for_scroll(x, y);
let global_scope = self.upcast::<GlobalScope>();
- let message = ConstellationMsg::ScrollFragmentPoint(
- global_scope.pipeline_id(), scroll_root_id, point, smooth);
+ let message = ConstellationMsg::ScrollFragmentPoint(scroll_root_id, point, smooth);
global_scope.constellation_chan().send(message).unwrap();
}
@@ -1484,6 +1501,23 @@ impl Window {
assert!(self.document.get().is_none());
assert!(document.window() == self);
self.document.set(Some(&document));
+ if !opts::get().unminify_js {
+ return;
+ }
+ // Create a folder for the document host to store unminified scripts.
+ if let Some(&Host::Domain(ref host)) = document.url().origin().host() {
+ let mut path = env::current_dir().unwrap();
+ path.push("unminified-js");
+ path.push(host);
+ let _ = fs::remove_dir_all(&path);
+ match fs::create_dir_all(&path) {
+ Ok(_) => {
+ *self.unminified_js_dir.borrow_mut() = Some(path.into_os_string().into_string().unwrap());
+ debug!("Created folder for {:?} unminified scripts {:?}", host, self.unminified_js_dir.borrow());
+ },
+ Err(_) => warn!("Could not create unminified dir for {:?}", host),
+ }
+ }
}
/// Commence a new URL load which will either replace this window or scroll to a fragment.
@@ -1691,6 +1725,10 @@ impl Window {
self.upcast::<GlobalScope>().slow_down_timers();
}
}
+
+ pub fn unminified_js_dir(&self) -> Option<String> {
+ self.unminified_js_dir.borrow().clone()
+ }
}
impl Window {
@@ -1717,6 +1755,7 @@ impl Window {
id: PipelineId,
parent_info: Option<(PipelineId, FrameType)>,
window_size: Option<WindowSizeData>,
+ origin: MutableOrigin,
webvr_thread: Option<IpcSender<WebVRMsg>>)
-> Root<Window> {
let layout_rpc: Box<LayoutRPC + Send> = {
@@ -1739,7 +1778,8 @@ impl Window {
constellation_chan,
scheduler_chan,
resource_threads,
- timer_event_chan),
+ timer_event_chan,
+ origin),
script_chan: script_chan,
dom_manipulation_task_source: dom_task_source,
user_interaction_task_source: user_task_source,
@@ -1785,6 +1825,7 @@ impl Window {
webvr_thread: webvr_thread,
permission_state_invocation_results: DOMRefCell::new(HashMap::new()),
pending_layout_images: DOMRefCell::new(HashMap::new()),
+ unminified_js_dir: DOMRefCell::new(None),
};
unsafe {
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index 948d72c251b..fd1f03db1e3 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -37,7 +37,7 @@ use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use script_thread::RunnableWrapper;
use script_traits::{TimerEvent, TimerEventId};
use script_traits::WorkerGlobalScopeInit;
-use servo_url::ServoUrl;
+use servo_url::{MutableOrigin, ServoUrl};
use std::default::Default;
use std::rc::Rc;
use std::sync::Arc;
@@ -59,6 +59,7 @@ pub fn prepare_workerscope_init(global: &GlobalScope,
scheduler_chan: global.scheduler_chan().clone(),
worker_id: global.get_next_worker_id(),
pipeline_id: global.pipeline_id(),
+ origin: global.origin().immutable().clone(),
};
init
@@ -109,7 +110,8 @@ impl WorkerGlobalScope {
init.constellation_chan,
init.scheduler_chan,
init.resource_threads,
- timer_event_chan),
+ timer_event_chan,
+ MutableOrigin::new(init.origin)),
worker_id: init.worker_id,
worker_url: worker_url,
closing: closing,
diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs
index 4b118bdf7f1..3ddb1d2b5c9 100644
--- a/components/script/layout_wrapper.rs
+++ b/components/script/layout_wrapper.rs
@@ -55,6 +55,7 @@ use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::fmt;
use std::fmt::Debug;
+use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::mem::transmute;
use std::sync::Arc;
@@ -460,12 +461,16 @@ impl<'le> TElement for ServoLayoutElement<'le> {
self.element.has_selector_flags(flags)
}
- fn has_animations(&self, _pseudo: Option<&PseudoElement>) -> bool {
- panic!("this should be only called on gecko");
+ fn has_animations(&self) -> bool {
+ unreachable!("this should be only called on gecko");
}
- fn has_css_animations(&self, _pseudo: Option<&PseudoElement>) -> bool {
- panic!("this should be only called on gecko");
+ fn has_css_animations(&self) -> bool {
+ unreachable!("this should be only called on gecko");
+ }
+
+ fn has_css_transitions(&self) -> bool {
+ unreachable!("this should be only called on gecko");
}
}
@@ -475,6 +480,14 @@ impl<'le> PartialEq for ServoLayoutElement<'le> {
}
}
+impl<'le> Hash for ServoLayoutElement<'le> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.element.hash(state);
+ }
+}
+
+impl<'le> Eq for ServoLayoutElement<'le> {}
+
impl<'le> ServoLayoutElement<'le> {
fn from_layout_js(el: LayoutJS<Element>) -> ServoLayoutElement<'le> {
ServoLayoutElement {
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 2de2e37ea38..678603ee60f 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -12,7 +12,6 @@
#![feature(optin_builtin_traits)]
#![feature(plugin)]
#![feature(proc_macro)]
-#![feature(slice_patterns)]
#![feature(stmt_expr_attributes)]
#![feature(try_from)]
#![feature(untagged_unions)]
@@ -97,6 +96,7 @@ extern crate style_traits;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
+extern crate unicode_segmentation;
extern crate url;
extern crate uuid;
extern crate webrender_traits;
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 955887addf4..96167cec236 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -27,6 +27,7 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::Bindings::EventBinding::EventInit;
+use dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorMethods;
use dom::bindings::codegen::Bindings::TransitionEventBinding::TransitionEventInit;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior};
@@ -91,7 +92,6 @@ use script_traits::{ScriptThreadFactory, TimerEvent, TimerSchedulerMsg, TimerSou
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent};
-use script_traits::WebVREventMsg;
use script_traits::webdriver_msg::WebDriverScriptCommand;
use serviceworkerjob::{Job, JobQueue, AsyncJobHandler};
use servo_config::opts;
@@ -119,7 +119,7 @@ use task_source::user_interaction::{UserInteractionTask, UserInteractionTaskSour
use time::Tm;
use url::Position;
use webdriver_handlers;
-use webvr_traits::WebVRMsg;
+use webvr_traits::{WebVREvent, WebVRMsg};
pub type ImageCacheMsg = (PipelineId, PendingImageResponse);
@@ -1070,8 +1070,8 @@ impl ScriptThread {
self.handle_reload(pipeline_id),
ConstellationControlMsg::ExitPipeline(pipeline_id, discard_browsing_context) =>
self.handle_exit_pipeline_msg(pipeline_id, discard_browsing_context),
- ConstellationControlMsg::WebVREvent(pipeline_id, event) =>
- self.handle_webvr_event(pipeline_id, event),
+ ConstellationControlMsg::WebVREvents(pipeline_id, events) =>
+ self.handle_webvr_events(pipeline_id, events),
msg @ ConstellationControlMsg::AttachLayout(..) |
msg @ ConstellationControlMsg::Viewport(..) |
msg @ ConstellationControlMsg::SetScrollState(..) |
@@ -1784,6 +1784,7 @@ impl ScriptThread {
incomplete.pipeline_id,
incomplete.parent_info,
incomplete.window_size,
+ incomplete.origin.clone(),
self.webvr_thread.clone());
// Initialize the browsing context for the window.
@@ -2186,11 +2187,11 @@ impl ScriptThread {
}
}
- fn handle_webvr_event(&self, pipeline_id: PipelineId, event: WebVREventMsg) {
+ fn handle_webvr_events(&self, pipeline_id: PipelineId, events: Vec<WebVREvent>) {
let window = self.documents.borrow().find_window(pipeline_id);
if let Some(window) = window {
- let navigator = window.Navigator();
- navigator.handle_webvr_event(event);
+ let vr = window.Navigator().Vr();
+ vr.handle_webvr_events(events);
}
}
diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs
index cdafde510c9..14b8c385e39 100644
--- a/components/script/stylesheet_loader.rs
+++ b/components/script/stylesheet_loader.rs
@@ -22,7 +22,6 @@ use ipc_channel::router::ROUTER;
use net_traits::{FetchResponseListener, FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy};
use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode, Type as RequestType};
use network_listener::{NetworkListener, PreInvoke};
-use script_layout_interface::message::Msg;
use servo_url::ServoUrl;
use std::mem;
use std::sync::{Arc, Mutex};
@@ -145,15 +144,14 @@ impl FetchResponseListener for StylesheetContext {
media.take().unwrap(),
shared_lock,
Some(&loader),
- win.css_error_reporter()));
+ win.css_error_reporter(),
+ document.quirks_mode()));
if link.is_alternate() {
sheet.set_disabled(true);
}
- link.set_stylesheet(sheet.clone());
-
- win.layout_chan().send(Msg::AddStylesheet(sheet)).unwrap();
+ link.set_stylesheet(sheet);
}
}
StylesheetContextSource::Import(ref stylesheet) => {
@@ -271,15 +269,15 @@ impl<'a> StylesheetLoader<'a> {
impl<'a> StyleStylesheetLoader for StylesheetLoader<'a> {
fn request_stylesheet(
&self,
- media: MediaList,
- make_import: &mut FnMut(MediaList) -> ImportRule,
+ media: Arc<StyleLocked<MediaList>>,
+ make_import: &mut FnMut(Arc<StyleLocked<MediaList>>) -> ImportRule,
make_arc: &mut FnMut(ImportRule) -> Arc<StyleLocked<ImportRule>>,
) -> Arc<StyleLocked<ImportRule>> {
let import = make_import(media);
let url = import.url.url().expect("Invalid urls shouldn't enter the loader").clone();
- //TODO (mrnayak) : Whether we should use the original loader's CORS setting?
- //Fix this when spec has more details.
+ // TODO (mrnayak) : Whether we should use the original loader's CORS
+ // setting? Fix this when spec has more details.
let source = StylesheetContextSource::Import(import.stylesheet.clone());
self.load(source, url, None, "".to_owned());
diff --git a/components/script/textinput.rs b/components/script/textinput.rs
index 5f04b5b187e..144be9dbd78 100644
--- a/components/script/textinput.rs
+++ b/components/script/textinput.rs
@@ -14,6 +14,7 @@ use std::cmp::{max, min};
use std::default::Default;
use std::ops::Range;
use std::usize;
+use unicode_segmentation::UnicodeSegmentation;
#[derive(Copy, Clone, PartialEq)]
pub enum Selection {
@@ -376,18 +377,16 @@ impl<T: ClipboardProvider> TextInput<T> {
}
let adjust = {
let current_line = &self.lines[self.edit_point.line];
- // FIXME: We adjust by one code point, but it proably should be one grapheme cluster
- // https://github.com/unicode-rs/unicode-segmentation
match direction {
Direction::Forward => {
- match current_line[self.edit_point.index..].chars().next() {
- Some(c) => c.len_utf8() as isize,
+ match current_line[self.edit_point.index..].graphemes(true).next() {
+ Some(c) => c.len() as isize,
None => 1, // Going to the next line is a "one byte" offset
}
}
Direction::Backward => {
- match current_line[..self.edit_point.index].chars().next_back() {
- Some(c) => -(c.len_utf8() as isize),
+ match current_line[..self.edit_point.index].graphemes(true).next_back() {
+ Some(c) => -(c.len() as isize),
None => -1, // Going to the previous line is a "one byte" offset
}
}
@@ -468,6 +467,111 @@ impl<T: ClipboardProvider> TextInput<T> {
self.selection_begin = None;
}
+ pub fn adjust_horizontal_by_word(&mut self, direction: Direction, select: Selection) {
+ if self.adjust_selection_for_horizontal_change(direction, select) {
+ return
+ }
+ let shift_increment: isize = {
+ let input: &str;
+ match direction {
+ Direction::Backward => {
+ let remaining = self.edit_point.index;
+ let current_line = self.edit_point.line;
+ let mut newline_adjustment = 0;
+ if remaining == 0 && current_line > 0 {
+ input = &self
+ .lines[current_line-1];
+ newline_adjustment = 1;
+ } else {
+ input = &self
+ .lines[current_line]
+ [..remaining];
+ }
+
+ let mut iter = input.split_word_bounds().rev();
+ let mut shift_temp: isize = 0;
+ loop {
+ match iter.next() {
+ None => break,
+ Some(x) => {
+ shift_temp += - (x.len() as isize);
+ if x.chars().any(|x| x.is_alphabetic() || x.is_numeric()) {
+ break;
+ }
+ }
+ }
+ }
+ shift_temp - newline_adjustment
+ }
+ Direction::Forward => {
+ let remaining = self.current_line_length() - self.edit_point.index;
+ let current_line = self.edit_point.line;
+ let mut newline_adjustment = 0;
+ if remaining == 0 && self.lines.len() > self.edit_point.line + 1 {
+ input = &self
+ .lines[current_line + 1];
+ newline_adjustment = 1;
+ } else {
+ input = &self
+ .lines[current_line]
+ [self.edit_point.index..];
+ }
+
+ let mut iter = input.split_word_bounds();
+ let mut shift_temp: isize = 0;
+ loop {
+ match iter.next() {
+ None => break,
+ Some(x) => {
+ shift_temp += x.len() as isize;
+ if x.chars().any(|x| x.is_alphabetic() || x.is_numeric()) {
+ break;
+ }
+ }
+ }
+ }
+ shift_temp + newline_adjustment
+ }
+ }
+ };
+
+ self.adjust_horizontal(shift_increment, select);
+ }
+
+ pub fn adjust_horizontal_to_line_end(&mut self, direction: Direction, select: Selection) {
+ if self.adjust_selection_for_horizontal_change(direction, select) {
+ return
+ }
+ let shift: isize = {
+ let current_line = &self.lines[self.edit_point.line];
+ match direction {
+ Direction::Backward => {
+ - (current_line[..self.edit_point.index].len() as isize)
+ },
+ Direction::Forward => {
+ current_line[self.edit_point.index..].len() as isize
+ }
+ }
+ };
+ self.perform_horizontal_adjustment(shift, select);
+ }
+
+ pub fn adjust_horizontal_to_limit(&mut self, direction: Direction, select: Selection) {
+ if self.adjust_selection_for_horizontal_change(direction, select) {
+ return
+ }
+ match direction {
+ Direction::Backward => {
+ self.edit_point.line = 0;
+ self.edit_point.index = 0;
+ },
+ Direction::Forward => {
+ self.edit_point.line = &self.lines.len() - 1;
+ self.edit_point.index = (&self.lines[&self.lines.len() - 1]).len();
+ }
+ }
+ }
+
/// Process a given `KeyboardEvent` and return an action for the caller to execute.
pub fn handle_keydown(&mut self, event: &KeyboardEvent) -> KeyReaction {
if let Some(key) = event.get_key() {
@@ -483,6 +587,32 @@ impl<T: ClipboardProvider> TextInput<T> {
mods: KeyModifiers) -> KeyReaction {
let maybe_select = if mods.contains(SHIFT) { Selection::Selected } else { Selection::NotSelected };
match (printable, key) {
+ (_, Key::B) if mods.contains(CONTROL | ALT) => {
+ self.adjust_horizontal_by_word(Direction::Backward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ (_, Key::F) if mods.contains(CONTROL | ALT) => {
+ self.adjust_horizontal_by_word(Direction::Forward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ (_, Key::A) if mods.contains(CONTROL | ALT) => {
+ self.adjust_horizontal_to_line_end(Direction::Backward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ (_, Key::E) if mods.contains(CONTROL | ALT) => {
+ self.adjust_horizontal_to_line_end(Direction::Forward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ #[cfg(target_os = "macos")]
+ (None, Key::A) if mods == CONTROL => {
+ self.adjust_horizontal_to_line_end(Direction::Backward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ #[cfg(target_os = "macos")]
+ (None, Key::E) if mods == CONTROL => {
+ self.adjust_horizontal_to_line_end(Direction::Forward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
(Some('a'), _) if is_control_key(mods) => {
self.select_all();
KeyReaction::RedrawSelection
@@ -501,49 +631,85 @@ impl<T: ClipboardProvider> TextInput<T> {
(Some(c), _) => {
self.insert_char(c);
KeyReaction::DispatchInput
- }
+ },
+ #[cfg(target_os = "macos")]
+ (None, Key::Home) => {
+ KeyReaction::RedrawSelection
+ },
+ #[cfg(target_os = "macos")]
+ (None, Key::End) => {
+ KeyReaction::RedrawSelection
+ },
(None, Key::Delete) => {
self.delete_char(Direction::Forward);
KeyReaction::DispatchInput
- }
+ },
(None, Key::Backspace) => {
self.delete_char(Direction::Backward);
KeyReaction::DispatchInput
- }
+ },
+ #[cfg(target_os = "macos")]
+ (None, Key::Left) if mods.contains(SUPER) => {
+ self.adjust_horizontal_to_line_end(Direction::Backward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ #[cfg(target_os = "macos")]
+ (None, Key::Right) if mods.contains(SUPER) => {
+ self.adjust_horizontal_to_line_end(Direction::Forward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ #[cfg(target_os = "macos")]
+ (None, Key::Up) if mods.contains(SUPER) => {
+ self.adjust_horizontal_to_limit(Direction::Backward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ #[cfg(target_os = "macos")]
+ (None, Key::Down) if mods.contains(SUPER) => {
+ self.adjust_horizontal_to_limit(Direction::Forward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ (None, Key::Left) if mods.contains(ALT) => {
+ self.adjust_horizontal_by_word(Direction::Backward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
+ (None, Key::Right) if mods.contains(ALT) => {
+ self.adjust_horizontal_by_word(Direction::Forward, maybe_select);
+ KeyReaction::RedrawSelection
+ },
(None, Key::Left) => {
self.adjust_horizontal_by_one(Direction::Backward, maybe_select);
KeyReaction::RedrawSelection
- }
+ },
(None, Key::Right) => {
self.adjust_horizontal_by_one(Direction::Forward, maybe_select);
KeyReaction::RedrawSelection
- }
+ },
(None, Key::Up) => {
self.adjust_vertical(-1, maybe_select);
KeyReaction::RedrawSelection
- }
+ },
(None, Key::Down) => {
self.adjust_vertical(1, maybe_select);
KeyReaction::RedrawSelection
- }
+ },
(None, Key::Enter) | (None, Key::KpEnter) => self.handle_return(),
(None, Key::Home) => {
self.edit_point.index = 0;
KeyReaction::RedrawSelection
- }
+ },
(None, Key::End) => {
self.edit_point.index = self.current_line_length();
self.assert_ok_selection();
KeyReaction::RedrawSelection
- }
+ },
(None, Key::PageUp) => {
self.adjust_vertical(-28, maybe_select);
KeyReaction::RedrawSelection
- }
+ },
(None, Key::PageDown) => {
self.adjust_vertical(28, maybe_select);
KeyReaction::RedrawSelection
- }
+ },
_ => KeyReaction::Nothing,
}
}
@@ -677,4 +843,12 @@ impl<T: ClipboardProvider> TextInput<T> {
selection_start as u32
}
+
+ pub fn set_edit_point_index(&mut self, index: usize) {
+ let byte_size = self.lines[self.edit_point.line]
+ .graphemes(true)
+ .take(index)
+ .fold(0, |acc, x| acc + x.len());
+ self.edit_point.index = byte_size;
+ }
}