aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/bluetooth/lib.rs19
-rw-r--r--components/bluetooth/test.rs2
-rw-r--r--components/compositing/compositor.rs16
-rw-r--r--components/compositing/compositor_thread.rs3
-rw-r--r--components/constellation/constellation.rs3
-rw-r--r--components/jstraceable_derive/lib.rs5
-rw-r--r--components/layout/display_list_builder.rs31
-rw-r--r--components/layout/flow.rs5
-rw-r--r--components/layout/query.rs17
-rw-r--r--components/layout_thread/lib.rs16
-rw-r--r--components/script/devtools.rs9
-rw-r--r--components/script/docs/JS-Servos-only-GC.md6
-rw-r--r--components/script/dom/abstractworkerglobalscope.rs5
-rw-r--r--components/script/dom/bindings/js.rs8
-rw-r--r--components/script/dom/bindings/trace.rs426
-rw-r--r--components/script/dom/bindings/weakref.rs24
-rw-r--r--components/script/dom/bluetooth.rs22
-rw-r--r--components/script/dom/bluetoothdevice.rs79
-rw-r--r--components/script/dom/bluetoothremotegattcharacteristic.rs28
-rw-r--r--components/script/dom/bluetoothremotegattserver.rs36
-rw-r--r--components/script/dom/bluetoothremotegattservice.rs58
-rw-r--r--components/script/dom/bluetoothuuid.rs39
-rw-r--r--components/script/dom/crypto.rs2
-rw-r--r--components/script/dom/cssrulelist.rs6
-rw-r--r--components/script/dom/document.rs44
-rw-r--r--components/script/dom/htmliframeelement.rs3
-rw-r--r--components/script/dom/htmllinkelement.rs2
-rw-r--r--components/script/dom/keyboardevent.rs2
-rw-r--r--components/script/dom/macros.rs39
-rw-r--r--components/script/dom/mediaquerylist.rs5
-rw-r--r--components/script/dom/node.rs2
-rw-r--r--components/script/dom/range.rs6
-rw-r--r--components/script/dom/servoparser/html.rs7
-rw-r--r--components/script/dom/servoparser/xml.rs7
-rw-r--r--components/script/dom/webgltexture.rs2
-rw-r--r--components/script/dom/window.rs61
-rw-r--r--components/script/dom/xmlhttprequest.rs9
-rw-r--r--components/script/layout_wrapper.rs4
-rw-r--r--components/script/lib.rs2
-rw-r--r--components/script/script_runtime.rs4
-rw-r--r--components/script_layout_interface/message.rs1
-rw-r--r--components/script_layout_interface/rpc.rs5
-rw-r--r--components/script_layout_interface/wrapper_traits.rs16
-rw-r--r--components/script_traits/script_msg.rs3
-rw-r--r--components/style/dom.rs5
-rw-r--r--components/style/gecko/wrapper.rs9
-rw-r--r--components/style/gecko_bindings/structs_debug.rs22
-rw-r--r--components/style/gecko_bindings/structs_release.rs22
-rw-r--r--components/style/keyframes.rs12
-rw-r--r--components/style/matching.rs5
-rw-r--r--components/style/properties/data.py8
-rw-r--r--components/style/properties/gecko.mako.rs30
-rw-r--r--components/style/properties/helpers.mako.rs2
-rw-r--r--components/style/properties/longhand/border.mako.rs2
-rw-r--r--components/style/properties/longhand/box.mako.rs7
-rw-r--r--components/style/properties/longhand/inherited_svg.mako.rs2
-rw-r--r--components/style/properties/longhand/pointing.mako.rs3
-rw-r--r--components/style/properties/longhand/ui.mako.rs1
-rw-r--r--components/style/properties/longhand/xul.mako.rs1
-rw-r--r--components/style/properties/properties.mako.rs52
60 files changed, 796 insertions, 476 deletions
diff --git a/components/bluetooth/lib.rs b/components/bluetooth/lib.rs
index 5b24690ddd6..0207c9e6f74 100644
--- a/components/bluetooth/lib.rs
+++ b/components/bluetooth/lib.rs
@@ -424,10 +424,15 @@ impl BluetoothManager {
adapter: &mut BluetoothAdapter,
device_id: &str)
-> Vec<BluetoothGATTService> {
- let services = match self.get_device(adapter, device_id) {
+ let mut services = match self.get_device(adapter, device_id) {
Some(d) => d.get_gatt_services().unwrap_or(vec!()),
None => vec!(),
};
+
+ services.retain(|s| !uuid_is_blocklisted(&s.get_uuid().unwrap_or(String::new()), Blocklist::All) &&
+ self.allowed_services
+ .get(device_id)
+ .map_or(false, |uuids| uuids.contains(&s.get_uuid().unwrap_or(String::new()))));
for service in &services {
self.cached_services.insert(service.get_id(), service.clone());
self.service_to_device.insert(service.get_id(), device_id.to_owned());
@@ -461,11 +466,12 @@ impl BluetoothManager {
adapter: &mut BluetoothAdapter,
service_id: &str)
-> Vec<BluetoothGATTCharacteristic> {
- let characteristics = match self.get_gatt_service(adapter, service_id) {
+ let mut characteristics = match self.get_gatt_service(adapter, service_id) {
Some(s) => s.get_gatt_characteristics().unwrap_or(vec!()),
None => vec!(),
};
+ characteristics.retain(|c| !uuid_is_blocklisted(&c.get_uuid().unwrap_or(String::new()), Blocklist::All));
for characteristic in &characteristics {
self.cached_characteristics.insert(characteristic.get_id(), characteristic.clone());
self.characteristic_to_service.insert(characteristic.get_id(), service_id.to_owned());
@@ -524,11 +530,12 @@ impl BluetoothManager {
adapter: &mut BluetoothAdapter,
characteristic_id: &str)
-> Vec<BluetoothGATTDescriptor> {
- let descriptors = match self.get_gatt_characteristic(adapter, characteristic_id) {
+ let mut descriptors = match self.get_gatt_characteristic(adapter, characteristic_id) {
Some(c) => c.get_gatt_descriptors().unwrap_or(vec!()),
None => vec!(),
};
+ descriptors.retain(|d| !uuid_is_blocklisted(&d.get_uuid().unwrap_or(String::new()), Blocklist::All));
for descriptor in &descriptors {
self.cached_descriptors.insert(descriptor.get_id(), descriptor.clone());
self.descriptor_to_characteristic.insert(descriptor.get_id(), characteristic_id.to_owned());
@@ -743,10 +750,6 @@ impl BluetoothManager {
}
}
}
- services_vec.retain(|s| !uuid_is_blocklisted(&s.uuid, Blocklist::All) &&
- self.allowed_services
- .get(&device_id)
- .map_or(false, |uuids| uuids.contains(&s.uuid)));
// Step 7.
if services_vec.is_empty() {
@@ -919,7 +922,6 @@ impl BluetoothManager {
);
}
}
- characteristics_vec.retain(|c| !uuid_is_blocklisted(&c.uuid, Blocklist::All));
// Step 7.
if characteristics_vec.is_empty() {
@@ -987,7 +989,6 @@ impl BluetoothManager {
);
}
}
- descriptors_vec.retain(|d| !uuid_is_blocklisted(&d.uuid, Blocklist::All));
// Step 7.
if descriptors_vec.is_empty() {
diff --git a/components/bluetooth/test.rs b/components/bluetooth/test.rs
index 8578db79aa5..e2c6e639e82 100644
--- a/components/bluetooth/test.rs
+++ b/components/bluetooth/test.rs
@@ -99,7 +99,7 @@ const SERIAL_NUMBER_STRING_UUID: &'static str = "00002a25-0000-1000-8000-00805f9
// Descriptor UUIDs
const BLOCKLIST_EXCLUDE_READS_DESCRIPTOR_UUID: &'static str = "aaaaaaaa-aaaa-1181-0510-810819516110";
-const BLOCKLIST_DESCRIPTOR_UUID: &'static str = "07711111-6104-0970-7011-1107105110aaa";
+const BLOCKLIST_DESCRIPTOR_UUID: &'static str = "07711111-6104-0970-7011-1107105110aa";
// https://www.bluetooth.com/specifications/gatt/
// viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_user_description.xml
const CHARACTERISTIC_USER_DESCRIPTION_UUID: &'static str = "00002901-0000-1000-8000-00805f9b34fb";
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index 8f0c12e5bf7..1fc3a5b27f5 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -39,7 +39,7 @@ use util::geometry::ScreenPx;
use util::opts;
use util::prefs::PREFS;
use webrender;
-use webrender_traits::{self, ScrollEventPhase};
+use webrender_traits::{self, ScrollEventPhase, ServoScrollRootId};
use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg};
#[derive(Debug, PartialEq)]
@@ -493,9 +493,9 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.title_for_main_frame();
}
- (Msg::ScrollFragmentPoint(pipeline_id, point, _),
+ (Msg::ScrollFragmentPoint(pipeline_id, scroll_root_id, point, _),
ShutdownState::NotShuttingDown) => {
- self.scroll_fragment_to_point(pipeline_id, point);
+ self.scroll_fragment_to_point(pipeline_id, scroll_root_id, point);
}
(Msg::MoveTo(point),
@@ -761,9 +761,13 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn scroll_fragment_to_point(&mut self,
- _pipeline_id: PipelineId,
- _point: Point2D<f32>) {
- println!("TODO: Support scroll_fragment_to_point again");
+ pipeline_id: PipelineId,
+ scroll_root_id: ScrollRootId,
+ point: Point2D<f32>) {
+ self.webrender_api.scroll_layers_with_scroll_root_id(
+ point,
+ pipeline_id.to_webrender(),
+ ServoScrollRootId(scroll_root_id.0));
}
fn handle_window_message(&mut self, event: WindowEvent) {
diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs
index f8f35e995d7..0a7962c7917 100644
--- a/components/compositing/compositor_thread.rs
+++ b/components/compositing/compositor_thread.rs
@@ -8,6 +8,7 @@ use SendableFrameTree;
use compositor::CompositingReason;
use euclid::point::Point2D;
use euclid::size::Size2D;
+use gfx_traits::ScrollRootId;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId};
use net_traits::image::base::Image;
@@ -72,7 +73,7 @@ pub enum Msg {
ShutdownComplete,
/// Scroll a page in a window
- ScrollFragmentPoint(PipelineId, Point2D<f32>, bool),
+ ScrollFragmentPoint(PipelineId, ScrollRootId, Point2D<f32>, bool),
/// Alerts the compositor that the current page has changed its title.
ChangePageTitle(PipelineId, Option<String>),
/// Alerts the compositor that the current page has changed its URL.
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index 19e70c90bfc..c64e3ee3811 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -1038,8 +1038,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.handle_alert(pipeline_id, message, sender);
}
- FromScriptMsg::ScrollFragmentPoint(pipeline_id, point, smooth) => {
+ FromScriptMsg::ScrollFragmentPoint(pipeline_id, scroll_root_id, point, smooth) => {
self.compositor_proxy.send(ToCompositorMsg::ScrollFragmentPoint(pipeline_id,
+ scroll_root_id,
point,
smooth));
}
diff --git a/components/jstraceable_derive/lib.rs b/components/jstraceable_derive/lib.rs
index 527c517ef07..3d3c785d971 100644
--- a/components/jstraceable_derive/lib.rs
+++ b/components/jstraceable_derive/lib.rs
@@ -41,10 +41,11 @@ fn expand_string(input: &str) -> String {
}
let tokens = quote! {
- impl #impl_generics ::dom::bindings::trace::JSTraceable for #name #ty_generics #where_clause {
+ #[allow(unsafe_code)]
+ unsafe impl #impl_generics ::dom::bindings::trace::JSTraceable for #name #ty_generics #where_clause {
#[inline]
#[allow(unused_variables, unused_imports)]
- fn trace(&self, tracer: *mut ::js::jsapi::JSTracer) {
+ unsafe fn trace(&self, tracer: *mut ::js::jsapi::JSTracer) {
use ::dom::bindings::trace::JSTraceable;
match *self {
#match_body
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index 4505ac10192..0c34a147655 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -15,7 +15,6 @@ use block::{BlockFlow, BlockStackingContextType};
use canvas_traits::{CanvasData, CanvasMsg, FromLayoutMsg};
use context::SharedLayoutContext;
use euclid::{Matrix4D, Point2D, Radians, Rect, SideOffsets2D, Size2D};
-use euclid::point::TypedPoint2D;
use flex::FlexFlow;
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref::FlowRef;
@@ -98,6 +97,7 @@ pub struct DisplayListBuildState<'a> {
pub scroll_roots: HashMap<ScrollRootId, ScrollRoot>,
pub stacking_context_id_stack: Vec<StackingContextId>,
pub scroll_root_id_stack: Vec<ScrollRootId>,
+ pub processing_scroll_root_element: bool,
}
impl<'a> DisplayListBuildState<'a> {
@@ -111,6 +111,7 @@ impl<'a> DisplayListBuildState<'a> {
scroll_roots: HashMap::new(),
stacking_context_id_stack: vec!(stacking_context_id),
scroll_root_id_stack: vec!(ScrollRootId::root()),
+ processing_scroll_root_element: false,
}
}
@@ -162,6 +163,14 @@ impl<'a> DisplayListBuildState<'a> {
cursor: Option<Cursor>,
section: DisplayListSection)
-> BaseDisplayItem {
+ let scroll_root_id = if (section == DisplayListSection::BackgroundAndBorders ||
+ section == DisplayListSection::BlockBackgroundsAndBorders) &&
+ self.processing_scroll_root_element {
+ self.parent_scroll_root_id()
+ } else {
+ self.scroll_root_id()
+ };
+
BaseDisplayItem::new(&bounds,
DisplayItemMetadata {
node: node,
@@ -170,7 +179,7 @@ impl<'a> DisplayListBuildState<'a> {
&clip,
section,
self.stacking_context_id(),
- self.scroll_root_id())
+ scroll_root_id)
}
pub fn to_display_list(mut self) -> DisplayList {
@@ -1977,21 +1986,25 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
if self.has_scrolling_overflow() {
let size = self.base.overflow.scroll.size;
- let mut clip = self.fragment.stacking_relative_border_box(
+ let coordinate_system = if establishes_stacking_context {
+ CoordinateSystem::Own
+ } else {
+ CoordinateSystem::Parent
+ };
+
+ let border_box = self.fragment.stacking_relative_border_box(
&self.base.stacking_relative_position,
&self.base.early_absolute_position_info.relative_containing_block_size,
self.base.early_absolute_position_info.relative_containing_block_mode,
- CoordinateSystem::Parent);
- if establishes_stacking_context {
- clip = Rect::new(TypedPoint2D::zero(), clip.size);
- }
+ coordinate_system);
let parent_id = state.parent_scroll_root_id();
+ state.processing_scroll_root_element = true;
state.add_scroll_root(
ScrollRoot {
id: self.base.scroll_root_id,
parent_id: parent_id,
- clip: clip,
+ clip: self.fragment.stacking_relative_content_box(&border_box),
size: size,
}
);
@@ -2012,6 +2025,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base.clip);
self.base.build_display_items_for_debugging_tint(state, self.fragment.node);
+
+ state.processing_scroll_root_element = false;
}
fn switch_coordinate_system_if_necessary(&mut self) {
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index 6f441d737c3..df7a6510ff2 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -406,7 +406,10 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
/// Print any extra children (such as fragments) contained in this Flow
/// for debugging purposes. Any items inserted into the tree will become
/// children of this flow.
- fn print_extra_flow_children(&self, _: &mut PrintTree) {
+ fn print_extra_flow_children(&self, _: &mut PrintTree) { }
+
+ fn scroll_root_id(&self) -> ScrollRootId {
+ base(self).scroll_root_id
}
}
diff --git a/components/layout/query.rs b/components/layout/query.rs
index d34dbc59f07..765cd2bdab4 100644
--- a/components/layout/query.rs
+++ b/components/layout/query.rs
@@ -12,13 +12,14 @@ use euclid::size::Size2D;
use flow::{self, Flow};
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use gfx::display_list::{DisplayItemMetadata, DisplayList, OpaqueNode, ScrollOffsetMap};
+use gfx_traits::ScrollRootId;
use ipc_channel::ipc::IpcSender;
use opaque_node::OpaqueNodeMethods;
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse};
use script_layout_interface::rpc::{HitTestResponse, LayoutRPC};
use script_layout_interface::rpc::{MarginStyleResponse, NodeGeometryResponse};
use script_layout_interface::rpc::{NodeOverflowResponse, OffsetParentResponse};
-use script_layout_interface::rpc::ResolvedStyleResponse;
+use script_layout_interface::rpc::{NodeScrollRootIdResponse, ResolvedStyleResponse};
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use script_traits::LayoutMsg as ConstellationMsg;
use script_traits::UntrustedNodeAddress;
@@ -64,6 +65,9 @@ pub struct LayoutThreadData {
/// A queued response for the node at a given point
pub hit_test_response: (Option<DisplayItemMetadata>, bool),
+ /// A queued response for the scroll root id for a given node.
+ pub scroll_root_id_response: Option<ScrollRootId>,
+
/// A pair of overflow property in x and y
pub overflow_response: NodeOverflowResponse,
@@ -178,6 +182,12 @@ impl LayoutRPC for LayoutRPCImpl {
}
}
+ fn node_scroll_root_id(&self) -> NodeScrollRootIdResponse {
+ NodeScrollRootIdResponse(self.0.lock()
+ .unwrap().scroll_root_id_response
+ .expect("scroll_root_id is not correctly fetched"))
+ }
+
/// Retrieves the resolved value for a CSS style property.
fn resolved_style(&self) -> ResolvedStyleResponse {
let &LayoutRPCImpl(ref rw_data) = self;
@@ -578,6 +588,11 @@ pub fn process_node_geometry_request<N: LayoutNode>(requested_node: N, layout_ro
iterator.client_rect
}
+pub fn process_node_scroll_root_id_request<N: LayoutNode>(requested_node: N) -> ScrollRootId {
+ let layout_node = requested_node.to_threadsafe();
+ layout_node.scroll_root_id()
+}
+
pub fn process_node_scroll_area_request< N: LayoutNode>(requested_node: N, layout_root: &mut Flow)
-> Rect<i32> {
let mut iterator = UnioningFragmentScrollAreaIterator::new(requested_node.opaque());
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs
index 85330e3a6cb..04f35183ff4 100644
--- a/components/layout_thread/lib.rs
+++ b/components/layout_thread/lib.rs
@@ -72,7 +72,7 @@ use layout::parallel;
use layout::query::{LayoutRPCImpl, LayoutThreadData, process_content_box_request, process_content_boxes_request};
use layout::query::{process_margin_style_query, process_node_overflow_request, process_resolved_style_request};
use layout::query::{process_node_geometry_request, process_node_scroll_area_request};
-use layout::query::process_offset_parent_query;
+use layout::query::{process_node_scroll_root_id_request, process_offset_parent_query};
use layout::sequential;
use layout::traversal::{ComputeAbsolutePositions, RecalcStyleAndConstructFlows};
use layout::webrender_helpers::WebRenderDisplayListConverter;
@@ -462,6 +462,7 @@ impl LayoutThread {
content_boxes_response: Vec::new(),
client_rect_response: Rect::zero(),
hit_test_response: (None, false),
+ scroll_root_id_response: None,
scroll_area_response: Rect::zero(),
overflow_response: NodeOverflowResponse(None),
resolved_style_response: None,
@@ -1012,6 +1013,9 @@ impl LayoutThread {
ReflowQueryType::NodeOverflowQuery(_) => {
rw_data.overflow_response = NodeOverflowResponse(None);
},
+ ReflowQueryType::NodeScrollRootIdQuery(_) => {
+ rw_data.scroll_root_id_response = None;
+ },
ReflowQueryType::ResolvedStyleQuery(_, _, _) => {
rw_data.resolved_style_response = None;
},
@@ -1239,6 +1243,10 @@ impl LayoutThread {
let node = unsafe { ServoLayoutNode::new(&node) };
rw_data.overflow_response = process_node_overflow_request(node);
},
+ ReflowQueryType::NodeScrollRootIdQuery(node) => {
+ let node = unsafe { ServoLayoutNode::new(&node) };
+ rw_data.scroll_root_id_response = Some(process_node_scroll_root_id_request(node));
+ },
ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) => {
let node = unsafe { ServoLayoutNode::new(&node) };
let layout_context = LayoutContext::new(&shared_layout_context);
@@ -1561,9 +1569,9 @@ fn reflow_query_type_needs_display_list(query_type: &ReflowQueryType) -> bool {
ReflowQueryType::HitTestQuery(..) => true,
ReflowQueryType::ContentBoxQuery(_) | ReflowQueryType::ContentBoxesQuery(_) |
ReflowQueryType::NodeGeometryQuery(_) | ReflowQueryType::NodeScrollGeometryQuery(_) |
- ReflowQueryType::NodeOverflowQuery(_) | ReflowQueryType::ResolvedStyleQuery(..) |
- ReflowQueryType::OffsetParentQuery(_) | ReflowQueryType::MarginStyleQuery(_) |
- ReflowQueryType::NoQuery => false,
+ ReflowQueryType::NodeOverflowQuery(_) | ReflowQueryType::NodeScrollRootIdQuery(_) |
+ ReflowQueryType::ResolvedStyleQuery(..) | ReflowQueryType::OffsetParentQuery(_) |
+ ReflowQueryType::MarginStyleQuery(_) | ReflowQueryType::NoQuery => false,
}
}
diff --git a/components/script/devtools.rs b/components/script/devtools.rs
index 9e6a0f1e528..1b1ef4596d6 100644
--- a/components/script/devtools.rs
+++ b/components/script/devtools.rs
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use devtools_traits::{AutoMargins, CONSOLE_API, CachedConsoleMessage, CachedConsoleMessageTypes};
-use devtools_traits::{ComputedNodeLayout, ConsoleAPI, PageError, ScriptToDevtoolsControlMsg};
+use devtools_traits::{ComputedNodeLayout, ConsoleAPI, PageError};
use devtools_traits::{EvaluateJSReply, Modification, NodeInfo, PAGE_ERROR, TimelineMarker};
use devtools_traits::TimelineMarkerType;
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
@@ -17,6 +17,7 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
+use dom::document::AnimationFrameCallback;
use dom::element::Element;
use dom::globalscope::GlobalScope;
use dom::node::{Node, window_from_node};
@@ -253,11 +254,7 @@ pub fn handle_request_animation_frame(documents: &Documents,
id: PipelineId,
actor_name: String) {
if let Some(doc) = documents.find_document(id) {
- let devtools_sender = doc.window().upcast::<GlobalScope>().devtools_chan().unwrap().clone();
- doc.request_animation_frame(box move |time| {
- let msg = ScriptToDevtoolsControlMsg::FramerateTick(actor_name, time);
- devtools_sender.send(msg).unwrap();
- });
+ doc.request_animation_frame(AnimationFrameCallback::DevtoolsFramerateTick { actor_name });
}
}
diff --git a/components/script/docs/JS-Servos-only-GC.md b/components/script/docs/JS-Servos-only-GC.md
index e7237853217..c8129241a84 100644
--- a/components/script/docs/JS-Servos-only-GC.md
+++ b/components/script/docs/JS-Servos-only-GC.md
@@ -122,8 +122,8 @@ which has an area, and the trait provides a way to get that object's area.
Now let's look at the `JSTraceable` trait, which we use for tracing:
```rust
-pub trait JSTraceable {
- fn trace(&self, trc: *mut JSTracer);
+pub unsafe trait JSTraceable {
+ unsafe fn trace(&self, trc: *mut JSTracer);
}
```
@@ -182,7 +182,7 @@ pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Ref
}
impl<T: Reflectable> JSTraceable for JS<T> {
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
trace_reflector(trc, "", unsafe { (**self.ptr).reflector() });
}
}
diff --git a/components/script/dom/abstractworkerglobalscope.rs b/components/script/dom/abstractworkerglobalscope.rs
index e584e41c62a..dc4bf15c89e 100644
--- a/components/script/dom/abstractworkerglobalscope.rs
+++ b/components/script/dom/abstractworkerglobalscope.rs
@@ -5,6 +5,7 @@
use dom::abstractworker::WorkerScriptMsg;
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::Reflectable;
+use dom::bindings::trace::JSTraceable;
use script_runtime::{ScriptChan, CommonScriptMsg, ScriptPort};
use std::sync::mpsc::{Receiver, Sender};
@@ -17,7 +18,7 @@ pub struct SendableWorkerScriptChan<T: Reflectable> {
pub worker: Trusted<T>,
}
-impl<T: Reflectable + 'static> ScriptChan for SendableWorkerScriptChan<T> {
+impl<T: JSTraceable + Reflectable + 'static> ScriptChan for SendableWorkerScriptChan<T> {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
self.sender.send((self.worker.clone(), msg)).map_err(|_| ())
}
@@ -39,7 +40,7 @@ pub struct WorkerThreadWorkerChan<T: Reflectable> {
pub worker: Trusted<T>,
}
-impl<T: Reflectable + 'static> ScriptChan for WorkerThreadWorkerChan<T> {
+impl<T: JSTraceable + Reflectable + 'static> ScriptChan for WorkerThreadWorkerChan<T> {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
self.sender
.send((self.worker.clone(), WorkerScriptMsg::Common(msg)))
diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs
index 528b1213ccb..9ddf3fc46fc 100644
--- a/components/script/dom/bindings/js.rs
+++ b/components/script/dom/bindings/js.rs
@@ -105,10 +105,10 @@ impl<T: Reflectable> Deref for JS<T> {
}
}
-impl<T: Reflectable> JSTraceable for JS<T> {
- fn trace(&self, trc: *mut JSTracer) {
+unsafe impl<T: Reflectable> JSTraceable for JS<T> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
#[cfg(debug_assertions)]
- let trace_str = format!("for {} on heap", unsafe { type_name::<T>() });
+ let trace_str = format!("for {} on heap", type_name::<T>());
#[cfg(debug_assertions)]
let trace_info = &trace_str[..];
#[cfg(not(debug_assertions))]
@@ -116,7 +116,7 @@ impl<T: Reflectable> JSTraceable for JS<T> {
trace_reflector(trc,
trace_info,
- unsafe { (**self.ptr).reflector() });
+ (**self.ptr).reflector());
}
}
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 8323c6996ae..6da8e9a1c5f 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -15,7 +15,7 @@
//! This is typically derived via a `#[dom_struct]`
//! (implies `#[derive(JSTraceable)]`) annotation.
//! Non-JS-managed types have an empty inline `trace()` method,
-//! achieved via `no_jsmanaged_fields!` or similar.
+//! achieved via `unsafe_no_jsmanaged_fields!` or similar.
//! 3. For all fields, `Foo::trace()`
//! calls `trace()` on the field.
//! For example, for fields of type `JS<T>`, `JS<T>::trace()` calls
@@ -26,14 +26,14 @@
//! 5. When the GC finishes tracing, it [`finalizes`](../index.html#destruction)
//! any reflectors that were not reachable.
//!
-//! The `no_jsmanaged_fields!()` macro adds an empty implementation of `JSTraceable` to
-//! a datatype.
+//! The `unsafe_no_jsmanaged_fields!()` macro adds an empty implementation of
+//! `JSTraceable` to a datatype.
+use app_units::Au;
use canvas_traits::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle};
use canvas_traits::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
use cssparser::RGBA;
-use devtools_traits::CSSError;
-use devtools_traits::WorkerId;
+use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
use dom::abstractworker::SharedRt;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::js::{JS, Root};
@@ -70,35 +70,38 @@ use net_traits::response::{Response, ResponseBody};
use net_traits::response::HttpsState;
use net_traits::storage_thread::StorageType;
use offscreen_gl_context::GLLimits;
+use parking_lot::RwLock;
use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan;
use script_layout_interface::OpaqueStyleAndLayoutData;
use script_layout_interface::reporter::CSSErrorReporter;
use script_layout_interface::rpc::LayoutRPC;
-use script_runtime::ScriptChan;
use script_traits::{TimerEventId, TimerSource, TouchpadPressurePhase};
use script_traits::{UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use serde::{Deserialize, Serialize};
use servo_atoms::Atom;
use servo_url::ServoUrl;
use smallvec::SmallVec;
-use std::boxed::FnBox;
use std::cell::{Cell, UnsafeCell};
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::hash::{BuildHasher, Hash};
use std::ops::{Deref, DerefMut};
use std::path::PathBuf;
use std::rc::Rc;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::mpsc::{Receiver, Sender};
use std::time::{SystemTime, Instant};
use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
use style::element_state::*;
+use style::font_face::FontFaceRule;
+use style::keyframes::Keyframe;
use style::media_queries::MediaList;
use style::properties::PropertyDeclarationBlock;
use style::selector_parser::{PseudoElement, Snapshot};
+use style::stylesheets::{CssRules, KeyframesRule, MediaRule, NamespaceRule, StyleRule};
use style::values::specified::Length;
+use style::viewport::ViewportRule;
use time::Duration;
use url::Origin as UrlOrigin;
use uuid::Uuid;
@@ -106,18 +109,18 @@ use webrender_traits::{WebGLBufferId, WebGLError, WebGLFramebufferId, WebGLProgr
use webrender_traits::{WebGLRenderbufferId, WebGLShaderId, WebGLTextureId};
/// A trait to allow tracing (only) DOM objects.
-pub trait JSTraceable {
+pub unsafe trait JSTraceable {
/// Trace `self`.
- fn trace(&self, trc: *mut JSTracer);
+ unsafe fn trace(&self, trc: *mut JSTracer);
}
-no_jsmanaged_fields!(CSSError);
+unsafe_no_jsmanaged_fields!(CSSError);
-no_jsmanaged_fields!(EncodingRef);
+unsafe_no_jsmanaged_fields!(EncodingRef);
-no_jsmanaged_fields!(Reflector);
+unsafe_no_jsmanaged_fields!(Reflector);
-no_jsmanaged_fields!(Duration);
+unsafe_no_jsmanaged_fields!(Duration);
/// Trace a `JSVal`.
pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap<JSVal>) {
@@ -154,40 +157,44 @@ pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: &Heap<*mut JS
}
}
-impl<T: JSTraceable> JSTraceable for Rc<T> {
- fn trace(&self, trc: *mut JSTracer) {
+unsafe impl<T: JSTraceable> JSTraceable for Rc<T> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
(**self).trace(trc)
}
}
-impl<T: JSTraceable + ?Sized> JSTraceable for Box<T> {
- fn trace(&self, trc: *mut JSTracer) {
+unsafe impl<T: JSTraceable> JSTraceable for Arc<T> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
(**self).trace(trc)
}
}
-impl<T: JSTraceable + Copy> JSTraceable for Cell<T> {
- fn trace(&self, trc: *mut JSTracer) {
+unsafe impl<T: JSTraceable + ?Sized> JSTraceable for Box<T> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
+ (**self).trace(trc)
+ }
+}
+
+unsafe impl<T: JSTraceable + Copy> JSTraceable for Cell<T> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
self.get().trace(trc)
}
}
-impl<T: JSTraceable> JSTraceable for UnsafeCell<T> {
- fn trace(&self, trc: *mut JSTracer) {
- unsafe { (*self.get()).trace(trc) }
+unsafe impl<T: JSTraceable> JSTraceable for UnsafeCell<T> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
+ (*self.get()).trace(trc)
}
}
-impl<T: JSTraceable> JSTraceable for DOMRefCell<T> {
- fn trace(&self, trc: *mut JSTracer) {
- unsafe {
- (*self).borrow_for_gc_trace().trace(trc)
- }
+unsafe impl<T: JSTraceable> JSTraceable for DOMRefCell<T> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
+ (*self).borrow_for_gc_trace().trace(trc)
}
}
-impl JSTraceable for Heap<*mut JSObject> {
- fn trace(&self, trc: *mut JSTracer) {
+unsafe impl JSTraceable for Heap<*mut JSObject> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
if self.get().is_null() {
return;
}
@@ -195,34 +202,34 @@ impl JSTraceable for Heap<*mut JSObject> {
}
}
-impl JSTraceable for Heap<JSVal> {
- fn trace(&self, trc: *mut JSTracer) {
+unsafe impl JSTraceable for Heap<JSVal> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
trace_jsval(trc, "heap value", self);
}
}
// XXXManishearth Check if the following three are optimized to no-ops
-// if e.trace() is a no-op (e.g it is an no_jsmanaged_fields type)
-impl<T: JSTraceable> JSTraceable for Vec<T> {
+// if e.trace() is a no-op (e.g it is an unsafe_no_jsmanaged_fields type)
+unsafe impl<T: JSTraceable> JSTraceable for Vec<T> {
#[inline]
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
for e in &*self {
e.trace(trc);
}
}
}
-impl<T: JSTraceable> JSTraceable for VecDeque<T> {
+unsafe impl<T: JSTraceable> JSTraceable for VecDeque<T> {
#[inline]
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
for e in &*self {
e.trace(trc);
}
}
}
-impl<T: JSTraceable> JSTraceable for (T, T, T, T) {
- fn trace(&self, trc: *mut JSTracer) {
+unsafe impl<T: JSTraceable> JSTraceable for (T, T, T, T) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
self.0.trace(trc);
self.1.trace(trc);
self.2.trace(trc);
@@ -231,26 +238,26 @@ impl<T: JSTraceable> JSTraceable for (T, T, T, T) {
}
// XXXManishearth Check if the following three are optimized to no-ops
-// if e.trace() is a no-op (e.g it is an no_jsmanaged_fields type)
-impl<T: JSTraceable + 'static> JSTraceable for SmallVec<[T; 1]> {
+// if e.trace() is a no-op (e.g it is an unsafe_no_jsmanaged_fields type)
+unsafe impl<T: JSTraceable + 'static> JSTraceable for SmallVec<[T; 1]> {
#[inline]
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
for e in self.iter() {
e.trace(trc);
}
}
}
-impl<T: JSTraceable> JSTraceable for Option<T> {
+unsafe impl<T: JSTraceable> JSTraceable for Option<T> {
#[inline]
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
self.as_ref().map(|e| e.trace(trc));
}
}
-impl<T: JSTraceable, U: JSTraceable> JSTraceable for Result<T, U> {
+unsafe impl<T: JSTraceable, U: JSTraceable> JSTraceable for Result<T, U> {
#[inline]
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
match *self {
Ok(ref inner) => inner.trace(trc),
Err(ref inner) => inner.trace(trc),
@@ -258,13 +265,13 @@ impl<T: JSTraceable, U: JSTraceable> JSTraceable for Result<T, U> {
}
}
-impl<K, V, S> JSTraceable for HashMap<K, V, S>
+unsafe impl<K, V, S> JSTraceable for HashMap<K, V, S>
where K: Hash + Eq + JSTraceable,
V: JSTraceable,
S: BuildHasher
{
#[inline]
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
for (k, v) in &*self {
k.trace(trc);
v.trace(trc);
@@ -272,9 +279,21 @@ impl<K, V, S> JSTraceable for HashMap<K, V, S>
}
}
-impl<K: Ord + JSTraceable, V: JSTraceable> JSTraceable for BTreeMap<K, V> {
+unsafe impl<T, S> JSTraceable for HashSet<T, S>
+ where T: Hash + Eq + JSTraceable,
+ S: BuildHasher
+{
#[inline]
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
+ for v in &*self {
+ v.trace(trc);
+ }
+ }
+}
+
+unsafe impl<K: Ord + JSTraceable, V: JSTraceable> JSTraceable for BTreeMap<K, V> {
+ #[inline]
+ unsafe fn trace(&self, trc: *mut JSTracer) {
for (k, v) in self {
k.trace(trc);
v.trace(trc);
@@ -282,18 +301,18 @@ impl<K: Ord + JSTraceable, V: JSTraceable> JSTraceable for BTreeMap<K, V> {
}
}
-impl<A: JSTraceable, B: JSTraceable> JSTraceable for (A, B) {
+unsafe impl<A: JSTraceable, B: JSTraceable> JSTraceable for (A, B) {
#[inline]
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
let (ref a, ref b) = *self;
a.trace(trc);
b.trace(trc);
}
}
-impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A, B, C) {
+unsafe impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A, B, C) {
#[inline]
- fn trace(&self, trc: *mut JSTracer) {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
let (ref a, ref b, ref c) = *self;
a.trace(trc);
b.trace(trc);
@@ -301,139 +320,258 @@ impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A, B, C) {
}
}
-no_jsmanaged_fields!(bool, f32, f64, String, ServoUrl, AtomicBool, AtomicUsize, UrlOrigin, Uuid, char);
-no_jsmanaged_fields!(usize, u8, u16, u32, u64);
-no_jsmanaged_fields!(isize, i8, i16, i32, i64);
-no_jsmanaged_fields!(Sender<T>);
-no_jsmanaged_fields!(Receiver<T>);
-no_jsmanaged_fields!(Point2D<T>);
-no_jsmanaged_fields!(Rect<T>);
-no_jsmanaged_fields!(Size2D<T>);
-no_jsmanaged_fields!(Arc<T>);
-no_jsmanaged_fields!(Image, ImageMetadata, ImageCacheChan, ImageCacheThread);
-no_jsmanaged_fields!(Metadata);
-no_jsmanaged_fields!(NetworkError);
-no_jsmanaged_fields!(Atom, Prefix, LocalName, Namespace, QualName);
-no_jsmanaged_fields!(Trusted<T: Reflectable>);
-no_jsmanaged_fields!(TrustedPromise);
-no_jsmanaged_fields!(PropertyDeclarationBlock);
-no_jsmanaged_fields!(HashSet<T>);
+unsafe_no_jsmanaged_fields!(bool, f32, f64, String, ServoUrl, AtomicBool, AtomicUsize, UrlOrigin, Uuid, char);
+unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64);
+unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64);
+unsafe_no_jsmanaged_fields!(Image, ImageMetadata, ImageCacheChan, ImageCacheThread);
+unsafe_no_jsmanaged_fields!(Metadata);
+unsafe_no_jsmanaged_fields!(NetworkError);
+unsafe_no_jsmanaged_fields!(Atom, Prefix, LocalName, Namespace, QualName);
+unsafe_no_jsmanaged_fields!(TrustedPromise);
+unsafe_no_jsmanaged_fields!(PropertyDeclarationBlock);
// These three are interdependent, if you plan to put jsmanaged data
// in one of these make sure it is propagated properly to containing structs
-no_jsmanaged_fields!(FrameId, FrameType, WindowSizeData, WindowSizeType, PipelineId);
-no_jsmanaged_fields!(TimerEventId, TimerSource);
-no_jsmanaged_fields!(WorkerId);
-no_jsmanaged_fields!(BufferQueue, QuirksMode);
-no_jsmanaged_fields!(Runtime);
-no_jsmanaged_fields!(Headers, Method);
-no_jsmanaged_fields!(WindowProxyHandler);
-no_jsmanaged_fields!(UntrustedNodeAddress);
-no_jsmanaged_fields!(LengthOrPercentageOrAuto);
-no_jsmanaged_fields!(RGBA);
-no_jsmanaged_fields!(EuclidLength<Unit, T>);
-no_jsmanaged_fields!(Matrix2D<T>);
-no_jsmanaged_fields!(Matrix4D<T>);
-no_jsmanaged_fields!(StorageType);
-no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);
-no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
-no_jsmanaged_fields!(RepetitionStyle);
-no_jsmanaged_fields!(WebGLError, GLLimits);
-no_jsmanaged_fields!(TimeProfilerChan);
-no_jsmanaged_fields!(MemProfilerChan);
-no_jsmanaged_fields!(PseudoElement);
-no_jsmanaged_fields!(Length);
-no_jsmanaged_fields!(ElementState);
-no_jsmanaged_fields!(DOMString);
-no_jsmanaged_fields!(Mime);
-no_jsmanaged_fields!(AttrIdentifier);
-no_jsmanaged_fields!(AttrValue);
-no_jsmanaged_fields!(Snapshot);
-no_jsmanaged_fields!(PendingRestyle);
-no_jsmanaged_fields!(HttpsState);
-no_jsmanaged_fields!(Request);
-no_jsmanaged_fields!(RequestInit);
-no_jsmanaged_fields!(SharedRt);
-no_jsmanaged_fields!(TouchpadPressurePhase);
-no_jsmanaged_fields!(USVString);
-no_jsmanaged_fields!(ReferrerPolicy);
-no_jsmanaged_fields!(Response);
-no_jsmanaged_fields!(ResponseBody);
-no_jsmanaged_fields!(ResourceThreads);
-no_jsmanaged_fields!(StatusCode);
-no_jsmanaged_fields!(SystemTime);
-no_jsmanaged_fields!(Instant);
-no_jsmanaged_fields!(RelativePos);
-no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
-no_jsmanaged_fields!(PathBuf);
-no_jsmanaged_fields!(CSSErrorReporter);
-no_jsmanaged_fields!(WebGLBufferId);
-no_jsmanaged_fields!(WebGLFramebufferId);
-no_jsmanaged_fields!(WebGLProgramId);
-no_jsmanaged_fields!(WebGLRenderbufferId);
-no_jsmanaged_fields!(WebGLShaderId);
-no_jsmanaged_fields!(WebGLTextureId);
-no_jsmanaged_fields!(MediaList);
-
-impl JSTraceable for Box<ScriptChan + Send> {
+unsafe_no_jsmanaged_fields!(FrameId, FrameType, WindowSizeData, WindowSizeType, PipelineId);
+unsafe_no_jsmanaged_fields!(TimerEventId, TimerSource);
+unsafe_no_jsmanaged_fields!(TimelineMarkerType);
+unsafe_no_jsmanaged_fields!(WorkerId);
+unsafe_no_jsmanaged_fields!(BufferQueue, QuirksMode);
+unsafe_no_jsmanaged_fields!(Runtime);
+unsafe_no_jsmanaged_fields!(Headers, Method);
+unsafe_no_jsmanaged_fields!(WindowProxyHandler);
+unsafe_no_jsmanaged_fields!(UntrustedNodeAddress);
+unsafe_no_jsmanaged_fields!(LengthOrPercentageOrAuto);
+unsafe_no_jsmanaged_fields!(RGBA);
+unsafe_no_jsmanaged_fields!(StorageType);
+unsafe_no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);
+unsafe_no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
+unsafe_no_jsmanaged_fields!(RepetitionStyle);
+unsafe_no_jsmanaged_fields!(WebGLError, GLLimits);
+unsafe_no_jsmanaged_fields!(TimeProfilerChan);
+unsafe_no_jsmanaged_fields!(MemProfilerChan);
+unsafe_no_jsmanaged_fields!(PseudoElement);
+unsafe_no_jsmanaged_fields!(Length);
+unsafe_no_jsmanaged_fields!(ElementState);
+unsafe_no_jsmanaged_fields!(DOMString);
+unsafe_no_jsmanaged_fields!(Mime);
+unsafe_no_jsmanaged_fields!(AttrIdentifier);
+unsafe_no_jsmanaged_fields!(AttrValue);
+unsafe_no_jsmanaged_fields!(Snapshot);
+unsafe_no_jsmanaged_fields!(PendingRestyle);
+unsafe_no_jsmanaged_fields!(HttpsState);
+unsafe_no_jsmanaged_fields!(Request);
+unsafe_no_jsmanaged_fields!(RequestInit);
+unsafe_no_jsmanaged_fields!(SharedRt);
+unsafe_no_jsmanaged_fields!(TouchpadPressurePhase);
+unsafe_no_jsmanaged_fields!(USVString);
+unsafe_no_jsmanaged_fields!(ReferrerPolicy);
+unsafe_no_jsmanaged_fields!(Response);
+unsafe_no_jsmanaged_fields!(ResponseBody);
+unsafe_no_jsmanaged_fields!(ResourceThreads);
+unsafe_no_jsmanaged_fields!(StatusCode);
+unsafe_no_jsmanaged_fields!(SystemTime);
+unsafe_no_jsmanaged_fields!(Instant);
+unsafe_no_jsmanaged_fields!(RelativePos);
+unsafe_no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
+unsafe_no_jsmanaged_fields!(PathBuf);
+unsafe_no_jsmanaged_fields!(CSSErrorReporter);
+unsafe_no_jsmanaged_fields!(WebGLBufferId);
+unsafe_no_jsmanaged_fields!(WebGLFramebufferId);
+unsafe_no_jsmanaged_fields!(WebGLProgramId);
+unsafe_no_jsmanaged_fields!(WebGLRenderbufferId);
+unsafe_no_jsmanaged_fields!(WebGLShaderId);
+unsafe_no_jsmanaged_fields!(WebGLTextureId);
+unsafe_no_jsmanaged_fields!(MediaList);
+
+unsafe impl<'a> JSTraceable for &'a str {
+ #[inline]
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ // Do nothing
+ }
+}
+
+unsafe impl<A, B> JSTraceable for fn(A) -> B {
+ #[inline]
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ // Do nothing
+ }
+}
+
+unsafe impl<T> JSTraceable for IpcSender<T> where T: Deserialize + Serialize {
+ #[inline]
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ // Do nothing
+ }
+}
+
+// Safe thanks to the Send bound.
+unsafe impl JSTraceable for Box<LayoutRPC + Send + 'static> {
+ #[inline]
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ // Do nothing
+ }
+}
+
+unsafe impl JSTraceable for () {
+ #[inline]
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ // Do nothing
+ }
+}
+
+unsafe impl<T> JSTraceable for IpcReceiver<T> where T: Deserialize + Serialize {
+ #[inline]
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ // Do nothing
+ }
+}
+
+unsafe impl<T: Reflectable> JSTraceable for Trusted<T> {
+ #[inline]
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ // Do nothing
+ }
+}
+
+unsafe impl<T: Send> JSTraceable for Receiver<T> {
+ #[inline]
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ // Do nothing
+ }
+}
+
+unsafe impl<T: Send> JSTraceable for Sender<T> {
#[inline]
- fn trace(&self, _trc: *mut JSTracer) {
+ unsafe fn trace(&self, _: *mut JSTracer) {
// Do nothing
}
}
-impl JSTraceable for Box<FnBox(f64, )> {
+unsafe impl JSTraceable for Matrix2D<f32> {
#[inline]
- fn trace(&self, _trc: *mut JSTracer) {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}
-impl<'a> JSTraceable for &'a str {
+unsafe impl JSTraceable for Matrix4D<f64> {
#[inline]
- fn trace(&self, _: *mut JSTracer) {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}
-impl<A, B> JSTraceable for fn(A) -> B {
+unsafe impl JSTraceable for Point2D<f32> {
#[inline]
- fn trace(&self, _: *mut JSTracer) {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}
-impl<T> JSTraceable for IpcSender<T> where T: Deserialize + Serialize {
+unsafe impl<T> JSTraceable for EuclidLength<u64, T> {
#[inline]
- fn trace(&self, _: *mut JSTracer) {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}
-impl JSTraceable for Box<LayoutRPC + 'static> {
+unsafe impl JSTraceable for Rect<Au> {
#[inline]
- fn trace(&self, _: *mut JSTracer) {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}
-impl JSTraceable for () {
+unsafe impl JSTraceable for Rect<f32> {
#[inline]
- fn trace(&self, _: *mut JSTracer) {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}
-impl<T> JSTraceable for IpcReceiver<T> where T: Deserialize + Serialize {
+unsafe impl JSTraceable for Size2D<i32> {
#[inline]
- fn trace(&self, _: *mut JSTracer) {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}
+unsafe impl JSTraceable for Mutex<Option<SharedRt>> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<FontFaceRule> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<CssRules> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<Keyframe> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<KeyframesRule> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<MediaRule> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<NamespaceRule> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<StyleRule> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<ViewportRule> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<PropertyDeclarationBlock> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<SharedRt> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
+unsafe impl JSTraceable for RwLock<MediaList> {
+ unsafe fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing.
+ }
+}
+
/// Homemade trait object for JSTraceable things
struct TraceableInfo {
pub ptr: *const libc::c_void,
- pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer),
+ pub trace: unsafe fn(obj: *const libc::c_void, tracer: *mut JSTracer),
}
/// Holds a set of JSTraceables that need to be rooted
@@ -474,8 +612,8 @@ impl RootedTraceableSet {
unsafe fn add<T: JSTraceable>(traceable: &T) {
ROOTED_TRACEABLES.with(|ref traceables| {
- fn trace<T: JSTraceable>(obj: *const libc::c_void, tracer: *mut JSTracer) {
- let obj: &T = unsafe { &*(obj as *const T) };
+ unsafe fn trace<T: JSTraceable>(obj: *const libc::c_void, tracer: *mut JSTracer) {
+ let obj: &T = &*(obj as *const T);
obj.trace(tracer);
}
diff --git a/components/script/dom/bindings/weakref.rs b/components/script/dom/bindings/weakref.rs
index 761aaf7721c..68feff79180 100644
--- a/components/script/dom/bindings/weakref.rs
+++ b/components/script/dom/bindings/weakref.rs
@@ -133,7 +133,11 @@ impl<T: WeakReferenceable> PartialEq<T> for WeakRef<T> {
}
}
-no_jsmanaged_fields!(WeakRef<T: WeakReferenceable>);
+unsafe impl<T: WeakReferenceable> JSTraceable for WeakRef<T> {
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ // Do nothing.
+ }
+}
impl<T: WeakReferenceable> Drop for WeakRef<T> {
fn drop(&mut self) {
@@ -188,17 +192,15 @@ impl<T: WeakReferenceable> HeapSizeOf for MutableWeakRef<T> {
}
}
-impl<T: WeakReferenceable> JSTraceable for MutableWeakRef<T> {
- fn trace(&self, _: *mut JSTracer) {
+unsafe impl<T: WeakReferenceable> JSTraceable for MutableWeakRef<T> {
+ unsafe fn trace(&self, _: *mut JSTracer) {
let ptr = self.cell.get();
- unsafe {
- let should_drop = match *ptr {
- Some(ref value) => !value.is_alive(),
- None => false,
- };
- if should_drop {
- mem::drop((*ptr).take().unwrap());
- }
+ let should_drop = match *ptr {
+ Some(ref value) => !value.is_alive(),
+ None => false,
+ };
+ if should_drop {
+ mem::drop((*ptr).take().unwrap());
}
}
}
diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs
index aa2c4c4639a..61a9588dfab 100644
--- a/components/script/dom/bluetooth.rs
+++ b/components/script/dom/bluetooth.rs
@@ -21,9 +21,6 @@ use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::bluetoothadvertisingdata::BluetoothAdvertisingData;
use dom::bluetoothdevice::BluetoothDevice;
-use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
-use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor;
-use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
@@ -90,9 +87,6 @@ impl<Listener: AsyncBluetoothListener + Reflectable> BluetoothResponseListener f
pub struct Bluetooth {
eventtarget: EventTarget,
device_instance_map: DOMRefCell<HashMap<String, MutHeap<JS<BluetoothDevice>>>>,
- service_instance_map: DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTService>>>>,
- characteristic_instance_map: DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTCharacteristic>>>>,
- descriptor_instance_map: DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTDescriptor>>>>,
}
impl Bluetooth {
@@ -100,9 +94,6 @@ impl Bluetooth {
Bluetooth {
eventtarget: EventTarget::new_inherited(),
device_instance_map: DOMRefCell::new(HashMap::new()),
- service_instance_map: DOMRefCell::new(HashMap::new()),
- characteristic_instance_map: DOMRefCell::new(HashMap::new()),
- descriptor_instance_map: DOMRefCell::new(HashMap::new()),
}
}
@@ -112,19 +103,6 @@ impl Bluetooth {
BluetoothBinding::Wrap)
}
- pub fn get_service_map(&self) -> &DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTService>>>> {
- &self.service_instance_map
- }
-
- pub fn get_characteristic_map(&self)
- -> &DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTCharacteristic>>>> {
- &self.characteristic_instance_map
- }
-
- pub fn get_descriptor_map(&self) -> &DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTDescriptor>>>> {
- &self.descriptor_instance_map
- }
-
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
self.global().as_window().bluetooth_thread()
}
diff --git a/components/script/dom/bluetoothdevice.rs b/components/script/dom/bluetoothdevice.rs
index 4af6b2a4f59..5bd3bd8233d 100644
--- a/components/script/dom/bluetoothdevice.rs
+++ b/components/script/dom/bluetoothdevice.rs
@@ -2,17 +2,26 @@
* 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 bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothDescriptorMsg, BluetoothServiceMsg};
+use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding;
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
+use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::js::{JS, Root, MutHeap, MutNullableHeap};
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::bluetooth::Bluetooth;
use dom::bluetoothadvertisingdata::BluetoothAdvertisingData;
+use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
+use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
+use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor;
use dom::bluetoothremotegattserver::BluetoothRemoteGATTServer;
+use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
+use std::collections::HashMap;
+
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothdevice
#[dom_struct]
@@ -23,6 +32,9 @@ pub struct BluetoothDevice {
ad_data: MutHeap<JS<BluetoothAdvertisingData>>,
gatt: MutNullableHeap<JS<BluetoothRemoteGATTServer>>,
context: MutHeap<JS<Bluetooth>>,
+ attribute_instance_map: (DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTService>>>>,
+ DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTCharacteristic>>>>,
+ DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTDescriptor>>>>),
}
impl BluetoothDevice {
@@ -38,6 +50,9 @@ impl BluetoothDevice {
ad_data: MutHeap::new(ad_data),
gatt: Default::default(),
context: MutHeap::new(context),
+ attribute_instance_map: (DOMRefCell::new(HashMap::new()),
+ DOMRefCell::new(HashMap::new()),
+ DOMRefCell::new(HashMap::new())),
}
}
@@ -55,8 +70,68 @@ impl BluetoothDevice {
BluetoothDeviceBinding::Wrap)
}
- pub fn get_context(&self) -> Root<Bluetooth> {
- self.context.get()
+ pub fn get_or_create_service(&self,
+ service: &BluetoothServiceMsg,
+ server: &BluetoothRemoteGATTServer)
+ -> Root<BluetoothRemoteGATTService> {
+ let (ref service_map_ref, _, _) = self.attribute_instance_map;
+ let mut service_map = service_map_ref.borrow_mut();
+ if let Some(existing_service) = service_map.get(&service.instance_id) {
+ return existing_service.get();
+ }
+ let bt_service = BluetoothRemoteGATTService::new(&server.global(),
+ &server.Device(),
+ DOMString::from(service.uuid.clone()),
+ service.is_primary,
+ service.instance_id.clone());
+ service_map.insert(service.instance_id.clone(), MutHeap::new(&bt_service));
+ return bt_service;
+ }
+
+ pub fn get_or_create_characteristic(&self,
+ characteristic: &BluetoothCharacteristicMsg,
+ service: &BluetoothRemoteGATTService)
+ -> Root<BluetoothRemoteGATTCharacteristic> {
+ let (_, ref characteristic_map_ref, _) = self.attribute_instance_map;
+ let mut characteristic_map = characteristic_map_ref.borrow_mut();
+ if let Some(existing_characteristic) = characteristic_map.get(&characteristic.instance_id) {
+ return existing_characteristic.get();
+ }
+ let properties =
+ BluetoothCharacteristicProperties::new(&service.global(),
+ characteristic.broadcast,
+ characteristic.read,
+ characteristic.write_without_response,
+ characteristic.write,
+ characteristic.notify,
+ characteristic.indicate,
+ characteristic.authenticated_signed_writes,
+ characteristic.reliable_write,
+ characteristic.writable_auxiliaries);
+ let bt_characteristic = BluetoothRemoteGATTCharacteristic::new(&service.global(),
+ service,
+ DOMString::from(characteristic.uuid.clone()),
+ &properties,
+ characteristic.instance_id.clone());
+ characteristic_map.insert(characteristic.instance_id.clone(), MutHeap::new(&bt_characteristic));
+ return bt_characteristic;
+ }
+
+ pub fn get_or_create_descriptor(&self,
+ descriptor: &BluetoothDescriptorMsg,
+ characteristic: &BluetoothRemoteGATTCharacteristic)
+ -> Root<BluetoothRemoteGATTDescriptor> {
+ let (_, _, ref descriptor_map_ref) = self.attribute_instance_map;
+ let mut descriptor_map = descriptor_map_ref.borrow_mut();
+ if let Some(existing_descriptor) = descriptor_map.get(&descriptor.instance_id) {
+ return existing_descriptor.get();
+ }
+ let bt_descriptor = BluetoothRemoteGATTDescriptor::new(&characteristic.global(),
+ characteristic,
+ DOMString::from(descriptor.uuid.clone()),
+ descriptor.instance_id.clone());
+ descriptor_map.insert(descriptor.instance_id.clone(), MutHeap::new(&bt_descriptor));
+ return bt_descriptor;
}
}
diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs
index 3c3c86001fb..ecbb77b64a2 100644
--- a/components/script/dom/bluetoothremotegattcharacteristic.rs
+++ b/components/script/dom/bluetoothremotegattcharacteristic.rs
@@ -21,7 +21,6 @@ use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::{ByteString, DOMString};
use dom::bluetooth::{AsyncBluetoothListener, response_async};
use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
-use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor;
use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
use dom::bluetoothuuid::{BluetoothDescriptorUUID, BluetoothUUID};
use dom::eventtarget::EventTarget;
@@ -330,21 +329,13 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) {
+ let device = self.Service().Device();
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
// Step 7.
BluetoothResponse::GetDescriptor(descriptor) => {
- let context = self.service.get().get_device().get_context();
- let mut descriptor_map = context.get_descriptor_map().borrow_mut();
- if let Some(existing_descriptor) = descriptor_map.get(&descriptor.instance_id) {
- return promise.resolve_native(promise_cx, &existing_descriptor.get());
- }
- let bt_descriptor = BluetoothRemoteGATTDescriptor::new(&self.global(),
- self,
- DOMString::from(descriptor.uuid),
- descriptor.instance_id.clone());
- descriptor_map.insert(descriptor.instance_id, MutHeap::new(&bt_descriptor));
+ let bt_descriptor = device.get_or_create_descriptor(&descriptor, &self);
promise.resolve_native(promise_cx, &bt_descriptor);
},
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors
@@ -352,21 +343,8 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
// Step 7.
BluetoothResponse::GetDescriptors(descriptors_vec) => {
let mut descriptors = vec!();
- let context = self.service.get().get_device().get_context();
- let mut descriptor_map = context.get_descriptor_map().borrow_mut();
for descriptor in descriptors_vec {
- let bt_descriptor = match descriptor_map.get(&descriptor.instance_id) {
- Some(existing_descriptor) => existing_descriptor.get(),
- None => {
- BluetoothRemoteGATTDescriptor::new(&self.global(),
- self,
- DOMString::from(descriptor.uuid),
- descriptor.instance_id.clone())
- },
- };
- if !descriptor_map.contains_key(&descriptor.instance_id) {
- descriptor_map.insert(descriptor.instance_id, MutHeap::new(&bt_descriptor));
- }
+ let bt_descriptor = device.get_or_create_descriptor(&descriptor, &self);
descriptors.push(bt_descriptor);
}
promise.resolve_native(promise_cx, &descriptors);
diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs
index 06c11f0aa21..f325414e230 100644
--- a/components/script/dom/bluetoothremotegattserver.rs
+++ b/components/script/dom/bluetoothremotegattserver.rs
@@ -11,10 +11,8 @@ use dom::bindings::error::Error::{self, Network, Security};
use dom::bindings::error::ErrorResult;
use dom::bindings::js::{JS, MutHeap, Root};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
-use dom::bindings::str::DOMString;
use dom::bluetooth::{AsyncBluetoothListener, response_async};
use dom::bluetoothdevice::BluetoothDevice;
-use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
use dom::globalscope::GlobalScope;
use dom::promise::Promise;
@@ -90,7 +88,10 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
fn Disconnect(&self) -> ErrorResult {
// TODO: Step 1: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer.
- // TODO: Step 2: Check if this.connected is false here too.
+ // Step 2.
+ if !self.Connected() {
+ return Ok(());
+ }
let (sender, receiver) = ipc::channel().unwrap();
self.get_bluetooth_thread().send(
BluetoothRequest::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap();
@@ -197,6 +198,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) {
+ let device = self.Device();
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
BluetoothResponse::GATTServerConnect(connected) => {
@@ -210,17 +212,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
// Step 7.
BluetoothResponse::GetPrimaryService(service) => {
- let context = self.device.get().get_context();
- let mut service_map = context.get_service_map().borrow_mut();
- if let Some(existing_service) = service_map.get(&service.instance_id) {
- promise.resolve_native(promise_cx, &existing_service.get());
- }
- let bt_service = BluetoothRemoteGATTService::new(&self.global(),
- &self.device.get(),
- DOMString::from(service.uuid),
- service.is_primary,
- service.instance_id.clone());
- service_map.insert(service.instance_id, MutHeap::new(&bt_service));
+ let bt_service = device.get_or_create_service(&service, &self);
promise.resolve_native(promise_cx, &bt_service);
},
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
@@ -228,22 +220,8 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
// Step 7.
BluetoothResponse::GetPrimaryServices(services_vec) => {
let mut services = vec!();
- let context = self.device.get().get_context();
- let mut service_map = context.get_service_map().borrow_mut();
for service in services_vec {
- let bt_service = match service_map.get(&service.instance_id) {
- Some(existing_service) => existing_service.get(),
- None => {
- BluetoothRemoteGATTService::new(&self.global(),
- &self.device.get(),
- DOMString::from(service.uuid),
- service.is_primary,
- service.instance_id.clone())
- },
- };
- if !service_map.contains_key(&service.instance_id) {
- service_map.insert(service.instance_id, MutHeap::new(&bt_service));
- }
+ let bt_service = device.get_or_create_service(&service, &self);
services.push(bt_service);
}
promise.resolve_native(promise_cx, &services);
diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs
index ef922e9b385..60fcc694ed8 100644
--- a/components/script/dom/bluetoothremotegattservice.rs
+++ b/components/script/dom/bluetoothremotegattservice.rs
@@ -14,9 +14,7 @@ use dom::bindings::js::{JS, MutHeap, Root};
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::bluetooth::{AsyncBluetoothListener, response_async};
-use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
use dom::bluetoothdevice::BluetoothDevice;
-use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUID, BluetoothUUID};
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
@@ -64,10 +62,6 @@ impl BluetoothRemoteGATTService {
BluetoothRemoteGATTServiceBinding::Wrap)
}
- pub fn get_device(&self) -> Root<BluetoothDevice> {
- self.device.get()
- }
-
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
self.global().as_window().bluetooth_thread()
}
@@ -276,33 +270,13 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
impl AsyncBluetoothListener for BluetoothRemoteGATTService {
fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) {
+ let device = self.Device();
match response {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
// Step 7.
BluetoothResponse::GetCharacteristic(characteristic) => {
- let context = self.device.get().get_context();
- let mut characteristic_map = context.get_characteristic_map().borrow_mut();
- if let Some(existing_characteristic) = characteristic_map.get(&characteristic.instance_id) {
- return promise.resolve_native(promise_cx, &existing_characteristic.get());
- }
- let properties =
- BluetoothCharacteristicProperties::new(&self.global(),
- characteristic.broadcast,
- characteristic.read,
- characteristic.write_without_response,
- characteristic.write,
- characteristic.notify,
- characteristic.indicate,
- characteristic.authenticated_signed_writes,
- characteristic.reliable_write,
- characteristic.writable_auxiliaries);
- let bt_characteristic = BluetoothRemoteGATTCharacteristic::new(&self.global(),
- self,
- DOMString::from(characteristic.uuid),
- &properties,
- characteristic.instance_id.clone());
- characteristic_map.insert(characteristic.instance_id, MutHeap::new(&bt_characteristic));
+ let bt_characteristic = device.get_or_create_characteristic(&characteristic, &self);
promise.resolve_native(promise_cx, &bt_characteristic);
},
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
@@ -310,34 +284,8 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService {
// Step 7.
BluetoothResponse::GetCharacteristics(characteristics_vec) => {
let mut characteristics = vec!();
- let context = self.device.get().get_context();
- let mut characteristic_map = context.get_characteristic_map().borrow_mut();
for characteristic in characteristics_vec {
- let bt_characteristic = match characteristic_map.get(&characteristic.instance_id) {
- Some(existing_characteristic) => existing_characteristic.get(),
- None => {
- let properties =
- BluetoothCharacteristicProperties::new(&self.global(),
- characteristic.broadcast,
- characteristic.read,
- characteristic.write_without_response,
- characteristic.write,
- characteristic.notify,
- characteristic.indicate,
- characteristic.authenticated_signed_writes,
- characteristic.reliable_write,
- characteristic.writable_auxiliaries);
-
- BluetoothRemoteGATTCharacteristic::new(&self.global(),
- self,
- DOMString::from(characteristic.uuid),
- &properties,
- characteristic.instance_id.clone())
- },
- };
- if !characteristic_map.contains_key(&characteristic.instance_id) {
- characteristic_map.insert(characteristic.instance_id, MutHeap::new(&bt_characteristic));
- }
+ let bt_characteristic = device.get_or_create_characteristic(&characteristic, &self);
characteristics.push(bt_characteristic);
}
promise.resolve_native(promise_cx, &characteristics);
diff --git a/components/script/dom/bluetoothuuid.rs b/components/script/dom/bluetoothuuid.rs
index fbf49142aa3..e16d8141e50 100644
--- a/components/script/dom/bluetoothuuid.rs
+++ b/components/script/dom/bluetoothuuid.rs
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong;
-use dom::bindings::error::Error::Syntax;
+use dom::bindings::error::Error::Type;
use dom::bindings::error::Fallible;
use dom::bindings::reflector::Reflector;
use dom::bindings::str::DOMString;
@@ -267,7 +267,19 @@ const BASE_UUID: &'static str = "-0000-1000-8000-00805f9b34fb";
const SERVICE_PREFIX: &'static str = "org.bluetooth.service";
const CHARACTERISTIC_PREFIX: &'static str = "org.bluetooth.characteristic";
const DESCRIPTOR_PREFIX: &'static str = "org.bluetooth.descriptor";
-const VALID_UUID_REGEX: &'static str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
+const VALID_UUID_REGEX: &'static str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
+// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=314
+const UUID_ERROR_MESSAGE: &'static str = "It must be a valid UUID alias (e.g. 0x1234), \
+ UUID (lowercase hex characters e.g. '00001234-0000-1000-8000-00805f9b34fb'),\nor recognized standard name from";
+// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=321
+const SERVICES_ERROR_MESSAGE: &'static str = "https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx\
+ \ne.g. 'alert_notification'.";
+// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=327
+const CHARACTERISTIC_ERROR_MESSAGE: &'static str = "https://developer.bluetooth.org/gatt/characteristics/Pages/\
+ CharacteristicsHome.aspx\ne.g. 'aerobic_heart_rate_lower_limit'.";
+// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/bluetooth/BluetoothUUID.cpp?l=333
+const DESCRIPTOR_ERROR_MESSAGE: &'static str = "https://developer.bluetooth.org/gatt/descriptors/Pages/\
+ DescriptorsHomePage.aspx\ne.g. 'gatt.characteristic_presentation_format'.";
impl BluetoothUUID {
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-canonicaluuid
@@ -296,7 +308,7 @@ impl BluetoothUUID {
resolve_uuid_name(name, BLUETOOTH_ASSIGNED_SERVICES, SERVICE_PREFIX)
}
- pub fn characteristic(name: BluetoothServiceUUID) -> Fallible<UUID> {
+ pub fn characteristic(name: BluetoothCharacteristicUUID) -> Fallible<UUID> {
resolve_uuid_name(name, BLUETOOTH_ASSIGNED_CHARCTERISTICS, CHARACTERISTIC_PREFIX)
}
@@ -325,22 +337,35 @@ fn resolve_uuid_name(
prefix: &str)
-> Fallible<DOMString> {
match name {
- // Step 1
+ // Step 1.
StringOrUnsignedLong::UnsignedLong(unsigned32) => {
Ok(canonical_uuid(unsigned32))
},
StringOrUnsignedLong::String(dstring) => {
- // Step 2
+ // Step 2.
let regex = Regex::new(VALID_UUID_REGEX).unwrap();
if regex.is_match(&*dstring) {
Ok(dstring)
} else {
- // Step 3
+ // Step 3.
let concatenated = format!("{}.{}", prefix, dstring);
let is_in_table = assigned_numbers_table.iter().find(|p| p.0 == concatenated);
match is_in_table {
Some(&(_, alias)) => Ok(canonical_uuid(alias)),
- None => Err(Syntax),
+ None => {
+ let (attribute_type, error_url_message) = match prefix {
+ SERVICE_PREFIX => ("Service", SERVICES_ERROR_MESSAGE),
+ CHARACTERISTIC_PREFIX => ("Characteristic", CHARACTERISTIC_ERROR_MESSAGE),
+ DESCRIPTOR_PREFIX => ("Descriptor", DESCRIPTOR_ERROR_MESSAGE),
+ _ => unreachable!(),
+ };
+ // Step 4.
+ return Err(Type(format!("Invalid {} name : '{}'.\n{} {}",
+ attribute_type,
+ dstring,
+ UUID_ERROR_MESSAGE,
+ error_url_message)));
+ },
}
}
},
diff --git a/components/script/dom/crypto.rs b/components/script/dom/crypto.rs
index 22466f3f14c..4120456c77c 100644
--- a/components/script/dom/crypto.rs
+++ b/components/script/dom/crypto.rs
@@ -15,7 +15,7 @@ use js::jsapi::{JSContext, JSObject};
use js::jsapi::{JS_GetArrayBufferViewType, Type};
use rand::{OsRng, Rng};
-no_jsmanaged_fields!(OsRng);
+unsafe_no_jsmanaged_fields!(OsRng);
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto
#[dom_struct]
diff --git a/components/script/dom/cssrulelist.rs b/components/script/dom/cssrulelist.rs
index 5f594c27d8c..9c55f561806 100644
--- a/components/script/dom/cssrulelist.rs
+++ b/components/script/dom/cssrulelist.rs
@@ -16,8 +16,10 @@ use parking_lot::RwLock;
use std::sync::Arc;
use style::stylesheets::{CssRules, KeyframesRule, RulesMutateError};
-no_jsmanaged_fields!(RulesSource);
-no_jsmanaged_fields!(CssRules);
+#[allow(unsafe_code)]
+unsafe_no_jsmanaged_fields!(RulesSource);
+
+unsafe_no_jsmanaged_fields!(CssRules);
impl From<RulesMutateError> for Error {
fn from(other: RulesMutateError) -> Self {
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index cf63dfcfb9a..468f127f7ad 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -3,9 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use core::nonzero::NonZero;
+use devtools_traits::ScriptToDevtoolsControlMsg;
use document_loader::{DocumentLoader, LoadType};
use dom::activation::{ActivationSource, synthetic_click_activation};
use dom::attr::Attr;
+use dom::bindings::callback::ExceptionHandling;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
use dom::bindings::codegen::Bindings::DocumentBinding;
@@ -18,7 +20,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter;
use dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods;
use dom::bindings::codegen::Bindings::TouchBinding::TouchMethods;
-use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, WindowMethods};
+use dom::bindings::codegen::Bindings::WindowBinding::{FrameRequestCallback, ScrollBehavior, WindowMethods};
use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
@@ -87,6 +89,7 @@ use dom::window::{ReflowReason, Window};
use encoding::EncodingRef;
use encoding::all::UTF_8;
use euclid::point::Point2D;
+use gfx_traits::ScrollRootId;
use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks, QuirksMode};
use html5ever_atoms::{LocalName, QualName};
use ipc_channel::ipc::{self, IpcSender};
@@ -111,7 +114,6 @@ use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
-use std::boxed::FnBox;
use std::cell::{Cell, Ref, RefMut};
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -232,8 +234,7 @@ pub struct Document {
animation_frame_ident: Cell<u32>,
/// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks
/// List of animation frame callbacks
- #[ignore_heap_size_of = "closures are hard"]
- animation_frame_list: DOMRefCell<Vec<(u32, Option<Box<FnBox(f64)>>)>>,
+ animation_frame_list: DOMRefCell<Vec<(u32, Option<AnimationFrameCallback>)>>,
/// Whether we're in the process of running animation callbacks.
///
/// Tracking this is not necessary for correctness. Instead, it is an optimization to avoid
@@ -641,7 +642,10 @@ impl Document {
if let Some((x, y)) = point {
// Step 3
- self.window.perform_a_scroll(x, y, ScrollBehavior::Instant,
+ self.window.perform_a_scroll(x,
+ y,
+ ScrollRootId::root(),
+ ScrollBehavior::Instant,
target.r());
}
}
@@ -1479,7 +1483,7 @@ impl Document {
}
/// https://html.spec.whatwg.org/multipage/#dom-window-requestanimationframe
- pub fn request_animation_frame(&self, callback: Box<FnBox(f64)>) -> u32 {
+ pub fn request_animation_frame(&self, callback: AnimationFrameCallback) -> u32 {
let ident = self.animation_frame_ident.get() + 1;
self.animation_frame_ident.set(ident);
@@ -1520,7 +1524,7 @@ impl Document {
for (_, callback) in animation_frame_list.drain(..) {
if let Some(callback) = callback {
- callback(*timing);
+ callback.call(self, *timing);
}
}
@@ -3201,3 +3205,29 @@ pub enum FocusEventType {
Focus, // Element gained focus. Doesn't bubble.
Blur, // Element lost focus. Doesn't bubble.
}
+
+#[derive(HeapSizeOf, JSTraceable)]
+pub enum AnimationFrameCallback {
+ DevtoolsFramerateTick { actor_name: String },
+ FrameRequestCallback {
+ #[ignore_heap_size_of = "Rc is hard"]
+ callback: Rc<FrameRequestCallback>
+ },
+}
+
+impl AnimationFrameCallback {
+ fn call(&self, document: &Document, now: f64) {
+ match *self {
+ AnimationFrameCallback::DevtoolsFramerateTick { ref actor_name } => {
+ let msg = ScriptToDevtoolsControlMsg::FramerateTick(actor_name.clone(), now);
+ let devtools_sender = document.window().upcast::<GlobalScope>().devtools_chan().unwrap();
+ devtools_sender.send(msg).unwrap();
+ }
+ AnimationFrameCallback::FrameRequestCallback { ref callback } => {
+ // TODO(jdm): The spec says that any exceptions should be suppressed:
+ // https://github.com/servo/servo/issues/6928
+ let _ = callback.Call__(Finite::wrap(now), ExceptionHandling::Report);
+ }
+ }
+ }
+}
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index c322b96a555..87674c835d0 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -109,6 +109,7 @@ impl HTMLIFrameElement {
let old_pipeline_id = self.pipeline_id.get();
let new_pipeline_id = PipelineId::new();
self.pipeline_id.set(Some(new_pipeline_id));
+ debug!("Frame {} created pipeline {}.", self.frame_id, new_pipeline_id);
(old_pipeline_id, new_pipeline_id)
}
@@ -692,6 +693,7 @@ impl VirtualMethods for HTMLIFrameElement {
// iframe attributes for the "first time"."
if self.upcast::<Node>().is_in_doc_with_browsing_context() {
debug!("iframe {} bound to browsing context.", self.frame_id);
+ debug_assert!(tree_in_doc, "is_in_doc_with_bc, but not tree_in_doc");
self.create_nested_browsing_context();
self.process_the_iframe_attributes(ProcessingMode::FirstTime);
}
@@ -705,6 +707,7 @@ impl VirtualMethods for HTMLIFrameElement {
// https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded
if let Some(pipeline_id) = self.pipeline_id.get() {
+ debug!("Unbinding pipeline {} from frame {}.", pipeline_id, self.frame_id);
let window = window_from_node(self);
// The only reason we're waiting for the iframe to be totally
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index f0518c55f88..e158caac17e 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -50,7 +50,7 @@ use style::parser::ParserContextExtraData;
use style::str::HTML_SPACE_CHARACTERS;
use style::stylesheets::{Stylesheet, Origin};
-no_jsmanaged_fields!(Stylesheet);
+unsafe_no_jsmanaged_fields!(Stylesheet);
#[dom_struct]
pub struct HTMLLinkElement {
diff --git a/components/script/dom/keyboardevent.rs b/components/script/dom/keyboardevent.rs
index 99cc61e021f..38a25d4dc1e 100644
--- a/components/script/dom/keyboardevent.rs
+++ b/components/script/dom/keyboardevent.rs
@@ -19,7 +19,7 @@ use msg::constellation_msg::{Key, KeyModifiers};
use std::borrow::Cow;
use std::cell::Cell;
-no_jsmanaged_fields!(Key);
+unsafe_no_jsmanaged_fields!(Key);
#[dom_struct]
pub struct KeyboardEvent {
diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs
index 53c5bd20115..99b06bae39d 100644
--- a/components/script/dom/macros.rs
+++ b/components/script/dom/macros.rs
@@ -302,38 +302,31 @@ macro_rules! make_nonzero_dimension_setter(
/// For use on non-jsmanaged types
/// Use #[derive(JSTraceable)] on JS managed types
-macro_rules! no_jsmanaged_fields(
- ([$ty:ident; $count:expr]) => (
- impl $crate::dom::bindings::trace::JSTraceable for [$ty; $count] {
- #[inline]
- fn trace(&self, _: *mut ::js::jsapi::JSTracer) {
- // Do nothing
- }
- }
- );
+macro_rules! unsafe_no_jsmanaged_fields(
($($ty:ident),+) => (
$(
- impl $crate::dom::bindings::trace::JSTraceable for $ty {
+ #[allow(unsafe_code)]
+ unsafe impl $crate::dom::bindings::trace::JSTraceable for $ty {
#[inline]
- fn trace(&self, _: *mut ::js::jsapi::JSTracer) {
+ unsafe fn trace(&self, _: *mut ::js::jsapi::JSTracer) {
// Do nothing
}
}
)+
);
- ($ty:ident<$($gen:ident),+>) => (
- impl<$($gen),+> $crate::dom::bindings::trace::JSTraceable for $ty<$($gen),+> {
- #[inline]
- fn trace(&self, _: *mut ::js::jsapi::JSTracer) {
- // Do nothing
- }
- }
- );
- ($ty:ident<$($gen:ident: $bound:ident),+>) => (
- impl<$($gen: $bound),+> $crate::dom::bindings::trace::JSTraceable for $ty<$($gen),+> {
+);
+
+macro_rules! jsmanaged_array(
+ ($count:expr) => (
+ #[allow(unsafe_code)]
+ unsafe impl<T> $crate::dom::bindings::trace::JSTraceable for [T; $count]
+ where T: $crate::dom::bindings::trace::JSTraceable
+ {
#[inline]
- fn trace(&self, _: *mut ::js::jsapi::JSTracer) {
- // Do nothing
+ unsafe fn trace(&self, tracer: *mut ::js::jsapi::JSTracer) {
+ for v in self.iter() {
+ v.trace(tracer);
+ }
}
}
);
diff --git a/components/script/dom/mediaquerylist.rs b/components/script/dom/mediaquerylist.rs
index 8b77bc4155b..86f67cdd8a1 100644
--- a/components/script/dom/mediaquerylist.rs
+++ b/components/script/dom/mediaquerylist.rs
@@ -143,8 +143,9 @@ impl WeakMediaQueryListVec {
}
}
-impl JSTraceable for WeakMediaQueryListVec {
- fn trace(&self, _: *mut JSTracer) {
+#[allow(unsafe_code)]
+unsafe impl JSTraceable for WeakMediaQueryListVec {
+ unsafe fn trace(&self, _: *mut JSTracer) {
self.cell.borrow_mut().retain_alive()
}
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index f08b1480eef..5f979bd8c9f 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -2566,7 +2566,7 @@ struct UniqueId {
cell: UnsafeCell<Option<Box<Uuid>>>,
}
-no_jsmanaged_fields!(UniqueId);
+unsafe_no_jsmanaged_fields!(UniqueId);
impl HeapSizeOf for UniqueId {
#[allow(unsafe_code)]
diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs
index b2507aeab3b..723239ea3d3 100644
--- a/components/script/dom/range.rs
+++ b/components/script/dom/range.rs
@@ -1262,8 +1262,8 @@ impl HeapSizeOf for WeakRangeVec {
}
#[allow(unsafe_code)]
-impl JSTraceable for WeakRangeVec {
- fn trace(&self, _: *mut JSTracer) {
- unsafe { (*self.cell.get()).retain_alive() }
+unsafe impl JSTraceable for WeakRangeVec {
+ unsafe fn trace(&self, _: *mut JSTracer) {
+ (*self.cell.get()).retain_alive()
}
}
diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs
index 0f806171a9b..ac6330c3ca2 100644
--- a/components/script/dom/servoparser/html.rs
+++ b/components/script/dom/servoparser/html.rs
@@ -96,8 +96,9 @@ impl Tokenizer {
}
}
-impl JSTraceable for HtmlTokenizer<TreeBuilder<JS<Node>, Sink>> {
- fn trace(&self, trc: *mut JSTracer) {
+#[allow(unsafe_code)]
+unsafe impl JSTraceable for HtmlTokenizer<TreeBuilder<JS<Node>, Sink>> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
struct Tracer(*mut JSTracer);
let tracer = Tracer(trc);
@@ -105,7 +106,7 @@ impl JSTraceable for HtmlTokenizer<TreeBuilder<JS<Node>, Sink>> {
type Handle = JS<Node>;
#[allow(unrooted_must_root)]
fn trace_handle(&self, node: &JS<Node>) {
- node.trace(self.0);
+ unsafe { node.trace(self.0); }
}
}
diff --git a/components/script/dom/servoparser/xml.rs b/components/script/dom/servoparser/xml.rs
index 9d527ce21d1..bcbfa6c4169 100644
--- a/components/script/dom/servoparser/xml.rs
+++ b/components/script/dom/servoparser/xml.rs
@@ -72,8 +72,9 @@ impl Tokenizer {
}
}
-impl JSTraceable for XmlTokenizer<XmlTreeBuilder<JS<Node>, Sink>> {
- fn trace(&self, trc: *mut JSTracer) {
+#[allow(unsafe_code)]
+unsafe impl JSTraceable for XmlTokenizer<XmlTreeBuilder<JS<Node>, Sink>> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
struct Tracer(*mut JSTracer);
let tracer = Tracer(trc);
@@ -81,7 +82,7 @@ impl JSTraceable for XmlTokenizer<XmlTreeBuilder<JS<Node>, Sink>> {
type Handle = JS<Node>;
#[allow(unrooted_must_root)]
fn trace_handle(&self, node: JS<Node>) {
- node.trace(self.0);
+ unsafe { node.trace(self.0); }
}
}
diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs
index 9a1e4663152..ad20a127e17 100644
--- a/components/script/dom/webgltexture.rs
+++ b/components/script/dom/webgltexture.rs
@@ -26,7 +26,7 @@ pub enum TexParameterValue {
const MAX_LEVEL_COUNT: usize = 31;
const MAX_FACE_COUNT: usize = 6;
-no_jsmanaged_fields!([ImageInfo; MAX_LEVEL_COUNT * MAX_FACE_COUNT]);
+jsmanaged_array!(MAX_LEVEL_COUNT * MAX_FACE_COUNT);
#[dom_struct]
pub struct WebGLTexture {
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 3b1bd124398..77a569ef65a 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -6,7 +6,6 @@ use app_units::Au;
use bluetooth_traits::BluetoothRequest;
use cssparser::Parser;
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
-use dom::bindings::callback::ExceptionHandling;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
@@ -30,7 +29,7 @@ use dom::bindings::utils::{GlobalStaticData, WindowProxyHandler};
use dom::browsingcontext::BrowsingContext;
use dom::crypto::Crypto;
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
-use dom::document::Document;
+use dom::document::{AnimationFrameCallback, Document};
use dom::element::Element;
use dom::event::Event;
use dom::globalscope::GlobalScope;
@@ -48,6 +47,7 @@ use dom::storage::Storage;
use dom::testrunner::TestRunner;
use euclid::{Point2D, Rect, Size2D};
use fetch;
+use gfx_traits::ScrollRootId;
use ipc_channel::ipc::{self, IpcSender};
use js::jsapi::{HandleObject, HandleValue, JSAutoCompartment, JSContext};
use js::jsapi::{JS_GC, JS_GetRuntime, SetWindowProxy};
@@ -67,7 +67,8 @@ use script_layout_interface::TrustedNodeAddress;
use script_layout_interface::message::{Msg, Reflow, ReflowQueryType, ScriptReflow};
use script_layout_interface::reporter::CSSErrorReporter;
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
-use script_layout_interface::rpc::{MarginStyleResponse, ResolvedStyleResponse};
+use script_layout_interface::rpc::{MarginStyleResponse, NodeScrollRootIdResponse};
+use script_layout_interface::rpc::ResolvedStyleResponse;
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory};
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, RunnableWrapper};
use script_thread::SendableMainThreadScriptChan;
@@ -197,7 +198,7 @@ pub struct Window {
/// A handle to perform RPC calls into the layout, quickly.
#[ignore_heap_size_of = "trait objects are hard"]
- layout_rpc: Box<LayoutRPC + 'static>,
+ layout_rpc: Box<LayoutRPC + Send + 'static>,
/// The current size of the window, in pixels.
window_size: Cell<Option<WindowSizeData>>,
@@ -599,15 +600,8 @@ impl WindowMethods for Window {
/// https://html.spec.whatwg.org/multipage/#dom-window-requestanimationframe
fn RequestAnimationFrame(&self, callback: Rc<FrameRequestCallback>) -> u32 {
- let doc = self.Document();
-
- let callback = move |now: f64| {
- // TODO: @jdm The spec says that any exceptions should be suppressed;
- // https://github.com/servo/servo/issues/6928
- let _ = callback.Call__(Finite::wrap(now), ExceptionHandling::Report);
- };
-
- doc.request_animation_frame(Box::new(callback))
+ self.Document()
+ .request_animation_frame(AnimationFrameCallback::FrameRequestCallback { callback })
}
/// https://html.spec.whatwg.org/multipage/#dom-window-cancelanimationframe
@@ -967,13 +961,20 @@ impl Window {
//TODO Step 11
//let document = self.Document();
// Step 12
- self.perform_a_scroll(x.to_f32().unwrap_or(0.0f32), y.to_f32().unwrap_or(0.0f32),
- behavior, None);
+ self.perform_a_scroll(x.to_f32().unwrap_or(0.0f32),
+ y.to_f32().unwrap_or(0.0f32),
+ ScrollRootId::root(),
+ behavior,
+ None);
}
/// https://drafts.csswg.org/cssom-view/#perform-a-scroll
- pub fn perform_a_scroll(&self, x: f32, y: f32,
- behavior: ScrollBehavior, element: Option<&Element>) {
+ pub fn perform_a_scroll(&self,
+ x: f32,
+ y: f32,
+ scroll_root_id: ScrollRootId,
+ behavior: ScrollBehavior,
+ element: Option<&Element>) {
//TODO Step 1
let point = Point2D::new(x, y);
let smooth = match behavior {
@@ -992,7 +993,7 @@ impl Window {
let global_scope = self.upcast::<GlobalScope>();
let message = ConstellationMsg::ScrollFragmentPoint(
- global_scope.pipeline_id(), point, smooth);
+ global_scope.pipeline_id(), scroll_root_id, point, smooth);
global_scope.constellation_chan().send(message).unwrap();
}
@@ -1273,11 +1274,24 @@ impl Window {
}
// https://drafts.csswg.org/cssom-view/#dom-element-scroll
- pub fn scroll_node(&self, _node: TrustedNodeAddress,
- x_: f64, y_: f64, behavior: ScrollBehavior) {
+ pub fn scroll_node(&self,
+ node: TrustedNodeAddress,
+ x_: f64,
+ y_: f64,
+ behavior: ScrollBehavior) {
+ if !self.reflow(ReflowGoal::ForScriptQuery,
+ ReflowQueryType::NodeScrollRootIdQuery(node),
+ ReflowReason::Query) {
+ return;
+ }
+ let NodeScrollRootIdResponse(scroll_root_id) = self.layout_rpc.node_scroll_root_id();
+
// Step 12
- self.perform_a_scroll(x_.to_f32().unwrap_or(0.0f32), y_.to_f32().unwrap_or(0.0f32),
- behavior, None);
+ self.perform_a_scroll(x_.to_f32().unwrap_or(0.0f32),
+ y_.to_f32().unwrap_or(0.0f32),
+ scroll_root_id,
+ behavior,
+ None);
}
pub fn resolved_style_query(&self,
@@ -1547,7 +1561,7 @@ impl Window {
parent_info: Option<(PipelineId, FrameType)>,
window_size: Option<WindowSizeData>)
-> Root<Window> {
- let layout_rpc: Box<LayoutRPC> = {
+ let layout_rpc: Box<LayoutRPC + Send> = {
let (rpc_send, rpc_recv) = channel();
layout_chan.send(Msg::GetRPC(rpc_send)).unwrap();
rpc_recv.recv().unwrap()
@@ -1649,6 +1663,7 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue
ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
ReflowQueryType::NodeOverflowQuery(_n) => "\tNodeOverFlowQuery",
ReflowQueryType::NodeScrollGeometryQuery(_n) => "\tNodeScrollGeometryQuery",
+ ReflowQueryType::NodeScrollRootIdQuery(_n) => "\tNodeScrollRootIdQuery",
ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
ReflowQueryType::OffsetParentQuery(_n) => "\tOffsetParentQuery",
ReflowQueryType::MarginStyleQuery(_n) => "\tMarginStyleQuery",
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 292de083c84..b7706114ad1 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -240,14 +240,7 @@ impl XMLHttpRequest {
}
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
- let rv = match response {
- Ok(()) => {
- self.xhr.root().process_response_complete(self.gen_id, Ok(()))
- }
- Err(e) => {
- self.xhr.root().process_response_complete(self.gen_id, Err(e))
- }
- };
+ let rv = self.xhr.root().process_response_complete(self.gen_id, response);
*self.sync_status.borrow_mut() = Some(rv);
}
}
diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs
index 8838787defc..a6d4815090f 100644
--- a/components/script/layout_wrapper.rs
+++ b/components/script/layout_wrapper.rs
@@ -477,6 +477,10 @@ impl<'le> TElement for ServoLayoutElement<'le> {
})
}
}
+
+ fn skip_root_and_item_based_display_fixup(&self) -> bool {
+ false
+ }
}
impl<'le> PartialEq for ServoLayoutElement<'le> {
diff --git a/components/script/lib.rs b/components/script/lib.rs
index cf3aadf1658..e80e9553956 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -6,7 +6,7 @@
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
-#![feature(fnbox)]
+#![feature(field_init_shorthand)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(on_unimplemented)]
diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs
index 154353c71e8..f65b145c4ec 100644
--- a/components/script/script_runtime.rs
+++ b/components/script/script_runtime.rs
@@ -10,7 +10,7 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::PromiseBinding::PromiseJobCallback;
use dom::bindings::js::{Root, RootCollection, RootCollectionPtr, trace_roots};
use dom::bindings::refcounted::{LiveDOMReferences, trace_refcounted_objects};
-use dom::bindings::trace::trace_traceables;
+use dom::bindings::trace::{JSTraceable, trace_traceables};
use dom::bindings::utils::DOM_CALLBACKS;
use dom::globalscope::GlobalScope;
use js::glue::CollectServoSizes;
@@ -48,7 +48,7 @@ pub enum CommonScriptMsg {
}
/// A cloneable interface for communicating with an event loop.
-pub trait ScriptChan {
+pub trait ScriptChan: JSTraceable {
/// Send a message to the associated event loop.
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()>;
/// Clone this handle.
diff --git a/components/script_layout_interface/message.rs b/components/script_layout_interface/message.rs
index 7fc50f0da14..581adbb45bc 100644
--- a/components/script_layout_interface/message.rs
+++ b/components/script_layout_interface/message.rs
@@ -94,6 +94,7 @@ pub enum ReflowQueryType {
ContentBoxesQuery(TrustedNodeAddress),
NodeOverflowQuery(TrustedNodeAddress),
HitTestQuery(Point2D<f32>, Point2D<f32>, bool),
+ NodeScrollRootIdQuery(TrustedNodeAddress),
NodeGeometryQuery(TrustedNodeAddress),
NodeScrollGeometryQuery(TrustedNodeAddress),
ResolvedStyleQuery(TrustedNodeAddress, Option<PseudoElement>, Atom),
diff --git a/components/script_layout_interface/rpc.rs b/components/script_layout_interface/rpc.rs
index 94deab19b2b..6e19b3f3bcf 100644
--- a/components/script_layout_interface/rpc.rs
+++ b/components/script_layout_interface/rpc.rs
@@ -5,6 +5,7 @@
use app_units::Au;
use euclid::point::Point2D;
use euclid::rect::Rect;
+use gfx_traits::ScrollRootId;
use script_traits::UntrustedNodeAddress;
use style::properties::longhands::{margin_top, margin_right, margin_bottom, margin_left, overflow_x};
@@ -27,6 +28,8 @@ pub trait LayoutRPC {
fn node_overflow(&self) -> NodeOverflowResponse;
/// Requests the scroll geometry of this node. Used by APIs such as `scrollTop`.
fn node_scroll_area(&self) -> NodeGeometryResponse;
+ /// Requests the scroll root id of this node. Used by APIs such as `scrollTop`
+ fn node_scroll_root_id(&self) -> NodeScrollRootIdResponse;
/// Requests the node containing the point of interest
fn hit_test(&self) -> HitTestResponse;
/// Query layout for the resolved value of a given CSS property
@@ -48,6 +51,8 @@ pub struct NodeGeometryResponse {
pub struct NodeOverflowResponse(pub Option<Point2D<overflow_x::computed_value::T>>);
+pub struct NodeScrollRootIdResponse(pub ScrollRootId);
+
pub struct HitTestResponse {
pub node_address: Option<UntrustedNodeAddress>,
}
diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs
index 428642ce93b..1d1f32bf4b6 100644
--- a/components/script_layout_interface/wrapper_traits.rs
+++ b/components/script_layout_interface/wrapper_traits.rs
@@ -8,7 +8,7 @@ use HTMLCanvasData;
use LayoutNodeType;
use OpaqueStyleAndLayoutData;
use SVGSVGData;
-use gfx_traits::ByteIndex;
+use gfx_traits::{ByteIndex, FragmentType, ScrollRootId};
use html5ever_atoms::{Namespace, LocalName};
use msg::constellation_msg::PipelineId;
use range::Range;
@@ -264,6 +264,20 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Debug + GetLayoutData + NodeInfo
fn iframe_pipeline_id(&self) -> PipelineId;
fn get_colspan(&self) -> u32;
+
+ fn fragment_type(&self) -> FragmentType {
+ match self.get_pseudo_element_type() {
+ PseudoElementType::Normal => FragmentType::FragmentBody,
+ PseudoElementType::Before(_) => FragmentType::BeforePseudoContent,
+ PseudoElementType::After(_) => FragmentType::AfterPseudoContent,
+ PseudoElementType::DetailsSummary(_) => FragmentType::FragmentBody,
+ PseudoElementType::DetailsContent(_) => FragmentType::FragmentBody,
+ }
+ }
+
+ fn scroll_root_id(&self) -> ScrollRootId {
+ ScrollRootId::new_of_type(self.opaque().id() as usize, self.fragment_type())
+ }
}
// This trait is only public so that it can be implemented by the gecko wrapper.
diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs
index 7ef20af9fbc..e91a034fec9 100644
--- a/components/script_traits/script_msg.rs
+++ b/components/script_traits/script_msg.rs
@@ -16,6 +16,7 @@ use canvas_traits::CanvasMsg;
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
use euclid::point::Point2D;
use euclid::size::Size2D;
+use gfx_traits::ScrollRootId;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::{FrameId, PipelineId, TraversalDirection};
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
@@ -121,7 +122,7 @@ pub enum ScriptMsg {
/// Check if an alert dialog box should be presented
Alert(PipelineId, String, IpcSender<bool>),
/// Scroll a page in a window
- ScrollFragmentPoint(PipelineId, Point2D<f32>, bool),
+ ScrollFragmentPoint(PipelineId, ScrollRootId, Point2D<f32>, bool),
/// Set title of current page
/// https://html.spec.whatwg.org/multipage/#document.title
SetTitle(PipelineId, Option<String>),
diff --git a/components/style/dom.rs b/components/style/dom.rs
index da476cedbaf..5c66bbc0e0f 100644
--- a/components/style/dom.rs
+++ b/components/style/dom.rs
@@ -269,4 +269,9 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>> {
self.get_data().map(|x| x.borrow_mut())
}
+
+ /// Whether we should skip any root- or item-based display property
+ /// blockification on this element. (This function exists so that Gecko
+ /// native anonymous content can opt out of this style fixup.)
+ fn skip_root_and_item_based_display_fixup(&self) -> bool;
}
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index 5a8c462db9e..6b124d55d20 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -371,6 +371,15 @@ impl<'le> TElement for GeckoElement<'le> {
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
unsafe { self.0.mServoData.get().as_ref() }
}
+
+ fn skip_root_and_item_based_display_fixup(&self) -> bool {
+ // We don't want to fix up display values of native anonymous content.
+ // Additionally, we want to skip root-based display fixup for document
+ // level native anonymous content subtree roots, since they're not
+ // really roots from the style fixup perspective. Checking that we
+ // are NAC handles both cases.
+ self.flags() & (NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE as u32) != 0
+ }
}
impl<'le> PartialEq for GeckoElement<'le> {
diff --git a/components/style/gecko_bindings/structs_debug.rs b/components/style/gecko_bindings/structs_debug.rs
index 2fa43b82fcc..4cfdc5899ed 100644
--- a/components/style/gecko_bindings/structs_debug.rs
+++ b/components/style/gecko_bindings/structs_debug.rs
@@ -2596,17 +2596,17 @@ pub enum StyleDisplay {
Contents = 24,
WebkitBox = 25,
WebkitInlineBox = 26,
- Box = 27,
- InlineBox = 28,
- XulGrid = 29,
- InlineXulGrid = 30,
- XulGridGroup = 31,
- XulGridLine = 32,
- Stack = 33,
- InlineStack = 34,
- Deck = 35,
- Groupbox = 36,
- Popup = 37,
+ MozBox = 27,
+ MozInlineBox = 28,
+ MozGrid = 29,
+ MozInlineGrid = 30,
+ MozGridGroup = 31,
+ MozGridLine = 32,
+ MozStack = 33,
+ MozInlineStack = 34,
+ MozDeck = 35,
+ MozGroupbox = 36,
+ MozPopup = 37,
}
/**
* A class for holding strong references to handle-managed objects.
diff --git a/components/style/gecko_bindings/structs_release.rs b/components/style/gecko_bindings/structs_release.rs
index 3d2bf88dbb7..11b1f6ea393 100644
--- a/components/style/gecko_bindings/structs_release.rs
+++ b/components/style/gecko_bindings/structs_release.rs
@@ -2570,17 +2570,17 @@ pub enum StyleDisplay {
Contents = 24,
WebkitBox = 25,
WebkitInlineBox = 26,
- Box = 27,
- InlineBox = 28,
- XulGrid = 29,
- InlineXulGrid = 30,
- XulGridGroup = 31,
- XulGridLine = 32,
- Stack = 33,
- InlineStack = 34,
- Deck = 35,
- Groupbox = 36,
- Popup = 37,
+ MozBox = 27,
+ MozInlineBox = 28,
+ MozGrid = 29,
+ MozInlineGrid = 30,
+ MozGridGroup = 31,
+ MozGridLine = 32,
+ MozStack = 33,
+ MozInlineStack = 34,
+ MozDeck = 35,
+ MozGroupbox = 36,
+ MozPopup = 37,
}
/**
* A class for holding strong references to handle-managed objects.
diff --git a/components/style/keyframes.rs b/components/style/keyframes.rs
index 831627d42c3..474e4c8b539 100644
--- a/components/style/keyframes.rs
+++ b/components/style/keyframes.rs
@@ -14,7 +14,7 @@ use std::sync::Arc;
use style_traits::ToCss;
use stylesheets::{MemoryHoleReporter, Stylesheet};
-/// A number from 1 to 100, indicating the percentage of the animation where
+/// A number from 0 to 1, indicating the percentage of the animation where
/// this keyframe should run.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@@ -30,6 +30,12 @@ impl ::std::cmp::Ord for KeyframePercentage {
impl ::std::cmp::Eq for KeyframePercentage { }
+impl ToCss for KeyframePercentage {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ write!(dest, "{}%", self.0 * 100.0)
+ }
+}
+
impl KeyframePercentage {
#[inline]
pub fn new(value: f32) -> KeyframePercentage {
@@ -93,10 +99,10 @@ pub struct Keyframe {
impl ToCss for Keyframe {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
let mut iter = self.selector.percentages().iter();
- try!(write!(dest, "{}%", iter.next().unwrap().0));
+ try!(iter.next().unwrap().to_css(dest));
for percentage in iter {
try!(write!(dest, ", "));
- try!(write!(dest, "{}%", percentage.0));
+ try!(percentage.to_css(dest));
}
try!(dest.write_str(" { "));
try!(self.block.read().to_css(dest));
diff --git a/components/style/matching.rs b/components/style/matching.rs
index e883d11bc3e..3b0a396507d 100644
--- a/components/style/matching.rs
+++ b/components/style/matching.rs
@@ -14,7 +14,7 @@ use cascade_info::CascadeInfo;
use context::{SharedStyleContext, StyleContext};
use data::{ComputedStyle, ElementData, ElementStyles, PseudoStyles};
use dom::{TElement, TNode, TRestyleDamage, UnsafeNode};
-use properties::{CascadeFlags, ComputedValues, SHAREABLE, cascade};
+use properties::{CascadeFlags, ComputedValues, SHAREABLE, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
use properties::longhands::display::computed_value as display;
use rule_tree::StrongRuleNode;
use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl};
@@ -405,6 +405,9 @@ trait PrivateMatchMethods: TElement {
if booleans.shareable {
cascade_flags.insert(SHAREABLE)
}
+ if self.skip_root_and_item_based_display_fixup() {
+ cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP)
+ }
let this_style = match parent_style {
Some(ref parent_style) => {
diff --git a/components/style/properties/data.py b/components/style/properties/data.py
index afddf0f4bb7..cdf4560783b 100644
--- a/components/style/properties/data.py
+++ b/components/style/properties/data.py
@@ -28,7 +28,9 @@ def to_camel_case(ident):
class Keyword(object):
def __init__(self, name, values, gecko_constant_prefix=None,
gecko_enum_prefix=None, custom_consts=None,
- extra_gecko_values=None, extra_servo_values=None):
+ extra_gecko_values=None, extra_servo_values=None,
+ gecko_strip_moz_prefix=True,
+ gecko_inexhaustive=None):
self.name = name
self.values = values.split()
if gecko_constant_prefix and gecko_enum_prefix:
@@ -39,6 +41,8 @@ class Keyword(object):
self.extra_gecko_values = (extra_gecko_values or "").split()
self.extra_servo_values = (extra_servo_values or "").split()
self.consts_map = {} if custom_consts is None else custom_consts
+ self.gecko_strip_moz_prefix = gecko_strip_moz_prefix
+ self.gecko_inexhaustive = gecko_inexhaustive or (gecko_enum_prefix is None)
def gecko_values(self):
return self.values + self.extra_gecko_values
@@ -55,7 +59,7 @@ class Keyword(object):
raise Exception("Bad product: " + product)
def gecko_constant(self, value):
- moz_stripped = value.replace("-moz-", '')
+ moz_stripped = value.replace("-moz-", '') if self.gecko_strip_moz_prefix else value
parts = moz_stripped.split('-')
if self.gecko_enum_prefix:
parts = [p.title() for p in parts]
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index a9afd64c5b0..c424ca705a7 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -255,7 +255,9 @@ def set_gecko_property(ffi_name, expr):
% for value in keyword.values_for('gecko'):
structs::${keyword.gecko_constant(value)} => Keyword::${to_rust_ident(value)},
% endfor
+ % if keyword.gecko_inexhaustive:
x => panic!("Found unexpected value in style struct for ${ident} property: {:?}", x),
+ % endif
}
}
</%def>
@@ -1026,9 +1028,31 @@ fn static_assert() {
<% display_keyword = Keyword("display", "inline block inline-block table inline-table table-row-group " +
"table-header-group table-footer-group table-row table-column-group " +
"table-column table-cell table-caption list-item flex none " +
- "-moz-box -moz-inline-box",
- gecko_enum_prefix="StyleDisplay") %>
- ${impl_keyword('display', 'mDisplay', display_keyword, True)}
+ "inline-flex grid inline-grid ruby ruby-base ruby-base-container " +
+ "ruby-text ruby-text-container contents -webkit-box -webkit-inline-box " +
+ "-moz-box -moz-inline-box -moz-grid -moz-inline-grid -moz-grid-group " +
+ "-moz-grid-line -moz-stack -moz-inline-stack -moz-deck -moz-popup " +
+ "-moz-groupbox",
+ gecko_enum_prefix="StyleDisplay",
+ gecko_strip_moz_prefix=False) %>
+
+ pub fn set_display(&mut self, v: longhands::display::computed_value::T) {
+ use properties::longhands::display::computed_value::T as Keyword;
+ // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
+ let result = match v {
+ % for value in display_keyword.values_for('gecko'):
+ Keyword::${to_rust_ident(value)} =>
+ structs::${display_keyword.gecko_constant(value)},
+ % endfor
+ };
+ self.gecko.mDisplay = result;
+ self.gecko.mOriginalDisplay = result;
+ }
+ pub fn copy_display_from(&mut self, other: &Self) {
+ self.gecko.mDisplay = other.gecko.mDisplay;
+ self.gecko.mOriginalDisplay = other.gecko.mOriginalDisplay;
+ }
+ <%call expr="impl_keyword_clone('display', 'mDisplay', display_keyword)"></%call>
// overflow-y is implemented as a newtype of overflow-x, so we need special handling.
// We could generalize this if we run into other newtype keywords.
diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs
index 4fdbeda88c8..5d58fd6db5c 100644
--- a/components/style/properties/helpers.mako.rs
+++ b/components/style/properties/helpers.mako.rs
@@ -329,7 +329,7 @@
keyword_kwargs = {a: kwargs.pop(a, None) for a in [
'gecko_constant_prefix', 'gecko_enum_prefix',
'extra_gecko_values', 'extra_servo_values',
- 'custom_consts',
+ 'custom_consts', 'gecko_inexhaustive',
]}
%>
diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs
index c4ccfeb032f..0393064d532 100644
--- a/components/style/properties/longhand/border.mako.rs
+++ b/components/style/properties/longhand/border.mako.rs
@@ -58,11 +58,13 @@
${helpers.single_keyword("box-decoration-break", "slice clone",
gecko_enum_prefix="StyleBoxDecorationBreak",
+ gecko_inexhaustive=True,
products="gecko", animatable=False)}
${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
gecko_ffi_name="mFloatEdge",
gecko_enum_prefix="StyleFloatEdge",
+ gecko_inexhaustive=True,
products="gecko",
animatable=False)}
diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs
index c48d4948376..818ed9316e1 100644
--- a/components/style/properties/longhand/box.mako.rs
+++ b/components/style/properties/longhand/box.mako.rs
@@ -22,7 +22,11 @@
none
""".split()
if product == "gecko":
- values += "-moz-box -moz-inline-box".split()
+ values += """inline-flex grid inline-grid ruby ruby-base ruby-base-container
+ ruby-text ruby-text-container contents -webkit-box -webkit-inline-box
+ -moz-box -moz-inline-box -moz-grid -moz-inline-grid -moz-grid-group
+ -moz-grid-line -moz-stack -moz-inline-stack -moz-deck -moz-popup
+ -moz-groupbox""".split()
%>
pub use self::computed_value::T as SpecifiedValue;
use values::computed::ComputedValueAsSpecified;
@@ -92,6 +96,7 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
animatable="False"
need_clone="True"
gecko_enum_prefix="StyleFloat"
+ gecko_inexhaustive="True"
gecko_ffi_name="mFloat">
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
diff --git a/components/style/properties/longhand/inherited_svg.mako.rs b/components/style/properties/longhand/inherited_svg.mako.rs
index 8bff77f9c37..6a0b00eced9 100644
--- a/components/style/properties/longhand/inherited_svg.mako.rs
+++ b/components/style/properties/longhand/inherited_svg.mako.rs
@@ -35,6 +35,7 @@ ${helpers.predefined_type("fill-opacity", "Opacity", "1.0",
${helpers.single_keyword("fill-rule", "nonzero evenodd",
gecko_enum_prefix="StyleFillRule",
+ gecko_inexhaustive=True,
products="gecko", animatable=False)}
${helpers.single_keyword("shape-rendering",
@@ -60,4 +61,5 @@ ${helpers.predefined_type("stroke-opacity", "Opacity", "1.0",
${helpers.single_keyword("clip-rule", "nonzero evenodd",
products="gecko",
gecko_enum_prefix="StyleFillRule",
+ gecko_inexhaustive=True,
animatable=False)}
diff --git a/components/style/properties/longhand/pointing.mako.rs b/components/style/properties/longhand/pointing.mako.rs
index d5306f376a9..412e2fe080c 100644
--- a/components/style/properties/longhand/pointing.mako.rs
+++ b/components/style/properties/longhand/pointing.mako.rs
@@ -151,15 +151,18 @@ ${helpers.single_keyword("pointer-events", "auto none", animatable=False)}
${helpers.single_keyword("-moz-user-input", "none enabled disabled",
products="gecko", gecko_ffi_name="mUserInput",
gecko_enum_prefix="StyleUserInput",
+ gecko_inexhaustive=True,
animatable=False)}
${helpers.single_keyword("-moz-user-modify", "read-only read-write write-only",
products="gecko", gecko_ffi_name="mUserModify",
gecko_enum_prefix="StyleUserModify",
+ gecko_inexhaustive=True,
animatable=False)}
${helpers.single_keyword("-moz-user-focus",
"ignore normal select-after select-before select-menu select-same select-all none",
products="gecko", gecko_ffi_name="mUserFocus",
gecko_enum_prefix="StyleUserFocus",
+ gecko_inexhaustive=True,
animatable=False)}
diff --git a/components/style/properties/longhand/ui.mako.rs b/components/style/properties/longhand/ui.mako.rs
index f815c1d8518..cd537677f6f 100644
--- a/components/style/properties/longhand/ui.mako.rs
+++ b/components/style/properties/longhand/ui.mako.rs
@@ -16,4 +16,5 @@ ${helpers.single_keyword("ime-mode", "normal auto active disabled inactive",
${helpers.single_keyword("-moz-user-select", "auto text none all", products="gecko",
gecko_ffi_name="mUserSelect",
gecko_enum_prefix="StyleUserSelect",
+ gecko_inexhaustive=True,
animatable=False)}
diff --git a/components/style/properties/longhand/xul.mako.rs b/components/style/properties/longhand/xul.mako.rs
index 23c1da1246b..bc64308a115 100644
--- a/components/style/properties/longhand/xul.mako.rs
+++ b/components/style/properties/longhand/xul.mako.rs
@@ -11,6 +11,7 @@
${helpers.single_keyword("-moz-box-align", "stretch start center baseline end",
products="gecko", gecko_ffi_name="mBoxAlign",
gecko_enum_prefix="StyleBoxAlign",
+ gecko_inexhaustive=True,
animatable=False)}
${helpers.predefined_type("-moz-box-flex", "Number", "0.0", "parse_non_negative",
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index 97e3271e8b6..46688434651 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -1436,6 +1436,8 @@ bitflags! {
/// Whether to inherit all styles from the parent. If this flag is not present,
/// non-inherited styles are reset to their initial values.
const INHERIT_ALL = 0x02,
+ /// Whether to skip any root element and flex/grid item display style fixup.
+ const SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP = 0x04,
}
}
@@ -1630,30 +1632,50 @@ pub fn apply_declarations<'a, F, I>(viewport_size: Size2D<Au>,
longhands::position::SpecifiedValue::absolute |
longhands::position::SpecifiedValue::fixed);
let floated = style.get_box().clone_float() != longhands::float::SpecifiedValue::none;
- let is_flex_item =
- context.inherited_style.get_box().clone_display() == computed_values::display::T::flex;
- if positioned || floated || is_root_element || is_flex_item {
+ // FIXME(heycam): We should look past any display:contents ancestors to
+ // determine if we are a flex or grid item, but we don't have access to
+ // grandparent or higher style here.
+ let is_item = matches!(context.inherited_style.get_box().clone_display(),
+ % if product == "gecko":
+ computed_values::display::T::grid |
+ % endif
+ computed_values::display::T::flex);
+ let (blockify_root, blockify_item) = match flags.contains(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP) {
+ false => (is_root_element, is_item),
+ true => (false, false),
+ };
+ if positioned || floated || blockify_root || blockify_item {
use computed_values::display::T;
let specified_display = style.get_box().clone_display();
let computed_display = match specified_display {
- T::inline_table => {
- Some(T::table)
- }
- T::inline | T::inline_block |
- T::table_row_group | T::table_column |
- T::table_column_group | T::table_header_group |
- T::table_footer_group | T::table_row | T::table_cell |
- T::table_caption => {
- Some(T::block)
- }
- _ => None
+ // Values that have a corresponding block-outside version.
+ T::inline_table => Some(T::table),
+ % if product == "gecko":
+ T::inline_flex => Some(T::flex),
+ T::inline_grid => Some(T::grid),
+ T::_webkit_inline_box => Some(T::_webkit_box),
+ % endif
+
+ // Special handling for contents and list-item on the root element for Gecko.
+ % if product == "gecko":
+ T::contents | T::list_item if blockify_root => Some(T::block),
+ % endif
+
+ // Values that are not changed by blockification.
+ T::block | T::flex | T::list_item | T::table => None,
+ % if product == "gecko":
+ T::contents | T::grid | T::_webkit_box => None,
+ % endif
+
+ // Everything becomes block.
+ _ => Some(T::block),
};
if let Some(computed_display) = computed_display {
let box_ = style.mutate_box();
box_.set_display(computed_display);
% if product == "servo":
- box_.set__servo_display_for_hypothetical_box(if is_root_element || is_flex_item {
+ box_.set__servo_display_for_hypothetical_box(if blockify_root || blockify_item {
computed_display
} else {
specified_display