aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in28
-rwxr-xr-xconfigure1
-rw-r--r--src/components/gfx/buffer_map.rs1
-rw-r--r--src/components/gfx/font.rs69
-rw-r--r--src/components/gfx/freetype_impl/font_context.rs6
-rw-r--r--src/components/gfx/gfx.rs4
-rw-r--r--src/components/gfx/platform/android/font.rs6
-rw-r--r--src/components/gfx/platform/android/font_list.rs2
-rw-r--r--src/components/main/compositing/compositor.rs12
-rw-r--r--src/components/main/compositing/compositor_layer.rs11
-rw-r--r--src/components/main/compositing/compositor_task.rs7
-rw-r--r--src/components/main/constellation.rs8
-rw-r--r--src/components/main/css/matching.rs4
-rw-r--r--src/components/main/layout/block.rs519
-rw-r--r--src/components/main/layout/construct.rs9
-rw-r--r--src/components/main/layout/context.rs75
-rw-r--r--src/components/main/layout/flow.rs21
-rw-r--r--src/components/main/layout/inline.rs2
-rw-r--r--src/components/main/layout/model.rs2
-rw-r--r--src/components/main/layout/table.rs21
-rw-r--r--src/components/main/layout/table_caption.rs5
-rw-r--r--src/components/main/layout/table_cell.rs39
-rw-r--r--src/components/main/layout/table_row.rs36
-rw-r--r--src/components/main/layout/table_rowgroup.rs15
-rw-r--r--src/components/main/layout/table_wrapper.rs45
-rw-r--r--src/components/main/platform/common/glut_windowing.rs44
-rwxr-xr-xsrc/components/main/servo.rs5
-rw-r--r--src/components/msg/compositor_msg.rs1
-rw-r--r--src/components/msg/msg.rs4
-rw-r--r--src/components/net/net.rs4
-rw-r--r--src/components/script/dom/attr.rs19
-rw-r--r--src/components/script/dom/bindings/callback.rs14
-rw-r--r--src/components/script/dom/bindings/codegen/CodegenRust.py314
-rw-r--r--src/components/script/dom/bindings/conversions.rs20
-rw-r--r--src/components/script/dom/bindings/proxyhandler.rs7
-rw-r--r--src/components/script/dom/document.rs45
-rw-r--r--src/components/script/dom/domexception.rs2
-rw-r--r--src/components/script/dom/element.rs328
-rw-r--r--src/components/script/dom/eventtarget.rs9
-rw-r--r--src/components/script/dom/formdata.rs2
-rw-r--r--src/components/script/dom/htmlelement.rs10
-rw-r--r--src/components/script/dom/htmliframeelement.rs28
-rw-r--r--src/components/script/dom/htmlimageelement.rs28
-rw-r--r--src/components/script/dom/htmlobjectelement.rs19
-rw-r--r--src/components/script/dom/htmlstyleelement.rs39
-rw-r--r--src/components/script/dom/node.rs42
-rw-r--r--src/components/script/dom/nodelist.rs2
-rw-r--r--src/components/script/dom/virtualmethods.rs107
-rw-r--r--src/components/script/dom/webidls/Element.webidl3
-rw-r--r--src/components/script/dom/webidls/Node.webidl4
-rw-r--r--src/components/script/dom/window.rs11
-rw-r--r--src/components/script/html/cssparse.rs55
-rw-r--r--src/components/script/html/hubbub_html_parser.rs24
-rw-r--r--src/components/script/script.rs5
-rw-r--r--src/components/script/script_task.rs39
-rw-r--r--src/components/style/style.rs4
-rw-r--r--src/components/util/util.rs4
m---------src/platform/android/servo-android-glue0
m---------src/platform/linux/fontconfig0
m---------src/platform/linux/rust-fontconfig0
m---------src/support/egl/rust-egl0
m---------src/support/glut/rust-glut0
m---------src/support/harfbuzz/rust-harfbuzz0
m---------src/support/layers/rust-layers0
m---------src/support/spidermonkey/rust-mozjs0
-rw-r--r--src/test/content/test_document_getElementById.html2
-rw-r--r--src/test/content/test_document_getElementById_tree_order.html40
-rw-r--r--src/test/content/test_element_attribute.html19
-rw-r--r--src/test/html/test_pseudo.html22
-rw-r--r--src/test/ref/append_style_a.html1
-rw-r--r--src/test/ref/append_style_b.html6
-rw-r--r--src/test/ref/basic.list5
-rw-r--r--src/test/ref/noteq_500x300_white.html5
-rw-r--r--src/test/ref/noteq_attr_exists_selector.html10
-rw-r--r--src/test/ref/pseudo_element_a.html22
-rw-r--r--src/test/ref/pseudo_element_b.html18
-rw-r--r--src/test/ref/setattribute_id_restyle_a.html12
-rw-r--r--src/test/ref/setattribute_id_restyle_b.html6
78 files changed, 1282 insertions, 1076 deletions
diff --git a/Makefile.in b/Makefile.in
index e96fac06955..de75507a6e1 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -30,7 +30,7 @@ B := $(CFG_BUILD_DIR)
MKFILE_DEPS := config.stamp $(call rwildcard,$(S)mk/,*)
CFG_GCCISH_CFLAGS += -DRUST_DEBUG
-CFG_RUSTC_FLAGS = -D unused-imports
+CFG_RUSTC_FLAGS += -D unused-imports
ifdef CFG_DISABLE_OPTIMIZE
$(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE))
@@ -107,6 +107,12 @@ $(B)src/compiler/rust/rust-auto-clean-stamp: $(S)src/compiler/rust-auto-clean-tr
rust: $(CFG_RUSTC)
+# These arguments are automatically provided by the Rust compiler's build process to
+# itself, so they must be specified later for our Rust modules.
+ifeq ($(CFG_OSTYPE),linux-androideabi)
+ CFG_RUSTC_FLAGS += --target arm-linux-androideabi -C android-cross-path=$(CFG_ANDROID_CROSS_PATH)
+endif
+
# Strip off submodule paths to determine "raw" submodule names.
SUBMODULES=$(shell echo $(CFG_SUBMODULES) | perl -p -e 's![A-Za-z0-9_-]+/!!g')
@@ -131,6 +137,8 @@ endif
# their name already, while others don't.
DONE_$(1) = $$(B)src/$$(PATH_$(1))/lib*.dummy
DEPS_SUBMODULES += $$(PATH_$(1))
+DEPS_SUBMODULES += $$(PATH_$(1))/.libs
+DEPS_SUBMODULES += $$(PATH_$(1))/src/.libs
endef
# these will get populated.
@@ -157,7 +165,7 @@ endef
define DEF_SUBMODULE_RULES
ENV_RLDFLAGS_$(1) = -L $$(CFG_BUILD_HOME)workspace/lib/$$(CFG_TARGET_TRIPLES)
-ENV_RLDFLAGS_$(1) += $$(foreach dep,$$(DEPS_$(1)),-L $$(B)src/$$(PATH_$$(dep)))
+ENV_RLDFLAGS_$(1) += $$(foreach dep,$$(DEPS_$(1)),-L $$(B)src/$$(PATH_$$(dep)) -L $$(B)src/$$(PATH_$$(dep))/.libs -L $$(B)src/$$(PATH_$$(dep))/src/.libs)
# variables that depend on dependency definitions from sub.mk!
ENV_CFLAGS_$(1) = CFLAGS="$$(CFLAGS_$(1))"
@@ -333,10 +341,17 @@ ifneq ($(CFG_OSTYPE),linux-androideabi)
servo: $(DEPS_servo)
@$(call E, compile: $@)
$(Q)$(RUSTC) $(RFLAGS_servo) -o $@ $<
+
+libservo.dummy: $(DEPS_servo)
+ @$(call E, compile: $@)
+ $(Q)$(RUSTC) $(RFLAGS_servo) $< --crate-type dylib,rlib
+ touch libservo.dummy
+
else
servo: $(DEPS_servo)
@$(call E, compile: $@)
- $(Q)$(RUSTC) $(RFLAGS_servo) -C gen-crate-map -o $@ $< --crate-type lib
+ $(Q)$(RUSTC) $(RFLAGS_servo) -C gen-crate-map $< -o libservo.so --crate-type dylib
+ touch servo
endif
# Darwin app packaging
@@ -354,12 +369,11 @@ package: servo
else ifeq ($(CFG_OSTYPE),linux-androideabi)
package: servo
mkdir -p sofile
- -exec cp -f {} $(CFG_BUILD_HOME)sofile \;
- find . ! \( \( -type d -path './sofile' -o -path './$(CFG_TARGET_TRIPLES)/src/compiler/rust' \) -prune \) -name '*.so' -type f | xargs cp -f -t $(CFG_BUILD_HOME)sofile
- find $(CFG_RUST_HOME)/lib/rustc/$(CFG_TARGET_TRIPLES)/lib/ -name '*.so' -type f -size +1c | xargs cp -f -t $(CFG_BUILD_HOME)sofile
+ find . ! \( \( -type d -path './sofile' -o -path './$(CFG_TARGET_TRIPLES)/src/compiler/rust' \) -prune \) -name '*.so' -type f | xargs -I {} cp -f {} $(CFG_BUILD_HOME)sofile/
+ find $(CFG_RUST_HOME)/lib/rustlib/$(CFG_TARGET_TRIPLES)/lib/ -name '*.so' -type f -size +1c | xargs -I {} cp -f {} $(CFG_BUILD_HOME)sofile/
cd $(S)src/platform/android/servo-android-glue && make with-libs
cd $(CFG_BUILD_HOME)
- cp $(S)src/platform/android/servo-android-glue/bin/ServoAndroid-debug.apk -t $(CFG_BUILD_HOME)
+ cp $(S)src/platform/android/servo-android-glue/bin/ServoAndroid-debug.apk $(CFG_BUILD_HOME)
else
diff --git a/configure b/configure
index ad101f6201f..a460952b47a 100755
--- a/configure
+++ b/configure
@@ -385,7 +385,6 @@ case ${TARGET_OSTYPE} in
probe CFG_RANLIB arm-linux-androideabi-ranlib
export PATH=${OLD_PATH}
- CFG_RUSTC_FLAGS="--target=${CFG_TARGET_TRIPLES} -C android-cross-path=${CFG_ANDROID_CROSS_PATH}"
;;
*)
CFG_PATH=$PATH
diff --git a/src/components/gfx/buffer_map.rs b/src/components/gfx/buffer_map.rs
index 4c9b8950d94..7980e16c421 100644
--- a/src/components/gfx/buffer_map.rs
+++ b/src/components/gfx/buffer_map.rs
@@ -83,6 +83,7 @@ impl<T: Tile> BufferMap<T> {
// memory limit, no need to store this new buffer; just let it drop.
if self.mem + new_buffer.get_mem() > self.max_mem && self.map.len() == 1 &&
self.map.contains_key(&new_key) {
+ new_buffer.destroy(graphics_context);
return;
}
diff --git a/src/components/gfx/font.rs b/src/components/gfx/font.rs
index 470e1bb49bb..b6a97837d90 100644
--- a/src/components/gfx/font.rs
+++ b/src/components/gfx/font.rs
@@ -453,72 +453,3 @@ impl Font {
}
}
-/*fn should_destruct_on_fail_without_leaking() {
- #[test];
- #[should_fail];
-
- let fctx = @FontContext();
- let matcher = @FontMatcher(fctx);
- let _font = matcher.get_test_font();
- fail;
-}
-
-fn should_get_glyph_indexes() {
- #[test];
-
- let fctx = @FontContext();
- let matcher = @FontMatcher(fctx);
- let font = matcher.get_test_font();
- let glyph_idx = font.glyph_index('w');
- assert!(glyph_idx == Some(40u as GlyphIndex));
-}
-
-fn should_get_glyph_advance() {
- #[test];
- #[ignore];
-
- let fctx = @FontContext();
- let matcher = @FontMatcher(fctx);
- let font = matcher.get_test_font();
- let x = font.glyph_h_advance(40u as GlyphIndex);
- assert!(x == 15f || x == 16f);
-}
-
-// Testing thread safety
-fn should_get_glyph_advance_stress() {
- #[test];
- #[ignore];
-
- let mut ports = ~[];
-
- for iter::repeat(100) {
- let (chan, port) = pipes::stream();
- ports += [@port];
- spawn_named("should_get_glyph_advance_stress") {
- let fctx = @FontContext();
- let matcher = @FontMatcher(fctx);
- let _font = matcher.get_test_font();
- let x = font.glyph_h_advance(40u as GlyphIndex);
- assert!(x == 15f || x == 16f);
- chan.send(());
- }
- }
-
- for ports.each |port| {
- port.recv();
- }
-}
-
-fn should_be_able_to_create_instances_in_multiple_threads() {
- #[test];
-
- for iter::repeat(10u) {
- do task::spawn {
- let fctx = @FontContext();
- let matcher = @FontMatcher(fctx);
- let _font = matcher.get_test_font();
- }
- }
-}
-
-*/
diff --git a/src/components/gfx/freetype_impl/font_context.rs b/src/components/gfx/freetype_impl/font_context.rs
index 4ae11ea9ade..bffe06ceda2 100644
--- a/src/components/gfx/freetype_impl/font_context.rs
+++ b/src/components/gfx/freetype_impl/font_context.rs
@@ -2,6 +2,8 @@
* 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 std::rc::Rc;
+
extern mod freetype;
extern mod fontconfig;
@@ -34,7 +36,7 @@ impl Drop for FreeTypeLibraryHandle {
}
pub struct FreeTypeFontContextHandle {
- ctx: @FreeTypeLibraryHandle,
+ ctx: Rc<FreeTypeLibraryHandle>,
}
pub impl FreeTypeFontContextHandle {
@@ -44,7 +46,7 @@ pub impl FreeTypeFontContextHandle {
if !result.succeeded() { fail!(); }
FreeTypeFontContextHandle {
- ctx: @FreeTypeLibraryHandle { ctx: ctx },
+ ctx: Rc::new(FreeTypeLibraryHandle { ctx: ctx }),
}
}
}
diff --git a/src/components/gfx/gfx.rs b/src/components/gfx/gfx.rs
index de02ece7fbd..3635d5d3b61 100644
--- a/src/components/gfx/gfx.rs
+++ b/src/components/gfx/gfx.rs
@@ -4,8 +4,10 @@
#[crate_id = "github.com/mozilla/servo#gfx:0.1"];
#[crate_type = "lib"];
+#[crate_type = "dylib"];
+#[crate_type = "rlib"];
-#[feature(globs, managed_boxes, macro_rules, phase)];
+#[feature(globs, macro_rules, phase)];
#[feature(phase)];
#[phase(syntax, link)]
diff --git a/src/components/gfx/platform/android/font.rs b/src/components/gfx/platform/android/font.rs
index 46205f57ffb..ad6228c7533 100644
--- a/src/components/gfx/platform/android/font.rs
+++ b/src/components/gfx/platform/android/font.rs
@@ -76,7 +76,7 @@ impl FontHandleMethods for FontHandle {
buf: ~[u8],
style: &SpecifiedFontStyle)
-> Result<FontHandle, ()> {
- let ft_ctx: FT_Library = fctx.ctx.borrow().ctx;
+ let ft_ctx: FT_Library = fctx.ctx.ctx;
if ft_ctx.is_null() { return Err(()); }
let face_result = create_face_from_buffer(ft_ctx, buf.as_ptr(), buf.len(), style.pt_size);
@@ -279,7 +279,7 @@ impl<'a> FontHandle {
pub fn new_from_file(fctx: &FontContextHandle, file: &str,
style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
unsafe {
- let ft_ctx: FT_Library = fctx.ctx.borrow().ctx;
+ let ft_ctx: FT_Library = fctx.ctx.ctx;
if ft_ctx.is_null() { return Err(()); }
let mut face: FT_Face = ptr::null();
@@ -306,7 +306,7 @@ impl<'a> FontHandle {
pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str)
-> Result<FontHandle, ()> {
unsafe {
- let ft_ctx: FT_Library = fctx.ctx.borrow().ctx;
+ let ft_ctx: FT_Library = fctx.ctx.ctx;
if ft_ctx.is_null() { return Err(()); }
let mut face: FT_Face = ptr::null();
diff --git a/src/components/gfx/platform/android/font_list.rs b/src/components/gfx/platform/android/font_list.rs
index e372d891797..b245b74e4bd 100644
--- a/src/components/gfx/platform/android/font_list.rs
+++ b/src/components/gfx/platform/android/font_list.rs
@@ -25,7 +25,7 @@ use font_list::{FontEntry, FontFamily, FontFamilyMap};
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;
-use collections::hashmap::HashMap;
+use collections::HashMap;
use std::libc;
use std::libc::{c_int, c_char};
use std::ptr;
diff --git a/src/components/main/compositing/compositor.rs b/src/components/main/compositing/compositor.rs
index 9ae6520c38a..72e0ec80a98 100644
--- a/src/components/main/compositing/compositor.rs
+++ b/src/components/main/compositing/compositor.rs
@@ -354,16 +354,15 @@ impl IOCompositor {
self.constellation_chan = new_constellation_chan;
}
- // FIXME(pcwalton): Take the pipeline ID into account.
fn create_root_compositor_layer_if_necessary(&mut self,
- _: PipelineId,
+ id: PipelineId,
layer_id: LayerId,
size: Size2D<f32>) {
let (root_pipeline, root_layer_id) = match self.compositor_layer {
- Some(ref compositor_layer) => {
+ Some(ref compositor_layer) if compositor_layer.pipeline.id == id => {
(compositor_layer.pipeline.clone(), compositor_layer.id_of_first_child())
}
- None => {
+ _ => {
match self.root_pipeline {
Some(ref root_pipeline) => (root_pipeline.clone(), LayerId::null()),
None => fail!("Compositor: Received new layer without initialized pipeline"),
@@ -395,6 +394,11 @@ impl IOCompositor {
ContainerLayer::add_child_start(self.root_layer.clone(),
ContainerLayerKind(new_layer.root_layer.clone()));
+
+ // Release all tiles from the layer before dropping it.
+ for layer in self.compositor_layer.mut_iter() {
+ layer.clear_all_tiles();
+ }
self.compositor_layer = Some(new_layer);
}
diff --git a/src/components/main/compositing/compositor_layer.rs b/src/components/main/compositing/compositor_layer.rs
index 678c8c03bd5..5b38b4f332f 100644
--- a/src/components/main/compositing/compositor_layer.rs
+++ b/src/components/main/compositing/compositor_layer.rs
@@ -879,7 +879,7 @@ impl CompositorLayer {
}
// Send back all tiles to renderer.
- child.get_mut_ref().child.clear();
+ child.get_mut_ref().child.clear_all_tiles();
self.build_layer_tree(graphics_context);
true
@@ -951,6 +951,15 @@ impl CompositorLayer {
}
}
+ /// Destroys tiles for this layer and all descendent layers, sending the buffers back to the
+ /// renderer to be destroyed or reused.
+ pub fn clear_all_tiles(&mut self) {
+ self.clear();
+ for kid in self.children.mut_iter() {
+ kid.child.clear_all_tiles();
+ }
+ }
+
/// Destroys all tiles of all layers, including children, *without* sending them back to the
/// renderer. You must call this only when the render task is destined to be going down;
/// otherwise, you will leak tiles.
diff --git a/src/components/main/compositing/compositor_task.rs b/src/components/main/compositing/compositor_task.rs
index f16beae7733..509c1481a0a 100644
--- a/src/components/main/compositing/compositor_task.rs
+++ b/src/components/main/compositing/compositor_task.rs
@@ -83,13 +83,6 @@ impl RenderListener for CompositorChan {
self.chan.send(Paint(pipeline_id, layer_id, layer_buffer_set, epoch))
}
- fn create_layer_group_for_pipeline(&self, id: PipelineId, page_size: Size2D<uint>) {
- let Size2D { width, height } = page_size;
- self.chan.send(CreateRootCompositorLayerIfNecessary(id,
- LayerId::null(),
- Size2D(width as f32, height as f32)))
- }
-
fn initialize_layers_for_pipeline(&self,
pipeline_id: PipelineId,
metadata: ~[LayerMetadata],
diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs
index 85fbc5eaf30..3832fac100c 100644
--- a/src/components/main/constellation.rs
+++ b/src/components/main/constellation.rs
@@ -52,7 +52,7 @@ pub struct Constellation {
}
/// Stores the Id of the outermost frame's pipeline, along with a vector of children frames
-struct FrameTree {
+pub struct FrameTree {
pipeline: RefCell<Rc<Pipeline>>,
parent: RefCell<Option<Rc<Pipeline>>>,
children: RefCell<~[ChildFrameTree]>,
@@ -74,7 +74,7 @@ impl Clone for FrameTree {
}
}
-struct ChildFrameTree {
+pub struct ChildFrameTree {
frame_tree: Rc<FrameTree>,
/// Clipping rect representing the size and position, in page coordinates, of the visible
/// region of the child frame relative to the parent.
@@ -176,14 +176,14 @@ impl Iterator<Rc<FrameTree>> for FrameTreeIterator {
}
/// Represents the portion of a page that is changing in navigating.
-struct FrameChange {
+pub struct FrameChange {
before: Option<PipelineId>,
after: Rc<FrameTree>,
navigation_type: NavigationType,
}
/// Stores the Id's of the pipelines previous and next in the browser's history
-struct NavigationContext {
+pub struct NavigationContext {
previous: ~[Rc<FrameTree>],
next: ~[Rc<FrameTree>],
current: Option<Rc<FrameTree>>,
diff --git a/src/components/main/css/matching.rs b/src/components/main/css/matching.rs
index cb60e0d9781..f84b4b53738 100644
--- a/src/components/main/css/matching.rs
+++ b/src/components/main/css/matching.rs
@@ -50,7 +50,7 @@ impl ApplicableDeclarations {
}
#[deriving(Clone)]
-struct ApplicableDeclarationsCacheEntry {
+pub struct ApplicableDeclarationsCacheEntry {
declarations: SmallVec16<MatchedProperty>,
}
@@ -159,7 +159,7 @@ pub struct StyleSharingCandidateCache {
}
#[deriving(Clone)]
-struct StyleSharingCandidate {
+pub struct StyleSharingCandidate {
style: Arc<ComputedValues>,
parent_style: Arc<ComputedValues>,
diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs
index b9f0e6fee55..7663a85a768 100644
--- a/src/components/main/layout/block.rs
+++ b/src/components/main/layout/block.rs
@@ -484,7 +484,7 @@ pub struct BlockFlow {
base: BaseFlow,
/// The associated box.
- box_: Option<Box>,
+ box_: Box,
/// TODO: is_root should be a bit field to conserve memory.
/// Whether this block flow is the root flow.
@@ -501,7 +501,7 @@ impl BlockFlow {
pub fn from_node(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> BlockFlow {
BlockFlow {
base: BaseFlow::new((*node).clone()),
- box_: Some(Box::new(constructor, node)),
+ box_: Box::new(constructor, node),
is_root: false,
static_y_offset: Au::new(0),
float: None
@@ -511,7 +511,7 @@ impl BlockFlow {
pub fn from_node_and_box(node: &ThreadSafeLayoutNode, box_: Box) -> BlockFlow {
BlockFlow {
base: BaseFlow::new((*node).clone()),
- box_: Some(box_),
+ box_: box_,
is_root: false,
static_y_offset: Au::new(0),
float: None
@@ -524,7 +524,7 @@ impl BlockFlow {
-> BlockFlow {
BlockFlow {
base: BaseFlow::new((*node).clone()),
- box_: Some(Box::new(constructor, node)),
+ box_: Box::new(constructor, node),
is_root: false,
static_y_offset: Au::new(0),
float: Some(~FloatedBlockInfo::new(float_kind))
@@ -590,10 +590,7 @@ impl BlockFlow {
/// Return this flow's box.
pub fn box_<'a>(&'a mut self) -> &'a mut Box {
- match self.box_ {
- Some(ref mut box_) => box_,
- None => fail!("BlockFlow: no principal box found")
- }
+ &mut self.box_
}
/// Return the static x offset from the appropriate Containing Block for this flow.
@@ -694,22 +691,14 @@ impl BlockFlow {
/// The only two types of replaced boxes currently are text boxes and
/// image boxes.
fn is_replaced_content(&self) -> bool {
- match self.box_ {
- Some(ref box_) => {
- match box_.specific {
- ScannedTextBox(_) | ImageBox(_) => true,
- _ => false,
- }
- }
- None => false,
+ match self.box_.specific {
+ ScannedTextBox(_) | ImageBox(_) => true,
+ _ => false,
}
}
pub fn teardown(&mut self) {
- for box_ in self.box_.iter() {
- box_.teardown();
- }
- self.box_ = None;
+ self.box_.teardown();
self.float = None;
}
@@ -791,11 +780,9 @@ impl BlockFlow {
self.base.position.size.height = self.base.position.size.height + top_margin_value +
bottom_margin_value;
- for fragment in self.box_.iter() {
- let mut position = fragment.border_box.get();
- position.size.height = position.size.height + top_margin_value + bottom_margin_value;
- fragment.border_box.set(position);
- }
+ let mut position = self.box_.border_box.get();
+ position.size.height = position.size.height + top_margin_value + bottom_margin_value;
+ self.box_.border_box.set(position);
}
/// Assign height for current flow.
@@ -819,9 +806,6 @@ impl BlockFlow {
// Our current border-box position.
let mut cur_y = Au(0);
- // The sum of our top border and top padding.
- let mut top_offset = Au(0);
-
// Absolute positioning establishes a block formatting context. Don't propagate floats
// in or out. (But do propagate them between kids.)
if inorder && self.is_absolutely_positioned() {
@@ -832,20 +816,19 @@ impl BlockFlow {
}
let mut margin_collapse_info = MarginCollapseInfo::new();
- for fragment in self.box_.iter() {
- self.base.floats.translate(Point2D(-fragment.left_offset(), Au(0)));
-
- top_offset = fragment.border.get().top + fragment.padding.get().top;
- translate_including_floats(&mut cur_y, top_offset, inorder, &mut self.base.floats);
-
- let can_collapse_top_margin_with_kids =
- margins_may_collapse == MarginsMayCollapse &&
- !self.is_absolutely_positioned() &&
- fragment.border.get().top == Au(0) &&
- fragment.padding.get().top == Au(0);
- margin_collapse_info.initialize_top_margin(fragment,
- can_collapse_top_margin_with_kids);
- }
+ self.base.floats.translate(Point2D(-self.box_.left_offset(), Au(0)));
+
+ // The sum of our top border and top padding.
+ let top_offset = self.box_.border.get().top + self.box_.padding.get().top;
+ translate_including_floats(&mut cur_y, top_offset, inorder, &mut self.base.floats);
+
+ let can_collapse_top_margin_with_kids =
+ margins_may_collapse == MarginsMayCollapse &&
+ !self.is_absolutely_positioned() &&
+ self.box_.border.get().top == Au(0) &&
+ self.box_.padding.get().top == Au(0);
+ margin_collapse_info.initialize_top_margin(&self.box_,
+ can_collapse_top_margin_with_kids);
// At this point, cur_y is at the content edge of the flow's box.
let mut floats = self.base.floats.clone();
@@ -954,19 +937,17 @@ impl BlockFlow {
self.collect_static_y_offsets_from_kids();
// Add in our bottom margin and compute our collapsible margins.
- for fragment in self.box_.iter() {
- let can_collapse_bottom_margin_with_kids =
- margins_may_collapse == MarginsMayCollapse &&
- !self.is_absolutely_positioned() &&
- fragment.border.get().bottom == Au(0) &&
- fragment.padding.get().bottom == Au(0);
- let (collapsible_margins, delta) =
- margin_collapse_info.finish_and_compute_collapsible_margins(
- fragment,
- can_collapse_bottom_margin_with_kids);
- self.base.collapsible_margins = collapsible_margins;
- translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
- }
+ let can_collapse_bottom_margin_with_kids =
+ margins_may_collapse == MarginsMayCollapse &&
+ !self.is_absolutely_positioned() &&
+ self.box_.border.get().bottom == Au(0) &&
+ self.box_.padding.get().bottom == Au(0);
+ let (collapsible_margins, delta) =
+ margin_collapse_info.finish_and_compute_collapsible_margins(
+ &self.box_,
+ can_collapse_bottom_margin_with_kids);
+ self.base.collapsible_margins = collapsible_margins;
+ translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
// FIXME(#2003, pcwalton): The max is taken here so that you can scroll the page, but this
// is not correct behavior according to CSS 2.1 § 10.5. Instead I think we should treat the
@@ -989,41 +970,37 @@ impl BlockFlow {
// Store the content height for use in calculating the absolute flow's dimensions
// later.
- for box_ in self.box_.iter() {
- let mut temp_position = box_.border_box.get();
- temp_position.size.height = height;
- box_.border_box.set(temp_position);
- }
+ let mut temp_position = self.box_.border_box.get();
+ temp_position.size.height = height;
+ self.box_.border_box.set(temp_position);
return
}
- for fragment in self.box_.iter() {
- let mut candidate_height_iterator = CandidateHeightIterator::new(fragment.style(),
- None);
- for (candidate_height, new_candidate_height) in candidate_height_iterator {
- *new_candidate_height = match candidate_height {
- Auto => height,
- Specified(value) => value
- }
+ let mut candidate_height_iterator = CandidateHeightIterator::new(self.box_.style(),
+ None);
+ for (candidate_height, new_candidate_height) in candidate_height_iterator {
+ *new_candidate_height = match candidate_height {
+ Auto => height,
+ Specified(value) => value
}
+ }
- // Adjust `cur_y` as necessary to account for the explicitly-specified height.
- height = candidate_height_iterator.candidate_value;
- let delta = height - (cur_y - top_offset);
- translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
+ // Adjust `cur_y` as necessary to account for the explicitly-specified height.
+ height = candidate_height_iterator.candidate_value;
+ let delta = height - (cur_y - top_offset);
+ translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
- // Compute content height and noncontent height.
- let bottom_offset = fragment.border.get().bottom + fragment.padding.get().bottom;
- translate_including_floats(&mut cur_y, bottom_offset, inorder, &mut floats);
-
- // Now that `cur_y` is at the bottom of the border box, compute the final border box
- // position.
- let mut border_box = fragment.border_box.get();
- border_box.size.height = cur_y;
- border_box.origin.y = Au(0);
- fragment.border_box.set(border_box);
- self.base.position.size.height = cur_y;
- }
+ // Compute content height and noncontent height.
+ let bottom_offset = self.box_.border.get().bottom + self.box_.padding.get().bottom;
+ translate_including_floats(&mut cur_y, bottom_offset, inorder, &mut floats);
+
+ // Now that `cur_y` is at the bottom of the border box, compute the final border box
+ // position.
+ let mut border_box = self.box_.border_box.get();
+ border_box.size.height = cur_y;
+ border_box.origin.y = Au(0);
+ self.box_.border_box.set(border_box);
+ self.base.position.size.height = cur_y;
self.base.floats = floats.clone();
self.adjust_boxes_for_collapsed_margins_if_root();
@@ -1054,25 +1031,18 @@ impl BlockFlow {
/// Therefore, assign_height_float was already called on this kid flow by
/// the traversal function. So, the values used are well-defined.
pub fn assign_height_float_inorder(&mut self) {
- let mut height = Au(0);
- let mut clearance = Au(0);
- let mut full_noncontent_width = Au(0);
- let mut margin_height = Au(0);
-
- for box_ in self.box_.iter() {
- height = box_.border_box.get().size.height;
- clearance = match box_.clear() {
- None => Au(0),
- Some(clear) => self.base.floats.clearance(clear),
- };
-
- let noncontent_width = box_.padding.get().left + box_.padding.get().right +
- box_.border.get().left + box_.border.get().right;
-
- full_noncontent_width = noncontent_width + box_.margin.get().left +
- box_.margin.get().right;
- margin_height = box_.margin.get().top + box_.margin.get().bottom;
- }
+ let height = self.box_.border_box.get().size.height;
+ let clearance = match self.box_.clear() {
+ None => Au(0),
+ Some(clear) => self.base.floats.clearance(clear),
+ };
+
+ let noncontent_width = self.box_.padding.get().left + self.box_.padding.get().right +
+ self.box_.border.get().left + self.box_.border.get().right;
+
+ let full_noncontent_width = noncontent_width + self.box_.margin.get().left +
+ self.box_.margin.get().right;
+ let margin_height = self.box_.margin.get().top + self.box_.margin.get().bottom;
let info = PlacementInfo {
size: Size2D(self.base.position.size.width + full_noncontent_width,
@@ -1112,12 +1082,9 @@ impl BlockFlow {
drop(floats);
}
let mut cur_y = Au(0);
- let mut top_offset = Au(0);
- for box_ in self.box_.iter() {
- top_offset = box_.margin.get().top + box_.border.get().top + box_.padding.get().top;
- cur_y = cur_y + top_offset;
- }
+ let top_offset = self.box_.margin.get().top + self.box_.border.get().top + self.box_.padding.get().top;
+ cur_y = cur_y + top_offset;
// cur_y is now at the top content edge
@@ -1131,18 +1098,17 @@ impl BlockFlow {
let content_height = cur_y - top_offset;
let mut noncontent_height;
- let box_ = self.box_.as_ref().unwrap();
- let mut position = box_.border_box.get();
+ let mut position = self.box_.border_box.get();
// The associated box is the border box of this flow.
- position.origin.y = box_.margin.get().top;
+ position.origin.y = self.box_.margin.get().top;
- noncontent_height = box_.padding.get().top + box_.padding.get().bottom +
- box_.border.get().top + box_.border.get().bottom;
+ noncontent_height = self.box_.padding.get().top + self.box_.padding.get().bottom +
+ self.box_.border.get().top + self.box_.border.get().bottom;
// Calculate content height, taking `min-height` and `max-height` into account.
- let mut candidate_height_iterator = CandidateHeightIterator::new(box_.style(), None);
+ let mut candidate_height_iterator = CandidateHeightIterator::new(self.box_.style(), None);
for (candidate_height, new_candidate_height) in candidate_height_iterator {
*new_candidate_height = match candidate_height {
Auto => content_height,
@@ -1155,7 +1121,7 @@ impl BlockFlow {
debug!("assign_height_float -- height: {}", content_height + noncontent_height);
position.size.height = content_height + noncontent_height;
- box_.border_box.set(position);
+ self.box_.border_box.set(position);
}
fn build_display_list_block_common(&mut self,
@@ -1165,28 +1131,25 @@ impl BlockFlow {
offset: Point2D<Au>,
background_border_level: BackgroundAndBorderLevel) {
let mut info = *info;
- let mut rel_offset = Point2D(Au(0), Au(0));
- for fragment in self.box_.iter() {
- rel_offset = fragment.relative_position(&info.relative_containing_block_size);
-
- // Add the box that starts the block context.
- fragment.build_display_list(stacking_context,
- builder,
- &info,
- self.base.abs_position + rel_offset + offset,
- (&*self) as &Flow,
- background_border_level);
-
- // For relatively-positioned descendants, the containing block formed by a block is
- // just the content box. The containing block for absolutely-positioned descendants,
- // on the other hand, only established if we are positioned.
- info.relative_containing_block_size = fragment.content_box_size();
- if self.is_positioned() {
- info.absolute_containing_block_position =
- self.base.abs_position +
- self.generated_cb_position() +
- fragment.relative_position(&info.relative_containing_block_size)
- }
+ let rel_offset = self.box_.relative_position(&info.relative_containing_block_size);
+
+ // Add the box that starts the block context.
+ self.box_.build_display_list(stacking_context,
+ builder,
+ &info,
+ self.base.abs_position + rel_offset + offset,
+ (&*self) as &Flow,
+ background_border_level);
+
+ // For relatively-positioned descendants, the containing block formed by a block is
+ // just the content box. The containing block for absolutely-positioned descendants,
+ // on the other hand, only established if we are positioned.
+ info.relative_containing_block_size = self.box_.content_box_size();
+ if self.is_positioned() {
+ info.absolute_containing_block_position =
+ self.base.abs_position +
+ self.generated_cb_position() +
+ self.box_.relative_position(&info.relative_containing_block_size)
}
let this_position = self.base.abs_position;
@@ -1268,40 +1231,54 @@ impl BlockFlow {
let containing_block_height = self.containing_block_size(ctx.screen_size).height;
let static_y_offset = self.static_y_offset;
- for box_ in self.box_.iter() {
- // This is the stored content height value from assign-height
- let content_height = box_.border_box.get().size.height - box_.noncontent_height();
-
- let style = box_.style();
-
- // Non-auto margin-top and margin-bottom values have already been
- // calculated during assign-width.
- let margin = box_.margin.get();
- let margin_top = match MaybeAuto::from_style(style.Margin.get().margin_top, Au(0)) {
- Auto => Auto,
- _ => Specified(margin.top)
- };
- let margin_bottom = match MaybeAuto::from_style(style.Margin.get().margin_bottom, Au(0)) {
- Auto => Auto,
- _ => Specified(margin.bottom)
- };
-
- let (top, bottom) =
- (MaybeAuto::from_style(style.PositionOffsets.get().top, containing_block_height),
- MaybeAuto::from_style(style.PositionOffsets.get().bottom, containing_block_height));
- let available_height = containing_block_height - box_.noncontent_height();
-
- let mut solution = None;
- if self.is_replaced_content() {
- // Calculate used value of height just like we do for inline replaced elements.
- // TODO: Pass in the containing block height when Box's
- // assign-height can handle it correctly.
- box_.assign_replaced_height_if_necessary();
- // TODO: Right now, this content height value includes the
- // margin because of erroneous height calculation in Box_.
- // Check this when that has been fixed.
- let height_used_val = box_.border_box.get().size.height;
- solution = Some(HeightConstraintSolution::solve_vertical_constraints_abs_replaced(
+ // This is the stored content height value from assign-height
+ let content_height = self.box_.border_box.get().size.height - self.box_.noncontent_height();
+
+ let style = self.box_.style();
+
+ // Non-auto margin-top and margin-bottom values have already been
+ // calculated during assign-width.
+ let margin = self.box_.margin.get();
+ let margin_top = match MaybeAuto::from_style(style.Margin.get().margin_top, Au(0)) {
+ Auto => Auto,
+ _ => Specified(margin.top)
+ };
+ let margin_bottom = match MaybeAuto::from_style(style.Margin.get().margin_bottom, Au(0)) {
+ Auto => Auto,
+ _ => Specified(margin.bottom)
+ };
+
+ let (top, bottom) =
+ (MaybeAuto::from_style(style.PositionOffsets.get().top, containing_block_height),
+ MaybeAuto::from_style(style.PositionOffsets.get().bottom, containing_block_height));
+ let available_height = containing_block_height - self.box_.noncontent_height();
+
+ let mut solution = None;
+ if self.is_replaced_content() {
+ // Calculate used value of height just like we do for inline replaced elements.
+ // TODO: Pass in the containing block height when Box's
+ // assign-height can handle it correctly.
+ self.box_.assign_replaced_height_if_necessary();
+ // TODO: Right now, this content height value includes the
+ // margin because of erroneous height calculation in Box_.
+ // Check this when that has been fixed.
+ let height_used_val = self.box_.border_box.get().size.height;
+ solution = Some(HeightConstraintSolution::solve_vertical_constraints_abs_replaced(
+ height_used_val,
+ margin_top,
+ margin_bottom,
+ top,
+ bottom,
+ content_height,
+ available_height,
+ static_y_offset));
+ } else {
+ let mut candidate_height_iterator =
+ CandidateHeightIterator::new(style, Some(containing_block_height));
+
+ for (height_used_val, new_candidate_height) in candidate_height_iterator {
+ solution =
+ Some(HeightConstraintSolution::solve_vertical_constraints_abs_nonreplaced(
height_used_val,
margin_top,
margin_bottom,
@@ -1310,43 +1287,27 @@ impl BlockFlow {
content_height,
available_height,
static_y_offset));
- } else {
- let mut candidate_height_iterator =
- CandidateHeightIterator::new(style, Some(containing_block_height));
-
- for (height_used_val, new_candidate_height) in candidate_height_iterator {
- solution =
- Some(HeightConstraintSolution::solve_vertical_constraints_abs_nonreplaced(
- height_used_val,
- margin_top,
- margin_bottom,
- top,
- bottom,
- content_height,
- available_height,
- static_y_offset));
-
- *new_candidate_height = solution.unwrap().height
- }
+
+ *new_candidate_height = solution.unwrap().height
}
+ }
- let solution = solution.unwrap();
+ let solution = solution.unwrap();
- let mut margin = box_.margin.get();
- margin.top = solution.margin_top;
- margin.bottom = solution.margin_bottom;
- box_.margin.set(margin);
+ let mut margin = self.box_.margin.get();
+ margin.top = solution.margin_top;
+ margin.bottom = solution.margin_bottom;
+ self.box_.margin.set(margin);
- let mut position = box_.border_box.get();
- position.origin.y = Au(0);
- // Border box height
- let border_and_padding = box_.noncontent_height();
- position.size.height = solution.height + border_and_padding;
- box_.border_box.set(position);
+ let mut position = self.box_.border_box.get();
+ position.origin.y = Au(0);
+ // Border box height
+ let border_and_padding = self.box_.noncontent_height();
+ position.size.height = solution.height + border_and_padding;
+ self.box_.border_box.set(position);
- self.base.position.origin.y = solution.top + margin.top;
- self.base.position.size.height = solution.height + border_and_padding;
- }
+ self.base.position.origin.y = solution.top + margin.top;
+ self.base.position.size.height = solution.height + border_and_padding;
}
/// Add display items for Absolutely Positioned flow.
@@ -1439,15 +1400,10 @@ impl BlockFlow {
let kid_abs_cb_x_offset;
if self.is_positioned() {
- match self.box_ {
- Some(ref box_) => {
- // Pass yourself as a new Containing Block
- // The static x offset for any immediate kid flows will be the
- // left padding
- kid_abs_cb_x_offset = box_.padding.get().left;
- }
- None => fail!("BlockFlow: no principal box found"),
- }
+ // Pass yourself as a new Containing Block
+ // The static x offset for any immediate kid flows will be the
+ // left padding
+ kid_abs_cb_x_offset = self.box_.padding.get().left;
} else {
// For kids, the left margin edge will be at our left content edge.
// The current static offset is at our left margin
@@ -1565,20 +1521,18 @@ impl Flow for BlockFlow {
}
// Add in borders, padding, and margins.
- for box_ in self.box_.iter() {
- {
- // Can compute border width here since it doesn't depend on anything.
- box_.compute_borders(box_.style())
- }
-
- let box_intrinsic_widths = box_.intrinsic_widths();
- intrinsic_widths.minimum_width = geometry::max(intrinsic_widths.minimum_width,
- box_intrinsic_widths.minimum_width);
- intrinsic_widths.preferred_width = geometry::max(intrinsic_widths.preferred_width,
- box_intrinsic_widths.preferred_width);
- intrinsic_widths.surround_width = box_intrinsic_widths.surround_width
+ {
+ // Can compute border width here since it doesn't depend on anything.
+ self.box_.compute_borders(self.box_.style())
}
+ let box_intrinsic_widths = self.box_.intrinsic_widths();
+ intrinsic_widths.minimum_width = geometry::max(intrinsic_widths.minimum_width,
+ box_intrinsic_widths.minimum_width);
+ intrinsic_widths.preferred_width = geometry::max(intrinsic_widths.preferred_width,
+ box_intrinsic_widths.preferred_width);
+ intrinsic_widths.surround_width = box_intrinsic_widths.surround_width;
+
self.base.intrinsic_widths = intrinsic_widths
}
@@ -1606,25 +1560,21 @@ impl Flow for BlockFlow {
// The position was set to the containing block by the flow's parent.
let containing_block_width = self.base.position.size.width;
- let mut left_content_edge = Au::new(0);
- let mut content_width = containing_block_width;
self.set_containing_width_if_float(containing_block_width);
self.compute_used_width(ctx, containing_block_width);
- for box_ in self.box_.iter() {
- // Assign `clear` now so that the assign-heights pass will have the correct value for
- // it.
- self.base.clear = box_.style().Box.get().clear;
-
- // Move in from the left border edge
- left_content_edge = box_.border_box.get().origin.x
- + box_.padding.get().left + box_.border.get().left;
- let padding_and_borders = box_.padding.get().left + box_.padding.get().right +
- box_.border.get().left + box_.border.get().right;
- content_width = box_.border_box.get().size.width - padding_and_borders;
- }
+ // Assign `clear` now so that the assign-heights pass will have the correct value for
+ // it.
+ self.base.clear = self.box_.style().Box.get().clear;
+
+ // Move in from the left border edge
+ let left_content_edge = self.box_.border_box.get().origin.x
+ + self.box_.padding.get().left + self.box_.border.get().left;
+ let padding_and_borders = self.box_.padding.get().left + self.box_.padding.get().right +
+ self.box_.border.get().left + self.box_.border.get().right;
+ let content_width = self.box_.border_box.get().size.width - padding_and_borders;
if self.is_float() {
self.base.position.size.width = content_width;
@@ -1649,9 +1599,7 @@ impl Flow for BlockFlow {
fn assign_height(&mut self, ctx: &mut LayoutContext) {
// Assign height for box if it is an image box.
- for box_ in self.box_.iter() {
- box_.assign_replaced_height_if_necessary();
- }
+ self.box_.assign_replaced_height_if_necessary();
if self.is_float() {
debug!("assign_height_float: assigning height for float");
@@ -1689,12 +1637,7 @@ impl Flow for BlockFlow {
/// The 'position' property of this flow.
fn positioning(&self) -> position::T {
- match self.box_ {
- Some(ref box_) => {
- box_.style.get().Box.get().position
- }
- None => fail!("BlockFlow does not have a box_")
- }
+ self.box_.style.get().Box.get().position
}
/// Return true if this is the root of an Absolute flow tree.
@@ -1708,34 +1651,20 @@ impl Flow for BlockFlow {
///
/// For Blocks, this will be the padding box.
fn generated_cb_size(&self) -> Size2D<Au> {
- match self.box_ {
- Some(ref box_) => {
- box_.padding_box_size()
- }
- None => fail!("Containing Block must have a box")
- }
+ self.box_.padding_box_size()
}
/// Return position of the CB generated by this flow from the start of this flow.
fn generated_cb_position(&self) -> Point2D<Au> {
- match self.box_ {
- Some(ref box_) => {
- // Border box y coordinate + border top
- box_.border_box.get().origin + Point2D(box_.border.get().left, box_.border.get().top)}
- None => fail!("Containing Block must have a box")
- }
+ // Border box y coordinate + border top
+ self.box_.border_box.get().origin + Point2D(self.box_.border.get().left, self.box_.border.get().top)
}
fn layer_id(&self, fragment_index: uint) -> LayerId {
// FIXME(#2010, pcwalton): This is a hack and is totally bogus in the presence of pseudo-
// elements. But until we have incremental reflow we can't do better--we recreate the flow
// for every DOM node so otherwise we nuke layers on every reflow.
- match self.box_ {
- Some(ref box_) => {
- LayerId(box_.node.id(), fragment_index)
- }
- None => fail!("can't make a layer ID for a flow with no box"),
- }
+ LayerId(self.box_.node.id(), fragment_index)
}
fn debug_str(&self) -> ~str {
@@ -1746,10 +1675,7 @@ impl Flow for BlockFlow {
} else {
~"BlockFlow: "
};
- txt.append(match self.box_ {
- Some(ref rb) => rb.debug_str(),
- None => ~"",
- })
+ txt.append(self.box_.debug_str())
}
fn is_absolute_containing_block(&self) -> bool {
@@ -1841,35 +1767,32 @@ pub trait WidthAndMarginsComputer {
-> WidthConstraintInput {
let containing_block_width = self.containing_block_width(block, parent_flow_width, ctx);
let computed_width = self.initial_computed_width(block, parent_flow_width, ctx);
- for box_ in block.box_.iter() {
- let style = box_.style();
-
- // The text alignment of a block flow is the text alignment of its box's style.
- block.base.flags_info.flags.set_text_align(style.InheritedText.get().text_align);
-
- box_.compute_padding(style, containing_block_width);
-
- // We calculate and set margin-top and margin-bottom here
- // because CSS 2.1 defines % on this wrt CB *width*.
- box_.compute_margin_top_bottom(containing_block_width);
-
- let (margin_left, margin_right) =
- (MaybeAuto::from_style(style.Margin.get().margin_left, containing_block_width),
- MaybeAuto::from_style(style.Margin.get().margin_right, containing_block_width));
-
- let (left, right) =
- (MaybeAuto::from_style(style.PositionOffsets.get().left, containing_block_width),
- MaybeAuto::from_style(style.PositionOffsets.get().right, containing_block_width));
- let available_width = containing_block_width - box_.noncontent_width();
- return WidthConstraintInput::new(computed_width,
- margin_left,
- margin_right,
- left,
- right,
- available_width,
- block.static_x_offset());
- }
- fail!("Block doesn't have a principal box")
+ let style = block.box_.style();
+
+ // The text alignment of a block flow is the text alignment of its box's style.
+ block.base.flags_info.flags.set_text_align(style.InheritedText.get().text_align);
+
+ block.box_.compute_padding(style, containing_block_width);
+
+ // We calculate and set margin-top and margin-bottom here
+ // because CSS 2.1 defines % on this wrt CB *width*.
+ block.box_.compute_margin_top_bottom(containing_block_width);
+
+ let (margin_left, margin_right) =
+ (MaybeAuto::from_style(style.Margin.get().margin_left, containing_block_width),
+ MaybeAuto::from_style(style.Margin.get().margin_right, containing_block_width));
+
+ let (left, right) =
+ (MaybeAuto::from_style(style.PositionOffsets.get().left, containing_block_width),
+ MaybeAuto::from_style(style.PositionOffsets.get().right, containing_block_width));
+ let available_width = containing_block_width - block.box_.noncontent_width();
+ return WidthConstraintInput::new(computed_width,
+ margin_left,
+ margin_right,
+ left,
+ right,
+ available_width,
+ block.static_x_offset());
}
/// Set the used values for width and margins got from the relevant constraint equation.
diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs
index 398f915197b..bf5ed0673d0 100644
--- a/src/components/main/layout/construct.rs
+++ b/src/components/main/layout/construct.rs
@@ -98,7 +98,7 @@ impl ConstructionResult {
/// Represents the output of flow construction for a DOM node that has not yet resulted in a
/// complete flow. Construction items bubble up the tree until they find a `Flow` to be
/// attached to.
-enum ConstructionItem {
+pub enum ConstructionItem {
/// Inline boxes and associated {ib} splits that have not yet found flows.
InlineBoxesConstructionItem(InlineBoxesConstructionResult),
/// Potentially ignorable whitespace.
@@ -124,7 +124,7 @@ impl ConstructionItem {
}
/// Represents inline boxes and {ib} splits that are bubbling up from an inline.
-struct InlineBoxesConstructionResult {
+pub struct InlineBoxesConstructionResult {
/// Any {ib} splits that we're bubbling up.
///
/// TODO(pcwalton): Small vector optimization.
@@ -159,7 +159,7 @@ struct InlineBoxesConstructionResult {
/// }),~[
/// C
/// ])
-struct InlineBlockSplit {
+pub struct InlineBlockSplit {
/// The inline boxes that precede the flow.
///
/// TODO(pcwalton): Small vector optimization.
@@ -558,6 +558,9 @@ impl<'a> FlowConstructor<'a> {
// Concatenate all the boxes of our kids, creating {ib} splits as necessary.
for kid in node.children() {
+ if kid.get_element_type() != Normal {
+ self.process(&kid);
+ }
match kid.swap_out_construction_result() {
NoConstructionResult => {}
FlowConstructionResult(flow, kid_abs_descendants) => {
diff --git a/src/components/main/layout/context.rs b/src/components/main/layout/context.rs
index 1b13470ed30..512e71aca7a 100644
--- a/src/components/main/layout/context.rs
+++ b/src/components/main/layout/context.rs
@@ -9,6 +9,7 @@ use css::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
use geom::size::Size2D;
use gfx::display_list::OpaqueNode;
use gfx::font_context::{FontContext, FontContextInfo};
+#[cfg(not(target_os="android"))]
use green::task::GreenTask;
use script::layout_interface::LayoutChan;
use servo_msg::constellation_msg::ConstellationChan;
@@ -16,25 +17,44 @@ use servo_net::local_image_cache::LocalImageCache;
use servo_util::geometry::Au;
use servo_util::opts::Opts;
use std::cast;
+#[cfg(not(target_os="android"))]
use std::ptr;
+#[cfg(not(target_os="android"))]
use std::rt::Runtime;
+#[cfg(not(target_os="android"))]
use std::rt::local::Local;
+#[cfg(not(target_os="android"))]
use std::rt::task::Task;
use style::{ComputedValues, Stylist};
use sync::{Arc, MutexArc};
use url::Url;
+#[cfg(target_os="android")]
+use std::local_data;
+
+#[cfg(not(target_os="android"))]
#[thread_local]
static mut FONT_CONTEXT: *mut FontContext = 0 as *mut FontContext;
+#[cfg(target_os="android")]
+local_data_key!(font_context: *mut FontContext)
+
+#[cfg(not(target_os="android"))]
#[thread_local]
static mut APPLICABLE_DECLARATIONS_CACHE: *mut ApplicableDeclarationsCache =
0 as *mut ApplicableDeclarationsCache;
+#[cfg(target_os="android")]
+local_data_key!(applicable_declarations_cache: *mut ApplicableDeclarationsCache)
+
+#[cfg(not(target_os="android"))]
#[thread_local]
static mut STYLE_SHARING_CANDIDATE_CACHE: *mut StyleSharingCandidateCache =
0 as *mut StyleSharingCandidateCache;
+#[cfg(target_os="android")]
+local_data_key!(style_sharing_candidate_cache: *mut StyleSharingCandidateCache)
+
/// Data shared by all layout workers.
#[deriving(Clone)]
pub struct LayoutContext {
@@ -71,6 +91,7 @@ pub struct LayoutContext {
opts: Opts,
}
+#[cfg(not(target_os="android"))]
impl LayoutContext {
pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
// Sanity check.
@@ -139,3 +160,57 @@ impl LayoutContext {
}
}
+
+// On Android, we don't have the __tls_* functions emitted by rustc, so we
+// need to use the slower local_data functions.
+// Making matters worse, the local_data functions are very particular about
+// enforcing the lifetimes associated with objects that they hold onto,
+// which causes us some trouble we work around as below.
+#[cfg(target_os="android")]
+impl LayoutContext {
+ pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
+ unsafe {
+ let opt = local_data::pop(font_context);
+ let mut context;
+ match opt {
+ Some(c) => context = cast::transmute(c),
+ None => {
+ context = cast::transmute(~FontContext::new(self.font_context_info.clone()))
+ }
+ }
+ local_data::set(font_context, context);
+ cast::transmute(context)
+ }
+ }
+
+ pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
+ unsafe {
+ let opt = local_data::pop(applicable_declarations_cache);
+ let mut cache;
+ match opt {
+ Some(c) => cache = cast::transmute(c),
+ None => {
+ cache = cast::transmute(~ApplicableDeclarationsCache::new());
+ }
+ }
+ local_data::set(applicable_declarations_cache, cache);
+ cast::transmute(cache)
+ }
+ }
+
+ pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
+ unsafe {
+ let opt = local_data::pop(style_sharing_candidate_cache);
+ let mut cache;
+ match opt {
+ Some(c) => cache = cast::transmute(c),
+ None => {
+ cache = cast::transmute(~StyleSharingCandidateCache::new());
+ }
+ }
+ local_data::set(style_sharing_candidate_cache, cache);
+ cast::transmute(cache)
+ }
+ }
+}
+
diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs
index 2fd6b310d86..96db9770a5d 100644
--- a/src/components/main/layout/flow.rs
+++ b/src/components/main/layout/flow.rs
@@ -718,9 +718,9 @@ impl Descendants {
pub type AbsDescendants = Descendants;
-type DescendantIter<'a> = MutItems<'a, Rawlink>;
+pub type DescendantIter<'a> = MutItems<'a, Rawlink>;
-type DescendantOffsetIter<'a> = Zip<MutItems<'a, Rawlink>, MutItems<'a, Au>>;
+pub type DescendantOffsetIter<'a> = Zip<MutItems<'a, Rawlink>, MutItems<'a, Au>>;
/// Data common to all flows.
pub struct BaseFlow {
@@ -805,23 +805,6 @@ impl Drop for BaseFlow {
}
}
-pub struct BoxIterator {
- priv boxes: ~[@Box],
- priv index: uint,
-}
-
-impl Iterator<@Box> for BoxIterator {
- fn next(&mut self) -> Option<@Box> {
- if self.index >= self.boxes.len() {
- None
- } else {
- let v = self.boxes[self.index].clone();
- self.index += 1;
- Some(v)
- }
- }
-}
-
impl BaseFlow {
#[inline]
pub fn new(node: ThreadSafeLayoutNode) -> BaseFlow {
diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs
index 940d2b50d95..a504031b69b 100644
--- a/src/components/main/layout/inline.rs
+++ b/src/components/main/layout/inline.rs
@@ -50,7 +50,7 @@ use style::computed_values::{text_align, vertical_align, white_space};
/// with a float or a horizontal wall of the containing block. The top
/// left corner of the green zone is the same as that of the line, but
/// the green zone can be taller and wider than the line itself.
-struct LineBox {
+pub struct LineBox {
range: Range,
bounds: Rect<Au>,
green_zone: Size2D<Au>
diff --git a/src/components/main/layout/model.rs b/src/components/main/layout/model.rs
index 098e238a252..fac209ac770 100644
--- a/src/components/main/layout/model.rs
+++ b/src/components/main/layout/model.rs
@@ -231,7 +231,7 @@ impl MarginCollapseInfo {
}
}
-enum MarginCollapseState {
+pub enum MarginCollapseState {
AccumulatingCollapsibleTopMargin,
AccumulatingMarginIn,
}
diff --git a/src/components/main/layout/table.rs b/src/components/main/layout/table.rs
index 1a8b38975ba..679a944a333 100644
--- a/src/components/main/layout/table.rs
+++ b/src/components/main/layout/table.rs
@@ -241,9 +241,7 @@ impl Flow for TableFlow {
let child_base = flow::mut_base(kid);
num_floats = num_floats + child_base.num_floats;
}
- for box_ in self.block_flow.box_.iter() {
- box_.compute_borders(box_.style());
- }
+ self.block_flow.box_.compute_borders(self.block_flow.box_.style());
self.block_flow.base.num_floats = num_floats;
self.block_flow.base.intrinsic_widths.minimum_width = min_width;
self.block_flow.base.intrinsic_widths.preferred_width = geometry::max(min_width, pref_width);
@@ -256,8 +254,6 @@ impl Flow for TableFlow {
// The position was set to the containing block by the flow's parent.
let containing_block_width = self.block_flow.base.position.size.width;
- let mut left_content_edge = Au::new(0);
- let mut content_width = containing_block_width;
let mut num_unspecified_widths = 0;
let mut total_column_width = Au::new(0);
@@ -272,12 +268,10 @@ impl Flow for TableFlow {
let width_computer = InternalTable;
width_computer.compute_used_width(&mut self.block_flow, ctx, containing_block_width);
- for box_ in self.block_flow.box_.iter() {
- left_content_edge = box_.padding.get().left + box_.border.get().left;
- let padding_and_borders = box_.padding.get().left + box_.padding.get().right +
- box_.border.get().left + box_.border.get().right;
- content_width = box_.border_box.get().size.width - padding_and_borders;
- }
+ let left_content_edge = self.block_flow.box_.padding.get().left + self.block_flow.box_.border.get().left;
+ let padding_and_borders = self.block_flow.box_.padding.get().left + self.block_flow.box_.padding.get().right +
+ self.block_flow.box_.border.get().left + self.block_flow.box_.border.get().right;
+ let content_width = self.block_flow.box_.border_box.get().size.width - padding_and_borders;
match self.table_layout {
FixedLayout => {
@@ -319,10 +313,7 @@ impl Flow for TableFlow {
fn debug_str(&self) -> ~str {
let txt = ~"TableFlow: ";
- txt.append(match self.block_flow.box_ {
- Some(ref rb) => rb.debug_str(),
- None => ~"",
- })
+ txt.append(self.block_flow.box_.debug_str())
}
}
diff --git a/src/components/main/layout/table_caption.rs b/src/components/main/layout/table_caption.rs
index 7aecbe22fb5..2b55ad95e30 100644
--- a/src/components/main/layout/table_caption.rs
+++ b/src/components/main/layout/table_caption.rs
@@ -78,9 +78,6 @@ impl Flow for TableCaptionFlow {
fn debug_str(&self) -> ~str {
let txt = ~"TableCaptionFlow: ";
- txt.append(match self.block_flow.box_ {
- Some(ref rb) => rb.debug_str(),
- None => ~"",
- })
+ txt.append(self.block_flow.box_.debug_str())
}
}
diff --git a/src/components/main/layout/table_cell.rs b/src/components/main/layout/table_cell.rs
index d6e88b629fe..6f6da339d55 100644
--- a/src/components/main/layout/table_cell.rs
+++ b/src/components/main/layout/table_cell.rs
@@ -35,7 +35,7 @@ impl TableCellFlow {
self.block_flow.teardown()
}
- pub fn box_<'a>(&'a mut self) -> &'a Option<Box>{
+ pub fn box_<'a>(&'a mut self) -> &'a Box {
&self.block_flow.box_
}
@@ -77,17 +77,15 @@ impl Flow for TableCellFlow {
/// Minimum/preferred widths set by this function are used in automatic table layout calculation.
fn bubble_widths(&mut self, ctx: &mut LayoutContext) {
self.block_flow.bubble_widths(ctx);
- for box_ in self.block_flow.box_.iter() {
- let specified_width = MaybeAuto::from_style(box_.style().Box.get().width,
- Au::new(0)).specified_or_zero();
- if self.block_flow.base.intrinsic_widths.minimum_width < specified_width {
- self.block_flow.base.intrinsic_widths.minimum_width = specified_width;
- }
- if self.block_flow.base.intrinsic_widths.preferred_width <
- self.block_flow.base.intrinsic_widths.minimum_width {
- self.block_flow.base.intrinsic_widths.preferred_width =
- self.block_flow.base.intrinsic_widths.minimum_width;
- }
+ let specified_width = MaybeAuto::from_style(self.block_flow.box_.style().Box.get().width,
+ Au::new(0)).specified_or_zero();
+ if self.block_flow.base.intrinsic_widths.minimum_width < specified_width {
+ self.block_flow.base.intrinsic_widths.minimum_width = specified_width;
+ }
+ if self.block_flow.base.intrinsic_widths.preferred_width <
+ self.block_flow.base.intrinsic_widths.minimum_width {
+ self.block_flow.base.intrinsic_widths.preferred_width =
+ self.block_flow.base.intrinsic_widths.minimum_width;
}
}
@@ -98,18 +96,14 @@ impl Flow for TableCellFlow {
// The position was set to the column width by the parent flow, table row flow.
let containing_block_width = self.block_flow.base.position.size.width;
- let mut left_content_edge = Au::new(0);
- let mut content_width = containing_block_width;
let width_computer = InternalTable;
width_computer.compute_used_width(&mut self.block_flow, ctx, containing_block_width);
- for box_ in self.block_flow.box_.iter() {
- left_content_edge = box_.border_box.get().origin.x + box_.padding.get().left + box_.border.get().left;
- let padding_and_borders = box_.padding.get().left + box_.padding.get().right +
- box_.border.get().left + box_.border.get().right;
- content_width = box_.border_box.get().size.width - padding_and_borders;
- }
+ let left_content_edge = self.block_flow.box_.border_box.get().origin.x + self.block_flow.box_.padding.get().left + self.block_flow.box_.border.get().left;
+ let padding_and_borders = self.block_flow.box_.padding.get().left + self.block_flow.box_.padding.get().right +
+ self.block_flow.box_.border.get().left + self.block_flow.box_.border.get().right;
+ let content_width = self.block_flow.box_.border_box.get().size.width - padding_and_borders;
self.block_flow.propagate_assigned_width_to_children(left_content_edge, content_width, None);
}
@@ -130,10 +124,7 @@ impl Flow for TableCellFlow {
fn debug_str(&self) -> ~str {
let txt = ~"TableCellFlow: ";
- txt.append(match self.block_flow.box_ {
- Some(ref rb) => rb.debug_str(),
- None => ~"",
- })
+ txt.append(self.block_flow.box_.debug_str())
}
}
diff --git a/src/components/main/layout/table_row.rs b/src/components/main/layout/table_row.rs
index d0b251d08de..f4319fabee3 100644
--- a/src/components/main/layout/table_row.rs
+++ b/src/components/main/layout/table_row.rs
@@ -64,7 +64,7 @@ impl TableRowFlow {
self.col_pref_widths = ~[];
}
- pub fn box_<'a>(&'a mut self) -> &'a Option<Box>{
+ pub fn box_<'a>(&'a mut self) -> &'a Box {
&self.block_flow.box_
}
@@ -93,7 +93,8 @@ impl TableRowFlow {
kid.assign_height_inorder(layout_context)
}
- for child_box in kid.as_table_cell().box_().iter() {
+ {
+ let child_box = kid.as_table_cell().box_();
// TODO: Percentage height
let child_specified_height = MaybeAuto::from_style(child_box.style().Box.get().height,
Au::new(0)).specified_or_zero();
@@ -105,28 +106,25 @@ impl TableRowFlow {
}
let mut height = max_y;
- for box_ in self.block_flow.box_.iter() {
- // TODO: Percentage height
- height = match MaybeAuto::from_style(box_.style().Box.get().height, Au(0)) {
- Auto => height,
- Specified(value) => geometry::max(value, height)
- };
- }
+ // TODO: Percentage height
+ height = match MaybeAuto::from_style(self.block_flow.box_.style().Box.get().height, Au(0)) {
+ Auto => height,
+ Specified(value) => geometry::max(value, height)
+ };
// cur_y = cur_y + height;
// Assign the height of own box
//
// FIXME(pcwalton): Take `cur_y` into account.
- for box_ in self.block_flow.box_.iter() {
- let mut position = box_.border_box.get();
- position.size.height = height;
- box_.border_box.set(position);
- }
+ let mut position = self.block_flow.box_.border_box.get();
+ position.size.height = height;
+ self.block_flow.box_.border_box.set(position);
self.block_flow.base.position.size.height = height;
// Assign the height of kid boxes, which is the same value as own height.
for kid in self.block_flow.base.child_iter() {
- for kid_box_ in kid.as_table_cell().box_().iter() {
+ {
+ let kid_box_ = kid.as_table_cell().box_();
let mut position = kid_box_.border_box.get();
position.size.height = height;
kid_box_.border_box.set(position);
@@ -185,7 +183,8 @@ impl Flow for TableRowFlow {
assert!(kid.is_table_cell());
// collect the specified column widths of cells. These are used in fixed table layout calculation.
- for child_box in kid.as_table_cell().box_().iter() {
+ {
+ let child_box = kid.as_table_cell().box_();
let child_specified_width = MaybeAuto::from_style(child_box.style().Box.get().width,
Au::new(0)).specified_or_zero();
self.col_widths.push(child_specified_width);
@@ -237,10 +236,7 @@ impl Flow for TableRowFlow {
fn debug_str(&self) -> ~str {
let txt = ~"TableRowFlow: ";
- txt.append(match self.block_flow.box_ {
- Some(ref rb) => rb.debug_str(),
- None => ~"",
- })
+ txt.append(self.block_flow.box_.debug_str())
}
}
diff --git a/src/components/main/layout/table_rowgroup.rs b/src/components/main/layout/table_rowgroup.rs
index a0b2364146c..af1e9a025e9 100644
--- a/src/components/main/layout/table_rowgroup.rs
+++ b/src/components/main/layout/table_rowgroup.rs
@@ -63,7 +63,7 @@ impl TableRowGroupFlow {
self.col_pref_widths = ~[];
}
- pub fn box_<'a>(&'a mut self) -> &'a Option<Box>{
+ pub fn box_<'a>(&'a mut self) -> &'a Box {
&self.block_flow.box_
}
@@ -93,11 +93,9 @@ impl TableRowGroupFlow {
let height = cur_y - top_offset;
- for box_ in self.block_flow.box_.iter() {
- let mut position = box_.border_box.get();
- position.size.height = height;
- box_.border_box.set(position);
- }
+ let mut position = self.block_flow.box_.border_box.get();
+ position.size.height = height;
+ self.block_flow.box_.border_box.set(position);
self.block_flow.base.position.size.height = height;
}
@@ -219,10 +217,7 @@ impl Flow for TableRowGroupFlow {
fn debug_str(&self) -> ~str {
let txt = ~"TableRowGroupFlow: ";
- txt.append(match self.block_flow.box_ {
- Some(ref rb) => rb.debug_str(),
- None => ~"",
- })
+ txt.append(self.block_flow.box_.debug_str())
}
}
diff --git a/src/components/main/layout/table_wrapper.rs b/src/components/main/layout/table_wrapper.rs
index 639eb542902..c124e46b5a7 100644
--- a/src/components/main/layout/table_wrapper.rs
+++ b/src/components/main/layout/table_wrapper.rs
@@ -166,16 +166,12 @@ impl Flow for TableWrapperFlow {
// The position was set to the containing block by the flow's parent.
let containing_block_width = self.block_flow.base.position.size.width;
- let mut left_content_edge = Au::new(0);
- let mut content_width = containing_block_width;
let width_computer = TableWrapper;
width_computer.compute_used_width_table_wrapper(self, ctx, containing_block_width);
- for box_ in self.block_flow.box_.iter() {
- left_content_edge = box_.border_box.get().origin.x;
- content_width = box_.border_box.get().size.width;
- }
+ let left_content_edge = self.block_flow.box_.border_box.get().origin.x;
+ let content_width = self.block_flow.box_.border_box.get().size.width;
match self.table_layout {
FixedLayout | _ if self.is_float() =>
@@ -221,10 +217,7 @@ impl Flow for TableWrapperFlow {
} else {
~"TableWrapperFlow: "
};
- txt.append(match self.block_flow.box_ {
- Some(ref rb) => rb.debug_str(),
- None => ~"",
- })
+ txt.append(self.block_flow.box_.debug_str())
}
}
@@ -258,23 +251,21 @@ impl TableWrapper {
|sum, width| sum.add(width));
let mut computed_width = input.computed_width.specified_or_zero();
- for box_ in table_wrapper.block_flow.box_.iter() {
- let style = box_.style();
-
- // Get left and right paddings, borders for table.
- // We get these values from the box's style since table_wrapper doesn't have it's own border or padding.
- // input.available_width is same as containing_block_width in table_wrapper.
- let padding_left = specified(style.Padding.get().padding_left,
- input.available_width);
- let padding_right = specified(style.Padding.get().padding_right,
- input.available_width);
- let border_left = style.Border.get().border_left_width;
- let border_right = style.Border.get().border_right_width;
- let padding_and_borders = padding_left + padding_right + border_left + border_right;
- // Compare border-edge widths. Because fixed_cells_width indicates content-width,
- // padding and border values are added to fixed_cells_width.
- computed_width = geometry::max(fixed_cells_width + padding_and_borders, computed_width);
- }
+ let style = table_wrapper.block_flow.box_.style();
+
+ // Get left and right paddings, borders for table.
+ // We get these values from the box's style since table_wrapper doesn't have it's own border or padding.
+ // input.available_width is same as containing_block_width in table_wrapper.
+ let padding_left = specified(style.Padding.get().padding_left,
+ input.available_width);
+ let padding_right = specified(style.Padding.get().padding_right,
+ input.available_width);
+ let border_left = style.Border.get().border_left_width;
+ let border_right = style.Border.get().border_right_width;
+ let padding_and_borders = padding_left + padding_right + border_left + border_right;
+ // Compare border-edge widths. Because fixed_cells_width indicates content-width,
+ // padding and border values are added to fixed_cells_width.
+ computed_width = geometry::max(fixed_cells_width + padding_and_borders, computed_width);
computed_width
},
AutoLayout => {
diff --git a/src/components/main/platform/common/glut_windowing.rs b/src/components/main/platform/common/glut_windowing.rs
index 2d59539a8d1..23d6ab2d4f6 100644
--- a/src/components/main/platform/common/glut_windowing.rs
+++ b/src/components/main/platform/common/glut_windowing.rs
@@ -97,7 +97,7 @@ impl WindowMethods<Application> for Window {
impl glut::ReshapeCallback for ReshapeCallbackState {
fn call(&self, width: c_int, height: c_int) {
let tmp = local_window();
- tmp.borrow().event_queue.with_mut(|queue| queue.push(ResizeWindowEvent(width as uint, height as uint)))
+ tmp.event_queue.borrow_mut().push(ResizeWindowEvent(width as uint, height as uint))
}
}
glut::reshape_func(glut_window, ~ReshapeCallbackState);
@@ -105,7 +105,7 @@ impl WindowMethods<Application> for Window {
impl glut::KeyboardCallback for KeyboardCallbackState {
fn call(&self, key: c_uchar, _x: c_int, _y: c_int) {
let tmp = local_window();
- tmp.borrow().handle_key(key)
+ tmp.handle_key(key)
}
}
glut::keyboard_func(~KeyboardCallbackState);
@@ -114,16 +114,16 @@ impl WindowMethods<Application> for Window {
fn call(&self, button: c_int, state: c_int, x: c_int, y: c_int) {
if button < 3 {
let tmp = local_window();
- tmp.borrow().handle_mouse(button, state, x, y);
+ tmp.handle_mouse(button, state, x, y);
} else {
match button {
3 => {
let tmp = local_window();
- tmp.borrow().event_queue.with_mut(|queue| queue.push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32))));
+ tmp.event_queue.borrow_mut().push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32)));
},
4 => {
let tmp = local_window();
- tmp.borrow().event_queue.with_mut(|queue| queue.push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32))));
+ tmp.event_queue.borrow_mut().push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32)));
},
_ => {}
}
@@ -150,15 +150,13 @@ impl WindowMethods<Application> for Window {
}
fn recv(&self) -> WindowEvent {
- if !self.event_queue.with_mut(|queue| queue.is_empty()) {
- return self.event_queue.with_mut(|queue| queue.shift().unwrap())
+ if !self.event_queue.borrow_mut().is_empty() {
+ return self.event_queue.borrow_mut().shift().unwrap();
}
+
glut::check_loop();
- if !self.event_queue.with_mut(|queue| queue.is_empty()) {
- self.event_queue.with_mut(|queue| queue.shift().unwrap())
- } else {
- IdleWindowEvent
- }
+
+ self.event_queue.borrow_mut().shift().unwrap_or(IdleWindowEvent)
}
/// Sets the ready state.
@@ -174,7 +172,7 @@ impl WindowMethods<Application> for Window {
self.render_state.get() == RenderingRenderState &&
render_state == IdleRenderState {
// page loaded
- self.event_queue.with_mut(|queue| queue.push(FinishedWindowEvent));
+ self.event_queue.borrow_mut().push(FinishedWindowEvent);
}
self.render_state.set(render_state);
@@ -219,16 +217,16 @@ impl Window {
let modifiers = glut::get_modifiers();
match key {
42 => self.load_url(),
- 43 => self.event_queue.with_mut(|queue| queue.push(ZoomWindowEvent(1.1))),
- 45 => self.event_queue.with_mut(|queue| queue.push(ZoomWindowEvent(0.909090909))),
- 56 => self.event_queue.with_mut(|queue| queue.push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32)))),
- 50 => self.event_queue.with_mut(|queue| queue.push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32)))),
+ 43 => self.event_queue.borrow_mut().push(ZoomWindowEvent(1.1)),
+ 45 => self.event_queue.borrow_mut().push(ZoomWindowEvent(0.909090909)),
+ 56 => self.event_queue.borrow_mut().push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32))),
+ 50 => self.event_queue.borrow_mut().push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32))),
127 => {
if (modifiers & ACTIVE_SHIFT) != 0 {
- self.event_queue.with_mut(|queue| queue.push(NavigationWindowEvent(Forward)));
+ self.event_queue.borrow_mut().push(NavigationWindowEvent(Forward));
}
else {
- self.event_queue.with_mut(|queue| queue.push(NavigationWindowEvent(Back)));
+ self.event_queue.borrow_mut().push(NavigationWindowEvent(Back));
}
}
_ => {}
@@ -253,14 +251,14 @@ impl Window {
if pixel_dist < max_pixel_dist {
let click_event = MouseWindowClickEvent(button as uint,
Point2D(x as f32, y as f32));
- self.event_queue.with_mut(|queue| queue.push(MouseWindowEventClass(click_event)));
+ self.event_queue.borrow_mut().push(MouseWindowEventClass(click_event));
}
}
MouseWindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32))
}
_ => fail!("I cannot recognize the type of mouse action that occured. :-(")
};
- self.event_queue.with_mut(|queue| queue.push(MouseWindowEventClass(event)));
+ self.event_queue.borrow_mut().push(MouseWindowEventClass(event));
}
/// Helper function to pop up an alert box prompting the user to load a URL.
@@ -270,9 +268,9 @@ impl Window {
alert.run();
let value = alert.prompt_value();
if "" == value { // To avoid crashing on Linux.
- self.event_queue.with_mut(|queue| queue.push(LoadUrlWindowEvent(~"http://purple.com/")))
+ self.event_queue.borrow_mut().push(LoadUrlWindowEvent(~"http://purple.com/"))
} else {
- self.event_queue.with_mut(|queue| queue.push(LoadUrlWindowEvent(value.clone())))
+ self.event_queue.borrow_mut().push(LoadUrlWindowEvent(value.clone()))
}
}
}
diff --git a/src/components/main/servo.rs b/src/components/main/servo.rs
index 225922f01d6..72a28d93322 100755
--- a/src/components/main/servo.rs
+++ b/src/components/main/servo.rs
@@ -6,7 +6,7 @@
#[comment = "The Servo Parallel Browser Project"];
#[license = "MPL"];
-#[feature(globs, macro_rules, managed_boxes, phase, thread_local)];
+#[feature(globs, macro_rules, phase, thread_local)];
#[feature(phase)];
#[phase(syntax, link)]
@@ -67,7 +67,8 @@ use servo_util::opts;
#[cfg(not(test))]
use servo_util::url::parse_url;
-#[cfg(not(test))]
+
+#[cfg(not(test), not(target_os="android"))]
use std::os;
#[cfg(not(test), target_os="android")]
use std::str;
diff --git a/src/components/msg/compositor_msg.rs b/src/components/msg/compositor_msg.rs
index 8518bd3024a..33e0230d687 100644
--- a/src/components/msg/compositor_msg.rs
+++ b/src/components/msg/compositor_msg.rs
@@ -121,7 +121,6 @@ pub struct LayerMetadata {
/// submit them to be drawn to the display.
pub trait RenderListener {
fn get_graphics_metadata(&self) -> Option<NativeGraphicsMetadata>;
- fn create_layer_group_for_pipeline(&self, PipelineId, Size2D<uint>);
/// Informs the compositor of the layers for the given pipeline. The compositor responds by
/// creating and/or destroying render layers as necessary.
diff --git a/src/components/msg/msg.rs b/src/components/msg/msg.rs
index 659de719d32..c3e332746f3 100644
--- a/src/components/msg/msg.rs
+++ b/src/components/msg/msg.rs
@@ -4,8 +4,8 @@
#[crate_id = "github.com/mozilla/servo#msg:0.1"];
#[crate_type = "lib"];
-
-#[feature(managed_boxes)];
+#[crate_type = "dylib"];
+#[crate_type = "rlib"];
extern crate azure;
extern crate geom;
diff --git a/src/components/net/net.rs b/src/components/net/net.rs
index 7f4b340cf84..c0f1080e699 100644
--- a/src/components/net/net.rs
+++ b/src/components/net/net.rs
@@ -4,8 +4,10 @@
#[crate_id = "github.com/mozilla/servo#net:0.1"];
#[crate_type = "lib"];
+#[crate_type = "dylib"];
+#[crate_type = "rlib"];
-#[feature(globs, managed_boxes)];
+#[feature(globs)];
#[feature(phase)];
#[phase(syntax, link)]
diff --git a/src/components/script/dom/attr.rs b/src/components/script/dom/attr.rs
index 8357665b63d..40da74cfbd2 100644
--- a/src/components/script/dom/attr.rs
+++ b/src/components/script/dom/attr.rs
@@ -6,7 +6,7 @@ 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};
+use servo_util::namespace::Namespace;
use servo_util::str::DOMString;
#[deriving(Encodable)]
@@ -43,20 +43,9 @@ impl Attr {
}
}
- pub fn new(window: &JS<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: &JS<Window>, local_name: DOMString, value: DOMString,
- name: DOMString, namespace: Namespace,
- prefix: Option<DOMString>) -> JS<Attr> {
- Attr::new_helper(window, local_name, value, name, namespace, prefix)
- }
-
- fn new_helper(window: &JS<Window>, local_name: DOMString, value: DOMString,
- name: DOMString, namespace: Namespace,
- prefix: Option<DOMString>) -> JS<Attr> {
+ pub fn new(window: &JS<Window>, local_name: DOMString, value: DOMString,
+ name: DOMString, namespace: Namespace,
+ prefix: Option<DOMString>) -> JS<Attr> {
let attr = Attr::new_inherited(local_name, value, name, namespace, prefix);
reflect_dom_object(~attr, window, AttrBinding::Wrap)
}
diff --git a/src/components/script/dom/bindings/callback.rs b/src/components/script/dom/bindings/callback.rs
index dff5aeb6a2b..a6d7eb6a507 100644
--- a/src/components/script/dom/bindings/callback.rs
+++ b/src/components/script/dom/bindings/callback.rs
@@ -5,7 +5,7 @@
use dom::bindings::utils::Reflectable;
use js::jsapi::{JSContext, JSObject, JS_WrapObject, JS_ObjectIsCallable};
use js::jsapi::{JS_GetProperty, JSTracer, JS_CallTracer};
-use js::jsval::JSVal;
+use js::jsval::{JSVal, UndefinedValue};
use js::JSTRACE_OBJECT;
use std::cast;
@@ -61,20 +61,20 @@ impl CallbackInterface {
}
}
- pub fn GetCallableProperty(&self, cx: *JSContext, name: *libc::c_char, callable: &mut JSVal) -> bool {
+ pub fn GetCallableProperty(&self, cx: *JSContext, name: &str) -> Result<JSVal, ()> {
+ let mut callable = UndefinedValue();
unsafe {
- if JS_GetProperty(cx, self.callback, name, &*callable) == 0 {
- return false;
+ if name.to_c_str().with_ref(|name| JS_GetProperty(cx, self.callback, name, &mut callable as *mut JSVal as *JSVal)) == 0 {
+ return Err(());
}
if !callable.is_object() ||
JS_ObjectIsCallable(cx, callable.to_object()) == 0 {
//ThrowErrorMessage(cx, MSG_NOT_CALLABLE, description.get());
- return false;
+ return Err(());
}
-
- return true;
}
+ Ok(callable)
}
}
diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py
index d319ebe909e..506398570ce 100644
--- a/src/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/src/components/script/dom/bindings/codegen/CodegenRust.py
@@ -1038,120 +1038,18 @@ class CGArgumentConverter(CGThing):
self.replacementVariables,
self.argcAndIndex).define()
-def getWrapTemplateForType(type, descriptorProvider, result, successCode,
- isCreator, exceptionCode):
- """
- Reflect a C++ value stored in "result", of IDL type "type" into JS. The
- "successCode" is the code to run once we have successfully done the
- conversion. The resulting string should be used with string.Template, it
- needs the following keys when substituting: jsvalPtr/jsvalRef/obj.
- Returns (templateString, infallibility of conversion template)
+def wrapForType(jsvalRef, result='result', successCode='return 1;'):
"""
- haveSuccessCode = successCode is not None
- if not haveSuccessCode:
- successCode = "return 1;"
-
- # We often want exceptionCode to be indented, since it often appears in an
- # if body.
- exceptionCodeIndented = CGIndenter(CGGeneric(exceptionCode))
-
- def setValue(value, callWrapValue=False):
- """
- Returns the code to set the jsval to value. If "callWrapValue" is true
- JS_WrapValue will be called on the jsval.
- """
- if not callWrapValue:
- tail = successCode
- elif haveSuccessCode:
- tail = ("if JS_WrapValue(cx, ${jsvalPtr}) == 0 {\n" +
- " return 0;\n" +
- "}\n" +
- successCode)
- else:
- tail = "return JS_WrapValue(cx, ${jsvalPtr} as *JSVal);"
- return ("${jsvalRef} = %s;\n" +
- tail) % (value)
-
- if type is None or type.isVoid():
- return (setValue("UndefinedValue()"), True)
+ Reflect a Rust value into JS.
- if type.isArray():
- raise TypeError("Can't handle array return values yet")
-
- if type.isSequence():
- raise TypeError("Can't handle sequence return values yet")
-
- if type.isGeckoInterface():
- return (setValue("(%s).to_jsval(cx)" % result), True)
-
- if type.isString():
- return (setValue("(%s).to_jsval(cx)" % result), True)
-
- if type.isEnum():
- return (setValue("(%s).to_jsval(cx)" % result), True)
-
- if type.isCallback():
- assert not type.isInterface()
- # XXXbz we're going to assume that callback types are always
- # nullable and always have [TreatNonCallableAsNull] for now.
- # See comments in WrapNewBindingObject explaining why we need
- # to wrap here.
- # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
- return (setValue("JS::ObjectOrNullValue(%s)" % result, True), False)
-
- if type.tag() == IDLType.Tags.any:
- # See comments in WrapNewBindingObject explaining why we need
- # to wrap here.
- # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
- return (setValue(result, True), False)
-
- if type.isObject() or type.isSpiderMonkeyInterface():
- # See comments in WrapNewBindingObject explaining why we need
- # to wrap here.
- if type.nullable():
- toValue = "ObjectOrNullValue(%s)"
- else:
- toValue = "ObjectValue(&*(%s))"
- # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
- return (setValue(toValue % result, True), False)
-
- if not type.isPrimitive():
- raise TypeError("Need to learn to wrap %s" % type)
-
- return (setValue("(%s).to_jsval(cx)" % result), True)
-
-
-def wrapForType(type, descriptorProvider, templateValues):
+ * 'jsvalRef': a Rust reference to the JSVal in which to store the result
+ of the conversion;
+ * 'result': the name of the variable in which the Rust value is stored;
+ * 'successCode': the code to run once we have done the conversion.
"""
- Reflect a C++ value of IDL type "type" into JS. TemplateValues is a dict
- that should contain:
-
- * 'jsvalRef': a C++ reference to the jsval in which to store the result of
- the conversion
- * 'jsvalPtr': a C++ pointer to the jsval in which to store the result of
- the conversion
- * 'obj' (optional): the name of the variable that contains the JSObject to
- use as a scope when wrapping, if not supplied 'obj'
- will be used as the name
- * 'result' (optional): the name of the variable in which the C++ value is
- stored, if not supplied 'result' will be used as
- the name
- * 'successCode' (optional): the code to run once we have successfully done
- the conversion, if not supplied 'return true;'
- will be used as the code
- * 'isCreator' (optional): If true, we're wrapping for the return value of
- a [Creator] method. Assumed false if not set.
- """
- wrap = getWrapTemplateForType(type, descriptorProvider,
- templateValues.get('result', 'result'),
- templateValues.get('successCode', None),
- templateValues.get('isCreator', False),
- templateValues.get('exceptionCode',
- "return 0;"),)[0]
+ return "%s = (%s).to_jsval(cx);\n%s" % (jsvalRef, result, successCode)
- defaultValues = {'obj': 'obj'}
- return string.Template(wrap).substitute(defaultValues, **templateValues)
def typeNeedsCx(type, retVal=False):
if type is None:
@@ -1361,13 +1259,13 @@ class MethodDefiner(PropertyDefiner):
if any(m.isGetter() and m.isIndexed() for m in methods):
self.chrome.append({"name": 'iterator',
"methodInfo": False,
- "nativeName": "crust::JS_ArrayIterator",
+ "nativeName": "JS_ArrayIterator",
"length": 0,
"flags": "JSPROP_ENUMERATE",
"pref": None })
self.regular.append({"name": 'iterator',
"methodInfo": False,
- "nativeName": "crust::JS_ArrayIterator",
+ "nativeName": "JS_ArrayIterator",
"length": 0,
"flags": "JSPROP_ENUMERATE",
"pref": None })
@@ -1630,19 +1528,19 @@ static Class_name: [u8, ..%i] = %s;
static Class: DOMJSClass = DOMJSClass {
base: JSClass { name: &Class_name as *u8 as *libc::c_char,
flags: JSCLASS_IS_DOMJSCLASS | %s | (((%s) & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT), //JSCLASS_HAS_RESERVED_SLOTS(%s),
- addProperty: Some(%s), /* addProperty */
- delProperty: Some(crust::JS_PropertyStub), /* delProperty */
- getProperty: Some(crust::JS_PropertyStub), /* getProperty */
- setProperty: Some(crust::JS_StrictPropertyStub), /* setProperty */
- enumerate: Some(crust::JS_EnumerateStub),
- resolve: Some(crust::JS_ResolveStub),
- convert: Some(crust::JS_ConvertStub),
- finalize: Some(%s), /* finalize */
- checkAccess: None, /* checkAccess */
- call: None, /* call */
- hasInstance: None, /* hasInstance */
- construct: None, /* construct */
- trace: %s, /* trace */
+ addProperty: Some(JS_PropertyStub),
+ delProperty: Some(JS_PropertyStub),
+ getProperty: Some(JS_PropertyStub),
+ setProperty: Some(JS_StrictPropertyStub),
+ enumerate: Some(JS_EnumerateStub),
+ resolve: Some(JS_ResolveStub),
+ convert: Some(JS_ConvertStub),
+ finalize: Some(%s),
+ checkAccess: None,
+ call: None,
+ hasInstance: None,
+ construct: None,
+ trace: %s,
reserved: (0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 05
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 10
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 15
@@ -1657,7 +1555,6 @@ static Class: DOMJSClass = DOMJSClass {
""" % (len(self.descriptor.interface.identifier.name) + 1,
str_to_const_array(self.descriptor.interface.identifier.name),
flags, slots, slots,
- 'crust::JS_PropertyStub',
FINALIZE_HOOK_NAME, traceHook,
CGIndenter(CGGeneric(DOMClass(self.descriptor))).define())
@@ -1675,19 +1572,19 @@ static PrototypeClassName__: [u8, ..%s] = %s;
static PrototypeClass: JSClass = JSClass {
name: &PrototypeClassName__ as *u8 as *libc::c_char,
flags: (1 & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT, //JSCLASS_HAS_RESERVED_SLOTS(1)
- addProperty: Some(crust::JS_PropertyStub), /* addProperty */
- delProperty: Some(crust::JS_PropertyStub), /* delProperty */
- getProperty: Some(crust::JS_PropertyStub), /* getProperty */
- setProperty: Some(crust::JS_StrictPropertyStub), /* setProperty */
- enumerate: Some(crust::JS_EnumerateStub),
- resolve: Some(crust::JS_ResolveStub),
- convert: Some(crust::JS_ConvertStub),
- finalize: None, /* finalize */
- checkAccess: None, /* checkAccess */
- call: None, /* call */
- hasInstance: None, /* hasInstance */
- construct: None, /* construct */
- trace: None, /* trace */
+ addProperty: Some(JS_PropertyStub),
+ delProperty: Some(JS_PropertyStub),
+ getProperty: Some(JS_PropertyStub),
+ setProperty: Some(JS_StrictPropertyStub),
+ enumerate: Some(JS_EnumerateStub),
+ resolve: Some(JS_ResolveStub),
+ convert: Some(JS_ConvertStub),
+ finalize: None,
+ checkAccess: None,
+ call: None,
+ hasInstance: None,
+ construct: None,
+ trace: None,
reserved: (0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 05
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 10
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 15
@@ -1713,19 +1610,19 @@ class CGInterfaceObjectJSClass(CGThing):
return """
static InterfaceObjectClass: JSClass = {
%s, 0,
- crust::JS_PropertyStub, /* addProperty */
- crust::JS_PropertyStub, /* delProperty */
- crust::JS_PropertyStub, /* getProperty */
- crust::JS_StrictPropertyStub, /* setProperty */
- crust::JS_EnumerateStub,
- crust::JS_ResolveStub,
- crust::JS_ConvertStub,
- 0 as *u8, /* finalize */
- 0 as *u8, /* checkAccess */
- %s, /* call */
- %s, /* hasInstance */
- %s, /* construct */
- 0 as *u8, /* trace */
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_StrictPropertyStub,
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ 0 as *u8,
+ 0 as *u8,
+ %s,
+ %s,
+ %s,
+ 0 as *u8,
JSCLASS_NO_INTERNAL_MEMBERS
};
""" % (str_to_const_array("Function"), ctorname, hasinstance, ctorname)
@@ -1960,12 +1857,6 @@ 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 mut raw: JS<%s> = JS::from_raw(&mut *aObject);\n" % descriptor.concreteType
if descriptor.proxy:
@@ -1998,10 +1889,10 @@ class CGWrapMethod(CGAbstractMethod):
assert descriptor.interface.hasInterfacePrototypeObject()
if not descriptor.createGlobal:
args = [Argument('*JSContext', 'aCx'), Argument('&JS<Window>', 'aScope'),
- Argument(DOMObjectPointerArg(descriptor), 'aObject', mutable=True)]
+ Argument("~" + descriptor.concreteType, 'aObject', mutable=True)]
else:
args = [Argument('*JSContext', 'aCx'),
- Argument(DOMObjectPointerArg(descriptor), 'aObject', mutable=True)]
+ Argument("~" + descriptor.concreteType, 'aObject', mutable=True)]
retval = 'JS<%s>' % descriptor.concreteType
CGAbstractMethod.__init__(self, descriptor, 'Wrap', retval, args, pub=True)
@@ -2232,7 +2123,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
"""
def __init__(self, descriptor):
args = [Argument('&mut JSPageInfo', 'js_info')]
- CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'bool', args, pub=True)
+ CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'void', args, pub=True)
def define(self):
return CGAbstractMethod.define(self)
@@ -2289,7 +2180,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
return (body + """ let cx = js_info.js_context.deref().ptr;
let receiver = js_info.js_compartment.global_obj;
let global: *JSObject = JS_GetGlobalForObject(cx, receiver);
- return %s(cx, global, receiver).is_not_null();""" % (getter))
+ assert!(%s(cx, global, receiver).is_not_null());""" % (getter))
def needCx(returnType, arguments, extendedAttributes, considerTypes):
return (considerTypes and
@@ -2445,18 +2336,7 @@ class CGPerSignatureCall(CGThing):
return not 'infallible' in self.extendedAttributes
def wrap_return_value(self):
- isCreator = memberIsCreator(self.idlNode)
- resultTemplateValues = { 'jsvalRef': '*vp', 'jsvalPtr': 'vp',
- 'isCreator': isCreator}
- try:
- return wrapForType(self.returnType, self.descriptor,
- resultTemplateValues)
- except MethodNotCreatorError, err:
- assert not isCreator
- raise TypeError("%s being returned from non-creator method or property %s.%s" %
- (err.typename,
- self.descriptor.interface.identifier.name,
- self.idlNode.identifier.name))
+ return wrapForType('*vp')
def getErrorReport(self):
return CGGeneric(
@@ -2617,7 +2497,7 @@ class CGSpecializedMethod(CGAbstractExternMethod):
def __init__(self, descriptor, method):
self.method = method
name = method.identifier.name
- args = [Argument('*JSContext', 'cx'), Argument('JSHandleObject', 'obj'),
+ args = [Argument('*JSContext', 'cx'), Argument('JSHandleObject', '_obj'),
Argument('*mut %s' % descriptor.concreteType, 'this'),
Argument('libc::c_uint', 'argc'), Argument('*mut JSVal', 'vp')]
CGAbstractExternMethod.__init__(self, descriptor, name, 'JSBool', args)
@@ -2634,7 +2514,6 @@ class CGSpecializedMethod(CGAbstractExternMethod):
return CGWrapper(CGMethodCall(argsPre, nativeName, self.method.isStatic(),
self.descriptor, self.method),
pre=extraPre +
- " let obj = *obj.unnamed;\n" +
" let this = &mut *this;\n").define()
class CGGenericGetter(CGAbstractBindingMethod):
@@ -2672,7 +2551,7 @@ class CGSpecializedGetter(CGAbstractExternMethod):
self.attr = attr
name = 'get_' + attr.identifier.name
args = [ Argument('*JSContext', 'cx'),
- Argument('JSHandleObject', 'obj'),
+ Argument('JSHandleObject', '_obj'),
Argument('*mut %s' % descriptor.concreteType, 'this'),
Argument('*mut JSVal', 'vp') ]
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
@@ -2694,7 +2573,6 @@ class CGSpecializedGetter(CGAbstractExternMethod):
return CGWrapper(CGIndenter(CGGetterCall(argsPre, self.attr.type, nativeName,
self.descriptor, self.attr)),
pre=extraPre +
- " let obj = *obj.unnamed;\n" +
" let this = &mut *this;\n").define()
class CGGenericSetter(CGAbstractBindingMethod):
@@ -2738,7 +2616,7 @@ class CGSpecializedSetter(CGAbstractExternMethod):
self.attr = attr
name = 'set_' + attr.identifier.name
args = [ Argument('*JSContext', 'cx'),
- Argument('JSHandleObject', 'obj'),
+ Argument('JSHandleObject', '_obj'),
Argument('*mut %s' % descriptor.concreteType, 'this'),
Argument('*mut JSVal', 'argv')]
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
@@ -2755,22 +2633,8 @@ class CGSpecializedSetter(CGAbstractExternMethod):
return CGWrapper(CGIndenter(CGSetterCall(argsPre, self.attr.type, nativeName,
self.descriptor, self.attr)),
pre=extraPre +
- " let obj = *obj.unnamed;\n" +
" let this = &mut *this;\n").define()
-def infallibleForMember(member, type, descriptorProvider):
- """
- Determine the fallibility of changing a C++ value of IDL type "type" into
- JS for the given attribute. Apart from isCreator, all the defaults are used,
- since the fallbility does not change based on the boolean values,
- and the template will be discarded.
-
- CURRENT ASSUMPTIONS:
- We assume that successCode for wrapping up return values cannot contain
- failure conditions.
- """
- return getWrapTemplateForType(type, descriptorProvider, 'result', None,\
- memberIsCreator(member), "return false;",)[1]
class CGMemberJITInfo(CGThing):
"""
@@ -2799,7 +2663,6 @@ class CGMemberJITInfo(CGThing):
getterinfo = ("%s_getterinfo" % self.member.identifier.name)
getter = ("get_%s" % self.member.identifier.name)
getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
- getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
result = self.defineJitInfo(getterinfo, getter, getterinfal)
if not self.member.readonly:
setterinfo = ("%s_setterinfo" % self.member.identifier.name)
@@ -2821,7 +2684,7 @@ class CGMemberJITInfo(CGThing):
# Don't handle overloading. If there's more than one signature,
# one of them must take arguments.
sig = sigs[0]
- if len(sig[1]) == 0 and infallibleForMember(self.member, sig[0], self.descriptor):
+ if len(sig[1]) == 0:
# No arguments and infallible return boxing
methodInfal = True
@@ -3693,7 +3556,7 @@ class CGProxySpecialOperation(CGPerSignatureCall):
if not self.idlNode.isGetter() or self.templateValues is None:
return ""
- wrap = CGGeneric(wrapForType(self.returnType, self.descriptor, self.templateValues))
+ wrap = CGGeneric(wrapForType(**self.templateValues))
wrap = CGIfWrapper(wrap, "found")
return "\n" + wrap.define()
@@ -3761,8 +3624,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
if indexedGetter:
readonly = toStringBool(self.descriptor.operations['IndexedSetter'] is None)
fillDescriptor = "FillPropertyDescriptor(&mut *desc, proxy, %s);\nreturn 1;" % readonly
- templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': '&mut (*desc).value',
- 'obj': 'proxy', 'successCode': fillDescriptor}
+ templateValues = {'jsvalRef': '(*desc).value', 'successCode': fillDescriptor}
get = ("if index.is_some() {\n" +
" let index = index.unwrap();\n" +
" let this: *%s = UnwrapProxy(proxy);\n" +
@@ -3803,8 +3665,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
if namedGetter:
readonly = toStringBool(self.descriptor.operations['NamedSetter'] is None)
fillDescriptor = "FillPropertyDescriptor(&mut *desc, proxy, %s);\nreturn 1;" % readonly
- templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': '&mut(*desc).value',
- 'obj': 'proxy', 'successCode': fillDescriptor}
+ templateValues = {'jsvalRef': '(*desc).value', 'successCode': fillDescriptor}
# Once we start supporting OverrideBuiltins we need to make
# ResolveOwnProperty or EnumerateOwnProperties filter out named
# properties that shadow prototype properties.
@@ -3958,7 +3819,7 @@ if expando.is_not_null() {
}
}"""
- templateValues = {'jsvalRef': '*vp', 'jsvalPtr': 'vp', 'obj': 'proxy'}
+ templateValues = {'jsvalRef': '*vp'}
indexedGetter = self.descriptor.operations['IndexedGetter']
if indexedGetter:
@@ -4061,9 +3922,9 @@ class CGAbstractClassHook(CGAbstractExternMethod):
def finalizeHook(descriptor, hookName, context):
release = """let val = JS_GetReservedSlot(obj, dom_object_slot(obj));
-let _: %s %s = cast::transmute(val.to_private());
+let _: ~%s = cast::transmute(val.to_private());
debug!("%s finalize: {:p}", this);
-""" % (DOMObjectPointerType(descriptor), descriptor.concreteType, descriptor.concreteType)
+""" % (descriptor.concreteType, descriptor.concreteType)
return release
class CGClassTraceHook(CGAbstractClassHook):
@@ -4514,7 +4375,7 @@ class CGRegisterProtos(CGAbstractMethod):
self.config = config
def _registerProtos(self):
- lines = [" assert!(codegen::%sBinding::DefineDOMInterface(js_info));" % (desc.name)
+ lines = [" codegen::%sBinding::DefineDOMInterface(js_info);" % desc.name
for desc in self.config.getDescriptors(hasInterfaceObject=True,
register=True)]
return '\n'.join(lines) + '\n'
@@ -4587,7 +4448,7 @@ class CGBindingRoot(CGThing):
#XXXjdm This should only import the namespace for the current binding,
# not every binding ever.
curr = CGImports(curr, [
- 'js::{crust, JS_ARGV, JS_CALLEE, JS_THIS_OBJECT}',
+ 'js::{JS_ARGV, JS_CALLEE, JS_THIS_OBJECT}',
'js::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IS_DOMJSCLASS}',
'js::{JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_SHIFT}',
'js::{JSCLASS_RESERVED_SLOTS_MASK, JSID_VOID, JSJitInfo}',
@@ -4600,9 +4461,10 @@ class CGBindingRoot(CGThing):
'js::jsapi::{JS_NewObject, JS_ObjectIsCallable, JS_SetPrototype}',
'js::jsapi::{JS_SetReservedSlot, JS_WrapValue, JSBool, JSContext}',
'js::jsapi::{JSClass, JSFreeOp, JSFunctionSpec, JSHandleObject, jsid}',
- 'js::jsapi::{JSNativeWrapper, JSObject, JSPropertyDescriptor}',
- 'js::jsapi::{JSPropertyOpWrapper, JSPropertySpec}',
- 'js::jsapi::{JSStrictPropertyOpWrapper, JSString, JSTracer}',
+ 'js::jsapi::{JSNativeWrapper, JSObject, JSPropertyDescriptor, JS_ArrayIterator}',
+ 'js::jsapi::{JSPropertyOpWrapper, JSPropertySpec, JS_PropertyStub}',
+ 'js::jsapi::{JSStrictPropertyOpWrapper, JSString, JSTracer, JS_ConvertStub}',
+ 'js::jsapi::{JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub}',
'js::jsval::JSVal',
'js::jsval::{ObjectValue, ObjectOrNullValue, PrivateValue}',
'js::jsval::{NullValue, UndefinedValue}',
@@ -5293,21 +5155,9 @@ class CallbackMember(CGNativeMember):
result = argval
prepend = ""
- conversion = prepend + wrapForType(
- arg.type, self.descriptorProvider,
- {
- 'result' : result,
- 'successCode' : "continue;" if arg.variadic else "break;",
- 'jsvalRef' : "argv[%s]" % jsvalIndex,
- 'jsvalHandle' : "argv.handleAt(%s)" % jsvalIndex,
- 'jsvalPtr': "&mut argv[%s]" % jsvalIndex,
- # XXXbz we don't have anything better to use for 'obj',
- # really... It's OK to use CallbackPreserveColor because
- # CallSetup already handled the unmark-gray bits for us.
- 'obj' : 'ptr::null() /*XXXjdm proper scope*/', #XXXjdm 'CallbackPreserveColor()',
- 'returnsNewObject': False,
- 'exceptionCode' : self.exceptionCode
- })
+ conversion = prepend + wrapForType("argv[%s]" % jsvalIndex,
+ result=result,
+ successCode="continue;" if arg.variadic else "break;")
if arg.variadic:
conversion = string.Template(
"for (uint32_t idx = 0; idx < ${arg}.Length(); ++idx) {\n" +
@@ -5453,19 +5303,19 @@ class CallbackOperationBase(CallbackMethod):
"methodName": self.methodName
}
getCallableFromProp = string.Template(
- 'if "${methodName}".to_c_str().with_ref(|name| !self.parent.GetCallableProperty(cx, name, &mut callable)) {\n'
- ' return${errorReturn};\n'
- '}\n').substitute(replacements)
+ 'match self.parent.GetCallableProperty(cx, "${methodName}") {\n'
+ ' Err(_) => return${errorReturn},\n'
+ ' Ok(callable) => callable,\n'
+ '}').substitute(replacements)
if not self.singleOperation:
return 'JS::Rooted<JS::Value> callable(cx);\n' + getCallableFromProp
return (
'let isCallable = unsafe { JS_ObjectIsCallable(cx, self.parent.callback) != 0 };\n'
- 'let mut callable = UndefinedValue();\n'
- 'if isCallable {\n'
- ' callable = unsafe { ObjectValue(&*self.parent.callback) };\n'
- '} else {\n'
- '%s'
- '}\n' % CGIndenter(CGGeneric(getCallableFromProp)).define())
+ 'let callable =\n' +
+ CGIndenter(
+ CGIfElseWrapper('isCallable',
+ CGGeneric('unsafe { ObjectValue(&*self.parent.callback) }'),
+ CGGeneric(getCallableFromProp))).define() + ';\n')
class CallbackOperation(CallbackOperationBase):
"""
@@ -5712,7 +5562,7 @@ class GlobalGenRoots():
'dom::bindings::error::throw_not_in_union',
'dom::bindings::js::JS',
'dom::types::*',
- 'js::{crust, JS_ARGV, JS_CALLEE, JS_THIS_OBJECT}',
+ 'js::{JS_ARGV, JS_CALLEE, JS_THIS_OBJECT}',
'js::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IS_DOMJSCLASS}',
'js::{JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_SHIFT}',
'js::{JSCLASS_RESERVED_SLOTS_MASK, JSID_VOID, JSJitInfo}',
diff --git a/src/components/script/dom/bindings/conversions.rs b/src/components/script/dom/bindings/conversions.rs
index 513dac9964a..1826782ac84 100644
--- a/src/components/script/dom/bindings/conversions.rs
+++ b/src/components/script/dom/bindings/conversions.rs
@@ -14,8 +14,8 @@ use js::jsapi::{JS_ValueToUint16, JS_ValueToNumber, JS_ValueToBoolean};
use js::jsapi::{JS_NewUCStringCopyN, JS_ValueToString};
use js::jsapi::{JS_WrapValue};
use js::jsval::JSVal;
-use js::jsval::{NullValue, BooleanValue, Int32Value, UInt32Value, StringValue};
-use js::jsval::ObjectValue;
+use js::jsval::{UndefinedValue, NullValue, BooleanValue, Int32Value, UInt32Value};
+use js::jsval::{StringValue, ObjectValue};
use js::glue::RUST_JS_NumberValue;
use std::default::Default;
use std::libc;
@@ -29,6 +29,22 @@ pub trait FromJSValConvertible<T> {
}
+impl ToJSValConvertible for () {
+ fn to_jsval(&self, _cx: *JSContext) -> JSVal {
+ UndefinedValue()
+ }
+}
+
+impl ToJSValConvertible for JSVal {
+ fn to_jsval(&self, cx: *JSContext) -> JSVal {
+ let mut value = *self;
+ if unsafe { JS_WrapValue(cx, &mut value as *mut JSVal as *JSVal) } == 0 {
+ fail!("JS_WrapValue failed.");
+ }
+ value
+ }
+}
+
unsafe fn convert_from_jsval<T: Default>(
cx: *JSContext, value: JSVal,
convert_fn: extern "C" unsafe fn(*JSContext, JSVal, *T) -> JSBool) -> Result<T, ()> {
diff --git a/src/components/script/dom/bindings/proxyhandler.rs b/src/components/script/dom/bindings/proxyhandler.rs
index 80320ec4cfb..22df6e0df86 100644
--- a/src/components/script/dom/bindings/proxyhandler.rs
+++ b/src/components/script/dom/bindings/proxyhandler.rs
@@ -6,11 +6,11 @@ use dom::bindings::utils::is_dom_proxy;
use js::jsapi::{JSContext, jsid, JSPropertyDescriptor, JSObject, JSString, jschar};
use js::jsapi::{JS_GetPropertyDescriptorById, JS_NewUCString, JS_malloc, JS_free};
use js::jsapi::{JSBool, JS_DefinePropertyById, JS_NewObjectWithGivenProto};
+use js::jsapi::JS_StrictPropertyStub;
use js::jsval::ObjectValue;
use js::glue::GetProxyExtra;
use js::glue::{GetObjectProto, GetObjectParent, SetProxyExtra, GetProxyHandler};
use js::glue::InvokeGetOwnPropertyDescriptor;
-use js::crust::{JS_StrictPropertyStub};
use js::{JSPROP_GETTER, JSPROP_ENUMERATE, JSPROP_READONLY, JSRESOLVE_QUALIFIED};
use std::cast;
@@ -46,7 +46,10 @@ pub extern fn getPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
pub fn defineProperty_(cx: *JSContext, proxy: *JSObject, id: jsid,
desc: *JSPropertyDescriptor) -> JSBool {
unsafe {
- if ((*desc).attrs & JSPROP_GETTER) != 0 && (*desc).setter == Some(JS_StrictPropertyStub) {
+ //FIXME: Workaround for https://github.com/mozilla/rust/issues/13385
+ let setter: *libc::c_void = cast::transmute((*desc).setter);
+ let setter_stub: *libc::c_void = cast::transmute(JS_StrictPropertyStub);
+ if ((*desc).attrs & JSPROP_GETTER) != 0 && setter == setter_stub {
/*return JS_ReportErrorFlagsAndNumber(cx,
JSREPORT_WARNING | JSREPORT_STRICT |
JSREPORT_STRICT_MODE_ERROR,
diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs
index 6d8c7fe9313..f4391e4e541 100644
--- a/src/components/script/dom/document.rs
+++ b/src/components/script/dom/document.rs
@@ -59,7 +59,7 @@ pub struct Document {
node: Node,
reflector_: Reflector,
window: JS<Window>,
- idmap: HashMap<DOMString, JS<Element>>,
+ idmap: HashMap<DOMString, ~[JS<Element>]>,
implementation: Option<JS<DOMImplementation>>,
content_type: DOMString,
encoding_name: DOMString,
@@ -249,7 +249,7 @@ impl Document {
// http://dom.spec.whatwg.org/#dom-document-getelementbyid.
match self.idmap.find_equiv(&id) {
None => None,
- Some(node) => Some(node.clone()),
+ Some(ref elements) => Some(elements[0].clone()),
}
}
@@ -647,8 +647,22 @@ impl Document {
/// Remove any existing association between the provided id and any elements in this document.
pub fn unregister_named_element(&mut self,
+ abstract_self: &JS<Element>,
id: DOMString) {
- self.idmap.remove(&id);
+ let mut is_empty = false;
+ match self.idmap.find_mut(&id) {
+ None => {},
+ Some(elements) => {
+ let position = elements.iter()
+ .position(|element| element == abstract_self)
+ .expect("This element should be in registered.");
+ elements.remove(position);
+ is_empty = elements.is_empty();
+ }
+ }
+ if is_empty {
+ self.idmap.remove(&id);
+ }
}
/// Associate an element present in this document with the provided id.
@@ -660,17 +674,32 @@ impl Document {
node.is_in_doc()
});
- // TODO: support the case if multiple elements
- // which haves same id are in the same document.
// FIXME https://github.com/mozilla/rust/issues/13195
// Use mangle() when it exists again.
+ let root = self.GetDocumentElement().expect("The element is in the document, so there must be a document element.");
match self.idmap.find_mut(&id) {
- Some(v) => {
- *v = element.clone();
+ Some(elements) => {
+ let new_node = NodeCast::from(element);
+ let mut head : uint = 0u;
+ let root: JS<Node> = NodeCast::from(&root);
+ for node in root.traverse_preorder() {
+ match ElementCast::to(&node) {
+ Some(elem) => {
+ if elements[head] == elem {
+ head = head + 1;
+ }
+ if new_node == node || head == elements.len() {
+ break;
+ }
+ }
+ None => {}
+ }
+ }
+ elements.insert(head, element.clone());
return;
},
None => (),
}
- self.idmap.insert(id, element.clone());
+ self.idmap.insert(id, ~[element.clone()]);
}
}
diff --git a/src/components/script/dom/domexception.rs b/src/components/script/dom/domexception.rs
index fe439a944e2..1c44a88af1f 100644
--- a/src/components/script/dom/domexception.rs
+++ b/src/components/script/dom/domexception.rs
@@ -11,7 +11,7 @@ use servo_util::str::DOMString;
#[repr(uint)]
#[deriving(Show, Encodable)]
-enum DOMErrorName {
+pub enum DOMErrorName {
IndexSizeError = DOMExceptionConstants::INDEX_SIZE_ERR,
HierarchyRequestError = DOMExceptionConstants::HIERARCHY_REQUEST_ERR,
WrongDocumentError = DOMExceptionConstants::WRONG_DOCUMENT_ERR,
diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs
index 8299f516119..3abe8de8edb 100644
--- a/src/components/script/dom/element.rs
+++ b/src/components/script/dom/element.rs
@@ -7,26 +7,22 @@
use dom::attr::Attr;
use dom::attrlist::AttrList;
use dom::bindings::codegen::ElementBinding;
-use dom::bindings::codegen::InheritTypes::{ElementDerived, HTMLImageElementCast};
-use dom::bindings::codegen::InheritTypes::{HTMLIFrameElementCast, NodeCast};
-use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast;
+use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast};
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::bindings::error::{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::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, document_from_node};
+use dom::htmlcollection::HTMLCollection;
use dom::htmlserializer::serialize;
+use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node};
+use dom::virtualmethods::{VirtualMethods, vtable_for};
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage};
-use layout_interface::{MatchSelectorsDocumentDamage};
+use layout_interface::MatchSelectorsDocumentDamage;
use style;
use servo_util::namespace;
use servo_util::namespace::{Namespace, Null};
@@ -195,9 +191,14 @@ pub trait AttributeHandlers {
fn set_attr(&mut self, name: DOMString, value: DOMString) -> ErrorResult;
fn set_attribute(&mut self, namespace: Namespace, name: DOMString,
value: DOMString) -> ErrorResult;
- fn after_set_attr(&mut self, local_name: DOMString, value: DOMString);
+ fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString,
+ name: DOMString, namespace: Namespace,
+ prefix: Option<DOMString>, cb: |&JS<Attr>| -> bool);
+ fn SetAttribute(&mut self, name: DOMString, value: DOMString) -> ErrorResult;
+ fn SetAttributeNS(&mut self, namespace_url: Option<DOMString>,
+ name: DOMString, value: DOMString) -> ErrorResult;
+
fn remove_attribute(&mut self, namespace: Namespace, name: DOMString) -> ErrorResult;
- fn before_remove_attr(&mut self, local_name: DOMString, old_value: DOMString);
fn notify_attribute_changed(&self, local_name: DOMString);
fn has_class(&self, name: &str) -> bool;
@@ -209,14 +210,6 @@ pub trait AttributeHandlers {
fn set_uint_attribute(&mut self, name: &str, value: u32);
}
-pub trait AfterSetAttrListener {
- fn AfterSetAttr(&mut self, name: DOMString, value: DOMString);
-}
-
-pub trait BeforeRemoveAttrListener {
- fn BeforeRemoveAttr(&mut self, name: DOMString);
-}
-
impl AttributeHandlers for JS<Element> {
fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<JS<Attr>> {
if self.get().html_element_in_html_document() {
@@ -253,76 +246,123 @@ impl AttributeHandlers for JS<Element> {
let node: JS<Node> = NodeCast::from(self);
node.get().wait_until_safe_to_modify_dom();
- // FIXME: reduce the time of `value.clone()`.
- let idx = self.get().attrs.iter().position(|attr| {
+ let position: |&JS<Attr>| -> bool =
if self.get().html_element_in_html_document() {
- attr.get().local_name.eq_ignore_ascii_case(local_name)
+ |attr| attr.get().local_name.eq_ignore_ascii_case(local_name)
} else {
- attr.get().local_name == local_name
- }
- });
+ |attr| attr.get().local_name == local_name
+ };
+ self.do_set_attribute(name.clone(), value, name.clone(), namespace::Null, None, position);
+ Ok(())
+ }
+ fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString,
+ name: DOMString, namespace: Namespace,
+ prefix: Option<DOMString>, cb: |&JS<Attr>| -> bool) {
+ let node: JS<Node> = NodeCast::from(self);
+ let idx = self.get().attrs.iter().position(cb);
match idx {
Some(idx) => {
if namespace == namespace::Null {
let old_value = self.get().attrs[idx].get().Value();
- self.before_remove_attr(local_name.clone(), old_value);
+ vtable_for(&node).before_remove_attr(local_name.clone(), old_value);
}
self.get_mut().attrs[idx].get_mut().set_value(value.clone());
}
+
None => {
- let node: JS<Node> = NodeCast::from(self);
let doc = node.get().owner_doc().get();
- let new_attr = Attr::new_ns(&doc.window, local_name.clone(), value.clone(),
- name.clone(), namespace.clone(),
- prefix);
+ let new_attr = Attr::new(&doc.window, local_name.clone(), value.clone(),
+ name, namespace.clone(), prefix);
self.get_mut().attrs.push(new_attr);
}
}
if namespace == namespace::Null {
- self.after_set_attr(local_name, value);
+ vtable_for(&node).after_set_attr(local_name, value);
+ }
+ }
+
+ // http://dom.spec.whatwg.org/#dom-element-setattribute
+ fn SetAttribute(&mut self, name: DOMString, value: DOMString) -> ErrorResult {
+ let node: JS<Node> = NodeCast::from(self);
+ node.get().wait_until_safe_to_modify_dom();
+
+ // Step 1.
+ match xml_name_type(name) {
+ InvalidXMLName => return Err(InvalidCharacter),
+ _ => {}
}
+
+ // Step 2.
+ let name = if self.get().html_element_in_html_document() {
+ name.to_ascii_lower()
+ } else {
+ name
+ };
+
+ // Step 3-5.
+ self.do_set_attribute(name.clone(), value, name.clone(), namespace::Null, None, |attr| {
+ attr.get().name == name
+ });
Ok(())
}
- fn after_set_attr(&mut self, local_name: DOMString, value: DOMString) {
+ fn SetAttributeNS(&mut self, namespace_url: Option<DOMString>,
+ name: DOMString, value: DOMString) -> ErrorResult {
let node: JS<Node> = NodeCast::from(self);
- match local_name.as_slice() {
- "style" => {
- let doc = node.get().owner_doc();
- let base_url = doc.get().url().clone();
- self.get_mut().style_attribute = Some(style::parse_style_attribute(value, &base_url))
- }
- "id" if 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 = node.get().owner_doc().clone();
- let doc = doc.get_mut();
- doc.register_named_element(self, value.clone());
- }
- _ => ()
+ node.get().wait_until_safe_to_modify_dom();
+
+ // Step 1.
+ let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace_url));
+
+ let name_type = xml_name_type(name);
+ match name_type {
+ // Step 2.
+ InvalidXMLName => return Err(InvalidCharacter),
+ // Step 3.
+ Name => return Err(NamespaceError),
+ QName => {}
}
- //XXXjdm We really need something like a vtable so we can call AfterSetAttr.
- // This hardcoding is awful.
- match node.type_id() {
- ElementNodeTypeId(HTMLImageElementTypeId) => {
- let mut elem: JS<HTMLImageElement> = HTMLImageElementCast::to(self).unwrap();
- elem.AfterSetAttr(local_name.clone(), value.clone());
- }
- ElementNodeTypeId(HTMLIFrameElementTypeId) => {
- let mut elem: JS<HTMLIFrameElement> = HTMLIFrameElementCast::to(self).unwrap();
- elem.AfterSetAttr(local_name.clone(), value.clone());
- }
- ElementNodeTypeId(HTMLObjectElementTypeId) => {
- let mut elem: JS<HTMLObjectElement> = HTMLObjectElementCast::to(self).unwrap();
- elem.AfterSetAttr(local_name.clone(), value.clone());
- }
- _ => ()
+ // Step 4.
+ let (prefix, local_name) = get_attribute_parts(name.clone());
+ match prefix {
+ Some(ref prefix_str) => {
+ // Step 5.
+ if namespace == namespace::Null {
+ return Err(NamespaceError);
+ }
+
+ // Step 6.
+ if "xml" == prefix_str.as_slice() && namespace != namespace::XML {
+ return Err(NamespaceError);
+ }
+
+ // Step 7b.
+ if "xmlns" == prefix_str.as_slice() && namespace != namespace::XMLNS {
+ return Err(NamespaceError);
+ }
+ },
+ None => {}
}
- self.notify_attribute_changed(local_name);
+ // Step 7a.
+ if "xmlns" == name && namespace != namespace::XMLNS {
+ return Err(NamespaceError);
+ }
+
+ // Step 8.
+ if namespace == namespace::XMLNS && "xmlns" != name && Some(~"xmlns") != prefix {
+ return Err(NamespaceError);
+ }
+
+ // Step 9.
+ self.do_set_attribute(local_name.clone(), value, name, namespace.clone(), prefix, |attr| {
+ attr.get().local_name == local_name &&
+ attr.get().namespace == namespace
+ });
+ Ok(())
}
fn remove_attribute(&mut self, namespace: Namespace, name: DOMString) -> ErrorResult {
@@ -340,7 +380,7 @@ impl AttributeHandlers for JS<Element> {
Some(idx) => {
if namespace == namespace::Null {
let removed_raw_value = self.get().attrs[idx].get().Value();
- self.before_remove_attr(local_name, removed_raw_value);
+ vtable_for(&node).before_remove_attr(local_name.clone(), removed_raw_value);
}
self.get_mut().attrs.remove(idx);
@@ -350,39 +390,6 @@ impl AttributeHandlers for JS<Element> {
Ok(())
}
- fn before_remove_attr(&mut self, local_name: DOMString, old_value: DOMString) {
- let node: JS<Node> = NodeCast::from(self);
- match local_name.as_slice() {
- "style" => {
- self.get_mut().style_attribute = None
- }
- "id" if 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 = node.get().owner_doc().clone();
- let doc = doc.get_mut();
- doc.unregister_named_element(old_value);
- }
- _ => ()
- }
-
- //XXXjdm We really need something like a vtable so we can call BeforeRemoveAttr.
- // This hardcoding is awful.
- match node.type_id() {
- ElementNodeTypeId(HTMLImageElementTypeId) => {
- let mut elem: JS<HTMLImageElement> = HTMLImageElementCast::to(self).unwrap();
- elem.BeforeRemoveAttr(local_name.clone());
- }
- ElementNodeTypeId(HTMLIFrameElementTypeId) => {
- let mut elem: JS<HTMLIFrameElement> = HTMLIFrameElementCast::to(self).unwrap();
- elem.BeforeRemoveAttr(local_name.clone());
- }
- _ => ()
- }
-
- self.notify_attribute_changed(local_name);
- }
-
fn notify_attribute_changed(&self, local_name: DOMString) {
let node: JS<Node> = NodeCast::from(self);
if node.is_in_doc() {
@@ -443,6 +450,11 @@ impl Element {
}
impl Element {
+ // http://dom.spec.whatwg.org/#dom-element-namespaceuri
+ pub fn NamespaceURI(&self) -> DOMString {
+ self.namespace.to_str().to_owned()
+ }
+
// http://dom.spec.whatwg.org/#dom-element-tagname
pub fn TagName(&self) -> DOMString {
self.tag_name.to_ascii_upper()
@@ -502,33 +514,19 @@ impl Element {
}
// http://dom.spec.whatwg.org/#dom-element-setattribute
- pub fn SetAttribute(&mut self, abstract_self: &mut JS<Element>,
+ pub fn SetAttribute(&self, abstract_self: &mut 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() {
- name.to_ascii_lower()
- } else {
- name
- };
- abstract_self.set_attr(name, value)
+ abstract_self.SetAttribute(name, value)
}
// http://dom.spec.whatwg.org/#dom-element-setattributens
- pub fn SetAttributeNS(&mut self,
+ pub fn SetAttributeNS(&self,
abstract_self: &mut JS<Element>,
namespace_url: Option<DOMString>,
name: DOMString,
value: DOMString) -> ErrorResult {
- let name_type = xml_name_type(name);
- match name_type {
- InvalidXMLName => return Err(InvalidCharacter),
- Name => return Err(NamespaceError),
- QName => {}
- }
-
- let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace_url));
- abstract_self.set_attribute(namespace, name, value)
+ abstract_self.SetAttributeNS(namespace_url, name, value)
}
// http://dom.spec.whatwg.org/#dom-element-removeattribute
@@ -634,13 +632,81 @@ impl Element {
}
}
-pub trait IElement {
- fn bind_to_tree_impl(&self);
- fn unbind_from_tree_impl(&self);
+pub fn get_attribute_parts(name: DOMString) -> (Option<~str>, ~str) {
+ //FIXME: Throw for XML-invalid names
+ //FIXME: Throw for XMLNS-invalid names
+ let (prefix, local_name) = if name.contains(":") {
+ let parts: ~[&str] = name.splitn(':', 1).collect();
+ (Some(parts[0].to_owned()), parts[1].to_owned())
+ } else {
+ (None, name)
+ };
+
+ (prefix, local_name)
}
-impl IElement for JS<Element> {
- fn bind_to_tree_impl(&self) {
+impl VirtualMethods for JS<Element> {
+ fn super_type(&self) -> Option<~VirtualMethods:> {
+ let node: JS<Node> = NodeCast::from(self);
+ Some(~node as ~VirtualMethods:)
+ }
+
+ fn after_set_attr(&mut self, name: DOMString, value: DOMString) {
+ match self.super_type() {
+ Some(ref mut s) => s.after_set_attr(name.clone(), value.clone()),
+ _ => (),
+ }
+
+ let node: JS<Node> = NodeCast::from(self);
+ match name.as_slice() {
+ "style" => {
+ let doc = node.get().owner_doc();
+ let base_url = doc.get().url().clone();
+ self.get_mut().style_attribute = Some(style::parse_style_attribute(value, &base_url))
+ }
+ "id" if 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 = node.get().owner_doc().clone();
+ let doc = doc.get_mut();
+ doc.register_named_element(self, value.clone());
+ }
+ _ => ()
+ }
+
+ self.notify_attribute_changed(name);
+ }
+
+ fn before_remove_attr(&mut self, name: DOMString, value: DOMString) {
+ match self.super_type() {
+ Some(ref mut s) => s.before_remove_attr(name.clone(), value.clone()),
+ _ => (),
+ }
+
+ let node: JS<Node> = NodeCast::from(self);
+ match name.as_slice() {
+ "style" => {
+ self.get_mut().style_attribute = None
+ }
+ "id" if 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 = node.get().owner_doc().clone();
+ let doc = doc.get_mut();
+ doc.unregister_named_element(self, value);
+ }
+ _ => ()
+ }
+
+ self.notify_attribute_changed(name);
+ }
+
+ fn bind_to_tree(&mut self) {
+ match self.super_type() {
+ Some(ref mut s) => s.bind_to_tree(),
+ _ => (),
+ }
+
match self.get_attribute(Null, "id") {
Some(attr) => {
let mut doc = document_from_node(self);
@@ -650,26 +716,18 @@ impl IElement for JS<Element> {
}
}
- fn unbind_from_tree_impl(&self) {
+ fn unbind_from_tree(&mut self) {
+ match self.super_type() {
+ Some(ref mut s) => s.unbind_from_tree(),
+ _ => (),
+ }
+
match self.get_attribute(Null, "id") {
Some(attr) => {
let mut doc = document_from_node(self);
- doc.get_mut().unregister_named_element(attr.get().Value());
+ doc.get_mut().unregister_named_element(self, attr.get().Value());
}
_ => ()
}
}
}
-
-pub fn get_attribute_parts(name: DOMString) -> (Option<~str>, ~str) {
- //FIXME: Throw for XML-invalid names
- //FIXME: Throw for XMLNS-invalid names
- let (prefix, local_name) = if name.contains(":") {
- let parts: ~[&str] = name.splitn(':', 1).collect();
- (Some(parts[0].to_owned()), parts[1].to_owned())
- } else {
- (None, name)
- };
-
- (prefix, local_name)
-}
diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs
index a1a3a9d7514..f953774bb5d 100644
--- a/src/components/script/dom/eventtarget.rs
+++ b/src/components/script/dom/eventtarget.rs
@@ -9,6 +9,7 @@ use dom::bindings::codegen::EventListenerBinding::EventListener;
use dom::event::Event;
use dom::eventdispatcher::dispatch_event;
use dom::node::NodeTypeId;
+use dom::virtualmethods::VirtualMethods;
use servo_util::str::DOMString;
use collections::hashmap::HashMap;
@@ -26,7 +27,7 @@ pub enum EventTargetTypeId {
}
#[deriving(Eq,Encodable)]
-struct EventListenerEntry {
+pub struct EventListenerEntry {
phase: ListenerPhase,
listener: EventListener
}
@@ -123,3 +124,9 @@ impl Reflectable for EventTarget {
&mut self.reflector_
}
}
+
+impl VirtualMethods for JS<EventTarget> {
+ fn super_type(&self) -> Option<~VirtualMethods:> {
+ None
+ }
+}
diff --git a/src/components/script/dom/formdata.rs b/src/components/script/dom/formdata.rs
index ac6cdac403e..db380af6a55 100644
--- a/src/components/script/dom/formdata.rs
+++ b/src/components/script/dom/formdata.rs
@@ -14,7 +14,7 @@ use servo_util::str::DOMString;
use collections::hashmap::HashMap;
#[deriving(Encodable)]
-enum FormDatum {
+pub enum FormDatum {
StringData(DOMString),
BlobData { blob: JS<Blob>, name: DOMString }
}
diff --git a/src/components/script/dom/htmlelement.rs b/src/components/script/dom/htmlelement.rs
index f8a1cd96a9b..30f3e7b552c 100644
--- a/src/components/script/dom/htmlelement.rs
+++ b/src/components/script/dom/htmlelement.rs
@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::HTMLElementBinding;
+use dom::bindings::codegen::InheritTypes::ElementCast;
use dom::bindings::codegen::InheritTypes::HTMLElementDerived;
use dom::bindings::js::JS;
use dom::bindings::error::{ErrorResult, Fallible};
@@ -10,6 +11,7 @@ use dom::document::Document;
use dom::element::{Element, ElementTypeId, HTMLElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::node::{Node, ElementNodeTypeId};
+use dom::virtualmethods::VirtualMethods;
use js::jsapi::JSContext;
use js::jsval::{JSVal, NullValue};
use servo_util::namespace;
@@ -23,6 +25,7 @@ pub struct HTMLElement {
impl HTMLElementDerived for EventTarget {
fn is_htmlelement(&self) -> bool {
match self.type_id {
+ NodeTargetTypeId(ElementNodeTypeId(ElementTypeId)) => false,
NodeTargetTypeId(ElementNodeTypeId(_)) => true,
_ => false
}
@@ -160,3 +163,10 @@ impl HTMLElement {
0
}
}
+
+impl VirtualMethods for JS<HTMLElement> {
+ fn super_type(&self) -> Option<~VirtualMethods:> {
+ let element: JS<Element> = ElementCast::from(self);
+ Some(~element as ~VirtualMethods:)
+ }
+}
diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs
index a33e5baf84d..c98634682a6 100644
--- a/src/components/script/dom/htmliframeelement.rs
+++ b/src/components/script/dom/htmliframeelement.rs
@@ -3,15 +3,16 @@
* 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::codegen::InheritTypes::{ElementCast, HTMLIFrameElementDerived, HTMLElementCast};
use dom::bindings::js::JS;
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::{HTMLIFrameElementTypeId, Element};
-use dom::element::{AttributeHandlers, AfterSetAttrListener, BeforeRemoveAttrListener};
+use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
+use dom::virtualmethods::VirtualMethods;
use dom::windowproxy::WindowProxy;
use servo_util::str::DOMString;
@@ -210,8 +211,18 @@ impl HTMLIFrameElement {
}
}
-impl AfterSetAttrListener for JS<HTMLIFrameElement> {
- fn AfterSetAttr(&mut self, name: DOMString, value: DOMString) {
+impl VirtualMethods for JS<HTMLIFrameElement> {
+ fn super_type(&self) -> Option<~VirtualMethods:> {
+ let htmlelement: JS<HTMLElement> = HTMLElementCast::from(self);
+ Some(~htmlelement as ~VirtualMethods:)
+ }
+
+ fn after_set_attr(&mut self, name: DOMString, value: DOMString) {
+ match self.super_type() {
+ Some(ref mut s) => s.after_set_attr(name.clone(), value.clone()),
+ _ => (),
+ }
+
if "sandbox" == name {
let mut modes = AllowNothing as u8;
for word in value.split(' ') {
@@ -230,10 +241,13 @@ impl AfterSetAttrListener for JS<HTMLIFrameElement> {
self.get_mut().sandbox = Some(modes);
}
}
-}
-impl BeforeRemoveAttrListener for JS<HTMLIFrameElement> {
- fn BeforeRemoveAttr(&mut self, name: DOMString) {
+ fn before_remove_attr(&mut self, name: DOMString, value: DOMString) {
+ match self.super_type() {
+ Some(ref mut s) => s.before_remove_attr(name.clone(), value),
+ _ => (),
+ }
+
if "sandbox" == name {
self.get_mut().sandbox = None;
}
diff --git a/src/components/script/dom/htmlimageelement.rs b/src/components/script/dom/htmlimageelement.rs
index 63ff2c4549b..3b966bbfe24 100644
--- a/src/components/script/dom/htmlimageelement.rs
+++ b/src/components/script/dom/htmlimageelement.rs
@@ -4,15 +4,16 @@
use dom::bindings::codegen::HTMLImageElementBinding;
use dom::bindings::codegen::InheritTypes::{NodeCast, HTMLImageElementDerived};
-use dom::bindings::codegen::InheritTypes::{ElementCast};
+use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::js::JS;
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::{Element, HTMLImageElementTypeId};
-use dom::element::{AttributeHandlers, AfterSetAttrListener, BeforeRemoveAttrListener};
+use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId, NodeHelpers, window_from_node};
+use dom::virtualmethods::VirtualMethods;
use servo_util::geometry::to_px;
use layout_interface::{ContentBoxQuery, ContentBoxResponse};
use servo_net::image_cache_task;
@@ -244,18 +245,31 @@ impl HTMLImageElement {
}
}
-impl AfterSetAttrListener for JS<HTMLImageElement> {
- fn AfterSetAttr(&mut self, name: DOMString, value: DOMString) {
+impl VirtualMethods for JS<HTMLImageElement> {
+ fn super_type(&self) -> Option<~VirtualMethods:> {
+ let htmlelement: JS<HTMLElement> = HTMLElementCast::from(self);
+ Some(~htmlelement as ~VirtualMethods:)
+ }
+
+ fn after_set_attr(&mut self, name: DOMString, value: DOMString) {
+ match self.super_type() {
+ Some(ref mut s) => s.after_set_attr(name.clone(), value.clone()),
+ _ => (),
+ }
+
if "src" == name {
let window = window_from_node(self);
let url = Some(window.get().get_url());
self.get_mut().update_image(Some(value), url);
}
}
-}
-impl BeforeRemoveAttrListener for JS<HTMLImageElement> {
- fn BeforeRemoveAttr(&mut self, name: DOMString) {
+ fn before_remove_attr(&mut self, name: DOMString, value: DOMString) {
+ match self.super_type() {
+ Some(ref mut s) => s.before_remove_attr(name.clone(), value.clone()),
+ _ => (),
+ }
+
if "src" == name {
self.get_mut().update_image(None, None);
}
diff --git a/src/components/script/dom/htmlobjectelement.rs b/src/components/script/dom/htmlobjectelement.rs
index 03fc8984845..6288dcfc33d 100644
--- a/src/components/script/dom/htmlobjectelement.rs
+++ b/src/components/script/dom/htmlobjectelement.rs
@@ -4,17 +4,18 @@
use dom::bindings::codegen::HTMLObjectElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLObjectElementDerived;
-use dom::bindings::codegen::InheritTypes::ElementCast;
+use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::js::JS;
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::{Element, HTMLObjectElementTypeId};
-use dom::element::{AttributeHandlers, AfterSetAttrListener};
+use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::htmlformelement::HTMLFormElement;
use dom::node::{Node, ElementNodeTypeId, NodeHelpers, window_from_node};
use dom::validitystate::ValidityState;
+use dom::virtualmethods::VirtualMethods;
use dom::windowproxy::WindowProxy;
use servo_util::str::DOMString;
@@ -244,8 +245,18 @@ impl HTMLObjectElement {
}
}
-impl AfterSetAttrListener for JS<HTMLObjectElement> {
- fn AfterSetAttr(&mut self, name: DOMString, _value: DOMString) {
+impl VirtualMethods for JS<HTMLObjectElement> {
+ fn super_type(&self) -> Option<~VirtualMethods:> {
+ let htmlelement: JS<HTMLElement> = HTMLElementCast::from(self);
+ Some(~htmlelement as ~VirtualMethods:)
+ }
+
+ fn after_set_attr(&mut self, name: DOMString, value: DOMString) {
+ match self.super_type() {
+ Some(ref mut s) => s.after_set_attr(name.clone(), value),
+ _ => (),
+ }
+
if "data" == name {
let window = window_from_node(self);
let url = Some(window.get().get_url());
diff --git a/src/components/script/dom/htmlstyleelement.rs b/src/components/script/dom/htmlstyleelement.rs
index 8c09d6336c0..ed335dd70eb 100644
--- a/src/components/script/dom/htmlstyleelement.rs
+++ b/src/components/script/dom/htmlstyleelement.rs
@@ -3,14 +3,17 @@
* 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::codegen::InheritTypes::{HTMLElementCast, HTMLStyleElementDerived, NodeCast};
use dom::bindings::js::JS;
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLStyleElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
-use dom::node::{Node, ElementNodeTypeId};
+use dom::node::{Node, ElementNodeTypeId, window_from_node};
+use dom::virtualmethods::VirtualMethods;
+use html::cssparse::parse_inline_css;
+use layout_interface::{AddStylesheetMsg, LayoutChan};
use servo_util::str::DOMString;
#[deriving(Encodable)]
@@ -72,3 +75,35 @@ impl HTMLStyleElement {
Ok(())
}
}
+
+pub trait StyleElementHelpers {
+ fn parse_own_css(&self);
+}
+
+impl StyleElementHelpers for JS<HTMLStyleElement> {
+ fn parse_own_css(&self) {
+ let node: JS<Node> = NodeCast::from(self);
+ let win = window_from_node(&node);
+ let url = win.get().page().get_url();
+
+ let data = node.get().GetTextContent(&node).expect("Element.textContent must be a string");
+ let sheet = parse_inline_css(url, data);
+ let LayoutChan(ref layout_chan) = win.get().page().layout_chan;
+ layout_chan.send(AddStylesheetMsg(sheet));
+ }
+}
+
+impl VirtualMethods for JS<HTMLStyleElement> {
+ fn super_type(&self) -> Option<~VirtualMethods:> {
+ let htmlelement: JS<HTMLElement> = HTMLElementCast::from(self);
+ Some(~htmlelement as ~VirtualMethods:)
+ }
+
+ fn child_inserted(&mut self, child: &JS<Node>) {
+ match self.super_type() {
+ Some(ref mut s) => s.child_inserted(child),
+ _ => (),
+ }
+ self.parse_own_css();
+ }
+}
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs
index 77ca388be9e..bf2669512ff 100644
--- a/src/components/script/dom/node.rs
+++ b/src/components/script/dom/node.rs
@@ -8,7 +8,7 @@ use dom::attr::Attr;
use dom::bindings::codegen::InheritTypes::{CommentCast, DocumentCast, DocumentTypeCast};
use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived};
-use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast;
+use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast};
use dom::bindings::codegen::NodeBinding::NodeConstants;
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
@@ -19,11 +19,12 @@ use dom::comment::Comment;
use dom::document::{Document, HTMLDocument, NonHTMLDocument};
use dom::documentfragment::DocumentFragment;
use dom::documenttype::DocumentType;
-use dom::element::{Element, ElementTypeId, HTMLAnchorElementTypeId, IElement};
+use dom::element::{Element, ElementTypeId, HTMLAnchorElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::nodelist::{NodeList};
-use dom::text::Text;
use dom::processinginstruction::ProcessingInstruction;
+use dom::text::Text;
+use dom::virtualmethods::{VirtualMethods, vtable_for};
use dom::window::Window;
use html::hubbub_html_parser::build_element_from_tag;
use layout_interface::{LayoutChan, ReapLayoutDataMsg, UntrustedNodeAddress};
@@ -403,13 +404,11 @@ impl NodeHelpers for JS<Node> {
if self.is_in_doc() {
for node in self.traverse_preorder() {
- if node.is_element() {
- let element: JS<Element> = ElementCast::to(&node).unwrap();
- element.bind_to_tree_impl();
- }
+ vtable_for(&node).bind_to_tree();
}
}
+ self.parent_node().map(|parent| vtable_for(&parent).child_inserted(self));
document.get().content_changed();
}
@@ -419,10 +418,8 @@ impl NodeHelpers for JS<Node> {
let document = document_from_node(self);
for node in self.traverse_preorder() {
- if node.is_element() {
- let element: JS<Element> = ElementCast::to(&node).unwrap();
- element.unbind_from_tree_impl();
- }
+ // XXX how about if the node wasn't in the tree in the first place?
+ vtable_for(&node).unbind_from_tree();
}
document.get().content_changed();
@@ -573,7 +570,7 @@ impl NodeHelpers for JS<Node> {
// Iteration and traversal
//
-type ChildElementIterator<'a> = Map<'a, JS<Node>,
+pub type ChildElementIterator<'a> = Map<'a, JS<Node>,
JS<Element>,
Filter<'a, JS<Node>, AbstractNodeChildrenIterator>>;
@@ -1372,10 +1369,10 @@ impl Node {
copy_elem.namespace = node_elem.namespace.clone();
for attr in node_elem.attrs.iter() {
let attr = attr.get();
- copy_elem.attrs.push(Attr::new_ns(&document.get().window,
- attr.local_name.clone(), attr.value.clone(),
- attr.name.clone(), attr.namespace.clone(),
- attr.prefix.clone()));
+ copy_elem.attrs.push(Attr::new(&document.get().window,
+ attr.local_name.clone(), attr.value.clone(),
+ attr.name.clone(), attr.namespace.clone(),
+ attr.prefix.clone()));
}
},
_ => ()
@@ -1733,12 +1730,6 @@ impl Node {
false
}
- // http://dom.spec.whatwg.org/#dom-node-namespaceuri
- pub fn GetNamespaceURI(&self, abstract_self: &JS<Node>) -> Option<DOMString> {
- let element: Option<JS<Element>> = ElementCast::to(abstract_self);
- element.map(|element| element.get().namespace.to_str().to_owned())
- }
-
// http://dom.spec.whatwg.org/#dom-node-prefix
pub fn GetPrefix(&self) -> Option<DOMString> {
None
@@ -1840,3 +1831,10 @@ pub fn window_from_node<T: NodeBase>(derived: &JS<T>) -> JS<Window> {
let document: JS<Document> = document_from_node(derived);
document.get().window.clone()
}
+
+impl VirtualMethods for JS<Node> {
+ fn super_type(&self) -> Option<~VirtualMethods:> {
+ let eventtarget: JS<EventTarget> = EventTargetCast::from(self);
+ Some(~eventtarget as ~VirtualMethods:)
+ }
+}
diff --git a/src/components/script/dom/nodelist.rs b/src/components/script/dom/nodelist.rs
index ab2bbb7f575..396fbad9c82 100644
--- a/src/components/script/dom/nodelist.rs
+++ b/src/components/script/dom/nodelist.rs
@@ -9,7 +9,7 @@ use dom::node::{Node, NodeHelpers};
use dom::window::Window;
#[deriving(Encodable)]
-enum NodeListType {
+pub enum NodeListType {
Simple(~[JS<Node>]),
Children(JS<Node>)
}
diff --git a/src/components/script/dom/virtualmethods.rs b/src/components/script/dom/virtualmethods.rs
new file mode 100644
index 00000000000..85ae37cb032
--- /dev/null
+++ b/src/components/script/dom/virtualmethods.rs
@@ -0,0 +1,107 @@
+/* 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::InheritTypes::ElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLIFrameElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLImageElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast;
+use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast;
+use dom::bindings::js::JS;
+use dom::element::Element;
+use dom::element::{ElementTypeId, HTMLImageElementTypeId};
+use dom::element::{HTMLIFrameElementTypeId, HTMLObjectElementTypeId, HTMLStyleElementTypeId};
+use dom::htmlelement::HTMLElement;
+use dom::htmliframeelement::HTMLIFrameElement;
+use dom::htmlimageelement::HTMLImageElement;
+use dom::htmlobjectelement::HTMLObjectElement;
+use dom::htmlstyleelement::HTMLStyleElement;
+use dom::node::{Node, ElementNodeTypeId};
+use servo_util::str::DOMString;
+
+/// Trait to allow DOM nodes to opt-in to overriding (or adding to) common
+/// behaviours. Replicates the effect of C++ virtual methods.
+pub trait VirtualMethods {
+ /// Returns self as the superclass of the implementation for this trait,
+ /// if any.
+ fn super_type(&self) -> Option<~VirtualMethods:>;
+
+ /// Called when changing or adding attributes, after the attribute's value
+ /// has been updated.
+ fn after_set_attr(&mut self, name: DOMString, value: DOMString) {
+ match self.super_type() {
+ Some(ref mut s) => s.after_set_attr(name, value),
+ _ => (),
+ }
+ }
+
+ /// Called when changing or removing attributes, before any modification
+ /// has taken place.
+ fn before_remove_attr(&mut self, name: DOMString, value: DOMString) {
+ match self.super_type() {
+ Some(ref mut s) => s.before_remove_attr(name, value),
+ _ => (),
+ }
+ }
+
+ /// Called when a Node is appended to a tree that is part of a Document.
+ fn bind_to_tree(&mut self) {
+ match self.super_type() {
+ Some(ref mut s) => s.bind_to_tree(),
+ _ => (),
+ }
+ }
+
+ /// Called when a Node is removed from a tree that is part of a Document.
+ fn unbind_from_tree(&mut self) {
+ match self.super_type() {
+ Some(ref mut s) => s.unbind_from_tree(),
+ _ => (),
+ }
+ }
+
+ /// Called on the parent when a node is added to its child list.
+ fn child_inserted(&mut self, child: &JS<Node>) {
+ match self.super_type() {
+ Some(ref mut s) => s.child_inserted(child),
+ _ => (),
+ }
+ }
+}
+
+/// Obtain a VirtualMethods instance for a given Node-derived object. Any
+/// method call on the trait object will invoke the corresponding method on the
+/// concrete type, propagating up the parent hierarchy unless otherwise
+/// interrupted.
+pub fn vtable_for<'a>(node: &JS<Node>) -> ~VirtualMethods: {
+ match node.get().type_id {
+ ElementNodeTypeId(HTMLImageElementTypeId) => {
+ let element: JS<HTMLImageElement> = HTMLImageElementCast::to(node).unwrap();
+ ~element as ~VirtualMethods:
+ }
+ ElementNodeTypeId(HTMLIFrameElementTypeId) => {
+ let element: JS<HTMLIFrameElement> = HTMLIFrameElementCast::to(node).unwrap();
+ ~element as ~VirtualMethods:
+ }
+ ElementNodeTypeId(HTMLObjectElementTypeId) => {
+ let element: JS<HTMLObjectElement> = HTMLObjectElementCast::to(node).unwrap();
+ ~element as ~VirtualMethods:
+ }
+ ElementNodeTypeId(HTMLStyleElementTypeId) => {
+ let element: JS<HTMLStyleElement> = HTMLStyleElementCast::to(node).unwrap();
+ ~element as ~VirtualMethods:
+ }
+ ElementNodeTypeId(ElementTypeId) => {
+ let element: JS<Element> = ElementCast::to(node).unwrap();
+ ~element as ~VirtualMethods:
+ }
+ ElementNodeTypeId(_) => {
+ let element: JS<HTMLElement> = HTMLElementCast::to(node).unwrap();
+ ~element as ~VirtualMethods:
+ }
+ _ => {
+ ~node.clone() as ~VirtualMethods:
+ }
+ }
+}
diff --git a/src/components/script/dom/webidls/Element.webidl b/src/components/script/dom/webidls/Element.webidl
index 2211fd5c887..aa0161204b0 100644
--- a/src/components/script/dom/webidls/Element.webidl
+++ b/src/components/script/dom/webidls/Element.webidl
@@ -18,10 +18,11 @@ interface Element : Node {
We haven't moved these from Node to Element like the spec wants.
[Throws]
- readonly attribute DOMString? namespaceURI;
readonly attribute DOMString? prefix;
readonly attribute DOMString localName;
*/
+ [Constant]
+ readonly attribute DOMString namespaceURI;
// Not [Constant] because it depends on which document we're in
[Pure]
readonly attribute DOMString tagName;
diff --git a/src/components/script/dom/webidls/Node.webidl b/src/components/script/dom/webidls/Node.webidl
index 2a13d6ab381..39555e1e0d8 100644
--- a/src/components/script/dom/webidls/Node.webidl
+++ b/src/components/script/dom/webidls/Node.webidl
@@ -79,11 +79,9 @@ interface Node : EventTarget {
// Mozilla-specific stuff
// These have been moved to Element in the spec.
- // If we move namespaceURI, prefix and localName to Element they should return
+ // If we move prefix and localName to Element they should return
// a non-nullable type.
[Constant]
- readonly attribute DOMString? namespaceURI;
- [Constant]
readonly attribute DOMString? prefix;
[Constant]
readonly attribute DOMString? localName;
diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs
index dae0020abe8..9ba9d00da82 100644
--- a/src/components/script/dom/window.rs
+++ b/src/components/script/dom/window.rs
@@ -19,14 +19,11 @@ use servo_net::image_cache_task::ImageCacheTask;
use servo_util::str::DOMString;
use servo_util::task::{spawn_named};
-use js::glue::*;
-use js::jsapi::{JSObject, JSContext, JS_DefineProperty};
-use js::jsval::JSVal;
-use js::jsval::{NullValue, ObjectValue};
+use js::jsapi::{JSObject, JSContext, JS_DefineProperty, JS_PropertyStub, JS_StrictPropertyStub};
+use js::jsval::{NullValue, ObjectValue, JSVal};
use js::JSPROP_ENUMERATE;
use collections::hashmap::HashMap;
-use std::cast;
use std::cmp;
use std::comm::{channel, Sender, Receiver};
use std::comm::Select;
@@ -329,8 +326,8 @@ impl Window {
unsafe {
JS_DefineProperty(cx, object, name,
ObjectValue(&*object),
- Some(cast::transmute(GetJSClassHookStubPointer(PROPERTY_STUB))),
- Some(cast::transmute(GetJSClassHookStubPointer(STRICT_PROPERTY_STUB))),
+ Some(JS_PropertyStub),
+ Some(JS_StrictPropertyStub),
JSPROP_ENUMERATE);
}
})
diff --git a/src/components/script/html/cssparse.rs b/src/components/script/html/cssparse.rs
index c5cad0849de..b538676edac 100644
--- a/src/components/script/html/cssparse.rs
+++ b/src/components/script/html/cssparse.rs
@@ -18,34 +18,45 @@ pub enum StylesheetProvenance {
InlineProvenance(Url, ~str),
}
+// Parses the style data and returns the stylesheet
+pub fn parse_inline_css(url: Url, data: ~str) -> Stylesheet {
+ let resource_task = ResourceTask(); // Resource task is not used for inline parsing
+ parse_css(InlineProvenance(url, data), resource_task)
+}
+
+fn parse_css(provenance: StylesheetProvenance,
+ resource_task: ResourceTask) -> Stylesheet {
+ // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding
+ let environment_encoding = UTF_8 as EncodingRef;
+
+ match provenance {
+ UrlProvenance(url) => {
+ debug!("cssparse: loading style sheet at {:s}", url.to_str());
+ let (input_chan, input_port) = channel();
+ resource_task.send(Load(url, input_chan));
+ let LoadResponse { metadata: metadata, progress_port: progress_port }
+ = input_port.recv();
+ let final_url = &metadata.final_url;
+ let protocol_encoding_label = metadata.charset.as_ref().map(|s| s.as_slice());
+ let iter = ProgressMsgPortIterator { progress_port: progress_port };
+ Stylesheet::from_bytes_iter(
+ iter, final_url.clone(),
+ protocol_encoding_label, Some(environment_encoding))
+ }
+ InlineProvenance(base_url, data) => {
+ debug!("cssparse: loading inline stylesheet {:s}", data);
+ Stylesheet::from_str(data, base_url, environment_encoding)
+ }
+ }
+}
+
pub fn spawn_css_parser(provenance: StylesheetProvenance,
resource_task: ResourceTask)
-> Receiver<Stylesheet> {
let (result_chan, result_port) = channel();
- // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding
- let environment_encoding = UTF_8 as EncodingRef;
-
spawn_named("cssparser", proc() {
- let sheet = match provenance {
- UrlProvenance(url) => {
- debug!("cssparse: loading style sheet at {:s}", url.to_str());
- let (input_chan, input_port) = channel();
- resource_task.send(Load(url, input_chan));
- let LoadResponse { metadata: metadata, progress_port: progress_port }
- = input_port.recv();
- let final_url = &metadata.final_url;
- let protocol_encoding_label = metadata.charset.as_ref().map(|s| s.as_slice());
- let iter = ProgressMsgPortIterator { progress_port: progress_port };
- Stylesheet::from_bytes_iter(
- iter, final_url.clone(),
- protocol_encoding_label, Some(environment_encoding))
- }
- InlineProvenance(base_url, data) => {
- Stylesheet::from_str(data, base_url, environment_encoding)
- }
- };
- result_chan.send(sheet);
+ result_chan.send(parse_css(provenance, resource_task));
});
return result_port;
diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs
index 438d28a4898..21d285632f8 100644
--- a/src/components/script/html/hubbub_html_parser.rs
+++ b/src/components/script/html/hubbub_html_parser.rs
@@ -14,7 +14,7 @@ use dom::htmliframeelement::IFrameSize;
use dom::htmlformelement::HTMLFormElement;
use dom::node::{ElementNodeTypeId, INode, NodeHelpers};
use dom::types::*;
-use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
+use html::cssparse::{StylesheetProvenance, UrlProvenance, spawn_css_parser};
use script_task::Page;
use hubbub::hubbub;
@@ -50,7 +50,7 @@ pub struct JSFile {
url: Url
}
-type JSResult = ~[JSFile];
+pub type JSResult = ~[JSFile];
enum CSSMessage {
CSSTaskNewFile(StylesheetProvenance),
@@ -298,7 +298,7 @@ pub fn parse_html(page: &Page,
parser.enable_scripting(true);
parser.enable_styling(true);
- let (css_chan2, css_chan3, js_chan2) = (css_chan.clone(), css_chan.clone(), js_chan.clone());
+ let (css_chan2, js_chan2) = (css_chan.clone(), js_chan.clone());
let next_subpage_id = RefCell::new(next_subpage_id);
@@ -483,22 +483,8 @@ pub fn parse_html(page: &Page,
}
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: 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);
- let text: JS<Text> = TextCast::to(&child).unwrap();
- data.push(text.get().characterdata.data.to_str()); // FIXME: Bad copy.
- }
-
- debug!("style data = {:?}", data);
- let provenance = InlineProvenance(base_url.clone(), data.concat());
- css_chan3.send(CSSTaskNewFile(provenance));
- }
+ complete_style: |_| {
+ // style parsing is handled in element::notify_child_list_changed.
},
};
parser.set_tree_handler(&tree_handler);
diff --git a/src/components/script/script.rs b/src/components/script/script.rs
index 9ab4c2cc671..7b9f63c4dc4 100644
--- a/src/components/script/script.rs
+++ b/src/components/script/script.rs
@@ -4,11 +4,13 @@
#[crate_id = "github.com/mozilla/servo#script:0.1"];
#[crate_type = "lib"];
+#[crate_type = "dylib"];
+#[crate_type = "rlib"];
#[comment = "The Servo Parallel Browser Project"];
#[license = "MPL"];
-#[feature(globs, macro_rules, struct_variant, managed_boxes, phase)];
+#[feature(globs, macro_rules, struct_variant, phase)];
#[feature(phase)];
#[phase(syntax, link)]
@@ -153,6 +155,7 @@ pub mod dom {
pub mod uievent;
pub mod text;
pub mod validitystate;
+ pub mod virtualmethods;
pub mod window;
pub mod windowproxy;
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index dcee911c46a..a585c320ad9 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -405,6 +405,23 @@ impl Page {
}
}
+ fn find_fragment_node(&self, fragid: ~str) -> Option<JS<Element>> {
+ let document = self.frame().get_ref().document.clone();
+ match document.get().GetElementById(fragid.to_owned()) {
+ Some(node) => Some(node),
+ None => {
+ let doc_node: JS<Node> = NodeCast::from(&document);
+ let mut anchors = doc_node.traverse_preorder().filter(|node| node.is_anchor_element());
+ anchors.find(|node| {
+ let elem: JS<Element> = ElementCast::to(node).unwrap();
+ elem.get_attribute(Null, "name").map_or(false, |attr| {
+ attr.get().value_ref() == fragid
+ })
+ }).map(|node| ElementCast::to(&node).unwrap())
+ }
+ }
+ }
+
pub fn initialize_js_info(&self, js_context: Rc<Cx>, global: *JSObject) {
assert!(global.is_not_null());
@@ -896,30 +913,12 @@ impl ScriptTask {
let _ = wintarget.get_mut().dispatch_event_with_target(&winclone, Some(doctarget), &mut event);
let mut fragment_node = page.fragment_node.borrow_mut();
- *fragment_node = fragment.map_or(None, |fragid| self.find_fragment_node(page, fragid));
+ *fragment_node = fragment.map_or(None, |fragid| page.find_fragment_node(fragid));
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(LoadCompleteMsg(page.id, url));
}
- fn find_fragment_node(&self, page: &Page, fragid: ~str) -> Option<JS<Element>> {
- let frame = page.frame();
- let document = frame.get_ref().document.clone();
- match document.get().GetElementById(fragid.to_owned()) {
- Some(node) => Some(node),
- None => {
- let doc_node: JS<Node> = NodeCast::from(&document);
- let mut anchors = doc_node.traverse_preorder().filter(|node| node.is_anchor_element());
- anchors.find(|node| {
- let elem: JS<Element> = ElementCast::to(node).unwrap();
- elem.get_attribute(Null, "name").map_or(false, |attr| {
- attr.get().value_ref() == fragid
- })
- }).map(|node| ElementCast::to(&node).unwrap())
- }
- }
- }
-
fn scroll_fragment_point(&self, pipeline_id: PipelineId, page: &Page, node: JS<Element>) {
let (chan, port) = channel();
let node: JS<Node> = NodeCast::from(&node);
@@ -1122,7 +1121,7 @@ impl ScriptTask {
let url = parse_url(href.get().value_ref(), base_url);
if click_frag {
- match self.find_fragment_node(page, url.fragment.unwrap()) {
+ match page.find_fragment_node(url.fragment.unwrap()) {
Some(node) => self.scroll_fragment_point(page.id, page, node),
None => {}
}
diff --git a/src/components/style/style.rs b/src/components/style/style.rs
index c2659665063..b296b34c035 100644
--- a/src/components/style/style.rs
+++ b/src/components/style/style.rs
@@ -4,11 +4,13 @@
#[crate_id = "github.com/mozilla/servo#style:0.1"];
#[crate_type = "lib"];
+#[crate_type = "dylib"];
+#[crate_type = "rlib"];
#[comment = "The Servo Parallel Browser Project"];
#[license = "MPL"];
-#[feature(globs, macro_rules, managed_boxes)];
+#[feature(globs, macro_rules)];
#[feature(phase)];
#[phase(syntax, link)] extern crate log;
diff --git a/src/components/util/util.rs b/src/components/util/util.rs
index 78ff97a5e05..08e06e43b6e 100644
--- a/src/components/util/util.rs
+++ b/src/components/util/util.rs
@@ -4,8 +4,10 @@
#[crate_id = "github.com/mozilla/servo#util:0.1"];
#[crate_type = "lib"];
+#[crate_type = "dylib"];
+#[crate_type = "rlib"];
-#[feature(macro_rules, managed_boxes)];
+#[feature(macro_rules)];
#[feature(phase)];
#[phase(syntax, link)]
diff --git a/src/platform/android/servo-android-glue b/src/platform/android/servo-android-glue
-Subproject caf03d371cb99c9c72a7127114d8f5365a02eb0
+Subproject 0941b7702380d57ffe95823cfb057d752fd150a
diff --git a/src/platform/linux/fontconfig b/src/platform/linux/fontconfig
-Subproject b2cfb1f4b3561e01a58359cd18929457a0486db
+Subproject 0450af3d92f1fb4f269cc64e58647871a5bf728
diff --git a/src/platform/linux/rust-fontconfig b/src/platform/linux/rust-fontconfig
-Subproject 7bac3e9f27c42ef74085dd002c922c2f051c602
+Subproject 51d0a1bfe3a2e6b5cd935d9a7bf4922a3105c63
diff --git a/src/support/egl/rust-egl b/src/support/egl/rust-egl
-Subproject 38cc35371a88f6240cd4b35205b2ec8b6703f13
+Subproject ffb1be4fecbfadacd02e5a714025bc58e6833f2
diff --git a/src/support/glut/rust-glut b/src/support/glut/rust-glut
-Subproject be49cbc2d5455744c7951b07160f0d29fed2364
+Subproject 6050ecb8e884b4eba1155dacb29d1c9567886c2
diff --git a/src/support/harfbuzz/rust-harfbuzz b/src/support/harfbuzz/rust-harfbuzz
-Subproject c422c3ca200da371d73af2246b62e6d7c40125e
+Subproject 9c2a78f3c43d3b52391b94aa43dc61d6bddab50
diff --git a/src/support/layers/rust-layers b/src/support/layers/rust-layers
-Subproject 493a4311f1202907208aecdaf3fc4a4c192608e
+Subproject 10d40153462cf7248fcf35db5c18cf026cd25ae
diff --git a/src/support/spidermonkey/rust-mozjs b/src/support/spidermonkey/rust-mozjs
-Subproject f81f450ba6a742041844d40154dfe8ad1e540a4
+Subproject 9f0ae0ab33f786c9d2d5e1a9fdfdc6c07fa9803
diff --git a/src/test/content/test_document_getElementById.html b/src/test/content/test_document_getElementById.html
index 9d066137ef3..97b506f58af 100644
--- a/src/test/content/test_document_getElementById.html
+++ b/src/test/content/test_document_getElementById.html
@@ -76,9 +76,9 @@
is(document.getElementById("should-not-exist"), e, "test 4-1");
}
- // TODO:
// test5: "in tree order, within the context object's tree"
// http://dom.spec.whatwg.org/#dom-document-getelementbyid.
+ // we test this in test_document_getElementById_tree_order.html
// TODO:
// test6: innerHTML
diff --git a/src/test/content/test_document_getElementById_tree_order.html b/src/test/content/test_document_getElementById_tree_order.html
new file mode 100644
index 00000000000..ccf0c37bb01
--- /dev/null
+++ b/src/test/content/test_document_getElementById_tree_order.html
@@ -0,0 +1,40 @@
+<html>
+ <head>
+ <script src="harness.js"></script>
+ </head>
+ <body>
+ <div id="a">
+ </div>
+ <div id="b">
+ <p id="b">P</p>
+ <input id="b" type="submit" value="Submit">
+ </div>
+ <script>
+ {
+ var b = document.getElementById("b");
+ is_a(b, HTMLDivElement);
+ var a = document.getElementById("a");
+ var p = document.createElement("p");
+ p.id = "b";
+ a.appendChild(p);
+ var newB = document.getElementById("b");
+ is_a(newB, HTMLParagraphElement);
+ }
+ {
+ var gbody = document.getElementsByTagName("body")[0];
+ var div = document.createElement("div");
+ div.setAttribute("id", "c");
+ var h1 = document.createElement("h1");
+ h1.setAttribute("id", "c");
+ gbody.appendChild(div);
+ gbody.appendChild(h1);
+ var c = document.getElementById("c");
+ is_a(c, HTMLDivElement);
+ gbody.removeChild(div);
+ var newC = document.getElementById("c");
+ is_a(newC, HTMLHeadingElement);
+ }
+ finish();
+ </script>
+ </body>
+</html>
diff --git a/src/test/content/test_element_attribute.html b/src/test/content/test_element_attribute.html
index 8631138c767..d7ee6a23640 100644
--- a/src/test/content/test_element_attribute.html
+++ b/src/test/content/test_element_attribute.html
@@ -41,6 +41,25 @@
is(r2, null, "test4-1, Element.removeAttribute().");
}
+ {
+ test.setAttribute("xml:lang", "en");
+
+ let r1 = test.hasAttribute("xml:lang");
+ is(r1, true, "test5-0, Element.setAttribute('xml:lang').");
+ let r2 = test.getAttribute("xml:lang");
+ is_not(r2, null, "test5-1, Element.setAttribute('xml:lang').");
+ }
+
+ should_throw(function () {
+ test.setAttributeNS("http://example.com", "xmlns", "foo");
+ });
+ should_throw(function () {
+ test.setAttributeNS("http://www.w3.org/2000/xmlns/", "attr", "value");
+ });
+ should_throw(function () {
+ test.setAttributeNS("http://www.w3.org/2000/xmlns/", "prefix:attr", "value");
+ });
+
finish();
</script>
</body>
diff --git a/src/test/html/test_pseudo.html b/src/test/html/test_pseudo.html
new file mode 100644
index 00000000000..bfe528df145
--- /dev/null
+++ b/src/test/html/test_pseudo.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+span.servo1:before { display:inline; content:'Hello'; color:blue}
+span.servo1:after { display:inline; content:'ervo'; color:blue}
+div.servo2:before { display:inline; content:'Hello'; color:blue}
+div.servo2:after { display:inline; content:'ervo'; color:blue}
+span.servo3:before { display:block; content:'Smile'; color:blue}
+span.servo3:after { display:block; content:'And thanks';}
+div.rust:before { display:block; content:'Hello,';}
+div.rust:after { display:inline; content:'ust';}
+</style>
+</head>
+
+<body>
+<span class="servo1">, S</span>
+<div class="servo2">, S</div>
+<span class="servo3">Servo</span>
+<div class="rust">R</div>
+</body>
+</html>
diff --git a/src/test/ref/append_style_a.html b/src/test/ref/append_style_a.html
new file mode 100644
index 00000000000..40521ba3d08
--- /dev/null
+++ b/src/test/ref/append_style_a.html
@@ -0,0 +1 @@
+<div style="background-color: blue">this is the story of a girl</div>
diff --git a/src/test/ref/append_style_b.html b/src/test/ref/append_style_b.html
new file mode 100644
index 00000000000..4792dbc86e2
--- /dev/null
+++ b/src/test/ref/append_style_b.html
@@ -0,0 +1,6 @@
+<div id="hello">this is the story of a girl</div>
+<script>
+ var style = document.createElement('style');
+ style.textContent = "#hello { background-color: blue; }"
+ document.head.appendChild(style);
+</script>
diff --git a/src/test/ref/basic.list b/src/test/ref/basic.list
index 4df86c52e8b..81b8f7761dd 100644
--- a/src/test/ref/basic.list
+++ b/src/test/ref/basic.list
@@ -27,12 +27,15 @@
# inline_border_a.html inline_border_b.html
== anon_block_inherit_a.html anon_block_inherit_b.html
== attr_exists_selector.html attr_exists_selector_ref.html
+!= noteq_attr_exists_selector.html attr_exists_selector_ref.html
== data_img_a.html data_img_b.html
== background_style_attr.html background_ref.html
== background_external_stylesheet.html background_ref.html
== block_image.html 500x300_green.html
+!= block_image.html noteq_500x300_white.html
# == simple_iframe.html simple_iframe_ref.html -- disabled due to iframe crashiness
== object_element_a.html object_element_b.html
+== append_style_a.html append_style_b.html
== height_compute_reset.html height_compute.html
== width_nonreplaced_block_simple_a.html width_nonreplaced_block_simple_b.html
== max_width_float_simple_a.html max_width_float_simple_b.html
@@ -65,3 +68,5 @@
== background_repeat_y_a.html background_repeat_y_b.html
== background_repeat_none_a.html background_repeat_none_b.html
== background_repeat_both_a.html background_repeat_both_b.html
+== setattribute_id_restyle_a.html setattribute_id_restyle_b.html
+== pseudo_element_a.html pseudo_element_b.html
diff --git a/src/test/ref/noteq_500x300_white.html b/src/test/ref/noteq_500x300_white.html
new file mode 100644
index 00000000000..af89ba927e1
--- /dev/null
+++ b/src/test/ref/noteq_500x300_white.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<div style="width: 500px; height: 300px; background-color: #fff;"></div>
+</body>
+</html>
diff --git a/src/test/ref/noteq_attr_exists_selector.html b/src/test/ref/noteq_attr_exists_selector.html
new file mode 100644
index 00000000000..58bce6d5d39
--- /dev/null
+++ b/src/test/ref/noteq_attr_exists_selector.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Attribute exists selector: [foo]</title>
+ </head>
+ <body>
+ <p>This text should be green.</p>
+ <p>This text should be black.</p>
+ </body>
+</html>
diff --git a/src/test/ref/pseudo_element_a.html b/src/test/ref/pseudo_element_a.html
new file mode 100644
index 00000000000..4700d0e593a
--- /dev/null
+++ b/src/test/ref/pseudo_element_a.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+span.servo1:before { display:inline; content:'Hello';}
+span.servo1:after { display:inline; content:'ervo';}
+div.servo2:before { display:inline; content:'Hello';}
+div.servo2:after { display:inline; content:'ervo';}
+span.servo3:before { display:block; content:'Smile'; color:blue}
+span.servo3:after { display:block; content:'And thanks'; color:blue}
+div.rust:before { display:block; content:'Hello,';}
+div.rust:after { display:inline; content:'ust';}
+</style>
+</head>
+
+<body>
+<span class="servo1">, S</span>
+<div class="servo2">, S</div>
+<span class="servo3">Servo</span>
+<div class="rust">R</div>
+</body>
+</html>
diff --git a/src/test/ref/pseudo_element_b.html b/src/test/ref/pseudo_element_b.html
new file mode 100644
index 00000000000..892ce7ed4d9
--- /dev/null
+++ b/src/test/ref/pseudo_element_b.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+.col { color:blue; }
+</style>
+</head>
+
+<body>
+Hello,<span> Servo</span>
+<div class="servo">Hello, Servo</div>
+<div class="col">Smile</div>
+<span>Servo</span>
+<div class="col">And thanks</div>
+<div>Hello,</div>
+<span>Rust</span>
+</body>
+</html>
diff --git a/src/test/ref/setattribute_id_restyle_a.html b/src/test/ref/setattribute_id_restyle_a.html
new file mode 100644
index 00000000000..469ce797db7
--- /dev/null
+++ b/src/test/ref/setattribute_id_restyle_a.html
@@ -0,0 +1,12 @@
+<style>
+ #foo { background-color: #FF0000; }
+</style>
+
+<div>hello</div>
+<div id="">world</div>
+
+<script>
+ var divs = document.getElementsByTagName('div');
+ divs[0].setAttribute('id', 'foo');
+ divs[1].setAttribute('id', 'foo');
+</script>
diff --git a/src/test/ref/setattribute_id_restyle_b.html b/src/test/ref/setattribute_id_restyle_b.html
new file mode 100644
index 00000000000..f16fe454c50
--- /dev/null
+++ b/src/test/ref/setattribute_id_restyle_b.html
@@ -0,0 +1,6 @@
+<style>
+ #foo { background-color: #FF0000; }
+</style>
+
+<div id="foo">hello</div>
+<div id="foo">world</div>