diff options
author | Sankha Narayan Guria <sankha93@gmail.com> | 2014-02-27 03:31:05 +0530 |
---|---|---|
committer | Sankha Narayan Guria <sankha93@gmail.com> | 2014-02-27 03:31:05 +0530 |
commit | 1e9fec9172364346937f375e315e1ce745662611 (patch) | |
tree | a55173568e6dd6a8b4cb4dfcc42ed81204d49874 /src | |
parent | 47e6e6ec8f2dfbd56e50f9f2ec2762b85087d948 (diff) | |
parent | da16e54243e256dee927f720ce6b9903b62ec14e (diff) | |
download | servo-1e9fec9172364346937f375e315e1ce745662611.tar.gz servo-1e9fec9172364346937f375e315e1ce745662611.zip |
Merge master into this branch
Diffstat (limited to 'src')
161 files changed, 4693 insertions, 3359 deletions
diff --git a/src/components/gfx/gfx.rs b/src/components/gfx/gfx.rs index 5f30e60b4aa..c15d660b934 100644 --- a/src/components/gfx/gfx.rs +++ b/src/components/gfx/gfx.rs @@ -54,7 +54,6 @@ pub mod font_context; pub mod font_list; // Misc. -pub mod opts; mod buffer_map; // Platform-specific implementations. diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index f69c6a29a81..33dd70e87eb 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -4,7 +4,6 @@ use font_context::FontContext; use style::computed_values::border_style; -use opts::Opts; use azure::azure_hl::{B8G8R8A8, Color, ColorPattern, DrawOptions}; use azure::azure_hl::{DrawSurfaceOptions, DrawTarget, Linear, StrokeOptions}; @@ -18,6 +17,7 @@ use geom::side_offsets::SideOffsets2D; use servo_net::image::base::Image; use png::{RGBA8, K8, KA8}; use servo_util::geometry::Au; +use servo_util::opts::Opts; use std::libc::types::common::c99::uint16_t; use std::libc::size_t; diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs index 297c4f5517a..d60a0d84885 100644 --- a/src/components/gfx/render_task.rs +++ b/src/components/gfx/render_task.rs @@ -17,6 +17,7 @@ use servo_msg::compositor_msg::{RenderListener, RenderingRenderState}; use servo_msg::constellation_msg::{ConstellationChan, PipelineId, RendererReadyMsg}; use servo_msg::constellation_msg::{Failure, FailureMsg}; use servo_msg::platform::surface::NativeSurfaceAzureMethods; +use servo_util::opts::Opts; use servo_util::time::{ProfilerChan, profile}; use servo_util::time; use servo_util::task::send_on_failure; @@ -28,7 +29,6 @@ use extra::arc::Arc; use buffer_map::BufferMap; use display_list::DisplayListCollection; use font_context::{FontContext, FontContextInfo}; -use opts::Opts; use render_context::RenderContext; pub struct RenderLayer<T> { diff --git a/src/components/main/compositing/compositor.rs b/src/components/main/compositing/compositor.rs index 6b6b55254d9..d3f09d823a7 100644 --- a/src/components/main/compositing/compositor.rs +++ b/src/components/main/compositing/compositor.rs @@ -23,7 +23,6 @@ use geom::matrix::identity; use geom::point::Point2D; use geom::rect::Rect; use geom::size::Size2D; -use gfx::opts::Opts; use layers::layers::{ContainerLayer, ContainerLayerKind}; use layers::platform::surface::NativeCompositingGraphicsContext; use layers::rendergl; @@ -34,6 +33,7 @@ use png; use servo_msg::compositor_msg::{Blank, Epoch, FinishedLoading, IdleRenderState, LayerBufferSet, ReadyState, RenderState}; use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, NavigateMsg, ResizedWindowMsg, LoadUrlMsg, PipelineId}; use servo_msg::constellation_msg; +use servo_util::opts::Opts; use servo_util::time::{profile, ProfilerChan, Timer}; use servo_util::{time, url}; use std::comm::Port; diff --git a/src/components/main/compositing/compositor_task.rs b/src/components/main/compositing/compositor_task.rs index 6b5e6c9e347..38e43a8824b 100644 --- a/src/components/main/compositing/compositor_task.rs +++ b/src/components/main/compositing/compositor_task.rs @@ -12,11 +12,11 @@ use azure::azure_hl::{SourceSurfaceMethods, Color}; use geom::point::Point2D; use geom::rect::Rect; use geom::size::Size2D; -use gfx::opts::Opts; use layers::platform::surface::{NativeCompositingGraphicsContext, NativeGraphicsMetadata}; use servo_msg::compositor_msg::{Epoch, RenderListener, LayerBufferSet, RenderState, ReadyState}; use servo_msg::compositor_msg::{ScriptListener, Tile}; use servo_msg::constellation_msg::{ConstellationChan, PipelineId}; +use servo_util::opts::Opts; use servo_util::time::ProfilerChan; use std::comm::{Chan, SharedChan, Port}; use std::num::Orderable; diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs index f03dae64245..aa5f07b844f 100644 --- a/src/components/main/constellation.rs +++ b/src/components/main/constellation.rs @@ -7,7 +7,6 @@ use compositing::{CompositorChan, LoadComplete, SetIds, SetLayerClipRect, Shutdo use extra::url::Url; use geom::rect::Rect; use geom::size::Size2D; -use gfx::opts::Opts; use gfx::render_task; use pipeline::{Pipeline, CompositionPipeline}; use script::script_task::{ResizeMsg, ResizeInactiveMsg, ExitPipelineMsg}; @@ -21,6 +20,7 @@ use servo_msg::constellation_msg; use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient}; use servo_net::resource_task::ResourceTask; use servo_net::resource_task; +use servo_util::opts::Opts; use servo_util::time::ProfilerChan; use servo_util::url::parse_url; use servo_util::task::spawn_named; diff --git a/src/components/main/css/matching.rs b/src/components/main/css/matching.rs index 0f56c74fdfc..0dd4299e5d4 100644 --- a/src/components/main/css/matching.rs +++ b/src/components/main/css/matching.rs @@ -5,12 +5,14 @@ // High-level interface to CSS selector matching. use css::node_style::StyledNode; +use layout::construct::FlowConstructor; +use layout::context::LayoutContext; use layout::extra::LayoutAuxMethods; use layout::util::{LayoutDataAccess, LayoutDataWrapper}; -use layout::wrapper::{LayoutElement, LayoutNode}; +use layout::wrapper::{LayoutElement, LayoutNode, PostorderNodeMutTraversal, ThreadSafeLayoutNode}; use extra::arc::Arc; -use script::layout_interface::LayoutChan; +use gfx::font_context::FontContext; use servo_util::cache::{Cache, LRUCache, SimpleHashCache}; use servo_util::namespace::Null; use servo_util::smallvec::{SmallVec, SmallVec0, SmallVec16}; @@ -280,15 +282,17 @@ pub enum StyleSharingResult<'ln> { } pub trait MatchMethods { - /// Performs aux initialization, selector matching, and cascading sequentially. - fn match_and_cascade_subtree(&self, - stylist: &Stylist, - layout_chan: &LayoutChan, - applicable_declarations: &mut ApplicableDeclarations, - initial_values: &ComputedValues, - applicable_declarations_cache: &mut ApplicableDeclarationsCache, - style_sharing_candidate_cache: &mut StyleSharingCandidateCache, - parent: Option<LayoutNode>); + /// Performs aux initialization, selector matching, cascading, and flow construction + /// sequentially. + fn recalc_style_for_subtree(&self, + stylist: &Stylist, + layout_context: &mut LayoutContext, + mut font_context: ~FontContext, + applicable_declarations: &mut ApplicableDeclarations, + applicable_declarations_cache: &mut ApplicableDeclarationsCache, + style_sharing_candidate_cache: &mut StyleSharingCandidateCache, + parent: Option<LayoutNode>) + -> ~FontContext; fn match_node(&self, stylist: &Stylist, @@ -381,7 +385,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> { assert!(self.is_element()); let parent_node = match parent_node { - Some(parent_node) if parent_node.is_element() => parent_node, + Some(ref parent_node) if parent_node.is_element() => parent_node, Some(_) | None => return None, }; @@ -455,7 +459,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> { } for (i, &(ref candidate, ())) in style_sharing_candidate_cache.iter().enumerate() { - match self.share_style_with_candidate_if_possible(parent, candidate) { + match self.share_style_with_candidate_if_possible(parent.clone(), candidate) { Some(shared_style) => { // Yay, cache hit. Share the style. let mut layout_data_ref = self.mutate_layout_data(); @@ -474,19 +478,20 @@ impl<'ln> MatchMethods for LayoutNode<'ln> { CannotShare(true) } - fn match_and_cascade_subtree(&self, - stylist: &Stylist, - layout_chan: &LayoutChan, - applicable_declarations: &mut ApplicableDeclarations, - initial_values: &ComputedValues, - applicable_declarations_cache: &mut ApplicableDeclarationsCache, - style_sharing_candidate_cache: &mut StyleSharingCandidateCache, - parent: Option<LayoutNode>) { - self.initialize_layout_data((*layout_chan).clone()); + fn recalc_style_for_subtree(&self, + stylist: &Stylist, + layout_context: &mut LayoutContext, + mut font_context: ~FontContext, + applicable_declarations: &mut ApplicableDeclarations, + applicable_declarations_cache: &mut ApplicableDeclarationsCache, + style_sharing_candidate_cache: &mut StyleSharingCandidateCache, + parent: Option<LayoutNode>) + -> ~FontContext { + self.initialize_layout_data(layout_context.layout_chan.clone()); // First, check to see whether we can share a style with someone. let sharing_result = unsafe { - self.share_style_if_possible(style_sharing_candidate_cache, parent) + self.share_style_if_possible(style_sharing_candidate_cache, parent.clone()) }; // Otherwise, match and cascade selectors. @@ -497,6 +502,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> { } unsafe { + let initial_values = layout_context.initial_css_values.get(); self.cascade_node(parent, initial_values, applicable_declarations, @@ -514,14 +520,20 @@ impl<'ln> MatchMethods for LayoutNode<'ln> { } for kid in self.children() { - kid.match_and_cascade_subtree(stylist, - layout_chan, - applicable_declarations, - initial_values, - applicable_declarations_cache, - style_sharing_candidate_cache, - Some(*self)) + font_context = kid.recalc_style_for_subtree(stylist, + layout_context, + font_context, + applicable_declarations, + applicable_declarations_cache, + style_sharing_candidate_cache, + Some(self.clone())) } + + // Construct flows. + let layout_node = ThreadSafeLayoutNode::new(self); + let mut flow_constructor = FlowConstructor::new(layout_context, Some(font_context)); + flow_constructor.process(&layout_node); + flow_constructor.unwrap_font_context().unwrap() } unsafe fn cascade_node(&self, diff --git a/src/components/main/css/node_util.rs b/src/components/main/css/node_util.rs index 7493281d5cc..a14c2901452 100644 --- a/src/components/main/css/node_util.rs +++ b/src/components/main/css/node_util.rs @@ -12,10 +12,10 @@ use style::ComputedValues; pub trait NodeUtil { fn get_css_select_results<'a>(&'a self) -> &'a Arc<ComputedValues>; - fn have_css_select_results(self) -> bool; + fn have_css_select_results(&self) -> bool; - fn get_restyle_damage(self) -> RestyleDamage; - fn set_restyle_damage(self, damage: RestyleDamage); + fn get_restyle_damage(&self) -> RestyleDamage; + fn set_restyle_damage(&self, damage: RestyleDamage); } impl<'ln> NodeUtil for ThreadSafeLayoutNode<'ln> { @@ -36,14 +36,14 @@ impl<'ln> NodeUtil for ThreadSafeLayoutNode<'ln> { } /// Does this node have a computed style yet? - fn have_css_select_results(self) -> bool { + fn have_css_select_results(&self) -> bool { let layout_data_ref = self.borrow_layout_data(); layout_data_ref.get().get_ref().data.style.is_some() } /// Get the description of how to account for recent style changes. /// This is a simple bitfield and fine to copy by value. - fn get_restyle_damage(self) -> RestyleDamage { + fn get_restyle_damage(&self) -> RestyleDamage { // For DOM elements, if we haven't computed damage yet, assume the worst. // Other nodes don't have styles. let default = if self.node_is_element() { @@ -63,7 +63,7 @@ impl<'ln> NodeUtil for ThreadSafeLayoutNode<'ln> { } /// Set the restyle damage field. - fn set_restyle_damage(self, damage: RestyleDamage) { + fn set_restyle_damage(&self, damage: RestyleDamage) { let mut layout_data_ref = self.mutate_layout_data(); match *layout_data_ref.get() { Some(ref mut layout_data) => layout_data.data.restyle_damage = Some(damage.to_int()), diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index 607a85c2b7b..079654658b9 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -68,10 +68,10 @@ pub struct BlockFlow { } impl BlockFlow { - pub fn from_node(constructor: &mut FlowConstructor, node: ThreadSafeLayoutNode, is_fixed: bool) + pub fn from_node(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode, is_fixed: bool) -> BlockFlow { BlockFlow { - base: BaseFlow::new(constructor.next_flow_id(), node), + base: BaseFlow::new((*node).clone()), box_: Some(Box::new(constructor, node)), is_root: false, is_fixed: is_fixed, @@ -80,11 +80,11 @@ impl BlockFlow { } pub fn float_from_node(constructor: &mut FlowConstructor, - node: ThreadSafeLayoutNode, + node: &ThreadSafeLayoutNode, float_type: FloatType) -> BlockFlow { BlockFlow { - base: BaseFlow::new(constructor.next_flow_id(), node), + base: BaseFlow::new((*node).clone()), box_: Some(Box::new(constructor, node)), is_root: false, is_fixed: false, @@ -688,13 +688,12 @@ impl Flow for BlockFlow { /// Dual boxes consume some width first, and the remainder is assigned to all child (block) /// contexts. fn assign_widths(&mut self, ctx: &mut LayoutContext) { - debug!("assign_widths({}): assigning width for flow {}", + debug!("assign_widths({}): assigning width for flow", if self.is_float() { "float" } else { "block" - }, - self.base.id); + }); if self.is_root { debug!("Setting root position"); @@ -803,10 +802,10 @@ impl Flow for BlockFlow { fn assign_height_inorder(&mut self, ctx: &mut LayoutContext) { if self.is_float() { - debug!("assign_height_inorder_float: assigning height for float {}", self.base.id); + debug!("assign_height_inorder_float: assigning height for float"); self.assign_height_float_inorder(); } else { - debug!("assign_height_inorder: assigning height for block {}", self.base.id); + debug!("assign_height_inorder: assigning height for block"); self.assign_height_block_base(ctx, true); } } @@ -818,10 +817,10 @@ impl Flow for BlockFlow { } if self.is_float() { - debug!("assign_height_float: assigning height for float {}", self.base.id); + debug!("assign_height_float: assigning height for float"); self.assign_height_float(ctx); } else { - debug!("assign_height: assigning height for block {}", self.base.id); + debug!("assign_height: assigning height for block"); // This is the only case in which a block flow can start an inorder // subtraversal. if self.is_root && self.base.num_floats > 0 { diff --git a/src/components/main/layout/box_.rs b/src/components/main/layout/box_.rs index d0386cdb48a..ff6ccaf93b6 100644 --- a/src/components/main/layout/box_.rs +++ b/src/components/main/layout/box_.rs @@ -384,9 +384,9 @@ def_noncontent_horiz!(right, merge_noncontent_inline_right, clear_noncontent_inl impl Box { /// Constructs a new `Box` instance. - pub fn new(constructor: &mut FlowConstructor, node: ThreadSafeLayoutNode) -> Box { + pub fn new(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> Box { Box { - node: OpaqueNode::from_thread_safe_layout_node(&node), + node: OpaqueNode::from_thread_safe_layout_node(node), style: node.style().clone(), border_box: RefCell::new(Au::zero_rect()), border: RefCell::new(Zero::zero()), diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs index 41b38577599..0b43884c01f 100644 --- a/src/components/main/layout/construct.rs +++ b/src/components/main/layout/construct.rs @@ -27,17 +27,20 @@ use layout::box_::{InlineInfo, InlineParentInfo, SpecificBoxInfo, UnscannedTextB use layout::box_::{UnscannedTextBoxInfo}; use layout::context::LayoutContext; use layout::float_context::FloatType; -use layout::flow::{Flow, FlowLeafSet, ImmutableFlowUtils, MutableOwnedFlowUtils}; +use layout::flow::{Flow, MutableOwnedFlowUtils}; use layout::inline::InlineFlow; use layout::text::TextRunScanner; use layout::util::{LayoutDataAccess, OpaqueNode}; use layout::wrapper::{PostorderNodeMutTraversal, TLayoutNode, ThreadSafeLayoutNode}; use gfx::font_context::FontContext; +use script::dom::bindings::codegen::InheritTypes::TextCast; +use script::dom::bindings::js::JS; use script::dom::element::{HTMLIframeElementTypeId, HTMLImageElementTypeId, HTMLObjectElementTypeId}; use script::dom::node::{CommentNodeTypeId, DoctypeNodeTypeId, DocumentFragmentNodeTypeId}; use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId}; use script::dom::node::{TextNodeTypeId}; +use script::dom::text::Text; use style::computed_values::{display, position, float, white_space}; use style::ComputedValues; use servo_util::namespace; @@ -47,8 +50,6 @@ use servo_util::str::is_whitespace; use extra::url::Url; use extra::arc::Arc; - -use std::cell::RefCell; use std::util; use std::num::Zero; @@ -68,11 +69,11 @@ pub enum ConstructionResult { } impl ConstructionResult { - fn destroy(&mut self, leaf_set: &FlowLeafSet) { + fn destroy(&mut self) { match *self { NoConstructionResult => {} - FlowConstructionResult(ref mut flow) => flow.destroy(leaf_set), - ConstructionItemConstructionResult(ref mut item) => item.destroy(leaf_set), + FlowConstructionResult(ref mut flow) => flow.destroy(), + ConstructionItemConstructionResult(ref mut item) => item.destroy(), } } } @@ -88,12 +89,12 @@ enum ConstructionItem { } impl ConstructionItem { - fn destroy(&mut self, leaf_set: &FlowLeafSet) { + fn destroy(&mut self) { match *self { InlineBoxesConstructionItem(ref mut result) => { for splits in result.splits.mut_iter() { for split in splits.mut_iter() { - split.destroy(leaf_set) + split.destroy() } } } @@ -146,8 +147,8 @@ struct InlineBlockSplit { } impl InlineBlockSplit { - fn destroy(&mut self, leaf_set: &FlowLeafSet) { - self.flow.destroy(leaf_set) + fn destroy(&mut self) { + self.flow.destroy() } } @@ -219,59 +220,66 @@ pub struct FlowConstructor<'a> { /// The layout context. layout_context: &'a mut LayoutContext, - /// The next flow ID to assign. + /// An optional font context. If this is `None`, then we fetch the font context from the + /// layout context. /// - /// FIXME(pcwalton): This is going to have to be atomic; can't we do something better? - next_flow_id: RefCell<int>, - - /// The font context. - font_context: ~FontContext, - - /// The URL of the page. - url: &'a Url, + /// FIXME(pcwalton): This is pretty bogus and is basically just a workaround for libgreen + /// having slow TLS. + font_context: Option<~FontContext>, } -impl<'fc> FlowConstructor<'fc> { +impl<'a> FlowConstructor<'a> { /// Creates a new flow constructor. - pub fn init<'a>(layout_context: &'a mut LayoutContext, url: &'a Url) -> FlowConstructor<'a> { - let font_context = ~FontContext::new(layout_context.font_context_info.clone()); + pub fn new(layout_context: &'a mut LayoutContext, font_context: Option<~FontContext>) + -> FlowConstructor<'a> { FlowConstructor { layout_context: layout_context, - next_flow_id: RefCell::new(0), font_context: font_context, - url: url, } } - /// Returns the next flow ID and bumps the internal counter. - pub fn next_flow_id(&self) -> int { - let id = self.next_flow_id.get(); - self.next_flow_id.set(id + 1); - id + fn font_context<'a>(&'a mut self) -> &'a mut FontContext { + match self.font_context { + Some(ref mut font_context) => { + let font_context: &mut FontContext = *font_context; + font_context + } + None => self.layout_context.font_context(), + } + } + + /// Destroys this flow constructor and retrieves the font context. + pub fn unwrap_font_context(self) -> Option<~FontContext> { + let FlowConstructor { + font_context, + .. + } = self; + font_context } /// Builds the `ImageBoxInfo` for the given image. This is out of line to guide inlining. - fn build_box_info_for_image(&mut self, node: ThreadSafeLayoutNode, url: Option<Url>) -> SpecificBoxInfo { + fn build_box_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>) -> SpecificBoxInfo { match url { None => GenericBox, Some(url) => { // FIXME(pcwalton): The fact that image boxes store the cache within them makes // little sense to me. - ImageBox(ImageBoxInfo::new(&node, url, self.layout_context.image_cache.clone())) + ImageBox(ImageBoxInfo::new(node, url, self.layout_context.image_cache.clone())) } } } /// Builds specific `Box` info for the given node. - pub fn build_specific_box_info_for_node(&mut self, node: ThreadSafeLayoutNode) + pub fn build_specific_box_info_for_node(&mut self, node: &ThreadSafeLayoutNode) -> SpecificBoxInfo { match node.type_id() { ElementNodeTypeId(HTMLImageElementTypeId) => self.build_box_info_for_image(node, node.image_url()), - ElementNodeTypeId(HTMLIframeElementTypeId) => IframeBox(IframeBoxInfo::new(&node)), + ElementNodeTypeId(HTMLIframeElementTypeId) => IframeBox(IframeBoxInfo::new(node)), ElementNodeTypeId(HTMLObjectElementTypeId) => { - self.build_box_info_for_image(node, node.get_object_data(self.url)) + let data = node.get_object_data(&self.layout_context.url); + self.build_box_info_for_image(node, data) } - TextNodeTypeId => UnscannedTextBox(UnscannedTextBoxInfo::new(&node)), + TextNodeTypeId => UnscannedTextBox(UnscannedTextBoxInfo::new(node)), _ => GenericBox, } } @@ -284,14 +292,14 @@ impl<'fc> FlowConstructor<'fc> { fn flush_inline_boxes_to_flow(&mut self, boxes: ~[Box], flow: &mut ~Flow, - node: ThreadSafeLayoutNode) { + node: &ThreadSafeLayoutNode) { if boxes.len() == 0 { return } - let mut inline_flow = ~InlineFlow::from_boxes(self.next_flow_id(), node, boxes) as ~Flow; - inline_flow.mark_as_leaf(self.layout_context.flow_leaf_set.get()); - TextRunScanner::new().scan_for_runs(self.font_context, inline_flow); + let mut inline_flow = ~InlineFlow::from_boxes((*node).clone(), boxes) as ~Flow; + TextRunScanner::new().scan_for_runs(self.font_context(), inline_flow); + inline_flow.finish(self.layout_context); flow.add_new_child(inline_flow) } @@ -301,7 +309,7 @@ impl<'fc> FlowConstructor<'fc> { fn flush_inline_boxes_to_flow_if_necessary(&mut self, opt_boxes: &mut Option<~[Box]>, flow: &mut ~Flow, - node: ThreadSafeLayoutNode) { + node: &ThreadSafeLayoutNode) { let opt_boxes = util::replace(opt_boxes, None); if opt_boxes.len() > 0 { self.flush_inline_boxes_to_flow(opt_boxes.to_vec(), flow, node) @@ -311,7 +319,7 @@ impl<'fc> FlowConstructor<'fc> { /// Builds the children flows underneath a node with `display: block`. After this call, /// other `BlockFlow`s or `InlineFlow`s will be populated underneath this node, depending on /// whether {ib} splits needed to happen. - fn build_children_of_block_flow(&mut self, flow: &mut ~Flow, node: ThreadSafeLayoutNode) { + fn build_children_of_block_flow(&mut self, flow: &mut ~Flow, node: &ThreadSafeLayoutNode) { // Gather up boxes for the inline flows we might need to create. let mut opt_boxes_for_inline_flow = None; let mut first_box = true; @@ -396,17 +404,13 @@ impl<'fc> FlowConstructor<'fc> { node); // The flow is done. If it ended up with no kids, add the flow to the leaf set. - if flow.child_count() == 0 { - flow.mark_as_leaf(self.layout_context.flow_leaf_set.get()) - } else { - flow.mark_as_nonleaf() - } + flow.finish(self.layout_context) } /// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly /// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed /// to happen. - fn build_flow_for_block(&mut self, node: ThreadSafeLayoutNode, is_fixed: bool) -> ~Flow { + fn build_flow_for_block(&mut self, node: &ThreadSafeLayoutNode, is_fixed: bool) -> ~Flow { let mut flow = ~BlockFlow::from_node(self, node, is_fixed) as ~Flow; self.build_children_of_block_flow(&mut flow, node); flow @@ -414,7 +418,7 @@ impl<'fc> FlowConstructor<'fc> { /// Builds the flow for a node with `float: {left|right}`. This yields a float `BlockFlow` with /// a `BlockFlow` underneath it. - fn build_flow_for_floated_block(&mut self, node: ThreadSafeLayoutNode, float_type: FloatType) + fn build_flow_for_floated_block(&mut self, node: &ThreadSafeLayoutNode, float_type: FloatType) -> ~Flow { let mut flow = ~BlockFlow::float_from_node(self, node, float_type) as ~Flow; self.build_children_of_block_flow(&mut flow, node); @@ -425,7 +429,7 @@ impl<'fc> FlowConstructor<'fc> { /// Concatenates the boxes of kids, adding in our own borders/padding/margins if necessary. /// Returns the `InlineBoxesConstructionResult`, if any. There will be no /// `InlineBoxesConstructionResult` if this node consisted entirely of ignorable whitespace. - fn build_boxes_for_nonreplaced_inline_content(&mut self, node: ThreadSafeLayoutNode) + fn build_boxes_for_nonreplaced_inline_content(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult { let mut opt_inline_block_splits = None; let mut opt_box_accumulator = None; @@ -542,10 +546,10 @@ impl<'fc> FlowConstructor<'fc> { fn set_inline_info_for_inline_child(&mut self, boxes: &~[&Box], - parent_node: ThreadSafeLayoutNode) { + parent_node: &ThreadSafeLayoutNode) { let parent_box = Box::new(self, parent_node); let font_style = parent_box.font_style(); - let font_group = self.font_context.get_resolved_font_for_style(&font_style); + let font_group = self.font_context().get_resolved_font_for_style(&font_style); let (font_ascent,font_descent) = font_group.borrow().with_mut( |fg| { fg.fonts[0].borrow().with_mut( |font| { (font.metrics.ascent,font.metrics.descent) @@ -580,7 +584,7 @@ impl<'fc> FlowConstructor<'fc> { style: parent_box.style.clone(), font_ascent: font_ascent, font_descent: font_descent, - node: OpaqueNode::from_thread_safe_layout_node(&parent_node), + node: OpaqueNode::from_thread_safe_layout_node(parent_node), }); }, &None => {} @@ -589,7 +593,7 @@ impl<'fc> FlowConstructor<'fc> { } /// Creates an `InlineBoxesConstructionResult` for replaced content. Replaced content doesn't /// render its children, so this just nukes a child's boxes and creates a `Box`. - fn build_boxes_for_replaced_inline_content(&mut self, node: ThreadSafeLayoutNode) + fn build_boxes_for_replaced_inline_content(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult { for kid in node.children() { kid.set_flow_construction_result(NoConstructionResult) @@ -597,7 +601,7 @@ impl<'fc> FlowConstructor<'fc> { // If this node is ignorable whitespace, bail out now. if node.is_ignorable_whitespace() { - let opaque_node = OpaqueNode::from_thread_safe_layout_node(&node); + let opaque_node = OpaqueNode::from_thread_safe_layout_node(node); return ConstructionItemConstructionResult(WhitespaceConstructionItem( opaque_node, node.style().clone())) @@ -614,7 +618,7 @@ impl<'fc> FlowConstructor<'fc> { /// Builds one or more boxes for a node with `display: inline`. This yields an /// `InlineBoxesConstructionResult`. - fn build_boxes_for_inline(&mut self, node: ThreadSafeLayoutNode) -> ConstructionResult { + fn build_boxes_for_inline(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult { // Is this node replaced content? if !node.is_replaced_content() { // Go to a path that concatenates our kids' boxes. @@ -630,7 +634,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> { // `#[inline(always)]` because this is always called from the traversal function and for some // reason LLVM's inlining heuristics go awry here. #[inline(always)] - fn process(&mut self, node: ThreadSafeLayoutNode) -> bool { + fn process(&mut self, node: &ThreadSafeLayoutNode) -> bool { // Get the `display` property for this node, and determine whether this node is floated. let (display, float, position) = match node.type_id() { ElementNodeTypeId(_) => { @@ -641,7 +645,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> { CommentNodeTypeId | DoctypeNodeTypeId | DocumentFragmentNodeTypeId | - DocumentNodeTypeId(_) | + DocumentNodeTypeId | ProcessingInstructionNodeTypeId => (display::none, float::none, position::static_), }; @@ -654,7 +658,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> { (display::none, _, _) => { for child in node.children() { let mut old_result = child.swap_out_construction_result(); - old_result.destroy(self.layout_context.flow_leaf_set.get()) + old_result.destroy() } } @@ -693,39 +697,40 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> { /// A utility trait with some useful methods for node queries. trait NodeUtils { /// Returns true if this node doesn't render its kids and false otherwise. - fn is_replaced_content(self) -> bool; + fn is_replaced_content(&self) -> bool; /// Returns true if this node is ignorable whitespace. - fn is_ignorable_whitespace(self) -> bool; + fn is_ignorable_whitespace(&self) -> bool; /// Sets the construction result of a flow. - fn set_flow_construction_result(self, result: ConstructionResult); + fn set_flow_construction_result(&self, result: ConstructionResult); /// Replaces the flow construction result in a node with `NoConstructionResult` and returns the /// old value. - fn swap_out_construction_result(self) -> ConstructionResult; + fn swap_out_construction_result(&self) -> ConstructionResult; } impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> { - fn is_replaced_content(self) -> bool { + fn is_replaced_content(&self) -> bool { match self.type_id() { TextNodeTypeId | ProcessingInstructionNodeTypeId | CommentNodeTypeId | DoctypeNodeTypeId | DocumentFragmentNodeTypeId | - DocumentNodeTypeId(_) | + DocumentNodeTypeId | ElementNodeTypeId(HTMLImageElementTypeId) => true, ElementNodeTypeId(HTMLObjectElementTypeId) => self.has_object_data(), ElementNodeTypeId(_) => false, } } - fn is_ignorable_whitespace(self) -> bool { + fn is_ignorable_whitespace(&self) -> bool { match self.type_id() { TextNodeTypeId => { unsafe { - if !self.with_text(|text| is_whitespace(text.characterdata.data)) { + let text: JS<Text> = TextCast::to(self.get_jsmanaged()); + if !is_whitespace(text.get().characterdata.data) { return false } @@ -746,7 +751,7 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> { } #[inline(always)] - fn set_flow_construction_result(self, result: ConstructionResult) { + fn set_flow_construction_result(&self, result: ConstructionResult) { let mut layout_data_ref = self.mutate_layout_data(); match *layout_data_ref.get() { Some(ref mut layout_data) => layout_data.data.flow_construction_result = result, @@ -755,7 +760,7 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> { } #[inline(always)] - fn swap_out_construction_result(self) -> ConstructionResult { + fn swap_out_construction_result(&self) -> ConstructionResult { let mut layout_data_ref = self.mutate_layout_data(); match *layout_data_ref.get() { Some(ref mut layout_data) => { @@ -769,29 +774,29 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> { /// Methods for interacting with HTMLObjectElement nodes trait ObjectElement { /// Returns None if this node is not matching attributes. - fn get_type_and_data(self) -> (Option<&'static str>, Option<&'static str>); + fn get_type_and_data(&self) -> (Option<&'static str>, Option<&'static str>); /// Returns true if this node has object data that is correct uri. - fn has_object_data(self) -> bool; + fn has_object_data(&self) -> bool; /// Returns the "data" attribute value parsed as a URL - fn get_object_data(self, base_url: &Url) -> Option<Url>; + fn get_object_data(&self, base_url: &Url) -> Option<Url>; } impl<'ln> ObjectElement for ThreadSafeLayoutNode<'ln> { - fn get_type_and_data(self) -> (Option<&'static str>, Option<&'static str>) { + fn get_type_and_data(&self) -> (Option<&'static str>, Option<&'static str>) { (self.with_element(|e| { e.get_attr(&namespace::Null, "type") } ), self.with_element(|e| { e.get_attr(&namespace::Null, "data") } )) } - fn has_object_data(self) -> bool { + fn has_object_data(&self) -> bool { match self.get_type_and_data() { (None, Some(uri)) => is_image_data(uri), _ => false } } - fn get_object_data(self, base_url: &Url) -> Option<Url> { + fn get_object_data(&self, base_url: &Url) -> Option<Url> { match self.get_type_and_data() { (None, Some(uri)) if is_image_data(uri) => Some(parse_url(uri, Some(base_url.clone()))), _ => None diff --git a/src/components/main/layout/context.rs b/src/components/main/layout/context.rs index 61b8c3e03e6..d2ce78bd3d8 100644 --- a/src/components/main/layout/context.rs +++ b/src/components/main/layout/context.rs @@ -5,11 +5,10 @@ //! Data needed by the layout task. use css::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache}; -use layout::flow::FlowLeafSet; use layout::util::OpaqueNode; -use layout::wrapper::DomLeafSet; use extra::arc::{Arc, MutexArc}; +use extra::url::Url; use geom::size::Size2D; use gfx::font_context::{FontContext, FontContextInfo}; use green::task::GreenTask; @@ -17,6 +16,7 @@ use script::layout_interface::LayoutChan; use servo_msg::constellation_msg::ConstellationChan; use servo_net::local_image_cache::LocalImageCache; use servo_util::geometry::Au; +use servo_util::opts::Opts; use std::cast; use std::ptr; use std::rt::Runtime; @@ -47,15 +47,9 @@ pub struct LayoutContext { /// A channel up to the constellation. constellation_chan: ConstellationChan, - /// The set of leaf DOM nodes. - dom_leaf_set: Arc<DomLeafSet>, - /// A channel up to the layout task. layout_chan: LayoutChan, - /// The set of leaf flows. - flow_leaf_set: Arc<FlowLeafSet>, - /// Information needed to construct a font context. font_context_info: FontContextInfo, @@ -69,18 +63,26 @@ pub struct LayoutContext { /// The root node at which we're starting the layout. reflow_root: OpaqueNode, + + /// The URL. + url: Url, + + /// The command line options. + opts: Opts, } impl LayoutContext { pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext { // Sanity check. - let mut task = Local::borrow(None::<Task>); - match task.get().maybe_take_runtime::<GreenTask>() { - Some(green) => { - task.get().put_runtime(green as ~Runtime); - fail!("can't call this on a green task!") + { + let mut task = Local::borrow(None::<Task>); + match task.get().maybe_take_runtime::<GreenTask>() { + Some(green) => { + task.get().put_runtime(green as ~Runtime); + fail!("can't call this on a green task!") + } + None => {} } - None => {} } unsafe { diff --git a/src/components/main/layout/extra.rs b/src/components/main/layout/extra.rs index ba7cf8a2595..a5724aaabcd 100644 --- a/src/components/main/layout/extra.rs +++ b/src/components/main/layout/extra.rs @@ -10,15 +10,15 @@ use script::layout_interface::LayoutChan; /// Functionality useful for querying the layout-specific data on DOM nodes. pub trait LayoutAuxMethods { - fn initialize_layout_data(self, chan: LayoutChan); - fn initialize_style_for_subtree(self, chan: LayoutChan); + fn initialize_layout_data(&self, chan: LayoutChan); + fn initialize_style_for_subtree(&self, chan: LayoutChan); } impl<'ln> LayoutAuxMethods for LayoutNode<'ln> { /// Resets layout data and styles for the node. /// /// FIXME(pcwalton): Do this as part of box building instead of in a traversal. - fn initialize_layout_data(self, chan: LayoutChan) { + fn initialize_layout_data(&self, chan: LayoutChan) { let mut layout_data_ref = self.mutate_layout_data(); match *layout_data_ref.get() { None => { @@ -34,7 +34,7 @@ impl<'ln> LayoutAuxMethods for LayoutNode<'ln> { /// Resets layout data and styles for a Node tree. /// /// FIXME(pcwalton): Do this as part of box building instead of in a traversal. - fn initialize_style_for_subtree(self, chan: LayoutChan) { + fn initialize_style_for_subtree(&self, chan: LayoutChan) { for n in self.traverse_preorder() { n.initialize_layout_data(chan.clone()); } diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs index 1cc1a1cf075..b4a14a53ad9 100644 --- a/src/components/main/layout/flow.rs +++ b/src/components/main/layout/flow.rs @@ -33,7 +33,7 @@ use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData}; use layout::float_context::{FloatContext, Invalid}; use layout::incremental::RestyleDamage; use layout::inline::InlineFlow; -use layout::parallel::{FlowParallelInfo, UnsafeFlow}; +use layout::parallel::FlowParallelInfo; use layout::parallel; use layout::wrapper::ThreadSafeLayoutNode; use layout::flow_list::{FlowList, Link, Rawlink, FlowListIterator, MutFlowListIterator}; @@ -45,7 +45,6 @@ use geom::rect::Rect; use gfx::display_list::{ClipDisplayItemClass, DisplayListCollection, DisplayList}; use layout::display_list_builder::ToGfxColor; use gfx::color::Color; -use servo_util::concurrentmap::{ConcurrentHashMap, ConcurrentHashMapIterator}; use servo_util::geometry::Au; use std::cast; use std::cell::RefCell; @@ -215,7 +214,7 @@ pub trait MutableFlowUtils { -> bool; /// Destroys the flow. - fn destroy(self, leaf_set: &FlowLeafSet); + fn destroy(self); } pub trait MutableOwnedFlowUtils { @@ -223,15 +222,16 @@ pub trait MutableOwnedFlowUtils { /// it's present. fn add_new_child(&mut self, new_child: ~Flow); - /// Marks the flow as a leaf. The flow must not have children and must not be marked as a - /// nonleaf. - fn mark_as_leaf(&mut self, leaf_set: &FlowLeafSet); - - /// Marks the flow as a nonleaf. The flow must not be marked as a leaf. - fn mark_as_nonleaf(&mut self); + /// Finishes a flow. Once a flow is finished, no more child flows or boxes may be added to it. + /// This will normally run the bubble-widths (minimum and preferred -- i.e. intrinsic -- width) + /// calculation, unless the global `bubble_widths_separately` flag is on. + /// + /// All flows must be finished at some point, or they will not have their intrinsic widths + /// properly computed. (This is not, however, a memory safety problem.) + fn finish(&mut self, context: &mut LayoutContext); /// Destroys the flow. - fn destroy(&mut self, leaf_set: &FlowLeafSet); + fn destroy(&mut self); } pub enum FlowClass { @@ -455,13 +455,6 @@ bitfield!(FlowFlags, override_overline, set_override_overline, 0b0000_0100) // NB: If you update this, you need to update TEXT_DECORATION_OVERRIDE_BITMASK. bitfield!(FlowFlags, override_line_through, set_override_line_through, 0b0000_1000) -// Whether this flow is marked as a leaf. Flows marked as leaves must not have any more kids added -// to them. -bitfield!(FlowFlags, is_leaf, set_is_leaf, 0b0100_0000) - -// Whether this flow is marked as a nonleaf. Flows marked as nonleaves must have children. -bitfield!(FlowFlags, is_nonleaf, set_is_nonleaf, 0b1000_0000) - // The text alignment for this flow. impl FlowFlags { #[inline] @@ -499,9 +492,6 @@ pub struct BaseFlow { next_sibling: Link, prev_sibling: Rawlink, - /* TODO (Issue #87): debug only */ - id: int, - /* layout computations */ // TODO: min/pref and position are used during disjoint phases of // layout; maybe combine into a single enum to save space. @@ -563,7 +553,7 @@ impl Iterator<@Box> for BoxIterator { impl BaseFlow { #[inline] - pub fn new(id: int, node: ThreadSafeLayoutNode) -> BaseFlow { + pub fn new(node: ThreadSafeLayoutNode) -> BaseFlow { let style = node.style(); BaseFlow { restyle_damage: node.restyle_damage(), @@ -572,8 +562,6 @@ impl BaseFlow { next_sibling: None, prev_sibling: Rawlink::none(), - id: id, - min_width: Au::new(0), pref_width: Au::new(0), position: Au::zero_rect(), @@ -740,7 +728,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow { mut index: uint, lists: &RefCell<DisplayListCollection<E>>) -> bool { - debug!("Flow: building display list for f{}", base(self).id); + debug!("Flow: building display list"); index = match self.class() { BlockFlowClass => self.as_block().build_display_list_block(builder, container_block_size, dirty, index, lists), InlineFlowClass => self.as_inline().build_display_list_inline(builder, container_block_size, dirty, index, lists), @@ -797,18 +785,9 @@ impl<'a> MutableFlowUtils for &'a mut Flow { } /// Destroys the flow. - fn destroy(self, leaf_set: &FlowLeafSet) { - let is_leaf = { - let base = mut_base(self); - base.children.len() == 0 - }; - - if is_leaf { - leaf_set.remove(self); - } else { - for kid in child_iter(self) { - kid.destroy(leaf_set) - } + fn destroy(self) { + for kid in child_iter(self) { + kid.destroy() } mut_base(self).destroyed = true @@ -824,84 +803,26 @@ impl MutableOwnedFlowUtils for ~Flow { } let base = mut_base(*self); - assert!(!base.flags_info.flags.is_leaf()); base.children.push_back(new_child); let _ = base.parallel.children_count.fetch_add(1, Relaxed); } - /// Marks the flow as a leaf. The flow must not have children and must not be marked as a - /// nonleaf. - fn mark_as_leaf(&mut self, leaf_set: &FlowLeafSet) { - { - let base = mut_base(*self); - if base.flags_info.flags.is_nonleaf() { - fail!("attempted to mark a nonleaf flow as a leaf!") - } - if base.children.len() != 0 { - fail!("attempted to mark a flow with children as a leaf!") - } - base.flags_info.flags.set_is_leaf(true) - } - let self_borrowed: &Flow = *self; - leaf_set.insert(self_borrowed); - } - - /// Marks the flow as a nonleaf. The flow must not be marked as a leaf. - fn mark_as_nonleaf(&mut self) { - let base = mut_base(*self); - if base.flags_info.flags.is_leaf() { - fail!("attempted to mark a leaf flow as a nonleaf!") + /// Finishes a flow. Once a flow is finished, no more child flows or boxes may be added to it. + /// This will normally run the bubble-widths (minimum and preferred -- i.e. intrinsic -- width) + /// calculation, unless the global `bubble_widths_separately` flag is on. + /// + /// All flows must be finished at some point, or they will not have their intrinsic widths + /// properly computed. (This is not, however, a memory safety problem.) + fn finish(&mut self, context: &mut LayoutContext) { + if !context.opts.bubble_widths_separately { + self.bubble_widths(context) } - base.flags_info.flags.set_is_nonleaf(true) - // We don't check to make sure there are no children as they might be added later. } /// Destroys the flow. - fn destroy(&mut self, leaf_set: &FlowLeafSet) { + fn destroy(&mut self) { let self_borrowed: &mut Flow = *self; - self_borrowed.destroy(leaf_set); + self_borrowed.destroy(); } } -/// Keeps track of the leaves of the flow tree. This is used to efficiently start bottom-up -/// parallel traversals. -pub struct FlowLeafSet { - priv set: ConcurrentHashMap<UnsafeFlow,()>, -} - -impl FlowLeafSet { - /// Creates a new flow leaf set. - pub fn new() -> FlowLeafSet { - FlowLeafSet { - set: ConcurrentHashMap::with_locks_and_buckets(64, 256), - } - } - - /// Inserts a newly-created flow into the leaf set. - fn insert(&self, flow: &Flow) { - self.set.insert(parallel::borrowed_flow_to_unsafe_flow(flow), ()); - } - - /// Removes a flow from the leaf set. Asserts that the flow was indeed in the leaf set. (This - /// invariant is needed for memory safety, as there must always be exactly one leaf set.) - fn remove(&self, flow: &Flow) { - if !self.contains(flow) { - fail!("attempted to remove a flow from the leaf set that wasn't in the set!") - } - let flow = parallel::borrowed_flow_to_unsafe_flow(flow); - self.set.remove(&flow); - } - - pub fn contains(&self, flow: &Flow) -> bool { - let flow = parallel::borrowed_flow_to_unsafe_flow(flow); - self.set.contains_key(&flow) - } - - pub fn clear(&self) { - self.set.clear() - } - - pub fn iter<'a>(&'a self) -> ConcurrentHashMapIterator<'a,UnsafeFlow,()> { - self.set.iter() - } -} diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs index 8332c7adb7d..e6a2643536f 100644 --- a/src/components/main/layout/inline.rs +++ b/src/components/main/layout/inline.rs @@ -84,8 +84,8 @@ impl LineboxScanner { self.floats.clone() } - fn reset_scanner(&mut self, flow: &mut InlineFlow) { - debug!("Resetting line box scanner's state for flow f{:d}.", flow.base.id); + fn reset_scanner(&mut self) { + debug!("Resetting line box scanner's state for flow."); self.lines = ~[]; self.new_boxes = ~[]; self.cur_y = Au::new(0); @@ -99,7 +99,7 @@ impl LineboxScanner { } pub fn scan_for_lines(&mut self, flow: &mut InlineFlow) { - self.reset_scanner(flow); + self.reset_scanner(); loop { // acquire the next box to lay out from work list or box list @@ -142,9 +142,8 @@ impl LineboxScanner { } fn swap_out_results(&mut self, flow: &mut InlineFlow) { - debug!("LineboxScanner: Propagating scanned lines[n={:u}] to inline flow f{:d}", - self.lines.len(), - flow.base.id); + debug!("LineboxScanner: Propagating scanned lines[n={:u}] to inline flow", + self.lines.len()); util::swap(&mut flow.boxes, &mut self.new_boxes); util::swap(&mut flow.lines, &mut self.lines); @@ -466,9 +465,9 @@ pub struct InlineFlow { } impl InlineFlow { - pub fn from_boxes(id: int, node: ThreadSafeLayoutNode, boxes: ~[Box]) -> InlineFlow { + pub fn from_boxes(node: ThreadSafeLayoutNode, boxes: ~[Box]) -> InlineFlow { InlineFlow { - base: BaseFlow::new(id, node), + base: BaseFlow::new(node), boxes: boxes, lines: ~[], elems: ElementMapping::new(), @@ -497,9 +496,7 @@ impl InlineFlow { // TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and // not recurse on a line if nothing in it can intersect the dirty region. - debug!("Flow[{:d}]: building display list for {:u} inline boxes", - self.base.id, - self.boxes.len()); + debug!("Flow: building display list for {:u} inline boxes", self.boxes.len()); for box_ in self.boxes.iter() { let rel_offset: Point2D<Au> = box_.relative_position(container_block_size); @@ -636,7 +633,7 @@ impl Flow for InlineFlow { let mut pref_width = Au::new(0); for box_ in self.boxes.iter() { - debug!("Flow[{:d}]: measuring {:s}", self.base.id, box_.debug_str()); + debug!("Flow: measuring {:s}", box_.debug_str()); box_.compute_borders(box_.style()); let (this_minimum_width, this_preferred_width) = box_.minimum_and_preferred_widths(); @@ -690,7 +687,7 @@ impl Flow for InlineFlow { } fn assign_height(&mut self, _: &mut LayoutContext) { - debug!("assign_height_inline: assigning height for flow {}", self.base.id); + debug!("assign_height_inline: assigning height for flow"); // Divide the boxes into lines. // diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index f9856724659..2f70d0ea499 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -9,18 +9,17 @@ use css::matching::{ApplicableDeclarations, ApplicableDeclarationsCache, MatchMe use css::matching::{StyleSharingCandidateCache}; use css::select::new_stylist; use css::node_style::StyledNode; -use layout::construct::{FlowConstructionResult, FlowConstructor, NoConstructionResult}; +use layout::construct::{FlowConstructionResult, NoConstructionResult}; use layout::context::LayoutContext; use layout::display_list_builder::{DisplayListBuilder, ToGfxColor}; -use layout::flow::{Flow, FlowLeafSet, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; +use layout::flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow::{PreorderFlowTraversal, PostorderFlowTraversal}; use layout::flow; use layout::incremental::RestyleDamage; -use layout::parallel::{AssignHeightsAndStoreOverflowTraversalKind, BubbleWidthsTraversalKind}; -use layout::parallel::{UnsafeFlow}; +use layout::parallel::PaddedUnsafeFlow; use layout::parallel; use layout::util::{LayoutDataAccess, OpaqueNode, LayoutDataWrapper}; -use layout::wrapper::{DomLeafSet, LayoutNode, TLayoutNode, ThreadSafeLayoutNode}; +use layout::wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode}; use extra::url::Url; use extra::arc::{Arc, MutexArc}; @@ -28,24 +27,25 @@ use geom::rect::Rect; use geom::size::Size2D; use gfx::display_list::{ClipDisplayItemClass, DisplayItem, DisplayItemIterator}; use gfx::display_list::{DisplayList, DisplayListCollection}; -use gfx::font_context::FontContextInfo; -use gfx::opts::Opts; +use gfx::font_context::{FontContext, FontContextInfo}; use gfx::render_task::{RenderMsg, RenderChan, RenderLayer}; use gfx::{render_task, color}; +use script::dom::bindings::js::JS; use script::dom::event::ReflowEvent; -use script::dom::node::{ElementNodeTypeId, LayoutDataRef}; +use script::dom::node::{ElementNodeTypeId, LayoutDataRef, Node}; use script::dom::element::{HTMLBodyElementTypeId, HTMLHtmlElementTypeId}; use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery}; use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitNowMsg, LayoutQuery}; use script::layout_interface::{HitTestQuery, ContentBoxResponse, HitTestResponse, MouseOverQuery, MouseOverResponse}; use script::layout_interface::{ContentChangedDocumentDamage, LayoutChan, Msg, PrepareToExitMsg}; -use script::layout_interface::{QueryMsg, ReapLayoutDataMsg, Reflow, ReflowDocumentDamage, UntrustedNodeAddress}; +use script::layout_interface::{QueryMsg, ReapLayoutDataMsg, Reflow, UntrustedNodeAddress}; use script::layout_interface::{ReflowForDisplay, ReflowMsg}; use script::script_task::{ReflowCompleteMsg, ScriptChan, SendEventMsg}; use servo_msg::constellation_msg::{ConstellationChan, PipelineId, Failure, FailureMsg}; use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg}; use servo_net::local_image_cache::{ImageResponder, LocalImageCache}; use servo_util::geometry::Au; +use servo_util::opts::Opts; use servo_util::time::{ProfilerChan, profile}; use servo_util::time; use servo_util::task::send_on_failure; @@ -86,12 +86,6 @@ pub struct LayoutTask { /// The local image cache. local_image_cache: MutexArc<LocalImageCache>, - /// The set of leaves in the DOM tree. - dom_leaf_set: Arc<DomLeafSet>, - - /// The set of leaves in the flow tree. - flow_leaf_set: Arc<FlowLeafSet>, - /// The size of the viewport. screen_size: Size2D<Au>, @@ -104,7 +98,7 @@ pub struct LayoutTask { initial_css_values: Arc<ComputedValues>, /// The workers that we use for parallel operation. - parallel_traversal: Option<WorkQueue<*mut LayoutContext,UnsafeFlow>>, + parallel_traversal: Option<WorkQueue<*mut LayoutContext,PaddedUnsafeFlow>>, /// The channel on which messages can be sent to the profiler. profiler_chan: ProfilerChan, @@ -194,12 +188,14 @@ impl<'a> PostorderFlowTraversal for BubbleWidthsTraversal<'a> { } /// The assign-widths traversal. In Gecko this corresponds to `Reflow`. -struct AssignWidthsTraversal<'a>(&'a mut LayoutContext); +pub struct AssignWidthsTraversal<'a> { + layout_context: &'a mut LayoutContext, +} impl<'a> PreorderFlowTraversal for AssignWidthsTraversal<'a> { #[inline] fn process(&mut self, flow: &mut Flow) -> bool { - flow.assign_widths(**self); + flow.assign_widths(self.layout_context); true } } @@ -303,8 +299,6 @@ impl LayoutTask { image_cache_task: image_cache_task.clone(), local_image_cache: local_image_cache, screen_size: screen_size, - dom_leaf_set: Arc::new(DomLeafSet::new()), - flow_leaf_set: Arc::new(FlowLeafSet::new()), display_list_collection: None, stylist: ~new_stylist(), @@ -323,7 +317,7 @@ impl LayoutTask { } // Create a layout context for use in building display lists, hit testing, &c. - fn build_layout_context(&self, reflow_root: &LayoutNode) -> LayoutContext { + fn build_layout_context(&self, reflow_root: &LayoutNode, url: &Url) -> LayoutContext { let font_context_info = FontContextInfo { backend: self.opts.render_backend, needs_font_list: true, @@ -334,13 +328,13 @@ impl LayoutTask { image_cache: self.local_image_cache.clone(), screen_size: self.screen_size.clone(), constellation_chan: self.constellation_chan.clone(), - dom_leaf_set: self.dom_leaf_set.clone(), - flow_leaf_set: self.flow_leaf_set.clone(), layout_chan: self.chan.clone(), font_context_info: font_context_info, stylist: &*self.stylist, initial_css_values: self.initial_css_values.clone(), + url: (*url).clone(), reflow_root: OpaqueNode::from_layout_node(reflow_root), + opts: self.opts.clone(), } } @@ -422,17 +416,8 @@ impl LayoutTask { self.stylist.add_stylesheet(sheet, AuthorOrigin) } - /// Builds the flow tree. - /// - /// This corresponds to the various `nsCSSFrameConstructor` methods in Gecko or - /// `createRendererIfNeeded` in WebKit. Note, however that in WebKit `createRendererIfNeeded` - /// is intertwined with selector matching, making it difficult to compare directly. It is - /// marked `#[inline(never)]` to aid benchmarking in sampling profilers. - #[inline(never)] - fn construct_flow_tree(&self, layout_context: &mut LayoutContext, node: LayoutNode, url: &Url) -> ~Flow { - let node = ThreadSafeLayoutNode::new(node); - node.traverse_postorder_mut(&mut FlowConstructor::init(layout_context, url)); - + /// Retrieves the flow tree root from the root node. + fn get_layout_root(&self, node: LayoutNode) -> ~Flow { let mut layout_data_ref = node.mutate_layout_data(); let result = match *layout_data_ref.get() { Some(ref mut layout_data) => { @@ -456,7 +441,7 @@ impl LayoutTask { fn solve_constraints(&mut self, layout_root: &mut Flow, layout_context: &mut LayoutContext) { - { + if layout_context.opts.bubble_widths_separately { let mut traversal = BubbleWidthsTraversal { layout_context: layout_context, }; @@ -468,7 +453,12 @@ impl LayoutTask { // recompute them every time. // NOTE: this currently computes borders, so any pruning should separate that operation // out. - layout_root.traverse_preorder(&mut AssignWidthsTraversal(layout_context)); + { + let mut traversal = AssignWidthsTraversal { + layout_context: layout_context, + }; + layout_root.traverse_preorder(&mut traversal); + } // FIXME(pcwalton): Prune this pass as well. { @@ -485,28 +475,24 @@ impl LayoutTask { /// benchmarked against those two. It is marked `#[inline(never)]` to aid profiling. #[inline(never)] fn solve_constraints_parallel(&mut self, - layout_root: &mut Flow, + layout_root: &mut ~Flow, layout_context: &mut LayoutContext) { + if layout_context.opts.bubble_widths_separately { + let mut traversal = BubbleWidthsTraversal { + layout_context: layout_context, + }; + layout_root.traverse_postorder(&mut traversal); + } + match self.parallel_traversal { None => fail!("solve_contraints_parallel() called with no parallel traversal ready"), Some(ref mut traversal) => { - parallel::traverse_flow_tree(BubbleWidthsTraversalKind, - &self.flow_leaf_set, - self.profiler_chan.clone(), - layout_context, - traversal); - // NOTE: this currently computes borders, so any pruning should separate that // operation out. - // TODO(pcwalton): Run this in parallel as well. This will require a bit more work - // because this is a top-down traversal, unlike the others. - layout_root.traverse_preorder(&mut AssignWidthsTraversal(layout_context)); - - parallel::traverse_flow_tree(AssignHeightsAndStoreOverflowTraversalKind, - &self.flow_leaf_set, - self.profiler_chan.clone(), - layout_context, - traversal); + parallel::traverse_flow_tree_preorder(layout_root, + self.profiler_chan.clone(), + layout_context, + traversal); } } } @@ -527,8 +513,9 @@ impl LayoutTask { /// The high-level routine that performs layout tasks. fn handle_reflow(&mut self, data: &Reflow) { // FIXME: Isolate this transmutation into a "bridge" module. - let node: &LayoutNode = unsafe { - transmute(&data.document_root) + let node: &mut LayoutNode = unsafe { + let mut node: JS<Node> = JS::from_trusted_node_address(data.document_root); + transmute(&mut node) }; debug!("layout: received layout request for: {:s}", data.url.to_str()); @@ -558,45 +545,51 @@ impl LayoutTask { self.screen_size = current_screen_size; // Create a layout context for use throughout the following passes. - let mut layout_ctx = self.build_layout_context(node); + let mut layout_ctx = self.build_layout_context(node, &data.url); + + // Create a font context, if this is sequential. + // + // FIXME(pcwalton): This is a pretty bogus thing to do. Essentially this is a workaround + // for libgreen having slow TLS. + let mut font_context_opt = if self.parallel_traversal.is_none() { + Some(~FontContext::new(layout_ctx.font_context_info.clone())) + } else { + None + }; + + // Create a font context, if this is sequential. + // + // FIXME(pcwalton): This is a pretty bogus thing to do. Essentially this is a workaround + // for libgreen having slow TLS. + let mut font_context_opt = if self.parallel_traversal.is_none() { + Some(~FontContext::new(layout_ctx.font_context_info.clone())) + } else { + None + }; let mut layout_root = profile(time::LayoutStyleRecalcCategory, self.profiler_chan.clone(), || { - // Perform CSS selector matching if necessary. - match data.damage.level { - ReflowDocumentDamage => {} - _ => { - profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone(), || { - match self.parallel_traversal { - None => { - let mut applicable_declarations = ApplicableDeclarations::new(); - let mut applicable_declarations_cache = - ApplicableDeclarationsCache::new(); - let mut style_sharing_candidate_cache = - StyleSharingCandidateCache::new(); - node.match_and_cascade_subtree(self.stylist, - &layout_ctx.layout_chan, - &mut applicable_declarations, - layout_ctx.initial_css_values.get(), - &mut applicable_declarations_cache, - &mut style_sharing_candidate_cache, - None) - } - Some(ref mut traversal) => { - parallel::match_and_cascade_subtree(node, - &mut layout_ctx, - traversal) - } - } - }) + // Perform CSS selector matching and flow construction. + match self.parallel_traversal { + None => { + let mut applicable_declarations = ApplicableDeclarations::new(); + let mut applicable_declarations_cache = ApplicableDeclarationsCache::new(); + let mut style_sharing_candidate_cache = StyleSharingCandidateCache::new(); + drop(node.recalc_style_for_subtree(self.stylist, + &mut layout_ctx, + font_context_opt.take_unwrap(), + &mut applicable_declarations, + &mut applicable_declarations_cache, + &mut style_sharing_candidate_cache, + None)) + } + Some(ref mut traversal) => { + parallel::recalc_style_for_subtree(node, &mut layout_ctx, traversal) } } - // Construct the flow tree. - profile(time::LayoutTreeBuilderCategory, - self.profiler_chan.clone(), - || self.construct_flow_tree(&mut layout_ctx, *node, &data.url)) + self.get_layout_root((*node).clone()) }); // Verification of the flow tree, which ensures that all nodes were either marked as leaves @@ -622,7 +615,7 @@ impl LayoutTask { } Some(_) => { // Parallel mode. - self.solve_constraints_parallel(layout_root, &mut layout_ctx) + self.solve_constraints_parallel(&mut layout_root, &mut layout_ctx) } } }); @@ -648,7 +641,7 @@ impl LayoutTask { if child.type_id() == ElementNodeTypeId(HTMLHtmlElementTypeId) || child.type_id() == ElementNodeTypeId(HTMLBodyElementTypeId) { let element_bg_color = { - let thread_safe_child = ThreadSafeLayoutNode::new(child); + let thread_safe_child = ThreadSafeLayoutNode::new(&child); thread_safe_child.style() .get() .resolve_color(thread_safe_child.style() @@ -683,7 +676,7 @@ impl LayoutTask { }); } - layout_root.destroy(self.flow_leaf_set.get()); + layout_root.destroy(); // Tell script that we're done. // @@ -700,7 +693,7 @@ impl LayoutTask { // The neat thing here is that in order to answer the following two queries we only // need to compare nodes for equality. Thus we can safely work only with `OpaqueNode`. ContentBoxQuery(node, reply_chan) => { - let node = OpaqueNode::from_script_node(&node); + let node = OpaqueNode::from_script_node(node); fn union_boxes_for_node<'a>( accumulator: &mut Option<Rect<Au>>, @@ -724,7 +717,7 @@ impl LayoutTask { reply_chan.send(ContentBoxResponse(rect.unwrap_or(Au::zero_rect()))) } ContentBoxesQuery(node, reply_chan) => { - let node = OpaqueNode::from_script_node(&node); + let node = OpaqueNode::from_script_node(node); fn add_boxes_for_node<'a>( accumulator: &mut ~[Rect<Au>], diff --git a/src/components/main/layout/parallel.rs b/src/components/main/layout/parallel.rs index f6ddc27cce4..5e4da051dbc 100644 --- a/src/components/main/layout/parallel.rs +++ b/src/components/main/layout/parallel.rs @@ -7,15 +7,17 @@ //! This code is highly unsafe. Keep this file small and easy to audit. use css::matching::{ApplicableDeclarations, CannotShare, MatchMethods, StyleWasShared}; +use layout::construct::FlowConstructor; use layout::context::LayoutContext; use layout::extra::LayoutAuxMethods; -use layout::flow::{Flow, FlowLeafSet, PostorderFlowTraversal}; +use layout::flow::{Flow, PreorderFlowTraversal, PostorderFlowTraversal}; use layout::flow; -use layout::layout_task::{AssignHeightsAndStoreOverflowTraversal, BubbleWidthsTraversal}; +use layout::layout_task::{AssignHeightsAndStoreOverflowTraversal, AssignWidthsTraversal}; +use layout::layout_task::{BubbleWidthsTraversal}; use layout::util::{LayoutDataAccess, OpaqueNode}; -use layout::wrapper::{layout_node_to_unsafe_layout_node, LayoutNode, UnsafeLayoutNode}; +use layout::wrapper::{layout_node_to_unsafe_layout_node, LayoutNode, PostorderNodeMutTraversal}; +use layout::wrapper::{ThreadSafeLayoutNode, UnsafeLayoutNode}; -use extra::arc::Arc; use servo_util::time::{ProfilerChan, profile}; use servo_util::time; use servo_util::workqueue::{WorkQueue, WorkUnit, WorkerProxy}; @@ -24,11 +26,36 @@ use std::ptr; use std::sync::atomics::{AtomicInt, Relaxed, SeqCst}; use style::{Stylist, TNode}; -pub enum TraversalKind { - BubbleWidthsTraversalKind, - AssignHeightsAndStoreOverflowTraversalKind, +#[allow(dead_code)] +fn static_assertion(node: UnsafeLayoutNode) { + unsafe { + let _: PaddedUnsafeFlow = ::std::unstable::intrinsics::transmute(node); + } +} + +/// Memory representation that is at least as large as UnsafeLayoutNode, as it must be +/// safely transmutable to and from that type to accommodate the type-unsafe parallel work +/// queue usage that stores both flows and nodes. +pub type PaddedUnsafeFlow = (uint, uint, uint); + +trait UnsafeFlowConversions { + fn to_flow(&self) -> UnsafeFlow; + fn from_flow(flow: &UnsafeFlow) -> Self; +} + +impl UnsafeFlowConversions for PaddedUnsafeFlow { + fn to_flow(&self) -> UnsafeFlow { + let (vtable, ptr, _padding) = *self; + (vtable, ptr) + } + + fn from_flow(flow: &UnsafeFlow) -> PaddedUnsafeFlow { + let &(vtable, ptr) = flow; + (vtable, ptr, 0) + } } +/// Vtable + pointer representation of a Flow trait object. pub type UnsafeFlow = (uint, uint); fn null_unsafe_flow() -> UnsafeFlow { @@ -92,7 +119,9 @@ impl FlowParallelInfo { /// A parallel bottom-up flow traversal. trait ParallelPostorderFlowTraversal : PostorderFlowTraversal { - fn run_parallel(&mut self, mut unsafe_flow: UnsafeFlow) { + fn run_parallel(&mut self, + mut unsafe_flow: UnsafeFlow, + _: &mut WorkerProxy<*mut LayoutContext,PaddedUnsafeFlow>) { loop { unsafe { // Get a real flow. @@ -131,17 +160,69 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal { } } +/// A parallel top-down flow traversal. +trait ParallelPreorderFlowTraversal : PreorderFlowTraversal { + fn run_parallel(&mut self, + unsafe_flow: UnsafeFlow, + proxy: &mut WorkerProxy<*mut LayoutContext,PaddedUnsafeFlow>); + + fn run_parallel_helper(&mut self, + unsafe_flow: UnsafeFlow, + proxy: &mut WorkerProxy<*mut LayoutContext,PaddedUnsafeFlow>, + top_down_func: extern "Rust" fn(PaddedUnsafeFlow, + &mut WorkerProxy<*mut LayoutContext, + PaddedUnsafeFlow>), + bottom_up_func: extern "Rust" fn(PaddedUnsafeFlow, + &mut WorkerProxy<*mut LayoutContext, + PaddedUnsafeFlow>)) { + let mut had_children = false; + unsafe { + // Get a real flow. + let flow: &mut ~Flow = cast::transmute(&unsafe_flow); + + // Perform the appropriate traversal. + self.process(*flow); + + // Possibly enqueue the children. + for kid in flow::child_iter(*flow) { + had_children = true; + proxy.push(WorkUnit { + fun: top_down_func, + data: UnsafeFlowConversions::from_flow(&borrowed_flow_to_unsafe_flow(kid)), + }); + } + + } + + // If there were no more children, start assigning heights. + if !had_children { + bottom_up_func(UnsafeFlowConversions::from_flow(&unsafe_flow), proxy) + } + } +} + impl<'a> ParallelPostorderFlowTraversal for BubbleWidthsTraversal<'a> {} +impl<'a> ParallelPreorderFlowTraversal for AssignWidthsTraversal<'a> { + fn run_parallel(&mut self, + unsafe_flow: UnsafeFlow, + proxy: &mut WorkerProxy<*mut LayoutContext,PaddedUnsafeFlow>) { + self.run_parallel_helper(unsafe_flow, + proxy, + assign_widths, + assign_heights_and_store_overflow) + } +} + impl<'a> ParallelPostorderFlowTraversal for AssignHeightsAndStoreOverflowTraversal<'a> {} -fn match_and_cascade_node(unsafe_layout_node: UnsafeLayoutNode, - proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) { +fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode, + proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) { unsafe { let layout_context: &mut LayoutContext = cast::transmute(*proxy.user_data()); // Get a real layout node. - let node: LayoutNode = cast::transmute(unsafe_layout_node); + let node: LayoutNode = ::std::unstable::intrinsics::transmute(unsafe_layout_node); // Initialize layout data. // @@ -159,7 +240,7 @@ fn match_and_cascade_node(unsafe_layout_node: UnsafeLayoutNode, // First, check to see whether we can share a style with someone. let style_sharing_candidate_cache = layout_context.style_sharing_candidate_cache(); let sharing_result = node.share_style_if_possible(style_sharing_candidate_cache, - parent_opt); + parent_opt.clone()); // Otherwise, match and cascade selectors. match sharing_result { @@ -186,24 +267,61 @@ fn match_and_cascade_node(unsafe_layout_node: UnsafeLayoutNode, StyleWasShared(index) => style_sharing_candidate_cache.touch(index), } - // Enqueue kids. + // Prepare for flow construction by counting the node's children and storing that count. let mut child_count = 0; - for kid in node.children() { + for _ in node.children() { child_count += 1; + } + if child_count != 0 { + let mut layout_data_ref = node.mutate_layout_data(); + match *layout_data_ref.get() { + Some(ref mut layout_data) => { + layout_data.data.parallel.children_count.store(child_count as int, Relaxed) + } + None => fail!("no layout data"), + } - proxy.push(WorkUnit { - fun: match_and_cascade_node, - data: layout_node_to_unsafe_layout_node(&kid), - }); + // Enqueue kids. + for kid in node.children() { + proxy.push(WorkUnit { + fun: recalc_style_for_node, + data: layout_node_to_unsafe_layout_node(&kid), + }); + } + return } - // Prepare for flow construction by adding this node to the leaf set or counting its - // children. - if child_count == 0 { - // We don't need set the `child_count` field here since that's only used by kids during - // bottom-up traversals, and since this node is a leaf it has no kids. - layout_context.dom_leaf_set.get().insert(&node); - } else { + // If we got here, we're a leaf. Start construction of flows for this node. + construct_flows(unsafe_layout_node, proxy) + } +} + +fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode, + proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) { + loop { + let layout_context: &mut LayoutContext = unsafe { + cast::transmute(*proxy.user_data()) + }; + + // Get a real layout node. + let node: LayoutNode = unsafe { + cast::transmute(unsafe_layout_node) + }; + + // Construct flows for this node. + { + let mut flow_constructor = FlowConstructor::new(layout_context, None); + flow_constructor.process(&ThreadSafeLayoutNode::new(&node)); + } + + // Reset the count of children for the next traversal. + // + // FIXME(pcwalton): Use children().len() when the implementation of that is efficient. + let mut child_count = 0; + for _ in node.children() { + child_count += 1 + } + { let mut layout_data_ref = node.mutate_layout_data(); match *layout_data_ref.get() { Some(ref mut layout_data) => { @@ -212,40 +330,75 @@ fn match_and_cascade_node(unsafe_layout_node: UnsafeLayoutNode, None => fail!("no layout data"), } } + + // If this is the reflow root, we're done. + if layout_context.reflow_root == OpaqueNode::from_layout_node(&node) { + break + } + + // Otherwise, enqueue the parent. + match node.parent_node() { + Some(parent) => { + + // No, we're not at the root yet. Then are we the last sibling of our parent? + // If so, we can continue on with our parent; otherwise, we've gotta wait. + unsafe { + match *parent.borrow_layout_data_unchecked() { + Some(ref parent_layout_data) => { + let parent_layout_data = cast::transmute_mut(parent_layout_data); + if parent_layout_data.data + .parallel + .children_count + .fetch_sub(1, SeqCst) == 1 { + // We were the last child of our parent. Construct flows for our + // parent. + unsafe_layout_node = layout_node_to_unsafe_layout_node(&parent) + } else { + // Get out of here and find another node to work on. + break + } + } + None => fail!("no layout data for parent?!"), + } + } + } + None => fail!("no parent and weren't at reflow root?!"), + } } } -fn bubble_widths(unsafe_flow: UnsafeFlow, proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) { +fn assign_widths(unsafe_flow: PaddedUnsafeFlow, + proxy: &mut WorkerProxy<*mut LayoutContext,PaddedUnsafeFlow>) { let layout_context: &mut LayoutContext = unsafe { cast::transmute(*proxy.user_data()) }; - let mut bubble_widths_traversal = BubbleWidthsTraversal { + let mut assign_widths_traversal = AssignWidthsTraversal { layout_context: layout_context, }; - bubble_widths_traversal.run_parallel(unsafe_flow) + assign_widths_traversal.run_parallel(unsafe_flow.to_flow(), proxy) } -fn assign_heights_and_store_overflow(unsafe_flow: UnsafeFlow, - proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) { +fn assign_heights_and_store_overflow(unsafe_flow: PaddedUnsafeFlow, + proxy: &mut WorkerProxy<*mut LayoutContext,PaddedUnsafeFlow>) { let layout_context: &mut LayoutContext = unsafe { cast::transmute(*proxy.user_data()) }; let mut assign_heights_traversal = AssignHeightsAndStoreOverflowTraversal { layout_context: layout_context, }; - assign_heights_traversal.run_parallel(unsafe_flow) + assign_heights_traversal.run_parallel(unsafe_flow.to_flow(), proxy) } -pub fn match_and_cascade_subtree(root_node: &LayoutNode, - layout_context: &mut LayoutContext, - queue: &mut WorkQueue<*mut LayoutContext,UnsafeLayoutNode>) { +pub fn recalc_style_for_subtree(root_node: &LayoutNode, + layout_context: &mut LayoutContext, + queue: &mut WorkQueue<*mut LayoutContext,UnsafeLayoutNode>) { unsafe { queue.data = cast::transmute(layout_context) } // Enqueue the root node. queue.push(WorkUnit { - fun: match_and_cascade_node, + fun: recalc_style_for_node, data: layout_node_to_unsafe_layout_node(root_node), }); @@ -254,27 +407,19 @@ pub fn match_and_cascade_subtree(root_node: &LayoutNode, queue.data = ptr::mut_null() } -pub fn traverse_flow_tree(kind: TraversalKind, - leaf_set: &Arc<FlowLeafSet>, - profiler_chan: ProfilerChan, - layout_context: &mut LayoutContext, - queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) { +pub fn traverse_flow_tree_preorder(root: &mut ~Flow, + profiler_chan: ProfilerChan, + layout_context: &mut LayoutContext, + queue: &mut WorkQueue<*mut LayoutContext,PaddedUnsafeFlow>) { unsafe { queue.data = cast::transmute(layout_context) } - let fun = match kind { - BubbleWidthsTraversalKind => bubble_widths, - AssignHeightsAndStoreOverflowTraversalKind => assign_heights_and_store_overflow, - }; - profile(time::LayoutParallelWarmupCategory, profiler_chan, || { - for (flow, _) in leaf_set.get().iter() { - queue.push(WorkUnit { - fun: fun, - data: *flow, - }) - } + queue.push(WorkUnit { + fun: assign_widths, + data: UnsafeFlowConversions::from_flow(&mut_owned_flow_to_unsafe_flow(root)), + }) }); queue.run(); diff --git a/src/components/main/layout/util.rs b/src/components/main/layout/util.rs index 7a2eeb8f805..de10f8a8d9a 100644 --- a/src/components/main/layout/util.rs +++ b/src/components/main/layout/util.rs @@ -8,9 +8,10 @@ use layout::parallel::DomParallelInfo; use layout::wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode}; use extra::arc::Arc; +use script::dom::bindings::js::JS; use script::dom::bindings::utils::Reflectable; -use script::dom::node::AbstractNode; -use script::layout_interface::{LayoutChan, UntrustedNodeAddress}; +use script::dom::node::Node; +use script::layout_interface::{LayoutChan, UntrustedNodeAddress, TrustedNodeAddress}; use servo_util::range::Range; use std::cast; use std::cell::{Ref, RefMut}; @@ -212,23 +213,28 @@ impl OpaqueNode { /// Converts a DOM node (layout view) to an `OpaqueNode`. pub fn from_layout_node(node: &LayoutNode) -> OpaqueNode { unsafe { - let abstract_node = node.get_abstract(); - let ptr: uintptr_t = cast::transmute(abstract_node.reflector().get_jsobject()); - OpaqueNode(ptr) + OpaqueNode::from_jsmanaged(node.get_jsmanaged()) } } /// Converts a thread-safe DOM node (layout view) to an `OpaqueNode`. pub fn from_thread_safe_layout_node(node: &ThreadSafeLayoutNode) -> OpaqueNode { unsafe { - let abstract_node = node.get_abstract(); + let abstract_node = node.get_jsmanaged(); let ptr: uintptr_t = cast::transmute(abstract_node.reflector().get_jsobject()); OpaqueNode(ptr) } } /// Converts a DOM node (script view) to an `OpaqueNode`. - pub fn from_script_node(node: &AbstractNode) -> OpaqueNode { + pub fn from_script_node(node: TrustedNodeAddress) -> OpaqueNode { + unsafe { + OpaqueNode::from_jsmanaged(&JS::from_trusted_node_address(node)) + } + } + + /// Converts a DOM node to an `OpaqueNode'. + fn from_jsmanaged(node: &JS<Node>) -> OpaqueNode { unsafe { let ptr: uintptr_t = cast::transmute(node.reflector().get_jsobject()); OpaqueNode(ptr) diff --git a/src/components/main/layout/wrapper.rs b/src/components/main/layout/wrapper.rs index 2e67eff3567..a5830b7f00c 100644 --- a/src/components/main/layout/wrapper.rs +++ b/src/components/main/layout/wrapper.rs @@ -11,18 +11,20 @@ //! //! (1) Layout is not allowed to mutate the DOM. //! -//! (2) Layout is not allowed to see anything with `Abstract` in the name, because it could hang +//! (2) Layout is not allowed to see anything with `JS` in the name, because it could hang //! onto these objects and cause use-after-free. use extra::url::Url; +use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementCast, HTMLIFrameElementCast}; +use script::dom::bindings::codegen::InheritTypes::{TextCast, ElementCast}; +use script::dom::bindings::js::JS; use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId}; use script::dom::element::{HTMLLinkElementTypeId}; use script::dom::htmliframeelement::HTMLIFrameElement; use script::dom::htmlimageelement::HTMLImageElement; -use script::dom::node::{AbstractNode, DocumentNodeTypeId, ElementNodeTypeId, Node, NodeTypeId}; +use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, Node, NodeTypeId, NodeHelpers}; use script::dom::text::Text; use servo_msg::constellation_msg::{PipelineId, SubpageId}; -use servo_util::concurrentmap::{ConcurrentHashMap, ConcurrentHashMapIterator}; use servo_util::namespace; use servo_util::namespace::Namespace; use std::cast; @@ -35,20 +37,20 @@ use layout::util::LayoutDataWrapper; /// Allows some convenience methods on generic layout nodes. pub trait TLayoutNode { /// Creates a new layout node with the same lifetime as this layout node. - unsafe fn new_with_this_lifetime(&self, node: AbstractNode) -> Self; + unsafe fn new_with_this_lifetime(&self, node: JS<Node>) -> Self; /// Returns the type ID of this node. Fails if this node is borrowed mutably. fn type_id(&self) -> NodeTypeId; - /// Returns the interior of this node as an `AbstractNode`. This is highly unsafe for layout to + + /// Returns the interior of this node as a `JS`. This is highly unsafe for layout to /// call and as such is marked `unsafe`. - unsafe fn get_abstract(&self) -> AbstractNode; + unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node>; /// Returns the interior of this node as a `Node`. This is highly unsafe for layout to call /// and as such is marked `unsafe`. unsafe fn get<'a>(&'a self) -> &'a Node { - let node = self.get_abstract(); - cast::transmute(node.node()) + self.get_jsmanaged().get() } fn node_is_element(&self) -> bool { @@ -70,40 +72,18 @@ pub trait TLayoutNode { /// FIXME(pcwalton): Don't copy URLs. fn image_url(&self) -> Option<Url> { unsafe { - self.with_image_element(|image_element| { - image_element.image.as_ref().map(|url| (*url).clone()) - }) - } - } - - /// Downcasts this node to an iframe element and calls the given closure. - /// - /// FIXME(pcwalton): RAII. - unsafe fn with_iframe_element<R>(&self, f: |&HTMLIFrameElement| -> R) -> R { - if !self.get_abstract().is_iframe_element() { - fail!(~"node is not an iframe element"); + let image_element: JS<HTMLImageElement> = HTMLImageElementCast::to(self.get_jsmanaged()); + image_element.get().extra.image.as_ref().map(|url| (*url).clone()) } - self.get_abstract().transmute(f) - } - - /// Downcasts this node to an image element and calls the given closure. - /// - /// FIXME(pcwalton): RAII. - unsafe fn with_image_element<R>(&self, f: |&HTMLImageElement| -> R) -> R { - if !self.get_abstract().is_image_element() { - fail!(~"node is not an image element"); - } - self.get_abstract().transmute(f) } /// If this node is an iframe element, returns its pipeline and subpage IDs. If this node is /// not an iframe element, fails. fn iframe_pipeline_and_subpage_ids(&self) -> (PipelineId, SubpageId) { unsafe { - self.with_iframe_element(|iframe_element| { - let size = iframe_element.size.unwrap(); - (size.pipeline_id, size.subpage_id) - }) + let iframe_element: JS<HTMLIFrameElement> = HTMLIFrameElementCast::to(self.get_jsmanaged()); + let size = iframe_element.get().size.unwrap(); + (size.pipeline_id, size.subpage_id) } } @@ -112,45 +92,39 @@ pub trait TLayoutNode { /// FIXME(pcwalton): Don't copy text. Atomically reference count instead. fn text(&self) -> ~str { unsafe { - self.with_text(|text| text.characterdata.data.to_str()) + let text: JS<Text> = TextCast::to(self.get_jsmanaged()); + text.get().characterdata.data.to_str() } } - /// Downcasts this node to a text node and calls the given closure. - /// - /// FIXME(pcwalton): RAII. - unsafe fn with_text<R>(&self, f: |&Text| -> R) -> R { - self.get_abstract().with_imm_text(f) - } - /// Returns the first child of this node. fn first_child(&self) -> Option<Self> { unsafe { - self.get_abstract().first_child().map(|node| self.new_with_this_lifetime(node)) + self.get_jsmanaged().first_child().map(|node| self.new_with_this_lifetime(node)) } } /// Dumps this node tree, for debugging. fn dump(&self) { unsafe { - self.get_abstract().dump() + self.get_jsmanaged().dump() } } } /// A wrapper so that layout can access only the methods that it should have access to. Layout must -/// only ever see these and must never see instances of `AbstractNode`. +/// only ever see these and must never see instances of `JS`. #[deriving(Clone, Eq)] pub struct LayoutNode<'a> { /// The wrapped node. - priv node: AbstractNode, + priv node: JS<Node>, /// Being chained to a value prevents `LayoutNode`s from escaping. priv chain: &'a (), } impl<'ln> TLayoutNode for LayoutNode<'ln> { - unsafe fn new_with_this_lifetime(&self, node: AbstractNode) -> LayoutNode<'ln> { + unsafe fn new_with_this_lifetime(&self, node: JS<Node>) -> LayoutNode<'ln> { LayoutNode { node: node, chain: self.chain, @@ -159,14 +133,14 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> { fn type_id(&self) -> NodeTypeId { self.node.type_id() } - unsafe fn get_abstract(&self) -> AbstractNode { - self.node + unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> { + &self.node } } impl<'ln> LayoutNode<'ln> { /// Creates a new layout node, scoped to the given closure. - pub unsafe fn with_layout_node<R>(node: AbstractNode, f: <'a> |LayoutNode<'a>| -> R) -> R { + pub unsafe fn with_layout_node<R>(node: JS<Node>, f: <'a> |LayoutNode<'a>| -> R) -> R { let heavy_iron_ball = (); f(LayoutNode { node: node, @@ -194,34 +168,34 @@ impl<'ln> LayoutNode<'ln> { impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> { fn parent_node(&self) -> Option<LayoutNode<'ln>> { unsafe { - self.node.node().parent_node.map(|node| self.new_with_this_lifetime(node)) + self.node.parent_node().map(|node| self.new_with_this_lifetime(node)) } } fn prev_sibling(&self) -> Option<LayoutNode<'ln>> { unsafe { - self.node.node().prev_sibling.map(|node| self.new_with_this_lifetime(node)) + self.node.prev_sibling().map(|node| self.new_with_this_lifetime(node)) } } fn next_sibling(&self) -> Option<LayoutNode<'ln>> { unsafe { - self.node.node().next_sibling.map(|node| self.new_with_this_lifetime(node)) + self.node.next_sibling().map(|node| self.new_with_this_lifetime(node)) } } /// If this is an element, accesses the element data. Fails if this is not an element node. #[inline] fn with_element<R>(&self, f: |&LayoutElement<'ln>| -> R) -> R { - self.node.with_imm_element(|element| { - // FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on - // implementations. - unsafe { - f(&LayoutElement { - element: cast::transmute_region(element), - }) - } - }) + let elem: JS<Element> = ElementCast::to(&self.node); + let element = elem.get(); + // FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on + // implementations. + unsafe { + f(&LayoutElement { + element: cast::transmute_region(element), + }) + } } fn is_element(&self) -> bool { @@ -257,8 +231,8 @@ pub struct LayoutNodeChildrenIterator<'a> { impl<'a> Iterator<LayoutNode<'a>> for LayoutNodeChildrenIterator<'a> { fn next(&mut self) -> Option<LayoutNode<'a>> { - let node = self.current_node; - self.current_node = self.current_node.and_then(|node| { + let node = self.current_node.clone(); + self.current_node = node.clone().and_then(|node| { node.next_sibling() }); node @@ -358,7 +332,7 @@ impl<'le> TElement for LayoutElement<'le> { /// node does not allow any parents or siblings of nodes to be accessed, to avoid races. pub struct ThreadSafeLayoutNode<'ln> { /// The wrapped node. - priv node: AbstractNode, + priv node: JS<Node>, /// Being chained to a value prevents `ThreadSafeLayoutNode`s from escaping. priv chain: &'ln (), @@ -366,7 +340,7 @@ pub struct ThreadSafeLayoutNode<'ln> { impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> { /// Creates a new layout node with the same lifetime as this layout node. - unsafe fn new_with_this_lifetime(&self, node: AbstractNode) -> ThreadSafeLayoutNode<'ln> { + unsafe fn new_with_this_lifetime(&self, node: JS<Node>) -> ThreadSafeLayoutNode<'ln> { ThreadSafeLayoutNode { node: node, chain: self.chain, @@ -375,23 +349,32 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> { fn type_id(&self) -> NodeTypeId { self.node.type_id() } - unsafe fn get_abstract(&self) -> AbstractNode { - self.node + unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> { + &self.node + } +} + +impl<'ln> Clone for ThreadSafeLayoutNode<'ln> { + fn clone(&self) -> ThreadSafeLayoutNode<'ln> { + ThreadSafeLayoutNode { + node: self.node.clone(), + chain: self.chain, + } } } impl<'ln> ThreadSafeLayoutNode<'ln> { /// Creates a new `ThreadSafeLayoutNode` from the given `LayoutNode`. - pub fn new<'a>(node: LayoutNode<'a>) -> ThreadSafeLayoutNode<'a> { + pub fn new<'a>(node: &LayoutNode<'a>) -> ThreadSafeLayoutNode<'a> { ThreadSafeLayoutNode { - node: node.node, + node: node.node.clone(), chain: node.chain, } } /// Returns the next sibling of this node. Unsafe and private because this can lead to races. unsafe fn next_sibling(&self) -> Option<ThreadSafeLayoutNode<'ln>> { - self.node.node().next_sibling.map(|node| self.new_with_this_lifetime(node)) + self.node.next_sibling().map(|node| self.new_with_this_lifetime(node)) } /// Returns an iterator over this node's children. @@ -405,12 +388,12 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { #[inline] pub fn with_element<R>(&self, f: |&ThreadSafeLayoutElement| -> R) -> R { unsafe { - self.get_abstract().with_imm_element(|element| { - // FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on - // implementations. - f(&ThreadSafeLayoutElement { - element: cast::transmute_region(element), - }) + let elem: JS<Element> = ElementCast::to(&self.node); + let element = elem.get(); + // FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on + // implementations. + f(&ThreadSafeLayoutElement { + element: cast::transmute_region(element), }) } } @@ -434,7 +417,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { /// Traverses the tree in postorder. /// /// TODO(pcwalton): Offer a parallel version with a compatible API. - pub fn traverse_postorder_mut<T:PostorderNodeMutTraversal>(mut self, traversal: &mut T) + pub fn traverse_postorder_mut<T:PostorderNodeMutTraversal>(&mut self, traversal: &mut T) -> bool { if traversal.should_prune(self) { return true @@ -444,7 +427,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { loop { match opt_kid { None => break, - Some(kid) => { + Some(mut kid) => { if !kid.traverse_postorder_mut(traversal) { return false } @@ -465,8 +448,8 @@ pub struct ThreadSafeLayoutNodeChildrenIterator<'a> { impl<'a> Iterator<ThreadSafeLayoutNode<'a>> for ThreadSafeLayoutNodeChildrenIterator<'a> { fn next(&mut self) -> Option<ThreadSafeLayoutNode<'a>> { - let node = self.current_node; - self.current_node = self.current_node.and_then(|node| { + let node = self.current_node.clone(); + self.current_node = self.current_node.clone().and_then(|node| { unsafe { node.next_sibling() } @@ -491,17 +474,19 @@ impl<'le> ThreadSafeLayoutElement<'le> { /// A bottom-up, parallelizable traversal. pub trait PostorderNodeMutTraversal { /// The operation to perform. Return true to continue or false to stop. - fn process<'a>(&'a mut self, node: ThreadSafeLayoutNode<'a>) -> bool; + fn process<'a>(&'a mut self, node: &ThreadSafeLayoutNode<'a>) -> bool; /// Returns true if this node should be pruned. If this returns true, we skip the operation /// entirely and do not process any descendant nodes. This is called *before* child nodes are /// visited. The default implementation never prunes any nodes. - fn should_prune<'a>(&'a self, _node: ThreadSafeLayoutNode<'a>) -> bool { + fn should_prune<'a>(&'a self, _node: &ThreadSafeLayoutNode<'a>) -> bool { false } } -pub type UnsafeLayoutNode = (uint, uint); +/// Opaque type stored in type-unsafe work queues for parallel layout. +/// Must be transmutable to and from LayoutNode/ThreadsafeLayoutNode/PaddedUnsafeFlow. +pub type UnsafeLayoutNode = (uint, uint, uint); pub fn layout_node_to_unsafe_layout_node(node: &LayoutNode) -> UnsafeLayoutNode { unsafe { @@ -509,32 +494,3 @@ pub fn layout_node_to_unsafe_layout_node(node: &LayoutNode) -> UnsafeLayoutNode } } -/// Keeps track of the leaves of the DOM. This is used to efficiently start bottom-up traversals. -pub struct DomLeafSet { - priv set: ConcurrentHashMap<UnsafeLayoutNode,()>, -} - -impl DomLeafSet { - /// Creates a new DOM leaf set. - pub fn new() -> DomLeafSet { - DomLeafSet { - set: ConcurrentHashMap::with_locks_and_buckets(64, 256), - } - } - - /// Inserts a DOM node into the leaf set. - pub fn insert(&self, node: &LayoutNode) { - self.set.insert(layout_node_to_unsafe_layout_node(node), ()); - } - - /// Removes all DOM nodes from the set. - pub fn clear(&self) { - self.set.clear() - } - - /// Iterates over the DOM nodes in the leaf set. - pub fn iter<'a>(&'a self) -> ConcurrentHashMapIterator<'a,UnsafeLayoutNode,()> { - self.set.iter() - } -} - diff --git a/src/components/main/pipeline.rs b/src/components/main/pipeline.rs index 3017e9653c5..68b64d66c48 100644 --- a/src/components/main/pipeline.rs +++ b/src/components/main/pipeline.rs @@ -7,7 +7,6 @@ use layout::layout_task::LayoutTask; use extra::url::Url; use geom::size::Size2D; -use gfx::opts::Opts; use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked}; use gfx::render_task::{RenderChan, RenderTask}; use layout::util::OpaqueNode; @@ -18,6 +17,7 @@ use script::script_task; use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineId, SubpageId}; use servo_net::image_cache_task::ImageCacheTask; use servo_net::resource_task::ResourceTask; +use servo_util::opts::Opts; use servo_util::time::ProfilerChan; use std::cell::RefCell; //FIXME: switch to std::rc when we upgrade Rust diff --git a/src/components/main/servo.rs b/src/components/main/servo.rs index b21c292255b..53071519273 100755 --- a/src/components/main/servo.rs +++ b/src/components/main/servo.rs @@ -47,18 +47,16 @@ use constellation::Constellation; use servo_msg::constellation_msg::InitLoadUrlMsg; #[cfg(not(test))] -use gfx::opts; - -#[cfg(not(test))] use servo_net::image_cache_task::{ImageCacheTask, SyncImageCacheTask}; #[cfg(not(test))] use servo_net::resource_task::ResourceTask; #[cfg(not(test))] use servo_util::time::Profiler; -pub use gfx::opts::Opts; -pub use gfx::text; -pub use servo_util::url::parse_url; +#[cfg(not(test))] +use servo_util::opts; +#[cfg(not(test))] +use servo_util::url::parse_url; #[cfg(not(test))] use std::os; @@ -138,7 +136,7 @@ pub extern "C" fn android_start(argc: int, argv: **u8) -> int { } #[cfg(not(test))] -fn run(opts: Opts) { +fn run(opts: opts::Opts) { let mut pool = green::SchedPool::new(green::PoolConfig::new()); let (compositor_port, compositor_chan) = CompositorChan::new(); diff --git a/src/components/msg/compositor_msg.rs b/src/components/msg/compositor_msg.rs index c1c28d9b467..4726f20e9a0 100644 --- a/src/components/msg/compositor_msg.rs +++ b/src/components/msg/compositor_msg.rs @@ -11,6 +11,8 @@ use layers::platform::surface::{NativeSurface, NativeSurfaceMethods}; use constellation_msg::PipelineId; +use extra::serialize::{Encoder, Encodable}; + pub struct LayerBuffer { /// The native surface which can be shared between threads or processes. On Mac this is an /// `IOSurface`; on Linux this is an X Pixmap; on Android this is an `EGLImageKHR`. @@ -94,6 +96,11 @@ pub trait ScriptListener : Clone { fn close(&self); } +impl<S: Encoder> Encodable<S> for @ScriptListener { + fn encode(&self, _s: &mut S) { + } +} + /// The interface used by the quadtree and buffer map to get info about layer buffers. pub trait Tile { /// Returns the amount of memory used by the tile diff --git a/src/components/msg/constellation_msg.rs b/src/components/msg/constellation_msg.rs index 9d3c1540066..a2197c26baa 100644 --- a/src/components/msg/constellation_msg.rs +++ b/src/components/msg/constellation_msg.rs @@ -60,8 +60,8 @@ pub enum NavigationDirection { Back, } -#[deriving(Clone, Eq, IterBytes)] +#[deriving(Clone, Eq, IterBytes, Encodable)] pub struct PipelineId(uint); -#[deriving(Clone, Eq, IterBytes)] +#[deriving(Clone, Eq, IterBytes, Encodable)] pub struct SubpageId(uint); diff --git a/src/components/msg/msg.rs b/src/components/msg/msg.rs index e27148b09d7..1315979ac18 100644 --- a/src/components/msg/msg.rs +++ b/src/components/msg/msg.rs @@ -5,6 +5,8 @@ #[crate_id = "github.com/mozilla/servo#msg:0.1"]; #[crate_type = "lib"]; +#[feature(managed_boxes)]; + extern mod azure; extern mod extra; extern mod geom; diff --git a/src/components/net/image_cache_task.rs b/src/components/net/image_cache_task.rs index fba676cbced..1212fa972c2 100644 --- a/src/components/net/image_cache_task.rs +++ b/src/components/net/image_cache_task.rs @@ -14,6 +14,7 @@ use std::util::replace; use std::result; use extra::arc::{Arc,MutexArc}; use extra::url::Url; +use extra::serialize::{Encoder, Encodable}; pub enum Msg { /// Tell the cache that we may need a particular image soon. Must be posted @@ -80,6 +81,11 @@ pub struct ImageCacheTask { chan: SharedChan<Msg>, } +impl<S: Encoder> Encodable<S> for ImageCacheTask { + fn encode(&self, _: &mut S) { + } +} + type DecoderFactory = fn() -> proc(&[u8]) -> Option<Image>; pub fn ImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask { diff --git a/src/components/script/dom/attr.rs b/src/components/script/dom/attr.rs index 6ae8009bb5a..3cf978d69c4 100644 --- a/src/components/script/dom/attr.rs +++ b/src/components/script/dom/attr.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::AttrBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; use servo_util::namespace::{Namespace, Null}; @@ -10,6 +11,7 @@ use servo_util::str::DOMString; use std::util; +#[deriving(Encodable)] pub struct Attr { reflector_: Reflector, local_name: DOMString, @@ -43,22 +45,22 @@ impl Attr { } } - pub fn new(window: &Window, local_name: DOMString, value: DOMString) -> @mut Attr { + pub fn new(window: &Window, local_name: DOMString, value: DOMString) -> JS<Attr> { let name = local_name.clone(); Attr::new_helper(window, local_name, value, name, Null, None) } pub fn new_ns(window: &Window, local_name: DOMString, value: DOMString, name: DOMString, namespace: Namespace, - prefix: Option<DOMString>) -> @mut Attr { + prefix: Option<DOMString>) -> JS<Attr> { Attr::new_helper(window, local_name, value, name, namespace, prefix) } fn new_helper(window: &Window, local_name: DOMString, value: DOMString, name: DOMString, namespace: Namespace, - prefix: Option<DOMString>) -> @mut Attr { + prefix: Option<DOMString>) -> JS<Attr> { let attr = Attr::new_inherited(local_name, value, name, namespace, prefix); - reflect_dom_object(@mut attr, window, AttrBinding::Wrap) + reflect_dom_object(~attr, window, AttrBinding::Wrap) } pub fn set_value(&mut self, mut value: DOMString) -> DOMString { diff --git a/src/components/script/dom/attrlist.rs b/src/components/script/dom/attrlist.rs index 9b8634de26c..100f057fe8f 100644 --- a/src/components/script/dom/attrlist.rs +++ b/src/components/script/dom/attrlist.rs @@ -4,18 +4,20 @@ use dom::attr::Attr; use dom::bindings::codegen::AttrListBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -use dom::node::{AbstractNode}; +use dom::element::Element; use dom::window::Window; +#[deriving(Encodable)] pub struct AttrList { reflector_: Reflector, - window: @mut Window, - owner: AbstractNode, + window: JS<Window>, + owner: JS<Element>, } impl AttrList { - pub fn new_inherited(window: @mut Window, elem: AbstractNode) -> AttrList { + pub fn new_inherited(window: JS<Window>, elem: JS<Element>) -> AttrList { AttrList { reflector_: Reflector::new(), window: window, @@ -23,22 +25,20 @@ impl AttrList { } } - pub fn new(window: @mut Window, elem: AbstractNode) -> @mut AttrList { - reflect_dom_object(@mut AttrList::new_inherited(window, elem), - window, AttrListBinding::Wrap) + pub fn new(window: &JS<Window>, elem: &JS<Element>) -> JS<AttrList> { + reflect_dom_object(~AttrList::new_inherited(window.clone(), elem.clone()), + window.get(), AttrListBinding::Wrap) } pub fn Length(&self) -> u32 { - self.owner.with_imm_element(|elem| elem.attrs.len() as u32) + self.owner.get().attrs.len() as u32 } - pub fn Item(&self, index: u32) -> Option<@mut Attr> { - self.owner.with_imm_element(|elem| { - elem.attrs.get_opt(index as uint).map(|&x| x) - }) + pub fn Item(&self, index: u32) -> Option<JS<Attr>> { + self.owner.get().attrs.get_opt(index as uint).map(|x| x.clone()) } - pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<@mut Attr> { + pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Attr>> { let item = self.Item(index); *found = item.is_some(); item diff --git a/src/components/script/dom/bindings/callback.rs b/src/components/script/dom/bindings/callback.rs index 40b3bd7b5fa..10cb35c3af4 100644 --- a/src/components/script/dom/bindings/callback.rs +++ b/src/components/script/dom/bindings/callback.rs @@ -4,12 +4,15 @@ use dom::bindings::utils::Reflectable; use js::jsapi::{JSContext, JSObject, JS_WrapObject, JSVal, JS_ObjectIsCallable}; -use js::jsapi::JS_GetProperty; -use js::{JSVAL_IS_OBJECT, JSVAL_TO_OBJECT}; +use js::jsapi::{JS_GetProperty, JSTracer, JS_CallTracer}; +use js::{JSVAL_IS_OBJECT, JSVAL_TO_OBJECT, JSTRACE_OBJECT}; +use std::cast; use std::libc; use std::ptr; +use extra::serialize::{Encodable, Encoder}; + pub enum ExceptionHandling { // Report any exception and don't throw it to the caller code. eReportExceptions, @@ -26,6 +29,20 @@ pub struct CallbackInterface { callback: *JSObject } +impl<S: Encoder> Encodable<S> for CallbackInterface { + fn encode(&self, s: &mut S) { + unsafe { + let tracer: *mut JSTracer = cast::transmute(s); + "callback".to_c_str().with_ref(|name| { + (*tracer).debugPrinter = ptr::null(); + (*tracer).debugPrintIndex = -1; + (*tracer).debugPrintArg = name as *libc::c_void; + JS_CallTracer(tracer as *JSTracer, self.callback, JSTRACE_OBJECT as u32); + }); + } + } +} + pub trait CallbackContainer { fn callback(&self) -> *JSObject; } @@ -66,7 +83,7 @@ pub fn GetJSObjectFromCallback<T: CallbackContainer>(callback: &T) -> *JSObject pub fn WrapCallThisObject<T: 'static + CallbackContainer + Reflectable>(cx: *JSContext, _scope: *JSObject, - p: @mut T) -> *JSObject { + p: ~T) -> *JSObject { let obj = GetJSObjectFromCallback(p); assert!(obj.is_not_null()); diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf index b45eca71ba8..8485377ed8b 100644 --- a/src/components/script/dom/bindings/codegen/Bindings.conf +++ b/src/components/script/dom/bindings/codegen/Bindings.conf @@ -96,7 +96,6 @@ DOMInterfaces = { 'Blob': [ { - 'headerFile': 'nsIDOMFile.h', }, #{ # 'workers': True, @@ -121,19 +120,14 @@ DOMInterfaces = { }], 'CharacterData': { - 'nativeType': 'AbstractNode', - 'concreteType': 'CharacterData', - 'pointerType': '' }, 'ClientRect': [ { - 'nativeType': 'ClientRect', }], 'ClientRectList': [ { - 'nativeType': 'ClientRectList', }], 'Console': { @@ -150,8 +144,6 @@ DOMInterfaces = { }, 'Document': { - 'nativeType': 'AbstractDocument', - 'pointerType': '', 'customTrace': 'trace', 'needsAbstract': [ 'createComment', @@ -165,15 +157,12 @@ DOMInterfaces = { }, 'DOMException': { - 'nativeType': 'DOMException', }, 'DOMImplementation': { - 'nativeType': 'DOMImplementation', }, 'DOMParser': { - 'nativeType': 'DOMParser', }, 'DOMSettableTokenList': [ @@ -195,15 +184,10 @@ DOMInterfaces = { }], 'Element': { - 'nativeType': 'AbstractNode', - 'pointerType': '', 'needsAbstract': ['getClientRects', 'getBoundingClientRect', 'setAttribute', 'setAttributeNS', 'removeAttribute', 'removeAttributeNS', 'id', 'attributes', 'innerHTML', 'outerHTML'] }, 'Event': { - 'nativeType': 'AbstractEvent', - 'concreteType': 'Event', - 'pointerType': '', }, 'EventListener': { @@ -211,9 +195,6 @@ DOMInterfaces = { }, 'EventTarget': { - 'nativeType': 'AbstractEventTarget', - 'concreteType': 'EventTarget', - 'pointerType': '', 'needsAbstract': ['dispatchEvent'] }, @@ -241,22 +222,8 @@ DOMInterfaces = { 'HTMLCollection': [ { - 'nativeType': 'HTMLCollection', - 'pointerType': '@mut ' }], -'HTMLDocument': { - 'nativeType': 'AbstractDocument', - 'pointerType': '', - 'customTrace': 'trace' -}, - -'HTMLFormElement': { - 'nativeType': 'AbstractNode', - 'pointerType': '', - 'register': False -}, - 'HTMLOptionsCollection': [ { 'nativeType': 'nsHTMLOptionCollection', @@ -306,27 +273,21 @@ DOMInterfaces = { }], 'MouseEvent': { - 'nativeType': 'AbstractEvent', - 'concreteType': 'MouseEvent', - 'pointerType': '', }, 'Navigator': { }, 'Node': { - 'nativeType': 'AbstractNode', - 'concreteType': 'Node', - 'pointerType': '', 'needsAbstract': [ 'appendChild', - 'insertBefore', - 'replaceChild', + 'childNodes', + 'insertBefore', 'nodeName', 'nodeValue', 'removeChild', + 'replaceChild', 'textContent', - 'childNodes', 'contains', 'isEqualNode', ] @@ -334,8 +295,6 @@ DOMInterfaces = { 'NodeList': [ { - 'nativeType': 'NodeList', - 'pointerType': '@mut ', 'resultNotAddRefed': ['item'] }], @@ -410,9 +369,6 @@ DOMInterfaces = { }], 'UIEvent': { - 'nativeType': 'AbstractEvent', - 'concreteType': 'UIEvent', - 'pointerType': '', }, 'ValidityState': { @@ -592,7 +548,7 @@ def addExternalIface(iface, nativeType=None, headerFile=None, pointerType=None): # FIXME: This should be renamed: https://github.com/mozilla/servo/issues/1625 def addHTMLElement(element, concrete=None, needsAbstract=[]): DOMInterfaces[element] = { - 'nativeType': 'AbstractNode', + 'nativeType': 'JS<%s>' % element, 'pointerType': '', 'concreteType': concrete if concrete else element, 'customTrace': 'trace', diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index bcd9a4a2de4..16ea49c38c0 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -92,9 +92,13 @@ class CastableObjectUnwrapper(): codeOnFailure is the code to run if unwrapping fails. """ - def __init__(self, descriptor, source, target, codeOnFailure, isOptional=False): + def __init__(self, descriptor, source, target, codeOnFailure, isOptional=False, + preUnwrapped=None, postUnwrapped=None): assert descriptor.castable + unwrappedVal = "val" + if preUnwrapped or postUnwrapped: + unwrappedVal = preUnwrapped + unwrappedVal + postUnwrapped self.substitution = { "type" : descriptor.nativeType, "depth": descriptor.interface.inheritanceDepth(), "prototype": "PrototypeList::id::" + descriptor.name, @@ -102,7 +106,8 @@ class CastableObjectUnwrapper(): "source" : source, "target" : target, "codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure), 4).define(), - "unwrapped_val" : "Some(val)" if isOptional else "val" } + "unwrapped_val" : ("Some(%s)" % unwrappedVal) if isOptional else unwrappedVal, + "unwrapFn": "unwrap_jsmanaged" if 'JS' in descriptor.nativeType else "unwrap_object"} if descriptor.hasXPConnectImpls: # We don't use xpc_qsUnwrapThis because it will always throw on # unwrap failure, whereas we want to control whether we throw or @@ -123,7 +128,7 @@ class CastableObjectUnwrapper(): def __str__(self): return string.Template( -"""match unwrap_object(${source}, ${prototype}, ${depth}) { +"""match ${unwrapFn}(${source}, ${prototype}, ${depth}) { Ok(val) => ${target} = ${unwrapped_val}, Err(()) => { ${codeOnFailure} @@ -406,8 +411,7 @@ class FakeCastableDescriptor(): def __init__(self, descriptor): self.castable = True self.workers = descriptor.workers - self.nativeType = descriptor.nativeType - self.pointerType = descriptor.pointerType + self.nativeType = "*Box<%s>" % descriptor.concreteType self.name = descriptor.name self.hasXPConnectImpls = descriptor.hasXPConnectImpls class FakeInterface: @@ -447,7 +451,9 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None, isClamp=False, exceptionCode=None, isCallbackReturnValue=False, - sourceDescription="value"): + sourceDescription="value", + preSuccess=None, + postSuccess=None): """ Get a template for converting a JS value to a native object based on the given type and descriptor. If failureCode is given, then we're actually @@ -706,8 +712,8 @@ for (uint32_t i = 0; i < length; ++i) { (isinstance(defaultValue, IDLNullValue) and nullable)) unionArgumentObj = "${holderName}" - if isOptional or nullable: - unionArgumentObj += ".ref()" + #if isOptional or nullable: + # unionArgumentObj += ".get_mut_ref()" memberTypes = type.flatMemberTypes names = [] @@ -720,7 +726,7 @@ for (uint32_t i = 0; i < length; ++i) { name = memberType.inner.identifier.name else: name = memberType.name - interfaceObject.append(CGGeneric("(failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext" % (unionArgumentObj, name))) + interfaceObject.append(CGGeneric("{res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()}" % (unionArgumentObj, name))) names.append(name) interfaceObject = CGWrapper(CGList(interfaceObject, " ||\n"), pre="done = ", post=";\n", reindent=True) else: @@ -731,7 +737,7 @@ for (uint32_t i = 0; i < length; ++i) { assert len(arrayObjectMemberTypes) == 1 memberType = arrayObjectMemberTypes[0] name = memberType.name - arrayObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name)) + arrayObject = CGGeneric("done = {res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()};" % (unionArgumentObj, name)) # XXX Now we're supposed to check for an array or a platform object # that supports indexed properties... skip that last for now. It's a # bit of a pain. @@ -761,7 +767,7 @@ for (uint32_t i = 0; i < length; ++i) { assert len(callbackMemberTypes) == 1 memberType = callbackMemberTypes[0] name = memberType.name - callbackObject = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name)) + callbackObject = CGGeneric("done = {res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()};" % (unionArgumentObj, name)) names.append(name) else: callbackObject = None @@ -816,7 +822,7 @@ for (uint32_t i = 0; i < length; ++i) { if any([arrayObject, dateObject, nonPlatformObject, object]): templateBody.prepend(CGGeneric("JSObject& argObj = ${val}.toObject();")) templateBody = CGWrapper(CGIndenter(templateBody), - pre="if (${val}.isObject()) {\n", + pre="if JSVAL_IS_OBJECT(${val}) {\n", post="\n}") else: templateBody = CGGeneric() @@ -831,7 +837,7 @@ for (uint32_t i = 0; i < length; ++i) { name = memberType.inner.identifier.name else: name = memberType.name - other = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${valPtr}, tryNext)) || !tryNext;" % (unionArgumentObj, name)) + other = CGGeneric("done = {res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()};" % (unionArgumentObj, name)) names.append(name) if hasObjectTypes: other = CGWrapper(CGIndenter(other), "{\n", post="\n}") @@ -844,28 +850,25 @@ for (uint32_t i = 0; i < length; ++i) { else: other = None - templateBody = CGWrapper(templateBody, pre="bool done = false, failed = false, tryNext;\n") - throw = CGGeneric("if (failed) {\n" - " return false;\n" + templateBody = CGWrapper(templateBody, pre="let mut done = false;\n" + "let mut res = Ok(true);\n") + throw = CGGeneric("if res.is_err() {\n" + " return 0;\n" "}\n" - "if (!done) {\n" - " return ThrowErrorMessage(cx, MSG_NOT_IN_UNION, \"%s\");\n" + "if !done {\n" + " return throw_not_in_union(cx, \"%s\");\n" "}" % ", ".join(names)) templateBody = CGWrapper(CGIndenter(CGList([templateBody, throw], "\n")), pre="{\n", post="\n}") typeName = type.name argumentTypeName = typeName + "Argument" if nullable: - typeName = "Nullable<" + typeName + " >" - if isOptional: - nonConstDecl = "const_cast<Optional<" + typeName + " >& >(${declName})" - else: - nonConstDecl = "const_cast<" + typeName + "& >(${declName})" - typeName = "const " + typeName + typeName = "Option<" + typeName + " >" + nonConstDecl = "${declName}" def handleNull(templateBody, setToNullVar, extraConditionForNull=""): - null = CGGeneric("if (%s${val}.isNullOrUndefined()) {\n" - " %s.SetNull();\n" + null = CGGeneric("if %s(RUST_JSVAL_IS_NULL(${val}) != 0 || RUST_JSVAL_IS_VOID(${val}) != 0) {\n" + " %s = None;\n" "}" % (extraConditionForNull, setToNullVar)) templateBody = CGWrapper(CGIndenter(templateBody), pre="{\n", post="\n}") return CGList([null, templateBody], " else ") @@ -878,21 +881,24 @@ for (uint32_t i = 0; i < length; ++i) { if isOptional: mutableDecl = nonConstDecl + ".Value()" declType = CGWrapper(declType, pre="const Optional<", post=" >") - holderType = CGWrapper(holderType, pre="Maybe<", post=" >") + holderType = CGWrapper(holderType, pre="Option<", post=" >") constructDecl = CGGeneric(nonConstDecl + ".Construct();") if nullable: - constructHolder = CGGeneric("${holderName}.construct(%s.SetValue());" % mutableDecl) + constructHolder = CGGeneric("${holderName} = Some(%s.SetValue());" % mutableDecl) else: - constructHolder = CGGeneric("${holderName}.construct(${declName}.Value());") + constructHolder = CGGeneric("${holderName} = Some(${declName}.Value());") else: mutableDecl = nonConstDecl constructDecl = None + holderInit = "${declName}" if nullable: - holderType = CGWrapper(holderType, pre="Maybe<", post=" >") - constructHolder = CGGeneric("${holderName}.construct(%s.SetValue());" % mutableDecl) + holderInit += ".get_mut_ref()" else: - constructHolder = CGWrapper(holderType, post=" ${holderName}(${declName});") - holderType = None + holderInit = "&mut " + holderInit + constructHolder = CGWrapper(holderType, pre="let mut ${holderName} = ", post="::new(" + holderInit + ");") + if nullable: + constructHolder = CGWrapper(constructHolder, pre="${declName} = Some(uninit());\n") + holderType = None templateBody = CGList([constructHolder, templateBody], "\n") if nullable: @@ -903,9 +909,10 @@ for (uint32_t i = 0; i < length; ++i) { valueMissing = "" templateBody = handleNull(templateBody, mutableDecl, extraConditionForNull=valueMissing) - templateBody = CGList([constructDecl, templateBody], "\n") + templateBody = CGWrapper(CGIndenter(CGList([constructDecl, templateBody], "\n")), + pre="{\n", post="\n}") - return templateBody.define(), declType, holderType, False, None + return templateBody.define(), declType, holderType, False, "uninit()" if not nullable else None if type.isGeckoInterface(): assert not isEnforceRange and not isClamp @@ -934,8 +941,7 @@ for (uint32_t i = 0; i < length; ++i) { forceOwningType = (descriptor.interface.isCallback() and not descriptor.workers) or isMember - typeName = descriptor.nativeType - typePtr = descriptor.pointerType + typeName + typePtr = descriptor.nativeType # Compute a few things: # - declType is the type we want to return as the first element of our @@ -969,7 +975,8 @@ for (uint32_t i = 0; i < length; ++i) { "JSVAL_TO_OBJECT(${val})", "${declName}", failureCode, - isOptional or argIsPointer or type.nullable())) + isOptional or argIsPointer or type.nullable(), + preUnwrapped=preSuccess, postUnwrapped=postSuccess)) else: templateBody += str(FailureFatalCastableObjectUnwrapper( descriptor, @@ -1255,32 +1262,41 @@ for (uint32_t i = 0; i < length; ++i) { elif isClamp: conversionBehavior = "eClamp" + if failureCode is None: + failureCode = 'return 0' + if type.nullable(): dataLoc = "${declName}.SetValue()" nullCondition = "(RUST_JSVAL_IS_NULL(${val}) != 0 || RUST_JSVAL_IS_VOID(${val}) != 0)" if defaultValue is not None and isinstance(defaultValue, IDLNullValue): nullCondition = "!(${haveValue}) || " + nullCondition + successVal = "val_" + if preSuccess or postSuccess: + successVal = preSuccess + successVal + postSuccess #XXXjdm support conversionBehavior here template = ( "if (%s) {\n" " ${declName} = None;\n" "} else {\n" " match JSValConvertible::from_jsval(${val}) {\n" - " Some(val_) => ${declName} = Some(val_),\n" - " None => return 0\n" + " Some(val_) => ${declName} = Some(%s),\n" + " None => %s\n" " }\n" - "}" % nullCondition) + "}" % (nullCondition, successVal, failureCode)) declType = CGGeneric("Option<" + typeName + ">") else: assert(defaultValue is None or not isinstance(defaultValue, IDLNullValue)) dataLoc = "${declName}" #XXXjdm conversionBehavior should be used + successVal = "v" + if preSuccess or postSuccess: + successVal = preSuccess + successVal + postSuccess template = ( "match JSValConvertible::from_jsval(${val}) {\n" - " None => return 0,\n" - " Some(v) => %s = v\n" - "}" % (dataLoc,)) + " None => %s,\n" + " Some(v) => %s = %s\n" + "}" % (failureCode, dataLoc, successVal)) declType = CGGeneric(typeName) if (defaultValue is not None and # We already handled IDLNullValue, so just deal with the other ones @@ -1730,9 +1746,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider, returnType.unroll().inner.identifier.name) result = CGGeneric(descriptor.nativeType) if returnType.nullable(): - result = CGWrapper(result, pre=("Option<" + descriptor.pointerType), post=">") - else: - result = CGWrapper(result, pre=descriptor.pointerType) + result = CGWrapper(result, pre="Option<", post=">") return result, False if returnType.isCallback(): # XXXbz we're going to assume that callback types are always @@ -2388,6 +2402,112 @@ class CGGeneric(CGThing): def define(self): return self.defineText +def getTypes(descriptor): + """ + Get all argument and return types for all members of the descriptor + """ + members = [m for m in descriptor.interface.members] + if descriptor.interface.ctor(): + members.append(descriptor.interface.ctor()) + signatures = [s for m in members if m.isMethod() for s in m.signatures()] + types = [] + for s in signatures: + assert len(s) == 2 + (returnType, arguments) = s + types.append(returnType) + types.extend([a.type for a in arguments]) + + types.extend(a.type for a in members if a.isAttr()) + return types + +def SortedTuples(l): + """ + Sort a list of tuples based on the first item in the tuple + """ + return sorted(l, key=operator.itemgetter(0)) + +def SortedDictValues(d): + """ + Returns a list of values from the dict sorted by key. + """ + # Create a list of tuples containing key and value, sorted on key. + d = SortedTuples(d.items()) + # We're only interested in the values. + return (i[1] for i in d) + +def UnionTypes(descriptors): + """ + Returns a tuple containing a set of header filenames to include, a set of + tuples containing a type declaration and a boolean if the type is a struct + for member types of the unions and a CGList containing CGUnionStructs for + every union. + """ + + # Now find all the things we'll need as arguments and return values because + # we need to wrap or unwrap them. + headers = set() + declarations = set() + unionStructs = dict() + for d in descriptors: + if d.interface.isExternal(): + continue + + for t in getTypes(d): + t = t.unroll() + if t.isUnion(): + name = str(t) + if not name in unionStructs: + unionStructs[name] = CGUnionStruct(t, d) + for f in t.flatMemberTypes: + f = f.unroll() + if f.isInterface(): + if f.isSpiderMonkeyInterface(): + headers.add("jsfriendapi.h") + headers.add("mozilla/dom/TypedArray.h") + else: + typeDesc = d.getDescriptor(f.inner.identifier.name) + if typeDesc is not None: + declarations.add((typeDesc.nativeType, False)) + elif f.isDictionary(): + declarations.add((f.inner.identifier.name, True)) + + return (headers, declarations, CGList(SortedDictValues(unionStructs), "\n")) + +def UnionConversions(descriptors): + """ + Returns a CGThing to declare all union argument conversion helper structs. + """ + # Now find all the things we'll need as arguments because we + # need to unwrap them. + unionConversions = dict() + for d in descriptors: + if d.interface.isExternal(): + continue + + def addUnionTypes(type): + if type.isUnion(): + type = type.unroll() + name = str(type) + if not name in unionConversions: + unionConversions[name] = CGUnionConversionStruct(type, d) + + members = [m for m in d.interface.members] + if d.interface.ctor(): + members.append(d.interface.ctor()) + signatures = [s for m in members if m.isMethod() for s in m.signatures()] + for s in signatures: + assert len(s) == 2 + (_, arguments) = s + for a in arguments: + addUnionTypes(a.type) + + for m in members: + if m.isAttr() and not m.readonly: + addUnionTypes(m.type) + + return CGWrapper(CGList(SortedDictValues(unionConversions), "\n"), + post="\n\n") + class Argument(): """ A class for outputting the type and name of an argument @@ -2497,33 +2617,40 @@ class CGAbstractMethod(CGThing): def definition_body(self): assert(False) # Override me! +def DOMObjectPointerType(descriptor): + return "~" + +def DOMObjectPointerArg(descriptor): + return DOMObjectPointerType(descriptor) + descriptor.concreteType + def CreateBindingJSObject(descriptor, parent=None): + create = " let raw: *mut %s = &mut *aObject;\n" % descriptor.concreteType; if descriptor.proxy: assert not descriptor.createGlobal handler = """ let page = page_from_context(aCx); let handler = (*page).js_info.get_ref().dom_static.proxy_handlers.get(&(PrototypeList::id::%s as uint)); """ % descriptor.name - create = handler + """ let obj = NewProxyObject(aCx, *handler, - ptr::to_unsafe_ptr(&RUST_PRIVATE_TO_JSVAL(squirrel_away(aObject) as *libc::c_void)), + create += handler + """ let obj = NewProxyObject(aCx, *handler, + ptr::to_unsafe_ptr(&RUST_PRIVATE_TO_JSVAL(squirrel_away_unique(aObject) as *libc::c_void)), proto, %s, ptr::null(), ptr::null()); if obj.is_null() { return ptr::null(); } -""" % parent +""" % (parent) else: if descriptor.createGlobal: - create = " let obj = CreateDOMGlobal(aCx, &Class.base);\n" + create += " let obj = CreateDOMGlobal(aCx, &Class.base);\n" else: - create = " let obj = JS_NewObject(aCx, &Class.base, proto, %s);\n" % parent + create += " let obj = JS_NewObject(aCx, &Class.base, proto, %s);\n" % parent create += """ if obj.is_null() { return ptr::null(); } JS_SetReservedSlot(obj, DOM_OBJECT_SLOT as u32, - RUST_PRIVATE_TO_JSVAL(squirrel_away(aObject) as *libc::c_void)); + RUST_PRIVATE_TO_JSVAL(squirrel_away_unique(aObject) as *libc::c_void)); """ return create @@ -2531,7 +2658,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod): def __init__(self, descriptor): assert descriptor.interface.hasInterfacePrototypeObject() args = [Argument('*JSContext', 'aCx'), Argument('*JSObject', 'aScope'), - Argument('@mut ' + descriptor.concreteType, 'aObject')] + Argument(DOMObjectPointerArg(descriptor), 'aObject', mutable=True)] CGAbstractMethod.__init__(self, descriptor, 'Wrap_', '*JSObject', args) def definition_body(self): @@ -2548,20 +2675,20 @@ class CGWrapWithCacheMethod(CGAbstractMethod): if proto.is_null() { return ptr::null(); } -%s - //NS_ADDREF(aObject); +%s - aObject.mut_reflector().set_jsobject(obj); + (*raw).mut_reflector().set_jsobject(obj); - return obj;""" % (CreateBindingJSObject(self.descriptor, "aScope")) + return obj;""" % CreateBindingJSObject(self.descriptor, "aScope") else: return """ assert!(aScope.is_null()); + %s let proto = GetProtoObject(aCx, obj, obj); JS_SetPrototype(aCx, obj, proto); - aObject.mut_reflector().set_jsobject(obj); + (*raw).mut_reflector().set_jsobject(obj); return obj;""" % CreateBindingJSObject(self.descriptor) class CGWrapMethod(CGAbstractMethod): @@ -2569,7 +2696,7 @@ class CGWrapMethod(CGAbstractMethod): # XXX can we wrap if we don't have an interface prototype object? assert descriptor.interface.hasInterfacePrototypeObject() args = [Argument('*JSContext', 'aCx'), Argument('*JSObject', 'aScope'), - Argument('@mut ' + descriptor.concreteType, 'aObject')] + Argument(DOMObjectPointerArg(descriptor), 'aObject', mutable=True)] CGAbstractMethod.__init__(self, descriptor, 'Wrap', '*JSObject', args, inline=True, pub=True) def definition_body(self): @@ -2961,7 +3088,11 @@ class CGCallGenerator(CGThing): if a.type.isObject() and not a.type.nullable() and not a.optional: name = "(JSObject&)" + name #XXXjdm Perhaps we should pass all nontrivial types by borrowed pointer - if a.type.isDictionary(): + if a.type.isGeckoInterface(): + argDescriptor = descriptorProvider.getDescriptor(a.type.name) + if not (a.type.nullable() or a.optional): + name = "&mut " + name + elif a.type.isDictionary(): name = "&" + name args.append(CGGeneric(name)) @@ -3288,8 +3419,8 @@ class CGSpecializedMethod(CGAbstractExternMethod): argsPre = [] if name in self.descriptor.needsAbstract: abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType) - extraPre = ' let abstract_this = %s::from_box(this);\n' % abstractName - argsPre = ['abstract_this'] + extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName + argsPre = ['&mut abstract_this'] return CGWrapper(CGMethodCall(argsPre, nativeName, self.method.isStatic(), self.descriptor, self.method), pre=extraPre + @@ -3317,8 +3448,10 @@ class CGGenericGetter(CGAbstractBindingMethod): def generate_code(self): return CGIndenter(CGGeneric( - "let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, &*vp));\n" - "return CallJitPropertyOp(info, cx, obj, this as *libc::c_void, &*vp);")) + "return with_gc_disabled(cx, || {\n" + " let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, &*vp));\n" + " CallJitPropertyOp(info, cx, obj, this as *libc::c_void, &*vp)\n" + "});\n")) class CGSpecializedGetter(CGAbstractExternMethod): """ @@ -3348,8 +3481,8 @@ class CGSpecializedGetter(CGAbstractExternMethod): getter=True)) if name in self.descriptor.needsAbstract: abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType) - extraPre = ' let abstract_this = %s::from_box(this);\n' % abstractName - argsPre = ['abstract_this'] + extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName + argsPre = ['&mut abstract_this'] if resultOutParam or self.attr.type.nullable() or not infallible: nativeName = "Get" + nativeName return CGWrapper(CGIndenter(CGGetterCall(argsPre, self.attr.type, nativeName, @@ -3381,7 +3514,10 @@ class CGGenericSetter(CGAbstractBindingMethod): "let undef = JSVAL_VOID;\n" "let argv: *JSVal = if argc != 0 { JS_ARGV(cx, vp as *JSVal) } else { &undef as *JSVal };\n" "let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp as *JSVal));\n" - "if CallJitPropertyOp(info, cx, obj, this as *libc::c_void, argv) == 0 {" + "let ok = with_gc_disabled(cx, || {\n" + " CallJitPropertyOp(info, cx, obj, this as *libc::c_void, argv)\n" + "});\n" + "if ok == 0 {\n" " return 0;\n" "}\n" "*vp = JSVAL_VOID;\n" @@ -3408,8 +3544,8 @@ class CGSpecializedSetter(CGAbstractExternMethod): extraPre = '' if name in self.descriptor.needsAbstract: abstractName = re.sub(r'<\w+>', '', self.descriptor.nativeType) - extraPre = ' let abstract_this = %s::from_box(this);\n' % abstractName - argsPre = ['abstract_this'] + extraPre = ' let mut abstract_this = %s::from_box(this);\n' % abstractName + argsPre = ['&mut abstract_this'] return CGWrapper(CGIndenter(CGSetterCall(argsPre, self.attr.type, nativeName, self.descriptor, self.attr)), pre=extraPre + @@ -3531,6 +3667,282 @@ class CGEnum(CGThing): """ % (",\n ".join(map(getEnumValueName, self.enum.values())), ",\n ".join(['EnumEntry {value: &"' + val + '", length: ' + str(len(val)) + '}' for val in self.enum.values()])) +def getUnionAccessorSignatureType(type, descriptorProvider): + """ + Returns the types that are used in the getter and setter signatures for + union types + """ + if type.isArray(): + raise TypeError("Can't handle array arguments yet") + + if type.isSequence(): + nullable = type.nullable(); + if nullable: + type = type.inner.inner + else: + type = type.inner + (elementTemplate, elementDeclType, + elementHolderType, dealWithOptional) = getJSToNativeConversionTemplate( + type, descriptorProvider, isSequenceMember=True) + typeName = CGWrapper(elementDeclType, pre="Sequence< ", post=" >&") + if nullable: + typeName = CGWrapper(typeName, pre="Nullable< ", post=" >&") + + return typeName + + if type.isUnion(): + typeName = CGGeneric(type.name) + if type.nullable(): + typeName = CGWrapper(typeName, pre="Nullable< ", post=" >&") + + return typeName + + if type.isGeckoInterface(): + descriptor = descriptorProvider.getDescriptor( + type.unroll().inner.identifier.name) + typeName = CGGeneric(descriptor.nativeType) + # Allow null pointers for nullable types and old-binding classes + if type.nullable() or type.unroll().inner.isExternal(): + typeName = CGWrapper(typeName, pre="Option<", post=">") + else: + typeName = CGWrapper(typeName, pre="&'a ") + return typeName + + if type.isSpiderMonkeyInterface(): + typeName = CGGeneric(type.name) + if type.nullable(): + typeName = CGWrapper(typeName, pre="Option<", post=">") + else: + typeName = CGWrapper(typeName, pre="&") + return typeName + + if type.isString(): + return CGGeneric("const nsAString&") + + if type.isEnum(): + if type.nullable(): + raise TypeError("We don't support nullable enumerated arguments or " + "union members yet") + return CGGeneric(type.inner.identifier.name) + + if type.isCallback(): + return CGGeneric("JSObject*") + + if type.isAny(): + return CGGeneric("JS::Value") + + if type.isObject(): + typeName = CGGeneric("JSObject") + if type.nullable(): + typeName = CGWrapper(typeName, post="*") + else: + typeName = CGWrapper(typeName, post="&") + return typeName + + if not type.isPrimitive(): + raise TypeError("Need native type for argument type '%s'" % str(type)) + + typeName = CGGeneric(builtinNames[type.tag()]) + if type.nullable(): + typeName = CGWrapper(typeName, pre="Nullable< ", post=" >&") + return typeName + +def getUnionTypeTemplateVars(type, descriptorProvider): + # For dictionaries and sequences we need to pass None as the failureCode + # for getJSToNativeConversionTemplate. + # Also, for dictionaries we would need to handle conversion of + # null/undefined to the dictionary correctly. + if type.isDictionary() or type.isSequence(): + raise TypeError("Can't handle dictionaries or sequences in unions") + + if type.isGeckoInterface(): + name = type.inner.identifier.name + typeName = descriptorProvider.getDescriptor(name).nativeType + elif type.isEnum(): + name = type.inner.identifier.name + typeName = name + elif type.isArray() or type.isSequence(): + name = str(type) + #XXXjdm dunno about typeName here + typeName = "/*" + type.name + "*/" + elif type.isPrimitive(): + name = type.name + typeName = builtinNames[type.tag()] + else: + name = type.name + typeName = "/*" + type.name + "*/" + + tryNextCode = """{ + return Ok(true); +}""" + (template, declType, holderType, + dealWithOptional, initialValue) = getJSToNativeConversionTemplate( + type, descriptorProvider, failureCode=tryNextCode, + isDefinitelyObject=True, isOptional=type.nullable(), preSuccess="e" + name + "(", postSuccess=")") + + structType = declType.define() + externalType = getUnionAccessorSignatureType(type, descriptorProvider).define() + + if type.isObject(): + setter = CGGeneric("pub fn SetToObject(obj: *JSObject) {\n" + " mUnion = Some(eObject(obj));\n" + "}") + else: + jsConversion = string.Template(template).substitute( + { + "val": "value", + "valPtr": "pvalue", + "declName": "*self.mUnion", + "holderName": "m" + name + "Holder" + } + ) + jsConversion = CGWrapper(CGGeneric(jsConversion), + post="\n" + "return Ok(false);") + setter = CGWrapper(CGIndenter(jsConversion), + pre="pub fn TrySetTo" + name + "(&mut self, cx: *JSContext, value: JSVal, pvalue: *JSVal) -> Result<bool,()> {\n", + post="\n" + "}") + + return { + "name": name, + "typeName": typeName, + "structType": structType, + "externalType": externalType, + "optRef": 'ref ' if externalType[0] == '&' else '', + "setter": CGIndenter(setter).define(), + "holderType": holderType.define() if holderType else None + } + +def mapTemplate(template, templateVarArray): + return map(lambda v: string.Template(template).substitute(v), + templateVarArray) + +class CGUnionStruct(CGThing): + def __init__(self, type, descriptorProvider): + CGThing.__init__(self) + self.type = type.unroll() + self.descriptorProvider = descriptorProvider + + def declare(self): + templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider), + self.type.flatMemberTypes) + + callDestructors = [] + enumValues = [] + methods = [] + if self.type.hasNullableType: + callDestructors.append(" case eNull:\n" + " break;") + enumValues.append("eNull") + methods.append(""" pub fn IsNull(&self) -> bool { + match *self { + eNull => true, + _ => false + } + }""") + + destructorTemplate = """ fn Destroy${name}(&mut self) { + assert!(Is${name}(), "Wrong type!"); + *self.mUnion = None; + }""" + destructors = mapTemplate(destructorTemplate, templateVars) + callDestructors.extend(mapTemplate(" case e${name}:\n" + " Destroy${name}();\n" + " break;", templateVars)) + enumValues.extend(mapTemplate("e${name}(${typeName})", templateVars)) + methodTemplate = """ pub fn Is${name}(&self) -> bool { + match *self { + e${name}(_) => true, + _ => false + } + } + pub fn GetAs${name}<'a>(&'a self) -> ${externalType} { + assert!(self.Is${name}()); + match *self { + e${name}(${optRef}inner) => inner, + _ => unreachable!() + } + }""" + methods.extend(mapTemplate(methodTemplate, templateVars)) + values = mapTemplate("UnionMember<${structType} > m${name};", templateVars) + return string.Template(""" +pub enum ${structName} { + ${enumValues} +} + +impl ${structName} { +${methods} +} +""").substitute( + { + "structName": self.type.__str__(), + "callDestructors": "\n".join(callDestructors), + "destructors": "\n".join(destructors), + "methods": "\n\n".join(methods), + "enumValues": ",\n ".join(enumValues), + "values": "\n ".join(values), + }) + + def define(self): + return """ +""" + +class CGUnionConversionStruct(CGThing): + def __init__(self, type, descriptorProvider): + CGThing.__init__(self) + self.type = type.unroll() + self.descriptorProvider = descriptorProvider + + def declare(self): + setters = [] + + if self.type.hasNullableType: + setters.append(""" pub fn SetNull(&mut self) -> bool + { + mUnion = Some(eNull); + return true; + }""") + + templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider), + self.type.flatMemberTypes) + structName = self.type.__str__() + + setters.extend(mapTemplate("${setter}", templateVars)) + private = "\n".join(mapTemplate(""" fn SetAs${name}() -> &${structType} + { + mUnion.mType = mUnion.e${name}; + return mUnion.mValue.m${name}.SetValue(); + }""", templateVars)) + private += "\n\n" + holders = filter(lambda v: v["holderType"] is not None, templateVars) + if len(holders) > 0: + private += "\n".join(mapTemplate(" ${holderType} m${name}Holder;", holders)) + private += "\n\n" + private += " " + structName + "& mUnion;" + return string.Template(""" +pub struct ${structName}Argument<'a> { + mUnion: &'a mut ${innerType} +} + +impl<'a> ${structName}Argument<'a> { + pub fn new(union: &'a mut ${innerType}) -> ${structName}Argument<'a> { + ${structName}Argument { + mUnion: union + } + } + +${setters} +} +""").substitute({"structName": structName, + "innerType": ("Option<%s>" % structName) if self.type.nullable() else structName, + "setters": "\n\n".join(setters), + }) + + def define(self): + return """ +""" + class ClassItem: """ Use with CGClass """ def __init__(self, name, visibility): @@ -4482,9 +4894,9 @@ def finalizeHook(descriptor, hookName, context): else: assert descriptor.nativeIsISupports release = """let val = JS_GetReservedSlot(obj, dom_object_slot(obj)); -let _: @mut %s = cast::transmute(RUST_JSVAL_TO_PRIVATE(val)); +let _: %s %s = cast::transmute(RUST_JSVAL_TO_PRIVATE(val)); debug!("%s finalize: {:p}", this); -""" % (descriptor.concreteType, descriptor.concreteType) +""" % (DOMObjectPointerType(descriptor), descriptor.concreteType, descriptor.concreteType) #return clearWrapper + release return release @@ -4530,10 +4942,10 @@ class CGClassConstructHook(CGAbstractExternMethod): // or through unwrapping a slot or something). We'll punt and get the Window // from the context for now. let page = page_from_context(cx); - let global = (*page).frame.get_ref().window; + let global = (*page).frame.get_ref().window.clone(); let obj = global.reflector().get_jsobject(); """ - preArgs = ["global"] + preArgs = ["&global"] name = self._ctor.identifier.name nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name)) @@ -5151,17 +5563,16 @@ class CGBindingRoot(CGThing): 'js::jsfriendapi::bindgen::*', 'js::glue::*', 'dom::types::*', + 'dom::bindings::js::JS', 'dom::bindings::utils::*', 'dom::bindings::callback::*', 'dom::bindings::conversions::*', 'dom::bindings::codegen::*', #XXXjdm + 'dom::bindings::codegen::UnionTypes::*', #XXXjdm + 'dom::bindings::codegen::UnionConversions::*', #XXXjdm 'script_task::{JSPageInfo, page_from_context}', 'dom::bindings::proxyhandler', 'dom::bindings::proxyhandler::*', - 'dom::document::AbstractDocument', - 'dom::node::AbstractNode', - 'dom::eventtarget::AbstractEventTarget', - 'dom::event::AbstractEvent', 'servo_util::str::DOMString', 'servo_util::vec::zip_copies', 'std::cast', @@ -5170,6 +5581,7 @@ class CGBindingRoot(CGThing): 'std::vec', 'std::str', 'std::num', + 'std::unstable::intrinsics::uninit', 'std::unstable::raw::Box', ], [], @@ -5427,9 +5839,9 @@ class CGNativeMember(ClassMethod): else: typeDecl = "NonNull<%s>" else: - typeDecl = "%s%s" + typeDecl = "%s" descriptor = self.descriptorProvider.getDescriptor(iface.identifier.name) - return (typeDecl % (descriptor.pointerType, descriptor.nativeType), + return (typeDecl % descriptor.nativeType, False, False) if type.isSpiderMonkeyInterface(): @@ -5560,7 +5972,7 @@ class CGCallback(CGClass): bases=[ClassBase(baseName)], constructors=self.getConstructors(), methods=realMethods+getters+setters, - decorators="#[deriving(Eq,Clone)]") + decorators="#[deriving(Eq,Clone,Encodable)]") def getConstructors(self): return [ClassConstructor( @@ -5591,20 +6003,19 @@ class CGCallback(CGClass): args.append(Argument("ExceptionHandling", "aExceptionHandling", "eReportExceptions")) - # Ensure the first argument is mutable - args[0] = Argument(args[0].argType, args[0].name, args[0].default, mutable=True) + args[0] = Argument('&' + args[0].argType, args[0].name, args[0].default) method.args[2] = args[0] # And now insert our template argument. argsWithoutThis = list(args) - args.insert(0, Argument("@mut T", "thisObj")) + args.insert(0, Argument("~T", "thisObj")) # And the self argument method.args.insert(0, Argument(None, "&self")) args.insert(0, Argument(None, "&self")) argsWithoutThis.insert(0, Argument(None, "&self")) - setupCall = ("let s = CallSetup::new(cx_for_dom_object(&mut ${cxProvider}), aExceptionHandling);\n" + setupCall = ("let s = CallSetup::new(cx_for_dom_object(${cxProvider}), aExceptionHandling);\n" "if s.GetContext().is_null() {\n" " return${errorReturn};\n" "}\n") @@ -5619,7 +6030,7 @@ class CGCallback(CGClass): "errorReturn" : method.getDefaultRetval(), "callArgs" : ", ".join(argnamesWithThis), "methodName": 'self.' + method.name, - "cxProvider": '*thisObj' + "cxProvider": 'thisObj' }) bodyWithoutThis = string.Template( setupCall + @@ -5954,8 +6365,14 @@ class CallbackMethod(CallbackMember): replacements["argv"] = "nullptr" replacements["argc"] = "0" return string.Template("${getCallable}" - "if unsafe { JS_CallFunctionValue(cx, ${thisObj}, callable,\n" - " ${argc}, ${argv}, &rval) == 0 } {\n" + "let ok = unsafe {\n" + " //JS_AllowGC(cx); // It's unsafe to enable GC at arbitrary points during Rust execution; leave it disabled\n" + " let ok = JS_CallFunctionValue(cx, ${thisObj}, callable,\n" + " ${argc}, ${argv}, &rval);\n" + " //JS_InhibitGC(cx);\n" + " ok\n" + "};\n" + "if ok == 0 {\n" " return${errorReturn};\n" "}\n").substitute(replacements) @@ -6176,3 +6593,152 @@ class GlobalGenRoots(): curr = CGList([CGGeneric(declare="pub mod %sBinding;\n" % name) for name in descriptors]) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) return curr + + @staticmethod + def InheritTypes(config): + + descriptors = config.getDescriptors(register=True, hasInterfaceObject=True) + allprotos = [CGGeneric(declare="#[allow(unused_imports)];\n"), + CGGeneric(declare="use dom::types::*;\n"), + CGGeneric(declare="use dom::bindings::js::JS;\n"), + CGGeneric(declare="use dom::bindings::utils::Traceable;\n"), + CGGeneric(declare="use extra::serialize::{Encodable, Encoder};\n"), + CGGeneric(declare="use js::jsapi::JSTracer;\n\n")] + for descriptor in descriptors: + name = descriptor.name + protos = [CGGeneric(declare='pub trait %s {}\n' % (name + 'Base'))] + for proto in descriptor.prototypeChain: + protos += [CGGeneric(declare='impl %s for %s {}\n' % (proto + 'Base', + descriptor.concreteType))] + derived = [CGGeneric(declare='pub trait %s { fn %s(&self) -> bool; }\n' % + (name + 'Derived', 'is_' + name.lower()))] + for protoName in descriptor.prototypeChain[1:-1]: + protoDescriptor = config.getDescriptor(protoName, False) + delegate = string.Template('''impl ${selfName} for ${baseName} { + fn ${fname}(&self) -> bool { + self.${parentName}.${fname}() + } +} +''').substitute({'fname': 'is_' + name.lower(), + 'selfName': name + 'Derived', + 'baseName': protoDescriptor.concreteType, + 'parentName': protoDescriptor.prototypeChain[-2].lower()}) + derived += [CGGeneric(declare=delegate)] + derived += [CGGeneric(declare='\n')] + + cast = [CGGeneric(declare=string.Template('''pub trait ${castTraitName} { + fn from<T: ${fromBound}>(derived: &JS<T>) -> JS<Self> { + unsafe { derived.clone().transmute() } + } + + fn to<T: ${toBound}>(base: &JS<T>) -> JS<Self> { + assert!(base.get().${checkFn}()); + unsafe { base.clone().transmute() } + } +} +''').substitute({'checkFn': 'is_' + name.lower(), + 'castTraitName': name + 'Cast', + 'fromBound': name + 'Base', + 'toBound': name + 'Derived'})), + CGGeneric(declare="impl %s for %s {}\n\n" % (name + 'Cast', name))] + + trace = [CGGeneric(declare=string.Template('''impl Traceable for ${name} { + fn trace(&self, tracer: *mut JSTracer) { + unsafe { + self.encode(&mut *tracer); + } + } +} +''').substitute({'name': name}))] + + allprotos += protos + derived + cast + trace + + curr = CGList(allprotos) + curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) + return curr + + @staticmethod + def UnionTypes(config): + + (includes, declarations, unions) = UnionTypes(config.getDescriptors()) + includes.add("mozilla/dom/BindingUtils.h") + + # Wrap all of that in our namespaces. + #curr = CGNamespace.build(['mozilla', 'dom'], unions, public=True) + curr = unions + + curr = CGWrapper(curr, post='\n') + + namespaces = [] + stack = [CGList([])] + for (clazz, isStruct) in SortedTuples(declarations): + elements = clazz.split("::") + elements.pop() + #clazz = CGClassForwardDeclare(elements.pop(), isStruct=isStruct) + i = 0 + if len(elements) > 0: + common = min(len(namespaces), len(elements)) + while i < common and namespaces[i] == elements[i]: + i += 1 + + # pop all the namespaces that should be closed + namespaces = namespaces[:i] + + # add all the namespaces that should be opened + for j, namespace in enumerate(elements[i:]): + namespaces.append(namespace) + # every CGNamespace that we add holds a CGList + list = CGList([]) + # add the new namespace to the list on top of the stack + stack[i + j].append(CGNamespace(namespace, list)) + # set the top of the namespace stack to the list of the new + # namespace + stack[i + j + 1:] = [list] + + #stack[len(elements)].append(clazz) + + curr = CGList([stack[0], curr], "\n") + + #curr = CGHeaders([], [], includes, [], curr) + + # Add include guards. + #curr = CGIncludeGuard('UnionTypes', curr) + + curr = CGImports([], [], ['dom::bindings::js::JS', + 'dom::types::*'], [], curr) + + # Add the auto-generated comment. + curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) + + # Done. + return curr + + @staticmethod + def UnionConversions(config): + + unions = UnionConversions(config.getDescriptors()) + curr = unions + + # Wrap all of that in our namespaces. + #curr = CGNamespace.build(['mozilla', 'dom'], unions) + + curr = CGWrapper(curr, post='\n') + + #curr = CGHeaders([], [], ["nsDebug.h", "mozilla/dom/UnionTypes.h", "nsDOMQS.h"], [], curr) + + # Add include guards. + #curr = CGIncludeGuard('UnionConversions', curr) + + curr = CGImports([], [], ['dom::bindings::utils::unwrap_jsmanaged', + 'dom::bindings::codegen::UnionTypes::*', + 'dom::bindings::codegen::PrototypeList', + 'dom::bindings::conversions::JSValConvertible', + 'js::*', + 'js::jsapi::*', + 'js::glue::*'], [], curr) + + # Add the auto-generated comment. + curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) + + # Done. + return curr diff --git a/src/components/script/dom/bindings/codegen/Configuration.py b/src/components/script/dom/bindings/codegen/Configuration.py index 0c87ead0259..e28e24bbcfa 100644 --- a/src/components/script/dom/bindings/codegen/Configuration.py +++ b/src/components/script/dom/bindings/codegen/Configuration.py @@ -158,10 +158,9 @@ class Descriptor(DescriptorProvider): if self.workers: nativeTypeDefault = "workers::" + ifaceName else: - nativeTypeDefault = ifaceName + nativeTypeDefault = 'JS<%s>' % ifaceName self.nativeType = desc.get('nativeType', nativeTypeDefault) - self.pointerType = desc.get('pointerType', '@mut ') self.concreteType = desc.get('concreteType', ifaceName) self.needsAbstract = desc.get('needsAbstract', []) self.hasInstanceInterface = desc.get('hasInstanceInterface', None) @@ -253,7 +252,7 @@ class Descriptor(DescriptorProvider): self.prefable = desc.get('prefable', False) self.nativeIsISupports = not self.workers - self.customTrace = desc.get('customTrace', self.workers) + self.customTrace = desc.get('customTrace', self.workers) or 'trace' self.customFinalize = desc.get('customFinalize', self.workers) self.wrapperCache = self.workers or desc.get('wrapperCache', True) diff --git a/src/components/script/dom/bindings/codegen/GlobalGen.py b/src/components/script/dom/bindings/codegen/GlobalGen.py index 9f46c786065..bd8b3d70793 100644 --- a/src/components/script/dom/bindings/codegen/GlobalGen.py +++ b/src/components/script/dom/bindings/codegen/GlobalGen.py @@ -83,12 +83,14 @@ def main(): # Generate the type list. generate_file(config, 'InterfaceTypes', 'declare+define') + # Generate the type list. + generate_file(config, 'InheritTypes', 'declare+define') + # Generate the module declarations. generate_file(config, 'BindingDeclarations', 'declare+define') - #XXXjdm No union support yet - #generate_file(config, 'UnionTypes', 'declare') - #generate_file(config, 'UnionConversions', 'declare') + generate_file(config, 'UnionTypes', 'declare+define') + generate_file(config, 'UnionConversions', 'declare+define') if __name__ == '__main__': main() diff --git a/src/components/script/dom/bindings/codegen/Makefile.in b/src/components/script/dom/bindings/codegen/Makefile.in index 69fe4be4e9b..5fef1e77218 100644 --- a/src/components/script/dom/bindings/codegen/Makefile.in +++ b/src/components/script/dom/bindings/codegen/Makefile.in @@ -95,7 +95,7 @@ CSS2Properties.webidl: $(topsrcdir)/layout/style/nsCSSPropList.h \ $(srcdir)/GenerateCSS2PropertiesWebIDL.py \ $(GLOBAL_DEPS) $(CPP) $(DEFINES) $(ACDEFINES) -I$(topsrcdir)/layout/style $(webidl_base)/CSS2PropertiesProps.h | \ - PYTHONDONTWRITEBYTECODE=1 $(PYTHON) \ + $(PYTHON) \ $(srcdir)/GenerateCSS2PropertiesWebIDL.py $(webidl_base)/CSS2Properties.webidl.in > CSS2Properties.webidl $(webidl_files): %: $(webidl_base)/% @@ -107,7 +107,7 @@ $(test_webidl_files): %: $(srcdir)/test/% $(binding_header_files): %Binding.h: $(bindinggen_dependencies) \ %.webidl \ $(NULL) - PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \ + $(PYTHON) $(topsrcdir)/config/pythonpath.py \ $(PLY_INCLUDE) -I$(srcdir)/parser \ $(srcdir)/BindingGen.py header \ $(srcdir)/Bindings.conf $*Binding \ @@ -116,7 +116,7 @@ $(binding_header_files): %Binding.h: $(bindinggen_dependencies) \ $(binding_cpp_files): %Binding.cpp: $(bindinggen_dependencies) \ %.webidl \ $(NULL) - PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \ + $(PYTHON) $(topsrcdir)/config/pythonpath.py \ $(PLY_INCLUDE) -I$(srcdir)/parser \ $(srcdir)/BindingGen.py cpp \ $(srcdir)/Bindings.conf $*Binding \ @@ -142,7 +142,7 @@ $(CACHE_DIR)/.done: ParserResults.pkl: $(globalgen_dependencies) \ $(all_webidl_files) - PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \ + $(PYTHON) $(topsrcdir)/config/pythonpath.py \ $(PLY_INCLUDE) -I$(srcdir)/parser \ $(srcdir)/GlobalGen.py $(srcdir)/Bindings.conf . \ --cachedir=$(CACHE_DIR) \ diff --git a/src/components/script/dom/bindings/codegen/test/Makefile.in b/src/components/script/dom/bindings/codegen/test/Makefile.in index de388187c87..d8104db5ffd 100644 --- a/src/components/script/dom/bindings/codegen/test/Makefile.in +++ b/src/components/script/dom/bindings/codegen/test/Makefile.in @@ -79,9 +79,9 @@ $(CPPSRCS): ../%Binding.cpp: $(bindinggen_dependencies) \ $(MAKE) -C .. $*Binding.cpp check:: - PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \ + $(PYTHON) $(topsrcdir)/config/pythonpath.py \ $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py check-interactive: - PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \ + $(PYTHON) $(topsrcdir)/config/pythonpath.py \ $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py -q diff --git a/src/components/script/dom/bindings/conversions.rs b/src/components/script/dom/bindings/conversions.rs index 06745217365..decb047ab9f 100644 --- a/src/components/script/dom/bindings/conversions.rs +++ b/src/components/script/dom/bindings/conversions.rs @@ -4,7 +4,9 @@ use js::jsapi::JSVal; use js::{JSVAL_FALSE, JSVAL_TRUE}; -use js::glue::{RUST_UINT_TO_JSVAL, RUST_JSVAL_TO_INT, RUST_DOUBLE_TO_JSVAL, RUST_JSVAL_TO_DOUBLE}; +use js::glue::{RUST_UINT_TO_JSVAL, RUST_JSVAL_TO_INT, RUST_DOUBLE_TO_JSVAL}; +use js::glue::{RUST_JSVAL_TO_DOUBLE, RUST_JSVAL_IS_INT, RUST_JSVAL_IS_DOUBLE}; +use js::glue::{RUST_JSVAL_IS_BOOLEAN, RUST_JSVAL_TO_BOOLEAN}; pub trait JSValConvertible { fn to_jsval(&self) -> JSVal; @@ -21,7 +23,11 @@ impl JSValConvertible for i64 { fn from_jsval(val: JSVal) -> Option<i64> { unsafe { - Some(RUST_JSVAL_TO_DOUBLE(val) as i64) + if RUST_JSVAL_IS_INT(val) != 0 { + Some(RUST_JSVAL_TO_DOUBLE(val) as i64) + } else { + None + } } } } @@ -35,7 +41,11 @@ impl JSValConvertible for u32 { fn from_jsval(val: JSVal) -> Option<u32> { unsafe { - Some(RUST_JSVAL_TO_INT(val) as u32) + if RUST_JSVAL_IS_INT(val) != 0 { + Some(RUST_JSVAL_TO_INT(val) as u32) + } else { + None + } } } } @@ -49,7 +59,11 @@ impl JSValConvertible for i32 { fn from_jsval(val: JSVal) -> Option<i32> { unsafe { - Some(RUST_JSVAL_TO_INT(val) as i32) + if RUST_JSVAL_IS_INT(val) != 0 { + Some(RUST_JSVAL_TO_INT(val) as i32) + } else { + None + } } } } @@ -63,7 +77,11 @@ impl JSValConvertible for u16 { fn from_jsval(val: JSVal) -> Option<u16> { unsafe { - Some(RUST_JSVAL_TO_INT(val) as u16) + if RUST_JSVAL_IS_INT(val) != 0 { + Some(RUST_JSVAL_TO_INT(val) as u16) + } else { + None + } } } } @@ -78,12 +96,12 @@ impl JSValConvertible for bool { } fn from_jsval(val: JSVal) -> Option<bool> { - if val == JSVAL_TRUE { - Some(true) - } else if val == JSVAL_FALSE { - Some(false) - } else { - None + unsafe { + if RUST_JSVAL_IS_BOOLEAN(val) != 0 { + Some(RUST_JSVAL_TO_BOOLEAN(val) != 0) + } else { + None + } } } } @@ -97,7 +115,11 @@ impl JSValConvertible for f32 { fn from_jsval(val: JSVal) -> Option<f32> { unsafe { - Some(RUST_JSVAL_TO_DOUBLE(val) as f32) + if RUST_JSVAL_IS_DOUBLE(val) != 0 { + Some(RUST_JSVAL_TO_DOUBLE(val) as f32) + } else { + None + } } } } @@ -111,7 +133,11 @@ impl JSValConvertible for f64 { fn from_jsval(val: JSVal) -> Option<f64> { unsafe { - Some(RUST_JSVAL_TO_DOUBLE(val) as f64) + if RUST_JSVAL_IS_DOUBLE(val) != 0 { + Some(RUST_JSVAL_TO_DOUBLE(val) as f64) + } else { + None + } } } } diff --git a/src/components/script/dom/bindings/element.rs b/src/components/script/dom/bindings/element.rs index 9bbaf08fc6e..64190409ef5 100644 --- a/src/components/script/dom/bindings/element.rs +++ b/src/components/script/dom/bindings/element.rs @@ -3,9 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::types::*; -use dom::bindings::utils::{Reflectable, Reflector, Traceable}; - -use js::jsapi::JSTracer; +use dom::bindings::utils::{Reflectable, Reflector}; // generate_cacheable_wrapper macro_rules! generate_cacheable_wrapper( @@ -58,277 +56,149 @@ macro_rules! generate_cacheable_wrapper_base( ) ) - -// generate_traceable -macro_rules! generate_traceable( - ($name: path) => ( - generate_traceable_base!($name, element) - ) -) - -macro_rules! generate_traceable_characterdata( - ($name: path) => ( - generate_traceable_base!($name, characterdata) - ) -) - -macro_rules! generate_traceable_htmlelement( - ($name: path) => ( - generate_traceable_base!($name, htmlelement) - ) -) - -macro_rules! generate_traceable_htmlmediaelement( - ($name: path) => ( - generate_traceable_base!($name, htmlmediaelement) - ) -) - -macro_rules! generate_traceable_htmltablecellelement( - ($name: path) => ( - generate_traceable_base!($name, htmltablecellelement) - ) -) - -macro_rules! generate_traceable_node( - ($name: path) => ( - generate_traceable_base!($name, node) - ) -) - -macro_rules! generate_traceable_base( - ($name: path, $parent: ident) => ( - impl Traceable for $name { - fn trace(&self, trc: *mut JSTracer) { - self.$parent.trace(trc); - } - } - ) -) - - generate_cacheable_wrapper_characterdata!(Comment, CommentBinding::Wrap) -generate_traceable_characterdata!(Comment) generate_cacheable_wrapper_node!(DocumentFragment, DocumentFragmentBinding::Wrap) -generate_traceable_node!(DocumentFragment) generate_cacheable_wrapper_node!(DocumentType, DocumentTypeBinding::Wrap) -generate_traceable_node!(DocumentType) generate_cacheable_wrapper_characterdata!(Text, TextBinding::Wrap) -generate_traceable_characterdata!(Text) generate_cacheable_wrapper_characterdata!(ProcessingInstruction, ProcessingInstruction::Wrap) -generate_traceable_characterdata!(ProcessingInstruction) generate_cacheable_wrapper_htmlelement!(HTMLHeadElement, HTMLHeadElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLHeadElement) generate_cacheable_wrapper_htmlelement!(HTMLAnchorElement, HTMLAnchorElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLAnchorElement) generate_cacheable_wrapper_htmlelement!(HTMLAppletElement, HTMLAppletElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLAppletElement) generate_cacheable_wrapper_htmlelement!(HTMLAreaElement, HTMLAreaElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLAreaElement) generate_cacheable_wrapper_htmlmediaelement!(HTMLAudioElement, HTMLAudioElementBinding::Wrap) -generate_traceable_htmlmediaelement!(HTMLAudioElement) generate_cacheable_wrapper_htmlelement!(HTMLBaseElement, HTMLBaseElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLBaseElement) generate_cacheable_wrapper_htmlelement!(HTMLBodyElement, HTMLBodyElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLBodyElement) generate_cacheable_wrapper_htmlelement!(HTMLButtonElement, HTMLButtonElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLButtonElement) generate_cacheable_wrapper_htmlelement!(HTMLCanvasElement, HTMLCanvasElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLCanvasElement) generate_cacheable_wrapper_htmlelement!(HTMLDataListElement, HTMLDataListElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLDataListElement) generate_cacheable_wrapper_htmlelement!(HTMLDListElement, HTMLDListElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLDListElement) generate_cacheable_wrapper_htmlelement!(HTMLFormElement, HTMLFormElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLFormElement) generate_cacheable_wrapper_htmlelement!(HTMLFrameElement, HTMLFrameElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLFrameElement) generate_cacheable_wrapper_htmlelement!(HTMLFrameSetElement, HTMLFrameSetElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLFrameSetElement) generate_cacheable_wrapper_htmlelement!(HTMLBRElement, HTMLBRElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLBRElement) generate_cacheable_wrapper_htmlelement!(HTMLHRElement, HTMLHRElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLHRElement) generate_cacheable_wrapper_htmlelement!(HTMLHtmlElement, HTMLHtmlElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLHtmlElement) generate_cacheable_wrapper_htmlelement!(HTMLDataElement, HTMLDataElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLDataElement) generate_cacheable_wrapper_htmlelement!(HTMLDirectoryElement, HTMLDirectoryElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLDirectoryElement) - generate_cacheable_wrapper_htmlelement!(HTMLDivElement, HTMLDivElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLDivElement) generate_cacheable_wrapper_htmlelement!(HTMLEmbedElement, HTMLEmbedElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLEmbedElement) generate_cacheable_wrapper_htmlelement!(HTMLFieldSetElement, HTMLFieldSetElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLFieldSetElement) generate_cacheable_wrapper_htmlelement!(HTMLFontElement, HTMLFontElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLFontElement) generate_cacheable_wrapper_htmlelement!(HTMLHeadingElement, HTMLHeadingElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLHeadingElement) generate_cacheable_wrapper_htmlelement!(HTMLIFrameElement, HTMLIFrameElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLIFrameElement) generate_cacheable_wrapper_htmlelement!(HTMLImageElement, HTMLImageElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLImageElement) generate_cacheable_wrapper_htmlelement!(HTMLInputElement, HTMLInputElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLInputElement) generate_cacheable_wrapper_htmlelement!(HTMLLabelElement, HTMLLabelElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLLabelElement) generate_cacheable_wrapper_htmlelement!(HTMLLegendElement, HTMLLegendElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLLegendElement) generate_cacheable_wrapper_htmlelement!(HTMLLIElement, HTMLLIElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLLIElement) generate_cacheable_wrapper_htmlelement!(HTMLLinkElement, HTMLLinkElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLLinkElement) generate_cacheable_wrapper_htmlelement!(HTMLMainElement, HTMLMainElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLMainElement) generate_cacheable_wrapper_htmlelement!(HTMLMapElement, HTMLMapElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLMapElement) generate_cacheable_wrapper_htmlelement!(HTMLMediaElement, HTMLMediaElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLMediaElement) generate_cacheable_wrapper_htmlelement!(HTMLMetaElement, HTMLMetaElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLMetaElement) generate_cacheable_wrapper_htmlelement!(HTMLMeterElement, HTMLMeterElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLMeterElement) generate_cacheable_wrapper_htmlelement!(HTMLModElement, HTMLModElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLModElement) generate_cacheable_wrapper_htmlelement!(HTMLObjectElement, HTMLObjectElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLObjectElement) generate_cacheable_wrapper_htmlelement!(HTMLOListElement, HTMLOListElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLOListElement) generate_cacheable_wrapper_htmlelement!(HTMLOptGroupElement, HTMLOptGroupElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLOptGroupElement) generate_cacheable_wrapper_htmlelement!(HTMLOptionElement, HTMLOptionElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLOptionElement) generate_cacheable_wrapper_htmlelement!(HTMLOutputElement, HTMLOutputElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLOutputElement) generate_cacheable_wrapper_htmlelement!(HTMLParagraphElement, HTMLParagraphElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLParagraphElement) generate_cacheable_wrapper_htmlelement!(HTMLParamElement, HTMLParamElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLParamElement) generate_cacheable_wrapper_htmlelement!(HTMLPreElement, HTMLPreElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLPreElement) generate_cacheable_wrapper_htmlelement!(HTMLProgressElement, HTMLProgressElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLProgressElement) generate_cacheable_wrapper_htmlelement!(HTMLQuoteElement, HTMLQuoteElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLQuoteElement) generate_cacheable_wrapper_htmlelement!(HTMLScriptElement, HTMLScriptElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLScriptElement) generate_cacheable_wrapper_htmlelement!(HTMLSelectElement, HTMLSelectElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLSelectElement) generate_cacheable_wrapper_htmlelement!(HTMLSourceElement, HTMLSourceElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLSourceElement) generate_cacheable_wrapper_htmlelement!(HTMLSpanElement, HTMLSpanElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLSpanElement) generate_cacheable_wrapper_htmlelement!(HTMLStyleElement, HTMLStyleElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLStyleElement) generate_cacheable_wrapper_htmlelement!(HTMLTableElement, HTMLTableElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTableElement) generate_cacheable_wrapper_htmlelement!(HTMLTableCaptionElement, HTMLTableCaptionElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTableCaptionElement) generate_cacheable_wrapper_htmlelement!(HTMLTableCellElement, HTMLTableCellElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTableCellElement) generate_cacheable_wrapper_htmltablecellelement!(HTMLTableDataCellElement, HTMLTableDataCellElementBinding::Wrap) -generate_traceable_htmltablecellelement!(HTMLTableDataCellElement) generate_cacheable_wrapper_htmltablecellelement!(HTMLTableHeaderCellElement, HTMLTableHeaderCellElementBinding::Wrap) -generate_traceable_htmltablecellelement!(HTMLTableHeaderCellElement) generate_cacheable_wrapper_htmlelement!(HTMLTableColElement, HTMLTableColElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTableColElement) generate_cacheable_wrapper_htmlelement!(HTMLTableRowElement, HTMLTableRowElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTableRowElement) generate_cacheable_wrapper_htmlelement!(HTMLTableSectionElement, HTMLTableSectionElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTableSectionElement) generate_cacheable_wrapper_htmlelement!(HTMLTemplateElement, HTMLTemplateElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTemplateElement) generate_cacheable_wrapper_htmlelement!(HTMLTextAreaElement, HTMLTextAreaElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTextAreaElement) generate_cacheable_wrapper_htmlelement!(HTMLTitleElement, HTMLTitleElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTitleElement) generate_cacheable_wrapper_htmlelement!(HTMLTimeElement, HTMLTimeElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTimeElement) generate_cacheable_wrapper_htmlelement!(HTMLTrackElement, HTMLTrackElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLTrackElement) generate_cacheable_wrapper_htmlelement!(HTMLUListElement, HTMLUListElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLUListElement) generate_cacheable_wrapper_htmlelement!(HTMLUnknownElement, HTMLUnknownElementBinding::Wrap) -generate_traceable_htmlelement!(HTMLUnknownElement) generate_cacheable_wrapper_htmlmediaelement!(HTMLVideoElement, HTMLVideoElementBinding::Wrap) -generate_traceable_htmlmediaelement!(HTMLVideoElement) generate_cacheable_wrapper!(HTMLElement, HTMLElementBinding::Wrap) -generate_traceable!(HTMLElement) - -generate_traceable_node!(Element) - -generate_traceable_node!(CharacterData) diff --git a/src/components/script/dom/bindings/js.rs b/src/components/script/dom/bindings/js.rs new file mode 100644 index 00000000000..aa7ba954a48 --- /dev/null +++ b/src/components/script/dom/bindings/js.rs @@ -0,0 +1,99 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::utils::{Reflector, Reflectable}; +use dom::window; +use js::jsapi::{JSContext, JSObject}; +use layout_interface::TrustedNodeAddress; + +use std::cast; +use std::cell::RefCell; +use std::unstable::raw::Box; + +pub struct JS<T> { + priv ptr: RefCell<*mut T> +} + +impl<T> Eq for JS<T> { + fn eq(&self, other: &JS<T>) -> bool { + self.ptr == other.ptr + } +} + +impl <T> Clone for JS<T> { + fn clone(&self) -> JS<T> { + JS { + ptr: self.ptr.clone() + } + } +} + +impl<T: Reflectable> JS<T> { + pub fn new(mut obj: ~T, + window: &window::Window, + wrap_fn: extern "Rust" fn(*JSContext, *JSObject, ~T) -> *JSObject) -> JS<T> { + let cx = window.get_cx(); + let scope = window.reflector().get_jsobject(); + let raw: *mut T = &mut *obj; + if wrap_fn(cx, scope, obj).is_null() { + fail!("Could not eagerly wrap object"); + } + JS { + ptr: RefCell::new(raw) + } + } + + pub unsafe fn from_raw(raw: *mut T) -> JS<T> { + JS { + ptr: RefCell::new(raw) + } + } + + + pub unsafe fn from_box(box_: *mut Box<T>) -> JS<T> { + let raw: *mut T = &mut (*box_).data; + JS { + ptr: RefCell::new(raw) + } + } + + pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS<T> { + JS { + ptr: RefCell::new(inner as *mut T) + } + } +} + +impl<T: Reflectable> Reflectable for JS<T> { + fn reflector<'a>(&'a self) -> &'a Reflector { + self.get().reflector() + } + + fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { + self.get_mut().mut_reflector() + } +} + +impl<T> JS<T> { + pub fn get<'a>(&'a self) -> &'a T { + let borrowed = self.ptr.borrow(); + unsafe { + &(**borrowed.get()) + } + } + + pub fn get_mut<'a>(&'a mut self) -> &'a mut T { + let mut borrowed = self.ptr.borrow_mut(); + unsafe { + &mut (**borrowed.get()) + } + } +} + +impl<From, To> JS<From> { + //XXXjdm It would be lovely if this could be private. + pub unsafe fn transmute(self) -> JS<To> { + cast::transmute(self) + } +} diff --git a/src/components/script/dom/bindings/node.rs b/src/components/script/dom/bindings/node.rs deleted file mode 100644 index 8bf2ab8a565..00000000000 --- a/src/components/script/dom/bindings/node.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use dom::bindings::utils::{Reflectable, Reflector, Traceable, trace_reflector}; -use dom::types::*; -use dom::node::AbstractNode; - -use std::cast; -use std::libc; -use std::ptr; -use js::jsapi::{JSTracer, JSTRACE_OBJECT, JS_CallTracer}; - -impl Reflectable for AbstractNode { - fn reflector<'a>(&'a self) -> &'a Reflector { - self.node().reflector() - } - - fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { - self.mut_node().mut_reflector() - } -} - -impl Traceable for Node { - fn trace(&self, tracer: *mut JSTracer) { - fn trace_node(tracer: *mut JSTracer, node: Option<AbstractNode>, name: &str) { - if node.is_none() { - return; - } - debug!("tracing {:s}", name); - let node = node.unwrap(); - let obj = node.reflector().get_jsobject(); - assert!(obj.is_not_null()); - unsafe { - (*tracer).debugPrinter = ptr::null(); - (*tracer).debugPrintIndex = -1; - name.to_c_str().with_ref(|name| { - (*tracer).debugPrintArg = name as *libc::c_void; - JS_CallTracer(cast::transmute(tracer), obj, JSTRACE_OBJECT as u32); - }); - } - } - debug!("tracing {:p}?:", self.reflector().get_jsobject()); - trace_node(tracer, self.parent_node, "parent"); - trace_node(tracer, self.first_child, "first child"); - trace_node(tracer, self.last_child, "last child"); - trace_node(tracer, self.next_sibling, "next sibling"); - trace_node(tracer, self.prev_sibling, "prev sibling"); - let owner_doc = self.owner_doc(); - trace_reflector(tracer, "document", owner_doc.reflector()); - } -} diff --git a/src/components/script/dom/bindings/trace.rs b/src/components/script/dom/bindings/trace.rs new file mode 100644 index 00000000000..6565bf8c2d9 --- /dev/null +++ b/src/components/script/dom/bindings/trace.rs @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::js::JS; +use dom::bindings::utils::{Reflectable, trace_reflector, Reflector}; + +use js::jsapi::JSTracer; + +use std::cast; +use extra::serialize::{Encodable, Encoder}; + +// IMPORTANT: We rely on the fact that we never attempt to encode DOM objects using +// any encoder but JSTracer. Since we derive trace hooks automatically, +// we are unfortunately required to use generic types everywhere and +// unsafely cast to the concrete JSTracer we actually require. + +impl<T: Reflectable+Encodable<S>, S: Encoder> Encodable<S> for JS<T> { + fn encode(&self, s: &mut S) { + let s: &mut JSTracer = unsafe { cast::transmute(s) }; + trace_reflector(s, "", self.reflector()); + } +} + +impl<S: Encoder> Encodable<S> for Reflector { + fn encode(&self, _s: &mut S) { + } +} diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 671f92e3766..80787d93416 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -4,11 +4,13 @@ use dom::bindings::codegen::PrototypeList; use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH; +use dom::bindings::js::JS; use dom::window; use servo_util::str::DOMString; use std::libc::c_uint; use std::cast; +use std::cmp::Eq; use std::hashmap::HashMap; use std::libc; use std::ptr; @@ -32,7 +34,7 @@ use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass, JSNative, JSTracer}; use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor}; use js::jsapi::{JS_NewGlobalObject, JS_InitStandardClasses}; use js::jsapi::{JSString, JS_CallTracer, JSTRACE_OBJECT}; -use js::jsapi::{JS_IsExceptionPending}; +use js::jsapi::{JS_IsExceptionPending, JS_AllowGC, JS_InhibitGC}; use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType; use js::{JSPROP_ENUMERATE, JSVAL_NULL, JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS}; use js::{JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER}; @@ -174,6 +176,17 @@ pub fn unwrap_object<T>(obj: *JSObject, proto_id: PrototypeList::id::ID, proto_d } } +pub fn unwrap_jsmanaged<T: Reflectable>(obj: *JSObject, + proto_id: PrototypeList::id::ID, + proto_depth: uint) -> Result<JS<T>, ()> { + let result: Result<*mut Box<T>, ()> = unwrap_object(obj, proto_id, proto_depth); + result.map(|unwrapped| { + unsafe { + JS::from_box(unwrapped) + } + }) +} + pub fn unwrap_value<T>(val: *JSVal, proto_id: PrototypeList::id::ID, proto_depth: uint) -> Result<T, ()> { unsafe { let obj = RUST_JSVAL_TO_OBJECT(*val); @@ -182,8 +195,11 @@ pub fn unwrap_value<T>(val: *JSVal, proto_id: PrototypeList::id::ID, proto_depth } pub unsafe fn squirrel_away<T>(x: @mut T) -> *Box<T> { - let y: *Box<T> = cast::transmute(x); - y + cast::transmute(x) +} + +pub unsafe fn squirrel_away_unique<T>(x: ~T) -> *Box<T> { + cast::transmute(x) } pub fn jsstring_to_str(cx: *JSContext, s: *JSString) -> DOMString { @@ -557,10 +573,6 @@ pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Ref } } -pub fn trace_option<T: Reflectable>(tracer: *mut JSTracer, description: &str, option: Option<@mut T>) { - option.map(|some| trace_reflector(tracer, description, some.reflector())); -} - pub fn initialize_global(global: *JSObject) { let protoArray = @mut ([0 as *JSObject, ..PrototypeList::id::_ID_Count as uint]); unsafe { @@ -579,21 +591,17 @@ pub trait Reflectable { } pub fn reflect_dom_object<T: Reflectable> - (obj: @mut T, + (obj: ~T, window: &window::Window, - wrap_fn: extern "Rust" fn(*JSContext, *JSObject, @mut T) -> *JSObject) - -> @mut T { - let cx = window.get_cx(); - let scope = window.reflector().get_jsobject(); - if wrap_fn(cx, scope, obj).is_null() { - fail!("Could not eagerly wrap object"); - } - assert!(obj.reflector().get_jsobject().is_not_null()); - obj + wrap_fn: extern "Rust" fn(*JSContext, *JSObject, ~T) -> *JSObject) + -> JS<T> { + JS::new(obj, window, wrap_fn) } +#[deriving(Eq)] pub struct Reflector { - object: *JSObject + object: *JSObject, + force_box_layout: @int, } impl Reflector { @@ -610,7 +618,8 @@ impl Reflector { pub fn new() -> Reflector { Reflector { - object: ptr::null() + object: ptr::null(), + force_box_layout: @1, } } } @@ -849,11 +858,11 @@ fn cx_for_dom_reflector(obj: *JSObject) -> *JSContext { } /// Returns the global object of the realm that the given DOM object was created in. -pub fn global_object_for_dom_object<T: Reflectable>(obj: &mut T) -> *Box<window::Window> { +pub fn global_object_for_dom_object<T: Reflectable>(obj: &T) -> *Box<window::Window> { global_object_for_js_object(obj.reflector().get_jsobject()) } -pub fn cx_for_dom_object<T: Reflectable>(obj: &mut T) -> *JSContext { +pub fn cx_for_dom_object<T: Reflectable>(obj: &T) -> *JSContext { cx_for_dom_reflector(obj.reflector().get_jsobject()) } @@ -870,6 +879,35 @@ pub fn throw_method_failed_with_details<T>(cx: *JSContext, return 0; } +pub fn throw_not_in_union(cx: *JSContext, names: &'static str) -> JSBool { + assert!(unsafe { JS_IsExceptionPending(cx) } == 0); + let message = format!("argument could not be converted to any of: {}", names); + message.with_c_str(|string| { + unsafe { ReportError(cx, string) }; + }); + return 0; +} + +/// Execute arbitrary code with the JS GC enabled, then disable it afterwards. +pub fn with_gc_enabled<R>(cx: *JSContext, f: || -> R) -> R { + unsafe { + JS_AllowGC(cx); + let rv = f(); + JS_InhibitGC(cx); + rv + } +} + +/// Execute arbitrary code with the JS GC disabled, then enable it afterwards. +pub fn with_gc_disabled<R>(cx: *JSContext, f: || -> R) -> R { + unsafe { + JS_InhibitGC(cx); + let rv = f(); + JS_AllowGC(cx); + rv + } +} + /// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name /// for details. #[deriving(Eq)] diff --git a/src/components/script/dom/blob.rs b/src/components/script/dom/blob.rs index 2bf0d0b7510..386b9447590 100644 --- a/src/components/script/dom/blob.rs +++ b/src/components/script/dom/blob.rs @@ -2,32 +2,36 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::Fallible; use dom::bindings::codegen::BlobBinding; use dom::window::Window; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct Blob { reflector_: Reflector, - window: @mut Window, + window: JS<Window> } impl Blob { - pub fn new_inherited(window: @mut Window) -> Blob { + pub fn new_inherited(window: JS<Window>) -> Blob { Blob { reflector_: Reflector::new(), - window: window, + window: window } } - pub fn new(window: @mut Window) -> @mut Blob { - reflect_dom_object(@mut Blob::new_inherited(window), window, BlobBinding::Wrap) + pub fn new(window: &JS<Window>) -> JS<Blob> { + reflect_dom_object(~Blob::new_inherited(window.clone()), + window.get(), + BlobBinding::Wrap) } } impl Blob { - pub fn Constructor(window: @mut Window) -> Fallible<@mut Blob> { + pub fn Constructor(window: &JS<Window>) -> Fallible<JS<Blob>> { Ok(Blob::new(window)) } @@ -39,8 +43,8 @@ impl Blob { ~"" } - pub fn Slice(&self, _start: i64, _end: i64, _contentType: Option<DOMString>) -> @mut Blob { - Blob::new(self.window) + pub fn Slice(&self, _start: i64, _end: i64, _contentType: Option<DOMString>) -> JS<Blob> { + Blob::new(&self.window) } pub fn Close(&self) {} diff --git a/src/components/script/dom/characterdata.rs b/src/components/script/dom/characterdata.rs index 0ad5f35bc78..f4bb567b5c6 100644 --- a/src/components/script/dom/characterdata.rs +++ b/src/components/script/dom/characterdata.rs @@ -4,19 +4,34 @@ //! DOM bindings for `CharacterData`. +use dom::bindings::codegen::InheritTypes::CharacterDataDerived; +use dom::bindings::js::JS; use dom::bindings::utils::{Fallible, ErrorResult}; use dom::bindings::utils::{Reflectable, Reflector}; -use dom::document::AbstractDocument; -use dom::node::{Node, NodeTypeId}; +use dom::document::Document; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::node::{CommentNodeTypeId, Node, NodeTypeId, TextNodeTypeId, ProcessingInstructionNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct CharacterData { node: Node, data: DOMString, } +impl CharacterDataDerived for EventTarget { + fn is_characterdata(&self) -> bool { + match self.type_id { + NodeTargetTypeId(TextNodeTypeId) | + NodeTargetTypeId(CommentNodeTypeId) | + NodeTargetTypeId(ProcessingInstructionNodeTypeId) => true, + _ => false + } + } +} + impl CharacterData { - pub fn new_inherited(id: NodeTypeId, data: DOMString, document: AbstractDocument) -> CharacterData { + pub fn new_inherited(id: NodeTypeId, data: DOMString, document: JS<Document>) -> CharacterData { CharacterData { node: Node::new_inherited(id, document), data: data diff --git a/src/components/script/dom/clientrect.rs b/src/components/script/dom/clientrect.rs index 366c33fecbe..e4fd8716c26 100644 --- a/src/components/script/dom/clientrect.rs +++ b/src/components/script/dom/clientrect.rs @@ -3,21 +3,23 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::ClientRectBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; use servo_util::geometry::Au; +#[deriving(Encodable)] pub struct ClientRect { reflector_: Reflector, top: f32, bottom: f32, left: f32, right: f32, - window: @mut Window, + window: JS<Window>, } impl ClientRect { - pub fn new_inherited(window: @mut Window, + pub fn new_inherited(window: JS<Window>, top: Au, bottom: Au, left: Au, right: Au) -> ClientRect { ClientRect { @@ -30,11 +32,11 @@ impl ClientRect { } } - pub fn new(window: @mut Window, + pub fn new(window: &JS<Window>, top: Au, bottom: Au, - left: Au, right: Au) -> @mut ClientRect { - let rect = ClientRect::new_inherited(window, top, bottom, left, right); - reflect_dom_object(@mut rect, window, ClientRectBinding::Wrap) + left: Au, right: Au) -> JS<ClientRect> { + let rect = ClientRect::new_inherited(window.clone(), top, bottom, left, right); + reflect_dom_object(~rect, window.get(), ClientRectBinding::Wrap) } diff --git a/src/components/script/dom/clientrectlist.rs b/src/components/script/dom/clientrectlist.rs index 7d221754fa3..bae001379ae 100644 --- a/src/components/script/dom/clientrectlist.rs +++ b/src/components/script/dom/clientrectlist.rs @@ -3,19 +3,21 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::ClientRectListBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::clientrect::ClientRect; use dom::window::Window; +#[deriving(Encodable)] pub struct ClientRectList { reflector_: Reflector, - rects: ~[@mut ClientRect], - window: @mut Window, + rects: ~[JS<ClientRect>], + window: JS<Window>, } impl ClientRectList { - pub fn new_inherited(window: @mut Window, - rects: ~[@mut ClientRect]) -> ClientRectList { + pub fn new_inherited(window: JS<Window>, + rects: ~[JS<ClientRect>]) -> ClientRectList { ClientRectList { reflector_: Reflector::new(), rects: rects, @@ -23,25 +25,25 @@ impl ClientRectList { } } - pub fn new(window: @mut Window, - rects: ~[@mut ClientRect]) -> @mut ClientRectList { - reflect_dom_object(@mut ClientRectList::new_inherited(window, rects), - window, ClientRectListBinding::Wrap) + pub fn new(window: &JS<Window>, + rects: ~[JS<ClientRect>]) -> JS<ClientRectList> { + reflect_dom_object(~ClientRectList::new_inherited(window.clone(), rects), + window.get(), ClientRectListBinding::Wrap) } pub fn Length(&self) -> u32 { self.rects.len() as u32 } - pub fn Item(&self, index: u32) -> Option<@mut ClientRect> { + pub fn Item(&self, index: u32) -> Option<JS<ClientRect>> { if index < self.rects.len() as u32 { - Some(self.rects[index]) + Some(self.rects[index].clone()) } else { None } } - pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<@mut ClientRect> { + pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<ClientRect>> { *found = index < self.rects.len() as u32; self.Item(index) } diff --git a/src/components/script/dom/comment.rs b/src/components/script/dom/comment.rs index a94c7bb2970..5dcfde7b418 100644 --- a/src/components/script/dom/comment.rs +++ b/src/components/script/dom/comment.rs @@ -2,32 +2,45 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::codegen::InheritTypes::CommentDerived; use dom::bindings::codegen::CommentBinding; +use dom::bindings::js::JS; use dom::bindings::utils::Fallible; use dom::characterdata::CharacterData; -use dom::document::AbstractDocument; -use dom::node::{AbstractNode, CommentNodeTypeId, Node}; +use dom::document::Document; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::node::{CommentNodeTypeId, Node}; use dom::window::Window; use servo_util::str::DOMString; /// An HTML comment. +#[deriving(Encodable)] pub struct Comment { characterdata: CharacterData, } +impl CommentDerived for EventTarget { + fn is_comment(&self) -> bool { + match self.type_id { + NodeTargetTypeId(CommentNodeTypeId) => true, + _ => false + } + } +} + impl Comment { - pub fn new_inherited(text: DOMString, document: AbstractDocument) -> Comment { + pub fn new_inherited(text: DOMString, document: JS<Document>) -> Comment { Comment { characterdata: CharacterData::new_inherited(CommentNodeTypeId, text, document) } } - pub fn new(text: DOMString, document: AbstractDocument) -> AbstractNode { - let node = Comment::new_inherited(text, document); - Node::reflect_node(@mut node, document, CommentBinding::Wrap) + pub fn new(text: DOMString, document: &JS<Document>) -> JS<Comment> { + let node = Comment::new_inherited(text, document.clone()); + Node::reflect_node(~node, document, CommentBinding::Wrap) } - pub fn Constructor(owner: @mut Window, data: DOMString) -> Fallible<AbstractNode> { - Ok(Comment::new(data, owner.Document())) + pub fn Constructor(owner: &JS<Window>, data: DOMString) -> Fallible<JS<Comment>> { + Ok(Comment::new(data, &owner.get().Document())) } } diff --git a/src/components/script/dom/console.rs b/src/components/script/dom/console.rs index 98d12a17389..3c5a219b39c 100644 --- a/src/components/script/dom/console.rs +++ b/src/components/script/dom/console.rs @@ -2,11 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::codegen::ConsoleBinding; +use dom::bindings::js::JS; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct Console { reflector_: Reflector } @@ -18,8 +20,8 @@ impl Console { } } - pub fn new(window: &Window) -> @mut Console { - reflect_dom_object(@mut Console::new_inherited(), window, ConsoleBinding::Wrap) + pub fn new(window: &Window) -> JS<Console> { + reflect_dom_object(~Console::new_inherited(), window, ConsoleBinding::Wrap) } pub fn Log(&self, message: DOMString) { diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index 37df96353a9..e839e4aa233 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -2,25 +2,35 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::comment::Comment; +use dom::bindings::codegen::InheritTypes::{DocumentDerived, EventCast, HTMLElementCast}; +use dom::bindings::codegen::InheritTypes::{DocumentBase, NodeCast, DocumentCast}; +use dom::bindings::codegen::InheritTypes::{HTMLHeadElementCast, TextCast, ElementCast}; +use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast}; use dom::bindings::codegen::DocumentBinding; -use dom::bindings::utils::{Reflectable, Reflector, Traceable, reflect_dom_object}; +use dom::bindings::js::JS; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{ErrorResult, Fallible, NotSupported, InvalidCharacter, HierarchyRequest}; use dom::bindings::utils::{xml_name_type, InvalidXMLName}; +use dom::comment::Comment; use dom::documentfragment::DocumentFragment; +use dom::documenttype::DocumentType; use dom::domimplementation::DOMImplementation; use dom::element::{Element}; -use dom::element::{HTMLHtmlElementTypeId, HTMLHeadElementTypeId, HTMLTitleElementTypeId, HTMLBodyElementTypeId, HTMLFrameSetElementTypeId}; -use dom::event::{AbstractEvent, Event}; +use dom::element::{HTMLHtmlElementTypeId, HTMLHeadElementTypeId, HTMLTitleElementTypeId}; +use dom::element::{HTMLBodyElementTypeId, HTMLFrameSetElementTypeId}; +use dom::event::Event; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlcollection::HTMLCollection; -use dom::htmldocument::HTMLDocument; +use dom::htmlelement::HTMLElement; +use dom::htmlheadelement::HTMLHeadElement; +use dom::htmlhtmlelement::HTMLHtmlElement; +use dom::htmltitleelement::HTMLTitleElement; use dom::mouseevent::MouseEvent; -use dom::node::{AbstractNode, Node, ElementNodeTypeId, DocumentNodeTypeId}; +use dom::node::{Node, ElementNodeTypeId, DocumentNodeTypeId, NodeHelpers, INode}; use dom::text::Text; use dom::processinginstruction::ProcessingInstruction; use dom::uievent::UIEvent; use dom::window::Window; -use dom::htmltitleelement::HTMLTitleElement; use html::hubbub_html_parser::build_element_from_tag; use hubbub::hubbub::{QuirksMode, NoQuirks, LimitedQuirks, FullQuirks}; use layout_interface::{DocumentDamageLevel, ContentChangedDocumentDamage}; @@ -28,154 +38,109 @@ use servo_util::namespace::Null; use servo_util::str::DOMString; use extra::url::{Url, from_str}; -use js::jsapi::{JSObject, JSContext, JSTracer}; +use js::jsapi::{JSObject, JSContext}; use std::ascii::StrAsciiExt; -use std::cast; use std::hashmap::HashMap; -use std::unstable::raw::Box; - -#[deriving(Eq)] -pub enum DocumentTypeId { - PlainDocumentTypeId, - HTMLDocumentTypeId -} - -#[deriving(Eq)] -pub struct AbstractDocument { - document: *mut Box<Document> -} - -impl AbstractDocument { - pub fn document<'a>(&'a self) -> &'a Document { - unsafe { - &(*self.document).data - } - } - - pub fn mut_document<'a>(&'a self) -> &'a mut Document { - unsafe { - &mut (*self.document).data - } - } - - unsafe fn transmute<T, R>(&self, f: |&T| -> R) -> R { - let box_: *Box<T> = cast::transmute(self.document); - f(&(*box_).data) - } - pub fn with_html<R>(&self, callback: |&HTMLDocument| -> R) -> R { - match self.document().doctype { - HTML => unsafe { self.transmute(callback) }, - _ => fail!("attempt to downcast a non-HTMLDocument to HTMLDocument") - } - } - - pub fn from_box<T>(ptr: *mut Box<T>) -> AbstractDocument { - AbstractDocument { - document: ptr as *mut Box<Document> - } - } - - pub fn from_node(node: AbstractNode) -> AbstractDocument { - if !node.is_document() { - fail!("node is not a document"); - } - unsafe { - cast::transmute(node) - } - } -} +use extra::serialize::{Encoder, Encodable}; -#[deriving(Eq)] -pub enum DocumentType { - HTML, - SVG, - XML +#[deriving(Eq,Encodable)] +pub enum IsHTMLDocument { + HTMLDocument, + NonHTMLDocument, } +#[deriving(Encodable)] pub struct Document { node: Node, reflector_: Reflector, - window: @mut Window, - doctype: DocumentType, - idmap: HashMap<DOMString, AbstractNode>, - implementation: Option<@mut DOMImplementation>, + window: JS<Window>, + idmap: HashMap<DOMString, JS<Element>>, + implementation: Option<JS<DOMImplementation>>, content_type: DOMString, + encoding_name: DOMString, + is_html_document: bool, + extra: Untraceable, +} + +struct Untraceable { url: Url, quirks_mode: QuirksMode, - encoding_name: DOMString, +} + +impl<S: Encoder> Encodable<S> for Untraceable { + fn encode(&self, _: &mut S) { + } +} + +impl DocumentDerived for EventTarget { + fn is_document(&self) -> bool { + match self.type_id { + NodeTargetTypeId(DocumentNodeTypeId) => true, + _ => false + } + } } impl Document { - pub fn reflect_document<D: Reflectable> - (document: @mut D, - window: @mut Window, - wrap_fn: extern "Rust" fn(*JSContext, *JSObject, @mut D) -> *JSObject) - -> AbstractDocument { + pub fn reflect_document<D: Reflectable+DocumentBase> + (document: ~D, + window: &JS<Window>, + wrap_fn: extern "Rust" fn(*JSContext, *JSObject, ~D) -> *JSObject) + -> JS<D> { assert!(document.reflector().get_jsobject().is_null()); - let document = reflect_dom_object(document, window, wrap_fn); - assert!(document.reflector().get_jsobject().is_not_null()); - - // JS object now owns the Document, so transmute_copy is needed - let abstract = AbstractDocument { - document: unsafe { cast::transmute_copy(&document) } - }; - abstract.mut_document().node.set_owner_doc(abstract); - abstract - } - - pub fn new_inherited(window: @mut Window, url: Option<Url>, doctype: DocumentType, content_type: Option<DOMString>) -> Document { - let node_type = match doctype { - HTML => HTMLDocumentTypeId, - SVG | XML => PlainDocumentTypeId - }; + let raw_doc = reflect_dom_object(document, window.get(), wrap_fn); + assert!(raw_doc.reflector().get_jsobject().is_not_null()); + + let document = DocumentCast::from(&raw_doc); + let mut node: JS<Node> = NodeCast::from(&document); + node.get_mut().set_owner_doc(&document); + raw_doc + } + + pub fn new_inherited(window: JS<Window>, + url: Option<Url>, + is_html_document: IsHTMLDocument, + content_type: Option<DOMString>) -> Document { Document { - node: Node::new_without_doc(DocumentNodeTypeId(node_type)), + node: Node::new_without_doc(DocumentNodeTypeId), reflector_: Reflector::new(), window: window, - doctype: doctype, idmap: HashMap::new(), implementation: None, content_type: match content_type { Some(string) => string.clone(), - None => match doctype { + None => match is_html_document { // http://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument - HTML => ~"text/html", + HTMLDocument => ~"text/html", // http://dom.spec.whatwg.org/#concept-document-content-type - SVG | XML => ~"application/xml" + NonHTMLDocument => ~"application/xml" } }, - url: match url { - None => from_str("about:blank").unwrap(), - Some(_url) => _url + extra: Untraceable { + url: match url { + None => from_str("about:blank").unwrap(), + Some(_url) => _url + }, + // http://dom.spec.whatwg.org/#concept-document-quirks + quirks_mode: NoQuirks, }, - // http://dom.spec.whatwg.org/#concept-document-quirks - quirks_mode: NoQuirks, // http://dom.spec.whatwg.org/#concept-document-encoding encoding_name: ~"utf-8", + is_html_document: is_html_document == HTMLDocument, } } - pub fn new(window: @mut Window, url: Option<Url>, doctype: DocumentType, content_type: Option<DOMString>) -> AbstractDocument { - let document = Document::new_inherited(window, url, doctype, content_type); - Document::reflect_document(@mut document, window, DocumentBinding::Wrap) + pub fn new(window: &JS<Window>, url: Option<Url>, doctype: IsHTMLDocument, content_type: Option<DOMString>) -> JS<Document> { + let document = Document::new_inherited(window.clone(), url, doctype, content_type); + Document::reflect_document(~document, window, DocumentBinding::Wrap) } } impl Document { // http://dom.spec.whatwg.org/#dom-document - pub fn Constructor(owner: @mut Window) -> Fallible<AbstractDocument> { - Ok(Document::new(owner, None, XML, None)) - } -} - -impl Reflectable for AbstractDocument { - fn reflector<'a>(&'a self) -> &'a Reflector { - self.document().reflector() - } - - fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { - self.mut_document().mut_reflector() + pub fn Constructor(owner: &JS<Window>) -> Fallible<JS<Document>> { + Ok(Document::new(owner, None, NonHTMLDocument, None)) } } @@ -191,16 +156,16 @@ impl Reflectable for Document { impl Document { // http://dom.spec.whatwg.org/#dom-document-implementation - pub fn Implementation(&mut self) -> @mut DOMImplementation { + pub fn Implementation(&mut self) -> JS<DOMImplementation> { if self.implementation.is_none() { - self.implementation = Some(DOMImplementation::new(self.window)); + self.implementation = Some(DOMImplementation::new(&self.window)); } - self.implementation.unwrap() + self.implementation.get_ref().clone() } // http://dom.spec.whatwg.org/#dom-document-url pub fn URL(&self) -> DOMString { - self.url.to_str() + self.extra.url.to_str() } // http://dom.spec.whatwg.org/#dom-document-documenturi @@ -210,14 +175,14 @@ impl Document { // http://dom.spec.whatwg.org/#dom-document-compatmode pub fn CompatMode(&self) -> DOMString { - match self.quirks_mode { + match self.extra.quirks_mode { NoQuirks => ~"CSS1Compat", LimitedQuirks | FullQuirks => ~"BackCompat" } } pub fn set_quirks_mode(&mut self, mode: QuirksMode) { - self.quirks_mode = mode; + self.extra.quirks_mode = mode; } // http://dom.spec.whatwg.org/#dom-document-characterset @@ -235,43 +200,34 @@ impl Document { } // http://dom.spec.whatwg.org/#dom-document-doctype - pub fn GetDoctype(&self) -> Option<AbstractNode> { + pub fn GetDoctype(&self) -> Option<JS<DocumentType>> { self.node.children().find(|child| child.is_doctype()) + .map(|node| DocumentTypeCast::to(&node)) } // http://dom.spec.whatwg.org/#dom-document-documentelement - pub fn GetDocumentElement(&self) -> Option<AbstractNode> { + pub fn GetDocumentElement(&self) -> Option<JS<Element>> { self.node.child_elements().next() } // http://dom.spec.whatwg.org/#dom-document-getelementsbytagname - pub fn GetElementsByTagName(&self, tag: DOMString) -> @mut HTMLCollection { + pub fn GetElementsByTagName(&self, tag: DOMString) -> JS<HTMLCollection> { self.createHTMLCollection(|elem| elem.tag_name == tag) } - // http://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens - pub fn GetElementsByTagNameNS(&self, _ns: Option<DOMString>, _tag: DOMString) -> @mut HTMLCollection { - HTMLCollection::new(self.window, ~[]) - } - - // http://dom.spec.whatwg.org/#dom-document-getelementsbyclassname - pub fn GetElementsByClassName(&self, _class: DOMString) -> @mut HTMLCollection { - HTMLCollection::new(self.window, ~[]) - } - // http://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid - pub fn GetElementById(&self, id: DOMString) -> Option<AbstractNode> { + pub fn GetElementById(&self, id: DOMString) -> Option<JS<Element>> { // TODO: "in tree order, within the context object's tree" // http://dom.spec.whatwg.org/#dom-document-getelementbyid. match self.idmap.find_equiv(&id) { None => None, - Some(node) => Some(*node), + Some(node) => Some(node.clone()), } } // http://dom.spec.whatwg.org/#dom-document-createelement - pub fn CreateElement(&self, abstract_self: AbstractDocument, local_name: DOMString) - -> Fallible<AbstractNode> { + pub fn CreateElement(&self, abstract_self: &JS<Document>, local_name: DOMString) + -> Fallible<JS<Element>> { if xml_name_type(local_name) == InvalidXMLName { debug!("Not a valid element name"); return Err(InvalidCharacter); @@ -281,24 +237,24 @@ impl Document { } // http://dom.spec.whatwg.org/#dom-document-createdocumentfragment - pub fn CreateDocumentFragment(&self, abstract_self: AbstractDocument) -> AbstractNode { + pub fn CreateDocumentFragment(&self, abstract_self: &JS<Document>) -> JS<DocumentFragment> { DocumentFragment::new(abstract_self) } // http://dom.spec.whatwg.org/#dom-document-createtextnode - pub fn CreateTextNode(&self, abstract_self: AbstractDocument, data: DOMString) - -> AbstractNode { + pub fn CreateTextNode(&self, abstract_self: &JS<Document>, data: DOMString) + -> JS<Text> { Text::new(data, abstract_self) } // http://dom.spec.whatwg.org/#dom-document-createcomment - pub fn CreateComment(&self, abstract_self: AbstractDocument, data: DOMString) -> AbstractNode { + pub fn CreateComment(&self, abstract_self: &JS<Document>, data: DOMString) -> JS<Comment> { Comment::new(data, abstract_self) } // http://dom.spec.whatwg.org/#dom-document-createprocessinginstruction - pub fn CreateProcessingInstruction(&self, abstract_self: AbstractDocument, target: DOMString, - data: DOMString) -> Fallible<AbstractNode> { + pub fn CreateProcessingInstruction(&self, abstract_self: &JS<Document>, target: DOMString, + data: DOMString) -> Fallible<JS<ProcessingInstruction>> { // Step 1. if xml_name_type(target) == InvalidXMLName { return Err(InvalidCharacter); @@ -314,43 +270,29 @@ impl Document { } // http://dom.spec.whatwg.org/#dom-document-createevent - pub fn CreateEvent(&self, interface: DOMString) -> Fallible<AbstractEvent> { + pub fn CreateEvent(&self, interface: DOMString) -> Fallible<JS<Event>> { match interface.as_slice() { - "UIEvents" => Ok(UIEvent::new(self.window)), - "MouseEvents" => Ok(MouseEvent::new(self.window)), - "HTMLEvents" => Ok(Event::new(self.window)), + "UIEvents" => Ok(EventCast::from(&UIEvent::new(&self.window))), + "MouseEvents" => Ok(EventCast::from(&MouseEvent::new(&self.window))), + "HTMLEvents" => Ok(Event::new(&self.window)), _ => Err(NotSupported) } } // http://www.whatwg.org/specs/web-apps/current-work/#document.title - pub fn Title(&self, _: AbstractDocument) -> DOMString { + pub fn Title(&self, _: &JS<Document>) -> DOMString { let mut title = ~""; - match self.doctype { - SVG => { - fail!("no SVG document yet") - }, - _ => { - match self.GetDocumentElement() { - None => {}, - Some(root) => { - for node in root.traverse_preorder() { - if node.type_id() != ElementNodeTypeId(HTMLTitleElementTypeId) { - continue; - } - for child in node.children() { - if child.is_text() { - child.with_imm_text(|text| { - title.push_str(text.characterdata.data.as_slice()); - }); - } - } - break; - } + self.GetDocumentElement().map(|root| { + let root: JS<Node> = NodeCast::from(&root); + root.traverse_preorder() + .find(|node| node.type_id() == ElementNodeTypeId(HTMLTitleElementTypeId)) + .map(|title_elem| { + for child in title_elem.children() { + let text: JS<Text> = TextCast::to(&child); + title.push_str(text.get().characterdata.data.as_slice()); } - } - } - } + }); + }); let v: ~[&str] = title.words().collect(); title = v.connect(" "); title = title.trim().to_owned(); @@ -358,85 +300,74 @@ impl Document { } // http://www.whatwg.org/specs/web-apps/current-work/#document.title - pub fn SetTitle(&self, abstract_self: AbstractDocument, title: DOMString) -> ErrorResult { - match self.doctype { - SVG => { - fail!("no SVG document yet") - }, - _ => { - match self.GetDocumentElement() { - None => {}, - Some(root) => { - for node in root.traverse_preorder() { - if node.type_id() != ElementNodeTypeId(HTMLHeadElementTypeId) { - continue; - } - let mut has_title = false; - for child in node.children() { - if child.type_id() != ElementNodeTypeId(HTMLTitleElementTypeId) { - continue; - } - has_title = true; - for title_child in child.children() { - child.RemoveChild(title_child); - } - child.AppendChild(self.CreateTextNode(abstract_self, title.clone())); - break; - } - if !has_title { - let new_title = HTMLTitleElement::new(~"title", abstract_self); - new_title.AppendChild(self.CreateTextNode(abstract_self, title.clone())); - node.AppendChild(new_title); - } - break; - } + pub fn SetTitle(&self, abstract_self: &JS<Document>, title: DOMString) -> ErrorResult { + self.GetDocumentElement().map(|root| { + let root: JS<Node> = NodeCast::from(&root); + let mut head_node = root.traverse_preorder().find(|child| { + child.get().type_id == ElementNodeTypeId(HTMLHeadElementTypeId) + }); + head_node.as_mut().map(|head| { + + let mut title_node = head.children().find(|child| { + child.get().type_id == ElementNodeTypeId(HTMLTitleElementTypeId) + }); + + title_node.as_mut().map(|title_node| { + for mut title_child in title_node.children() { + title_node.RemoveChild(&mut title_child); } + let new_text = self.CreateTextNode(abstract_self, title.clone()); + title_node.AppendChild(&mut NodeCast::from(&new_text)); + }); + + if title_node.is_none() { + let mut new_title: JS<Node> = + NodeCast::from(&HTMLTitleElement::new(~"title", abstract_self)); + let new_text = self.CreateTextNode(abstract_self, title.clone()); + new_title.AppendChild(&mut NodeCast::from(&new_text)); + head.AppendChild(&mut new_title); } - } - } + }); + }); Ok(()) } - fn get_html_element(&self) -> Option<AbstractNode> { + fn get_html_element(&self) -> Option<JS<HTMLHtmlElement>> { self.GetDocumentElement().filtered(|root| { - match root.type_id() { - ElementNodeTypeId(HTMLHtmlElementTypeId) => true, - _ => false - } - }) + root.get().node.type_id == ElementNodeTypeId(HTMLHtmlElementTypeId) + }).map(|elem| HTMLHtmlElementCast::to(&elem)) } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-head - pub fn GetHead(&self) -> Option<AbstractNode> { + pub fn GetHead(&self) -> Option<JS<HTMLHeadElement>> { self.get_html_element().and_then(|root| { - root.children().find(|child| { + let node: JS<Node> = NodeCast::from(&root); + node.children().find(|child| { child.type_id() == ElementNodeTypeId(HTMLHeadElementTypeId) - }) + }).map(|node| HTMLHeadElementCast::to(&node)) }) } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-body - pub fn GetBody(&self, _: AbstractDocument) -> Option<AbstractNode> { - match self.get_html_element() { - None => None, - Some(root) => { - root.children().find(|child| { - match child.type_id() { - ElementNodeTypeId(HTMLBodyElementTypeId) | - ElementNodeTypeId(HTMLFrameSetElementTypeId) => true, - _ => false - } - }) - } - } + pub fn GetBody(&self, _: &JS<Document>) -> Option<JS<HTMLElement>> { + self.get_html_element().and_then(|root| { + let node: JS<Node> = NodeCast::from(&root); + node.children().find(|child| { + match child.type_id() { + ElementNodeTypeId(HTMLBodyElementTypeId) | + ElementNodeTypeId(HTMLFrameSetElementTypeId) => true, + _ => false + } + }).map(|node| HTMLElementCast::to(&node)) + }) } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-body - pub fn SetBody(&self, abstract_self: AbstractDocument, new_body: Option<AbstractNode>) -> ErrorResult { + pub fn SetBody(&self, abstract_self: &JS<Document>, new_body: Option<JS<HTMLElement>>) -> ErrorResult { // Step 1. match new_body { - Some(node) => { - match node.type_id() { + Some(ref node) => { + match node.get().element.node.type_id { ElementNodeTypeId(HTMLBodyElementTypeId) | ElementNodeTypeId(HTMLFrameSetElementTypeId) => {} _ => return Err(HierarchyRequest) } @@ -445,7 +376,7 @@ impl Document { } // Step 2. - let old_body: Option<AbstractNode> = self.GetBody(abstract_self); + let old_body: Option<JS<HTMLElement>> = self.GetBody(abstract_self); if old_body == new_body { return Ok(()); } @@ -455,41 +386,84 @@ impl Document { // Step 4. None => return Err(HierarchyRequest), Some(root) => { + let mut new_body: JS<Node> = NodeCast::from(&new_body.unwrap()); + let mut root: JS<Node> = NodeCast::from(&root); match old_body { - Some(child) => { root.ReplaceChild(new_body.unwrap(), child); } - None => { root.AppendChild(new_body.unwrap()); } - } + Some(child) => { + let mut child: JS<Node> = NodeCast::from(&child); + root.ReplaceChild(&mut new_body, &mut child) + } + None => root.AppendChild(&mut new_body) + }; } } Ok(()) } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-getelementsbyname - pub fn GetElementsByName(&self, name: DOMString) -> @mut HTMLCollection { + pub fn GetElementsByName(&self, name: DOMString) -> JS<HTMLCollection> { self.createHTMLCollection(|elem| { elem.get_attribute(Null, "name").map_default(false, |attr| { - attr.value_ref() == name + attr.get().value_ref() == name }) }) } - pub fn createHTMLCollection(&self, callback: |elem: &Element| -> bool) -> @mut HTMLCollection { + pub fn Images(&self) -> JS<HTMLCollection> { + self.createHTMLCollection(|elem| "img" == elem.tag_name) + } + + pub fn Embeds(&self) -> JS<HTMLCollection> { + self.createHTMLCollection(|elem| "embed" == elem.tag_name) + } + + pub fn Plugins(&self) -> JS<HTMLCollection> { + self.Embeds() + } + + pub fn Links(&self) -> JS<HTMLCollection> { + self.createHTMLCollection(|elem| { + ("a" == elem.tag_name || "area" == elem.tag_name) && + elem.get_attribute(Null, "href").is_some() + }) + } + + pub fn Forms(&self) -> JS<HTMLCollection> { + self.createHTMLCollection(|elem| "form" == elem.tag_name) + } + + pub fn Scripts(&self) -> JS<HTMLCollection> { + self.createHTMLCollection(|elem| "script" == elem.tag_name) + } + + pub fn Anchors(&self) -> JS<HTMLCollection> { + self.createHTMLCollection(|elem| { + "a" == elem.tag_name && elem.get_attribute(Null, "name").is_some() + }) + } + + pub fn Applets(&self) -> JS<HTMLCollection> { + // FIXME: This should be return OBJECT elements containing applets. + self.createHTMLCollection(|elem| "applet" == elem.tag_name) + } + + pub fn createHTMLCollection(&self, callback: |elem: &Element| -> bool) -> JS<HTMLCollection> { let mut elements = ~[]; match self.GetDocumentElement() { None => {}, Some(root) => { + let root: JS<Node> = NodeCast::from(&root); for child in root.traverse_preorder() { if child.is_element() { - child.with_imm_element(|elem| { - if callback(elem) { - elements.push(child); - } - }); + let elem: JS<Element> = ElementCast::to(&child); + if callback(elem.get()) { + elements.push(elem); + } } } } } - HTMLCollection::new(self.window, elements) + HTMLCollection::new(&self.window, elements) } pub fn content_changed(&self) { @@ -497,22 +471,22 @@ impl Document { } pub fn damage_and_reflow(&self, damage: DocumentDamageLevel) { - self.window.damage_and_reflow(damage); + self.window.get().damage_and_reflow(damage); } pub fn wait_until_safe_to_modify_dom(&self) { - self.window.wait_until_safe_to_modify_dom(); + self.window.get().wait_until_safe_to_modify_dom(); } - pub fn register_nodes_with_id(&mut self, root: &AbstractNode) { - foreach_ided_elements(root, |id: &DOMString, abstract_node: &AbstractNode| { + pub fn register_nodes_with_id(&mut self, root: &JS<Element>) { + foreach_ided_elements(root, |id: &DOMString, abstract_node: &JS<Element>| { // TODO: "in tree order, within the context object's tree" // http://dom.spec.whatwg.org/#dom-document-getelementbyid. - self.idmap.find_or_insert(id.clone(), *abstract_node); + self.idmap.find_or_insert(id.clone(), abstract_node.clone()); }); } - pub fn unregister_nodes_with_id(&mut self, root: &AbstractNode) { + pub fn unregister_nodes_with_id(&mut self, root: &JS<Element>) { foreach_ided_elements(root, |id: &DOMString, _| { // TODO: "in tree order, within the context object's tree" // http://dom.spec.whatwg.org/#dom-document-getelementbyid. @@ -521,7 +495,7 @@ impl Document { } pub fn update_idmap(&mut self, - abstract_self: AbstractNode, + abstract_self: &JS<Element>, new_id: Option<DOMString>, old_id: Option<DOMString>) { // remove old ids: @@ -539,11 +513,11 @@ impl Document { Some(new_id) => { // TODO: support the case if multiple elements // which haves same id are in the same document. - self.idmap.mangle(new_id, abstract_self, - |_, new_node: AbstractNode| -> AbstractNode { + self.idmap.mangle(new_id, abstract_self.clone(), + |_, new_node: JS<Element>| -> JS<Element> { new_node }, - |_, old_node: &mut AbstractNode, new_node: AbstractNode| { + |_, old_node: &mut JS<Element>, new_node: JS<Element>| { *old_node = new_node; }); } @@ -553,25 +527,19 @@ impl Document { } #[inline(always)] -fn foreach_ided_elements(root: &AbstractNode, callback: |&DOMString, &AbstractNode|) { +fn foreach_ided_elements(root: &JS<Element>, callback: |&DOMString, &JS<Element>|) { + let root: JS<Node> = NodeCast::from(root); for node in root.traverse_preorder() { if !node.is_element() { continue; } - node.with_imm_element(|element| { - match element.get_attribute(Null, "id") { - Some(id) => { - callback(&id.Value(), &node); - } - None => () + let element: JS<Element> = ElementCast::to(&node); + match element.get().get_attribute(Null, "id") { + Some(id) => { + callback(&id.get().Value(), &element); } - }); - } -} - -impl Traceable for Document { - fn trace(&self, tracer: *mut JSTracer) { - self.node.trace(tracer); + None => () + } } } diff --git a/src/components/script/dom/documentfragment.rs b/src/components/script/dom/documentfragment.rs index 0b4c56d2c92..0e38b72f8ea 100644 --- a/src/components/script/dom/documentfragment.rs +++ b/src/components/script/dom/documentfragment.rs @@ -2,32 +2,45 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::codegen::InheritTypes::DocumentFragmentDerived; use dom::bindings::codegen::DocumentFragmentBinding; +use dom::bindings::js::JS; use dom::bindings::utils::Fallible; -use dom::document::AbstractDocument; -use dom::node::{AbstractNode, DocumentFragmentNodeTypeId, Node}; +use dom::document::Document; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::node::{DocumentFragmentNodeTypeId, Node}; use dom::window::Window; +#[deriving(Encodable)] pub struct DocumentFragment { node: Node, } +impl DocumentFragmentDerived for EventTarget { + fn is_documentfragment(&self) -> bool { + match self.type_id { + NodeTargetTypeId(DocumentFragmentNodeTypeId) => true, + _ => false + } + } +} + impl DocumentFragment { /// Creates a new DocumentFragment. - pub fn new_inherited(document: AbstractDocument) -> DocumentFragment { + pub fn new_inherited(document: JS<Document>) -> DocumentFragment { DocumentFragment { node: Node::new_inherited(DocumentFragmentNodeTypeId, document), } } - pub fn new(document: AbstractDocument) -> AbstractNode { - let node = DocumentFragment::new_inherited(document); - Node::reflect_node(@mut node, document, DocumentFragmentBinding::Wrap) + pub fn new(document: &JS<Document>) -> JS<DocumentFragment> { + let node = DocumentFragment::new_inherited(document.clone()); + Node::reflect_node(~node, document, DocumentFragmentBinding::Wrap) } } impl DocumentFragment { - pub fn Constructor(owner: @mut Window) -> Fallible<AbstractNode> { - Ok(DocumentFragment::new(owner.Document())) + pub fn Constructor(owner: &JS<Window>) -> Fallible<JS<DocumentFragment>> { + Ok(DocumentFragment::new(&owner.get().Document())) } } diff --git a/src/components/script/dom/documenttype.rs b/src/components/script/dom/documenttype.rs index f161b287702..3892f2a3235 100644 --- a/src/components/script/dom/documenttype.rs +++ b/src/components/script/dom/documenttype.rs @@ -2,12 +2,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::codegen::InheritTypes::DocumentTypeDerived; use dom::bindings::codegen::DocumentTypeBinding; -use dom::document::AbstractDocument; -use dom::node::{AbstractNode, Node, DoctypeNodeTypeId}; +use dom::bindings::js::JS; +use dom::document::Document; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::node::{Node, DoctypeNodeTypeId}; use servo_util::str::DOMString; /// The `DOCTYPE` tag. +#[deriving(Encodable)] pub struct DocumentType { node: Node, name: DOMString, @@ -15,11 +19,20 @@ pub struct DocumentType { system_id: DOMString, } +impl DocumentTypeDerived for EventTarget { + fn is_documenttype(&self) -> bool { + match self.type_id { + NodeTargetTypeId(DoctypeNodeTypeId) => true, + _ => false + } + } +} + impl DocumentType { pub fn new_inherited(name: DOMString, public_id: Option<DOMString>, system_id: Option<DOMString>, - document: AbstractDocument) + document: JS<Document>) -> DocumentType { DocumentType { node: Node::new_inherited(DoctypeNodeTypeId, document), @@ -32,13 +45,13 @@ impl DocumentType { pub fn new(name: DOMString, public_id: Option<DOMString>, system_id: Option<DOMString>, - document: AbstractDocument) - -> AbstractNode { + document: &JS<Document>) + -> JS<DocumentType> { let documenttype = DocumentType::new_inherited(name, public_id, system_id, - document); - Node::reflect_node(@mut documenttype, document, DocumentTypeBinding::Wrap) + document.clone()); + Node::reflect_node(~documenttype, document, DocumentTypeBinding::Wrap) } } diff --git a/src/components/script/dom/domexception.rs b/src/components/script/dom/domexception.rs index f0801fee40f..f6eb1751adc 100644 --- a/src/components/script/dom/domexception.rs +++ b/src/components/script/dom/domexception.rs @@ -3,12 +3,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::DOMExceptionBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; use servo_util::str::DOMString; #[repr(uint)] -#[deriving(ToStr)] +#[deriving(ToStr, Encodable)] enum DOMErrorName { IndexSizeError = 1, HierarchyRequestError = 3, @@ -33,6 +34,7 @@ enum DOMErrorName { EncodingError } +#[deriving(Encodable)] pub struct DOMException { code: DOMErrorName, reflector_: Reflector @@ -46,8 +48,8 @@ impl DOMException { } } - pub fn new(window: &Window, code: DOMErrorName) -> @mut DOMException { - reflect_dom_object(@mut DOMException::new_inherited(code), window, DOMExceptionBinding::Wrap) + pub fn new(window: &Window, code: DOMErrorName) -> JS<DOMException> { + reflect_dom_object(~DOMException::new_inherited(code), window, DOMExceptionBinding::Wrap) } } @@ -67,7 +69,7 @@ impl DOMException { match self.code { // http://dom.spec.whatwg.org/#concept-throw EncodingError => 0, - _ => self.code as u16 + code => code as u16 } } diff --git a/src/components/script/dom/domimplementation.rs b/src/components/script/dom/domimplementation.rs index 8595d54c065..86968680741 100644 --- a/src/components/script/dom/domimplementation.rs +++ b/src/components/script/dom/domimplementation.rs @@ -3,36 +3,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::DOMImplementationBinding; +use dom::bindings::codegen::InheritTypes::NodeCast; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object}; use dom::bindings::utils::{Fallible, InvalidCharacter, NamespaceError}; use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type}; -use dom::document::{AbstractDocument, HTML, HTMLDocumentTypeId}; +use dom::document::{Document, HTMLDocument}; use dom::documenttype::DocumentType; -use dom::htmldocument::HTMLDocument; use dom::htmlbodyelement::HTMLBodyElement; use dom::htmlheadelement::HTMLHeadElement; use dom::htmlhtmlelement::HTMLHtmlElement; use dom::htmltitleelement::HTMLTitleElement; -use dom::node::{AbstractNode, DocumentNodeTypeId}; +use dom::node::{Node, INode}; use dom::text::Text; use dom::window::Window; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct DOMImplementation { - owner: @mut Window, - reflector_: Reflector + owner: JS<Window>, + reflector_: Reflector, } impl DOMImplementation { - pub fn new_inherited(owner: @mut Window) -> DOMImplementation { + pub fn new_inherited(owner: JS<Window>) -> DOMImplementation { DOMImplementation { owner: owner, - reflector_: Reflector::new() + reflector_: Reflector::new(), } } - pub fn new(owner: @mut Window) -> @mut DOMImplementation { - reflect_dom_object(@mut DOMImplementation::new_inherited(owner), owner, + pub fn new(owner: &JS<Window>) -> JS<DOMImplementation> { + reflect_dom_object(~DOMImplementation::new_inherited(owner.clone()), owner.get(), DOMImplementationBinding::Wrap) } } @@ -50,66 +52,63 @@ impl Reflectable for DOMImplementation { // http://dom.spec.whatwg.org/#domimplementation impl DOMImplementation { // http://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype - pub fn CreateDocumentType(&self, qname: DOMString, pubid: DOMString, sysid: DOMString) -> Fallible<AbstractNode> { + pub fn CreateDocumentType(&self, qname: DOMString, pubid: DOMString, sysid: DOMString) -> Fallible<JS<DocumentType>> { match xml_name_type(qname) { // Step 1. InvalidXMLName => Err(InvalidCharacter), // Step 2. Name => Err(NamespaceError), // Step 3. - QName => Ok(DocumentType::new(qname, Some(pubid), Some(sysid), self.owner.Document())) + QName => Ok(DocumentType::new(qname, Some(pubid), Some(sysid), &self.owner.get().Document())) } } // http://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument - pub fn CreateHTMLDocument(&self, title: Option<DOMString>) -> AbstractDocument { + pub fn CreateHTMLDocument(&self, title: Option<DOMString>) -> JS<Document> { // Step 1-2. - let abstract_doc = HTMLDocument::new(self.owner, None); - assert!(abstract_doc.document().doctype == HTML); - - let abstract_node = AbstractNode::from_document(abstract_doc); - assert!(abstract_node.type_id() == DocumentNodeTypeId(HTMLDocumentTypeId)); + let doc = Document::new(&self.owner, None, HTMLDocument, None); + let mut doc_node: JS<Node> = NodeCast::from(&doc); { // Step 3. - let doc_type = DocumentType::new(~"html", None, None, abstract_doc); - abstract_node.AppendChild(doc_type); + let doc_type = DocumentType::new(~"html", None, None, &doc); + doc_node.AppendChild(&mut NodeCast::from(&doc_type)); } { // Step 4. - let doc_html = HTMLHtmlElement::new(~"html", abstract_doc); - abstract_node.AppendChild(doc_html); + let mut doc_html = NodeCast::from(&HTMLHtmlElement::new(~"html", &doc)); + doc_node.AppendChild(&mut doc_html); { // Step 5. - let doc_head = HTMLHeadElement::new(~"head", abstract_doc); - doc_html.AppendChild(doc_head); + let mut doc_head = NodeCast::from(&HTMLHeadElement::new(~"head", &doc)); + doc_html.AppendChild(&mut doc_head); // Step 6. match title { None => (), Some(title_str) => { // Step 6.1. - let doc_title = HTMLTitleElement::new(~"title", abstract_doc); - doc_head.AppendChild(doc_title); + let mut doc_title = NodeCast::from(&HTMLTitleElement::new(~"title", &doc)); + doc_head.AppendChild(&mut doc_title); // Step 6.2. - let title_text = Text::new(title_str, abstract_doc); - doc_title.AppendChild(title_text); + let title_text = Text::new(title_str, &doc); + doc_title.AppendChild(&mut NodeCast::from(&title_text)); } } } // Step 7. - let doc_body = HTMLBodyElement::new(~"body", abstract_doc); - doc_html.AppendChild(doc_body); + let doc_body = HTMLBodyElement::new(~"body", &doc); + doc_html.AppendChild(&mut NodeCast::from(&doc_body)); } // Step 8. // FIXME: https://github.com/mozilla/servo/issues/1522 // Step 9. - abstract_doc + doc } } diff --git a/src/components/script/dom/domparser.rs b/src/components/script/dom/domparser.rs index 1dec0025e8a..f66e737a5f8 100644 --- a/src/components/script/dom/domparser.rs +++ b/src/components/script/dom/domparser.rs @@ -4,46 +4,47 @@ use dom::bindings::codegen::DOMParserBinding; use dom::bindings::codegen::DOMParserBinding::SupportedTypeValues::{Text_html, Text_xml}; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object}; use dom::bindings::utils::Fallible; use dom::bindings::utils::FailureUnknown; -use dom::document::{AbstractDocument, Document}; -use dom::htmldocument::HTMLDocument; +use dom::document::{Document, HTMLDocument}; use dom::window::Window; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct DOMParser { - owner: @mut Window, //XXXjdm Document instead? + owner: JS<Window>, //XXXjdm Document instead? reflector_: Reflector } impl DOMParser { - pub fn new_inherited(owner: @mut Window) -> DOMParser { + pub fn new_inherited(owner: JS<Window>) -> DOMParser { DOMParser { owner: owner, reflector_: Reflector::new() } } - pub fn new(owner: @mut Window) -> @mut DOMParser { - reflect_dom_object(@mut DOMParser::new_inherited(owner), owner, + pub fn new(owner: &JS<Window>) -> JS<DOMParser> { + reflect_dom_object(~DOMParser::new_inherited(owner.clone()), owner.get(), DOMParserBinding::Wrap) } - pub fn Constructor(owner: @mut Window) -> Fallible<@mut DOMParser> { + pub fn Constructor(owner: &JS<Window>) -> Fallible<JS<DOMParser>> { Ok(DOMParser::new(owner)) } pub fn ParseFromString(&self, _s: DOMString, ty: DOMParserBinding::SupportedType) - -> Fallible<AbstractDocument> { + -> Fallible<JS<Document>> { match ty { Text_html => { - Ok(HTMLDocument::new(self.owner, None)) + Ok(Document::new(&self.owner, None, HTMLDocument, None)) } Text_xml => { - Document::Constructor(self.owner) + Document::Constructor(&self.owner) } _ => { Err(FailureUnknown) diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 12361d7ec85..d7bbaa065a6 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -6,15 +6,22 @@ use dom::attr::Attr; use dom::attrlist::AttrList; +use dom::bindings::codegen::InheritTypes::{ElementDerived, HTMLImageElementCast}; +use dom::bindings::codegen::InheritTypes::{HTMLIFrameElementCast, NodeCast}; +use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{ErrorResult, Fallible, NamespaceError, InvalidCharacter}; use dom::bindings::utils::{QName, Name, InvalidXMLName, xml_name_type}; use dom::htmlcollection::HTMLCollection; use dom::clientrect::ClientRect; use dom::clientrectlist::ClientRectList; -use dom::document::AbstractDocument; -use dom::node::{AbstractNode, ElementNodeTypeId, Node, NodeIterator}; -use dom::document; +use dom::document::Document; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::htmlimageelement::HTMLImageElement; +use dom::htmliframeelement::HTMLIFrameElement; +use dom::htmlobjectelement::HTMLObjectElement; +use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator}; use dom::htmlserializer::serialize; use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery}; use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage}; @@ -26,15 +33,24 @@ use servo_util::str::{DOMString, null_str_as_empty_ref}; use std::ascii::StrAsciiExt; use std::cast; -use std::unstable::raw::Box; +#[deriving(Encodable)] pub struct Element { node: Node, tag_name: DOMString, // TODO: This should be an atom, not a DOMString. namespace: Namespace, - attrs: ~[@mut Attr], + attrs: ~[JS<Attr>], style_attribute: Option<style::PropertyDeclarationBlock>, - attr_list: Option<@mut AttrList> + attr_list: Option<JS<AttrList>> +} + +impl ElementDerived for EventTarget { + fn is_element(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(_)) => true, + _ => false + } + } } impl Reflectable for Element { @@ -47,7 +63,7 @@ impl Reflectable for Element { } } -#[deriving(Eq)] +#[deriving(Eq,Encodable)] pub enum ElementTypeId { HTMLElementTypeId, HTMLAnchorElementTypeId, @@ -104,7 +120,6 @@ pub enum ElementTypeId { HTMLStyleElementTypeId, HTMLTableElementTypeId, HTMLTableCaptionElementTypeId, - HTMLTableCellElementTypeId, HTMLTableDataCellElementTypeId, HTMLTableHeaderCellElementTypeId, HTMLTableColElementTypeId, @@ -124,9 +139,8 @@ pub enum ElementTypeId { // Element methods // - impl Element { - pub fn new_inherited(type_id: ElementTypeId, tag_name: ~str, namespace: Namespace, document: AbstractDocument) -> Element { + pub fn new_inherited(type_id: ElementTypeId, tag_name: ~str, namespace: Namespace, document: JS<Document>) -> Element { Element { node: Node::new_inherited(ElementNodeTypeId(type_id), document), tag_name: tag_name, @@ -138,41 +152,40 @@ impl Element { } pub fn html_element_in_html_document(&self) -> bool { - let owner = self.node.owner_doc(); self.namespace == namespace::HTML && - // FIXME: check that this matches what the spec calls "is in an HTML document" - owner.document().doctype == document::HTML + self.node.owner_doc().get().is_html_document } pub fn get_attribute(&self, namespace: Namespace, - name: &str) -> Option<@mut Attr> { + name: &str) -> Option<JS<Attr>> { self.attrs.iter().find(|attr| { + let attr = attr.get(); name == attr.local_name && attr.namespace == namespace - }).map(|&x| x) + }).map(|x| x.clone()) } #[inline] pub unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str) -> Option<&'static str> { - self.attrs.iter().find(|attr: & &@mut Attr| { + self.attrs.iter().find(|attr: & &JS<Attr>| { // unsafely avoid a borrow because this is accessed by many tasks // during parallel layout - let attr: ***Box<Attr> = cast::transmute(attr); - name == (***attr).data.local_name && (***attr).data.namespace == *namespace + let attr: ***Attr = cast::transmute(attr); + name == (***attr).local_name && (***attr).namespace == *namespace }).map(|attr| { - let attr: **Box<Attr> = cast::transmute(attr); - cast::transmute((**attr).data.value.as_slice()) + let attr: **Attr = cast::transmute(attr); + cast::transmute((**attr).value.as_slice()) }) } - pub fn set_attr(&mut self, abstract_self: AbstractNode, name: DOMString, value: DOMString) + pub fn set_attr(&mut self, abstract_self: &JS<Element>, name: DOMString, value: DOMString) -> ErrorResult { self.set_attribute(abstract_self, namespace::Null, name, value) } pub fn set_attribute(&mut self, - abstract_self: AbstractNode, + abstract_self: &JS<Element>, namespace: Namespace, name: DOMString, value: DOMString) -> ErrorResult { @@ -192,7 +205,8 @@ impl Element { // FIXME: reduce the time of `value.clone()`. let mut old_raw_value: Option<DOMString> = None; - for attr in self.attrs.iter() { + for attr in self.attrs.mut_iter() { + let attr = attr.get_mut(); if attr.local_name == local_name { old_raw_value = Some(attr.set_value(value.clone())); break; @@ -200,8 +214,9 @@ impl Element { } if old_raw_value.is_none() { - let win = self.node.owner_doc().document().window; - let new_attr = Attr::new_ns(win, local_name.clone(), value.clone(), + let doc = self.node.owner_doc(); + let doc = doc.get(); + let new_attr = Attr::new_ns(doc.window.get(), local_name.clone(), value.clone(), name.clone(), namespace.clone(), prefix); self.attrs.push(new_attr); @@ -214,7 +229,7 @@ impl Element { } fn after_set_attr(&mut self, - abstract_self: AbstractNode, + abstract_self: &JS<Element>, local_name: DOMString, value: DOMString, old_value: Option<DOMString>) { @@ -222,36 +237,36 @@ impl Element { match local_name.as_slice() { "style" => { let doc = self.node.owner_doc(); - let base_url = doc.document().url.clone(); + let base_url = doc.get().extra.url.clone(); self.style_attribute = Some(style::parse_style_attribute(value, &base_url)) } - "id" if abstract_self.is_in_doc() => { - // XXX: this dual declaration are workaround to avoid the compile error: - // "borrowed value does not live long enough" - let doc = self.node.owner_doc(); - let doc = doc.mut_document(); - doc.update_idmap(abstract_self, Some(value.clone()), old_value); + "id" => { + let self_node: JS<Node> = NodeCast::from(abstract_self); + if self_node.is_in_doc() { + // XXX: this dual declaration are workaround to avoid the compile error: + // "borrowed value does not live long enough" + let mut doc = self.node.owner_doc(); + let doc = doc.get_mut(); + doc.update_idmap(abstract_self, Some(value.clone()), old_value); + } } _ => () } //XXXjdm We really need something like a vtable so we can call AfterSetAttr. // This hardcoding is awful. - match abstract_self.type_id() { + match abstract_self.get().node.type_id { ElementNodeTypeId(HTMLImageElementTypeId) => { - abstract_self.with_mut_image_element(|image| { - image.AfterSetAttr(local_name.clone(), value.clone()); - }); + let mut elem: JS<HTMLImageElement> = HTMLImageElementCast::to(abstract_self); + elem.get_mut().AfterSetAttr(local_name.clone(), value.clone()); } ElementNodeTypeId(HTMLIframeElementTypeId) => { - abstract_self.with_mut_iframe_element(|iframe| { - iframe.AfterSetAttr(local_name.clone(), value.clone()); - }); + let mut elem: JS<HTMLIFrameElement> = HTMLIFrameElementCast::to(abstract_self); + elem.get_mut().AfterSetAttr(local_name.clone(), value.clone()); } ElementNodeTypeId(HTMLObjectElementTypeId) => { - abstract_self.with_mut_object_element(|object| { - object.AfterSetAttr(local_name.clone(), value.clone()); - }); + let mut elem: JS<HTMLObjectElement> = HTMLObjectElementCast::to(abstract_self); + elem.get_mut().AfterSetAttr(local_name.clone(), value.clone()); } _ => () } @@ -260,22 +275,22 @@ impl Element { } pub fn remove_attribute(&mut self, - abstract_self: AbstractNode, + abstract_self: &JS<Element>, namespace: Namespace, name: DOMString) -> ErrorResult { let (_, local_name) = get_attribute_parts(name.clone()); self.node.wait_until_safe_to_modify_dom(); - let idx = self.attrs.iter().position(|attr: &@mut Attr| -> bool { - attr.local_name == local_name + let idx = self.attrs.iter().position(|attr: &JS<Attr>| -> bool { + attr.get().local_name == local_name }); match idx { None => (), Some(idx) => { let removed = self.attrs.remove(idx); - let removed_raw_value = Some(removed.Value()); + let removed_raw_value = Some(removed.get().Value()); if namespace == namespace::Null { self.after_remove_attr(abstract_self, local_name, removed_raw_value); @@ -287,35 +302,36 @@ impl Element { } fn after_remove_attr(&mut self, - abstract_self: AbstractNode, + abstract_self: &JS<Element>, local_name: DOMString, old_value: Option<DOMString>) { match local_name.as_slice() { "style" => { self.style_attribute = None } - "id" if abstract_self.is_in_doc() => { - // XXX: this dual declaration are workaround to avoid the compile error: - // "borrowed value does not live long enough" - let doc = self.node.owner_doc(); - let doc = doc.mut_document(); - doc.update_idmap(abstract_self, None, old_value); + "id" => { + let self_node: JS<Node> = NodeCast::from(abstract_self); + if self_node.is_in_doc() { + // XXX: this dual declaration are workaround to avoid the compile error: + // "borrowed value does not live long enough" + let mut doc = self.node.owner_doc(); + let doc = doc.get_mut(); + doc.update_idmap(abstract_self, None, old_value); + } } _ => () } //XXXjdm We really need something like a vtable so we can call AfterSetAttr. // This hardcoding is awful. - match abstract_self.type_id() { + match abstract_self.get().node.type_id { ElementNodeTypeId(HTMLImageElementTypeId) => { - abstract_self.with_mut_image_element(|image| { - image.AfterRemoveAttr(local_name.clone()); - }); + let mut elem: JS<HTMLImageElement> = HTMLImageElementCast::to(abstract_self); + elem.get_mut().AfterRemoveAttr(local_name.clone()); } ElementNodeTypeId(HTMLIframeElementTypeId) => { - abstract_self.with_mut_iframe_element(|iframe| { - iframe.AfterRemoveAttr(local_name.clone()); - }); + let mut elem: JS<HTMLIFrameElement> = HTMLIFrameElementCast::to(abstract_self); + elem.get_mut().AfterRemoveAttr(local_name.clone()); } _ => () } @@ -324,15 +340,16 @@ impl Element { } fn notify_attribute_changed(&self, - abstract_self: AbstractNode, + abstract_self: &JS<Element>, local_name: DOMString) { - if abstract_self.is_in_doc() { + let node: JS<Node> = NodeCast::from(abstract_self); + if node.is_in_doc() { let damage = match local_name.as_slice() { "style" | "id" | "class" => MatchSelectorsDocumentDamage, _ => ContentChangedDocumentDamage }; let document = self.node.owner_doc(); - document.document().damage_and_reflow(damage); + document.get().damage_and_reflow(damage); } } @@ -357,18 +374,18 @@ impl Element { // XXX Resolve URL. self.get_string_attribute(name) } - pub fn set_url_attribute(&mut self, abstract_self: AbstractNode, + pub fn set_url_attribute(&mut self, abstract_self: &JS<Element>, name: &str, value: DOMString) { self.set_string_attribute(abstract_self, name, value); } pub fn get_string_attribute(&self, name: &str) -> DOMString { match self.get_attribute(Null, name) { - Some(x) => x.Value(), + Some(x) => x.get().Value(), None => ~"" } } - pub fn set_string_attribute(&mut self, abstract_self: AbstractNode, + pub fn set_string_attribute(&mut self, abstract_self: &JS<Element>, name: &str, value: DOMString) { assert!(name == name.to_ascii_lower()); self.set_attribute(abstract_self, Null, name.to_owned(), value); @@ -382,25 +399,26 @@ impl Element { } // http://dom.spec.whatwg.org/#dom-element-id - pub fn Id(&self, _abstract_self: AbstractNode) -> DOMString { + pub fn Id(&self, _abstract_self: &JS<Element>) -> DOMString { self.get_string_attribute("id") } // http://dom.spec.whatwg.org/#dom-element-id - pub fn SetId(&mut self, abstract_self: AbstractNode, id: DOMString) { + pub fn SetId(&mut self, abstract_self: &JS<Element>, id: DOMString) { self.set_string_attribute(abstract_self, "id", id); } // http://dom.spec.whatwg.org/#dom-element-attributes - pub fn Attributes(&mut self, abstract_self: AbstractNode) -> @mut AttrList { + pub fn Attributes(&mut self, abstract_self: &JS<Element>) -> JS<AttrList> { match self.attr_list { None => { - let window = self.node.owner_doc().document().window; - let list = AttrList::new(window, abstract_self); - self.attr_list = Some(list); + let doc = self.node.owner_doc(); + let doc = doc.get(); + let list = AttrList::new(&doc.window, abstract_self); + self.attr_list = Some(list.clone()); list } - Some(list) => list + Some(ref list) => list.clone() } } @@ -411,18 +429,18 @@ impl Element { } else { name }; - self.get_attribute(Null, name).map(|s| s.Value()) + self.get_attribute(Null, name).map(|s| s.get().Value()) } // http://dom.spec.whatwg.org/#dom-element-getattributens pub fn GetAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> Option<DOMString> { let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace)); self.get_attribute(namespace, local_name) - .map(|attr| attr.value.clone()) + .map(|attr| attr.get().value.clone()) } // http://dom.spec.whatwg.org/#dom-element-setattribute - pub fn SetAttribute(&mut self, abstract_self: AbstractNode, name: DOMString, value: DOMString) + pub fn SetAttribute(&mut self, abstract_self: &JS<Element>, name: DOMString, value: DOMString) -> ErrorResult { // FIXME: If name does not match the Name production in XML, throw an "InvalidCharacterError" exception. let name = if self.html_element_in_html_document() { @@ -435,7 +453,7 @@ impl Element { // http://dom.spec.whatwg.org/#dom-element-setattributens pub fn SetAttributeNS(&mut self, - abstract_self: AbstractNode, + abstract_self: &JS<Element>, namespace_url: Option<DOMString>, name: DOMString, value: DOMString) -> ErrorResult { @@ -452,7 +470,7 @@ impl Element { // http://dom.spec.whatwg.org/#dom-element-removeattribute pub fn RemoveAttribute(&mut self, - abstract_self: AbstractNode, + abstract_self: &JS<Element>, name: DOMString) -> ErrorResult { let name = if self.html_element_in_html_document() { name.to_ascii_lower() @@ -464,7 +482,7 @@ impl Element { // http://dom.spec.whatwg.org/#dom-element-removeattributens pub fn RemoveAttributeNS(&mut self, - abstract_self: AbstractNode, + abstract_self: &JS<Element>, namespace: Option<DOMString>, localname: DOMString) -> ErrorResult { let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace)); @@ -482,21 +500,24 @@ impl Element { } // http://dom.spec.whatwg.org/#dom-element-getelementsbytagname - pub fn GetElementsByTagName(&self, _localname: DOMString) -> @mut HTMLCollection { + pub fn GetElementsByTagName(&self, _localname: DOMString) -> JS<HTMLCollection> { // FIXME: stub - https://github.com/mozilla/servo/issues/1660 - HTMLCollection::new(self.node.owner_doc().document().window, ~[]) + let doc = self.node.owner_doc(); + HTMLCollection::new(&doc.get().window, ~[]) } // http://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens - pub fn GetElementsByTagNameNS(&self, _namespace: Option<DOMString>, _localname: DOMString) -> Fallible<@mut HTMLCollection> { + pub fn GetElementsByTagNameNS(&self, _namespace: Option<DOMString>, _localname: DOMString) -> Fallible<JS<HTMLCollection>> { // FIXME: stub - https://github.com/mozilla/servo/issues/1660 - Ok(HTMLCollection::new(self.node.owner_doc().document().window, ~[])) + let doc = self.node.owner_doc(); + Ok(HTMLCollection::new(&doc.get().window, ~[])) } // http://dom.spec.whatwg.org/#dom-element-getelementsbyclassname - pub fn GetElementsByClassName(&self, _names: DOMString) -> @mut HTMLCollection { + pub fn GetElementsByClassName(&self, _names: DOMString) -> JS<HTMLCollection> { // FIXME: stub - https://github.com/mozilla/servo/issues/1660 - HTMLCollection::new(self.node.owner_doc().document().window, ~[]) + let doc = self.node.owner_doc(); + HTMLCollection::new(&doc.get().window, ~[]) } // http://dom.spec.whatwg.org/#dom-element-matches @@ -517,13 +538,14 @@ impl Element { pub fn MozRequestPointerLock(&self) { } - pub fn GetClientRects(&self, abstract_self: AbstractNode) -> @mut ClientRectList { - let win = self.node.owner_doc().document().window; - let node = abstract_self; - assert!(node.is_element()); + pub fn GetClientRects(&self, abstract_self: &JS<Element>) -> JS<ClientRectList> { + let doc = self.node.owner_doc(); + let win = &doc.get().window; + let node: JS<Node> = NodeCast::from(abstract_self); let (port, chan) = Chan::new(); + let addr = node.to_trusted_node_address(); let rects = - match win.page.query_layout(ContentBoxesQuery(node, chan), port) { + match win.get().page.query_layout(ContentBoxesQuery(addr, chan), port) { ContentBoxesResponse(rects) => { rects.map(|r| { ClientRect::new( @@ -539,12 +561,13 @@ impl Element { ClientRectList::new(win, rects) } - pub fn GetBoundingClientRect(&self, abstract_self: AbstractNode) -> @mut ClientRect { - let win = self.node.owner_doc().document().window; - let node = abstract_self; - assert!(node.is_element()); + pub fn GetBoundingClientRect(&self, abstract_self: &JS<Element>) -> JS<ClientRect> { + let doc = self.node.owner_doc(); + let win = &doc.get().window; + let node: JS<Node> = NodeCast::from(abstract_self); let (port, chan) = Chan::new(); - match win.page.query_layout(ContentBoxQuery(node, chan), port) { + let addr = node.to_trusted_node_address(); + match win.get().page.query_layout(ContentBoxQuery(addr, chan), port) { ContentBoxResponse(rect) => { ClientRect::new( win, @@ -597,20 +620,20 @@ impl Element { 0 } - pub fn GetInnerHTML(&self, abstract_self: AbstractNode) -> Fallible<DOMString> { + pub fn GetInnerHTML(&self, abstract_self: &JS<Element>) -> Fallible<DOMString> { //XXX TODO: XML case - Ok(serialize(&mut NodeIterator::new(abstract_self, false, false))) + Ok(serialize(&mut NodeIterator::new(NodeCast::from(abstract_self), false, false))) } - pub fn SetInnerHTML(&mut self, _abstract_self: AbstractNode, _value: DOMString) -> ErrorResult { + pub fn SetInnerHTML(&mut self, _abstract_self: &JS<Element>, _value: DOMString) -> ErrorResult { Ok(()) } - pub fn GetOuterHTML(&self, abstract_self:AbstractNode) -> Fallible<DOMString> { - Ok(serialize(&mut NodeIterator::new(abstract_self, true, false))) + pub fn GetOuterHTML(&self, abstract_self: &JS<Element>) -> Fallible<DOMString> { + Ok(serialize(&mut NodeIterator::new(NodeCast::from(abstract_self), true, false))) } - pub fn SetOuterHTML(&mut self, _abstract_self: AbstractNode, _value: DOMString) -> ErrorResult { + pub fn SetOuterHTML(&mut self, _abstract_self: &JS<Element>, _value: DOMString) -> ErrorResult { Ok(()) } @@ -618,7 +641,7 @@ impl Element { Ok(()) } - pub fn QuerySelector(&self, _selectors: DOMString) -> Fallible<Option<AbstractNode>> { + pub fn QuerySelector(&self, _selectors: DOMString) -> Fallible<Option<JS<Element>>> { Ok(None) } } diff --git a/src/components/script/dom/event.rs b/src/components/script/dom/event.rs index aef1b4270cd..a8fac4308ef 100644 --- a/src/components/script/dom/event.rs +++ b/src/components/script/dom/event.rs @@ -2,20 +2,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::eventtarget::AbstractEventTarget; -use dom::window::Window; use dom::bindings::codegen::EventBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Fallible, ErrorResult}; -use dom::mouseevent::MouseEvent; -use dom::uievent::UIEvent; +use dom::eventtarget::EventTarget; +use dom::window::Window; use servo_util::str::DOMString; use geom::point::Point2D; -use std::cast; -use std::unstable::raw::Box; - pub enum Event_ { ResizeEvent(uint, uint), ReflowEvent, @@ -25,10 +21,7 @@ pub enum Event_ { MouseMoveEvent(Point2D<f32>) } -pub struct AbstractEvent { - event: *mut Box<Event> -} - +#[deriving(Encodable)] pub enum EventPhase { Phase_None = 0, Phase_Capturing, @@ -36,91 +29,7 @@ pub enum EventPhase { Phase_Bubbling } -impl AbstractEvent { - pub fn from_box(box_: *mut Box<Event>) -> AbstractEvent { - AbstractEvent { - event: box_ - } - } - - // - // Downcasting borrows - // - - fn transmute<'a, T>(&'a self) -> &'a T { - unsafe { - let box_: *Box<T> = self.event as *Box<T>; - &(*box_).data - } - } - - fn transmute_mut<'a, T>(&'a self) -> &'a mut T { - unsafe { - let box_: *mut Box<T> = self.event as *mut Box<T>; - &mut (*box_).data - } - } - - pub fn type_id(&self) -> EventTypeId { - self.event().type_id - } - - pub fn event<'a>(&'a self) -> &'a Event { - self.transmute() - } - - pub fn mut_event<'a>(&'a self) -> &'a mut Event { - self.transmute_mut() - } - - pub fn is_uievent(&self) -> bool { - self.type_id() == UIEventTypeId - } - - pub fn uievent<'a>(&'a self) -> &'a UIEvent { - assert!(self.is_uievent()); - self.transmute() - } - - pub fn mut_uievent<'a>(&'a self) -> &'a mut UIEvent { - assert!(self.is_uievent()); - self.transmute_mut() - } - - pub fn is_mouseevent(&self) -> bool { - self.type_id() == MouseEventTypeId - } - - pub fn mouseevent<'a>(&'a self) -> &'a MouseEvent { - assert!(self.is_mouseevent()); - self.transmute() - } - - pub fn mut_mouseevent<'a>(&'a self) -> &'a mut MouseEvent { - assert!(self.is_mouseevent()); - self.transmute_mut() - } - - pub fn propagation_stopped(&self) -> bool { - self.event().stop_propagation - } - - pub fn bubbles(&self) -> bool { - self.event().bubbles - } -} - -impl Reflectable for AbstractEvent { - fn reflector<'a>(&'a self) -> &'a Reflector { - self.event().reflector() - } - - fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { - self.mut_event().mut_reflector() - } -} - -#[deriving(Eq)] +#[deriving(Eq, Encodable)] pub enum EventTypeId { HTMLEventTypeId, UIEventTypeId, @@ -128,11 +37,12 @@ pub enum EventTypeId { KeyEventTypeId } +#[deriving(Encodable)] pub struct Event { type_id: EventTypeId, reflector_: Reflector, - current_target: Option<AbstractEventTarget>, - target: Option<AbstractEventTarget>, + current_target: Option<JS<EventTarget>>, + target: Option<JS<EventTarget>>, type_: DOMString, phase: EventPhase, default_prevented: bool, @@ -142,7 +52,7 @@ pub struct Event { bubbles: bool, trusted: bool, dispatching: bool, - initialized: bool + initialized: bool, } impl Event { @@ -165,18 +75,10 @@ impl Event { } } - //FIXME: E should be bounded by some trait that is only implemented for Event types - pub fn as_abstract<E>(event: @mut E) -> AbstractEvent { - // This surrenders memory management of the event! - AbstractEvent { - event: unsafe { cast::transmute(event) }, - } - } - - pub fn new(window: @mut Window) -> AbstractEvent { - let ev = reflect_dom_object(@mut Event::new_inherited(HTMLEventTypeId), - window, EventBinding::Wrap); - Event::as_abstract(ev) + pub fn new(window: &JS<Window>) -> JS<Event> { + reflect_dom_object(~Event::new_inherited(HTMLEventTypeId), + window.get(), + EventBinding::Wrap) } pub fn EventPhase(&self) -> u16 { @@ -187,12 +89,12 @@ impl Event { self.type_.clone() } - pub fn GetTarget(&self) -> Option<AbstractEventTarget> { - self.target + pub fn GetTarget(&self) -> Option<JS<EventTarget>> { + self.target.clone() } - pub fn GetCurrentTarget(&self) -> Option<AbstractEventTarget> { - self.current_target + pub fn GetCurrentTarget(&self) -> Option<JS<EventTarget>> { + self.current_target.clone() } pub fn DefaultPrevented(&self) -> bool { @@ -241,11 +143,11 @@ impl Event { self.trusted } - pub fn Constructor(global: @mut Window, + pub fn Constructor(global: &JS<Window>, type_: DOMString, - init: &EventBinding::EventInit) -> Fallible<AbstractEvent> { - let ev = Event::new(global); - ev.mut_event().InitEvent(type_, init.bubbles, init.cancelable); + init: &EventBinding::EventInit) -> Fallible<JS<Event>> { + let mut ev = Event::new(global); + ev.get_mut().InitEvent(type_, init.bubbles, init.cancelable); Ok(ev) } } diff --git a/src/components/script/dom/eventdispatcher.rs b/src/components/script/dom/eventdispatcher.rs index 5a1c09ce9f6..c22ef7716c1 100644 --- a/src/components/script/dom/eventdispatcher.rs +++ b/src/components/script/dom/eventdispatcher.rs @@ -3,50 +3,57 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::callback::eReportExceptions; -use dom::eventtarget::{AbstractEventTarget, Capturing, Bubbling}; -use dom::event::{AbstractEvent, Phase_At_Target, Phase_None, Phase_Bubbling, Phase_Capturing}; -use dom::node::AbstractNode; +use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, NodeDerived}; +use dom::bindings::js::JS; +use dom::eventtarget::{Capturing, Bubbling, EventTarget}; +use dom::event::{Event, Phase_At_Target, Phase_None, Phase_Bubbling, Phase_Capturing}; +use dom::node::{Node, NodeHelpers}; // See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm -pub fn dispatch_event(target: AbstractEventTarget, - pseudo_target: Option<AbstractEventTarget>, - event: AbstractEvent) -> bool { - assert!(!event.event().dispatching); +pub fn dispatch_event(target: &JS<EventTarget>, + pseudo_target: Option<JS<EventTarget>>, + event: &mut JS<Event>) -> bool { + assert!(!event.get().dispatching); { - let event = event.mut_event(); - event.target = Some(pseudo_target.unwrap_or(target)); + let event = event.get_mut(); + event.target = match pseudo_target { + Some(pseudo_target) => Some(pseudo_target), + None => Some(target.clone()) + }; event.dispatching = true; } - let type_ = event.event().type_.clone(); + let type_ = event.get().type_.clone(); let mut chain = ~[]; //TODO: no chain if not participating in a tree - if target.is_node() { - for ancestor in AbstractNode::from_eventtarget(target).ancestors() { - chain.push(AbstractEventTarget::from_node(ancestor)); + if target.get().is_node() { + let target_node: JS<Node> = NodeCast::to(target); + for ancestor in target_node.ancestors() { + let ancestor_target: JS<EventTarget> = EventTargetCast::from(&ancestor); + chain.push(ancestor_target); } } - event.mut_event().phase = Phase_Capturing; + event.get_mut().phase = Phase_Capturing; //FIXME: The "callback this value" should be currentTarget /* capturing */ - for &cur_target in chain.rev_iter() { - let stopped = match cur_target.eventtarget().get_listeners_for(type_, Capturing) { + for cur_target in chain.rev_iter() { + let stopped = match cur_target.get().get_listeners_for(type_, Capturing) { Some(listeners) => { - event.mut_event().current_target = Some(cur_target); + event.get_mut().current_target = Some(cur_target.clone()); for listener in listeners.iter() { listener.HandleEvent__(event, eReportExceptions); - if event.event().stop_immediate { + if event.get().stop_immediate { break; } } - event.propagation_stopped() + event.get().stop_propagation } None => false }; @@ -57,18 +64,18 @@ pub fn dispatch_event(target: AbstractEventTarget, } /* at target */ - if !event.propagation_stopped() { + if !event.get().stop_propagation { { - let event = event.mut_event(); + let event = event.get_mut(); event.phase = Phase_At_Target; - event.current_target = Some(target); + event.current_target = Some(target.clone()); } - let opt_listeners = target.eventtarget().get_listeners(type_); + let opt_listeners = target.get().get_listeners(type_); for listeners in opt_listeners.iter() { for listener in listeners.iter() { listener.HandleEvent__(event, eReportExceptions); - if event.event().stop_immediate { + if event.get().stop_immediate { break; } } @@ -76,22 +83,22 @@ pub fn dispatch_event(target: AbstractEventTarget, } /* bubbling */ - if event.bubbles() && !event.propagation_stopped() { - event.mut_event().phase = Phase_Bubbling; + if event.get().bubbles && !event.get().stop_propagation { + event.get_mut().phase = Phase_Bubbling; - for &cur_target in chain.iter() { - let stopped = match cur_target.eventtarget().get_listeners_for(type_, Bubbling) { + for cur_target in chain.iter() { + let stopped = match cur_target.get().get_listeners_for(type_, Bubbling) { Some(listeners) => { - event.mut_event().current_target = Some(cur_target); + event.get_mut().current_target = Some(cur_target.clone()); for listener in listeners.iter() { listener.HandleEvent__(event, eReportExceptions); - if event.event().stop_immediate { + if event.get().stop_immediate { break; } } - event.propagation_stopped() + event.get().stop_propagation } None => false }; @@ -101,7 +108,7 @@ pub fn dispatch_event(target: AbstractEventTarget, } } - let event = event.mut_event(); + let event = event.get_mut(); event.dispatching = false; event.phase = Phase_None; event.current_target = None; diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs index dbc435ac012..07445b12de5 100644 --- a/src/components/script/dom/eventtarget.rs +++ b/src/components/script/dom/eventtarget.rs @@ -2,122 +2,42 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Fallible, InvalidState}; use dom::bindings::codegen::EventListenerBinding::EventListener; -use dom::document::AbstractDocument; -use dom::event::AbstractEvent; +use dom::event::Event; use dom::eventdispatcher::dispatch_event; -use dom::node::AbstractNode; -use dom::window::Window; +use dom::node::NodeTypeId; use servo_util::str::DOMString; -use std::cast; use std::hashmap::HashMap; -use std::unstable::raw::Box; -#[deriving(Eq)] +#[deriving(Eq,Encodable)] pub enum ListenerPhase { Capturing, Bubbling, } -#[deriving(Eq)] +#[deriving(Eq,Encodable)] pub enum EventTargetTypeId { WindowTypeId, - NodeTypeId + NodeTargetTypeId(NodeTypeId) } -#[deriving(Eq)] +#[deriving(Eq,Encodable)] struct EventListenerEntry { phase: ListenerPhase, listener: EventListener } +#[deriving(Encodable)] pub struct EventTarget { type_id: EventTargetTypeId, reflector_: Reflector, handlers: HashMap<DOMString, ~[EventListenerEntry]>, } -pub struct AbstractEventTarget { - eventtarget: *mut Box<EventTarget> -} - -impl AbstractEventTarget { - pub fn from_box<T>(box_: *mut Box<T>) -> AbstractEventTarget { - AbstractEventTarget { - eventtarget: box_ as *mut Box<EventTarget> - } - } - - pub fn from_node(node: AbstractNode) -> AbstractEventTarget { - unsafe { - cast::transmute(node) - } - } - - pub fn from_window(window: @mut Window) -> AbstractEventTarget { - AbstractEventTarget { - eventtarget: unsafe { cast::transmute(window) } - } - } - - pub fn from_document(document: AbstractDocument) -> AbstractEventTarget { - unsafe { - cast::transmute(document) - } - } - - pub fn type_id(&self) -> EventTargetTypeId { - self.eventtarget().type_id - } - - pub fn is_window(&self) -> bool { - self.type_id() == WindowTypeId - } - - pub fn is_node(&self) -> bool { - self.type_id() == NodeTypeId - } - - // - // Downcasting borrows - // - - fn transmute<'a, T>(&'a self) -> &'a T { - unsafe { - let box_: *Box<T> = self.eventtarget as *Box<T>; - &(*box_).data - } - } - - fn transmute_mut<'a, T>(&'a mut self) -> &'a mut T { - unsafe { - let box_: *mut Box<T> = self.eventtarget as *mut Box<T>; - &mut (*box_).data - } - } - - pub fn eventtarget<'a>(&'a self) -> &'a EventTarget { - self.transmute() - } - - pub fn mut_eventtarget<'a>(&'a mut self) -> &'a mut EventTarget { - self.transmute_mut() - } -} - -impl Reflectable for AbstractEventTarget { - fn reflector<'a>(&'a self) -> &'a Reflector { - self.eventtarget().reflector() - } - - fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { - self.mut_eventtarget().mut_reflector() - } -} - impl EventTarget { pub fn new_inherited(type_id: EventTargetTypeId) -> EventTarget { EventTarget { @@ -178,15 +98,16 @@ impl EventTarget { } } - pub fn DispatchEvent(&self, abstract_self: AbstractEventTarget, event: AbstractEvent) -> Fallible<bool> { + pub fn DispatchEvent(&self, abstract_self: &JS<EventTarget>, + event: &mut JS<Event>) -> Fallible<bool> { self.dispatch_event_with_target(abstract_self, None, event) } pub fn dispatch_event_with_target(&self, - abstract_self: AbstractEventTarget, - abstract_target: Option<AbstractEventTarget>, - event: AbstractEvent) -> Fallible<bool> { - if event.event().dispatching || !event.event().initialized { + abstract_self: &JS<EventTarget>, + abstract_target: Option<JS<EventTarget>>, + event: &mut JS<Event>) -> Fallible<bool> { + if event.get().dispatching || !event.get().initialized { return Err(InvalidState); } Ok(dispatch_event(abstract_self, abstract_target, event)) diff --git a/src/components/script/dom/formdata.rs b/src/components/script/dom/formdata.rs index b446c44a7d7..3beb7e996aa 100644 --- a/src/components/script/dom/formdata.rs +++ b/src/components/script/dom/formdata.rs @@ -4,27 +4,30 @@ use dom::bindings::utils::{Fallible, Reflectable, Reflector, reflect_dom_object}; use dom::bindings::codegen::FormDataBinding; +use dom::bindings::js::JS; use dom::blob::Blob; -use dom::node::AbstractNode; +use dom::htmlformelement::HTMLFormElement; use dom::window::Window; use servo_util::str::DOMString; use std::hashmap::HashMap; +#[deriving(Encodable)] enum FormDatum { StringData(DOMString), - BlobData { blob: @mut Blob, name: DOMString } + BlobData { blob: JS<Blob>, name: DOMString } } +#[deriving(Encodable)] pub struct FormData { data: HashMap<DOMString, FormDatum>, reflector_: Reflector, - window: @mut Window, - form: Option<AbstractNode> + window: JS<Window>, + form: Option<JS<HTMLFormElement>> } impl FormData { - pub fn new_inherited(form: Option<AbstractNode>, window: @mut Window) -> FormData { + pub fn new_inherited(form: Option<JS<HTMLFormElement>>, window: JS<Window>) -> FormData { FormData { data: HashMap::new(), reflector_: Reflector::new(), @@ -33,18 +36,18 @@ impl FormData { } } - pub fn new(form: Option<AbstractNode>, window: @mut Window) -> @mut FormData { - reflect_dom_object(@mut FormData::new_inherited(form, window), window, FormDataBinding::Wrap) + pub fn new(form: Option<JS<HTMLFormElement>>, window: &JS<Window>) -> JS<FormData> { + reflect_dom_object(~FormData::new_inherited(form, window.clone()), window.get(), FormDataBinding::Wrap) } - pub fn Constructor(window: @mut Window, form: Option<AbstractNode>) - -> Fallible<@mut FormData> { + pub fn Constructor(window: &JS<Window>, form: Option<JS<HTMLFormElement>>) + -> Fallible<JS<FormData>> { Ok(FormData::new(form, window)) } - pub fn Append(&mut self, name: DOMString, value: @mut Blob, filename: Option<DOMString>) { + pub fn Append(&mut self, name: DOMString, value: &JS<Blob>, filename: Option<DOMString>) { let blob = BlobData { - blob: value, + blob: value.clone(), name: filename.unwrap_or(~"default") }; self.data.insert(name.clone(), blob); diff --git a/src/components/script/dom/htmlanchorelement.rs b/src/components/script/dom/htmlanchorelement.rs index d398a8cbe03..4b4bcf7c115 100644 --- a/src/components/script/dom/htmlanchorelement.rs +++ b/src/components/script/dom/htmlanchorelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLAnchorElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLAnchorElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLAnchorElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLAnchorElement { htmlelement: HTMLElement } +impl HTMLAnchorElementDerived for EventTarget { + fn is_htmlanchorelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLAnchorElementTypeId)) => true, + _ => false + } + } +} + impl HTMLAnchorElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLAnchorElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLAnchorElement { HTMLAnchorElement { htmlelement: HTMLElement::new_inherited(HTMLAnchorElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLAnchorElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLAnchorElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLAnchorElement> { + let element = HTMLAnchorElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLAnchorElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlappletelement.rs b/src/components/script/dom/htmlappletelement.rs index babaeaaf1f0..463414890c8 100644 --- a/src/components/script/dom/htmlappletelement.rs +++ b/src/components/script/dom/htmlappletelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLAppletElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLAppletElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLAppletElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLAppletElement { htmlelement: HTMLElement } +impl HTMLAppletElementDerived for EventTarget { + fn is_htmlappletelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLAppletElementTypeId)) => true, + _ => false + } + } +} + impl HTMLAppletElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLAppletElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLAppletElement { HTMLAppletElement { htmlelement: HTMLElement::new_inherited(HTMLAppletElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLAppletElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLAppletElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLAppletElement> { + let element = HTMLAppletElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLAppletElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlareaelement.rs b/src/components/script/dom/htmlareaelement.rs index 3d80090d2c4..91d89feed00 100644 --- a/src/components/script/dom/htmlareaelement.rs +++ b/src/components/script/dom/htmlareaelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLAreaElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLAreaElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLAreaElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLAreaElement { htmlelement: HTMLElement } +impl HTMLAreaElementDerived for EventTarget { + fn is_htmlareaelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLAreaElementTypeId)) => true, + _ => false + } + } +} + impl HTMLAreaElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLAreaElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLAreaElement { HTMLAreaElement { htmlelement: HTMLElement::new_inherited(HTMLAreaElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLAreaElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLAreaElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLAreaElement> { + let element = HTMLAreaElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLAreaElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlaudioelement.rs b/src/components/script/dom/htmlaudioelement.rs index 6e753318cb7..0575d3a49f2 100644 --- a/src/components/script/dom/htmlaudioelement.rs +++ b/src/components/script/dom/htmlaudioelement.rs @@ -3,25 +3,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLAudioElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLAudioElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLAudioElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlmediaelement::HTMLMediaElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLAudioElement { htmlmediaelement: HTMLMediaElement } +impl HTMLAudioElementDerived for EventTarget { + fn is_htmlaudioelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLAudioElementTypeId)) => true, + _ => false + } + } +} + impl HTMLAudioElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLAudioElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLAudioElement { HTMLAudioElement { htmlmediaelement: HTMLMediaElement::new_inherited(HTMLAudioElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLAudioElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLAudioElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLAudioElement> { + let element = HTMLAudioElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLAudioElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlbaseelement.rs b/src/components/script/dom/htmlbaseelement.rs index cf71f76dfbd..4384d620e93 100644 --- a/src/components/script/dom/htmlbaseelement.rs +++ b/src/components/script/dom/htmlbaseelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLBaseElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLBaseElementDerived; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLBaseElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLBaseElement { htmlelement: HTMLElement } +impl HTMLBaseElementDerived for EventTarget { + fn is_htmlbaseelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLBaseElementTypeId)) => true, + _ => false + } + } +} + impl HTMLBaseElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLBaseElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLBaseElement { HTMLBaseElement { htmlelement: HTMLElement::new_inherited(HTMLBaseElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLBaseElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLBaseElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLBaseElement> { + let element = HTMLBaseElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLBaseElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlbodyelement.rs b/src/components/script/dom/htmlbodyelement.rs index 32d133f6760..a12a0dcf68f 100644 --- a/src/components/script/dom/htmlbodyelement.rs +++ b/src/components/script/dom/htmlbodyelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLBodyElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLBodyElementDerived; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLBodyElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLBodyElement { htmlelement: HTMLElement } +impl HTMLBodyElementDerived for EventTarget { + fn is_htmlbodyelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLBodyElementTypeId)) => true, + _ => false + } + } +} + impl HTMLBodyElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLBodyElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLBodyElement { HTMLBodyElement { htmlelement: HTMLElement::new_inherited(HTMLBodyElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLBodyElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLBodyElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLBodyElement> { + let element = HTMLBodyElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLBodyElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlbrelement.rs b/src/components/script/dom/htmlbrelement.rs index 67462d28abb..9da6651455d 100644 --- a/src/components/script/dom/htmlbrelement.rs +++ b/src/components/script/dom/htmlbrelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLBRElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLBRElementDerived; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLBRElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLBRElement { htmlelement: HTMLElement, } +impl HTMLBRElementDerived for EventTarget { + fn is_htmlbrelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLBRElementTypeId)) => true, + _ => false + } + } +} + impl HTMLBRElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLBRElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLBRElement { HTMLBRElement { htmlelement: HTMLElement::new_inherited(HTMLBRElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLBRElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLBRElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLBRElement> { + let element = HTMLBRElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLBRElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlbuttonelement.rs b/src/components/script/dom/htmlbuttonelement.rs index 4847ce12394..83662da0340 100644 --- a/src/components/script/dom/htmlbuttonelement.rs +++ b/src/components/script/dom/htmlbuttonelement.rs @@ -3,28 +3,42 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLButtonElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLButtonElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLButtonElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::htmlformelement::HTMLFormElement; +use dom::node::{Node, ElementNodeTypeId}; use dom::validitystate::ValidityState; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLButtonElement { htmlelement: HTMLElement } +impl HTMLButtonElementDerived for EventTarget { + fn is_htmlbuttonelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLButtonElementTypeId)) => true, + _ => false + } + } +} + impl HTMLButtonElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLButtonElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLButtonElement { HTMLButtonElement { htmlelement: HTMLElement::new_inherited(HTMLButtonElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLButtonElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLButtonElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLButtonElement> { + let element = HTMLButtonElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLButtonElementBinding::Wrap) } } @@ -45,7 +59,7 @@ impl HTMLButtonElement { Ok(()) } - pub fn GetForm(&self) -> Option<AbstractNode> { + pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { None } @@ -120,12 +134,13 @@ impl HTMLButtonElement { pub fn SetWillValidate(&mut self, _will_validate: bool) { } - pub fn Validity(&self) -> @mut ValidityState { - let global = self.htmlelement.element.node.owner_doc().document().window; - ValidityState::new(global) + pub fn Validity(&self) -> JS<ValidityState> { + let doc = self.htmlelement.element.node.owner_doc(); + let doc = doc.get(); + ValidityState::new(&doc.window) } - pub fn SetValidity(&mut self, _validity: @mut ValidityState) { + pub fn SetValidity(&mut self, _validity: JS<ValidityState>) { } pub fn ValidationMessage(&self) -> DOMString { diff --git a/src/components/script/dom/htmlcanvaselement.rs b/src/components/script/dom/htmlcanvaselement.rs index dcc75ea73f1..199f4ad8c5b 100644 --- a/src/components/script/dom/htmlcanvaselement.rs +++ b/src/components/script/dom/htmlcanvaselement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLCanvasElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLCanvasElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::{ErrorResult}; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLCanvasElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLCanvasElement { htmlelement: HTMLElement, } +impl HTMLCanvasElementDerived for EventTarget { + fn is_htmlcanvaselement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLCanvasElementTypeId)) => true, + _ => false + } + } +} + impl HTMLCanvasElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLCanvasElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLCanvasElement { HTMLCanvasElement { htmlelement: HTMLElement::new_inherited(HTMLCanvasElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLCanvasElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLCanvasElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLCanvasElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlcollection.rs b/src/components/script/dom/htmlcollection.rs index 32cdd52280c..f14ecd05db7 100644 --- a/src/components/script/dom/htmlcollection.rs +++ b/src/components/script/dom/htmlcollection.rs @@ -3,9 +3,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLCollectionBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::Fallible; -use dom::node::AbstractNode; +use dom::element::Element; use dom::window::Window; use servo_util::str::DOMString; @@ -13,14 +14,15 @@ use js::jsapi::{JSObject, JSContext}; use std::ptr; +#[deriving(Encodable)] pub struct HTMLCollection { - elements: ~[AbstractNode], + elements: ~[JS<Element>], reflector_: Reflector, - window: @mut Window, + window: JS<Window>, } impl HTMLCollection { - pub fn new_inherited(window: @mut Window, elements: ~[AbstractNode]) -> HTMLCollection { + pub fn new_inherited(window: JS<Window>, elements: ~[JS<Element>]) -> HTMLCollection { HTMLCollection { elements: elements, reflector_: Reflector::new(), @@ -28,18 +30,18 @@ impl HTMLCollection { } } - pub fn new(window: @mut Window, elements: ~[AbstractNode]) -> @mut HTMLCollection { - reflect_dom_object(@mut HTMLCollection::new_inherited(window, elements), - window, HTMLCollectionBinding::Wrap) + pub fn new(window: &JS<Window>, elements: ~[JS<Element>]) -> JS<HTMLCollection> { + reflect_dom_object(~HTMLCollection::new_inherited(window.clone(), elements), + window.get(), HTMLCollectionBinding::Wrap) } pub fn Length(&self) -> u32 { self.elements.len() as u32 } - pub fn Item(&self, index: u32) -> Option<AbstractNode> { + pub fn Item(&self, index: u32) -> Option<JS<Element>> { if index < self.Length() { - Some(self.elements[index]) + Some(self.elements[index].clone()) } else { None } @@ -49,7 +51,7 @@ impl HTMLCollection { Ok(ptr::null()) } - pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<AbstractNode> { + pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Element>> { *found = true; self.Item(index) } diff --git a/src/components/script/dom/htmldataelement.rs b/src/components/script/dom/htmldataelement.rs index cd8a99bd282..59eb30945c6 100644 --- a/src/components/script/dom/htmldataelement.rs +++ b/src/components/script/dom/htmldataelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLDataElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLDataElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLDataElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLDataElement { htmlelement: HTMLElement } +impl HTMLDataElementDerived for EventTarget { + fn is_htmldataelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLDataElementTypeId)) => true, + _ => false + } + } +} + impl HTMLDataElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLDataElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLDataElement { HTMLDataElement { htmlelement: HTMLElement::new_inherited(HTMLDataElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLDataElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLDataElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLDataElement> { + let element = HTMLDataElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLDataElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmldatalistelement.rs b/src/components/script/dom/htmldatalistelement.rs index 41665545a48..6cd888029c2 100644 --- a/src/components/script/dom/htmldatalistelement.rs +++ b/src/components/script/dom/htmldatalistelement.rs @@ -3,33 +3,47 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLDataListElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLDataListElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLDataListElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlcollection::HTMLCollection; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLDataListElement { htmlelement: HTMLElement } +impl HTMLDataListElementDerived for EventTarget { + fn is_htmldatalistelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLDataListElementTypeId)) => true, + _ => false + } + } +} + impl HTMLDataListElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLDataListElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLDataListElement { HTMLDataListElement { htmlelement: HTMLElement::new_inherited(HTMLDataListElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLDataListElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLDataListElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLDataListElement> { + let element = HTMLDataListElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLDataListElementBinding::Wrap) } } impl HTMLDataListElement { - pub fn Options(&self) -> @mut HTMLCollection { - let window = self.htmlelement.element.node.owner_doc().document().window; - HTMLCollection::new(window, ~[]) + pub fn Options(&self) -> JS<HTMLCollection> { + let doc = self.htmlelement.element.node.owner_doc(); + let doc = doc.get(); + HTMLCollection::new(&doc.window, ~[]) } } diff --git a/src/components/script/dom/htmldirectoryelement.rs b/src/components/script/dom/htmldirectoryelement.rs index 137aaffd1a2..6847d7b1cf3 100644 --- a/src/components/script/dom/htmldirectoryelement.rs +++ b/src/components/script/dom/htmldirectoryelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLDirectoryElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLDirectoryElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLDirectoryElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLDirectoryElement { htmlelement: HTMLElement } +impl HTMLDirectoryElementDerived for EventTarget { + fn is_htmldirectoryelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLDirectoryElementTypeId)) => true, + _ => false + } + } +} + impl HTMLDirectoryElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLDirectoryElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLDirectoryElement { HTMLDirectoryElement { htmlelement: HTMLElement::new_inherited(HTMLDirectoryElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLDirectoryElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLDirectoryElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLDirectoryElement> { + let element = HTMLDirectoryElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLDirectoryElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmldivelement.rs b/src/components/script/dom/htmldivelement.rs index 3e09183e5bd..3220a7c6e24 100644 --- a/src/components/script/dom/htmldivelement.rs +++ b/src/components/script/dom/htmldivelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLDivElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLDivElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLDivElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLDivElement { htmlelement: HTMLElement } +impl HTMLDivElementDerived for EventTarget { + fn is_htmldivelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLDivElementTypeId)) => true, + _ => false + } + } +} + impl HTMLDivElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLDivElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLDivElement { HTMLDivElement { htmlelement: HTMLElement::new_inherited(HTMLDivElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLDivElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLDivElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLDivElement> { + let element = HTMLDivElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLDivElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmldlistelement.rs b/src/components/script/dom/htmldlistelement.rs index da9576fcb07..c1394c37bd8 100644 --- a/src/components/script/dom/htmldlistelement.rs +++ b/src/components/script/dom/htmldlistelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLDListElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLDListElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLDListElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLDListElement { htmlelement: HTMLElement } +impl HTMLDListElementDerived for EventTarget { + fn is_htmldlistelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLDListElementTypeId)) => true, + _ => false + } + } +} + impl HTMLDListElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLDListElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLDListElement { HTMLDListElement { htmlelement: HTMLElement::new_inherited(HTMLDListElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLDListElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLDListElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLDListElement> { + let element = HTMLDListElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLDListElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmldocument.rs b/src/components/script/dom/htmldocument.rs deleted file mode 100644 index 8297fd3e90c..00000000000 --- a/src/components/script/dom/htmldocument.rs +++ /dev/null @@ -1,86 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use dom::bindings::codegen::HTMLDocumentBinding; -use dom::bindings::utils::{Reflectable, Reflector, Traceable}; -use dom::document::{AbstractDocument, Document, HTML}; -use dom::htmlcollection::HTMLCollection; -use dom::window::Window; -use servo_util::namespace::Null; - -use extra::url::Url; -use js::jsapi::JSTracer; - -pub struct HTMLDocument { - parent: Document -} - -impl HTMLDocument { - pub fn new_inherited(window: @mut Window, url: Option<Url>) -> HTMLDocument { - HTMLDocument { - parent: Document::new_inherited(window, url, HTML, None) - } - } - - pub fn new(window: @mut Window, url: Option<Url>) -> AbstractDocument { - let document = HTMLDocument::new_inherited(window, url); - Document::reflect_document(@mut document, window, HTMLDocumentBinding::Wrap) - } -} - -impl HTMLDocument { - pub fn Images(&self) -> @mut HTMLCollection { - self.parent.createHTMLCollection(|elem| "img" == elem.tag_name) - } - - pub fn Embeds(&self) -> @mut HTMLCollection { - self.parent.createHTMLCollection(|elem| "embed" == elem.tag_name) - } - - pub fn Plugins(&self) -> @mut HTMLCollection { - self.Embeds() - } - - pub fn Links(&self) -> @mut HTMLCollection { - self.parent.createHTMLCollection(|elem| { - ("a" == elem.tag_name || "area" == elem.tag_name) && - elem.get_attribute(Null, "href").is_some() - }) - } - - pub fn Forms(&self) -> @mut HTMLCollection { - self.parent.createHTMLCollection(|elem| "form" == elem.tag_name) - } - - pub fn Scripts(&self) -> @mut HTMLCollection { - self.parent.createHTMLCollection(|elem| "script" == elem.tag_name) - } - - pub fn Anchors(&self) -> @mut HTMLCollection { - self.parent.createHTMLCollection(|elem| { - "a" == elem.tag_name && elem.get_attribute(Null, "name").is_some() - }) - } - - pub fn Applets(&self) -> @mut HTMLCollection { - // FIXME: This should be return OBJECT elements containing applets. - self.parent.createHTMLCollection(|elem| "applet" == elem.tag_name) - } -} - -impl Reflectable for HTMLDocument { - fn reflector<'a>(&'a self) -> &'a Reflector { - self.parent.reflector() - } - - fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { - self.parent.mut_reflector() - } -} - -impl Traceable for HTMLDocument { - fn trace(&self, tracer: *mut JSTracer) { - self.parent.trace(tracer); - } -} diff --git a/src/components/script/dom/htmlelement.rs b/src/components/script/dom/htmlelement.rs index 06ab085f945..55c7c1141b6 100644 --- a/src/components/script/dom/htmlelement.rs +++ b/src/components/script/dom/htmlelement.rs @@ -3,29 +3,42 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLElementBinding; -use dom::bindings::utils::{Fallible, ErrorResult}; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLElementDerived; +use dom::bindings::js::JS; +use dom::bindings::utils::{ErrorResult, Fallible}; +use dom::document::Document; use dom::element::{Element, ElementTypeId, HTMLElementTypeId}; -use dom::node::{AbstractNode, Node}; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::node::{Node, ElementNodeTypeId}; use js::jsapi::{JSContext, JSVal}; use js::JSVAL_NULL; use servo_util::namespace; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLElement { element: Element } +impl HTMLElementDerived for EventTarget { + fn is_htmlelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(_)) => true, + _ => false + } + } +} + impl HTMLElement { - pub fn new_inherited(type_id: ElementTypeId, tag_name: DOMString, document: AbstractDocument) -> HTMLElement { + pub fn new_inherited(type_id: ElementTypeId, tag_name: DOMString, document: JS<Document>) -> HTMLElement { HTMLElement { element: Element::new_inherited(type_id, tag_name, namespace::HTML, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLElement::new_inherited(HTMLElementTypeId, localName, document); - Node::reflect_node(@mut element, document, HTMLElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLElement> { + let element = HTMLElement::new_inherited(HTMLElementTypeId, localName, document.clone()); + Node::reflect_node(~element, document, HTMLElementBinding::Wrap) } } @@ -134,7 +147,7 @@ impl HTMLElement { pub fn SetClassName(&self, _class: DOMString) { } - pub fn GetOffsetParent(&self) -> Option<AbstractNode> { + pub fn GetOffsetParent(&self) -> Option<JS<Element>> { None } diff --git a/src/components/script/dom/htmlembedelement.rs b/src/components/script/dom/htmlembedelement.rs index a7b5609bfd2..d2da7f540d1 100644 --- a/src/components/script/dom/htmlembedelement.rs +++ b/src/components/script/dom/htmlembedelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLEmbedElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLEmbedElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLEmbedElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLEmbedElement { htmlelement: HTMLElement } +impl HTMLEmbedElementDerived for EventTarget { + fn is_htmlembedelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLEmbedElementTypeId)) => true, + _ => false + } + } +} + impl HTMLEmbedElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLEmbedElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLEmbedElement { HTMLEmbedElement { htmlelement: HTMLElement::new_inherited(HTMLEmbedElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLEmbedElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLEmbedElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLEmbedElement> { + let element = HTMLEmbedElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLEmbedElementBinding::Wrap) } } @@ -76,7 +89,7 @@ impl HTMLEmbedElement { Ok(()) } - pub fn GetSVGDocument(&self) -> Option<AbstractDocument> { + pub fn GetSVGDocument(&self) -> Option<JS<Document>> { None } } diff --git a/src/components/script/dom/htmlfieldsetelement.rs b/src/components/script/dom/htmlfieldsetelement.rs index a9939b4c4c9..a67e3a8bc91 100644 --- a/src/components/script/dom/htmlfieldsetelement.rs +++ b/src/components/script/dom/htmlfieldsetelement.rs @@ -3,29 +3,43 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLFieldSetElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLFieldSetElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLFieldSetElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::htmlformelement::HTMLFormElement; use dom::htmlcollection::HTMLCollection; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use dom::validitystate::ValidityState; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLFieldSetElement { htmlelement: HTMLElement } +impl HTMLFieldSetElementDerived for EventTarget { + fn is_htmlfieldsetelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLFieldSetElementTypeId)) => true, + _ => false + } + } +} + impl HTMLFieldSetElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLFieldSetElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLFieldSetElement { HTMLFieldSetElement { htmlelement: HTMLElement::new_inherited(HTMLFieldSetElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLFieldSetElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLFieldSetElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLFieldSetElement> { + let element = HTMLFieldSetElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLFieldSetElementBinding::Wrap) } } @@ -38,7 +52,7 @@ impl HTMLFieldSetElement { Ok(()) } - pub fn GetForm(&self) -> Option<AbstractNode> { + pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { None } @@ -54,18 +68,20 @@ impl HTMLFieldSetElement { ~"" } - pub fn Elements(&self) -> @mut HTMLCollection { - let window = self.htmlelement.element.node.owner_doc().document().window; - HTMLCollection::new(window, ~[]) + pub fn Elements(&self) -> JS<HTMLCollection> { + let doc = self.htmlelement.element.node.owner_doc(); + let doc = doc.get(); + HTMLCollection::new(&doc.window, ~[]) } pub fn WillValidate(&self) -> bool { false } - pub fn Validity(&self) -> @mut ValidityState { - let global = self.htmlelement.element.node.owner_doc().document().window; - ValidityState::new(global) + pub fn Validity(&self) -> JS<ValidityState> { + let doc = self.htmlelement.element.node.owner_doc(); + let doc = doc.get(); + ValidityState::new(&doc.window) } pub fn ValidationMessage(&self) -> DOMString { diff --git a/src/components/script/dom/htmlfontelement.rs b/src/components/script/dom/htmlfontelement.rs index b3ccf1a6f14..024d546cc41 100644 --- a/src/components/script/dom/htmlfontelement.rs +++ b/src/components/script/dom/htmlfontelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLFontElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLFontElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLFontElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLFontElement { htmlelement: HTMLElement } +impl HTMLFontElementDerived for EventTarget { + fn is_htmlfontelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLFontElementTypeId)) => true, + _ => false + } + } +} + impl HTMLFontElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLFontElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLFontElement { HTMLFontElement { htmlelement: HTMLElement::new_inherited(HTMLFontElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLFontElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLFontElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLFontElement> { + let element = HTMLFontElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLFontElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlformelement.rs b/src/components/script/dom/htmlformelement.rs index 554cabd6090..d213c68dbdb 100644 --- a/src/components/script/dom/htmlformelement.rs +++ b/src/components/script/dom/htmlformelement.rs @@ -3,28 +3,41 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLFormElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; -use dom::element::HTMLFormElementTypeId; +use dom::document::Document; +use dom::element::{Element, HTMLFormElementTypeId}; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlcollection::HTMLCollection; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLFormElement { htmlelement: HTMLElement } +impl HTMLFormElementDerived for EventTarget { + fn is_htmlformelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLFormElementTypeId)) => true, + _ => false + } + } +} + impl HTMLFormElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLFormElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLFormElement { HTMLFormElement { htmlelement: HTMLElement::new_inherited(HTMLFormElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLFormElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLFormElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLFormElement> { + let element = HTMLFormElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLFormElementBinding::Wrap) } } @@ -101,9 +114,10 @@ impl HTMLFormElement { Ok(()) } - pub fn Elements(&self) -> @mut HTMLCollection { - let window = self.htmlelement.element.node.owner_doc().document().window; - HTMLCollection::new(window, ~[]) + pub fn Elements(&self) -> JS<HTMLCollection> { + let doc = self.htmlelement.element.node.owner_doc(); + let doc = doc.get(); + HTMLCollection::new(&doc.window, ~[]) } pub fn Length(&self) -> i32 { @@ -121,7 +135,7 @@ impl HTMLFormElement { false } - pub fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> AbstractNode { + pub fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> JS<Element> { fail!("Not implemented.") } } diff --git a/src/components/script/dom/htmlframeelement.rs b/src/components/script/dom/htmlframeelement.rs index 25e6feae0b6..26486c7cceb 100644 --- a/src/components/script/dom/htmlframeelement.rs +++ b/src/components/script/dom/htmlframeelement.rs @@ -3,28 +3,41 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLFrameElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLFrameElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLFrameElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use dom::windowproxy::WindowProxy; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLFrameElement { htmlelement: HTMLElement } +impl HTMLFrameElementDerived for EventTarget { + fn is_htmlframeelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLFrameElementTypeId)) => true, + _ => false + } + } +} + impl HTMLFrameElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLFrameElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLFrameElement { HTMLFrameElement { htmlelement: HTMLElement::new_inherited(HTMLFrameElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLFrameElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLFrameElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLFrameElement> { + let element = HTMLFrameElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLFrameElementBinding::Wrap) } } @@ -77,11 +90,11 @@ impl HTMLFrameElement { Ok(()) } - pub fn GetContentDocument(&self) -> Option<AbstractDocument> { + pub fn GetContentDocument(&self) -> Option<JS<Document>> { None } - pub fn GetContentWindow(&self) -> Option<@mut WindowProxy> { + pub fn GetContentWindow(&self) -> Option<JS<WindowProxy>> { None } diff --git a/src/components/script/dom/htmlframesetelement.rs b/src/components/script/dom/htmlframesetelement.rs index 5b40a4b5fe1..252c17709c5 100644 --- a/src/components/script/dom/htmlframesetelement.rs +++ b/src/components/script/dom/htmlframesetelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLFrameSetElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLFrameSetElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLFrameSetElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLFrameSetElement { htmlelement: HTMLElement } +impl HTMLFrameSetElementDerived for EventTarget { + fn is_htmlframesetelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLFrameSetElementTypeId)) => true, + _ => false + } + } +} + impl HTMLFrameSetElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLFrameSetElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLFrameSetElement { HTMLFrameSetElement { htmlelement: HTMLElement::new_inherited(HTMLFrameSetElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLFrameSetElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLFrameSetElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLFrameSetElement> { + let element = HTMLFrameSetElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLFrameSetElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlheadelement.rs b/src/components/script/dom/htmlheadelement.rs index f7459d0ac4f..91266180c27 100644 --- a/src/components/script/dom/htmlheadelement.rs +++ b/src/components/script/dom/htmlheadelement.rs @@ -3,25 +3,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLHeadElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLHeadElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLHeadElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLHeadElement { htmlelement: HTMLElement } +impl HTMLHeadElementDerived for EventTarget { + fn is_htmlheadelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLHeadElementTypeId)) => true, + _ => false + } + } +} + impl HTMLHeadElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLHeadElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLHeadElement { HTMLHeadElement { htmlelement: HTMLElement::new_inherited(HTMLHeadElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLHeadElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLHeadElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLHeadElement> { + let element = HTMLHeadElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLHeadElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlheadingelement.rs b/src/components/script/dom/htmlheadingelement.rs index f15075f30cd..ecae9910b6d 100644 --- a/src/components/script/dom/htmlheadingelement.rs +++ b/src/components/script/dom/htmlheadingelement.rs @@ -3,12 +3,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLHeadingElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLHeadingElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLHeadingElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub enum HeadingLevel { Heading1, Heading2, @@ -18,22 +22,32 @@ pub enum HeadingLevel { Heading6, } +#[deriving(Encodable)] pub struct HTMLHeadingElement { htmlelement: HTMLElement, level: HeadingLevel, } +impl HTMLHeadingElementDerived for EventTarget { + fn is_htmlheadingelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLHeadingElementTypeId)) => true, + _ => false + } + } +} + impl HTMLHeadingElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument, level: HeadingLevel) -> HTMLHeadingElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>, level: HeadingLevel) -> HTMLHeadingElement { HTMLHeadingElement { htmlelement: HTMLElement::new_inherited(HTMLHeadingElementTypeId, localName, document), level: level, } } - pub fn new(localName: DOMString, document: AbstractDocument, level: HeadingLevel) -> AbstractNode { - let element = HTMLHeadingElement::new_inherited(localName, document, level); - Node::reflect_node(@mut element, document, HTMLHeadingElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>, level: HeadingLevel) -> JS<HTMLHeadingElement> { + let element = HTMLHeadingElement::new_inherited(localName, document.clone(), level); + Node::reflect_node(~element, document, HTMLHeadingElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlhrelement.rs b/src/components/script/dom/htmlhrelement.rs index 1a239a30049..557a423787c 100644 --- a/src/components/script/dom/htmlhrelement.rs +++ b/src/components/script/dom/htmlhrelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLHRElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLHRElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLHRElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLHRElement { htmlelement: HTMLElement, } +impl HTMLHRElementDerived for EventTarget { + fn is_htmlhrelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLHRElementTypeId)) => true, + _ => false + } + } +} + impl HTMLHRElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLHRElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLHRElement { HTMLHRElement { htmlelement: HTMLElement::new_inherited(HTMLHRElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLHRElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLHRElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLHRElement> { + let element = HTMLHRElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLHRElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlhtmlelement.rs b/src/components/script/dom/htmlhtmlelement.rs index 2da7b45f40b..dcadd267abb 100644 --- a/src/components/script/dom/htmlhtmlelement.rs +++ b/src/components/script/dom/htmlhtmlelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLHtmlElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLHtmlElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLHtmlElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLHtmlElement { htmlelement: HTMLElement } +impl HTMLHtmlElementDerived for EventTarget { + fn is_htmlhtmlelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLHtmlElementTypeId)) => true, + _ => false + } + } +} + impl HTMLHtmlElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLHtmlElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLHtmlElement { HTMLHtmlElement { htmlelement: HTMLElement::new_inherited(HTMLHtmlElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLHtmlElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLHtmlElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLHtmlElement> { + let element = HTMLHtmlElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLHtmlElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs index ca38c069d14..92e0c63dfc7 100644 --- a/src/components/script/dom/htmliframeelement.rs +++ b/src/components/script/dom/htmliframeelement.rs @@ -3,17 +3,21 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLIFrameElementBinding; +use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementDerived}; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLIframeElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use dom::windowproxy::WindowProxy; use servo_util::str::DOMString; use extra::url::Url; use servo_msg::constellation_msg::{PipelineId, SubpageId}; use std::ascii::StrAsciiExt; +use extra::serialize::{Encoder, Encodable}; enum SandboxAllowance { AllowNothing = 0x00, @@ -25,13 +29,33 @@ enum SandboxAllowance { AllowPopups = 0x20 } +#[deriving(Encodable)] pub struct HTMLIFrameElement { htmlelement: HTMLElement, - frame: Option<Url>, + extra: Untraceable, size: Option<IFrameSize>, sandbox: Option<u8> } +struct Untraceable { + frame: Option<Url>, +} + +impl<S: Encoder> Encodable<S> for Untraceable { + fn encode(&self, _s: &mut S) { + } +} + +impl HTMLIFrameElementDerived for EventTarget { + fn is_htmliframeelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLIframeElementTypeId)) => true, + _ => false + } + } +} + +#[deriving(Encodable)] pub struct IFrameSize { pipeline_id: PipelineId, subpage_id: SubpageId, @@ -44,18 +68,20 @@ impl HTMLIFrameElement { } impl HTMLIFrameElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLIFrameElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLIFrameElement { HTMLIFrameElement { htmlelement: HTMLElement::new_inherited(HTMLIframeElementTypeId, localName, document), - frame: None, + extra: Untraceable { + frame: None + }, size: None, sandbox: None, } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLIFrameElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLIFrameElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLIFrameElement> { + let element = HTMLIFrameElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLIFrameElementBinding::Wrap) } } @@ -84,12 +110,13 @@ impl HTMLIFrameElement { Ok(()) } - pub fn Sandbox(&self, _abstract_self: AbstractNode) -> DOMString { + pub fn Sandbox(&self, _abstract_self: &JS<HTMLIFrameElement>) -> DOMString { self.htmlelement.element.get_string_attribute("sandbox") } - pub fn SetSandbox(&mut self, abstract_self: AbstractNode, sandbox: DOMString) { - self.htmlelement.element.set_string_attribute(abstract_self, "sandbox", + pub fn SetSandbox(&mut self, abstract_self: &JS<HTMLIFrameElement>, sandbox: DOMString) { + self.htmlelement.element.set_string_attribute(&ElementCast::from(abstract_self), + "sandbox", sandbox); } @@ -143,11 +170,11 @@ impl HTMLIFrameElement { Ok(()) } - pub fn GetContentDocument(&self) -> Option<AbstractDocument> { + pub fn GetContentDocument(&self) -> Option<JS<Document>> { None } - pub fn GetContentWindow(&self) -> Option<@mut WindowProxy> { + pub fn GetContentWindow(&self) -> Option<JS<WindowProxy>> { None } @@ -199,7 +226,7 @@ impl HTMLIFrameElement { Ok(()) } - pub fn GetSVGDocument(&self) -> Option<AbstractDocument> { + pub fn GetSVGDocument(&self) -> Option<JS<Document>> { None } } diff --git a/src/components/script/dom/htmlimageelement.rs b/src/components/script/dom/htmlimageelement.rs index 5e041572537..d2304944eeb 100644 --- a/src/components/script/dom/htmlimageelement.rs +++ b/src/components/script/dom/htmlimageelement.rs @@ -3,11 +3,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLImageElementBinding; +use dom::bindings::codegen::InheritTypes::{NodeCast, HTMLImageElementDerived}; +use dom::bindings::codegen::InheritTypes::{ElementCast}; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; -use dom::element::HTMLImageElementTypeId; +use dom::document::Document; +use dom::element::{Element, HTMLImageElementTypeId}; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId, NodeHelpers}; use extra::url::Url; use servo_util::geometry::to_px; use layout_interface::{ContentBoxQuery, ContentBoxResponse}; @@ -17,22 +21,45 @@ use servo_util::url::parse_url; use servo_util::namespace::Null; use servo_util::str::DOMString; +use extra::serialize::{Encoder, Encodable}; + +#[deriving(Encodable)] pub struct HTMLImageElement { htmlelement: HTMLElement, + extra: Untraceable, +} + +struct Untraceable { image: Option<Url>, } +impl<S: Encoder> Encodable<S> for Untraceable { + fn encode(&self, _s: &mut S) { + } +} + +impl HTMLImageElementDerived for EventTarget { + fn is_htmlimageelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLImageElementTypeId)) => true, + _ => false + } + } +} + impl HTMLImageElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLImageElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLImageElement { HTMLImageElement { htmlelement: HTMLElement::new_inherited(HTMLImageElementTypeId, localName, document), - image: None, + extra: Untraceable { + image: None, + } } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLImageElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLImageElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLImageElement> { + let element = HTMLImageElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLImageElementBinding::Wrap) } } @@ -41,12 +68,12 @@ impl HTMLImageElement { /// prefetching the image. This method must be called after `src` is changed. pub fn update_image(&mut self, image_cache: ImageCacheTask, url: Option<Url>) { let elem = &mut self.htmlelement.element; - let src_opt = elem.get_attribute(Null, "src").map(|x| x.Value()); + let src_opt = elem.get_attribute(Null, "src").map(|x| x.get().Value()); match src_opt { None => {} Some(src) => { let img_url = parse_url(src, url); - self.image = Some(img_url.clone()); + self.extra.image = Some(img_url.clone()); // inform the image cache to load this, but don't store a // handle. @@ -61,7 +88,7 @@ impl HTMLImageElement { pub fn AfterSetAttr(&mut self, name: DOMString, _value: DOMString) { if "src" == name { let document = self.htmlelement.element.node.owner_doc(); - let window = document.document().window; + let window = document.get().window.get(); let url = window.page.url.as_ref().map(|&(ref url, _)| url.clone()); self.update_image(window.image_cache_task.clone(), url); } @@ -73,7 +100,7 @@ impl HTMLImageElement { // `self.update_image()` will see the missing src attribute and return early. if "src" == name { let document = self.htmlelement.element.node.owner_doc(); - let window = document.document().window; + let window = document.get().window.get(); self.update_image(window.image_cache_task.clone(), None); } } @@ -86,13 +113,13 @@ impl HTMLImageElement { Ok(()) } - pub fn Src(&self, _abstract_self: AbstractNode) -> DOMString { + pub fn Src(&self, _abstract_self: &JS<HTMLImageElement>) -> DOMString { ~"" } - pub fn SetSrc(&mut self, abstract_self: AbstractNode, src: DOMString) -> ErrorResult { + pub fn SetSrc(&mut self, abstract_self: &JS<HTMLImageElement>, src: DOMString) -> ErrorResult { let node = &mut self.htmlelement.element; - node.set_attr(abstract_self, ~"src", src.clone()); + node.set_attr(&ElementCast::from(abstract_self), ~"src", src.clone()); Ok(()) } @@ -120,37 +147,43 @@ impl HTMLImageElement { Ok(()) } - pub fn Width(&self, abstract_self: AbstractNode) -> u32 { - let node = &self.htmlelement.element.node; - let page = node.owner_doc().document().window.page; + pub fn Width(&self, abstract_self: &JS<HTMLImageElement>) -> u32 { + let node: JS<Node> = NodeCast::from(abstract_self); + let doc = node.get().owner_doc(); + let page = doc.get().window.get().page; let (port, chan) = Chan::new(); - match page.query_layout(ContentBoxQuery(abstract_self, chan), port) { + let addr = node.to_trusted_node_address(); + match page.query_layout(ContentBoxQuery(addr, chan), port) { ContentBoxResponse(rect) => { to_px(rect.size.width) as u32 } } } - pub fn SetWidth(&mut self, abstract_self: AbstractNode, width: u32) -> ErrorResult { - let node = &mut self.htmlelement.element; - node.set_attr(abstract_self, ~"width", width.to_str()); + pub fn SetWidth(&mut self, abstract_self: &JS<HTMLImageElement>, width: u32) -> ErrorResult { + let mut elem: JS<Element> = ElementCast::from(abstract_self); + let mut elem_clone = elem.clone(); + elem.get_mut().set_attr(&mut elem_clone, ~"width", width.to_str()); Ok(()) } - pub fn Height(&self, abstract_self: AbstractNode) -> u32 { + pub fn Height(&self, abstract_self: &JS<HTMLImageElement>) -> u32 { let node = &self.htmlelement.element.node; - let page = node.owner_doc().document().window.page; + let doc = node.owner_doc(); + let page = doc.get().window.get().page; let (port, chan) = Chan::new(); - match page.query_layout(ContentBoxQuery(abstract_self, chan), port) { + let this_node: JS<Node> = NodeCast::from(abstract_self); + let addr = this_node.to_trusted_node_address(); + match page.query_layout(ContentBoxQuery(addr, chan), port) { ContentBoxResponse(rect) => { to_px(rect.size.height) as u32 } } } - pub fn SetHeight(&mut self, abstract_self: AbstractNode, height: u32) -> ErrorResult { + pub fn SetHeight(&mut self, abstract_self: &JS<HTMLImageElement>, height: u32) -> ErrorResult { let node = &mut self.htmlelement.element; - node.set_attr(abstract_self, ~"height", height.to_str()); + node.set_attr(&ElementCast::from(abstract_self), ~"height", height.to_str()); Ok(()) } diff --git a/src/components/script/dom/htmlinputelement.rs b/src/components/script/dom/htmlinputelement.rs index d2f2acd0249..426f78b3e6b 100644 --- a/src/components/script/dom/htmlinputelement.rs +++ b/src/components/script/dom/htmlinputelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLInputElementBinding; -use dom::bindings::utils::{Fallible, ErrorResult}; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLInputElementDerived; +use dom::bindings::js::JS; +use dom::bindings::utils::{ErrorResult, Fallible}; +use dom::document::Document; use dom::element::HTMLInputElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLInputElement { htmlelement: HTMLElement, } +impl HTMLInputElementDerived for EventTarget { + fn is_htmlinputelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLInputElementTypeId)) => true, + _ => false + } + } +} + impl HTMLInputElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLInputElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLInputElement { HTMLInputElement { htmlelement: HTMLElement::new_inherited(HTMLInputElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLInputElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLInputElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLInputElement> { + let element = HTMLInputElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLInputElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmllabelelement.rs b/src/components/script/dom/htmllabelelement.rs index 89cf6215ca9..e4da3eb661c 100644 --- a/src/components/script/dom/htmllabelelement.rs +++ b/src/components/script/dom/htmllabelelement.rs @@ -3,26 +3,39 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLLabelElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLLabelElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLLabelElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLLabelElement { htmlelement: HTMLElement, } +impl HTMLLabelElementDerived for EventTarget { + fn is_htmllabelelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLLabelElementTypeId)) => true, + _ => false + } + } +} + impl HTMLLabelElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLLabelElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLLabelElement { HTMLLabelElement { htmlelement: HTMLElement::new_inherited(HTMLLabelElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLLabelElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLLabelElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLLabelElement> { + let element = HTMLLabelElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLLabelElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmllegendelement.rs b/src/components/script/dom/htmllegendelement.rs index 43949db6e82..9c98a6b103a 100644 --- a/src/components/script/dom/htmllegendelement.rs +++ b/src/components/script/dom/htmllegendelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLLegendElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLLegendElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLLegendElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLLegendElement { htmlelement: HTMLElement, } +impl HTMLLegendElementDerived for EventTarget { + fn is_htmllegendelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLLegendElementTypeId)) => true, + _ => false + } + } +} + impl HTMLLegendElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLLegendElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLLegendElement { HTMLLegendElement { htmlelement: HTMLElement::new_inherited(HTMLLegendElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLLegendElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLLegendElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLLegendElement> { + let element = HTMLLegendElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLLegendElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmllielement.rs b/src/components/script/dom/htmllielement.rs index 2079df20568..79a243c7fb2 100644 --- a/src/components/script/dom/htmllielement.rs +++ b/src/components/script/dom/htmllielement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLLIElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLLIElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLLIElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLLIElement { htmlelement: HTMLElement, } +impl HTMLLIElementDerived for EventTarget { + fn is_htmllielement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLLIElementTypeId)) => true, + _ => false + } + } +} + impl HTMLLIElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLLIElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLLIElement { HTMLLIElement { htmlelement: HTMLElement::new_inherited(HTMLLIElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLLIElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLLIElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLLIElement> { + let element = HTMLLIElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLLIElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmllinkelement.rs b/src/components/script/dom/htmllinkelement.rs index d5fce888632..f8e6bdc73e7 100644 --- a/src/components/script/dom/htmllinkelement.rs +++ b/src/components/script/dom/htmllinkelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLLinkElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLLinkElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLLinkElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLLinkElement { htmlelement: HTMLElement, } +impl HTMLLinkElementDerived for EventTarget { + fn is_htmllinkelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLLinkElementTypeId)) => true, + _ => false + } + } +} + impl HTMLLinkElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLLinkElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLLinkElement { HTMLLinkElement { htmlelement: HTMLElement::new_inherited(HTMLLinkElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLLinkElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLLinkElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLLinkElement> { + let element = HTMLLinkElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLLinkElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlmainelement.rs b/src/components/script/dom/htmlmainelement.rs index 550e0470efb..b0fc11c2781 100644 --- a/src/components/script/dom/htmlmainelement.rs +++ b/src/components/script/dom/htmlmainelement.rs @@ -3,25 +3,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLMainElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLMainElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLMainElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLMainElement { htmlelement: HTMLElement } +impl HTMLMainElementDerived for EventTarget { + fn is_htmlmainelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLMainElementTypeId)) => true, + _ => false + } + } +} + impl HTMLMainElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLMainElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLMainElement { HTMLMainElement { htmlelement: HTMLElement::new_inherited(HTMLMainElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLMainElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLMainElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLMainElement> { + let element = HTMLMainElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLMainElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlmapelement.rs b/src/components/script/dom/htmlmapelement.rs index d61278ce070..fcb09820fb1 100644 --- a/src/components/script/dom/htmlmapelement.rs +++ b/src/components/script/dom/htmlmapelement.rs @@ -3,28 +3,41 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLMapElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLMapElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::htmlcollection::HTMLCollection; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLMapElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::htmlcollection::HTMLCollection; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLMapElement { htmlelement: HTMLElement } +impl HTMLMapElementDerived for EventTarget { + fn is_htmlmapelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLMapElementTypeId)) => true, + _ => false + } + } +} + impl HTMLMapElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLMapElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLMapElement { HTMLMapElement { htmlelement: HTMLElement::new_inherited(HTMLMapElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLMapElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLMapElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLMapElement> { + let element = HTMLMapElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLMapElementBinding::Wrap) } } @@ -37,8 +50,9 @@ impl HTMLMapElement { Ok(()) } - pub fn Areas(&self) -> @mut HTMLCollection { - let window = self.htmlelement.element.node.owner_doc().document().window; - HTMLCollection::new(window, ~[]) + pub fn Areas(&self) -> JS<HTMLCollection> { + let doc = self.htmlelement.element.node.owner_doc(); + let doc = doc.get(); + HTMLCollection::new(&doc.window, ~[]) } } diff --git a/src/components/script/dom/htmlmediaelement.rs b/src/components/script/dom/htmlmediaelement.rs index 371374c4859..d28b38085de 100644 --- a/src/components/script/dom/htmlmediaelement.rs +++ b/src/components/script/dom/htmlmediaelement.rs @@ -2,18 +2,33 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::js::JS; +use dom::bindings::codegen::InheritTypes::HTMLMediaElementDerived; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; -use dom::element::ElementTypeId; +use dom::document::Document; +use dom::element::{ElementTypeId, HTMLAudioElementTypeId, HTMLVideoElementTypeId}; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; +use dom::node::ElementNodeTypeId; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLMediaElement { htmlelement: HTMLElement, } +impl HTMLMediaElementDerived for EventTarget { + fn is_htmlmediaelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLVideoElementTypeId)) | + NodeTargetTypeId(ElementNodeTypeId(HTMLAudioElementTypeId)) => true, + _ => false + } + } +} + impl HTMLMediaElement { - pub fn new_inherited(type_id: ElementTypeId, tag_name: DOMString, document: AbstractDocument) -> HTMLMediaElement { + pub fn new_inherited(type_id: ElementTypeId, tag_name: DOMString, document: JS<Document>) -> HTMLMediaElement { HTMLMediaElement { htmlelement: HTMLElement::new_inherited(type_id, tag_name, document) } diff --git a/src/components/script/dom/htmlmetaelement.rs b/src/components/script/dom/htmlmetaelement.rs index 254fe4c94f4..94639c05d0e 100644 --- a/src/components/script/dom/htmlmetaelement.rs +++ b/src/components/script/dom/htmlmetaelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLMetaElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLMetaElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLMetaElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLMetaElement { htmlelement: HTMLElement, } +impl HTMLMetaElementDerived for EventTarget { + fn is_htmlmetaelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLMetaElementTypeId)) => true, + _ => false + } + } +} + impl HTMLMetaElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLMetaElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLMetaElement { HTMLMetaElement { htmlelement: HTMLElement::new_inherited(HTMLMetaElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLMetaElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLMetaElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLMetaElement> { + let element = HTMLMetaElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLMetaElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlmeterelement.rs b/src/components/script/dom/htmlmeterelement.rs index 3e179fa1743..ac7e4e04736 100644 --- a/src/components/script/dom/htmlmeterelement.rs +++ b/src/components/script/dom/htmlmeterelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLMeterElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLMeterElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLMeterElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLMeterElement { htmlelement: HTMLElement } +impl HTMLMeterElementDerived for EventTarget { + fn is_htmlmeterelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLMeterElementTypeId)) => true, + _ => false + } + } +} + impl HTMLMeterElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLMeterElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLMeterElement { HTMLMeterElement { htmlelement: HTMLElement::new_inherited(HTMLMeterElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLMeterElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLMeterElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLMeterElement> { + let element = HTMLMeterElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLMeterElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlmodelement.rs b/src/components/script/dom/htmlmodelement.rs index eb765ed0120..bd1b00f30f4 100644 --- a/src/components/script/dom/htmlmodelement.rs +++ b/src/components/script/dom/htmlmodelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLModElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLModElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLModElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLModElement { htmlelement: HTMLElement } +impl HTMLModElementDerived for EventTarget { + fn is_htmlmodelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLModElementTypeId)) => true, + _ => false + } + } +} + impl HTMLModElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLModElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLModElement { HTMLModElement { htmlelement: HTMLElement::new_inherited(HTMLModElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLModElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLModElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLModElement> { + let element = HTMLModElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLModElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlobjectelement.rs b/src/components/script/dom/htmlobjectelement.rs index 74f40db40dd..d373a0e6df4 100644 --- a/src/components/script/dom/htmlobjectelement.rs +++ b/src/components/script/dom/htmlobjectelement.rs @@ -3,11 +3,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLObjectElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLObjectElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLObjectElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::htmlformelement::HTMLFormElement; +use dom::node::{Node, ElementNodeTypeId}; use dom::validitystate::ValidityState; use dom::windowproxy::WindowProxy; use servo_util::str::DOMString; @@ -19,20 +23,30 @@ use servo_util::url::parse_url; use servo_util::namespace::Null; use servo_util::url::is_image_data; +#[deriving(Encodable)] pub struct HTMLObjectElement { htmlelement: HTMLElement, } +impl HTMLObjectElementDerived for EventTarget { + fn is_htmlobjectelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLObjectElementTypeId)) => true, + _ => false + } + } +} + impl HTMLObjectElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLObjectElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLObjectElement { HTMLObjectElement { htmlelement: HTMLElement::new_inherited(HTMLObjectElementTypeId, localName, document), } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLObjectElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLObjectElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLObjectElement> { + let element = HTMLObjectElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLObjectElementBinding::Wrap) } } @@ -44,8 +58,8 @@ impl HTMLObjectElement { let elem = &mut self.htmlelement.element; // TODO: support other values - match (elem.get_attribute(Null, "type").map(|x| x.Value()), - elem.get_attribute(Null, "data").map(|x| x.Value())) { + match (elem.get_attribute(Null, "type").map(|x| x.get().Value()), + elem.get_attribute(Null, "data").map(|x| x.get().Value())) { (None, Some(uri)) => { if is_image_data(uri) { let data_url = parse_url(uri, url); @@ -60,9 +74,9 @@ impl HTMLObjectElement { pub fn AfterSetAttr(&mut self, name: DOMString, _value: DOMString) { if "data" == name { let document = self.htmlelement.element.node.owner_doc(); - let window = document.document().window; - let url = window.page.url.as_ref().map(|&(ref url, _)| url.clone()); - self.process_data_url(window.image_cache_task.clone(), url); + let window = document.get().window.clone(); + let url = window.get().page.url.as_ref().map(|&(ref url, _)| url.clone()); + self.process_data_url(window.get().image_cache_task.clone(), url); } } @@ -98,7 +112,7 @@ impl HTMLObjectElement { Ok(()) } - pub fn GetForm(&self) -> Option<AbstractNode> { + pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { None } @@ -118,11 +132,11 @@ impl HTMLObjectElement { Ok(()) } - pub fn GetContentDocument(&self) -> Option<AbstractDocument> { + pub fn GetContentDocument(&self) -> Option<JS<Document>> { None } - pub fn GetContentWindow(&self) -> Option<@mut WindowProxy> { + pub fn GetContentWindow(&self) -> Option<JS<WindowProxy>> { None } @@ -130,9 +144,10 @@ impl HTMLObjectElement { false } - pub fn Validity(&self) -> @mut ValidityState { - let global = self.htmlelement.element.node.owner_doc().document().window; - ValidityState::new(global) + pub fn Validity(&self) -> JS<ValidityState> { + let doc = self.htmlelement.element.node.owner_doc(); + let doc = doc.get(); + ValidityState::new(&doc.window) } pub fn ValidationMessage(&self) -> DOMString { @@ -226,7 +241,7 @@ impl HTMLObjectElement { Ok(()) } - pub fn GetSVGDocument(&self) -> Option<AbstractDocument> { + pub fn GetSVGDocument(&self) -> Option<JS<Document>> { None } } diff --git a/src/components/script/dom/htmlolistelement.rs b/src/components/script/dom/htmlolistelement.rs index 6a762b31147..ea677919edb 100644 --- a/src/components/script/dom/htmlolistelement.rs +++ b/src/components/script/dom/htmlolistelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLOListElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLOListElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLOListElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLOListElement { htmlelement: HTMLElement, } +impl HTMLOListElementDerived for EventTarget { + fn is_htmlolistelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLOListElementTypeId)) => true, + _ => false + } + } +} + impl HTMLOListElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLOListElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLOListElement { HTMLOListElement { htmlelement: HTMLElement::new_inherited(HTMLOListElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLOListElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLOListElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLOListElement> { + let element = HTMLOListElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLOListElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmloptgroupelement.rs b/src/components/script/dom/htmloptgroupelement.rs index 020dd3a2471..d8a3d222cb3 100644 --- a/src/components/script/dom/htmloptgroupelement.rs +++ b/src/components/script/dom/htmloptgroupelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLOptGroupElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLOptGroupElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLOptGroupElement { htmlelement: HTMLElement } +impl HTMLOptGroupElementDerived for EventTarget { + fn is_htmloptgroupelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLOptGroupElementTypeId)) => true, + _ => false + } + } +} + impl HTMLOptGroupElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLOptGroupElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLOptGroupElement { HTMLOptGroupElement { htmlelement: HTMLElement::new_inherited(HTMLOptGroupElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLOptGroupElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLOptGroupElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLOptGroupElement> { + let element = HTMLOptGroupElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLOptGroupElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmloptionelement.rs b/src/components/script/dom/htmloptionelement.rs index d1761ecdd1a..d01de54a8bc 100644 --- a/src/components/script/dom/htmloptionelement.rs +++ b/src/components/script/dom/htmloptionelement.rs @@ -3,27 +3,41 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLOptionElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLOptionElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLOptionElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::htmlformelement::HTMLFormElement; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLOptionElement { htmlelement: HTMLElement } +impl HTMLOptionElementDerived for EventTarget { + fn is_htmloptionelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLOptionElementTypeId)) => true, + _ => false + } + } +} + impl HTMLOptionElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLOptionElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLOptionElement { HTMLOptionElement { htmlelement: HTMLElement::new_inherited(HTMLOptionElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLOptionElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLOptionElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLOptionElement> { + let element = HTMLOptionElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLOptionElementBinding::Wrap) } } @@ -36,7 +50,7 @@ impl HTMLOptionElement { Ok(()) } - pub fn GetForm(&self) -> Option<AbstractNode> { + pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { None } diff --git a/src/components/script/dom/htmloutputelement.rs b/src/components/script/dom/htmloutputelement.rs index 174e9258ecf..95c03763c3c 100644 --- a/src/components/script/dom/htmloutputelement.rs +++ b/src/components/script/dom/htmloutputelement.rs @@ -3,33 +3,47 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLOutputElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLOutputElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLOutputElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::htmlformelement::HTMLFormElement; +use dom::node::{Node, ElementNodeTypeId}; use dom::validitystate::ValidityState; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLOutputElement { htmlelement: HTMLElement } +impl HTMLOutputElementDerived for EventTarget { + fn is_htmloutputelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLOutputElementTypeId)) => true, + _ => false + } + } +} + impl HTMLOutputElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLOutputElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLOutputElement { HTMLOutputElement { htmlelement: HTMLElement::new_inherited(HTMLOutputElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLOutputElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLOutputElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLOutputElement> { + let element = HTMLOutputElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLOutputElementBinding::Wrap) } } impl HTMLOutputElement { - pub fn GetForm(&self) -> Option<AbstractNode> { + pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { None } @@ -68,12 +82,13 @@ impl HTMLOutputElement { pub fn SetWillValidate(&mut self, _will_validate: bool) { } - pub fn Validity(&self) -> @mut ValidityState { - let global = self.htmlelement.element.node.owner_doc().document().window; - ValidityState::new(global) + pub fn Validity(&self) -> JS<ValidityState> { + let doc = self.htmlelement.element.node.owner_doc(); + let doc = doc.get(); + ValidityState::new(&doc.window) } - pub fn SetValidity(&mut self, _validity: @mut ValidityState) { + pub fn SetValidity(&mut self, _validity: JS<ValidityState>) { } pub fn ValidationMessage(&self) -> DOMString { diff --git a/src/components/script/dom/htmlparagraphelement.rs b/src/components/script/dom/htmlparagraphelement.rs index 1132a496f26..a1aef4a7f5d 100644 --- a/src/components/script/dom/htmlparagraphelement.rs +++ b/src/components/script/dom/htmlparagraphelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLParagraphElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLParagraphElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLParagraphElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLParagraphElement { htmlelement: HTMLElement } +impl HTMLParagraphElementDerived for EventTarget { + fn is_htmlparagraphelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLParagraphElementTypeId)) => true, + _ => false + } + } +} + impl HTMLParagraphElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLParagraphElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLParagraphElement { HTMLParagraphElement { htmlelement: HTMLElement::new_inherited(HTMLParagraphElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLParagraphElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLParagraphElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLParagraphElement> { + let element = HTMLParagraphElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLParagraphElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlparamelement.rs b/src/components/script/dom/htmlparamelement.rs index 3cd242e0016..1e3e7785c0d 100644 --- a/src/components/script/dom/htmlparamelement.rs +++ b/src/components/script/dom/htmlparamelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLParamElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLParamElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLParamElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLParamElement { htmlelement: HTMLElement } +impl HTMLParamElementDerived for EventTarget { + fn is_htmlparamelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLParamElementTypeId)) => true, + _ => false + } + } +} + impl HTMLParamElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLParamElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLParamElement { HTMLParamElement { htmlelement: HTMLElement::new_inherited(HTMLParamElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLParamElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLParamElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLParamElement> { + let element = HTMLParamElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLParamElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlpreelement.rs b/src/components/script/dom/htmlpreelement.rs index c2bf04464f3..33f5b1a7247 100644 --- a/src/components/script/dom/htmlpreelement.rs +++ b/src/components/script/dom/htmlpreelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLPreElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLPreElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::{ErrorResult}; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLPreElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLPreElement { htmlelement: HTMLElement, } +impl HTMLPreElementDerived for EventTarget { + fn is_htmlpreelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLPreElementTypeId)) => true, + _ => false + } + } +} + impl HTMLPreElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLPreElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLPreElement { HTMLPreElement { htmlelement: HTMLElement::new_inherited(HTMLPreElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLPreElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLPreElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLPreElement> { + let element = HTMLPreElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLPreElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlprogresselement.rs b/src/components/script/dom/htmlprogresselement.rs index dca693fa9d3..ee6b3bff48b 100644 --- a/src/components/script/dom/htmlprogresselement.rs +++ b/src/components/script/dom/htmlprogresselement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLProgressElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLProgressElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::{ErrorResult, Fallible}; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLProgressElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLProgressElement { htmlelement: HTMLElement, } +impl HTMLProgressElementDerived for EventTarget { + fn is_htmlprogresselement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLProgressElementTypeId)) => true, + _ => false + } + } +} + impl HTMLProgressElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLProgressElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLProgressElement { HTMLProgressElement { htmlelement: HTMLElement::new_inherited(HTMLProgressElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLProgressElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLProgressElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLProgressElement> { + let element = HTMLProgressElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLProgressElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlquoteelement.rs b/src/components/script/dom/htmlquoteelement.rs index 3ad246f16c2..9fc115dcf9c 100644 --- a/src/components/script/dom/htmlquoteelement.rs +++ b/src/components/script/dom/htmlquoteelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLQuoteElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLQuoteElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLQuoteElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLQuoteElement { htmlelement: HTMLElement, } +impl HTMLQuoteElementDerived for EventTarget { + fn is_htmlquoteelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLQuoteElementTypeId)) => true, + _ => false + } + } +} + impl HTMLQuoteElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLQuoteElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLQuoteElement { HTMLQuoteElement { htmlelement: HTMLElement::new_inherited(HTMLQuoteElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLQuoteElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLQuoteElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLQuoteElement> { + let element = HTMLQuoteElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLQuoteElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlscriptelement.rs b/src/components/script/dom/htmlscriptelement.rs index 80513d5f649..191d588585b 100644 --- a/src/components/script/dom/htmlscriptelement.rs +++ b/src/components/script/dom/htmlscriptelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLScriptElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLScriptElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLScriptElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLScriptElement { htmlelement: HTMLElement, } +impl HTMLScriptElementDerived for EventTarget { + fn is_htmlscriptelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLScriptElementTypeId)) => true, + _ => false + } + } +} + impl HTMLScriptElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLScriptElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLScriptElement { HTMLScriptElement { htmlelement: HTMLElement::new_inherited(HTMLScriptElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLScriptElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLScriptElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLScriptElement> { + let element = HTMLScriptElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLScriptElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlselectelement.rs b/src/components/script/dom/htmlselectelement.rs index 61fb132dfe2..1b7e452a992 100644 --- a/src/components/script/dom/htmlselectelement.rs +++ b/src/components/script/dom/htmlselectelement.rs @@ -3,28 +3,44 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLSelectElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLSelectElementDerived; +use dom::bindings::codegen::UnionTypes::{HTMLElementOrLong, HTMLOptionElementOrHTMLOptGroupElement}; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; -use dom::element::HTMLSelectElementTypeId; +use dom::document::Document; +use dom::element::{Element, HTMLSelectElementTypeId}; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::htmlformelement::HTMLFormElement; +use dom::node::{Node, ElementNodeTypeId}; +use dom::htmloptionelement::HTMLOptionElement; use dom::validitystate::ValidityState; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLSelectElement { htmlelement: HTMLElement } +impl HTMLSelectElementDerived for EventTarget { + fn is_htmlselectelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLSelectElementTypeId)) => true, + _ => false + } + } +} + impl HTMLSelectElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLSelectElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLSelectElement { HTMLSelectElement { htmlelement: HTMLElement::new_inherited(HTMLSelectElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLSelectElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLSelectElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLSelectElement> { + let element = HTMLSelectElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLSelectElementBinding::Wrap) } } @@ -45,7 +61,7 @@ impl HTMLSelectElement { Ok(()) } - pub fn GetForm(&self) -> Option<AbstractNode> { + pub fn GetForm(&self) -> Option<JS<HTMLFormElement>> { None } @@ -93,19 +109,19 @@ impl HTMLSelectElement { Ok(()) } - pub fn Item(&self, _index: u32) -> Option<AbstractNode> { + pub fn Item(&self, _index: u32) -> Option<JS<Element>> { None } - pub fn NamedItem(&self, _name: DOMString) -> Option<AbstractNode> { + pub fn NamedItem(&self, _name: DOMString) -> Option<JS<HTMLOptionElement>> { None } - pub fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<AbstractNode> { + pub fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<JS<Element>> { None } - pub fn IndexedSetter(&mut self, _index: u32, _option: Option<AbstractNode>) -> ErrorResult { + pub fn IndexedSetter(&mut self, _index: u32, _option: Option<JS<HTMLOptionElement>>) -> ErrorResult { Ok(()) } @@ -137,12 +153,13 @@ impl HTMLSelectElement { pub fn SetWillValidate(&mut self, _will_validate: bool) { } - pub fn Validity(&self) -> @mut ValidityState { - let global = self.htmlelement.element.node.owner_doc().document().window; - ValidityState::new(global) + pub fn Validity(&self) -> JS<ValidityState> { + let doc = self.htmlelement.element.node.owner_doc(); + let doc = doc.get(); + ValidityState::new(&doc.window) } - pub fn SetValidity(&mut self, _validity: @mut ValidityState) { + pub fn SetValidity(&mut self, _validity: JS<ValidityState>) { } pub fn ValidationMessage(&self) -> DOMString { @@ -159,4 +176,8 @@ impl HTMLSelectElement { pub fn SetCustomValidity(&mut self, _error: DOMString) { } + + pub fn Add(&self, _element: HTMLOptionElementOrHTMLOptGroupElement, _before: Option<HTMLElementOrLong>) -> ErrorResult { + Ok(()) + } } diff --git a/src/components/script/dom/htmlserializer.rs b/src/components/script/dom/htmlserializer.rs index 97198b0ab79..482c724666b 100644 --- a/src/components/script/dom/htmlserializer.rs +++ b/src/components/script/dom/htmlserializer.rs @@ -4,10 +4,20 @@ use servo_util::namespace; use dom::attr::Attr; +use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, CommentCast}; +use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, CharacterDataCast}; +use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; +use dom::bindings::js::JS; +use dom::characterdata::CharacterData; +use dom::comment::Comment; +use dom::documenttype::DocumentType; +use dom::element::Element; use dom::node::NodeIterator; use dom::node::{DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId}; use dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstructionNodeTypeId}; -use dom::node::{TextNodeTypeId, AbstractNode}; +use dom::node::{TextNodeTypeId, NodeHelpers}; +use dom::processinginstruction::ProcessingInstruction; +use dom::text::Text; pub fn serialize(iterator: &mut NodeIterator) -> ~str { let mut html = ~""; @@ -20,28 +30,33 @@ pub fn serialize(iterator: &mut NodeIterator) -> ~str { html.push_str( match node.type_id() { ElementNodeTypeId(..) => { - serialize_elem(node, &mut open_elements) + let elem: JS<Element> = ElementCast::to(&node); + serialize_elem(&elem, &mut open_elements) } CommentNodeTypeId => { - serialize_comment(node) + let comment: JS<Comment> = CommentCast::to(&node); + serialize_comment(&comment) } TextNodeTypeId => { - serialize_text(node) + let text: JS<Text> = TextCast::to(&node); + serialize_text(&text) } DoctypeNodeTypeId => { - serialize_doctype(node) + let doctype: JS<DocumentType> = DocumentTypeCast::to(&node); + serialize_doctype(&doctype) } ProcessingInstructionNodeTypeId => { - serialize_processing_instruction(node) + let processing_instruction: JS<ProcessingInstruction> = ProcessingInstructionCast::to(&node); + serialize_processing_instruction(&processing_instruction) } DocumentFragmentNodeTypeId => { ~"" } - DocumentNodeTypeId(_) => { + DocumentNodeTypeId => { fail!("It shouldn't be possible to serialize a document node") } } - ); + ); } while open_elements.len() > 0 { html.push_str(~"</" + open_elements.pop() + ">"); @@ -49,88 +64,75 @@ pub fn serialize(iterator: &mut NodeIterator) -> ~str { html } -fn serialize_comment(node: AbstractNode) -> ~str { - node.with_imm_characterdata(|comment| { - ~"<!--" + comment.data + "-->" - }) +fn serialize_comment(comment: &JS<Comment>) -> ~str { + ~"<!--" + comment.get().characterdata.data + "-->" } -fn serialize_text(node: AbstractNode) -> ~str { - node.with_imm_characterdata(|text| { - match node.parent_node() { - Some(parent) if parent.is_element() => { - parent.with_imm_element(|elem| { - match elem.tag_name.as_slice() { - "style" | "script" | "xmp" | "iframe" | - "noembed" | "noframes" | "plaintext" | - "noscript" if elem.namespace == namespace::HTML => { - text.data.clone() - }, - _ => escape(text.data, false) - } - }) - }, - _ => escape(text.data, false) +fn serialize_text(text: &JS<Text>) -> ~str { + match text.get().characterdata.node.parent_node { + Some(ref parent) if parent.is_element() => { + let elem: JS<Element> = ElementCast::to(parent); + match elem.get().tag_name.as_slice() { + "style" | "script" | "xmp" | "iframe" | + "noembed" | "noframes" | "plaintext" | + "noscript" if elem.get().namespace == namespace::HTML => { + text.get().characterdata.data.clone() + }, + _ => escape(text.get().characterdata.data, false) + } } - }) + _ => escape(text.get().characterdata.data, false) + } } -fn serialize_processing_instruction(node: AbstractNode) -> ~str { - node.with_imm_processing_instruction(|processing_instruction| { - ~"<?" + processing_instruction.target + " " + processing_instruction.characterdata.data + "?>" - }) +fn serialize_processing_instruction(processing_instruction: &JS<ProcessingInstruction>) -> ~str { + ~"<?" + processing_instruction.get().target + " " + processing_instruction.get().characterdata.data + "?>" } -fn serialize_doctype(node: AbstractNode) -> ~str { - node.with_imm_doctype(|doctype| { - ~"<!DOCTYPE" + doctype.name + ">" - }) +fn serialize_doctype(doctype: &JS<DocumentType>) -> ~str { + ~"<!DOCTYPE" + doctype.get().name + ">" } -fn serialize_elem(node: AbstractNode, open_elements: &mut ~[~str]) -> ~str { - node.with_imm_element(|elem| { - let mut rv = ~"<" + elem.tag_name; - for attr in elem.attrs.iter() { - rv.push_str(serialize_attr(attr)); - }; - rv.push_str(">"); - match elem.tag_name.as_slice() { - "pre" | "listing" | "textarea" if - elem.namespace == namespace::HTML => { - match node.first_child() { - Some(child) if child.is_text() => { - child.with_imm_characterdata(|text| { - if text.data[0] == 0x0A as u8 { - rv.push_str("\x0A"); - } - }) - }, - _ => {} +fn serialize_elem(elem: &JS<Element>, open_elements: &mut ~[~str]) -> ~str { + let mut rv = ~"<" + elem.get().tag_name; + for attr in elem.get().attrs.iter() { + rv.push_str(serialize_attr(attr)); + }; + rv.push_str(">"); + match elem.get().tag_name.as_slice() { + "pre" | "listing" | "textarea" if elem.get().namespace == namespace::HTML => { + match elem.get().node.first_child { + Some(ref child) if child.is_text() => { + let text: JS<CharacterData> = CharacterDataCast::to(child); + if text.get().data[0] == 0x0A as u8 { + rv.push_str("\x0A"); } - }, - _ => {} - } - if !elem.is_void() { - open_elements.push(elem.tag_name.clone()); - } - rv - }) + }, + _ => {} + } + }, + _ => {} + } + if !elem.get().is_void() { + open_elements.push(elem.get().tag_name.clone()); + } + rv } -fn serialize_attr(attr: &@mut Attr) -> ~str { - let attr_name = if attr.namespace == namespace::XML { - ~"xml:" + attr.local_name.clone() - } else if attr.namespace == namespace::XMLNS && - attr.local_name.as_slice() == "xmlns" { +fn serialize_attr(attr: &JS<Attr>) -> ~str { + let attr_name = if attr.get().namespace == namespace::XML { + ~"xml:" + attr.get().local_name.clone() + } else if attr.get().namespace == namespace::XMLNS && + attr.get().local_name.as_slice() == "xmlns" { ~"xmlns" - } else if attr.namespace == namespace::XMLNS { - ~"xmlns:" + attr.local_name.clone() - } else if attr.namespace == namespace::XLink { - ~"xlink:" + attr.local_name.clone() + } else if attr.get().namespace == namespace::XMLNS { + ~"xmlns:" + attr.get().local_name.clone() + } else if attr.get().namespace == namespace::XLink { + ~"xlink:" + attr.get().local_name.clone() } else { - attr.name.clone() + attr.get().name.clone() }; - ~" " + attr_name + "=\"" + escape(attr.value, true) + "\"" + ~" " + attr_name + "=\"" + escape(attr.get().value, true) + "\"" } fn escape(string: &str, attr_mode: bool) -> ~str { diff --git a/src/components/script/dom/htmlsourceelement.rs b/src/components/script/dom/htmlsourceelement.rs index 212ddd77850..c5c7beaec13 100644 --- a/src/components/script/dom/htmlsourceelement.rs +++ b/src/components/script/dom/htmlsourceelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLSourceElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLSourceElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLSourceElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLSourceElement { htmlelement: HTMLElement } +impl HTMLSourceElementDerived for EventTarget { + fn is_htmlsourceelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLSourceElementTypeId)) => true, + _ => false + } + } +} + impl HTMLSourceElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLSourceElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLSourceElement { HTMLSourceElement { htmlelement: HTMLElement::new_inherited(HTMLSourceElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLSourceElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLSourceElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLSourceElement> { + let element = HTMLSourceElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLSourceElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlspanelement.rs b/src/components/script/dom/htmlspanelement.rs index 47a47f3a17e..8b827bbf234 100644 --- a/src/components/script/dom/htmlspanelement.rs +++ b/src/components/script/dom/htmlspanelement.rs @@ -3,25 +3,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLSpanElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLSpanElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLSpanElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLSpanElement { htmlelement: HTMLElement } +impl HTMLSpanElementDerived for EventTarget { + fn is_htmlspanelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLSpanElementTypeId)) => true, + _ => false + } + } +} + impl HTMLSpanElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLSpanElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLSpanElement { HTMLSpanElement { htmlelement: HTMLElement::new_inherited(HTMLSpanElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLSpanElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLSpanElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLSpanElement> { + let element = HTMLSpanElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLSpanElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlstyleelement.rs b/src/components/script/dom/htmlstyleelement.rs index 4a39f6bcf39..bc12ca5a291 100644 --- a/src/components/script/dom/htmlstyleelement.rs +++ b/src/components/script/dom/htmlstyleelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLStyleElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLStyleElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLStyleElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLStyleElement { htmlelement: HTMLElement, } +impl HTMLStyleElementDerived for EventTarget { + fn is_htmlstyleelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLStyleElementTypeId)) => true, + _ => false + } + } +} + impl HTMLStyleElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLStyleElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLStyleElement { HTMLStyleElement { htmlelement: HTMLElement::new_inherited(HTMLStyleElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLStyleElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLStyleElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLStyleElement> { + let element = HTMLStyleElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLStyleElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltablecaptionelement.rs b/src/components/script/dom/htmltablecaptionelement.rs index 94d5faf5ffc..0599e2624bf 100644 --- a/src/components/script/dom/htmltablecaptionelement.rs +++ b/src/components/script/dom/htmltablecaptionelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTableCaptionElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLTableCaptionElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLTableCaptionElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTableCaptionElement { htmlelement: HTMLElement } +impl HTMLTableCaptionElementDerived for EventTarget { + fn is_htmltablecaptionelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTableCaptionElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTableCaptionElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTableCaptionElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTableCaptionElement { HTMLTableCaptionElement { htmlelement: HTMLElement::new_inherited(HTMLTableCaptionElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTableCaptionElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTableCaptionElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTableCaptionElement> { + let element = HTMLTableCaptionElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTableCaptionElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltablecellelement.rs b/src/components/script/dom/htmltablecellelement.rs index ddca4692373..04c745affd4 100644 --- a/src/components/script/dom/htmltablecellelement.rs +++ b/src/components/script/dom/htmltablecellelement.rs @@ -2,18 +2,33 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::codegen::InheritTypes::HTMLTableCellElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; -use dom::element::ElementTypeId; +use dom::document::Document; +use dom::element::{ElementTypeId, HTMLTableDataCellElementTypeId, HTMLTableHeaderCellElementTypeId}; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; +use dom::node::ElementNodeTypeId; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTableCellElement { htmlelement: HTMLElement, } +impl HTMLTableCellElementDerived for EventTarget { + fn is_htmltablecellelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTableDataCellElementTypeId)) | + NodeTargetTypeId(ElementNodeTypeId(HTMLTableHeaderCellElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTableCellElement { - pub fn new_inherited(type_id: ElementTypeId, tag_name: DOMString, document: AbstractDocument) -> HTMLTableCellElement { + pub fn new_inherited(type_id: ElementTypeId, tag_name: DOMString, document: JS<Document>) -> HTMLTableCellElement { HTMLTableCellElement { htmlelement: HTMLElement::new_inherited(type_id, tag_name, document) } diff --git a/src/components/script/dom/htmltablecolelement.rs b/src/components/script/dom/htmltablecolelement.rs index 577718f5535..8fbdb208124 100644 --- a/src/components/script/dom/htmltablecolelement.rs +++ b/src/components/script/dom/htmltablecolelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTableColElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLTableColElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLTableColElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTableColElement { htmlelement: HTMLElement, } +impl HTMLTableColElementDerived for EventTarget { + fn is_htmltablecolelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTableColElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTableColElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTableColElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTableColElement { HTMLTableColElement { htmlelement: HTMLElement::new_inherited(HTMLTableColElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTableColElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTableColElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTableColElement> { + let element = HTMLTableColElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTableColElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltabledatacellelement.rs b/src/components/script/dom/htmltabledatacellelement.rs index edcfaae6053..f245f209513 100644 --- a/src/components/script/dom/htmltabledatacellelement.rs +++ b/src/components/script/dom/htmltabledatacellelement.rs @@ -3,25 +3,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTableDataCellElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLTableDataCellElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLTableDataCellElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmltablecellelement::HTMLTableCellElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTableDataCellElement { htmltablecellelement: HTMLTableCellElement, } +impl HTMLTableDataCellElementDerived for EventTarget { + fn is_htmltabledatacellelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTableDataCellElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTableDataCellElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTableDataCellElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTableDataCellElement { HTMLTableDataCellElement { htmltablecellelement: HTMLTableCellElement::new_inherited(HTMLTableDataCellElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTableDataCellElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTableDataCellElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTableDataCellElement> { + let element = HTMLTableDataCellElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTableDataCellElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltableelement.rs b/src/components/script/dom/htmltableelement.rs index bf46faa3bcc..4ebd2cc4c97 100644 --- a/src/components/script/dom/htmltableelement.rs +++ b/src/components/script/dom/htmltableelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTableElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLTableElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLTableElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTableElement { htmlelement: HTMLElement, } +impl HTMLTableElementDerived for EventTarget { + fn is_htmltableelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTableElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTableElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTableElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTableElement { HTMLTableElement { htmlelement: HTMLElement::new_inherited(HTMLTableElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTableElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTableElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTableElement> { + let element = HTMLTableElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTableElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltableheadercellelement.rs b/src/components/script/dom/htmltableheadercellelement.rs index ed9475f3683..66b94da6b4c 100644 --- a/src/components/script/dom/htmltableheadercellelement.rs +++ b/src/components/script/dom/htmltableheadercellelement.rs @@ -3,25 +3,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTableHeaderCellElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLTableHeaderCellElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLTableHeaderCellElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmltablecellelement::HTMLTableCellElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTableHeaderCellElement { htmltablecellelement: HTMLTableCellElement, } +impl HTMLTableHeaderCellElementDerived for EventTarget { + fn is_htmltableheadercellelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTableHeaderCellElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTableHeaderCellElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTableHeaderCellElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTableHeaderCellElement { HTMLTableHeaderCellElement { htmltablecellelement: HTMLTableCellElement::new_inherited(HTMLTableHeaderCellElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTableHeaderCellElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTableHeaderCellElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTableHeaderCellElement> { + let element = HTMLTableHeaderCellElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTableHeaderCellElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltablerowelement.rs b/src/components/script/dom/htmltablerowelement.rs index 53c5eaaa0b3..22ae9fa7071 100644 --- a/src/components/script/dom/htmltablerowelement.rs +++ b/src/components/script/dom/htmltablerowelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTableRowElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLTableRowElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLTableRowElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTableRowElement { htmlelement: HTMLElement, } +impl HTMLTableRowElementDerived for EventTarget { + fn is_htmltablerowelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTableRowElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTableRowElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTableRowElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTableRowElement { HTMLTableRowElement { htmlelement: HTMLElement::new_inherited(HTMLTableRowElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTableRowElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTableRowElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTableRowElement> { + let element = HTMLTableRowElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTableRowElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltablesectionelement.rs b/src/components/script/dom/htmltablesectionelement.rs index 7a3270197cb..f718e67586a 100644 --- a/src/components/script/dom/htmltablesectionelement.rs +++ b/src/components/script/dom/htmltablesectionelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTableSectionElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLTableSectionElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLTableSectionElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTableSectionElement { htmlelement: HTMLElement, } +impl HTMLTableSectionElementDerived for EventTarget { + fn is_htmltablesectionelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTableSectionElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTableSectionElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTableSectionElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTableSectionElement { HTMLTableSectionElement { htmlelement: HTMLElement::new_inherited(HTMLTableSectionElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTableSectionElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTableSectionElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTableSectionElement> { + let element = HTMLTableSectionElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTableSectionElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltemplateelement.rs b/src/components/script/dom/htmltemplateelement.rs index 1bfe4f0b236..ffb7cd7e771 100644 --- a/src/components/script/dom/htmltemplateelement.rs +++ b/src/components/script/dom/htmltemplateelement.rs @@ -3,25 +3,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTemplateElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLTemplateElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLTemplateElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTemplateElement { htmlelement: HTMLElement, } +impl HTMLTemplateElementDerived for EventTarget { + fn is_htmltemplateelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTemplateElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTemplateElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTemplateElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTemplateElement { HTMLTemplateElement { htmlelement: HTMLElement::new_inherited(HTMLTemplateElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTemplateElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTemplateElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTemplateElement> { + let element = HTMLTemplateElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTemplateElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltextareaelement.rs b/src/components/script/dom/htmltextareaelement.rs index 43da53af73b..b34dc05c3e3 100644 --- a/src/components/script/dom/htmltextareaelement.rs +++ b/src/components/script/dom/htmltextareaelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTextAreaElementBinding; -use dom::bindings::utils::{Fallible, ErrorResult}; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLTextAreaElementDerived; +use dom::bindings::js::JS; +use dom::bindings::utils::{ErrorResult, Fallible}; +use dom::document::Document; use dom::element::HTMLTextAreaElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTextAreaElement { htmlelement: HTMLElement, } +impl HTMLTextAreaElementDerived for EventTarget { + fn is_htmltextareaelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTextAreaElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTextAreaElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTextAreaElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTextAreaElement { HTMLTextAreaElement { htmlelement: HTMLElement::new_inherited(HTMLTextAreaElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTextAreaElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTextAreaElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTextAreaElement> { + let element = HTMLTextAreaElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTextAreaElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltimeelement.rs b/src/components/script/dom/htmltimeelement.rs index 23c48c71f70..baddd3bd908 100644 --- a/src/components/script/dom/htmltimeelement.rs +++ b/src/components/script/dom/htmltimeelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTimeElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLTimeElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLTimeElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTimeElement { htmlelement: HTMLElement } +impl HTMLTimeElementDerived for EventTarget { + fn is_htmltimeelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTimeElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTimeElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTimeElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTimeElement { HTMLTimeElement { htmlelement: HTMLElement::new_inherited(HTMLTimeElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTimeElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTimeElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTimeElement> { + let element = HTMLTimeElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTimeElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltitleelement.rs b/src/components/script/dom/htmltitleelement.rs index b6466637181..61eebf793a5 100644 --- a/src/components/script/dom/htmltitleelement.rs +++ b/src/components/script/dom/htmltitleelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTitleElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLTitleElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLTitleElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTitleElement { htmlelement: HTMLElement, } +impl HTMLTitleElementDerived for EventTarget { + fn is_htmltitleelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTitleElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTitleElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTitleElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTitleElement { HTMLTitleElement { htmlelement: HTMLElement::new_inherited(HTMLTitleElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTitleElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTitleElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTitleElement> { + let element = HTMLTitleElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTitleElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmltrackelement.rs b/src/components/script/dom/htmltrackelement.rs index bf081d44918..24fcb38dd12 100644 --- a/src/components/script/dom/htmltrackelement.rs +++ b/src/components/script/dom/htmltrackelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLTrackElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLTrackElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLTrackElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLTrackElement { htmlelement: HTMLElement, } +impl HTMLTrackElementDerived for EventTarget { + fn is_htmltrackelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLTrackElementTypeId)) => true, + _ => false + } + } +} + impl HTMLTrackElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLTrackElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLTrackElement { HTMLTrackElement { htmlelement: HTMLElement::new_inherited(HTMLTrackElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLTrackElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLTrackElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLTrackElement> { + let element = HTMLTrackElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLTrackElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlulistelement.rs b/src/components/script/dom/htmlulistelement.rs index 812144edf57..3533632b8a2 100644 --- a/src/components/script/dom/htmlulistelement.rs +++ b/src/components/script/dom/htmlulistelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLUListElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLUListElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLUListElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLUListElement { htmlelement: HTMLElement } +impl HTMLUListElementDerived for EventTarget { + fn is_htmlulistelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLUListElementTypeId)) => true, + _ => false + } + } +} + impl HTMLUListElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLUListElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLUListElement { HTMLUListElement { htmlelement: HTMLElement::new_inherited(HTMLUListElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLUListElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLUListElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLUListElement> { + let element = HTMLUListElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLUListElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlunknownelement.rs b/src/components/script/dom/htmlunknownelement.rs index 67aa56bc47c..3c353acdb25 100644 --- a/src/components/script/dom/htmlunknownelement.rs +++ b/src/components/script/dom/htmlunknownelement.rs @@ -3,25 +3,38 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLUnknownElementBinding; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::HTMLUnknownElementDerived; +use dom::bindings::js::JS; +use dom::document::Document; use dom::element::HTMLUnknownElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLUnknownElement { htmlelement: HTMLElement } +impl HTMLUnknownElementDerived for EventTarget { + fn is_htmlunknownelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLUnknownElementTypeId)) => true, + _ => false + } + } +} + impl HTMLUnknownElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLUnknownElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLUnknownElement { HTMLUnknownElement { htmlelement: HTMLElement::new_inherited(HTMLUnknownElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLUnknownElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLUnknownElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLUnknownElement> { + let element = HTMLUnknownElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLUnknownElementBinding::Wrap) } } diff --git a/src/components/script/dom/htmlvideoelement.rs b/src/components/script/dom/htmlvideoelement.rs index c3c1ac9a9b4..437e3f8bfc1 100644 --- a/src/components/script/dom/htmlvideoelement.rs +++ b/src/components/script/dom/htmlvideoelement.rs @@ -3,27 +3,40 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::HTMLVideoElementBinding; +use dom::bindings::codegen::InheritTypes::HTMLVideoElementDerived; +use dom::bindings::js::JS; use dom::bindings::utils::ErrorResult; -use dom::document::AbstractDocument; +use dom::document::Document; use dom::element::HTMLVideoElementTypeId; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlmediaelement::HTMLMediaElement; -use dom::node::{AbstractNode, Node}; +use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct HTMLVideoElement { htmlmediaelement: HTMLMediaElement } +impl HTMLVideoElementDerived for EventTarget { + fn is_htmlvideoelement(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ElementNodeTypeId(HTMLVideoElementTypeId)) => true, + _ => false + } + } +} + impl HTMLVideoElement { - pub fn new_inherited(localName: DOMString, document: AbstractDocument) -> HTMLVideoElement { + pub fn new_inherited(localName: DOMString, document: JS<Document>) -> HTMLVideoElement { HTMLVideoElement { htmlmediaelement: HTMLMediaElement::new_inherited(HTMLVideoElementTypeId, localName, document) } } - pub fn new(localName: DOMString, document: AbstractDocument) -> AbstractNode { - let element = HTMLVideoElement::new_inherited(localName, document); - Node::reflect_node(@mut element, document, HTMLVideoElementBinding::Wrap) + pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLVideoElement> { + let element = HTMLVideoElement::new_inherited(localName, document.clone()); + Node::reflect_node(~element, document, HTMLVideoElementBinding::Wrap) } } diff --git a/src/components/script/dom/location.rs b/src/components/script/dom/location.rs index b59248346e5..442373fea90 100644 --- a/src/components/script/dom/location.rs +++ b/src/components/script/dom/location.rs @@ -2,17 +2,19 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::codegen::LocationBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::Fallible; -use dom::bindings::codegen::LocationBinding; use dom::window::Window; use servo_util::str::DOMString; use script_task::{Page}; +#[deriving(Encodable)] pub struct Location { reflector_: Reflector, //XXXjdm cycle: window->Location->window - page: @mut Page + page: @mut Page, } impl Location { @@ -23,8 +25,10 @@ impl Location { } } - pub fn new(window: &Window, page: @mut Page) -> @mut Location { - reflect_dom_object(@mut Location::new_inherited(page), window, LocationBinding::Wrap) + pub fn new(window: &Window, page: @mut Page) -> JS<Location> { + reflect_dom_object(~Location::new_inherited(page), + window, + LocationBinding::Wrap) } pub fn Assign(&self, _url: DOMString) { diff --git a/src/components/script/dom/mouseevent.rs b/src/components/script/dom/mouseevent.rs index c61c5c1aee0..7f840877b30 100644 --- a/src/components/script/dom/mouseevent.rs +++ b/src/components/script/dom/mouseevent.rs @@ -3,17 +3,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::MouseEventBinding; +use dom::bindings::codegen::InheritTypes::MouseEventDerived; +use dom::bindings::js::JS; use dom::bindings::utils::{ErrorResult, Fallible}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -use dom::event::{AbstractEvent, Event, MouseEventTypeId}; -use dom::eventtarget::AbstractEventTarget; +use dom::event::{Event, MouseEventTypeId}; +use dom::eventtarget::EventTarget; use dom::uievent::UIEvent; use dom::window::Window; use dom::windowproxy::WindowProxy; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct MouseEvent { - parent: UIEvent, + mouseevent: UIEvent, screen_x: i32, screen_y: i32, client_x: i32, @@ -23,13 +26,19 @@ pub struct MouseEvent { alt_key: bool, meta_key: bool, button: u16, - related_target: Option<AbstractEventTarget> + related_target: Option<JS<EventTarget>> +} + +impl MouseEventDerived for Event { + fn is_mouseevent(&self) -> bool { + self.type_id == MouseEventTypeId + } } impl MouseEvent { pub fn new_inherited() -> MouseEvent { MouseEvent { - parent: UIEvent::new_inherited(MouseEventTypeId), + mouseevent: UIEvent::new_inherited(MouseEventTypeId), screen_x: 0, screen_y: 0, client_x: 0, @@ -43,21 +52,21 @@ impl MouseEvent { } } - pub fn new(window: @mut Window) -> AbstractEvent { - Event::as_abstract(reflect_dom_object(@mut MouseEvent::new_inherited(), - window, - MouseEventBinding::Wrap)) + pub fn new(window: &JS<Window>) -> JS<MouseEvent> { + reflect_dom_object(~MouseEvent::new_inherited(), + window.get(), + MouseEventBinding::Wrap) } - pub fn Constructor(owner: @mut Window, + pub fn Constructor(owner: &JS<Window>, type_: DOMString, - init: &MouseEventBinding::MouseEventInit) -> Fallible<AbstractEvent> { - let ev = MouseEvent::new(owner); - ev.mut_mouseevent().InitMouseEvent(type_, init.bubbles, init.cancelable, init.view, - init.detail, init.screenX, init.screenY, - init.clientX, init.clientY, init.ctrlKey, - init.altKey, init.shiftKey, init.metaKey, - init.button, init.relatedTarget); + init: &MouseEventBinding::MouseEventInit) -> Fallible<JS<MouseEvent>> { + let mut ev = MouseEvent::new(owner); + ev.get_mut().InitMouseEvent(type_, init.bubbles, init.cancelable, init.view.clone(), + init.detail, init.screenX, init.screenY, + init.clientX, init.clientY, init.ctrlKey, + init.altKey, init.shiftKey, init.metaKey, + init.button, init.relatedTarget.clone()); Ok(ev) } @@ -102,8 +111,8 @@ impl MouseEvent { 0 } - pub fn GetRelatedTarget(&self) -> Option<AbstractEventTarget> { - self.related_target + pub fn GetRelatedTarget(&self) -> Option<JS<EventTarget>> { + self.related_target.clone() } pub fn GetModifierState(&self, _keyArg: DOMString) -> bool { @@ -115,7 +124,7 @@ impl MouseEvent { typeArg: DOMString, canBubbleArg: bool, cancelableArg: bool, - viewArg: Option<@mut WindowProxy>, + viewArg: Option<JS<WindowProxy>>, detailArg: i32, screenXArg: i32, screenYArg: i32, @@ -126,8 +135,8 @@ impl MouseEvent { shiftKeyArg: bool, metaKeyArg: bool, buttonArg: u16, - relatedTargetArg: Option<AbstractEventTarget>) -> ErrorResult { - self.parent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); + relatedTargetArg: Option<JS<EventTarget>>) -> ErrorResult { + self.mouseevent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); self.screen_x = screenXArg; self.screen_y = screenYArg; self.client_x = clientXArg; @@ -144,10 +153,10 @@ impl MouseEvent { impl Reflectable for MouseEvent { fn reflector<'a>(&'a self) -> &'a Reflector { - self.parent.reflector() + self.mouseevent.reflector() } fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { - self.parent.mut_reflector() + self.mouseevent.mut_reflector() } } diff --git a/src/components/script/dom/navigator.rs b/src/components/script/dom/navigator.rs index 0c011f9bd58..693e86cb23d 100644 --- a/src/components/script/dom/navigator.rs +++ b/src/components/script/dom/navigator.rs @@ -2,12 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::codegen::NavigatorBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::Fallible; -use dom::bindings::codegen::NavigatorBinding; use dom::window::Window; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct Navigator { reflector_: Reflector //XXXjdm cycle: window->navigator->window } @@ -19,8 +21,10 @@ impl Navigator { } } - pub fn new(window: &Window) -> @mut Navigator { - reflect_dom_object(@mut Navigator::new_inherited(), window, NavigatorBinding::Wrap) + pub fn new(window: &Window) -> JS<Navigator> { + reflect_dom_object(~Navigator::new_inherited(), + window, + NavigatorBinding::Wrap) } pub fn DoNotTrack(&self) -> DOMString { diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 3f0649fbdac..a0357c92ab4 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -4,22 +4,23 @@ //! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. +use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, ElementCast, TextCast, NodeCast}; +use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived}; +use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{ErrorResult, Fallible, NotFound, HierarchyRequest}; use dom::bindings::utils; use dom::characterdata::CharacterData; -use dom::document::{AbstractDocument, DocumentTypeId}; +use dom::document::Document; use dom::documenttype::DocumentType; -use dom::element::{Element, ElementTypeId, HTMLImageElementTypeId, HTMLIframeElementTypeId, HTMLObjectElementTypeId}; -use dom::element::{HTMLAnchorElementTypeId, HTMLStyleElementTypeId}; -use dom::eventtarget::{AbstractEventTarget, EventTarget, NodeTypeId}; -use dom::htmliframeelement::HTMLIFrameElement; -use dom::htmlimageelement::HTMLImageElement; -use dom::htmlobjectelement::HTMLObjectElement; +use dom::element::{Element, ElementTypeId, HTMLAnchorElementTypeId}; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::nodelist::{NodeList}; use dom::text::Text; use dom::processinginstruction::ProcessingInstruction; use layout_interface::{LayoutChan, ReapLayoutDataMsg, UntrustedNodeAddress}; +use layout_interface::TrustedNodeAddress; use servo_util::str::{DOMString, null_str_as_empty}; use js::jsapi::{JSContext, JSObject, JSRuntime}; @@ -27,25 +28,19 @@ use js::jsfriendapi; use std::cast::transmute; use std::cast; use std::cell::{RefCell, Ref, RefMut}; -use std::iter::Filter; +use std::iter::{Map, Filter}; use std::libc::uintptr_t; -use std::util; use std::unstable::raw::Box; +use std::util; + +use extra::serialize::{Encoder, Encodable}; // // The basic Node structure // -/// This is what a Node looks like if you do not know what kind of node it is. To unpack it, use -/// downcast(). -/// -/// FIXME: This should be replaced with a trait once they can inherit from structs. -#[deriving(Eq)] -pub struct AbstractNode { - priv obj: *mut (), -} - /// An HTML node. +#[deriving(Encodable)] pub struct Node { /// The JavaScript reflector for this node. eventtarget: EventTarget, @@ -53,28 +48,26 @@ pub struct Node { /// The type of node that this is. type_id: NodeTypeId, - abstract: Option<AbstractNode>, - /// The parent of this node. - parent_node: Option<AbstractNode>, + parent_node: Option<JS<Node>>, /// The first child of this node. - first_child: Option<AbstractNode>, + first_child: Option<JS<Node>>, /// The last child of this node. - last_child: Option<AbstractNode>, + last_child: Option<JS<Node>>, /// The next sibling of this node. - next_sibling: Option<AbstractNode>, + next_sibling: Option<JS<Node>>, /// The previous sibling of this node. - prev_sibling: Option<AbstractNode>, + prev_sibling: Option<JS<Node>>, /// The document that this node belongs to. - priv owner_doc: Option<AbstractDocument>, + priv owner_doc: Option<JS<Document>>, /// The live list of children return by .childNodes. - child_list: Option<@mut NodeList>, + child_list: Option<JS<NodeList>>, /// A bitfield of flags for node items. priv flags: NodeFlags, @@ -86,14 +79,29 @@ pub struct Node { layout_data: LayoutDataRef, } +impl<S: Encoder> Encodable<S> for LayoutDataRef { + fn encode(&self, _s: &mut S) { + } +} + +impl NodeDerived for EventTarget { + fn is_node(&self) -> bool { + match self.type_id { + NodeTargetTypeId(_) => true, + _ => false + } + } +} + /// Flags for node items. +#[deriving(Encodable)] pub struct NodeFlags(u8); impl NodeFlags { pub fn new(type_id: NodeTypeId) -> NodeFlags { let mut flags = NodeFlags(0); match type_id { - DocumentNodeTypeId(_) => { flags.set_is_in_doc(true); } + DocumentNodeTypeId => { flags.set_is_in_doc(true); } _ => {} } flags @@ -195,424 +203,220 @@ impl LayoutDataRef { pub trait TLayoutData {} /// The different types of nodes. -#[deriving(Eq)] +#[deriving(Eq,Encodable)] pub enum NodeTypeId { DoctypeNodeTypeId, DocumentFragmentNodeTypeId, CommentNodeTypeId, - DocumentNodeTypeId(DocumentTypeId), + DocumentNodeTypeId, ElementNodeTypeId(ElementTypeId), TextNodeTypeId, ProcessingInstructionNodeTypeId, } -impl Clone for AbstractNode { - fn clone(&self) -> AbstractNode { - *self - } +pub trait INode { + fn AppendChild(&mut self, node: &mut JS<Node>) -> Fallible<JS<Node>>; + fn ReplaceChild(&mut self, node: &mut JS<Node>, child: &mut JS<Node>) -> Fallible<JS<Node>>; + fn RemoveChild(&mut self, node: &mut JS<Node>) -> Fallible<JS<Node>>; } -impl AbstractNode { - #[inline] - pub fn node<'a>(&'a self) -> &'a Node { - unsafe { - let box_: *mut Box<Node> = cast::transmute(self.obj); - &(*box_).data - } +impl INode for JS<Node> { + fn AppendChild(&mut self, node: &mut JS<Node>) -> Fallible<JS<Node>> { + let mut self_node = self.clone(); + self.get_mut().AppendChild(&mut self_node, node) } - #[inline] - pub fn mut_node<'a>(&'a self) -> &'a mut Node { - unsafe { - let box_: *mut Box<Node> = cast::transmute(self.obj); - &mut (*box_).data - } - } - - #[inline] - pub fn parent_node(&self) -> Option<AbstractNode> { - self.node().parent_node + fn ReplaceChild(&mut self, node: &mut JS<Node>, child: &mut JS<Node>) -> Fallible<JS<Node>> { + let mut self_node = self.clone(); + self.get_mut().ReplaceChild(&mut self_node, node, child) } - #[inline] - pub fn first_child(&self) -> Option<AbstractNode> { - self.node().first_child - } - - #[inline] - pub fn last_child(&self) -> Option<AbstractNode> { - self.node().last_child - } - - pub fn is_element(&self) -> bool { - match self.type_id() { - ElementNodeTypeId(..) => true, - _ => false - } - } - - pub fn is_document(&self) -> bool { - match self.type_id() { - DocumentNodeTypeId(..) => true, - _ => false - } - } - - /// If the given untrusted node address represents a valid DOM node in the given runtime, - /// returns it. - pub fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) - -> AbstractNode { - unsafe { - let candidate: uintptr_t = cast::transmute(candidate); - let object: *JSObject = jsfriendapi::bindgen::JS_GetAddressableObject(runtime, - candidate); - if object.is_null() { - fail!("Attempted to create an `AbstractNode` from an invalid pointer!") - } - let boxed_node: *mut Box<Node> = utils::unwrap(object); - AbstractNode::from_box(boxed_node) - } - } - - pub fn is_inclusive_ancestor_of(&self, parent: AbstractNode) -> bool { - *self == parent || parent.ancestors().any(|ancestor| ancestor == *self) - } - - pub fn is_parent_of(&self, child: AbstractNode) -> bool { - child.parent_node() == Some(*self) + fn RemoveChild(&mut self, node: &mut JS<Node>) -> Fallible<JS<Node>> { + let mut self_node = self.clone(); + self.get_mut().RemoveChild(&mut self_node, node) } } -impl<'a> AbstractNode { - // Unsafe accessors +pub trait NodeHelpers { + fn ancestors(&self) -> AncestorIterator; + fn children(&self) -> AbstractNodeChildrenIterator; + fn child_elements(&self) -> ChildElementIterator; + fn following_siblings(&self) -> AbstractNodeChildrenIterator; + fn is_in_doc(&self) -> bool; + fn is_inclusive_ancestor_of(&self, parent: &JS<Node>) -> bool; + fn is_parent_of(&self, child: &JS<Node>) -> bool; + + fn type_id(&self) -> NodeTypeId; + + fn parent_node(&self) -> Option<JS<Node>>; + fn first_child(&self) -> Option<JS<Node>>; + fn last_child(&self) -> Option<JS<Node>>; + fn prev_sibling(&self) -> Option<JS<Node>>; + fn next_sibling(&self) -> Option<JS<Node>>; + + fn is_element(&self) -> bool; + fn is_document(&self) -> bool; + fn is_doctype(&self) -> bool; + fn is_text(&self) -> bool; + fn is_anchor_element(&self) -> bool; + + fn node_inserted(&self); + fn node_removed(&self); + fn add_child(&mut self, new_child: &mut JS<Node>, before: Option<JS<Node>>); + fn remove_child(&mut self, child: &mut JS<Node>); + + fn get_hover_state(&self) -> bool; + fn set_hover_state(&mut self, state: bool); + + fn dump(&self); + fn dump_indent(&self, indent: uint); + fn debug_str(&self) -> ~str; + + fn traverse_preorder(&self) -> TreeIterator; + fn sequential_traverse_postorder(&self) -> TreeIterator; + fn inclusively_following_siblings(&self) -> AbstractNodeChildrenIterator; + + fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) -> Self; + fn to_trusted_node_address(&self) -> TrustedNodeAddress; +} - pub unsafe fn as_cacheable_wrapper(&self) -> @mut Reflectable { - match self.type_id() { - TextNodeTypeId => { - let node: @mut Text = cast::transmute(self.obj); - node as @mut Reflectable - } - _ => { - fail!("unsupported node type") - } - } +impl NodeHelpers for JS<Node> { + /// Dumps the subtree rooted at this node, for debugging. + fn dump(&self) { + self.dump_indent(0); } - /// Allow consumers to recreate an AbstractNode from the raw boxed type. - /// Must only be used in situations where the boxed type is in the inheritance - /// chain for nodes. - /// - /// FIXME(pcwalton): Mark unsafe? - pub fn from_box<T>(ptr: *mut Box<T>) -> AbstractNode { - AbstractNode { - obj: ptr as *mut () + /// Dumps the node tree, for debugging, with indentation. + fn dump_indent(&self, indent: uint) { + let mut s = ~""; + for _ in range(0, indent) { + s.push_str(" "); } - } - /// Allow consumers to upcast from derived classes. - pub fn from_document(doc: AbstractDocument) -> AbstractNode { - unsafe { - cast::transmute(doc) - } - } + s.push_str(self.debug_str()); + debug!("{:s}", s); - pub fn from_eventtarget(target: AbstractEventTarget) -> AbstractNode { - assert!(target.is_node()); - unsafe { - cast::transmute(target) + // FIXME: this should have a pure version? + for kid in self.children() { + kid.dump_indent(indent + 1u) } } - // Convenience accessors - - /// Returns the type ID of this node. Fails if this node is borrowed mutably. - #[inline] - pub fn type_id(self) -> NodeTypeId { - self.node().type_id + /// Returns a string that describes this node. + fn debug_str(&self) -> ~str { + format!("{:?}", self.type_id()) } - /// Returns the previous sibling of this node. Fails if this node is borrowed mutably. - pub fn prev_sibling(self) -> Option<AbstractNode> { - self.node().prev_sibling + /// Iterates over all ancestors of this node. + fn ancestors(&self) -> AncestorIterator { + self.get().ancestors() } - /// Returns the next sibling of this node. Fails if this node is borrowed mutably. - pub fn next_sibling(self) -> Option<AbstractNode> { - self.node().next_sibling + fn children(&self) -> AbstractNodeChildrenIterator { + self.get().children() } - // - // Downcasting borrows - // - - pub fn transmute<'a, T, R>(self, f: |&'a T| -> R) -> R { - unsafe { - let node_box: *mut Box<Node> = transmute(self.obj); - let node = &mut (*node_box).data; - let old = node.abstract; - node.abstract = Some(self); - let box_: *Box<T> = transmute(self.obj); - let rv = f(&(*box_).data); - node.abstract = old; - rv - } + fn child_elements(&self) -> ChildElementIterator { + self.get().child_elements() } - pub fn transmute_mut<T, R>(self, f: |&mut T| -> R) -> R { - unsafe { - let node_box: *mut Box<Node> = transmute(self.obj); - let node = &mut (*node_box).data; - let old = node.abstract; - node.abstract = Some(self); - let box_: *Box<T> = transmute(self.obj); - let rv = f(cast::transmute(&(*box_).data)); - node.abstract = old; - rv - } + fn is_in_doc(&self) -> bool { + self.get().flags.is_in_doc() } - // FIXME: This should be doing dynamic borrow checking for safety. - pub fn is_characterdata(self) -> bool { - self.is_text() || self.is_comment() || self.is_processing_instruction() + /// Returns the type ID of this node. Fails if this node is borrowed mutably. + fn type_id(&self) -> NodeTypeId { + self.get().type_id } - pub fn with_imm_characterdata<R>(self, f: |&CharacterData| -> R) -> R { - if !self.is_characterdata() { - fail!(~"node is not characterdata"); - } - self.transmute(f) + fn parent_node(&self) -> Option<JS<Node>> { + self.get().parent_node.clone() } - pub fn with_mut_characterdata<R>(self, f: |&mut CharacterData| -> R) -> R { - if !self.is_characterdata() { - fail!(~"node is not characterdata"); - } - self.transmute_mut(f) + fn first_child(&self) -> Option<JS<Node>> { + self.get().first_child.clone() } - pub fn is_doctype(self) -> bool { - self.type_id() == DoctypeNodeTypeId + fn last_child(&self) -> Option<JS<Node>> { + self.get().last_child.clone() } - pub fn with_imm_doctype<R>(self, f: |&DocumentType| -> R) -> R { - if !self.is_doctype() { - fail!(~"node is not doctype"); - } - self.transmute(f) + /// Returns the previous sibling of this node. Fails if this node is borrowed mutably. + fn prev_sibling(&self) -> Option<JS<Node>> { + self.get().prev_sibling.clone() } - pub fn with_mut_doctype<R>(self, f: |&mut DocumentType| -> R) -> R { - if !self.is_doctype() { - fail!(~"node is not doctype"); - } - self.transmute_mut(f) + /// Returns the next sibling of this node. Fails if this node is borrowed mutably. + fn next_sibling(&self) -> Option<JS<Node>> { + self.get().next_sibling.clone() } #[inline] - pub fn is_comment(self) -> bool { - // FIXME(pcwalton): Temporary workaround for the lack of inlining of autogenerated `Eq` - // implementations in Rust. + fn is_element(&self) -> bool { match self.type_id() { - CommentNodeTypeId => true, - _ => false, + ElementNodeTypeId(..) => true, + _ => false } } #[inline] - pub fn is_text(self) -> bool { - // FIXME(pcwalton): Temporary workaround for the lack of inlining of autogenerated `Eq` - // implementations in Rust. + fn is_document(&self) -> bool { match self.type_id() { - TextNodeTypeId => true, - _ => false, - } - } - - pub fn with_imm_text<R>(self, f: |&Text| -> R) -> R { - if !self.is_text() { - fail!(~"node is not text"); - } - self.transmute(f) - } - - pub fn with_mut_text<R>(self, f: |&mut Text| -> R) -> R { - if !self.is_text() { - fail!(~"node is not text"); + DocumentNodeTypeId => true, + _ => false } - self.transmute_mut(f) } #[inline] - pub fn is_processing_instruction(self) -> bool { - self.type_id() == ProcessingInstructionNodeTypeId - } - - pub fn with_imm_processing_instruction<R>(self, f: |&ProcessingInstruction| -> R) -> R { - if !self.is_processing_instruction() { - fail!("node is not processing instruction"); - } - self.transmute(f) - } - - // FIXME: This should be doing dynamic borrow checking for safety. - pub fn with_imm_element<R>(self, f: |&Element| -> R) -> R { - if !self.is_element() { - fail!(~"node is not an element"); - } - self.transmute(f) - } - - // FIXME: This should be doing dynamic borrow checking for safety. - pub fn as_mut_element<R>(self, f: |&mut Element| -> R) -> R { - if !self.is_element() { - fail!(~"node is not an element"); + fn is_anchor_element(&self) -> bool { + match self.type_id() { + ElementNodeTypeId(HTMLAnchorElementTypeId) => true, + _ => false } - self.transmute_mut(f) } #[inline] - pub fn is_image_element(self) -> bool { + fn is_doctype(&self) -> bool { match self.type_id() { - ElementNodeTypeId(HTMLImageElementTypeId) => true, - _ => false, - } - } - - pub fn with_mut_image_element<R>(self, f: |&mut HTMLImageElement| -> R) -> R { - if !self.is_image_element() { - fail!(~"node is not an image element"); + DoctypeNodeTypeId => true, + _ => false } - self.transmute_mut(f) - } - - pub fn is_iframe_element(self) -> bool { - self.type_id() == ElementNodeTypeId(HTMLIframeElementTypeId) } #[inline] - pub fn is_object_element(self) -> bool { - self.type_id() == ElementNodeTypeId(HTMLObjectElementTypeId) - } - - pub fn with_mut_object_element<R>(self, f: |&mut HTMLObjectElement| -> R) -> R { - if !self.is_object_element() { - fail!(~"node is not an image element"); - } - self.transmute_mut(f) - } - - pub fn with_mut_iframe_element<R>(self, f: |&mut HTMLIFrameElement| -> R) -> R { - if !self.is_iframe_element() { - fail!(~"node is not an iframe element"); - } - self.transmute_mut(f) - } - - pub fn is_style_element(self) -> bool { - self.type_id() == ElementNodeTypeId(HTMLStyleElementTypeId) - } - - pub fn is_anchor_element(self) -> bool { - self.type_id() == ElementNodeTypeId(HTMLAnchorElementTypeId) - } - - pub unsafe fn raw_object(self) -> *mut Box<Node> { - cast::transmute(self.obj) - } - - pub fn from_raw(raw: *mut Box<Node>) -> AbstractNode { - AbstractNode { - obj: raw as *mut () - } - } - - /// Dumps the subtree rooted at this node, for debugging. - pub fn dump(&self) { - self.dump_indent(0); - } - - /// Dumps the node tree, for debugging, with indentation. - pub fn dump_indent(&self, indent: uint) { - let mut s = ~""; - for _ in range(0, indent) { - s.push_str(" "); - } - - s.push_str(self.debug_str()); - debug!("{:s}", s); - - // FIXME: this should have a pure version? - for kid in self.children() { - kid.dump_indent(indent + 1u) + fn is_text(&self) -> bool { + // FIXME(pcwalton): Temporary workaround for the lack of inlining of autogenerated `Eq` + // implementations in Rust. + match self.type_id() { + TextNodeTypeId => true, + _ => false } } - /// Returns a string that describes this node. - pub fn debug_str(&self) -> ~str { - format!("{:?}", self.type_id()) - } - - // - // Convenience accessors - // - - pub fn children(&self) -> AbstractNodeChildrenIterator { - self.node().children() - } - - pub fn child_elements(&self) -> Filter<AbstractNode, AbstractNodeChildrenIterator> { - self.node().child_elements() - } - - pub fn is_in_doc(&self) -> bool { - self.node().flags.is_in_doc() - } - - pub fn get_hover_state(&self) -> bool { - self.node().flags.get_in_hover_state() - } - - pub fn set_hover_state(&self, state: bool) { - self.mut_node().flags.set_is_in_hover_state(state); - } -} - -impl AbstractNode { - // http://dom.spec.whatwg.org/#dom-node-appendchild - pub fn AppendChild(self, node: AbstractNode) -> Fallible<AbstractNode> { - self.node().AppendChild(self, node) - } - - // http://dom.spec.whatwg.org/#dom-node-replacechild - pub fn ReplaceChild(self, node: AbstractNode, child: AbstractNode) -> Fallible<AbstractNode> { - self.node().ReplaceChild(self, node, child) - } - - // http://dom.spec.whatwg.org/#dom-node-removechild - pub fn RemoveChild(self, node: AbstractNode) -> Fallible<AbstractNode> { - self.node().RemoveChild(self, node) - } - // http://dom.spec.whatwg.org/#node-is-inserted - fn node_inserted(self) { + fn node_inserted(&self) { assert!(self.parent_node().is_some()); - let document = self.node().owner_doc(); + let mut document = self.get().owner_doc(); // Register elements having "id" attribute to the owner doc. - document.mut_document().register_nodes_with_id(&self); + if self.is_element() { + document.get_mut().register_nodes_with_id(&ElementCast::to(self)); + } - document.document().content_changed(); + document.get().content_changed(); } // http://dom.spec.whatwg.org/#node-is-removed - fn node_removed(self) { + fn node_removed(&self) { assert!(self.parent_node().is_none()); - let document = self.node().owner_doc(); + let mut document = self.get().owner_doc(); // Unregister elements having "id". - document.mut_document().unregister_nodes_with_id(&self); + if self.is_element() { + document.get_mut().unregister_nodes_with_id(&ElementCast::to(self)); + } - document.document().content_changed(); + document.get().content_changed(); } // @@ -622,71 +426,66 @@ impl AbstractNode { /// Adds a new child to the end of this node's list of children. /// /// Fails unless `new_child` is disconnected from the tree. - fn add_child(&self, new_child: AbstractNode, before: Option<AbstractNode>) { - let this_node = self.mut_node(); - let new_child_node = new_child.mut_node(); - assert!(new_child_node.parent_node.is_none()); - assert!(new_child_node.prev_sibling.is_none()); - assert!(new_child_node.next_sibling.is_none()); + fn add_child(&mut self, new_child: &mut JS<Node>, before: Option<JS<Node>>) { + assert!(new_child.parent_node().is_none()); + assert!(new_child.prev_sibling().is_none()); + assert!(new_child.next_sibling().is_none()); match before { - Some(before) => { - let before_node = before.mut_node(); + Some(mut before) => { // XXX Should assert that parent is self. - assert!(before_node.parent_node.is_some()); - match before_node.prev_sibling { + assert!(before.parent_node().is_some()); + match before.prev_sibling() { None => { // XXX Should assert that before is the first child of // self. - this_node.set_first_child(Some(new_child.clone())); + self.get_mut().set_first_child(Some(new_child.clone())); }, - Some(prev_sibling) => { - let prev_sibling_node = prev_sibling.mut_node(); - prev_sibling_node.set_next_sibling(Some(new_child.clone())); - new_child_node.set_prev_sibling(Some(prev_sibling.clone())); + Some(mut prev_sibling) => { + prev_sibling.get_mut().set_next_sibling(Some(new_child.clone())); + new_child.get_mut().set_prev_sibling(Some(prev_sibling.clone())); }, } - before_node.set_prev_sibling(Some(new_child.clone())); - new_child_node.set_next_sibling(Some(before.clone())); + before.get_mut().set_prev_sibling(Some(new_child.clone())); + new_child.get_mut().set_next_sibling(Some(before.clone())); }, None => { - match this_node.last_child { - None => this_node.set_first_child(Some(new_child.clone())), - Some(last_child) => { - let last_child_node = last_child.mut_node(); - assert!(last_child_node.next_sibling.is_none()); - last_child_node.set_next_sibling(Some(new_child.clone())); - new_child_node.set_prev_sibling(Some(last_child.clone())); + match self.last_child() { + None => self.get_mut().set_first_child(Some(new_child.clone())), + Some(mut last_child) => { + assert!(last_child.next_sibling().is_none()); + last_child.get_mut().set_next_sibling(Some(new_child.clone())); + new_child.get_mut().set_prev_sibling(Some(last_child.clone())); } } - this_node.set_last_child(Some(new_child.clone())); + self.get_mut().set_last_child(Some(new_child.clone())); }, } - new_child_node.set_parent_node(Some((*self).clone())); + new_child.get_mut().set_parent_node(Some(self.clone())); } /// Removes the given child from this node's list of children. /// /// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.) - fn remove_child(&self, child: AbstractNode) { - let this_node = self.mut_node(); - let child_node = child.mut_node(); + fn remove_child(&mut self, child: &mut JS<Node>) { + let this_node = self.get_mut(); + let child_node = child.get_mut(); assert!(child_node.parent_node.is_some()); match child_node.prev_sibling { - None => this_node.set_first_child(child_node.next_sibling), - Some(prev_sibling) => { - let prev_sibling_node = prev_sibling.mut_node(); - prev_sibling_node.set_next_sibling(child_node.next_sibling); + None => this_node.set_first_child(child_node.next_sibling.clone()), + Some(ref mut prev_sibling) => { + let prev_sibling_node = prev_sibling.get_mut(); + prev_sibling_node.set_next_sibling(child_node.next_sibling.clone()); } } match child_node.next_sibling { - None => this_node.set_last_child(child_node.prev_sibling), - Some(next_sibling) => { - let next_sibling_node = next_sibling.mut_node(); - next_sibling_node.set_prev_sibling(child_node.prev_sibling); + None => this_node.set_last_child(child_node.prev_sibling.clone()), + Some(ref mut next_sibling) => { + let next_sibling_node = next_sibling.get_mut(); + next_sibling_node.set_prev_sibling(child_node.prev_sibling.clone()); } } @@ -694,20 +493,89 @@ impl AbstractNode { child_node.set_next_sibling(None); child_node.set_parent_node(None); } + + fn get_hover_state(&self) -> bool { + self.get().flags.get_in_hover_state() + } + + fn set_hover_state(&mut self, state: bool) { + self.get_mut().flags.set_is_in_hover_state(state); + } + + /// Iterates over this node and all its descendants, in preorder. + fn traverse_preorder(&self) -> TreeIterator { + let mut nodes = ~[]; + gather_abstract_nodes(self, &mut nodes, false); + TreeIterator::new(nodes) + } + + /// Iterates over this node and all its descendants, in postorder. + fn sequential_traverse_postorder(&self) -> TreeIterator { + let mut nodes = ~[]; + gather_abstract_nodes(self, &mut nodes, true); + TreeIterator::new(nodes) + } + + fn inclusively_following_siblings(&self) -> AbstractNodeChildrenIterator { + AbstractNodeChildrenIterator { + current_node: Some(self.clone()), + } + } + + fn is_inclusive_ancestor_of(&self, parent: &JS<Node>) -> bool { + self == parent || parent.ancestors().any(|ancestor| ancestor == *self) + } + + fn following_siblings(&self) -> AbstractNodeChildrenIterator { + AbstractNodeChildrenIterator { + current_node: self.next_sibling(), + } + } + + fn is_parent_of(&self, child: &JS<Node>) -> bool { + match child.parent_node() { + Some(ref parent) if parent == self => true, + _ => false + } + } + + /// If the given untrusted node address represents a valid DOM node in the given runtime, + /// returns it. + fn from_untrusted_node_address(runtime: *JSRuntime, candidate: UntrustedNodeAddress) + -> JS<Node> { + unsafe { + let candidate: uintptr_t = cast::transmute(candidate); + let object: *JSObject = jsfriendapi::bindgen::JS_GetAddressableObject(runtime, + candidate); + if object.is_null() { + fail!("Attempted to create a `JS<Node>` from an invalid pointer!") + } + let boxed_node: *mut Box<Node> = utils::unwrap(object); + JS::from_box(boxed_node) + } + } + + fn to_trusted_node_address(&self) -> TrustedNodeAddress { + self.get() as *Node as TrustedNodeAddress + } } // // Iteration and traversal // +type ChildElementIterator<'a> = Map<'a, JS<Node>, + JS<Element>, + Filter<'a, JS<Node>, AbstractNodeChildrenIterator>>; + pub struct AbstractNodeChildrenIterator { - priv current_node: Option<AbstractNode>, + priv current_node: Option<JS<Node>>, } -impl Iterator<AbstractNode> for AbstractNodeChildrenIterator { - fn next(&mut self) -> Option<AbstractNode> { - let node = self.current_node; - self.current_node = self.current_node.and_then(|node| { +impl Iterator<JS<Node>> for AbstractNodeChildrenIterator { + fn next(&mut self) -> Option<JS<Node>> { + let node = self.current_node.clone(); + self.current_node = node.clone().and_then(|node| { node.next_sibling() }); node @@ -715,11 +583,11 @@ impl Iterator<AbstractNode> for AbstractNodeChildrenIterator { } pub struct AncestorIterator { - priv current: Option<AbstractNode>, + priv current: Option<JS<Node>>, } -impl Iterator<AbstractNode> for AncestorIterator { - fn next(&mut self) -> Option<AbstractNode> { +impl Iterator<JS<Node>> for AncestorIterator { + fn next(&mut self) -> Option<JS<Node>> { if self.current.is_none() { return None; } @@ -734,12 +602,12 @@ impl Iterator<AbstractNode> for AncestorIterator { // FIXME: Do this without precomputing a vector of refs. // Easy for preorder; harder for postorder. pub struct TreeIterator { - priv nodes: ~[AbstractNode], + priv nodes: ~[JS<Node>], priv index: uint, } impl TreeIterator { - fn new(nodes: ~[AbstractNode]) -> TreeIterator { + fn new(nodes: ~[JS<Node>]) -> TreeIterator { TreeIterator { nodes: nodes, index: 0, @@ -747,8 +615,8 @@ impl TreeIterator { } } -impl Iterator<AbstractNode> for TreeIterator { - fn next(&mut self) -> Option<AbstractNode> { +impl Iterator<JS<Node>> for TreeIterator { + fn next(&mut self) -> Option<JS<Node>> { if self.index >= self.nodes.len() { None } else { @@ -760,15 +628,15 @@ impl Iterator<AbstractNode> for TreeIterator { } pub struct NodeIterator { - start_node: AbstractNode, - current_node: Option<AbstractNode>, + start_node: JS<Node>, + current_node: Option<JS<Node>>, depth: uint, priv include_start: bool, priv include_descendants_of_void: bool } impl NodeIterator { - pub fn new(start_node: AbstractNode, include_start: bool, include_descendants_of_void: bool) -> NodeIterator { + pub fn new(start_node: JS<Node>, include_start: bool, include_descendants_of_void: bool) -> NodeIterator { NodeIterator { start_node: start_node, current_node: None, @@ -778,44 +646,42 @@ impl NodeIterator { } } - fn next_child(&self, node: AbstractNode) -> Option<AbstractNode> { - if !self.include_descendants_of_void && - node.is_element() { - node.with_imm_element(|elem| { - if elem.is_void() { - None - } else { - node.first_child() - } - }) + fn next_child(&self, node: &JS<Node>) -> Option<JS<Node>> { + if !self.include_descendants_of_void && node.is_element() { + let elem: JS<Element> = ElementCast::to(node); + if elem.get().is_void() { + None + } else { + node.first_child() + } } else { node.first_child() } } } -impl Iterator<AbstractNode> for NodeIterator { - fn next(&mut self) -> Option<AbstractNode> { +impl Iterator<JS<Node>> for NodeIterator { + fn next(&mut self) -> Option<JS<Node>> { self.current_node = match self.current_node { None => { if self.include_start { - Some(self.start_node) + Some(self.start_node.clone()) } else { - self.next_child(self.start_node) + self.next_child(&self.start_node) } }, - Some(node) => { + Some(ref node) => { match self.next_child(node) { Some(child) => { self.depth += 1; - Some(child) + Some(child.clone()) }, - None if node == self.start_node => None, + None if node == &self.start_node => None, None => { match node.next_sibling() { Some(sibling) => Some(sibling), None => { - let mut candidate = node; + let mut candidate = node.clone(); while candidate.next_sibling().is_none() { candidate = candidate.parent_node().expect("Got to root without reaching start node"); self.depth -= 1; @@ -834,11 +700,11 @@ impl Iterator<AbstractNode> for NodeIterator { } } }; - self.current_node + self.current_node.clone() } } -fn gather_abstract_nodes(cur: &AbstractNode, refs: &mut ~[AbstractNode], postorder: bool) { +fn gather_abstract_nodes(cur: &JS<Node>, refs: &mut ~[JS<Node>], postorder: bool) { if !postorder { refs.push(cur.clone()); } @@ -850,75 +716,48 @@ fn gather_abstract_nodes(cur: &AbstractNode, refs: &mut ~[AbstractNode], postord } } -impl AbstractNode { - /// Iterates over all ancestors of this node. +impl Node { pub fn ancestors(&self) -> AncestorIterator { AncestorIterator { - current: self.parent_node(), - } - } - - pub fn inclusively_following_siblings(&self) -> AbstractNodeChildrenIterator { - AbstractNodeChildrenIterator { - current_node: Some(*self), + current: self.parent_node.clone(), } } - pub fn following_siblings(&self) -> AbstractNodeChildrenIterator { - AbstractNodeChildrenIterator { - current_node: self.next_sibling(), - } - } - - /// Iterates over this node and all its descendants, in preorder. - pub fn traverse_preorder(&self) -> TreeIterator { - let mut nodes = ~[]; - gather_abstract_nodes(self, &mut nodes, false); - TreeIterator::new(nodes) - } - - /// Iterates over this node and all its descendants, in postorder. - pub fn sequential_traverse_postorder(&self) -> TreeIterator { - let mut nodes = ~[]; - gather_abstract_nodes(self, &mut nodes, true); - TreeIterator::new(nodes) - } -} - -impl Node { - pub fn owner_doc(&self) -> AbstractDocument { - self.owner_doc.unwrap() + pub fn owner_doc(&self) -> JS<Document> { + self.owner_doc.clone().unwrap() } - pub fn set_owner_doc(&mut self, document: AbstractDocument) { - self.owner_doc = Some(document); + pub fn set_owner_doc(&mut self, document: &JS<Document>) { + self.owner_doc = Some(document.clone()); } pub fn children(&self) -> AbstractNodeChildrenIterator { AbstractNodeChildrenIterator { - current_node: self.first_child, + current_node: self.first_child.clone(), } } - pub fn child_elements(&self) -> Filter<AbstractNode, AbstractNodeChildrenIterator> { - self.children().filter(|node| node.is_element()) + pub fn child_elements(&self) -> ChildElementIterator { + self.children() + .filter(|node| node.is_element()) + .map(|node| { + let elem: JS<Element> = ElementCast::to(&node); + elem + }) } - pub fn reflect_node<N: Reflectable> - (node: @mut N, - document: AbstractDocument, - wrap_fn: extern "Rust" fn(*JSContext, *JSObject, @mut N) -> *JSObject) - -> AbstractNode { + pub fn reflect_node<N: Reflectable+NodeBase> + (node: ~N, + document: &JS<Document>, + wrap_fn: extern "Rust" fn(*JSContext, *JSObject, ~N) -> *JSObject) + -> JS<N> { assert!(node.reflector().get_jsobject().is_null()); - let node = reflect_dom_object(node, document.document().window, wrap_fn); + let node = reflect_dom_object(node, document.get().window.get(), wrap_fn); assert!(node.reflector().get_jsobject().is_not_null()); - // JS owns the node now, so transmute_copy to not increase the refcount - AbstractNode { - obj: unsafe { cast::transmute_copy(&node) }, - } + node } - pub fn new_inherited(type_id: NodeTypeId, doc: AbstractDocument) -> Node { + pub fn new_inherited(type_id: NodeTypeId, doc: JS<Document>) -> Node { Node::new_(type_id, Some(doc)) } @@ -926,13 +765,11 @@ impl Node { Node::new_(type_id, None) } - fn new_(type_id: NodeTypeId, doc: Option<AbstractDocument>) -> Node { + fn new_(type_id: NodeTypeId, doc: Option<JS<Document>>) -> Node { Node { - eventtarget: EventTarget::new_inherited(NodeTypeId), + eventtarget: EventTarget::new_inherited(NodeTargetTypeId(type_id)), type_id: type_id, - abstract: None, - parent_node: None, first_child: None, last_child: None, @@ -967,34 +804,32 @@ impl Node { TextNodeTypeId => 3, ProcessingInstructionNodeTypeId => 7, CommentNodeTypeId => 8, - DocumentNodeTypeId(_) => 9, + DocumentNodeTypeId => 9, DoctypeNodeTypeId => 10, DocumentFragmentNodeTypeId => 11, } } // http://dom.spec.whatwg.org/#dom-node-nodename - pub fn NodeName(&self, abstract_self: AbstractNode) -> DOMString { + pub fn NodeName(&self, abstract_self: &JS<Node>) -> DOMString { match self.type_id { ElementNodeTypeId(..) => { - abstract_self.with_imm_element(|element| { - element.TagName() - }) + let elem: JS<Element> = ElementCast::to(abstract_self); + elem.get().TagName() } TextNodeTypeId => ~"#text", ProcessingInstructionNodeTypeId => { - abstract_self.with_imm_processing_instruction(|processing_instruction| { - processing_instruction.Target() - }) + let processing_instruction: JS<ProcessingInstruction> = + ProcessingInstructionCast::to(abstract_self); + processing_instruction.get().Target() } CommentNodeTypeId => ~"#comment", DoctypeNodeTypeId => { - abstract_self.with_imm_doctype(|doctype| { - doctype.name.clone() - }) + let doctype: JS<DocumentType> = DocumentTypeCast::to(abstract_self); + doctype.get().name.clone() }, DocumentFragmentNodeTypeId => ~"#document-fragment", - DocumentNodeTypeId(_) => ~"#document" + DocumentNodeTypeId => ~"#document" } } @@ -1004,7 +839,7 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-ownerdocument - pub fn GetOwnerDocument(&self) -> Option<AbstractDocument> { + pub fn GetOwnerDocument(&self) -> Option<JS<Document>> { match self.type_id { ElementNodeTypeId(..) | CommentNodeTypeId | @@ -1012,18 +847,20 @@ impl Node { ProcessingInstructionNodeTypeId | DoctypeNodeTypeId | DocumentFragmentNodeTypeId => Some(self.owner_doc()), - DocumentNodeTypeId(_) => None + DocumentNodeTypeId => None } } // http://dom.spec.whatwg.org/#dom-node-parentnode - pub fn GetParentNode(&self) -> Option<AbstractNode> { - self.parent_node + pub fn GetParentNode(&self) -> Option<JS<Node>> { + self.parent_node.clone() } // http://dom.spec.whatwg.org/#dom-node-parentelement - pub fn GetParentElement(&self) -> Option<AbstractNode> { - self.parent_node.filtered(|parent| parent.is_element()) + pub fn GetParentElement(&self) -> Option<JS<Element>> { + self.parent_node.clone() + .filtered(|parent| parent.is_element()) + .map(|node| ElementCast::to(&node)) } // http://dom.spec.whatwg.org/#dom-node-haschildnodes @@ -1032,34 +869,33 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-firstchild - pub fn GetFirstChild(&self) -> Option<AbstractNode> { - self.first_child + pub fn GetFirstChild(&self) -> Option<JS<Node>> { + self.first_child.clone() } // http://dom.spec.whatwg.org/#dom-node-lastchild - pub fn GetLastChild(&self) -> Option<AbstractNode> { - self.last_child + pub fn GetLastChild(&self) -> Option<JS<Node>> { + self.last_child.clone() } // http://dom.spec.whatwg.org/#dom-node-previoussibling - pub fn GetPreviousSibling(&self) -> Option<AbstractNode> { - self.prev_sibling + pub fn GetPreviousSibling(&self) -> Option<JS<Node>> { + self.prev_sibling.clone() } // http://dom.spec.whatwg.org/#dom-node-nextsibling - pub fn GetNextSibling(&self) -> Option<AbstractNode> { - self.next_sibling + pub fn GetNextSibling(&self) -> Option<JS<Node>> { + self.next_sibling.clone() } // http://dom.spec.whatwg.org/#dom-node-nodevalue - pub fn GetNodeValue(&self, abstract_self: AbstractNode) -> Option<DOMString> { + pub fn GetNodeValue(&self, abstract_self: &JS<Node>) -> Option<DOMString> { match self.type_id { CommentNodeTypeId | TextNodeTypeId | ProcessingInstructionNodeTypeId => { - abstract_self.with_imm_characterdata(|characterdata| { - Some(characterdata.Data()) - }) + let chardata: JS<CharacterData> = CharacterDataCast::to(abstract_self); + Some(chardata.get().Data()) } _ => { None @@ -1068,23 +904,22 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-nodevalue - pub fn SetNodeValue(&mut self, _abstract_self: AbstractNode, _val: Option<DOMString>) + pub fn SetNodeValue(&mut self, _abstract_self: &JS<Node>, _val: Option<DOMString>) -> ErrorResult { // FIXME: Stub - https://github.com/mozilla/servo/issues/1655 Ok(()) } // http://dom.spec.whatwg.org/#dom-node-textcontent - pub fn GetTextContent(&self, abstract_self: AbstractNode) -> Option<DOMString> { + pub fn GetTextContent(&self, abstract_self: &JS<Node>) -> Option<DOMString> { match self.type_id { DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => { let mut content = ~""; for node in abstract_self.traverse_preorder() { if node.is_text() { - node.with_imm_text(|text| { - content.push_str(text.characterdata.data.as_slice()); - }) + let text: JS<Text> = TextCast::to(&node); + content.push_str(text.get().characterdata.data.as_slice()); } } Some(content) @@ -1092,42 +927,42 @@ impl Node { CommentNodeTypeId | TextNodeTypeId | ProcessingInstructionNodeTypeId => { - abstract_self.with_imm_characterdata(|characterdata| { - Some(characterdata.Data()) - }) + let characterdata: JS<CharacterData> = CharacterDataCast::to(abstract_self); + Some(characterdata.get().Data()) } DoctypeNodeTypeId | - DocumentNodeTypeId(_) => { + DocumentNodeTypeId => { None } } } // http://dom.spec.whatwg.org/#dom-node-childnodes - pub fn ChildNodes(&mut self, abstract_self: AbstractNode) -> @mut NodeList { + pub fn ChildNodes(&mut self, abstract_self: &JS<Node>) -> JS<NodeList> { match self.child_list { None => { - let window = self.owner_doc().document().window; - let list = NodeList::new_child_list(window, abstract_self); - self.child_list = Some(list); + let doc = self.owner_doc(); + let doc = doc.get(); + let list = NodeList::new_child_list(&doc.window, abstract_self); + self.child_list = Some(list.clone()); list } - Some(list) => list + Some(ref list) => list.clone() } } // http://dom.spec.whatwg.org/#concept-node-adopt - fn adopt(node: AbstractNode, document: AbstractDocument) { + fn adopt(node: &mut JS<Node>, document: &JS<Document>) { // Step 1. match node.parent_node() { - Some(parent) => Node::remove(node, parent, Unsuppressed), + Some(ref mut parent) => Node::remove(node, parent, Unsuppressed), None => (), } // Step 2. - if node.node().owner_doc() != document { - for descendant in node.traverse_preorder() { - descendant.mut_node().set_owner_doc(document); + if node.get().owner_doc() != *document { + for mut descendant in node.traverse_preorder() { + descendant.get_mut().set_owner_doc(document); } } @@ -1136,11 +971,11 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-pre-insert - fn pre_insert(node: AbstractNode, parent: AbstractNode, child: Option<AbstractNode>) - -> Fallible<AbstractNode> { + fn pre_insert(node: &mut JS<Node>, parent: &mut JS<Node>, child: Option<JS<Node>>) + -> Fallible<JS<Node>> { // Step 1. match parent.type_id() { - DocumentNodeTypeId(..) | + DocumentNodeTypeId | DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => (), _ => return Err(HierarchyRequest) @@ -1153,7 +988,7 @@ impl Node { // Step 3. match child { - Some(child) if !parent.is_parent_of(child) => return Err(NotFound), + Some(ref child) if !parent.is_parent_of(child) => return Err(NotFound), _ => () } @@ -1161,13 +996,13 @@ impl Node { match node.type_id() { TextNodeTypeId => { match node.parent_node() { - Some(parent) if parent.is_document() => return Err(HierarchyRequest), + Some(ref parent) if parent.is_document() => return Err(HierarchyRequest), _ => () } } DoctypeNodeTypeId => { match node.parent_node() { - Some(parent) if !parent.is_document() => return Err(HierarchyRequest), + Some(ref parent) if !parent.is_document() => return Err(HierarchyRequest), _ => () } } @@ -1175,12 +1010,12 @@ impl Node { ElementNodeTypeId(_) | ProcessingInstructionNodeTypeId | CommentNodeTypeId => (), - DocumentNodeTypeId(..) => return Err(HierarchyRequest) + DocumentNodeTypeId => return Err(HierarchyRequest) } // Step 6. match parent.type_id() { - DocumentNodeTypeId(_) => { + DocumentNodeTypeId => { match node.type_id() { // Step 6.1 DocumentFragmentNodeTypeId => { @@ -1198,8 +1033,8 @@ impl Node { return Err(HierarchyRequest); } match child { - Some(child) if child.inclusively_following_siblings() - .any(|child| child.is_doctype()) => { + Some(ref child) if child.inclusively_following_siblings() + .any(|child| child.is_doctype()) => { return Err(HierarchyRequest); } _ => (), @@ -1217,8 +1052,8 @@ impl Node { return Err(HierarchyRequest); } match child { - Some(child) if child.inclusively_following_siblings() - .any(|child| child.is_doctype()) => { + Some(ref child) if child.inclusively_following_siblings() + .any(|child| child.is_doctype()) => { return Err(HierarchyRequest); } _ => (), @@ -1230,9 +1065,9 @@ impl Node { return Err(HierarchyRequest); } match child { - Some(child) => { + Some(ref child) => { if parent.children() - .take_while(|&c| c != child) + .take_while(|c| c != child) .any(|c| c.is_element()) { return Err(HierarchyRequest); } @@ -1249,48 +1084,47 @@ impl Node { TextNodeTypeId | ProcessingInstructionNodeTypeId | CommentNodeTypeId => (), - DocumentNodeTypeId(_) => unreachable!(), + DocumentNodeTypeId => unreachable!(), } }, _ => (), } // Step 7-8. - let referenceChild = if child != Some(node) { - child - } else { - node.next_sibling() + let referenceChild = match child { + Some(ref child) if child == node => node.next_sibling(), + _ => child }; // Step 9. - Node::adopt(node, parent.node().owner_doc()); + Node::adopt(node, &parent.get().owner_doc()); // Step 10. Node::insert(node, parent, referenceChild, Unsuppressed); // Step 11. - return Ok(node) + return Ok(node.clone()) } // http://dom.spec.whatwg.org/#concept-node-insert - fn insert(node: AbstractNode, - parent: AbstractNode, - child: Option<AbstractNode>, + fn insert(node: &mut JS<Node>, + parent: &mut JS<Node>, + child: Option<JS<Node>>, suppress_observers: SuppressObserver) { // XXX assert owner_doc // Step 1-3: ranges. // Step 4. - let nodes = match node.type_id() { + let mut nodes = match node.type_id() { DocumentFragmentNodeTypeId => node.children().collect(), - _ => ~[node], + _ => ~[node.clone()], }; // Step 5: DocumentFragment, mutation records. // Step 6: DocumentFragment. match node.type_id() { DocumentFragmentNodeTypeId => { - for c in node.children() { - Node::remove(c, node, Suppressed); + for mut c in node.children() { + Node::remove(&mut c, node, Suppressed); } }, _ => (), @@ -1298,9 +1132,9 @@ impl Node { // Step 7: mutation records. // Step 8. - for node in nodes.iter() { - parent.add_child(*node, child); - node.mut_node().flags.set_is_in_doc(parent.is_in_doc()); + for node in nodes.mut_iter() { + parent.add_child(node, child.clone()); + node.get_mut().flags.set_is_in_doc(parent.is_in_doc()); } // Step 9. @@ -1315,33 +1149,33 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-replace-all - pub fn replace_all(node: Option<AbstractNode>, parent: AbstractNode) { + pub fn replace_all(mut node: Option<JS<Node>>, parent: &mut JS<Node>) { // Step 1. match node { - Some(node) => Node::adopt(node, parent.node().owner_doc()), + Some(ref mut node) => Node::adopt(node, &parent.get().owner_doc()), None => (), } // Step 2. - let removedNodes: ~[AbstractNode] = parent.children().collect(); + let removedNodes: ~[JS<Node>] = parent.children().collect(); // Step 3. let addedNodes = match node { None => ~[], - Some(node) => match node.type_id() { + Some(ref node) => match node.type_id() { DocumentFragmentNodeTypeId => node.children().collect(), - _ => ~[node], + _ => ~[node.clone()], }, }; // Step 4. - for child in parent.children() { - Node::remove(child, parent, Suppressed); + for mut child in parent.children() { + Node::remove(&mut child, parent, Suppressed); } // Step 5. match node { - Some(node) => Node::insert(node, parent, None, Suppressed), + Some(ref mut node) => Node::insert(node, parent, None, Suppressed), None => (), } @@ -1357,28 +1191,29 @@ impl Node { } // http://dom.spec.whatwg.org/#concept-node-pre-remove - fn pre_remove(child: AbstractNode, parent: AbstractNode) -> Fallible<AbstractNode> { + fn pre_remove(child: &mut JS<Node>, parent: &mut JS<Node>) -> Fallible<JS<Node>> { // Step 1. - if child.parent_node() != Some(parent) { - return Err(NotFound); + match child.parent_node() { + Some(ref node) if node != parent => return Err(NotFound), + _ => () } // Step 2. Node::remove(child, parent, Unsuppressed); // Step 3. - Ok(child) + Ok(child.clone()) } // http://dom.spec.whatwg.org/#concept-node-remove - fn remove(node: AbstractNode, parent: AbstractNode, suppress_observers: SuppressObserver) { - assert!(node.parent_node() == Some(parent)); + fn remove(node: &mut JS<Node>, parent: &mut JS<Node>, suppress_observers: SuppressObserver) { + assert!(node.parent_node().map_default(false, |ref node_parent| node_parent == parent)); // Step 1-5: ranges. // Step 6-7: mutation observers. // Step 8. parent.remove_child(node); - node.mut_node().flags.set_is_in_doc(false); + node.get_mut().flags.set_is_in_doc(false); // Step 9. match suppress_observers { @@ -1388,7 +1223,7 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-textcontent - pub fn SetTextContent(&mut self, abstract_self: AbstractNode, value: Option<DOMString>) + pub fn SetTextContent(&mut self, abstract_self: &mut JS<Node>, value: Option<DOMString>) -> ErrorResult { let value = null_str_as_empty(&value); match self.type_id { @@ -1399,7 +1234,7 @@ impl Node { None } else { let document = self.owner_doc(); - Some(document.document().CreateTextNode(document, value)) + Some(NodeCast::from(&document.get().CreateTextNode(&document, value))) }; // Step 3. Node::replace_all(node, abstract_self); @@ -1409,43 +1244,42 @@ impl Node { ProcessingInstructionNodeTypeId => { self.wait_until_safe_to_modify_dom(); - abstract_self.with_mut_characterdata(|characterdata| { - characterdata.data = value.clone(); + let mut characterdata: JS<CharacterData> = CharacterDataCast::to(abstract_self); + characterdata.get_mut().data = value.clone(); - // Notify the document that the content of this node is different - let document = self.owner_doc(); - document.document().content_changed(); - }) + // Notify the document that the content of this node is different + let document = self.owner_doc(); + document.get().content_changed(); } DoctypeNodeTypeId | - DocumentNodeTypeId(_) => {} + DocumentNodeTypeId => {} } Ok(()) } // http://dom.spec.whatwg.org/#dom-node-insertbefore - pub fn InsertBefore(&self, abstract_self: AbstractNode, node: AbstractNode, child: Option<AbstractNode>) - -> Fallible<AbstractNode> { + pub fn InsertBefore(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>, child: Option<JS<Node>>) + -> Fallible<JS<Node>> { Node::pre_insert(node, abstract_self, child) } pub fn wait_until_safe_to_modify_dom(&self) { let document = self.owner_doc(); - document.document().wait_until_safe_to_modify_dom(); + document.get().wait_until_safe_to_modify_dom(); } // http://dom.spec.whatwg.org/#dom-node-appendchild - pub fn AppendChild(&self, abstract_self: AbstractNode, node: AbstractNode) - -> Fallible<AbstractNode> { + pub fn AppendChild(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>) + -> Fallible<JS<Node>> { Node::pre_insert(node, abstract_self, None) } // http://dom.spec.whatwg.org/#concept-node-replace - pub fn ReplaceChild(&self, parent: AbstractNode, node: AbstractNode, child: AbstractNode) - -> Fallible<AbstractNode> { + pub fn ReplaceChild(&self, parent: &mut JS<Node>, node: &mut JS<Node>, child: &mut JS<Node>) + -> Fallible<JS<Node>> { // Step 1. match parent.type_id() { - DocumentNodeTypeId(..) | + DocumentNodeTypeId | DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => (), _ => return Err(HierarchyRequest) @@ -1471,12 +1305,12 @@ impl Node { TextNodeTypeId | ProcessingInstructionNodeTypeId | CommentNodeTypeId => (), - DocumentNodeTypeId(..) => return Err(HierarchyRequest) + DocumentNodeTypeId => return Err(HierarchyRequest) } // Step 6. match parent.type_id() { - DocumentNodeTypeId(..) => { + DocumentNodeTypeId => { match node.type_id() { // Step 6.1 DocumentFragmentNodeTypeId => { @@ -1488,7 +1322,7 @@ impl Node { 0 => (), // Step 6.1.2 1 => { - if parent.child_elements().any(|c| c != child) { + if parent.child_elements().any(|c| &NodeCast::from(&c) != child) { return Err(HierarchyRequest); } if child.following_siblings() @@ -1502,7 +1336,7 @@ impl Node { }, // Step 6.2 ElementNodeTypeId(..) => { - if parent.child_elements().any(|c| c != child) { + if parent.child_elements().any(|c| &NodeCast::from(&c) != child) { return Err(HierarchyRequest); } if child.following_siblings() @@ -1512,11 +1346,11 @@ impl Node { }, // Step 6.3 DoctypeNodeTypeId => { - if parent.children().any(|c| c.is_doctype() && c != child) { + if parent.children().any(|c| c.is_doctype() && &c != child) { return Err(HierarchyRequest); } if parent.children() - .take_while(|&c| c != child) + .take_while(|c| c != child) .any(|c| c.is_element()) { return Err(HierarchyRequest); } @@ -1524,26 +1358,26 @@ impl Node { TextNodeTypeId | ProcessingInstructionNodeTypeId | CommentNodeTypeId => (), - DocumentNodeTypeId(..) => unreachable!() + DocumentNodeTypeId => unreachable!() } }, _ => () } // Ok if not caught by previous error checks. - if node == child { - return Ok(child); + if *node == *child { + return Ok(child.clone()); } // Step 7-8. - let reference_child = if child.next_sibling() != Some(node) { - child.next_sibling() - } else { - node.next_sibling() + let next_sibling = child.next_sibling(); + let reference_child = match next_sibling { + Some(ref sibling) if sibling == node => node.next_sibling(), + _ => next_sibling }; // Step 9. - Node::adopt(node, parent.node().owner_doc()); + Node::adopt(node, &parent.get().owner_doc()); { // Step 10. @@ -1565,12 +1399,12 @@ impl Node { } // Step 15. - Ok(child) + Ok(child.clone()) } // http://dom.spec.whatwg.org/#dom-node-removechild - pub fn RemoveChild(&self, abstract_self: AbstractNode, node: AbstractNode) - -> Fallible<AbstractNode> { + pub fn RemoveChild(&self, abstract_self: &mut JS<Node>, node: &mut JS<Node>) + -> Fallible<JS<Node>> { Node::pre_remove(node, abstract_self) } @@ -1580,62 +1414,52 @@ impl Node { } // http://dom.spec.whatwg.org/#dom-node-clonenode - pub fn CloneNode(&self, _deep: bool) -> Fallible<AbstractNode> { + pub fn CloneNode(&self, _deep: bool) -> Fallible<JS<Node>> { // FIXME: stub - https://github.com/mozilla/servo/issues/1240 fail!("stub") } // http://dom.spec.whatwg.org/#dom-node-isequalnode - pub fn IsEqualNode(&self, abstract_self: AbstractNode, maybe_node: Option<AbstractNode>) -> bool { - fn is_equal_doctype(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_doctype(|doctype| { - other.with_imm_doctype(|other_doctype| { - (doctype.name == other_doctype.name) && - (doctype.public_id == other_doctype.public_id) && - (doctype.system_id == other_doctype.system_id) - }) - }) - } - fn is_equal_element(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_element(|element| { - other.with_imm_element(|other_element| { - // FIXME: namespace prefix - (element.namespace == other_element.namespace) && - (element.tag_name == other_element.tag_name) && - (element.attrs.len() == other_element.attrs.len()) - }) - }) - } - fn is_equal_processinginstruction(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_processing_instruction(|pi| { - other.with_imm_processing_instruction(|other_pi| { - (pi.target == other_pi.target) && - (pi.characterdata.data == other_pi.characterdata.data) - }) - }) - } - fn is_equal_characterdata(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_characterdata(|characterdata| { - other.with_imm_characterdata(|other_characterdata| { - characterdata.data == other_characterdata.data - }) - }) - } - fn is_equal_element_attrs(node: AbstractNode, other: AbstractNode) -> bool { - node.with_imm_element(|element| { - other.with_imm_element(|other_element| { - assert!(element.attrs.len() == other_element.attrs.len()); - element.attrs.iter().all(|attr| { - other_element.attrs.iter().any(|other_attr| { - (attr.namespace == other_attr.namespace) && - (attr.local_name == other_attr.local_name) && - (attr.value == other_attr.value) - }) - }) + pub fn IsEqualNode(&self, abstract_self: &JS<Node>, maybe_node: Option<JS<Node>>) -> bool { + fn is_equal_doctype(node: &JS<Node>, other: &JS<Node>) -> bool { + let doctype: JS<DocumentType> = DocumentTypeCast::to(node); + let other_doctype: JS<DocumentType> = DocumentTypeCast::to(other); + (doctype.get().name == other_doctype.get().name) && + (doctype.get().public_id == other_doctype.get().public_id) && + (doctype.get().system_id == other_doctype.get().system_id) + } + fn is_equal_element(node: &JS<Node>, other: &JS<Node>) -> bool { + let element: JS<Element> = ElementCast::to(node); + let other_element: JS<Element> = ElementCast::to(other); + // FIXME: namespace prefix + (element.get().namespace == other_element.get().namespace) && + (element.get().tag_name == other_element.get().tag_name) && + (element.get().attrs.len() == other_element.get().attrs.len()) + } + fn is_equal_processinginstruction(node: &JS<Node>, other: &JS<Node>) -> bool { + let pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(node); + let other_pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(other); + (pi.get().target == other_pi.get().target) && + (pi.get().characterdata.data == other_pi.get().characterdata.data) + } + fn is_equal_characterdata(node: &JS<Node>, other: &JS<Node>) -> bool { + let characterdata: JS<CharacterData> = CharacterDataCast::to(node); + let other_characterdata: JS<CharacterData> = CharacterDataCast::to(other); + characterdata.get().data == other_characterdata.get().data + } + fn is_equal_element_attrs(node: &JS<Node>, other: &JS<Node>) -> bool { + let element: JS<Element> = ElementCast::to(node); + let other_element: JS<Element> = ElementCast::to(other); + assert!(element.get().attrs.len() == other_element.get().attrs.len()); + element.get().attrs.iter().all(|attr| { + other_element.get().attrs.iter().any(|other_attr| { + (attr.get().namespace == other_attr.get().namespace) && + (attr.get().local_name == other_attr.get().local_name) && + (attr.get().value == other_attr.get().value) }) }) } - fn is_equal_node(this: AbstractNode, node: AbstractNode) -> bool { + fn is_equal_node(this: &JS<Node>, node: &JS<Node>) -> bool { // Step 2. if this.type_id() != node.type_id() { return false; @@ -1659,27 +1483,27 @@ impl Node { } // Step 6. - this.children().zip(node.children()).all(|(child, other_child)| is_equal_node(child, other_child)) + this.children().zip(node.children()).all(|(ref child, ref other_child)| is_equal_node(child, other_child)) } match maybe_node { // Step 1. None => false, // Step 2-6. - Some(node) => is_equal_node(abstract_self, node) + Some(ref node) => is_equal_node(abstract_self, node) } } // http://dom.spec.whatwg.org/#dom-node-comparedocumentposition - pub fn CompareDocumentPosition(&self, _other: AbstractNode) -> u16 { + pub fn CompareDocumentPosition(&self, _other: &JS<Node>) -> u16 { // FIXME: stub - https://github.com/mozilla/servo/issues/1655 0 } // http://dom.spec.whatwg.org/#dom-node-contains - pub fn Contains(&self, abstract_self: AbstractNode, maybe_other: Option<AbstractNode>) -> bool { + pub fn Contains(&self, abstract_self: &JS<Node>, maybe_other: Option<JS<Node>>) -> bool { match maybe_other { None => false, - Some(other) => abstract_self.is_inclusive_ancestor_of(other) + Some(ref other) => abstract_self.is_inclusive_ancestor_of(other) } } @@ -1725,33 +1549,33 @@ impl Node { // Low-level pointer stitching // - pub fn set_parent_node(&mut self, new_parent_node: Option<AbstractNode>) { + pub fn set_parent_node(&mut self, new_parent_node: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.parent_node = new_parent_node } - pub fn set_first_child(&mut self, new_first_child: Option<AbstractNode>) { + pub fn set_first_child(&mut self, new_first_child: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.first_child = new_first_child } - pub fn set_last_child(&mut self, new_last_child: Option<AbstractNode>) { + pub fn set_last_child(&mut self, new_last_child: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.last_child = new_last_child } - pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<AbstractNode>) { + pub fn set_prev_sibling(&mut self, new_prev_sibling: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.prev_sibling = new_prev_sibling } - pub fn set_next_sibling(&mut self, new_next_sibling: Option<AbstractNode>) { + pub fn set_next_sibling(&mut self, new_next_sibling: Option<JS<Node>>) { let doc = self.owner_doc(); - doc.document().wait_until_safe_to_modify_dom(); + doc.get().wait_until_safe_to_modify_dom(); self.next_sibling = new_next_sibling } diff --git a/src/components/script/dom/nodelist.rs b/src/components/script/dom/nodelist.rs index 6857add6600..84de1a56d19 100644 --- a/src/components/script/dom/nodelist.rs +++ b/src/components/script/dom/nodelist.rs @@ -3,43 +3,46 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::NodeListBinding; +use dom::bindings::js::JS; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -use dom::node::AbstractNode; +use dom::node::{Node, NodeHelpers}; use dom::window::Window; +#[deriving(Encodable)] enum NodeListType { - Simple(~[AbstractNode]), - Children(AbstractNode) + Simple(~[JS<Node>]), + Children(JS<Node>) } +#[deriving(Encodable)] pub struct NodeList { list_type: NodeListType, reflector_: Reflector, - window: @mut Window, + window: JS<Window> } impl NodeList { - pub fn new_inherited(window: @mut Window, + pub fn new_inherited(window: JS<Window>, list_type: NodeListType) -> NodeList { NodeList { list_type: list_type, reflector_: Reflector::new(), - window: window, + window: window } } - pub fn new(window: @mut Window, - list_type: NodeListType) -> @mut NodeList { - reflect_dom_object(@mut NodeList::new_inherited(window, list_type), - window, NodeListBinding::Wrap) + pub fn new(window: JS<Window>, + list_type: NodeListType) -> JS<NodeList> { + reflect_dom_object(~NodeList::new_inherited(window.clone(), list_type), + window.get(), NodeListBinding::Wrap) } - pub fn new_simple_list(window: @mut Window, elements: ~[AbstractNode]) -> @mut NodeList { - NodeList::new(window, Simple(elements)) + pub fn new_simple_list(window: &JS<Window>, elements: ~[JS<Node>]) -> JS<NodeList> { + NodeList::new(window.clone(), Simple(elements)) } - pub fn new_child_list(window: @mut Window, node: AbstractNode) -> @mut NodeList { - NodeList::new(window, Children(node)) + pub fn new_child_list(window: &JS<Window>, node: &JS<Node>) -> JS<NodeList> { + NodeList::new(window.clone(), Children(node.clone())) } pub fn Length(&self) -> u32 { @@ -49,15 +52,15 @@ impl NodeList { } } - pub fn Item(&self, index: u32) -> Option<AbstractNode> { + pub fn Item(&self, index: u32) -> Option<JS<Node>> { match self.list_type { _ if index >= self.Length() => None, - Simple(ref elems) => Some(elems[index]), + Simple(ref elems) => Some(elems[index].clone()), Children(ref node) => node.children().nth(index as uint) } } - pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<AbstractNode> { + pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Node>> { let item = self.Item(index); *found = item.is_some(); item diff --git a/src/components/script/dom/processinginstruction.rs b/src/components/script/dom/processinginstruction.rs index 0fd830be452..85d247fe94a 100644 --- a/src/components/script/dom/processinginstruction.rs +++ b/src/components/script/dom/processinginstruction.rs @@ -3,28 +3,41 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::ProcessingInstructionBinding; +use dom::bindings::codegen::InheritTypes::ProcessingInstructionDerived; +use dom::bindings::js::JS; use dom::characterdata::CharacterData; -use dom::document::AbstractDocument; -use dom::node::{AbstractNode, Node, ProcessingInstructionNodeTypeId}; +use dom::document::Document; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::node::{Node, ProcessingInstructionNodeTypeId}; use servo_util::str::DOMString; /// An HTML processing instruction node. +#[deriving(Encodable)] pub struct ProcessingInstruction { characterdata: CharacterData, target: DOMString, } +impl ProcessingInstructionDerived for EventTarget { + fn is_processinginstruction(&self) -> bool { + match self.type_id { + NodeTargetTypeId(ProcessingInstructionNodeTypeId) => true, + _ => false + } + } +} + impl ProcessingInstruction { - pub fn new_inherited(target: DOMString, data: DOMString, document: AbstractDocument) -> ProcessingInstruction { + pub fn new_inherited(target: DOMString, data: DOMString, document: JS<Document>) -> ProcessingInstruction { ProcessingInstruction { characterdata: CharacterData::new_inherited(ProcessingInstructionNodeTypeId, data, document), target: target } } - pub fn new(target: DOMString, data: DOMString, document: AbstractDocument) -> AbstractNode { - let node = ProcessingInstruction::new_inherited(target, data, document); - Node::reflect_node(@mut node, document, ProcessingInstructionBinding::Wrap) + pub fn new(target: DOMString, data: DOMString, document: &JS<Document>) -> JS<ProcessingInstruction> { + let node = ProcessingInstruction::new_inherited(target, data, document.clone()); + Node::reflect_node(~node, document, ProcessingInstructionBinding::Wrap) } } diff --git a/src/components/script/dom/text.rs b/src/components/script/dom/text.rs index 9ed8ba7a8b6..2d81937849e 100644 --- a/src/components/script/dom/text.rs +++ b/src/components/script/dom/text.rs @@ -3,35 +3,48 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::TextBinding; +use dom::bindings::codegen::InheritTypes::TextDerived; +use dom::bindings::js::JS; use dom::bindings::utils::Fallible; use dom::characterdata::CharacterData; -use dom::document::AbstractDocument; -use dom::node::{AbstractNode, Node, TextNodeTypeId}; +use dom::document::Document; +use dom::eventtarget::{EventTarget, NodeTargetTypeId}; +use dom::node::{Node, TextNodeTypeId}; use dom::window::Window; use servo_util::str::DOMString; /// An HTML text node. +#[deriving(Encodable)] pub struct Text { characterdata: CharacterData, } +impl TextDerived for EventTarget { + fn is_text(&self) -> bool { + match self.type_id { + NodeTargetTypeId(TextNodeTypeId) => true, + _ => false + } + } +} + impl Text { - pub fn new_inherited(text: DOMString, document: AbstractDocument) -> Text { + pub fn new_inherited(text: DOMString, document: JS<Document>) -> Text { Text { characterdata: CharacterData::new_inherited(TextNodeTypeId, text, document) } } - pub fn new(text: DOMString, document: AbstractDocument) -> AbstractNode { - let node = Text::new_inherited(text, document); - Node::reflect_node(@mut node, document, TextBinding::Wrap) + pub fn new(text: DOMString, document: &JS<Document>) -> JS<Text> { + let node = Text::new_inherited(text, document.clone()); + Node::reflect_node(~node, document, TextBinding::Wrap) } - pub fn Constructor(owner: @mut Window, text: DOMString) -> Fallible<AbstractNode> { - Ok(Text::new(text.clone(), owner.Document())) + pub fn Constructor(owner: &JS<Window>, text: DOMString) -> Fallible<JS<Text>> { + Ok(Text::new(text.clone(), &owner.get().Document())) } - pub fn SplitText(&self, _offset: u32) -> Fallible<AbstractNode> { + pub fn SplitText(&self, _offset: u32) -> Fallible<JS<Text>> { fail!("unimplemented") } diff --git a/src/components/script/dom/uievent.rs b/src/components/script/dom/uievent.rs index 4ae1c6869b2..92e36edd6a5 100644 --- a/src/components/script/dom/uievent.rs +++ b/src/components/script/dom/uievent.rs @@ -3,47 +3,55 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::UIEventBinding; +use dom::bindings::codegen::InheritTypes::UIEventDerived; +use dom::bindings::js::JS; use dom::bindings::utils::Fallible; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -use dom::node::AbstractNode; -use dom::event::{AbstractEvent, Event, EventTypeId, UIEventTypeId}; +use dom::event::{Event, EventTypeId, UIEventTypeId}; +use dom::node::Node; use dom::window::Window; use dom::windowproxy::WindowProxy; use servo_util::str::DOMString; +#[deriving(Encodable)] pub struct UIEvent { - parent: Event, - view: Option<@mut WindowProxy>, + event: Event, + view: Option<JS<WindowProxy>>, detail: i32 } +impl UIEventDerived for Event { + fn is_uievent(&self) -> bool { + self.type_id == UIEventTypeId + } +} + impl UIEvent { pub fn new_inherited(type_id: EventTypeId) -> UIEvent { UIEvent { - parent: Event::new_inherited(type_id), + event: Event::new_inherited(type_id), view: None, detail: 0 } } - pub fn new(window: @mut Window) -> AbstractEvent { - let ev = reflect_dom_object(@mut UIEvent::new_inherited(UIEventTypeId), - window, - UIEventBinding::Wrap); - Event::as_abstract(ev) + pub fn new(window: &JS<Window>) -> JS<UIEvent> { + reflect_dom_object(~UIEvent::new_inherited(UIEventTypeId), + window.get(), + UIEventBinding::Wrap) } - pub fn Constructor(owner: @mut Window, + pub fn Constructor(owner: &JS<Window>, type_: DOMString, - init: &UIEventBinding::UIEventInit) -> Fallible<AbstractEvent> { - let ev = UIEvent::new(owner); - ev.mut_uievent().InitUIEvent(type_, init.parent.bubbles, init.parent.cancelable, - init.view, init.detail); + init: &UIEventBinding::UIEventInit) -> Fallible<JS<UIEvent>> { + let mut ev = UIEvent::new(owner); + ev.get_mut().InitUIEvent(type_, init.parent.bubbles, init.parent.cancelable, + init.view.clone(), init.detail); Ok(ev) } - pub fn GetView(&self) -> Option<@mut WindowProxy> { - self.view + pub fn GetView(&self) -> Option<JS<WindowProxy>> { + self.view.clone() } pub fn Detail(&self) -> i32 { @@ -54,9 +62,9 @@ impl UIEvent { type_: DOMString, can_bubble: bool, cancelable: bool, - view: Option<@mut WindowProxy>, + view: Option<JS<WindowProxy>>, detail: i32) { - self.parent.InitEvent(type_, can_bubble, cancelable); + self.event.InitEvent(type_, can_bubble, cancelable); self.view = view; self.detail = detail; } @@ -86,7 +94,7 @@ impl UIEvent { 0 } - pub fn GetRangeParent(&self) -> Option<AbstractNode> { + pub fn GetRangeParent(&self) -> Option<JS<Node>> { //TODO None } @@ -113,10 +121,10 @@ impl UIEvent { impl Reflectable for UIEvent { fn reflector<'a>(&'a self) -> &'a Reflector { - self.parent.reflector() + self.event.reflector() } fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector { - self.parent.mut_reflector() + self.event.mut_reflector() } } diff --git a/src/components/script/dom/validitystate.rs b/src/components/script/dom/validitystate.rs index 562b58a16c6..1d7a690ffab 100644 --- a/src/components/script/dom/validitystate.rs +++ b/src/components/script/dom/validitystate.rs @@ -2,18 +2,20 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::codegen::ValidityStateBinding; +use dom::bindings::js::JS; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; +#[deriving(Encodable)] pub struct ValidityState { reflector_: Reflector, - window: @mut Window, + window: JS<Window>, state: u8, } impl ValidityState { - pub fn new_inherited(window: @mut Window) -> ValidityState { + pub fn new_inherited(window: JS<Window>) -> ValidityState { ValidityState { reflector_: Reflector::new(), window: window, @@ -21,8 +23,9 @@ impl ValidityState { } } - pub fn new(window: @mut Window) -> @mut ValidityState { - reflect_dom_object(@mut ValidityState::new_inherited(window), window, + pub fn new(window: &JS<Window>) -> JS<ValidityState> { + reflect_dom_object(~ValidityState::new_inherited(window.clone()), + window.get(), ValidityStateBinding::Wrap) } } diff --git a/src/components/script/dom/webidls/Document.webidl b/src/components/script/dom/webidls/Document.webidl index 12769016f38..daa91f540fb 100644 --- a/src/components/script/dom/webidls/Document.webidl +++ b/src/components/script/dom/webidls/Document.webidl @@ -21,8 +21,6 @@ interface Document : Node { readonly attribute DocumentType? doctype; readonly attribute Element? documentElement; HTMLCollection getElementsByTagName(DOMString localName); - HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); - HTMLCollection getElementsByClassName(DOMString classNames); Element? getElementById(DOMString elementId); [Creator, Throws] @@ -47,4 +45,13 @@ partial interface Document { attribute HTMLElement? body; readonly attribute HTMLHeadElement? head; /*NodeList*/ HTMLCollection getElementsByName(DOMString elementName); + + readonly attribute HTMLCollection images; + readonly attribute HTMLCollection embeds; + readonly attribute HTMLCollection plugins; + readonly attribute HTMLCollection links; + readonly attribute HTMLCollection forms; + readonly attribute HTMLCollection scripts; + readonly attribute HTMLCollection anchors; + readonly attribute HTMLCollection applets; }; diff --git a/src/components/script/dom/webidls/HTMLDocument.webidl b/src/components/script/dom/webidls/HTMLDocument.webidl deleted file mode 100644 index b899a46678f..00000000000 --- a/src/components/script/dom/webidls/HTMLDocument.webidl +++ /dev/null @@ -1,17 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* http://www.whatwg.org/specs/web-apps/current-work/#the-document-object */ -interface HTMLDocument : Document { - readonly attribute HTMLCollection images; - readonly attribute HTMLCollection embeds; - readonly attribute HTMLCollection plugins; - readonly attribute HTMLCollection links; - readonly attribute HTMLCollection forms; - readonly attribute HTMLCollection scripts; - readonly attribute HTMLCollection anchors; - readonly attribute HTMLCollection applets; -}; diff --git a/src/components/script/dom/webidls/HTMLSelectElement.webidl b/src/components/script/dom/webidls/HTMLSelectElement.webidl index b99bf149280..bb843fd3f92 100644 --- a/src/components/script/dom/webidls/HTMLSelectElement.webidl +++ b/src/components/script/dom/webidls/HTMLSelectElement.webidl @@ -32,8 +32,8 @@ interface HTMLSelectElement : HTMLElement { attribute unsigned long length; getter Element? item(unsigned long index); HTMLOptionElement? namedItem(DOMString name); - /*[Throws] - void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null);*/ + [Throws] + void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null); void remove(long index); [Throws] setter creator void (unsigned long index, HTMLOptionElement? option); diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index 3596c5de9f9..5c78af9f0d2 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -3,11 +3,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::WindowBinding; -use dom::bindings::utils::{Reflectable, Reflector, Traceable}; -use dom::bindings::utils::{trace_option, trace_reflector}; -use dom::document::AbstractDocument; +use dom::bindings::js::JS; +use dom::bindings::utils::{Reflectable, Reflector}; +use dom::document::Document; +use dom::element::Element; use dom::eventtarget::{EventTarget, WindowTypeId}; -use dom::node::AbstractNode; use dom::console::Console; use dom::location::Location; use dom::navigator::Navigator; @@ -20,7 +20,7 @@ use servo_util::str::DOMString; use servo_util::task::{spawn_named}; use js::glue::*; -use js::jsapi::{JSObject, JSContext, JS_DefineProperty, JSTracer, JSVal}; +use js::jsapi::{JSObject, JSContext, JS_DefineProperty, JSVal}; use js::{JSVAL_NULL, JSPROP_ENUMERATE}; use std::cast; @@ -32,6 +32,8 @@ use std::num; use std::ptr; use std::to_bytes::Cb; +use extra::serialize::{Encoder, Encodable}; + pub enum TimerControlMsg { TimerMessage_Fire(~TimerData), TimerMessage_Close, @@ -43,6 +45,11 @@ pub struct TimerHandle { cancel_chan: Option<Chan<()>>, } +impl<S: Encoder> Encodable<S> for TimerHandle { + fn encode(&self, _: &mut S) { + } +} + impl IterBytes for TimerHandle { fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { self.handle.iter_bytes(lsb0, f) @@ -61,18 +68,28 @@ impl TimerHandle { } } +#[deriving(Encodable)] pub struct Window { eventtarget: EventTarget, page: @mut Page, script_chan: ScriptChan, compositor: @ScriptListener, - console: Option<@mut Console>, - timer_chan: SharedChan<TimerControlMsg>, - location: Option<@mut Location>, - navigator: Option<@mut Navigator>, + console: Option<JS<Console>>, + location: Option<JS<Location>>, + navigator: Option<JS<Navigator>>, image_cache_task: ImageCacheTask, active_timers: ~HashSet<TimerHandle>, next_timer_handle: i32, + extra: Untraceable +} + +struct Untraceable { + timer_chan: SharedChan<TimerControlMsg>, +} + +impl<S: Encoder> Encodable<S> for Untraceable { + fn encode(&self, _: &mut S) { + } } impl Window { @@ -84,7 +101,7 @@ impl Window { #[unsafe_destructor] impl Drop for Window { fn drop(&mut self) { - self.timer_chan.send(TimerMessage_Close); + self.extra.timer_chan.send(TimerMessage_Close); for handle in self.active_timers.iter() { handle.cancel(); } @@ -107,11 +124,11 @@ impl Window { } pub fn Close(&self) { - self.timer_chan.send(TimerMessage_TriggerExit); + self.extra.timer_chan.send(TimerMessage_TriggerExit); } - pub fn Document(&self) -> AbstractDocument { - self.page.frame.unwrap().document + pub fn Document(&self) -> JS<Document> { + self.page.frame.get_ref().document.clone() } pub fn Name(&self) -> DOMString { @@ -141,29 +158,29 @@ impl Window { pub fn Blur(&self) { } - pub fn GetFrameElement(&self) -> Option<AbstractNode> { + pub fn GetFrameElement(&self) -> Option<JS<Element>> { None } - pub fn Location(&mut self) -> @mut Location { + pub fn Location(&mut self) -> JS<Location> { if self.location.is_none() { self.location = Some(Location::new(self, self.page)); } - self.location.unwrap() + self.location.get_ref().clone() } - pub fn Console(&mut self) -> @mut Console { + pub fn Console(&mut self) -> JS<Console> { if self.console.is_none() { self.console = Some(Console::new(self)); } - self.console.unwrap() + self.console.get_ref().clone() } - pub fn Navigator(&mut self) -> @mut Navigator { + pub fn Navigator(&mut self) -> JS<Navigator> { if self.navigator.is_none() { self.navigator = Some(Navigator::new(self)); } - self.navigator.unwrap() + self.navigator.get_ref().clone() } pub fn Confirm(&self, _message: DOMString) -> bool { @@ -202,7 +219,7 @@ impl Window { // to the relevant script handler that will deal with it. let tm = Timer::new().unwrap(); let (cancel_port, cancel_chan) = Chan::new(); - let chan = self.timer_chan.clone(); + let chan = self.extra.timer_chan.clone(); spawn_named("Window:SetTimeout", proc() { let mut tm = tm; let mut timeout_port = tm.oneshot(timeout); @@ -249,26 +266,28 @@ impl Window { script_chan: ScriptChan, compositor: @ScriptListener, image_cache_task: ImageCacheTask) - -> @mut Window { - let win = @mut Window { + -> JS<Window> { + let mut win = ~Window { eventtarget: EventTarget::new_inherited(WindowTypeId), page: page, script_chan: script_chan.clone(), compositor: compositor, console: None, - timer_chan: { - let (timer_port, timer_chan): (Port<TimerControlMsg>, SharedChan<TimerControlMsg>) = SharedChan::new(); - let id = page.id.clone(); - spawn_named("timer controller", proc() { - loop { - match timer_port.recv() { - TimerMessage_Close => break, - TimerMessage_Fire(td) => script_chan.send(FireTimerMsg(id, td)), - TimerMessage_TriggerExit => script_chan.send(ExitWindowMsg(id)), + extra: Untraceable { + timer_chan: { + let (timer_port, timer_chan): (Port<TimerControlMsg>, SharedChan<TimerControlMsg>) = SharedChan::new(); + let id = page.id.clone(); + spawn_named("timer controller", proc() { + loop { + match timer_port.recv() { + TimerMessage_Close => break, + TimerMessage_Fire(td) => script_chan.send(FireTimerMsg(id, td)), + TimerMessage_TriggerExit => script_chan.send(ExitWindowMsg(id)), + } } - } - }); - timer_chan + }); + timer_chan + } }, location: None, navigator: None, @@ -277,7 +296,9 @@ impl Window { next_timer_handle: 0 }; + let raw: *mut Window = &mut *win; let global = WindowBinding::Wrap(cx, ptr::null(), win); + assert!(global.is_not_null()); unsafe { let fn_names = ["window","self"]; for str in fn_names.iter() { @@ -291,17 +312,7 @@ impl Window { } + JS::from_raw(raw) } - win - } -} - -impl Traceable for Window { - fn trace(&self, tracer: *mut JSTracer) { - debug!("tracing window"); - - self.page.frame.map(|frame| trace_reflector(tracer, "document", frame.document.reflector())); - trace_option(tracer, "location", self.location); - trace_option(tracer, "navigator", self.navigator); } } diff --git a/src/components/script/dom/windowproxy.rs b/src/components/script/dom/windowproxy.rs index bae5c5b933f..35304d25d3c 100644 --- a/src/components/script/dom/windowproxy.rs +++ b/src/components/script/dom/windowproxy.rs @@ -2,17 +2,22 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::utils::{Reflectable, Reflector}; +use dom::bindings::codegen::WindowProxyBinding; +use dom::bindings::js::JS; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; +use dom::window::Window; +#[deriving(Encodable)] pub struct WindowProxy { reflector_: Reflector } impl WindowProxy { - pub fn new() -> @mut WindowProxy { - @mut WindowProxy { + pub fn new(owner: JS<Window>) -> JS<WindowProxy> { + let proxy = ~WindowProxy { reflector_: Reflector::new() - } + }; + reflect_dom_object(proxy, owner.get(), WindowProxyBinding::Wrap) } } diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index d388a77b0e3..cf692d43dfd 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -2,13 +2,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::{NodeBase, NodeCast, TextCast, ElementCast}; +use dom::bindings::codegen::InheritTypes::{HTMLIFrameElementCast, HTMLImageElementCast}; +use dom::bindings::js::JS; +use dom::bindings::utils::Reflectable; +use dom::document::Document; use dom::element::{HTMLLinkElementTypeId, HTMLIframeElementTypeId, HTMLImageElementTypeId}; use dom::htmlelement::HTMLElement; use dom::htmlheadingelement::{Heading1, Heading2, Heading3, Heading4, Heading5, Heading6}; use dom::htmliframeelement::IFrameSize; use dom::htmlformelement::HTMLFormElement; -use dom::node::{AbstractNode, ElementNodeTypeId}; +use dom::node::{ElementNodeTypeId, INode, NodeHelpers}; use dom::types::*; use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser}; use script_task::page_from_context; @@ -36,7 +40,7 @@ macro_rules! handle_element( $ctor: ident $(, $arg:expr )*) => ( if $string == $localName { - return $ctor::new($localName, $document $(, $arg)*); + return ElementCast::from(&$ctor::new($localName, $document $(, $arg)*)); } ) ) @@ -72,16 +76,16 @@ pub struct HtmlParserResult { } trait NodeWrapping { - unsafe fn to_hubbub_node(self) -> hubbub::NodeDataPtr; + unsafe fn to_hubbub_node(&self) -> hubbub::NodeDataPtr; unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> Self; } -impl NodeWrapping for AbstractNode { - unsafe fn to_hubbub_node(self) -> hubbub::NodeDataPtr { - cast::transmute(self) +impl<T: NodeBase+Reflectable> NodeWrapping for JS<T> { + unsafe fn to_hubbub_node(&self) -> hubbub::NodeDataPtr { + cast::transmute(self.get()) } - unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> AbstractNode { - cast::transmute(n) + unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> JS<T> { + JS::from_raw(cast::transmute(n)) } } @@ -158,7 +162,7 @@ fn js_script_listener(to_parent: SharedChan<HtmlDiscoveryMessage>, // Silly macros to handle constructing DOM nodes. This produces bad code and should be optimized // via atomization (issue #85). -pub fn build_element_from_tag(tag: DOMString, document: AbstractDocument) -> AbstractNode { +pub fn build_element_from_tag(tag: DOMString, document: &JS<Document>) -> JS<Element> { // TODO (Issue #85): use atoms handle_element!(document, tag, "a", HTMLAnchorElement); handle_element!(document, tag, "applet", HTMLAppletElement); @@ -240,11 +244,11 @@ pub fn build_element_from_tag(tag: DOMString, document: AbstractDocument) -> Abs handle_element!(document, tag, "ul", HTMLUListElement); handle_element!(document, tag, "video", HTMLVideoElement); - return HTMLUnknownElement::new(tag, document); + return ElementCast::from(&HTMLUnknownElement::new(tag, document)); } pub fn parse_html(cx: *JSContext, - document: AbstractDocument, + document: &mut JS<Document>, url: Url, resource_task: ResourceTask, image_cache_task: ImageCacheTask, @@ -294,8 +298,7 @@ pub fn parse_html(cx: *JSContext, let mut parser = hubbub::Parser("UTF-8", false); debug!("created parser"); - let document_node = AbstractNode::from_document(document); - parser.set_document_node(unsafe { document_node.to_hubbub_node() }); + parser.set_document_node(unsafe { document.to_hubbub_node() }); parser.enable_scripting(true); parser.enable_styling(true); @@ -306,7 +309,7 @@ pub fn parse_html(cx: *JSContext, let tree_handler = hubbub::TreeHandler { create_comment: |data: ~str| { debug!("create comment"); - let comment = Comment::new(data, document); + let comment: JS<Node> = NodeCast::from(&Comment::new(data, document)); unsafe { comment.to_hubbub_node() } }, create_doctype: |doctype: ~hubbub::Doctype| { @@ -315,87 +318,81 @@ pub fn parse_html(cx: *JSContext, public_id: public_id, system_id: system_id, force_quirks: _ } = doctype; - let node = DocumentType::new(name, - public_id, - system_id, - document); + let doctype_node = DocumentType::new(name, public_id, system_id, document); unsafe { - node.to_hubbub_node() + doctype_node.to_hubbub_node() } }, create_element: |tag: ~hubbub::Tag| { debug!("create element"); - let node = build_element_from_tag(tag.name.clone(), document); + let mut element = build_element_from_tag(tag.name.clone(), document); debug!("-- attach attrs"); - node.as_mut_element(|element| { - for attr in tag.attributes.iter() { - element.set_attr(node, - attr.name.clone(), - attr.value.clone()); - } - }); + for attr in tag.attributes.iter() { + let elem = element.clone(); + element.get_mut().set_attr(&elem, + attr.name.clone(), + attr.value.clone()); + } // Spawn additional parsing, network loads, etc. from tag and attrs - match node.type_id() { + match element.get().node.type_id { // Handle CSS style sheets from <link> elements ElementNodeTypeId(HTMLLinkElementTypeId) => { - node.with_imm_element(|element| { - match (element.get_attribute(Null, "rel"), element.get_attribute(Null, "href")) { - (Some(rel), Some(href)) => { - if "stylesheet" == rel.value_ref() { - debug!("found CSS stylesheet: {:s}", href.value_ref()); - let url = parse_url(href.value_ref(), Some(url2.clone())); - css_chan2.send(CSSTaskNewFile(UrlProvenance(url))); - } + match (element.get().get_attribute(Null, "rel"), + element.get().get_attribute(Null, "href")) { + (Some(rel), Some(href)) => { + if "stylesheet" == rel.get().value_ref() { + debug!("found CSS stylesheet: {:s}", href.get().value_ref()); + let url = parse_url(href.get().value_ref(), Some(url2.clone())); + css_chan2.send(CSSTaskNewFile(UrlProvenance(url))); } - _ => {} } - }); + _ => {} + } } ElementNodeTypeId(HTMLIframeElementTypeId) => { let iframe_chan = discovery_chan.clone(); - node.with_mut_iframe_element(|iframe_element| { - let sandboxed = iframe_element.is_sandboxed(); - let elem = &mut iframe_element.htmlelement.element; - let src_opt = elem.get_attribute(Null, "src").map(|x| x.Value()); - for src in src_opt.iter() { - let iframe_url = parse_url(*src, Some(url2.clone())); - iframe_element.frame = Some(iframe_url.clone()); - - // Subpage Id - let subpage_id = next_subpage_id.get(); - next_subpage_id.set(SubpageId(*subpage_id + 1)); - - // Pipeline Id - let pipeline_id = { - let page = page_from_context(cx); - unsafe { (*page).id } - }; - - iframe_element.size = Some(IFrameSize { - pipeline_id: pipeline_id, - subpage_id: subpage_id, - }); - iframe_chan.send(HtmlDiscoveredIFrame((iframe_url, - subpage_id, - sandboxed))); - } - }); + let mut iframe_element: JS<HTMLIFrameElement> = + HTMLIFrameElementCast::to(&element); + let sandboxed = iframe_element.get().is_sandboxed(); + let elem: JS<Element> = ElementCast::from(&iframe_element); + let src_opt = elem.get().get_attribute(Null, "src").map(|x| x.get().Value()); + for src in src_opt.iter() { + let iframe_url = parse_url(*src, Some(url2.clone())); + iframe_element.get_mut().extra.frame = Some(iframe_url.clone()); + + // Subpage Id + let subpage_id = next_subpage_id.get(); + next_subpage_id.set(SubpageId(*subpage_id + 1)); + + // Pipeline Id + let pipeline_id = { + let page = page_from_context(cx); + unsafe { (*page).id } + }; + + iframe_element.get_mut().size = Some(IFrameSize { + pipeline_id: pipeline_id, + subpage_id: subpage_id, + }); + iframe_chan.send(HtmlDiscoveredIFrame((iframe_url, + subpage_id, + sandboxed))); + } } //FIXME: This should be taken care of by set_attr, but we don't have // access to a window so HTMLImageElement::AfterSetAttr bails. ElementNodeTypeId(HTMLImageElementTypeId) => { - node.with_mut_image_element(|image_element| { - image_element.update_image(image_cache_task.clone(), Some(url2.clone())); - }); + let mut image_element: JS<HTMLImageElement> = HTMLImageElementCast::to(&element); + image_element.get_mut().update_image(image_cache_task.clone(), Some(url2.clone())); } _ => {} } - unsafe { node.to_hubbub_node() } + unsafe { element.to_hubbub_node() } }, create_text: |data: ~str| { debug!("create text"); @@ -407,9 +404,9 @@ pub fn parse_html(cx: *JSContext, append_child: |parent: hubbub::NodeDataPtr, child: hubbub::NodeDataPtr| { unsafe { debug!("append child {:x} {:x}", parent, child); - let parent: AbstractNode = NodeWrapping::from_hubbub_node(parent); - let child: AbstractNode = NodeWrapping::from_hubbub_node(child); - parent.AppendChild(child); + let mut parent: JS<Node> = NodeWrapping::from_hubbub_node(parent); + let mut child: JS<Node> = NodeWrapping::from_hubbub_node(child); + parent.AppendChild(&mut child); } child }, @@ -446,51 +443,48 @@ pub fn parse_html(cx: *JSContext, }, set_quirks_mode: |mode| { debug!("set quirks mode"); - document.mut_document().set_quirks_mode(mode); + document.get_mut().set_quirks_mode(mode); }, encoding_change: |encname| { debug!("encoding change"); - document.mut_document().set_encoding_name(encname); + document.get_mut().set_encoding_name(encname); }, complete_script: |script| { unsafe { - let scriptnode: AbstractNode = NodeWrapping::from_hubbub_node(script); - scriptnode.with_imm_element(|script| { - match script.get_attribute(Null, "src") { - Some(src) => { - debug!("found script: {:s}", src.Value()); - let new_url = parse_url(src.value_ref(), Some(url3.clone())); - js_chan2.send(JSTaskNewFile(new_url)); + let script: JS<Element> = NodeWrapping::from_hubbub_node(script); + match script.get().get_attribute(Null, "src") { + Some(src) => { + debug!("found script: {:s}", src.get().Value()); + let new_url = parse_url(src.get().value_ref(), Some(url3.clone())); + js_chan2.send(JSTaskNewFile(new_url)); + } + None => { + let mut data = ~[]; + let scriptnode: JS<Node> = NodeCast::from(&script); + debug!("iterating over children {:?}", scriptnode.first_child()); + for child in scriptnode.children() { + debug!("child = {:?}", child); + let text: JS<Text> = TextCast::to(&child); + data.push(text.get().characterdata.data.to_str()); // FIXME: Bad copy. } - None => { - let mut data = ~[]; - debug!("iterating over children {:?}", scriptnode.first_child()); - for child in scriptnode.children() { - debug!("child = {:?}", child); - child.with_imm_text(|text| { - data.push(text.characterdata.data.to_str()); // FIXME: Bad copy. - }); - } - debug!("script data = {:?}", data); - js_chan2.send(JSTaskNewInlineScript(data.concat(), url3.clone())); - } + debug!("script data = {:?}", data); + js_chan2.send(JSTaskNewInlineScript(data.concat(), url3.clone())); } - }); + } } debug!("complete script"); }, complete_style: |style| { // We've reached the end of a <style> so we can submit all the text to the parser. unsafe { - let style: AbstractNode = NodeWrapping::from_hubbub_node(style); + let style: JS<Node> = NodeWrapping::from_hubbub_node(style); let mut data = ~[]; debug!("iterating over children {:?}", style.first_child()); for child in style.children() { debug!("child = {:?}", child); - child.with_imm_text(|text| { - data.push(text.characterdata.data.to_str()); // FIXME: Bad copy. - }); + let text: JS<Text> = TextCast::to(&child); + data.push(text.get().characterdata.data.to_str()); // FIXME: Bad copy. } debug!("style data = {:?}", data); diff --git a/src/components/script/layout_interface.rs b/src/components/script/layout_interface.rs index 8f6688b84aa..6ebea1809af 100644 --- a/src/components/script/layout_interface.rs +++ b/src/components/script/layout_interface.rs @@ -6,7 +6,7 @@ /// coupling between these two components, and enables the DOM to be placed in a separate crate /// from layout. -use dom::node::{AbstractNode, LayoutDataRef}; +use dom::node::LayoutDataRef; use extra::url::Url; use geom::point::Point2D; @@ -52,14 +52,18 @@ pub enum Msg { /// Synchronous messages that script can send to layout. pub enum LayoutQuery { /// Requests the dimensions of the content box, as in the `getBoundingClientRect()` call. - ContentBoxQuery(AbstractNode, Chan<ContentBoxResponse>), + ContentBoxQuery(TrustedNodeAddress, Chan<ContentBoxResponse>), /// Requests the dimensions of all the content boxes, as in the `getClientRects()` call. - ContentBoxesQuery(AbstractNode, Chan<ContentBoxesResponse>), + ContentBoxesQuery(TrustedNodeAddress, Chan<ContentBoxesResponse>), /// Requests the node containing the point of interest - HitTestQuery(AbstractNode, Point2D<f32>, Chan<Result<HitTestResponse, ()>>), - MouseOverQuery(AbstractNode, Point2D<f32>, Chan<Result<MouseOverResponse, ()>>), + HitTestQuery(TrustedNodeAddress, Point2D<f32>, Chan<Result<HitTestResponse, ()>>), + MouseOverQuery(TrustedNodeAddress, Point2D<f32>, Chan<Result<MouseOverResponse, ()>>), } +/// The address of a node known to be valid. These must only be sent from content -> layout, +/// because we do not trust layout. +pub type TrustedNodeAddress = *c_void; + /// The address of a node. Layout sends these back. They must be validated via /// `from_untrusted_node_address` before they can be used, because we do not trust layout. pub type UntrustedNodeAddress = *c_void; @@ -92,7 +96,7 @@ impl DocumentDamageLevel { /// Note that this is fairly coarse-grained and is separate from layout's notion of the document pub struct DocumentDamage { /// The topmost node in the tree that has changed. - root: AbstractNode, + root: TrustedNodeAddress, /// The amount of damage that occurred. level: DocumentDamageLevel, } @@ -109,7 +113,7 @@ pub enum ReflowGoal { /// Information needed for a reflow. pub struct Reflow { /// The document node. - document_root: AbstractNode, + document_root: TrustedNodeAddress, /// The style changes that need to be done. damage: DocumentDamage, /// The goal of reflow: either to render to the screen or to flush layout info for script. diff --git a/src/components/script/script.rs b/src/components/script/script.rs index 5d270cf2e36..1d23dfc3402 100644 --- a/src/components/script/script.rs +++ b/src/components/script/script.rs @@ -26,18 +26,22 @@ mod macros; pub mod dom { pub mod bindings { + pub mod js; pub mod element; - pub mod node; pub mod utils; pub mod callback; pub mod conversions; pub mod proxyhandler; + pub mod trace; pub mod codegen { pub use self::BindingDeclarations::*; pub mod InterfaceTypes; + pub mod InheritTypes; pub mod PrototypeList; pub mod RegisterBindings; pub mod BindingDeclarations; + pub mod UnionConversions; + pub mod UnionTypes; } } @@ -79,7 +83,6 @@ pub mod dom { pub mod htmldirectoryelement; pub mod htmldivelement; pub mod htmldlistelement; - pub mod htmldocument; pub mod htmlelement; pub mod htmlembedelement; pub mod htmlfieldsetelement; diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 8a56291b95f..a9a284ad21f 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -6,14 +6,15 @@ //! and layout tasks. use dom::bindings::codegen::RegisterBindings; -use dom::bindings::utils::{Reflectable, GlobalStaticData}; -use dom::document::AbstractDocument; +use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, ElementCast}; +use dom::bindings::js::JS; +use dom::bindings::utils::{Reflectable, GlobalStaticData, with_gc_enabled}; +use dom::document::{Document, HTMLDocument}; use dom::element::Element; use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent}; use dom::event::Event; -use dom::eventtarget::AbstractEventTarget; -use dom::htmldocument::HTMLDocument; -use dom::node::AbstractNode; +use dom::eventtarget::EventTarget; +use dom::node::{Node, NodeHelpers}; use dom::window::{TimerData, TimerHandle, Window}; use html::hubbub_html_parser::HtmlParserResult; use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDiscoveredScript}; @@ -32,7 +33,7 @@ use geom::size::Size2D; use js::JSVAL_NULL; use js::global::debug_fns; use js::glue::RUST_JSVAL_TO_OBJECT; -use js::jsapi::{JSContext, JSObject}; +use js::jsapi::{JSContext, JSObject, JS_InhibitGC, JS_AllowGC}; use js::jsapi::{JS_CallFunctionValue, JS_GetContextPrivate}; use js::rust::{Compartment, Cx}; use js; @@ -52,6 +53,8 @@ use std::ptr; use std::task; use std::util::replace; +use extra::serialize::{Encoder, Encodable}; + /// Messages used to control the script task. pub enum ScriptMsg { /// Loads a new URL on the specified pipeline. @@ -86,6 +89,11 @@ pub struct NewLayoutInfo { #[deriving(Clone)] pub struct ScriptChan(SharedChan<ScriptMsg>); +impl<S: Encoder> Encodable<S> for ScriptChan { + fn encode(&self, _s: &mut S) { + } +} + impl ScriptChan { /// Creates a new script chan. pub fn new() -> (Port<ScriptMsg>, ScriptChan) { @@ -131,7 +139,13 @@ pub struct Page { resize_event: Option<Size2D<uint>>, /// Pending scroll to fragment event, if any - fragment_node: Option<AbstractNode> + fragment_node: Option<JS<Element>> +} + +impl<S: Encoder> Encodable<S> for Page { + fn encode(&self, s: &mut S) { + self.fragment_node.encode(s); + } } pub struct PageTree { @@ -223,23 +237,24 @@ impl Page { pub fn damage(&mut self, level: DocumentDamageLevel) { let root = match self.frame { None => return, - Some(ref frame) => frame.document.document().GetDocumentElement() + Some(ref frame) => frame.document.get().GetDocumentElement() }; match root { None => {}, Some(root) => { + let root: JS<Node> = NodeCast::from(&root); match self.damage { None => {} Some(ref mut damage) => { // FIXME(pcwalton): This is wrong. We should trace up to the nearest ancestor. - damage.root = root; + damage.root = root.to_trusted_node_address(); damage.level.add(level); return } } self.damage = Some(DocumentDamage { - root: root, + root: root.to_trusted_node_address(), level: level, }) } @@ -292,7 +307,7 @@ impl Page { let root = match self.frame { None => return, Some(ref frame) => { - frame.document.document().GetDocumentElement() + frame.document.get().GetDocumentElement() } }; @@ -314,8 +329,9 @@ impl Page { self.last_reflow_id += 1; // Send new document and relevant styles to layout. + let root: JS<Node> = NodeCast::from(&root); let reflow = ~Reflow { - document_root: root, + document_root: root.to_trusted_node_address(), url: self.url.get_ref().first().clone(), goal: goal, window_size: self.window_size, @@ -333,6 +349,8 @@ impl Page { } pub fn initialize_js_info(&mut self, js_context: @Cx, global: *JSObject) { + assert!(global.is_not_null()); + // Note that the order that these variables are initialized is _not_ arbitrary. Switching // them around can -- and likely will -- lead to things breaking. @@ -352,6 +370,8 @@ impl Page { unsafe { js_context.set_cx_private(page_ptr as *()); + + JS_InhibitGC(js_context.ptr); } self.js_info = Some(JSPageInfo { @@ -363,11 +383,12 @@ impl Page { } /// Information for one frame in the browsing context. +#[deriving(Encodable)] pub struct Frame { /// The document for this frame. - document: AbstractDocument, + document: JS<Document>, /// The window object for this frame. - window: @mut Window, + window: JS<Window>, } /// Encapsulation of the javascript information associated with each frame. @@ -406,7 +427,7 @@ pub struct ScriptTask { /// The JavaScript runtime. js_runtime: js::rust::rt, - mouse_over_targets:Option<~[AbstractNode]> + mouse_over_targets: Option<~[JS<Node>]> } /// Returns the relevant page from the associated JS Context. @@ -565,28 +586,27 @@ impl ScriptTask { fn handle_fire_timer_msg(&mut self, id: PipelineId, timer_data: ~TimerData) { let page = self.page_tree.find(id).expect("ScriptTask: received fire timer msg for a pipeline ID not associated with this script task. This is a bug.").page; - let window = page.frame.expect("ScriptTask: Expect a timeout to have a document").window; - if !window.active_timers.contains(&TimerHandle { handle: timer_data.handle, cancel_chan: None }) { + let mut window = page.frame.get_ref().window.clone(); + if !window.get().active_timers.contains(&TimerHandle { handle: timer_data.handle, cancel_chan: None }) { return; } - window.active_timers.remove(&TimerHandle { handle: timer_data.handle, cancel_chan: None }); - unsafe { - let this_value = if timer_data.args.len() > 0 { + window.get_mut().active_timers.remove(&TimerHandle { handle: timer_data.handle, cancel_chan: None }); + let this_value = if timer_data.args.len() > 0 { + unsafe { RUST_JSVAL_TO_OBJECT(timer_data.args[0]) - } else { - page.js_info.get_ref().js_compartment.global_obj.ptr - }; - - // TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`. - let rval = JSVAL_NULL; - JS_CallFunctionValue(page.js_info.get_ref().js_context.ptr, - this_value, - timer_data.funval, - 0, - ptr::null(), - &rval); + } + } else { + page.js_info.get_ref().js_compartment.global_obj.ptr + }; - } + // TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`. + let rval = JSVAL_NULL; + let cx = page.js_info.get_ref().js_context.ptr; + with_gc_enabled(cx, || { + unsafe { + JS_CallFunctionValue(cx, this_value, timer_data.funval, 0, ptr::null(), &rval); + } + }); } /// Handles a notification that reflow completed. @@ -697,9 +717,9 @@ impl ScriptTask { // Parse HTML. // // Note: We can parse the next document in parallel with any previous documents. - let document = HTMLDocument::new(window, Some(url.clone())); + let mut document = Document::new(&window, Some(url.clone()), HTMLDocument, None); let html_parsing_result = hubbub_html_parser::parse_html(cx.ptr, - document, + &mut document, url.clone(), self.resource_task.clone(), self.image_cache_task.clone(), @@ -711,8 +731,8 @@ impl ScriptTask { // Create the root frame. page.frame = Some(Frame { - document: document, - window: window, + document: document.clone(), + window: window.clone(), }); // Send style sheets over to layout. @@ -747,7 +767,7 @@ impl ScriptTask { } // Kick off the initial reflow of the page. - document.document().content_changed(); + document.get().content_changed(); let fragment = url.fragment.as_ref().map(|ref fragment| fragment.to_owned()); @@ -766,47 +786,50 @@ impl ScriptTask { // Evaluate every script in the document. for file in js_scripts.iter() { - let _ = cx.evaluate_script(compartment.global_obj, - file.data.clone(), - file.url.to_str(), - 1); + with_gc_enabled(cx.ptr, || { + cx.evaluate_script(compartment.global_obj, + file.data.clone(), + file.url.to_str(), + 1); + }); } // We have no concept of a document loader right now, so just dispatch the // "load" event as soon as we've finished executing all scripts parsed during // the initial load. - let event = Event::new(window); - event.mut_event().InitEvent(~"load", false, false); - let doctarget = AbstractEventTarget::from_document(document); - let wintarget = AbstractEventTarget::from_window(window); - window.eventtarget.dispatch_event_with_target(wintarget, Some(doctarget), event); + let mut event = Event::new(&window); + event.get_mut().InitEvent(~"load", false, false); + let doctarget = EventTargetCast::from(&document); + let mut wintarget: JS<EventTarget> = EventTargetCast::from(&window); + let winclone = wintarget.clone(); + wintarget.get_mut().dispatch_event_with_target(&winclone, Some(doctarget), &mut event); page.fragment_node = fragment.map_default(None, |fragid| self.find_fragment_node(page, fragid)); self.constellation_chan.send(LoadCompleteMsg(page.id, url)); } - fn find_fragment_node(&self, page: &mut Page, fragid: ~str) -> Option<AbstractNode> { - let document = page.frame.expect("root frame is None").document; - match document.document().GetElementById(fragid.to_owned()) { + fn find_fragment_node(&self, page: &mut Page, fragid: ~str) -> Option<JS<Element>> { + let document = page.frame.get_ref().document.clone(); + match document.get().GetElementById(fragid.to_owned()) { Some(node) => Some(node), None => { - let doc_node = AbstractNode::from_document(document); + let doc_node: JS<Node> = NodeCast::from(&document); let mut anchors = doc_node.traverse_preorder().filter(|node| node.is_anchor_element()); anchors.find(|node| { - node.with_imm_element(|elem| { - elem.get_attribute(Null, "name").map_default(false, |attr| { - attr.value_ref() == fragid - }) + let elem: JS<Element> = ElementCast::to(node); + elem.get().get_attribute(Null, "name").map_default(false, |attr| { + attr.get().value_ref() == fragid }) - }) + }).map(|node| ElementCast::to(&node)) } } } - fn scroll_fragment_point(&self, pipeline_id: PipelineId, page: &mut Page, node: AbstractNode) { + fn scroll_fragment_point(&self, pipeline_id: PipelineId, page: &mut Page, node: JS<Element>) { let (port, chan) = Chan::new(); - match page.query_layout(ContentBoxQuery(node, chan), port) { + let node: JS<Node> = NodeCast::from(&node); + match page.query_layout(ContentBoxQuery(node.to_trusted_node_address(), chan), port) { ContentBoxResponse(rect) => { let point = Point2D(to_frac_px(rect.origin.x).to_f32().unwrap(), to_frac_px(rect.origin.y).to_f32().unwrap()); @@ -852,18 +875,19 @@ impl ScriptTask { ClickEvent(_button, point) => { debug!("ClickEvent: clicked at {:?}", point); - let document = page.frame.expect("root frame is None").document; - let root = document.document().GetDocumentElement(); + let document = page.frame.get_ref().document.clone(); + let root = document.get().GetDocumentElement(); if root.is_none() { return; } let (port, chan) = Chan::new(); - match page.query_layout(HitTestQuery(root.unwrap(), point, chan), port) { + let root: JS<Node> = NodeCast::from(&root.unwrap()); + match page.query_layout(HitTestQuery(root.to_trusted_node_address(), point, chan), port) { Ok(HitTestResponse(node_address)) => { debug!("node address is {:?}", node_address); - let mut node = AbstractNode::from_untrusted_node_address(self.js_runtime - .ptr, - node_address); + let mut node: JS<Node> = + NodeHelpers::from_untrusted_node_address(self.js_runtime.ptr, + node_address); debug!("clicked on {:s}", node.debug_str()); // Traverse node generations until a node that is an element is @@ -876,11 +900,10 @@ impl ScriptTask { } if node.is_element() { - node.with_imm_element(|element| { - if "a" == element.tag_name { - self.load_url_from_element(page, element) - } - }) + let element: JS<Element> = ElementCast::to(&node); + if "a" == element.get().tag_name { + self.load_url_from_element(page, element.get()) + } } }, Err(()) => debug!("layout query error"), @@ -889,21 +912,22 @@ impl ScriptTask { MouseDownEvent(..) => {} MouseUpEvent(..) => {} MouseMoveEvent(point) => { - let document = page.frame.expect("root frame is None").document; - let root = document.document().GetDocumentElement(); + let document = page.frame.get_ref().document.clone(); + let root = document.get().GetDocumentElement(); if root.is_none() { return; } + let root: JS<Node> = NodeCast::from(&root.unwrap()); let (port, chan) = Chan::new(); - match page.query_layout(MouseOverQuery(root.unwrap(), point, chan), port) { + match page.query_layout(MouseOverQuery(root.to_trusted_node_address(), point, chan), port) { Ok(MouseOverResponse(node_address)) => { - let mut target_list:~[AbstractNode] = ~[]; + let mut target_list: ~[JS<Node>] = ~[]; let mut target_compare = false; match self.mouse_over_targets { Some(ref mut mouse_over_targets) => { - for node in mouse_over_targets.iter() { + for node in mouse_over_targets.mut_iter() { node.set_hover_state(false); } } @@ -911,9 +935,9 @@ impl ScriptTask { } for node_address in node_address.iter() { - let mut node = AbstractNode::from_untrusted_node_address(self.js_runtime - .ptr, - *node_address); + let mut node: JS<Node> = + NodeHelpers::from_untrusted_node_address( + self.js_runtime.ptr, *node_address); // Traverse node generations until a node that is an element is // found. while !node.is_element() { @@ -964,13 +988,13 @@ impl ScriptTask { // if the node's element is "a," load url from href attr let attr = element.get_attribute(Null, "href"); for href in attr.iter() { - debug!("ScriptTask: clicked on link to {:s}", href.Value()); - let click_frag = href.value_ref().starts_with("#"); + debug!("ScriptTask: clicked on link to {:s}", href.get().Value()); + let click_frag = href.get().value_ref().starts_with("#"); let base_url = page.url.as_ref().map(|&(ref url, _)| { url.clone() }); debug!("ScriptTask: current url is {:?}", base_url); - let url = parse_url(href.value_ref(), base_url); + let url = parse_url(href.get().value_ref(), base_url); if click_frag { match self.find_fragment_node(page, url.fragment.unwrap()) { @@ -995,6 +1019,11 @@ fn shut_down_layout(page: @mut Page) { // Destroy all nodes. Setting frame and js_info to None will trigger our // compartment to shutdown, run GC, etc. + + unsafe { + JS_AllowGC(page.js_info.get_ref().js_context.ptr); + } + page.frame = None; page.js_info = None; diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index 0f2d9cb63e3..a9e4c0b03fd 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -18,8 +18,9 @@ pub use parsing_utils::*; pub use self::common_types::*; use selector_matching::MatchedProperty; -pub mod common_types; +use extra::serialize::{Encodable, Encoder}; +pub mod common_types; <%! @@ -1025,6 +1026,11 @@ pub struct PropertyDeclarationBlock { normal: Arc<~[PropertyDeclaration]>, } +impl<S: Encoder> Encodable<S> for PropertyDeclarationBlock { + fn encode(&self, _: &mut S) { + } +} + pub fn parse_style_attribute(input: &str, base_url: &Url) -> PropertyDeclarationBlock { parse_property_declaration_list(tokenize(input), base_url) diff --git a/src/components/util/namespace.rs b/src/components/util/namespace.rs index ff9eda169c9..b23b235bad0 100644 --- a/src/components/util/namespace.rs +++ b/src/components/util/namespace.rs @@ -2,7 +2,7 @@ * 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/. */ -#[deriving(Eq, Clone)] +#[deriving(Eq, Clone, Encodable)] pub enum Namespace { Null, HTML, diff --git a/src/components/gfx/opts.rs b/src/components/util/opts.rs index 04daf519c87..2f1d9777b8a 100644 --- a/src/components/gfx/opts.rs +++ b/src/components/util/opts.rs @@ -46,6 +46,12 @@ pub struct Opts { output_file: Option<~str>, headless: bool, hard_fail: bool, + + /// True if we should bubble intrinsic widths sequentially (`-b`). If this is true, then + /// intrinsic widths are computed as a separate pass instead of during flow construction. You + /// may wish to turn this flag on in order to benchmark style recalculation against other + /// browser engines. + bubble_widths_separately: bool, } fn print_usage(app: &str, opts: &[groups::OptGroup]) { @@ -68,6 +74,7 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts { groups::optopt("y", "layout-threads", "Number of threads to use for layout", "1"), groups::optflag("z", "headless", "Headless mode"), groups::optflag("f", "hard-fail", "Exit on task failure instead of displaying about:failure"), + groups::optflag("b", "bubble-widths", "Bubble intrinsic widths separately like other engines"), groups::optflag("h", "help", "Print this message") ]; @@ -143,5 +150,6 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts { output_file: opt_match.opt_str("o"), headless: opt_match.opt_present("z"), hard_fail: opt_match.opt_present("f"), + bubble_widths_separately: opt_match.opt_present("b"), } } diff --git a/src/components/util/util.rs b/src/components/util/util.rs index 46b37ceb3be..9df491dfeb5 100644 --- a/src/components/util/util.rs +++ b/src/components/util/util.rs @@ -7,6 +7,7 @@ #[feature(macro_rules, managed_boxes)]; +extern mod azure; extern mod extra; extern mod geom; extern mod native; @@ -18,6 +19,7 @@ pub mod debug; pub mod geometry; pub mod io; pub mod namespace; +pub mod opts; pub mod range; pub mod smallvec; pub mod sort; diff --git a/src/support/spidermonkey/mozjs b/src/support/spidermonkey/mozjs -Subproject 3e633e7e498e64793cb2c75394ed78d507c383a +Subproject 6615c7e7d17a4f1a1c0c2adb39765082f5421b6 diff --git a/src/support/spidermonkey/rust-mozjs b/src/support/spidermonkey/rust-mozjs -Subproject c2f282d8762aec1a55007ff75ef85dfb34e61e7 +Subproject 6a9db14da31271868090963067e1e689904e515 diff --git a/src/test/html/content/harness.js b/src/test/html/content/harness.js index ade4536a879..72aa2712469 100644 --- a/src/test/html/content/harness.js +++ b/src/test/html/content/harness.js @@ -37,6 +37,24 @@ function is_function(val, name) { starts_with(String(val), "function " + name + "("); } +function should_throw(f) { + try { + f(); + _fail("operation should have thrown but did not"); + } catch (x) { + _pass("operation successfully threw an exception", x.toString()); + } +} + +function should_not_throw(f) { + try { + f(); + _pass("operation did not throw an exception"); + } catch (x) { + _fail("operation should have not thrown", x.toString()); + } +} + var _test_complete = false; var _test_timeout = 10000; //10 seconds function finish() { diff --git a/src/test/html/content/test_documentElement.html b/src/test/html/content/test_documentElement.html index eea379456b1..efe68e086d0 100644 --- a/src/test/html/content/test_documentElement.html +++ b/src/test/html/content/test_documentElement.html @@ -6,7 +6,6 @@ is_a(window, Window); is_a(document.documentElement, HTMLHtmlElement); is_a(document.documentElement.firstChild, HTMLHeadElement); is(document.documentElement.nextSibling, null); -is_a(document, HTMLDocument); is_a(document, Document); finish(); </script> diff --git a/src/test/html/content/test_document_contenttype.html b/src/test/html/content/test_document_contenttype.html index ede2696f98a..4a63a654547 100644 --- a/src/test/html/content/test_document_contenttype.html +++ b/src/test/html/content/test_document_contenttype.html @@ -5,14 +5,14 @@ <script> // test1: HTML document { - is_a(document, HTMLDocument, "test1-0, HTML document"); + is_a(document, Document, "test1-0, HTML document"); is(document.contentType, "text/html", "test1-1, HTML document"); } // test2: XML document { var doc = new Document; - is_not_a(doc, HTMLDocument, "test2-0, XML document"); + is_a(doc, Document, "test2-0, XML document"); is(doc.contentType, "application/xml", "test2-1, XML document"); } diff --git a/src/test/html/content/test_document_implementation.html b/src/test/html/content/test_document_implementation.html index 6f7ac8a89ab..57dabd13e71 100644 --- a/src/test/html/content/test_document_implementation.html +++ b/src/test/html/content/test_document_implementation.html @@ -27,7 +27,6 @@ var htmldoc = document.implementation.createHTMLDocument("example title"); isnot(htmldoc, null, "test3-0, createHTMLDocument"); is_a(htmldoc, Document, "test3-1, createHTMLDocument"); - is_a(htmldoc, HTMLDocument, "test3-2, createHTMLDocument"); is(htmldoc.childNodes.length, 2, "test3-3, createHTMLDocument"); is_a(htmldoc.doctype && htmldoc.doctype, DocumentType, "test3-4, createHTMLDocument"); diff --git a/src/test/html/content/test_exception.html b/src/test/html/content/test_exception.html index ed96fe22867..b2cfda177d4 100644 --- a/src/test/html/content/test_exception.html +++ b/src/test/html/content/test_exception.html @@ -1,11 +1,6 @@ <!doctype html> <script src="harness.js"></script> <script> -try { - document.createElement("1foo"); - is(true, false, "No exception thrown"); -} catch (e) { - is(true, true, "Exception caught"); -} +should_throw(function() { document.createElement("1foo") }); finish(); </script> diff --git a/src/test/html/content/test_parentnodes.html b/src/test/html/content/test_parentnodes.html index 0b1bb610414..2131b7270b2 100644 --- a/src/test/html/content/test_parentnodes.html +++ b/src/test/html/content/test_parentnodes.html @@ -6,7 +6,7 @@ <body> <div id="div1"></div> <script> - is_a(document.documentElement.parentNode, HTMLDocument); + is_a(document.documentElement.parentNode, Document); is(document.documentElement.parentElement, null); var elem = document.createElement("p"); diff --git a/src/test/html/content/test_prototypes.html b/src/test/html/content/test_prototypes.html index 11ee11242b5..93019abe424 100644 --- a/src/test/html/content/test_prototypes.html +++ b/src/test/html/content/test_prototypes.html @@ -5,6 +5,7 @@ <body> <foo-á>foo</foo-á> <script> +is_a(window.document, Node); gc(); // ensure that our document rooting works; subsequent accesses should be valid. is_a(window.document, Node); is(window.document.nodeType, Node.DOCUMENT_NODE); @@ -13,7 +14,6 @@ is_a(window.document.documentElement, Element); is_a(window.document.documentElement, HTMLElement); is_a(window.document.documentElement, HTMLHtmlElement); is_a(window.document, Document); -is_a(window.document, HTMLDocument); is(window.document.documentElement.tagName, "HTML"); is_a(window.document.getElementsByTagName('foo-á')[0], HTMLUnknownElement); is(window.document.getElementsByTagName('foo-á')[0].tagName, "FOO-á"); diff --git a/src/test/html/content/test_union.html b/src/test/html/content/test_union.html new file mode 100644 index 00000000000..d5483ad8a3a --- /dev/null +++ b/src/test/html/content/test_union.html @@ -0,0 +1,26 @@ +<html> +<head> +<script src="harness.js"></script> +<select id="sel"></select> +<script> + var div = document.createElement('div'); + var optgroup = document.createElement('optgroup'); + var sel = document.getElementById('sel'); + + should_not_throw(function() { + var opt = document.createElement('option'); + sel.add(opt); + sel.add(optgroup); + sel.add(opt, div); + sel.add(optgroup, div); + sel.add(opt, 5); + sel.add(optgroup, 5); + }); + + should_throw(function() { sel.add(div) }); + should_throw(function() { sel.add(optgroup, function() {}) }); + + finish(); +</script> +</head> +</html> |