diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/layout/construct.rs | 8 | ||||
-rw-r--r-- | components/layout/flow.rs | 5 | ||||
-rw-r--r-- | components/layout/layout_task.rs | 76 | ||||
-rw-r--r-- | components/layout/query.rs | 20 | ||||
-rw-r--r-- | components/plugins/lints/unrooted_must_root.rs | 174 | ||||
-rw-r--r-- | components/script/dom/bindings/js.rs | 35 | ||||
-rw-r--r-- | components/script/dom/bindings/utils.rs | 58 | ||||
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 1 | ||||
-rw-r--r-- | components/script/dom/element.rs | 5 | ||||
-rw-r--r-- | components/script/dom/filelist.rs | 2 | ||||
-rw-r--r-- | components/script/dom/htmlcollection.rs | 2 | ||||
-rw-r--r-- | components/script/dom/nodelist.rs | 2 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 1 | ||||
-rw-r--r-- | components/script/dom/webidls/Element.webidl | 2 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 2 |
15 files changed, 203 insertions, 190 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs index ff1ff42a1d2..2ed8f286db0 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -1659,7 +1659,9 @@ impl<'ln> ObjectElement<'ln> for ThreadSafeLayoutNode<'ln> { } } -pub trait FlowConstructionUtils { +// This must not be public because only the layout constructor can call these +// methods. +trait FlowConstructionUtils { /// Adds a new flow as a child of this flow. Removes the flow from the given leaf set if /// it's present. fn add_new_child(&mut self, new_child: FlowRef); @@ -1675,8 +1677,6 @@ pub trait FlowConstructionUtils { impl FlowConstructionUtils for FlowRef { /// Adds a new flow as a child of this flow. Fails if this flow is marked as a leaf. - /// - /// This must not be public because only the layout constructor can do this. fn add_new_child(&mut self, mut new_child: FlowRef) { { let kid_base = flow::mut_base(flow_ref::deref_mut(&mut new_child)); @@ -1694,8 +1694,6 @@ impl FlowConstructionUtils for FlowRef { /// /// All flows must be finished at some point, or they will not have their intrinsic inline-sizes /// properly computed. (This is not, however, a memory safety problem.) - /// - /// This must not be public because only the layout constructor can do this. fn finish(&mut self) { if !opts::get().bubble_inline_sizes_separately { flow_ref::deref_mut(self).bubble_inline_sizes() diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 96d4b4b159a..5be4533dc6a 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -937,11 +937,6 @@ pub struct BaseFlow { pub flags: FlowFlags, } -#[allow(unsafe_code)] -unsafe impl Send for BaseFlow {} -#[allow(unsafe_code)] -unsafe impl Sync for BaseFlow {} - impl fmt::Debug for BaseFlow { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 7dde0fe694c..9c3a3e7ea4c 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -324,7 +324,6 @@ fn add_font_face_rules(stylesheet: &Stylesheet, outstanding_web_fonts_counter: &Arc<AtomicUsize>) { for font_face in stylesheet.effective_rules(&device).font_face() { for source in &font_face.sources { - let font_cache_task = (*font_cache_task).clone(); outstanding_web_fonts_counter.fetch_add(1, Ordering::SeqCst); font_cache_task.add_web_font(font_face.family.clone(), (*source).clone(), @@ -878,25 +877,24 @@ impl LayoutTask { traversal); } - fn process_node_geometry_request<'a>(&'a self, - requested_node: TrustedNodeAddress, - layout_root: &mut FlowRef, - rw_data: &mut RWGuard<'a>) { + fn process_node_geometry_request(&self, + requested_node: TrustedNodeAddress, + layout_root: &mut FlowRef) + -> Rect<i32> { let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); let mut iterator = FragmentLocatingFragmentIterator::new(requested_node); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); - rw_data.client_rect_response = iterator.client_rect; + iterator.client_rect } - // Compute the resolved value of property for a given (pseudo)element. - // Stores the result in rw_data.resolved_style_response. - // https://drafts.csswg.org/cssom/#resolved-value - fn process_resolved_style_request<'a>(&'a self, - requested_node: TrustedNodeAddress, - pseudo: &Option<PseudoElement>, - property: &Atom, - layout_root: &mut FlowRef, - rw_data: &mut RWGuard<'a>) { + /// Return the resolved value of property for a given (pseudo)element. + /// https://drafts.csswg.org/cssom/#resolved-value + fn process_resolved_style_request(&self, + requested_node: TrustedNodeAddress, + pseudo: &Option<PseudoElement>, + property: &Atom, + layout_root: &mut FlowRef) + -> Option<String> { // FIXME: Isolate this transmutation into a "bridge" module. // FIXME(rust#16366): The following line had to be moved because of a // rustc bug. It should be in the next unsafe block. @@ -919,8 +917,7 @@ impl LayoutTask { // The pseudo doesn't exist, return nothing. Chrome seems to query // the element itself in this case, Firefox uses the resolved value. // https://www.w3.org/Bugs/Public/show_bug.cgi?id=29006 - rw_data.resolved_style_response = None; - return; + return None; } Some(layout_node) => layout_node }; @@ -945,7 +942,7 @@ impl LayoutTask { // TODO: we will return neither the computed nor used value for margin and padding. // Firefox returns blank strings for the computed value of shorthands, // so this should be web-compatible. - match property.clone() { + match *property { atom!("margin-bottom") | atom!("margin-top") | atom!("margin-left") | atom!("margin-right") | atom!("padding-bottom") | atom!("padding-top") | @@ -971,7 +968,7 @@ impl LayoutTask { style.writing_mode); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); - rw_data.resolved_style_response = iterator.result.map(|r| r.to_css_string()); + iterator.result.map(|r| r.to_css_string()) }, atom!("bottom") | atom!("top") | atom!("right") | @@ -1004,20 +1001,19 @@ impl LayoutTask { position); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); - rw_data.resolved_style_response = iterator.result.map(|r| r.to_css_string()); + iterator.result.map(|r| r.to_css_string()) }, // FIXME: implement used value computation for line-height - property => { - rw_data.resolved_style_response = - style.computed_value_to_string(property.as_slice()).ok(); + ref property => { + style.computed_value_to_string(property.as_slice()).ok() } - }; + } } - fn process_offset_parent_query<'a>(&'a self, - requested_node: TrustedNodeAddress, - layout_root: &mut FlowRef, - rw_data: &mut RWGuard<'a>) { + fn process_offset_parent_query(&self, + requested_node: TrustedNodeAddress, + layout_root: &mut FlowRef) + -> OffsetParentResponse { let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); let mut iterator = ParentOffsetBorderBoxIterator::new(requested_node); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); @@ -1027,13 +1023,13 @@ impl LayoutTask { let parent = iterator.parent_nodes[parent_info_index].as_ref().unwrap(); let origin = iterator.node_border_box.origin - parent.border_box.origin; let size = iterator.node_border_box.size; - rw_data.offset_parent_response = OffsetParentResponse { + OffsetParentResponse { node_address: Some(parent.node_address.to_untrusted_node_address()), rect: Rect::new(origin, size), - }; + } } None => { - rw_data.offset_parent_response = OffsetParentResponse::empty(); + OffsetParentResponse::empty() } } } @@ -1232,20 +1228,20 @@ impl LayoutTask { if let Some(mut root_flow) = rw_data.layout_root() { match data.query_type { ReflowQueryType::ContentBoxQuery(node) => - process_content_box_request(node, &mut root_flow, &mut rw_data), + rw_data.content_box_response = process_content_box_request(node, &mut root_flow), ReflowQueryType::ContentBoxesQuery(node) => - process_content_boxes_request(node, &mut root_flow, &mut rw_data), + rw_data.content_boxes_response = process_content_boxes_request(node, &mut root_flow), ReflowQueryType::NodeGeometryQuery(node) => - self.process_node_geometry_request(node, &mut root_flow, &mut rw_data), + rw_data.client_rect_response = self.process_node_geometry_request(node, &mut root_flow), ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) => { - self.process_resolved_style_request(node, - pseudo, - property, - &mut root_flow, - &mut rw_data) + rw_data.resolved_style_response = + self.process_resolved_style_request(node, + pseudo, + property, + &mut root_flow) } ReflowQueryType::OffsetParentQuery(node) => - self.process_offset_parent_query(node, &mut root_flow, &mut rw_data), + rw_data.offset_parent_response = self.process_offset_parent_query(node, &mut root_flow), ReflowQueryType::NoQuery => {} } } diff --git a/components/layout/query.rs b/components/layout/query.rs index 024d3022288..d50e150d0ae 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -10,7 +10,7 @@ use euclid::rect::Rect; use flow_ref::FlowRef; use fragment::{Fragment, FragmentBorderBoxIterator}; use gfx::display_list::{DisplayItemMetadata, OpaqueNode}; -use layout_task::{LayoutTaskData, RWGuard}; +use layout_task::LayoutTaskData; use msg::constellation_msg::ConstellationChan; use msg::constellation_msg::Msg as ConstellationMsg; use opaque_node::OpaqueNodeMethods; @@ -281,27 +281,27 @@ impl FragmentBorderBoxIterator for MarginRetrievingFragmentBorderBoxIterator { } } -pub fn process_content_box_request<'a>(requested_node: TrustedNodeAddress, - layout_root: &mut FlowRef, - rw_data: &mut RWGuard<'a>) { +pub fn process_content_box_request(requested_node: TrustedNodeAddress, + layout_root: &mut FlowRef) + -> Rect<Au> { // FIXME(pcwalton): This has not been updated to handle the stacking context relative // stuff. So the position is wrong in most cases. let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); let mut iterator = UnioningFragmentBorderBoxIterator::new(requested_node); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); - rw_data.content_box_response = match iterator.rect { + match iterator.rect { Some(rect) => rect, None => Rect::zero() - }; + } } -pub fn process_content_boxes_request<'a>(requested_node: TrustedNodeAddress, - layout_root: &mut FlowRef, - rw_data: &mut RWGuard<'a>) { +pub fn process_content_boxes_request(requested_node: TrustedNodeAddress, + layout_root: &mut FlowRef) + -> Vec<Rect<Au>> { // FIXME(pcwalton): This has not been updated to handle the stacking context relative // stuff. So the position is wrong in most cases. let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); let mut iterator = CollectingFragmentBorderBoxIterator::new(requested_node); sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); - rw_data.content_boxes_response = iterator.rects; + iterator.rects } diff --git a/components/plugins/lints/unrooted_must_root.rs b/components/plugins/lints/unrooted_must_root.rs index bb599e845de..5b6e16c99e9 100644 --- a/components/plugins/lints/unrooted_must_root.rs +++ b/components/plugins/lints/unrooted_must_root.rs @@ -8,7 +8,7 @@ use rustc::middle::ty; use rustc_front::{hir, visit}; use syntax::attr::AttrMetaMethods; use syntax::{ast, codemap}; -use utils::{match_def_path, unsafe_context, in_derive_expn}; +use utils::{match_def_path, in_derive_expn}; declare_lint!(UNROOTED_MUST_ROOT, Deny, "Warn and report usage of unrooted jsmanaged objects"); @@ -30,15 +30,11 @@ declare_lint!(UNROOTED_MUST_ROOT, Deny, /// Structs which have their own mechanism of rooting their unrooted contents (e.g. `ScriptTask`) /// can be marked as `#[allow(unrooted_must_root)]`. Smart pointers which root their interior type /// can be marked as `#[allow_unrooted_interior]` -pub struct UnrootedPass { - in_new_function: bool -} +pub struct UnrootedPass; impl UnrootedPass { pub fn new() -> UnrootedPass { - UnrootedPass { - in_new_function: true - } + UnrootedPass } } @@ -55,9 +51,11 @@ fn is_unrooted_ty(cx: &LateContext, ty: &ty::TyS, in_new_function: bool) -> bool } else if cx.tcx.has_attr(did.did, "allow_unrooted_interior") { false } else if match_def_path(cx, did.did, &["core", "cell", "Ref"]) - || match_def_path(cx, did.did, &["core", "cell", "RefMut"]) { - // Ref and RefMut are borrowed pointers, okay to hold unrooted stuff - // since it will be rooted elsewhere + || match_def_path(cx, did.did, &["core", "cell", "RefMut"]) + || match_def_path(cx, did.did, &["core", "slice", "Iter"]) + || match_def_path(cx, did.did, &["std", "collections", "hash", "map", "OccupiedEntry"]) + || match_def_path(cx, did.did, &["std", "collections", "hash", "map", "VacantEntry"]) { + // Structures which are semantically similar to an &ptr. false } else { true @@ -99,6 +97,7 @@ impl LateLintPass for UnrootedPass { } } } + /// All enums containing #[must_root] types must be #[must_root] themselves fn check_variant(&mut self, cx: &LateContext, var: &hir::Variant, _gen: &hir::Generics) { let ref map = cx.tcx.map; @@ -121,55 +120,56 @@ impl LateLintPass for UnrootedPass { } /// Function arguments that are #[must_root] types are not allowed fn check_fn(&mut self, cx: &LateContext, kind: visit::FnKind, decl: &hir::FnDecl, - block: &hir::Block, span: codemap::Span, id: ast::NodeId) { - match kind { + block: &hir::Block, span: codemap::Span, _id: ast::NodeId) { + let in_new_function = match kind { visit::FnKind::ItemFn(n, _, _, _, _, _) | - visit::FnKind::Method(n, _, _) if n.as_str() == "new" - || n.as_str().starts_with("new_") => { - self.in_new_function = true; - return; - }, - visit::FnKind::ItemFn(_, _, style, _, _, _) => match style { - hir::Unsafety::Unsafe => return, - _ => () - }, - _ => () - } - self.in_new_function = false; + visit::FnKind::Method(n, _, _) => { + n.as_str() == "new" || n.as_str().starts_with("new_") + } + visit::FnKind::Closure => return, + }; - if unsafe_context(&cx.tcx.map, id) { - return; + for arg in &decl.inputs { + cx.tcx.ast_ty_to_ty_cache.borrow().get(&arg.ty.id).map(|t| { + if is_unrooted_ty(cx, t, false) { + if in_derive_expn(cx, span) { + return; + } + cx.span_lint(UNROOTED_MUST_ROOT, arg.ty.span, "Type must be rooted") + } + }); } - match block.rules { - hir::DefaultBlock => { - for arg in &decl.inputs { - cx.tcx.ast_ty_to_ty_cache.borrow().get(&arg.ty.id).map(|t| { - if is_unrooted_ty(cx, t, false) { - if in_derive_expn(cx, span) { - return; - } - cx.span_lint(UNROOTED_MUST_ROOT, arg.ty.span, "Type must be rooted") - } - }); - } - if let hir::Return(ref ty) = decl.output { - cx.tcx.ast_ty_to_ty_cache.borrow().get(&ty.id).map(|t| { - if is_unrooted_ty(cx, t, false) { - if in_derive_expn(cx, span) { - return; - } - cx.span_lint(UNROOTED_MUST_ROOT, ty.span, "Type must be rooted") + if !in_new_function { + if let hir::Return(ref ty) = decl.output { + cx.tcx.ast_ty_to_ty_cache.borrow().get(&ty.id).map(|t| { + if is_unrooted_ty(cx, t, false) { + if in_derive_expn(cx, span) { + return; } - }); - } + cx.span_lint(UNROOTED_MUST_ROOT, ty.span, "Type must be rooted") + } + }); } - _ => () // fn is `unsafe` } + + let mut visitor = FnDefVisitor { + cx: cx, + in_new_function: in_new_function, + }; + visit::walk_block(&mut visitor, block); } +} + +struct FnDefVisitor<'a, 'b: 'a, 'tcx: 'a+'b> { + cx: &'a LateContext<'b, 'tcx>, + in_new_function: bool, +} + +impl<'a, 'b: 'a, 'tcx: 'a+'b> visit::Visitor<'a> for FnDefVisitor<'a, 'b, 'tcx> { + fn visit_expr(&mut self, expr: &'a hir::Expr) { + let cx = self.cx; - /// Trait casts from #[must_root] types are not allowed - fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { fn require_rooted(cx: &LateContext, in_new_function: bool, subexpr: &hir::Expr) { let ty = cx.tcx.expr_ty(&*subexpr); if is_unrooted_ty(cx, ty, in_new_function) { @@ -177,56 +177,52 @@ impl LateLintPass for UnrootedPass { subexpr.span, &format!("Expression of type {:?} must be rooted", ty)) } - }; + } match expr.node { + /// Trait casts from #[must_root] types are not allowed hir::ExprCast(ref subexpr, _) => require_rooted(cx, self.in_new_function, &*subexpr), + // This catches assignments... the main point of this would be to catch mutable + // references to `JS<T>`. + // FIXME: Enable this? Triggers on certain kinds of uses of DOMRefCell. + // hir::ExprAssign(_, ref rhs) => require_rooted(cx, self.in_new_function, &*rhs), + // This catches calls; basically, this enforces the constraint that only constructors + // can call other constructors. + // FIXME: Enable this? Currently triggers with constructs involving DOMRefCell, and + // constructs like Vec<JS<T>> and RootedVec<JS<T>>. + // hir::ExprCall(..) if !self.in_new_function => { + // require_rooted(cx, self.in_new_function, expr); + // } _ => { // TODO(pcwalton): Check generics with a whitelist of allowed generics. } } + + visit::walk_expr(self, expr); } - // Partially copied from rustc::middle::lint::builtin - // Catches `let` statements and assignments which store a #[must_root] value - // Expressions which return out of blocks eventually end up in a `let` or assignment - // statement or a function return (which will be caught when it is used elsewhere) - fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { - match s.node { - hir::StmtDecl(_, id) | - hir::StmtExpr(_, id) | - hir::StmtSemi(_, id) if unsafe_context(&cx.tcx.map, id) => { - return - }, - _ => () - }; + fn visit_pat(&mut self, pat: &'a hir::Pat) { + let cx = self.cx; - let expr = match s.node { - // Catch a `let` binding - hir::StmtDecl(ref decl, _) => match decl.node { - hir::DeclLocal(ref loc) => match loc.init { - Some(ref e) => &**e, - _ => return - }, - _ => return - }, - hir::StmtExpr(ref expr, _) => match expr.node { - // This catches deferred `let` statements - hir::ExprAssign(_, ref e) | - // Match statements allow you to bind onto the variable later in an arm - // We need not check arms individually since enum/struct fields are already - // linted in `check_struct_def` and `check_variant` - // (so there is no way of destructuring out a `#[must_root]` field) - hir::ExprMatch(ref e, _, _) => &**e, - _ => return - }, - _ => return - }; + if let hir::PatIdent(hir::BindByValue(_), _, _) = pat.node { + let ty = cx.tcx.pat_ty(pat); + if is_unrooted_ty(cx, ty, self.in_new_function) { + cx.span_lint(UNROOTED_MUST_ROOT, + pat.span, + &format!("Expression of type {:?} must be rooted", ty)) + } + } + + visit::walk_pat(self, pat); + } - let ty = cx.tcx.expr_ty(&*expr); - if is_unrooted_ty(cx, ty, self.in_new_function) { - cx.span_lint(UNROOTED_MUST_ROOT, expr.span, - &format!("Expression of type {:?} must be rooted", ty)) + fn visit_fn(&mut self, kind: visit::FnKind<'a>, decl: &'a hir::FnDecl, + block: &'a hir::Block, span: codemap::Span, _id: ast::NodeId) { + if kind == visit::FnKind::Closure { + visit::walk_fn(self, kind, decl, block, span); } } + + fn visit_foreign_item(&mut self, _: &'a hir::ForeignItem) {} + fn visit_ty(&mut self, _: &'a hir::Ty) { } } diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index 6faef9b111b..a2ec90033ba 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -273,6 +273,22 @@ impl<T: HeapGCValue> HeapSizeOf for MutHeap<T> { } } +impl<T: Reflectable> PartialEq for MutHeap<JS<T>> { + fn eq(&self, other: &Self) -> bool { + unsafe { + *self.val.get() == *other.val.get() + } + } +} + +impl<T: Reflectable + PartialEq> PartialEq<T> for MutHeap<JS<T>> { + fn eq(&self, other: &T) -> bool { + unsafe { + **self.val.get() == *other + } + } +} + /// A holder that provides interior mutability for GC-managed values such as /// `JS<T>`, with nullability represented by an enclosing Option wrapper. /// Essentially a `Cell<Option<JS<T>>>`, but safer. @@ -310,11 +326,13 @@ impl<T: Reflectable> MutNullableHeap<JS<T>> { /// Retrieve a copy of the inner optional `JS<T>` as `LayoutJS<T>`. /// For use by layout, which can't use safe types like Temporary. + #[allow(unrooted_must_root)] pub unsafe fn get_inner_as_layout(&self) -> Option<LayoutJS<T>> { ptr::read(self.ptr.get()).map(|js| js.to_layout()) } /// Get a rooted value out of this object + #[allow(unrooted_must_root)] pub fn get(&self) -> Option<Root<T>> { unsafe { ptr::read(self.ptr.get()).map(|o| o.root()) @@ -332,6 +350,23 @@ impl<T: Reflectable> MutNullableHeap<JS<T>> { *self.ptr.get() = val.map(|p| JS::from_ref(p)); } } + +} + +impl<T: Reflectable> PartialEq for MutNullableHeap<JS<T>> { + fn eq(&self, other: &Self) -> bool { + unsafe { + *self.ptr.get() == *other.ptr.get() + } + } +} + +impl<'a, T: Reflectable> PartialEq<Option<&'a T>> for MutNullableHeap<JS<T>> { + fn eq(&self, other: &Option<&T>) -> bool { + unsafe { + *self.ptr.get() == other.map(JS::from_ref) + } + } } impl<T: HeapGCValue> Default for MutNullableHeap<T> { diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 5dc7f2d6215..27fdb3efa9c 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -28,7 +28,6 @@ use js::jsapi::JS_GetFunctionObject; use js::jsapi::JS_IsExceptionPending; use js::jsapi::JS_NewObjectWithUniqueType; use js::jsapi::JS_ObjectToOuterObject; -use js::jsapi::PropertyDefinitionBehavior; use js::jsapi::{CallArgs, GetGlobalForObjectCrossCompartment, JSJitInfo}; use js::jsapi::{CompartmentOptions, OnNewGlobalHookOption}; use js::jsapi::{DOMCallbacks, JSWrapObjectCallbacks}; @@ -38,8 +37,7 @@ use js::jsapi::{JSClass, JSContext, JSObject, JSTracer}; use js::jsapi::{JSFunctionSpec, JSPropertySpec}; use js::jsapi::{JSTraceOp, JS_AlreadyHasOwnProperty, JS_NewFunction}; use js::jsapi::{JSVersion, JS_FireOnNewGlobalObject}; -use js::jsapi::{JS_DefineFunctions, JS_DefineProperty, JS_DefineProperty1}; -use js::jsapi::{JS_DefineProperties, JS_ForwardGetPropertyTo}; +use js::jsapi::{JS_DefineProperty, JS_DefineProperty1, JS_ForwardGetPropertyTo}; use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype}; use js::jsapi::{JS_GetProperty, JS_HasProperty, JS_SetProperty}; use js::jsapi::{JS_GetPrototype, JS_HasPropertyById}; @@ -47,7 +45,7 @@ use js::jsapi::{JS_GetReservedSlot, JS_SetReservedSlot}; use js::jsapi::{JS_InitStandardClasses, JS_NewGlobalObject}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue}; use js::jsval::{PrivateValue, UInt32Value, UndefinedValue}; -use js::rust::{GCMethods, ToString}; +use js::rust::{GCMethods, ToString, define_methods, define_properties}; use js::{JSFUN_CONSTRUCTOR, JSPROP_ENUMERATE, JS_CALLEE}; use js::{JSPROP_PERMANENT, JSPROP_READONLY}; use libc::{self, c_uint}; @@ -305,28 +303,28 @@ fn create_interface_object(cx: *mut JSContext, ctor_nargs: u32, proto: HandleObject, members: &'static NativeProperties, name: *const libc::c_char) { - let constructor = RootedObject::new(cx, create_constructor(cx, constructor_native, ctor_nargs, name)); - assert!(!constructor.ptr.is_null()); + unsafe { + let constructor = RootedObject::new(cx, create_constructor(cx, constructor_native, ctor_nargs, name)); + assert!(!constructor.ptr.is_null()); - if let Some(static_methods) = members.static_methods { - define_methods(cx, constructor.handle(), static_methods); - } + if let Some(static_methods) = members.static_methods { + define_methods(cx, constructor.handle(), static_methods).unwrap(); + } - if let Some(static_properties) = members.static_attrs { - define_properties(cx, constructor.handle(), static_properties); - } + if let Some(static_properties) = members.static_attrs { + define_properties(cx, constructor.handle(), static_properties).unwrap(); + } - if let Some(constants) = members.consts { - define_constants(cx, constructor.handle(), constants); - } + if let Some(constants) = members.consts { + define_constants(cx, constructor.handle(), constants); + } - unsafe { if !proto.get().is_null() { assert!(JS_LinkConstructorAndPrototype(cx, constructor.handle(), proto)); } - } - define_constructor(cx, receiver, name, constructor.handle()); + define_constructor(cx, receiver, name, constructor.handle()); + } } /// Defines constants on `obj`. @@ -344,26 +342,6 @@ fn define_constants(cx: *mut JSContext, obj: HandleObject, } } -/// Defines methods on `obj`. The last entry of `methods` must contain zeroed -/// memory. -/// Fails on JSAPI failure. -fn define_methods(cx: *mut JSContext, obj: HandleObject, - methods: &'static [JSFunctionSpec]) { - unsafe { - assert!(JS_DefineFunctions(cx, obj, methods.as_ptr(), PropertyDefinitionBehavior::DefineAllProperties)); - } -} - -/// Defines attributes on `obj`. The last entry of `properties` must contain -/// zeroed memory. -/// Fails on JSAPI failure. -fn define_properties(cx: *mut JSContext, obj: HandleObject, - properties: &'static [JSPropertySpec]) { - unsafe { - assert!(JS_DefineProperties(cx, obj, properties.as_ptr())); - } -} - /// Creates the *interface prototype object*. /// Fails on JSAPI failure. fn create_interface_prototype_object(cx: *mut JSContext, global: HandleObject, @@ -375,11 +353,11 @@ fn create_interface_prototype_object(cx: *mut JSContext, global: HandleObject, assert!(!rval.get().is_null()); if let Some(methods) = members.methods { - define_methods(cx, rval.handle(), methods); + define_methods(cx, rval.handle(), methods).unwrap(); } if let Some(properties) = members.attrs { - define_properties(cx, rval.handle(), properties); + define_properties(cx, rval.handle(), properties).unwrap(); } if let Some(constants) = members.consts { diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index f14612d1f2f..aa7936f69f5 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -431,6 +431,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SaveContext)).unwrap(); } + #[allow(unrooted_must_root)] // https://html.spec.whatwg.org/multipage/#dom-context-2d-restore fn Restore(&self) { let mut saved_states = self.saved_states.borrow_mut(); diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index f0d078fbaf1..1be58932305 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -1461,6 +1461,11 @@ impl ElementMethods for Element { } } + // https://dom.spec.whatwg.org/#dom-element-webkitmatchesselector + fn WebkitMatchesSelector(&self, selectors: DOMString) -> Fallible<bool> { + self.Matches(selectors) + } + // https://dom.spec.whatwg.org/#dom-element-closest fn Closest(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> { match parse_author_origin_selector_list_from_str(&selectors) { diff --git a/components/script/dom/filelist.rs b/components/script/dom/filelist.rs index 57542b0a51d..d695ac8f43a 100644 --- a/components/script/dom/filelist.rs +++ b/components/script/dom/filelist.rs @@ -18,6 +18,7 @@ pub struct FileList { } impl FileList { + #[allow(unrooted_must_root)] fn new_inherited(files: Vec<JS<File>>) -> FileList { FileList { reflector_: Reflector::new(), @@ -25,6 +26,7 @@ impl FileList { } } + #[allow(unrooted_must_root)] pub fn new(window: &Window, files: Vec<JS<File>>) -> Root<FileList> { reflect_dom_object(box FileList::new_inherited(files), GlobalRef::Window(window), FileListBinding::Wrap) } diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs index dda2bd9b3b8..4ddc0fef6dd 100644 --- a/components/script/dom/htmlcollection.rs +++ b/components/script/dom/htmlcollection.rs @@ -32,6 +32,7 @@ pub struct HTMLCollection { } impl HTMLCollection { + #[allow(unrooted_must_root)] fn new_inherited(collection: Collection) -> HTMLCollection { HTMLCollection { reflector_: Reflector::new(), @@ -39,6 +40,7 @@ impl HTMLCollection { } } + #[allow(unrooted_must_root)] pub fn new(window: &Window, collection: Collection) -> Root<HTMLCollection> { reflect_dom_object(box HTMLCollection::new_inherited(collection), GlobalRef::Window(window), HTMLCollectionBinding::Wrap) diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs index 2ed127dd2dc..490df73bd56 100644 --- a/components/script/dom/nodelist.rs +++ b/components/script/dom/nodelist.rs @@ -27,6 +27,7 @@ pub struct NodeList { } impl NodeList { + #[allow(unrooted_must_root)] fn new_inherited(list_type: NodeListType) -> NodeList { NodeList { reflector_: Reflector::new(), @@ -34,6 +35,7 @@ impl NodeList { } } + #[allow(unrooted_must_root)] pub fn new(window: &Window, list_type: NodeListType) -> Root<NodeList> { reflect_dom_object(box NodeList::new_inherited(list_type), diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index c7011c8e056..749885571eb 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -109,6 +109,7 @@ impl WebGLRenderingContext { }) } + #[allow(unrooted_must_root)] pub fn new(global: GlobalRef, canvas: &HTMLCanvasElement, size: Size2D<i32>, attrs: GLContextAttributes) -> Option<Root<WebGLRenderingContext>> { match WebGLRenderingContext::new_inherited(global, canvas, size, attrs) { diff --git a/components/script/dom/webidls/Element.webidl b/components/script/dom/webidls/Element.webidl index b5b35f8e802..2e3deb6adb0 100644 --- a/components/script/dom/webidls/Element.webidl +++ b/components/script/dom/webidls/Element.webidl @@ -55,6 +55,8 @@ interface Element : Node { [Pure, Throws] boolean matches(DOMString selectors); + [Pure, Throws] + boolean webkitMatchesSelector(DOMString selectors); HTMLCollection getElementsByTagName(DOMString localName); HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index a2844fb225a..f112af3d8bd 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "js" version = "0.1.0" -source = "git+https://github.com/servo/rust-mozjs#01ff3cb8cb253a8a634cf6aecf64c10bf9c7d8c4" +source = "git+https://github.com/servo/rust-mozjs#cb290c48a75852fb26ed67b3ef3e2508c1560b1a" dependencies = [ "heapsize 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", |