Auto merge of #6682 - boghison:scripttask, r=jdm

Fix a few issues

 - Use SmallVec<[T; N]>
 - Make find_iframe a free function
 - Make ProgressEvent use enums for bubbles and cancelable
 - Change README, as `rust-snapshot-hash` is just a text file

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6682)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-07-22 12:25:57 -06:00
commit aafc3dfa96
12 changed files with 46 additions and 44 deletions

View file

@ -61,7 +61,7 @@ Servo's build system automatically downloads a snapshot Rust compiler to build i
This is normally a specific revision of Rust upstream, but sometimes has a This is normally a specific revision of Rust upstream, but sometimes has a
backported patch or two. backported patch or two.
If you'd like to know the snapshot revision of Rust which we use, see If you'd like to know the snapshot revision of Rust which we use, see
`./rust-snapshot-hash`. `rust-snapshot-hash`.
## Building ## Building

View file

@ -32,7 +32,7 @@ use libc::uintptr_t;
use msg::compositor_msg::{LayerId, LayerKind}; use msg::compositor_msg::{LayerId, LayerKind};
use net_traits::image::base::Image; use net_traits::image::base::Image;
use paint_task::PaintLayer; use paint_task::PaintLayer;
use smallvec::SmallVec8; use smallvec::SmallVec;
use std::collections::linked_list::{self, LinkedList}; use std::collections::linked_list::{self, LinkedList};
use std::fmt; use std::fmt;
use std::slice::Iter; use std::slice::Iter;
@ -313,7 +313,7 @@ impl StackingContext {
} }
// Sort positioned children according to z-index. // Sort positioned children according to z-index.
let mut positioned_children = SmallVec8::new(); let mut positioned_children: SmallVec<[Arc<StackingContext>; 8]> = SmallVec::new();
for kid in display_list.children.iter() { for kid in display_list.children.iter() {
positioned_children.push((*kid).clone()); positioned_children.push((*kid).clone());
} }

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use euclid::{Point2D, Rect, Size2D}; use euclid::{Point2D, Rect, Size2D};
use smallvec::SmallVec8; use smallvec::SmallVec;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::mem; use std::mem;
use std::slice; use std::slice;
@ -204,11 +204,11 @@ impl Font {
} }
pub struct FontGroup { pub struct FontGroup {
pub fonts: SmallVec8<Rc<RefCell<Font>>>, pub fonts: SmallVec<[Rc<RefCell<Font>>; 8]>,
} }
impl FontGroup { impl FontGroup {
pub fn new(fonts: SmallVec8<Rc<RefCell<Font>>>) -> FontGroup { pub fn new(fonts: SmallVec<[Rc<RefCell<Font>>; 8]>) -> FontGroup {
FontGroup { FontGroup {
fonts: fonts, fonts: fonts,
} }

View file

@ -13,7 +13,7 @@ use font_template::FontTemplateDescriptor;
use fnv::FnvHasher; use fnv::FnvHasher;
use platform::font::FontHandle; use platform::font::FontHandle;
use platform::font_template::FontTemplateData; use platform::font_template::FontTemplateData;
use smallvec::SmallVec8; use smallvec::SmallVec;
use string_cache::Atom; use string_cache::Atom;
use util::cache::HashCache; use util::cache::HashCache;
use util::geometry::Au; use util::geometry::Au;
@ -159,7 +159,7 @@ impl FontContext {
style.font_style == font_style::T::italic || style.font_style == font_style::T::italic ||
style.font_style == font_style::T::oblique); style.font_style == font_style::T::oblique);
let mut fonts = SmallVec8::new(); let mut fonts: SmallVec<[Rc<RefCell<Font>>; 8]> = SmallVec::new();
for family in style.font_family.0.iter() { for family in style.font_family.0.iter() {
// GWTODO: Check on real pages if this is faster as Vec() or HashMap(). // GWTODO: Check on real pages if this is faster as Vec() or HashMap().

View file

@ -11,7 +11,7 @@ use context::SharedLayoutContext;
use css::node_style::StyledNode; use css::node_style::StyledNode;
use data::LayoutDataWrapper; use data::LayoutDataWrapper;
use incremental::{self, RestyleDamage}; use incremental::{self, RestyleDamage};
use smallvec::SmallVec16; use smallvec::SmallVec;
use wrapper::{LayoutElement, LayoutNode}; use wrapper::{LayoutElement, LayoutNode};
use script::dom::characterdata::CharacterDataTypeId; use script::dom::characterdata::CharacterDataTypeId;
@ -38,7 +38,7 @@ use util::opts;
use util::vec::ForgetfulSink; use util::vec::ForgetfulSink;
pub struct ApplicableDeclarations { pub struct ApplicableDeclarations {
pub normal: SmallVec16<DeclarationBlock>, pub normal: SmallVec<[DeclarationBlock; 16]>,
pub before: Vec<DeclarationBlock>, pub before: Vec<DeclarationBlock>,
pub after: Vec<DeclarationBlock>, pub after: Vec<DeclarationBlock>,
@ -49,7 +49,7 @@ pub struct ApplicableDeclarations {
impl ApplicableDeclarations { impl ApplicableDeclarations {
pub fn new() -> ApplicableDeclarations { pub fn new() -> ApplicableDeclarations {
ApplicableDeclarations { ApplicableDeclarations {
normal: SmallVec16::new(), normal: SmallVec::new(),
before: Vec::new(), before: Vec::new(),
after: Vec::new(), after: Vec::new(),
normal_shareable: false, normal_shareable: false,
@ -57,7 +57,7 @@ impl ApplicableDeclarations {
} }
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.normal = SmallVec16::new(); self.normal = SmallVec::new();
self.before = Vec::new(); self.before = Vec::new();
self.after = Vec::new(); self.after = Vec::new();
self.normal_shareable = false; self.normal_shareable = false;

View file

@ -13,7 +13,7 @@ use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, Immutab
use flow::{InorderFlowTraversal}; use flow::{InorderFlowTraversal};
use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo}; use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
use incremental::{self, RESOLVE_GENERATED_CONTENT}; use incremental::{self, RESOLVE_GENERATED_CONTENT};
use smallvec::SmallVec8; use smallvec::SmallVec;
use text::TextRunScanner; use text::TextRunScanner;
use gfx::display_list::OpaqueNode; use gfx::display_list::OpaqueNode;
@ -522,7 +522,7 @@ pub fn static_representation(list_style_type: list_style_type::T) -> char {
/// Pushes the string that represents the value rendered using the given *alphabetic system* onto /// Pushes the string that represents the value rendered using the given *alphabetic system* onto
/// the accumulator per CSS-COUNTER-STYLES § 3.1.4. /// the accumulator per CSS-COUNTER-STYLES § 3.1.4.
fn push_alphabetic_representation(mut value: i32, system: &[char], accumulator: &mut String) { fn push_alphabetic_representation(mut value: i32, system: &[char], accumulator: &mut String) {
let mut string = SmallVec8::new(); let mut string: SmallVec<[char; 8]> = SmallVec::new();
while value != 0 { while value != 0 {
// Step 1. // Step 1.
value = value - 1; value = value - 1;
@ -545,7 +545,7 @@ fn push_numeric_representation(mut value: i32, system: &[char], accumulator: &mu
} }
// Step 2. // Step 2.
let mut string = SmallVec8::new(); let mut string: SmallVec<[char; 8]> = SmallVec::new();
while value != 0 { while value != 0 {
// Step 2.1. // Step 2.1.
string.push(system[(value as usize) % system.len()]); string.push(system[(value as usize) % system.len()]);

View file

@ -57,7 +57,7 @@ use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask};
use net_traits::storage_task::StorageType; use net_traits::storage_task::StorageType;
use script_traits::ScriptControlChan; use script_traits::ScriptControlChan;
use script_traits::UntrustedNodeAddress; use script_traits::UntrustedNodeAddress;
use smallvec::SmallVec1; use smallvec::SmallVec;
use msg::compositor_msg::ScriptListener; use msg::compositor_msg::ScriptListener;
use msg::constellation_msg::ConstellationChan; use msg::constellation_msg::ConstellationChan;
use net_traits::image::base::Image; use net_traits::image::base::Image;
@ -219,7 +219,7 @@ impl<T: JSTraceable> JSTraceable for Vec<T> {
// XXXManishearth Check if the following three are optimized to no-ops // XXXManishearth Check if the following three are optimized to no-ops
// if e.trace() is a no-op (e.g it is an no_jsmanaged_fields type) // if e.trace() is a no-op (e.g it is an no_jsmanaged_fields type)
impl<T: JSTraceable + 'static> JSTraceable for SmallVec1<T> { impl<T: JSTraceable + 'static> JSTraceable for SmallVec<[T; 1]> {
#[inline] #[inline]
fn trace(&self, trc: *mut JSTracer) { fn trace(&self, trc: *mut JSTracer) {
for e in self.iter() { for e in self.iter() {

View file

@ -15,7 +15,7 @@ use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter;
use dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods; use dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::{DocumentDerived, EventCast, HTMLBodyElementCast}; use dom::bindings::codegen::InheritTypes::{DocumentDerived, EventCast, HTMLBodyElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLHeadElementCast, ElementCast}; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLHeadElementCast, ElementCast, HTMLIFrameElementCast};
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLAnchorElementCast}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLAnchorElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLAppletElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLAppletElementDerived};
@ -49,6 +49,7 @@ use dom::htmlcollection::{HTMLCollection, CollectionFilter};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::htmlheadelement::HTMLHeadElement; use dom::htmlheadelement::HTMLHeadElement;
use dom::htmlhtmlelement::HTMLHtmlElement; use dom::htmlhtmlelement::HTMLHtmlElement;
use dom::htmliframeelement::HTMLIFrameElement;
use dom::htmlscriptelement::HTMLScriptElement; use dom::htmlscriptelement::HTMLScriptElement;
use dom::location::Location; use dom::location::Location;
use dom::mouseevent::MouseEvent; use dom::mouseevent::MouseEvent;
@ -69,7 +70,7 @@ use layout_interface::{HitTestResponse, MouseOverResponse};
use msg::compositor_msg::ScriptListener; use msg::compositor_msg::ScriptListener;
use msg::constellation_msg::AnimationState; use msg::constellation_msg::AnimationState;
use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyModifiers, MozBrowserEvent}; use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyModifiers, MozBrowserEvent, SubpageId};
use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL}; use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL};
use net_traits::CookieSource::NonHTTP; use net_traits::CookieSource::NonHTTP;
use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl}; use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl};
@ -287,6 +288,7 @@ pub trait DocumentHelpers<'a> {
fn finish_load(self, load: LoadType); fn finish_load(self, load: LoadType);
fn set_current_parser(self, script: Option<&ServoHTMLParser>); fn set_current_parser(self, script: Option<&ServoHTMLParser>);
fn get_current_parser(self) -> Option<Root<ServoHTMLParser>>; fn get_current_parser(self) -> Option<Root<ServoHTMLParser>>;
fn find_iframe(self, subpage_id: SubpageId) -> Option<Root<HTMLIFrameElement>>;
} }
impl<'a> DocumentHelpers<'a> for &'a Document { impl<'a> DocumentHelpers<'a> for &'a Document {
@ -989,6 +991,13 @@ impl<'a> DocumentHelpers<'a> for &'a Document {
fn get_current_parser(self) -> Option<Root<ServoHTMLParser>> { fn get_current_parser(self) -> Option<Root<ServoHTMLParser>> {
self.current_parser.get().map(Root::from_rooted) self.current_parser.get().map(Root::from_rooted)
} }
/// Find an iframe element in the document.
fn find_iframe(self, subpage_id: SubpageId) -> Option<Root<HTMLIFrameElement>> {
NodeCast::from_ref(self).traverse_preorder()
.filter_map(HTMLIFrameElementCast::to_root)
.find(|node| node.r().subpage_id() == Some(subpage_id))
}
} }
pub enum MouseEventType { pub enum MouseEventType {

View file

@ -10,7 +10,7 @@ use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::bindings::utils::reflect_dom_object; use dom::bindings::utils::reflect_dom_object;
use dom::event::{Event, EventTypeId}; use dom::event::{Event, EventTypeId, EventBubbles, EventCancelable};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
@ -37,14 +37,14 @@ impl ProgressEvent {
} }
} }
pub fn new(global: GlobalRef, type_: DOMString, pub fn new(global: GlobalRef, type_: DOMString,
can_bubble: bool, cancelable: bool, can_bubble: EventBubbles, cancelable: EventCancelable,
length_computable: bool, loaded: u64, total: u64) -> Root<ProgressEvent> { length_computable: bool, loaded: u64, total: u64) -> Root<ProgressEvent> {
let ev = reflect_dom_object(box ProgressEvent::new_inherited(length_computable, loaded, total), let ev = reflect_dom_object(box ProgressEvent::new_inherited(length_computable, loaded, total),
global, global,
ProgressEventBinding::Wrap); ProgressEventBinding::Wrap);
{ {
let event = EventCast::from_ref(ev.r()); let event = EventCast::from_ref(ev.r());
event.InitEvent(type_, can_bubble, cancelable); event.InitEvent(type_, can_bubble == EventBubbles::Bubbles, cancelable == EventCancelable::Cancelable);
} }
ev ev
} }
@ -52,7 +52,10 @@ impl ProgressEvent {
type_: DOMString, type_: DOMString,
init: &ProgressEventBinding::ProgressEventInit) init: &ProgressEventBinding::ProgressEventInit)
-> Fallible<Root<ProgressEvent>> { -> Fallible<Root<ProgressEvent>> {
let ev = ProgressEvent::new(global, type_, init.parent.bubbles, init.parent.cancelable, let bubbles = if init.parent.bubbles {EventBubbles::Bubbles} else {EventBubbles::DoesNotBubble};
let cancelable = if init.parent.cancelable {EventCancelable::Cancelable}
else {EventCancelable::NotCancelable};
let ev = ProgressEvent::new(global, type_, bubbles, cancelable,
init.lengthComputable, init.loaded, init.total); init.lengthComputable, init.loaded, init.total);
Ok(ev) Ok(ev)
} }

View file

@ -942,7 +942,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for &'a XMLHttpRequest {
let global = self.global.root(); let global = self.global.root();
let upload_target = self.upload.root(); let upload_target = self.upload.root();
let progressevent = ProgressEvent::new(global.r(), let progressevent = ProgressEvent::new(global.r(),
type_, false, false, type_, EventBubbles::DoesNotBubble, EventCancelable::NotCancelable,
total.is_some(), loaded, total.is_some(), loaded,
total.unwrap_or(0)); total.unwrap_or(0));
let target = if upload { let target = if upload {

View file

@ -22,7 +22,7 @@
use document_loader::{LoadType, DocumentLoader, NotifierData}; use document_loader::{LoadType, DocumentLoader, NotifierData};
use dom::bindings::cell::DOMRefCell; use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState}; use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, NodeCast, EventCast};
use dom::bindings::conversions::FromJSValConvertible; use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior; use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::js::{JS, RootCollection, trace_roots}; use dom::bindings::js::{JS, RootCollection, trace_roots};
@ -35,7 +35,7 @@ use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentProgressH
DocumentProgressTask, DocumentSource, MouseEventType}; DocumentProgressTask, DocumentSource, MouseEventType};
use dom::element::{Element, AttributeHandlers}; use dom::element::{Element, AttributeHandlers};
use dom::event::{EventHelpers, EventBubbles, EventCancelable}; use dom::event::{EventHelpers, EventBubbles, EventCancelable};
use dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementHelpers}; use dom::htmliframeelement::HTMLIFrameElementHelpers;
use dom::uievent::UIEvent; use dom::uievent::UIEvent;
use dom::node::{Node, NodeHelpers, NodeDamage, window_from_node}; use dom::node::{Node, NodeHelpers, NodeDamage, window_from_node};
use dom::servohtmlparser::{ServoHTMLParser, ParserContext}; use dom::servohtmlparser::{ServoHTMLParser, ParserContext};
@ -1105,7 +1105,7 @@ impl ScriptTask {
let page = borrowed_page.find(parent_pipeline_id).unwrap(); let page = borrowed_page.find(parent_pipeline_id).unwrap();
let doc = page.document(); let doc = page.document();
let frame_element = self.find_iframe(doc.r(), subpage_id); let frame_element = doc.find_iframe(subpage_id);
if let Some(ref frame_element) = frame_element { if let Some(ref frame_element) = frame_element {
let element = ElementCast::from_ref(frame_element.r()); let element = ElementCast::from_ref(frame_element.r());
@ -1125,7 +1125,7 @@ impl ScriptTask {
let frame_element = borrowed_page.find(parent_pipeline_id).and_then(|page| { let frame_element = borrowed_page.find(parent_pipeline_id).and_then(|page| {
let doc = page.document(); let doc = page.document();
self.find_iframe(doc.r(), subpage_id) doc.find_iframe(subpage_id)
}); });
if let Some(ref frame_element) = frame_element { if let Some(ref frame_element) = frame_element {
@ -1141,7 +1141,7 @@ impl ScriptTask {
let frame_element = borrowed_page.find(containing_pipeline_id).and_then(|page| { let frame_element = borrowed_page.find(containing_pipeline_id).and_then(|page| {
let doc = page.document(); let doc = page.document();
self.find_iframe(doc.r(), old_subpage_id) doc.find_iframe(old_subpage_id)
}); });
frame_element.r().unwrap().update_subpage_id(new_subpage_id); frame_element.r().unwrap().update_subpage_id(new_subpage_id);
@ -1292,7 +1292,7 @@ impl ScriptTask {
borrowed_page.as_ref().and_then(|borrowed_page| { borrowed_page.as_ref().and_then(|borrowed_page| {
borrowed_page.find(parent_id).and_then(|page| { borrowed_page.find(parent_id).and_then(|page| {
let doc = page.document(); let doc = page.document();
self.find_iframe(doc.r(), subpage_id) doc.find_iframe(subpage_id)
}) })
}) })
}); });
@ -1459,16 +1459,6 @@ impl ScriptTask {
window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, reason); window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, reason);
} }
/// Find an iframe element in a provided document.
fn find_iframe(&self, doc: &Document, subpage_id: SubpageId)
-> Option<Root<HTMLIFrameElement>> {
let doc = NodeCast::from_ref(doc);
doc.traverse_preorder()
.filter_map(HTMLIFrameElementCast::to_root)
.find(|node| node.r().subpage_id() == Some(subpage_id))
}
/// This is the main entry point for receiving and dispatching DOM events. /// This is the main entry point for receiving and dispatching DOM events.
/// ///
/// TODO: Actually perform DOM event dispatch. /// TODO: Actually perform DOM event dispatch.
@ -1547,7 +1537,7 @@ impl ScriptTask {
let borrowed_page = self.root_page(); let borrowed_page = self.root_page();
let iframe = borrowed_page.find(pipeline_id).and_then(|page| { let iframe = borrowed_page.find(pipeline_id).and_then(|page| {
let doc = page.document(); let doc = page.document();
self.find_iframe(doc.r(), subpage_id) doc.find_iframe(subpage_id)
}); });
if let Some(iframe) = iframe.r() { if let Some(iframe) = iframe.r() {
iframe.navigate_child_browsing_context(load_data.url); iframe.navigate_child_browsing_context(load_data.url);

View file

@ -18,7 +18,7 @@ use parser::{ParserContext, log_css_error};
use properties::{PropertyDeclarationBlock, parse_property_declaration_list}; use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
use media_queries::{Device, MediaQueryList, parse_media_query_list}; use media_queries::{Device, MediaQueryList, parse_media_query_list};
use font_face::{FontFaceRule, parse_font_face_block}; use font_face::{FontFaceRule, parse_font_face_block};
use smallvec::SmallVec2; use smallvec::SmallVec;
use viewport::ViewportRule; use viewport::ViewportRule;
@ -161,13 +161,13 @@ impl Stylesheet {
/// conditional group rule will come before its nested rules. /// conditional group rule will come before its nested rules.
pub struct Rules<'a> { pub struct Rules<'a> {
// 2 because normal case is likely to be just one level of nesting (@media) // 2 because normal case is likely to be just one level of nesting (@media)
stack: SmallVec2<slice::Iter<'a, CSSRule>>, stack: SmallVec<[slice::Iter<'a, CSSRule>; 2]>,
device: Option<&'a Device> device: Option<&'a Device>
} }
impl<'a> Rules<'a> { impl<'a> Rules<'a> {
fn new(iter: slice::Iter<'a, CSSRule>, device: Option<&'a Device>) -> Rules<'a> { fn new(iter: slice::Iter<'a, CSSRule>, device: Option<&'a Device>) -> Rules<'a> {
let mut stack = SmallVec2::new(); let mut stack: SmallVec<[slice::Iter<'a, CSSRule>; 2]> = SmallVec::new();
stack.push(iter); stack.push(iter);
Rules { stack: stack, device: device } Rules { stack: stack, device: device }