aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock14
-rw-r--r--README.md8
-rw-r--r--components/gfx/display_list/mod.rs19
-rw-r--r--components/gfx/font.rs17
-rw-r--r--components/gfx/font_context.rs33
-rw-r--r--components/gfx/platform/macos/font_list.rs17
-rw-r--r--components/gfx/render_task.rs8
-rw-r--r--components/gfx/text/text_run.rs4
-rw-r--r--components/gfx/text/util.rs27
-rw-r--r--components/layout/construct.rs138
-rw-r--r--components/layout/flow.rs2
-rw-r--r--components/layout/fragment.rs44
-rw-r--r--components/layout/inline.rs52
-rw-r--r--components/layout/layout_task.rs4
-rw-r--r--components/layout/text.rs310
-rw-r--r--components/layout/wrapper.rs102
-rw-r--r--components/net/image_cache_task.rs46
-rw-r--r--components/script/dom/node.rs102
-rw-r--r--components/style/node.rs2
-rw-r--r--components/util/cache.rs7
-rw-r--r--components/util/dlist.rs68
-rw-r--r--components/util/lib.rs2
-rw-r--r--components/util/opts.rs5
-rw-r--r--components/util/taskpool.rs53
-rw-r--r--ports/android/glut_app/Cargo.lock14
-rw-r--r--ports/cef/Cargo.lock16
-rw-r--r--ports/cef/core.rs1
-rw-r--r--src/lib.rs7
-rw-r--r--tests/wpt/include.ini8
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/005.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/006.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/007.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/008.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/009.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/010.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/011.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/012.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/013.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/015.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/015a.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/016.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/017.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/018.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/019.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/020.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/022.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/023.html.ini6
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/024.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/025.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/026.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/027.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/028.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/029.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/030.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/031.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/033.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/034.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/035.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/036.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/037.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/038.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/039.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/040.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/041.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/042.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/043.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/044.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/045.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/046.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/047.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/048.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/049.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/050.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/051.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/052.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/053.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/054.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/055.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/056.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/068.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/069.html.ini6
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/070.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/071.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/072.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/073.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/074.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/075.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/076.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/077.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/078.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/079.html.ini6
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/080.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/081.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/082.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/083.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/084.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/085.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/086.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/088.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/091.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/092.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/094.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/095.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/096.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/097.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/098.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/099.html.ini3
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/100.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/101.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/103.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/104.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/105.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/106.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/107.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/108.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/109.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/110.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/111.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/116.html.ini6
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/117.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/118.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/119.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/120.html.ini6
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/122.html.ini8
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/123.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/124.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/125.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/126.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/127.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/128.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/129.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/130.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/132.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/133.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/134.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/135.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/136.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/137.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/138.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/139.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/140.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/141.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/142.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/143.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/144.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/145.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/146.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/147.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/148.html.ini5
-rw-r--r--tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/149.html.ini20
150 files changed, 1225 insertions, 513 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d0aeafa535f..06b4d0085d5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -29,7 +29,7 @@ source = "git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f2
dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"egl 0.1.0 (git+https://github.com/servo/rust-egl#88f2a13812ddbce2bf2317221663a61c31b3e220)",
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
@@ -60,7 +60,7 @@ dependencies = [
"alert 0.1.0 (git+https://github.com/servo/rust-alert#fdc24f13be8d8a2d15214ec228d166b3221b809e)",
"azure 0.1.0 (git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f20957dd112d)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"devtools 0.0.1",
"devtools_traits 0.0.1",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
@@ -92,7 +92,7 @@ dependencies = [
[[package]]
name = "core_text"
version = "0.1.0"
-source = "git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d"
+source = "git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e"
dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
@@ -101,7 +101,7 @@ dependencies = [
[[package]]
name = "cssparser"
version = "0.1.0"
-source = "git+https://github.com/servo/rust-cssparser#22146ce095cb62df39d459c3a79d1486041f96f6"
+source = "git+https://github.com/servo/rust-cssparser#7b0549a5d122135848b8813ec401112ab588063c"
dependencies = [
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#28eafb604a92c7786685b46c0fc02682ba3ab265)",
]
@@ -175,7 +175,7 @@ dependencies = [
"azure 0.1.0 (git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f20957dd112d)",
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"fontconfig 0.1.0 (git+https://github.com/servo/rust-fontconfig#b16c1e12ecb74b1e4e9a9b23c2b98580a34cf201)",
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
@@ -388,7 +388,7 @@ name = "script"
version = "0.0.1"
dependencies = [
"canvas 0.0.1",
- "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#22146ce095cb62df39d459c3a79d1486041f96f6)",
+ "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#7b0549a5d122135848b8813ec401112ab588063c)",
"devtools_traits 0.0.1",
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#28eafb604a92c7786685b46c0fc02682ba3ab265)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
@@ -461,7 +461,7 @@ dependencies = [
name = "style"
version = "0.0.1"
dependencies = [
- "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#22146ce095cb62df39d459c3a79d1486041f96f6)",
+ "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#7b0549a5d122135848b8813ec401112ab588063c)",
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#28eafb604a92c7786685b46c0fc02682ba3ab265)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
"lazy_static 0.1.0 (git+https://github.com/Kimundi/lazy-static.rs#e62a65372f1dd9019e37eb9381d819edff80e360)",
diff --git a/README.md b/README.md
index c544152555c..465e1bbbbfc 100644
--- a/README.md
+++ b/README.md
@@ -16,14 +16,14 @@ script](etc/ci/travis.install.sh).
On OS X (homebrew):
``` sh
-brew install automake pkg-config python glfw3
+brew install automake pkg-config python glfw3 cmake
pip install virtualenv
```
On OS X (MacPorts):
``` sh
-sudo port install python27 py27-virtualenv
+sudo port install python27 py27-virtualenv cmake
```
On Debian-based Linuxes:
@@ -41,7 +41,7 @@ On Fedora:
sudo yum install curl freeglut-devel libtool gcc-c++ libXi-devel \
freetype-devel mesa-libGL-devel glib2-devel libX11-devel libXrandr-devel gperf \
fontconfig-devel cabextract ttmkfdir python python-virtualenv expat-devel \
- rpm-build openssl-devel glfw-devel
+ rpm-build openssl-devel glfw-devel cmake
pushd .
cd /tmp
wget http://corefonts.sourceforge.net/msttcorefonts-2.5-1.spec
@@ -53,7 +53,7 @@ popd
On Arch Linux:
``` sh
-sudo pacman -S base-devel git python2 python2-virtualenv mesa glfw ttf-font
+sudo pacman -S base-devel git python2 python2-virtualenv mesa glfw ttf-font cmake
```
Cross-compilation for Android:
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs
index a72f0b44d08..7f8975a2ca6 100644
--- a/components/gfx/display_list/mod.rs
+++ b/components/gfx/display_list/mod.rs
@@ -288,10 +288,10 @@ impl DisplayList {
pub fn draw_into_context(&self,
render_context: &mut RenderContext,
current_transform: &Matrix2D<AzFloat>,
- current_clip_rect: &Rect<Au>) {
+ current_clip_stack: &mut Vec<Rect<Au>>) {
debug!("Beginning display list.");
for item in self.list.iter() {
- item.draw_into_context(render_context, current_transform, current_clip_rect)
+ item.draw_into_context(render_context, current_transform, current_clip_stack)
}
debug!("Ending display list.");
}
@@ -504,14 +504,19 @@ impl DisplayItem {
fn draw_into_context(&self,
render_context: &mut RenderContext,
current_transform: &Matrix2D<AzFloat>,
- current_clip_rect: &Rect<Au>) {
+ current_clip_stack: &mut Vec<Rect<Au>>) {
// This should have been flattened to the content stacking level first.
assert!(self.base().level == ContentStackingLevel);
+ // TODO(pcwalton): This will need some tweaking to deal with more complex clipping regions.
let clip_rect = &self.base().clip_rect;
- let need_to_clip = current_clip_rect != clip_rect;
- if need_to_clip {
+ if current_clip_stack.len() == 0 || current_clip_stack.last().unwrap() != clip_rect {
+ while current_clip_stack.len() != 0 {
+ render_context.draw_pop_clip();
+ drop(current_clip_stack.pop());
+ }
render_context.draw_push_clip(clip_rect);
+ current_clip_stack.push(*clip_rect);
}
match *self {
@@ -608,10 +613,6 @@ impl DisplayItem {
PseudoDisplayItemClass(_) => {}
}
-
- if need_to_clip {
- render_context.draw_pop_clip();
- }
}
pub fn base<'a>(&'a self) -> &'a BaseDisplayItem {
diff --git a/components/gfx/font.rs b/components/gfx/font.rs
index fe9445be107..f88d964b831 100644
--- a/components/gfx/font.rs
+++ b/components/gfx/font.rs
@@ -100,14 +100,19 @@ pub struct Font {
}
impl Font {
- pub fn shape_text(&mut self, text: String, is_whitespace: bool) -> Arc<GlyphStore> {
+ pub fn shape_text(&mut self, text: &str, is_whitespace: bool) -> Arc<GlyphStore> {
self.make_shaper();
let shaper = &self.shaper;
- self.shape_cache.find_or_create(&text, |txt| {
- let mut glyphs = GlyphStore::new(text.as_slice().char_len() as int, is_whitespace);
- shaper.as_ref().unwrap().shape_text(txt.as_slice(), &mut glyphs);
- Arc::new(glyphs)
- })
+ match self.shape_cache.find_equiv(&text) {
+ None => {}
+ Some(glyphs) => return (*glyphs).clone(),
+ }
+
+ let mut glyphs = GlyphStore::new(text.char_len() as int, is_whitespace);
+ shaper.as_ref().unwrap().shape_text(text, &mut glyphs);
+ let glyphs = Arc::new(glyphs);
+ self.shape_cache.insert(text.to_string(), glyphs.clone());
+ glyphs
}
fn make_shaper<'a>(&'a mut self) -> &'a Shaper {
diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs
index efb40d16abd..adcd9810b88 100644
--- a/components/gfx/font_context.rs
+++ b/components/gfx/font_context.rs
@@ -43,7 +43,7 @@ static SMALL_CAPS_SCALE_FACTOR: f64 = 0.8; // Matches FireFox (see gfxFont.
struct LayoutFontCacheEntry {
family: String,
- font: Rc<RefCell<Font>>,
+ font: Option<Rc<RefCell<Font>>>,
}
struct FallbackFontCacheEntry {
@@ -132,13 +132,21 @@ impl FontContext {
let mut cache_hit = false;
for cached_font_entry in self.layout_font_cache.iter() {
if cached_font_entry.family.as_slice() == family.name() {
- let cached_font = cached_font_entry.font.borrow();
- if cached_font.descriptor == desc &&
- cached_font.requested_pt_size == style.font_size.to_subpx() &&
- cached_font.variant == style.font_variant {
- fonts.push(cached_font_entry.font.clone());
- cache_hit = true;
- break;
+ match cached_font_entry.font {
+ None => {
+ cache_hit = true;
+ break;
+ }
+ Some(ref cached_font_ref) => {
+ let cached_font = cached_font_ref.borrow();
+ if cached_font.descriptor == desc &&
+ cached_font.requested_pt_size == style.font_size.to_subpx() &&
+ cached_font.variant == style.font_variant {
+ fonts.push((*cached_font_ref).clone());
+ cache_hit = true;
+ break;
+ }
+ }
}
}
}
@@ -156,11 +164,16 @@ impl FontContext {
let layout_font = Rc::new(RefCell::new(layout_font));
self.layout_font_cache.push(LayoutFontCacheEntry {
family: family.name().to_string(),
- font: layout_font.clone(),
+ font: Some(layout_font.clone()),
});
fonts.push(layout_font);
}
- None => {}
+ None => {
+ self.layout_font_cache.push(LayoutFontCacheEntry {
+ family: family.name().to_string(),
+ font: None,
+ });
+ }
}
}
}
diff --git a/components/gfx/platform/macos/font_list.rs b/components/gfx/platform/macos/font_list.rs
index 74e22d0feb9..0974ce3bf46 100644
--- a/components/gfx/platform/macos/font_list.rs
+++ b/components/gfx/platform/macos/font_list.rs
@@ -23,12 +23,17 @@ pub fn get_variations_for_family(family_name: &str, callback: |String|) {
let family_collection =
core_text::font_collection::create_for_family(family_name.as_slice());
- let family_descriptors = family_collection.get_descriptors();
- for descref in family_descriptors.iter() {
- let descref: CTFontDescriptorRef = unsafe { mem::transmute(descref) };
- let desc: CTFontDescriptor = unsafe { TCFType::wrap_under_get_rule(descref) };
- let postscript_name = desc.font_name();
- callback(postscript_name);
+ match family_collection {
+ Some(family_collection) => {
+ let family_descriptors = family_collection.get_descriptors();
+ for descref in family_descriptors.iter() {
+ let descref: CTFontDescriptorRef = unsafe { mem::transmute(descref) };
+ let desc: CTFontDescriptor = unsafe { TCFType::wrap_under_get_rule(descref) };
+ let postscript_name = desc.font_name();
+ callback(postscript_name);
+ }
+ }
+ None => {}
}
}
diff --git a/components/gfx/render_task.rs b/components/gfx/render_task.rs
index 53f50f95102..32c5d97c2b1 100644
--- a/components/gfx/render_task.rs
+++ b/components/gfx/render_task.rs
@@ -25,14 +25,13 @@ use servo_msg::compositor_msg::{LayerMetadata, RenderListener, RenderingRenderSt
use servo_msg::constellation_msg::{ConstellationChan, Failure, FailureMsg, PipelineId};
use servo_msg::constellation_msg::{RendererReadyMsg};
use servo_msg::platform::surface::NativeSurfaceAzureMethods;
-use servo_util::geometry::{Au, mod};
+use servo_util::geometry;
use servo_util::opts;
use servo_util::smallvec::{SmallVec, SmallVec1};
use servo_util::task::spawn_named_with_send_on_failure;
use servo_util::time::{TimeProfilerChan, profile};
use servo_util::time;
use std::comm::{Receiver, Sender, channel};
-use std::i32;
use sync::Arc;
use font_cache_task::FontCacheTask;
@@ -359,9 +358,8 @@ impl<C:RenderListener + Send> RenderTask<C> {
None,
self.time_profiler_chan.clone(),
|| {
- let clip_rect = Rect(Point2D(Au(i32::MIN), Au(i32::MIN)),
- Size2D(Au(i32::MAX), Au(i32::MAX)));
- display_list.draw_into_context(&mut ctx, &matrix, &clip_rect);
+ let mut clip_stack = Vec::new();
+ display_list.draw_into_context(&mut ctx, &matrix, &mut clip_stack);
ctx.draw_target.flush();
});
}
diff --git a/components/gfx/text/text_run.rs b/components/gfx/text/text_run.rs
index cdf7e5c9ddf..4ab5aed94e0 100644
--- a/components/gfx/text/text_run.rs
+++ b/components/gfx/text/text_run.rs
@@ -162,7 +162,7 @@ impl<'a> TextRun {
// Create a glyph store for this slice if it's nonempty.
if can_break_before && byte_i > byte_last_boundary {
- let slice = text.slice(byte_last_boundary, byte_i).to_string();
+ let slice = text.slice(byte_last_boundary, byte_i);
debug!("creating glyph store for slice {} (ws? {}), {} - {} in run {}",
slice, !cur_slice_is_whitespace, byte_last_boundary, byte_i, text);
glyphs.push(GlyphRun {
@@ -179,7 +179,7 @@ impl<'a> TextRun {
// Create a glyph store for the final slice if it's nonempty.
if byte_i > byte_last_boundary {
- let slice = text.slice_from(byte_last_boundary).to_string();
+ let slice = text.slice_from(byte_last_boundary);
debug!("creating glyph store for final slice {} (ws? {}), {} - {} in run {}",
slice, cur_slice_is_whitespace, byte_last_boundary, text.len(), text);
glyphs.push(GlyphRun {
diff --git a/components/gfx/text/util.rs b/components/gfx/text/util.rs
index 23b8b029144..3c43b5d9b0f 100644
--- a/components/gfx/text/util.rs
+++ b/components/gfx/text/util.rs
@@ -17,15 +17,17 @@ pub enum CompressionMode {
// High level TODOs:
//
// * Issue #113: consider incoming text state (arabic, etc)
-// and propogate outgoing text state (dual of above)
+// and propagate outgoing text state (dual of above)
//
// * Issue #114: record skipped and kept chars for mapping original to new text
//
// * Untracked: various edge cases for bidi, CJK, etc.
-pub fn transform_text(text: &str, mode: CompressionMode,
+pub fn transform_text(text: &str,
+ mode: CompressionMode,
incoming_whitespace: bool,
- new_line_pos: &mut Vec<CharIndex>) -> (String, bool) {
- let mut out_str = String::new();
+ output_text: &mut String,
+ new_line_pos: &mut Vec<CharIndex>)
+ -> bool {
let out_whitespace = match mode {
CompressNone | DiscardNewline => {
let mut new_line_index = CharIndex(0);
@@ -46,7 +48,7 @@ pub fn transform_text(text: &str, mode: CompressionMode,
if ch != '\n' {
new_line_index = new_line_index + CharIndex(1);
}
- out_str.push_char(ch);
+ output_text.push_char(ch);
}
}
text.len() > 0 && is_in_whitespace(text.char_at_reverse(0), mode)
@@ -65,14 +67,14 @@ pub fn transform_text(text: &str, mode: CompressionMode,
// TODO: record skipped char
} else {
// TODO: record kept char
- out_str.push_char(ch);
+ output_text.push_char(ch);
}
} else { /* next_in_whitespace; possibly add a space char */
if in_whitespace {
// TODO: record skipped char
} else {
// TODO: record kept char
- out_str.push_char(' ');
+ output_text.push_char(' ');
}
}
// save whitespace context for next char
@@ -82,7 +84,7 @@ pub fn transform_text(text: &str, mode: CompressionMode,
}
};
- return (out_str, out_whitespace);
+ return out_whitespace;
fn is_in_whitespace(ch: char, mode: CompressionMode) -> bool {
match (ch, mode) {
@@ -155,7 +157,8 @@ fn test_transform_compress_none() {
for test in test_strs.iter() {
let mut new_line_pos = vec!();
- let (trimmed_str, _out) = transform_text(*test, mode, true, &mut new_line_pos);
+ let mut trimmed_str = String::new();
+ transform_text(*test, mode, true, &mut trimmed_str, &mut new_line_pos);
assert_eq!(trimmed_str.as_slice(), *test)
}
}
@@ -187,7 +190,8 @@ fn test_transform_discard_newline() {
for (test, oracle) in test_strs.iter().zip(oracle_strs.iter()) {
let mut new_line_pos = vec!();
- let (trimmed_str, _out) = transform_text(*test, mode, true, &mut new_line_pos);
+ let mut trimmed_str = String::new();
+ transform_text(*test, mode, true, &mut trimmed_str, &mut new_line_pos);
assert_eq!(trimmed_str.as_slice(), *oracle)
}
}
@@ -279,7 +283,8 @@ fn test_transform_compress_whitespace_newline_no_incoming() {
for (test, oracle) in test_strs.iter().zip(oracle_strs.iter()) {
let mut new_line_pos = vec!();
- let (trimmed_str, _out) = transform_text(*test, mode, false, &mut new_line_pos);
+ let mut trimmed_str = String::new();
+ transform_text(*test, mode, false, &mut trimmed_str, &mut new_line_pos);
assert_eq!(trimmed_str.as_slice(), *oracle)
}
}
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index c69d04d1d49..ca97d7e36b7 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -28,7 +28,7 @@ use fragment::{InlineBlockFragmentInfo, InputFragment, SpecificFragmentInfo, Tab
use fragment::{TableColumnFragment, TableColumnFragmentInfo, TableFragment, TableRowFragment};
use fragment::{TableWrapperFragment, UnscannedTextFragment, UnscannedTextFragmentInfo};
use incremental::RestyleDamage;
-use inline::{InlineFragments, InlineFlow};
+use inline::InlineFlow;
use parallel;
use table_wrapper::TableWrapperFlow;
use table::TableFlow;
@@ -53,6 +53,7 @@ use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, ProcessingInstruc
use script::dom::node::{TextNodeTypeId};
use script::dom::htmlobjectelement::is_image_data;
use servo_util::opts;
+use std::collections::{DList, Deque};
use std::mem;
use std::sync::atomics::Relaxed;
use style::ComputedValues;
@@ -115,7 +116,7 @@ pub struct InlineFragmentsConstructionResult {
pub splits: Vec<InlineBlockSplit>,
/// Any fragments that succeed the {ib} splits.
- pub fragments: InlineFragments,
+ pub fragments: DList<Fragment>,
/// Any absolute descendants that we're bubbling up.
pub abs_descendants: AbsDescendants,
@@ -150,7 +151,7 @@ pub struct InlineFragmentsConstructionResult {
#[deriving(Clone)]
pub struct InlineBlockSplit {
/// The inline fragments that precede the flow.
- pub predecessors: InlineFragments,
+ pub predecessors: DList<Fragment>,
/// The flow that caused this {ib} split.
pub flow: FlowRef,
@@ -159,7 +160,7 @@ pub struct InlineBlockSplit {
/// Holds inline fragments that we're gathering for children of an inline node.
struct InlineFragmentsAccumulator {
/// The list of fragments.
- fragments: InlineFragments,
+ fragments: DList<Fragment>,
/// Whether we've created a range to enclose all the fragments. This will be Some() if the outer node
/// is an inline and None otherwise.
@@ -169,20 +170,28 @@ struct InlineFragmentsAccumulator {
impl InlineFragmentsAccumulator {
fn new() -> InlineFragmentsAccumulator {
InlineFragmentsAccumulator {
- fragments: InlineFragments::new(),
+ fragments: DList::new(),
enclosing_style: None,
}
}
fn from_inline_node(node: &ThreadSafeLayoutNode) -> InlineFragmentsAccumulator {
- let fragments = InlineFragments::new();
+ let fragments = DList::new();
InlineFragmentsAccumulator {
fragments: fragments,
enclosing_style: Some(node.style().clone()),
}
}
- fn finish(self) -> InlineFragments {
+ fn push_all(&mut self, fragments: DList<Fragment>) {
+ if fragments.len() == 0 {
+ return
+ }
+
+ self.fragments.append(fragments)
+ }
+
+ fn to_dlist(self) -> DList<Fragment> {
let InlineFragmentsAccumulator {
fragments: mut fragments,
enclosing_style
@@ -190,7 +199,7 @@ impl InlineFragmentsAccumulator {
match enclosing_style {
Some(enclosing_style) => {
- for frag in fragments.fragments.iter_mut() {
+ for frag in fragments.iter_mut() {
frag.add_inline_context_style(enclosing_style.clone());
}
}
@@ -289,7 +298,7 @@ impl<'a> FlowConstructor<'a> {
flow_list: &mut Vec<FlowRef>,
whitespace_stripping: WhitespaceStrippingMode,
node: &ThreadSafeLayoutNode) {
- let mut fragments = fragment_accumulator.finish();
+ let mut fragments = fragment_accumulator.to_dlist();
if fragments.is_empty() {
return
};
@@ -298,14 +307,14 @@ impl<'a> FlowConstructor<'a> {
NoWhitespaceStripping => {}
StripWhitespaceFromStart => {
flow::mut_base(flow.deref_mut()).restyle_damage.insert(
- fragments.strip_ignorable_whitespace_from_start());
+ strip_ignorable_whitespace_from_start(&mut fragments));
if fragments.is_empty() {
return
};
}
StripWhitespaceFromEnd => {
flow::mut_base(flow.deref_mut()).restyle_damage.insert(
- fragments.strip_ignorable_whitespace_from_end());
+ strip_ignorable_whitespace_from_end(&mut fragments));
if fragments.is_empty() {
return
};
@@ -314,7 +323,7 @@ impl<'a> FlowConstructor<'a> {
// Build a list of all the inline-block fragments before fragments is moved.
let mut inline_block_flows = vec!();
- for f in fragments.fragments.iter() {
+ for f in fragments.iter() {
match f.specific {
InlineBlockFragment(ref info) => inline_block_flows.push(info.flow_ref.clone()),
InlineAbsoluteHypotheticalFragment(ref info) => {
@@ -324,6 +333,12 @@ impl<'a> FlowConstructor<'a> {
}
}
+ // We must scan for runs before computing minimum ascent and descent because scanning
+ // for runs might collapse so much whitespace away that only hypothetical fragments
+ // remain. In that case the inline flow will compute its ascent and descent to be zero.
+ let fragments = TextRunScanner::new().scan_for_runs(self.layout_context.font_context(),
+ fragments);
+
let mut inline_flow_ref = FlowRef::new(box InlineFlow::from_fragments((*node).clone(),
fragments));
@@ -335,10 +350,6 @@ impl<'a> FlowConstructor<'a> {
{
let inline_flow = inline_flow_ref.as_inline();
- // We must scan for runs before computing minimum ascent and descent because scanning
- // for runs might collapse so much whitespace away that only hypothetical fragments
- // remain. In that case the inline flow will compute its ascent and descent to be zero.
- TextRunScanner::new().scan_for_runs(self.layout_context.font_context(), inline_flow);
let (ascent, descent) =
inline_flow.compute_minimum_ascent_and_descent(self.layout_context.font_context(),
@@ -409,7 +420,7 @@ impl<'a> FlowConstructor<'a> {
predecessors: predecessors,
flow: kid_flow
} = split;
- inline_fragment_accumulator.fragments.push_all(predecessors);
+ inline_fragment_accumulator.push_all(predecessors);
// If this is the first fragment in flow, then strip ignorable
// whitespace per CSS 2.1 § 9.2.1.1.
@@ -441,7 +452,7 @@ impl<'a> FlowConstructor<'a> {
}
// Add the fragments to the list we're maintaining.
- inline_fragment_accumulator.fragments.push_all(successor_fragments);
+ inline_fragment_accumulator.push_all(successor_fragments);
abs_descendants.push_descendants(kid_abs_descendants);
}
ConstructionItemConstructionResult(WhitespaceConstructionItem(whitespace_node,
@@ -451,11 +462,11 @@ impl<'a> FlowConstructor<'a> {
// between block elements, and retained when between inline elements.
let fragment_info =
UnscannedTextFragment(UnscannedTextFragmentInfo::from_text(" ".to_string()));
- let mut fragment = Fragment::from_opaque_node_and_style(whitespace_node,
- whitespace_style,
- whitespace_damage,
- fragment_info);
- inline_fragment_accumulator.fragments.push(&mut fragment);
+ let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
+ whitespace_style,
+ whitespace_damage,
+ fragment_info);
+ inline_fragment_accumulator.fragments.push(fragment);
}
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => {
// TODO: Implement anonymous table objects for missing parents
@@ -483,8 +494,8 @@ impl<'a> FlowConstructor<'a> {
if node.get_pseudo_element_type() != Normal ||
node.type_id() == Some(ElementNodeTypeId(HTMLInputElementTypeId)) {
let fragment_info = UnscannedTextFragment(UnscannedTextFragmentInfo::new(node));
- let mut fragment = Fragment::new_from_specific_info(node, fragment_info);
- inline_fragment_accumulator.fragments.push(&mut fragment);
+ let fragment = Fragment::new_from_specific_info(node, fragment_info);
+ inline_fragment_accumulator.fragments.push(fragment);
first_fragment = false;
}
@@ -577,7 +588,7 @@ impl<'a> FlowConstructor<'a> {
predecessors:
mem::replace(
&mut fragment_accumulator,
- InlineFragmentsAccumulator::from_inline_node(node)).finish(),
+ InlineFragmentsAccumulator::from_inline_node(node)).to_dlist(),
flow: flow,
};
opt_inline_block_splits.push(split);
@@ -596,32 +607,34 @@ impl<'a> FlowConstructor<'a> {
predecessors: predecessors,
flow: kid_flow
} = split;
- fragment_accumulator.fragments.push_all(predecessors);
+ fragment_accumulator.push_all(predecessors);
let split = InlineBlockSplit {
predecessors:
mem::replace(&mut fragment_accumulator,
InlineFragmentsAccumulator::from_inline_node(node))
- .finish(),
+ .to_dlist(),
flow: kid_flow,
};
opt_inline_block_splits.push(split)
}
// Push residual fragments.
- fragment_accumulator.fragments.push_all(successors);
+ fragment_accumulator.push_all(successors);
abs_descendants.push_descendants(kid_abs_descendants);
}
- ConstructionItemConstructionResult(WhitespaceConstructionItem(whitespace_node,
- whitespace_style,
- whitespace_damage)) => {
+ ConstructionItemConstructionResult(WhitespaceConstructionItem(
+ whitespace_node,
+ whitespace_style,
+ whitespace_damage)) => {
// Instantiate the whitespace fragment.
- let fragment_info = UnscannedTextFragment(UnscannedTextFragmentInfo::from_text(" ".to_string()));
- let mut fragment = Fragment::from_opaque_node_and_style(whitespace_node,
+ let fragment_info = UnscannedTextFragment(UnscannedTextFragmentInfo::from_text(
+ " ".to_string()));
+ let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_style,
whitespace_damage,
fragment_info);
- fragment_accumulator.fragments.push(&mut fragment)
+ fragment_accumulator.fragments.push(fragment)
}
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => {
// TODO: Implement anonymous table objects for missing parents
@@ -636,7 +649,7 @@ impl<'a> FlowConstructor<'a> {
let construction_item = InlineFragmentsConstructionItem(
InlineFragmentsConstructionResult {
splits: opt_inline_block_splits,
- fragments: fragment_accumulator.finish(),
+ fragments: fragment_accumulator.to_dlist(),
abs_descendants: abs_descendants,
});
ConstructionItemConstructionResult(construction_item)
@@ -668,15 +681,15 @@ impl<'a> FlowConstructor<'a> {
// If this is generated content, then we need to initialize the accumulator with the
// fragment corresponding to that content. Otherwise, just initialize with the ordinary
// fragment that needs to be generated for this inline node.
- let mut fragment = if node.get_pseudo_element_type() != Normal {
+ let fragment = if node.get_pseudo_element_type() != Normal {
let fragment_info = UnscannedTextFragment(UnscannedTextFragmentInfo::new(node));
Fragment::new_from_specific_info(node, fragment_info)
} else {
Fragment::new(self, node)
};
- let mut fragments = InlineFragments::new();
- fragments.push(&mut fragment);
+ let mut fragments = DList::new();
+ fragments.push(fragment);
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
splits: Vec::new(),
@@ -695,14 +708,14 @@ impl<'a> FlowConstructor<'a> {
};
let fragment_info = InlineBlockFragment(InlineBlockFragmentInfo::new(block_flow));
- let mut fragment = Fragment::new_from_specific_info(node, fragment_info);
+ let fragment = Fragment::new_from_specific_info(node, fragment_info);
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
- fragment_accumulator.fragments.push(&mut fragment);
+ fragment_accumulator.fragments.push(fragment);
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
splits: Vec::new(),
- fragments: fragment_accumulator.finish(),
+ fragments: fragment_accumulator.to_dlist(),
abs_descendants: abs_descendants,
});
ConstructionItemConstructionResult(construction_item)
@@ -720,14 +733,14 @@ impl<'a> FlowConstructor<'a> {
let fragment_info = InlineAbsoluteHypotheticalFragment(
InlineAbsoluteHypotheticalFragmentInfo::new(block_flow));
- let mut fragment = Fragment::new_from_specific_info(node, fragment_info);
+ let fragment = Fragment::new_from_specific_info(node, fragment_info);
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
- fragment_accumulator.fragments.push(&mut fragment);
+ fragment_accumulator.fragments.push(fragment);
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
splits: Vec::new(),
- fragments: fragment_accumulator.finish(),
+ fragments: fragment_accumulator.to_dlist(),
abs_descendants: abs_descendants,
});
ConstructionItemConstructionResult(construction_item)
@@ -1217,3 +1230,38 @@ impl FlowConstructionUtils for FlowRef {
}
}
}
+
+/// Strips ignorable whitespace from the start of a list of fragments.
+///
+/// Returns some damage that must be added to the `InlineFlow`.
+pub fn strip_ignorable_whitespace_from_start(this: &mut DList<Fragment>) -> RestyleDamage {
+ if this.is_empty() {
+ return RestyleDamage::empty() // Fast path.
+ }
+
+ let mut damage = RestyleDamage::empty();
+ while !this.is_empty() && this.front().as_ref().unwrap().is_ignorable_whitespace() {
+ debug!("stripping ignorable whitespace from start");
+ damage = RestyleDamage::all();
+ drop(this.pop_front());
+ }
+ damage
+}
+
+/// Strips ignorable whitespace from the end of a list of fragments.
+///
+/// Returns some damage that must be added to the `InlineFlow`.
+pub fn strip_ignorable_whitespace_from_end(this: &mut DList<Fragment>) -> RestyleDamage {
+ if this.is_empty() {
+ return RestyleDamage::empty();
+ }
+
+ let mut damage = RestyleDamage::empty();
+ while !this.is_empty() && this.back().as_ref().unwrap().is_ignorable_whitespace() {
+ debug!("stripping ignorable whitespace from end");
+ damage = RestyleDamage::all();
+ drop(this.pop());
+ }
+ damage
+}
+
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index aa434d63b1e..269aac1b81d 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -1022,7 +1022,7 @@ impl<'a> ImmutableFlowUtils for &'a Flow + 'a {
indent.push_str("| ")
}
- error!("{}+ {}", indent, self.to_string());
+ println!("{}+ {}", indent, self.to_string());
for kid in imm_child_iter(self) {
kid.dump_with_level(level + 1)
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 56b14754ca6..80d6c68be2a 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -42,6 +42,7 @@ use servo_net::local_image_cache::LocalImageCache;
use servo_util::geometry::{Au, ZERO_RECT};
use servo_util::geometry;
use servo_util::logical_geometry::{LogicalRect, LogicalSize, LogicalMargin, WritingMode};
+use servo_util::opts;
use servo_util::range::*;
use servo_util::smallvec::SmallVec;
use servo_util::str::is_whitespace;
@@ -386,7 +387,8 @@ pub struct ScannedTextFragmentInfo {
impl ScannedTextFragmentInfo {
/// Creates the information specific to a scanned text fragment from a range and a text run.
- pub fn new(run: Arc<Box<TextRun>>, range: Range<CharIndex>, content_inline_size: Au) -> ScannedTextFragmentInfo {
+ pub fn new(run: Arc<Box<TextRun>>, range: Range<CharIndex>, content_inline_size: Au)
+ -> ScannedTextFragmentInfo {
ScannedTextFragmentInfo {
run: run,
range: range,
@@ -509,7 +511,9 @@ impl Fragment {
}
/// Constructs a new `Fragment` instance for an anonymous table object.
- pub fn new_anonymous_table_fragment(node: &ThreadSafeLayoutNode, specific: SpecificFragmentInfo) -> Fragment {
+ pub fn new_anonymous_table_fragment(node: &ThreadSafeLayoutNode,
+ specific: SpecificFragmentInfo)
+ -> Fragment {
// CSS 2.1 § 17.2.1 This is for non-inherited properties on anonymous table fragments
// example:
//
@@ -517,7 +521,8 @@ impl Fragment {
// Foo
// </div>
//
- // Anonymous table fragments, TableRowFragment and TableCellFragment, are generated around `Foo`, but it shouldn't inherit the border.
+ // Anonymous table fragments, TableRowFragment and TableCellFragment, are generated around
+ // `Foo`, but they shouldn't inherit the border.
let node_style = cascade_anonymous(&**node.style());
let writing_mode = node_style.writing_mode;
@@ -587,14 +592,14 @@ impl Fragment {
}
}
- /// Returns a debug ID of this fragment. This ID should not be considered stable across multiple
- /// layouts or fragment manipulations.
+ /// Returns a debug ID of this fragment. This ID should not be considered stable across
+ /// multiple layouts or fragment manipulations.
pub fn debug_id(&self) -> uint {
self.debug_id
}
- /// Transforms this fragment into another fragment of the given type, with the given size, preserving all
- /// the other data.
+ /// Transforms this fragment into another fragment of the given type, with the given size,
+ /// preserving all the other data.
pub fn transform(&self, size: LogicalSize<Au>, mut info: ScannedTextFragmentInfo) -> Fragment {
let new_border_box =
LogicalRect::from_point_size(self.style.writing_mode, self.border_box.start, size);
@@ -1335,24 +1340,21 @@ impl Fragment {
});
}
- // Draw debug frames for text bounds.
- //
- // FIXME(#2263, pcwalton): This is a bit of an abuse of the logging infrastructure.
- // We should have a real `SERVO_DEBUG` system.
- debug!("{:?}", self.build_debug_borders_around_text_fragments(display_list,
- flow_origin,
- text_fragment,
- clip_rect))
+ if opts::get().show_debug_fragment_borders {
+ self.build_debug_borders_around_text_fragments(display_list,
+ flow_origin,
+ text_fragment,
+ clip_rect);
+ }
}
GenericFragment | IframeFragment(..) | TableFragment | TableCellFragment |
TableRowFragment | TableWrapperFragment | InlineBlockFragment(_) | InputFragment |
InlineAbsoluteHypotheticalFragment(_) => {
- // FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
- // should have a real `SERVO_DEBUG` system.
- debug!("{:?}",
- self.build_debug_borders_around_fragment(display_list,
- flow_origin,
- clip_rect))
+ if opts::get().show_debug_fragment_borders {
+ self.build_debug_borders_around_fragment(display_list,
+ flow_origin,
+ clip_rect);
+ }
}
ImageFragment(ref mut image_fragment) => {
let image_ref = &mut image_fragment.image;
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index 0babaa46234..bdfc9474fe7 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -11,7 +11,6 @@ use flow::{BaseFlow, FlowClass, Flow, InlineFlowClass, MutableFlowUtils};
use flow;
use fragment::{Fragment, InlineAbsoluteHypotheticalFragment, InlineBlockFragment};
use fragment::{ScannedTextFragment, ScannedTextFragmentInfo, SplitInfo};
-use incremental::RestyleDamage;
use layout_debug;
use model::IntrinsicISizesContribution;
use text;
@@ -620,57 +619,6 @@ impl InlineFragments {
self.fragments.get_mut(index)
}
- /// Strips ignorable whitespace from the start of a list of fragments.
- ///
- /// Returns some damage that must be added to the `InlineFlow`.
- pub fn strip_ignorable_whitespace_from_start(&mut self) -> RestyleDamage {
- if self.is_empty() { return RestyleDamage::empty() } // Fast path
-
- // FIXME (rust#16151): This can be reverted back to using skip_while once
- // the upstream bug is fixed.
- let mut fragments = mem::replace(&mut self.fragments, vec![]).into_iter();
- let mut new_fragments = Vec::new();
- let mut skipping = true;
- let mut damage = RestyleDamage::empty();
-
- for fragment in fragments {
- if skipping && fragment.is_ignorable_whitespace() {
- damage = RestyleDamage::all();
- debug!("stripping ignorable whitespace from start");
- continue
- }
-
- skipping = false;
- new_fragments.push(fragment);
- }
-
- self.fragments = new_fragments;
- damage
- }
-
- /// Strips ignorable whitespace from the end of a list of fragments.
- ///
- /// Returns some damage that must be added to the `InlineFlow`.
- pub fn strip_ignorable_whitespace_from_end(&mut self) -> RestyleDamage {
- if self.is_empty() {
- return RestyleDamage::empty();
- }
-
- let mut damage = RestyleDamage::empty();
-
- let mut new_fragments = self.fragments.clone();
- while new_fragments.len() > 0 &&
- new_fragments.as_slice().last().as_ref().unwrap().is_ignorable_whitespace() {
- debug!("stripping ignorable whitespace from end");
- damage = RestyleDamage::all();
- drop(new_fragments.pop());
- }
-
-
- self.fragments = new_fragments;
- damage
- }
-
/// This function merges previously-line-broken fragments back into their
/// original, pre-line-breaking form.
pub fn merge_broken_lines(&mut self) {
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs
index fbd840fdd9c..114f9b85e84 100644
--- a/components/layout/layout_task.rs
+++ b/components/layout/layout_task.rs
@@ -580,7 +580,7 @@ impl LayoutTask {
let current_screen_size = Size2D(Au::from_frac32_px(viewport_size.width.get()),
Au::from_frac32_px(viewport_size.height.get()));
- let old_screen_size = mem::replace(&mut rw_data.screen_size, current_screen_size);
+ rw_data.screen_size = current_screen_size;
// Create a layout context for use throughout the following passes.
let mut shared_layout_ctx =
@@ -591,8 +591,6 @@ impl LayoutTask {
// Handle conditions where the entire flow tree is invalid.
let mut needs_dirtying = false;
-
- needs_dirtying |= current_screen_size != old_screen_size;
needs_dirtying |= rw_data.stylesheet_dirty;
unsafe {
diff --git a/components/layout/text.rs b/components/layout/text.rs
index 19338d4c021..da5fd549697 100644
--- a/components/layout/text.rs
+++ b/components/layout/text.rs
@@ -6,78 +6,67 @@
#![deny(unsafe_block)]
-use flow::Flow;
use fragment::{Fragment, ScannedTextFragmentInfo, UnscannedTextFragment};
+use inline::InlineFragments;
use gfx::font::{FontMetrics,RunMetrics};
use gfx::font_context::FontContext;
use gfx::text::glyph::CharIndex;
use gfx::text::text_run::TextRun;
-use gfx::text::util::{CompressWhitespaceNewline, transform_text, CompressNone};
+use gfx::text::util::{mod, CompressWhitespaceNewline, CompressNone};
+use servo_util::dlist;
use servo_util::geometry::Au;
use servo_util::logical_geometry::{LogicalSize, WritingMode};
use servo_util::range::Range;
-use servo_util::smallvec::SmallVec;
+use servo_util::smallvec::{SmallVec, SmallVec1};
+use std::collections::{DList, Deque};
+use std::mem;
use style::ComputedValues;
use style::computed_values::{line_height, text_orientation, white_space};
use style::style_structs::Font as FontStyle;
use sync::Arc;
-struct NewLinePositions {
- new_line_pos: Vec<CharIndex>,
-}
-
-// A helper function.
-fn can_coalesce_text_nodes(fragments: &[Fragment], left_i: uint, right_i: uint) -> bool {
- assert!(left_i != right_i);
- fragments[left_i].can_merge_with_fragment(&fragments[right_i])
-}
-
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextFragment`s.
pub struct TextRunScanner {
- pub clump: Range<CharIndex>,
+ pub clump: DList<Fragment>,
}
impl TextRunScanner {
pub fn new() -> TextRunScanner {
TextRunScanner {
- clump: Range::empty(),
+ clump: DList::new(),
}
}
- pub fn scan_for_runs(&mut self, font_context: &mut FontContext, flow: &mut Flow) {
- {
- let inline = flow.as_immutable_inline();
- debug!("TextRunScanner: scanning {:u} fragments for text runs...", inline.fragments.len());
- }
-
- let fragments = &mut flow.as_inline().fragments;
+ pub fn scan_for_runs(&mut self, font_context: &mut FontContext, mut fragments: DList<Fragment>)
+ -> InlineFragments {
+ debug!("TextRunScanner: scanning {:u} fragments for text runs...", fragments.len());
+ // FIXME(pcwalton): We want to be sure not to allocate multiple times, since this is a
+ // performance-critical spot, but this may overestimate and allocate too much memory.
+ let mut new_fragments = Vec::with_capacity(fragments.len());
let mut last_whitespace = true;
- let mut new_fragments = Vec::new();
- for fragment_i in range(0, fragments.fragments.len()) {
- debug!("TextRunScanner: considering fragment: {:u}", fragment_i);
- if fragment_i > 0 && !can_coalesce_text_nodes(fragments.fragments.as_slice(), fragment_i - 1, fragment_i) {
- last_whitespace = self.flush_clump_to_list(font_context,
- fragments.fragments.as_slice(),
- &mut new_fragments,
- last_whitespace);
+ while !fragments.is_empty() {
+ // Create a clump.
+ self.clump.append(dlist::split(&mut fragments));
+ while !fragments.is_empty() && self.clump
+ .back()
+ .unwrap()
+ .can_merge_with_fragment(fragments.front()
+ .unwrap()) {
+ self.clump.append(dlist::split(&mut fragments));
}
- self.clump.extend_by(CharIndex(1));
+ // Flush that clump to the list of fragments we're building up.
+ last_whitespace = self.flush_clump_to_list(font_context,
+ &mut new_fragments,
+ last_whitespace);
}
- // Handle remaining clumps.
- if self.clump.length() > CharIndex(0) {
- drop(self.flush_clump_to_list(font_context,
- fragments.fragments.as_slice(),
- &mut new_fragments,
- last_whitespace))
+ debug!("TextRunScanner: complete.");
+ InlineFragments {
+ fragments: new_fragments,
}
-
- debug!("TextRunScanner: swapping out fragments.");
-
- fragments.fragments = new_fragments;
}
/// A "clump" is a range of inline flow leaves that can be merged together into a single
@@ -86,178 +75,109 @@ impl TextRunScanner {
/// The flow keeps track of the fragments contained by all non-leaf DOM nodes. This is necessary
/// for correct painting order. Since we compress several leaf fragments here, the mapping must
/// be adjusted.
- ///
- /// FIXME(#2267, pcwalton): Stop cloning fragments. Instead we will need to replace each
- /// `in_fragment` with some smaller stub.
fn flush_clump_to_list(&mut self,
font_context: &mut FontContext,
- in_fragments: &[Fragment],
out_fragments: &mut Vec<Fragment>,
- last_whitespace: bool)
+ mut last_whitespace: bool)
-> bool {
- assert!(self.clump.length() > CharIndex(0));
-
- debug!("TextRunScanner: flushing fragments in range={}", self.clump);
- let is_singleton = self.clump.length() == CharIndex(1);
-
- let is_text_clump = match in_fragments[self.clump.begin().to_uint()].specific {
- UnscannedTextFragment(_) => true,
- _ => false,
- };
-
- let mut new_whitespace = last_whitespace;
- match (is_singleton, is_text_clump) {
- (false, false) => {
- fail!("WAT: can't coalesce non-text nodes in flush_clump_to_list()!")
+ debug!("TextRunScanner: flushing {} fragments in range", self.clump.len());
+
+ debug_assert!(!self.clump.is_empty());
+ match self.clump.front().unwrap().specific {
+ UnscannedTextFragment(_) => {}
+ _ => {
+ debug_assert!(self.clump.len() == 1,
+ "WAT: can't coalesce non-text nodes in flush_clump_to_list()!");
+ out_fragments.push(self.clump.pop_front().unwrap());
+ return last_whitespace
}
- (true, false) => {
- // FIXME(pcwalton): Stop cloning fragments, as above.
- debug!("TextRunScanner: pushing single non-text fragment in range: {}", self.clump);
- let new_fragment = in_fragments[self.clump.begin().to_uint()].clone();
- out_fragments.push(new_fragment)
- },
- (true, true) => {
- let old_fragment = &in_fragments[self.clump.begin().to_uint()];
- let text = match old_fragment.specific {
- UnscannedTextFragment(ref text_fragment_info) => &text_fragment_info.text,
- _ => fail!("Expected an unscanned text fragment!"),
- };
-
- let font_style = old_fragment.style().get_font();
-
- let compression = match old_fragment.white_space() {
- white_space::normal | white_space::nowrap => CompressWhitespaceNewline,
- white_space::pre => CompressNone,
- };
-
- let mut new_line_pos = vec![];
-
- let (transformed_text, whitespace) = transform_text(text.as_slice(),
- compression,
- last_whitespace,
- &mut new_line_pos);
-
- new_whitespace = whitespace;
-
- if transformed_text.len() > 0 {
- // TODO(#177): Text run creation must account for the renderability of text by
- // font group fonts. This is probably achieved by creating the font group above
- // and then letting `FontGroup` decide which `Font` to stick into the text run.
- let fontgroup = font_context.get_layout_font_group_for_style(font_style);
- let run = box fontgroup.create_textrun(
- transformed_text.clone());
+ }
- debug!("TextRunScanner: pushing single text fragment in range: {} ({})",
- self.clump,
- *text);
- let range = Range::new(CharIndex(0), run.char_len());
- let new_metrics = run.metrics_for_range(&range);
- let bounding_box_size = bounding_box_for_run_metrics(
- &new_metrics, old_fragment.style.writing_mode);
- let new_text_fragment_info =
- ScannedTextFragmentInfo::new(Arc::new(run), range, old_fragment.border_box.size.inline);
- let mut new_fragment = old_fragment.transform(bounding_box_size, new_text_fragment_info);
- new_fragment.new_line_pos = new_line_pos;
- out_fragments.push(new_fragment)
- }
- },
- (false, true) => {
- // TODO(#177): Text run creation must account for the renderability of text by
- // font group fonts. This is probably achieved by creating the font group above
- // and then letting `FontGroup` decide which `Font` to stick into the text run.
- let in_fragment = &in_fragments[self.clump.begin().to_uint()];
+ // TODO(#177): Text run creation must account for the renderability of text by font group
+ // fonts. This is probably achieved by creating the font group above and then letting
+ // `FontGroup` decide which `Font` to stick into the text run.
+ //
+ // Concatenate all of the transformed strings together, saving the new character indices.
+ let mut new_ranges: SmallVec1<Range<CharIndex>> = SmallVec1::new();
+ let mut new_line_positions: SmallVec1<NewLinePositions> = SmallVec1::new();
+ let mut char_total = CharIndex(0);
+ let run = {
+ let fontgroup;
+ let compression;
+ {
+ let in_fragment = self.clump.front().unwrap();
let font_style = in_fragment.style().get_font();
- let fontgroup = font_context.get_layout_font_group_for_style(font_style);
-
- let compression = match in_fragment.white_space() {
+ fontgroup = font_context.get_layout_font_group_for_style(font_style);
+ compression = match in_fragment.white_space() {
white_space::normal | white_space::nowrap => CompressWhitespaceNewline,
white_space::pre => CompressNone,
- };
-
- let mut new_line_positions: Vec<NewLinePositions> = vec![];
-
- // First, transform/compress text of all the nodes.
- let mut last_whitespace_in_clump = new_whitespace;
- let transformed_strs: Vec<String> = Vec::from_fn(self.clump.length().to_uint(), |i| {
- let idx = CharIndex(i as int) + self.clump.begin();
- let in_fragment = match in_fragments[idx.to_uint()].specific {
- UnscannedTextFragment(ref text_fragment_info) => &text_fragment_info.text,
- _ => fail!("Expected an unscanned text fragment!"),
- };
-
- let mut new_line_pos = vec![];
-
- let (new_str, new_whitespace) = transform_text(in_fragment.as_slice(),
- compression,
- last_whitespace_in_clump,
- &mut new_line_pos);
- new_line_positions.push(NewLinePositions { new_line_pos: new_line_pos });
-
- last_whitespace_in_clump = new_whitespace;
- new_str
- });
- new_whitespace = last_whitespace_in_clump;
-
- // Next, concatenate all of the transformed strings together, saving the new
- // character indices.
- let mut run_str = String::new();
-
- let mut new_ranges: Vec<Range<CharIndex>> =
- Vec::with_capacity(transformed_strs.len());
-
- let mut char_total = CharIndex(0);
- for i in range(0, transformed_strs.len() as int) {
- let added_chars = CharIndex(transformed_strs[i as uint].as_slice().char_len() as int);
- new_ranges.push(Range::new(char_total, added_chars));
- run_str.push_str(transformed_strs[i as uint].as_slice());
- char_total = char_total + added_chars;
}
+ }
- // Now create the run.
- // TextRuns contain a cycle which is usually resolved by the teardown
- // sequence. If no clump takes ownership, however, it will leak.
- let clump = self.clump;
- let run = if clump.length() != CharIndex(0) && run_str.len() > 0 {
- Some(Arc::new(box TextRun::new(&mut *fontgroup.fonts.get(0).borrow_mut(),
- run_str.to_string())))
- } else {
- None
+ // First, transform/compress text of all the nodes.
+ let mut run_text = String::new();
+ for in_fragment in self.clump.iter() {
+ let in_fragment = match in_fragment.specific {
+ UnscannedTextFragment(ref text_fragment_info) => &text_fragment_info.text,
+ _ => fail!("Expected an unscanned text fragment!"),
};
- // Make new fragments with the run and adjusted text indices.
- debug!("TextRunScanner: pushing fragment(s) in range: {}", self.clump);
- for i in clump.each_index() {
- let logical_offset = i - self.clump.begin();
- let range = new_ranges[logical_offset.to_uint()];
- if range.length() == CharIndex(0) {
- debug!("Elided an `UnscannedTextFragment` because it was zero-length after \
- compression; {}", in_fragments[i.to_uint()]);
- continue
- }
+ let mut new_line_pos = Vec::new();
+ let old_length = CharIndex(run_text.as_slice().char_len() as int);
+ last_whitespace = util::transform_text(in_fragment.as_slice(),
+ compression,
+ last_whitespace,
+ &mut run_text,
+ &mut new_line_pos);
+ new_line_positions.push(NewLinePositions(new_line_pos));
+
+ let added_chars = CharIndex(run_text.as_slice().char_len() as int) - old_length;
+ new_ranges.push(Range::new(char_total, added_chars));
+ char_total = char_total + added_chars;
+ }
- let old_fragment = &in_fragments[i.to_uint()];
- let new_text_fragment_info =
- ScannedTextFragmentInfo::new(
- run.as_ref().unwrap().clone(),
- range,
- old_fragment.border_box.size.inline);
- let new_metrics = new_text_fragment_info.run.metrics_for_range(&range);
- let bounding_box_size = bounding_box_for_run_metrics(
- &new_metrics, old_fragment.style.writing_mode);
- let mut new_fragment = old_fragment.transform(bounding_box_size, new_text_fragment_info);
- new_fragment.new_line_pos = new_line_positions[logical_offset.to_uint()].new_line_pos.clone();
- out_fragments.push(new_fragment)
- }
+ // Now create the run.
+ //
+ // TextRuns contain a cycle which is usually resolved by the teardown sequence.
+ // If no clump takes ownership, however, it will leak.
+ if run_text.len() == 0 {
+ self.clump = DList::new();
+ return last_whitespace
+ }
+ Arc::new(box TextRun::new(&mut *fontgroup.fonts.get(0).borrow_mut(), run_text))
+ };
+
+ // Make new fragments with the run and adjusted text indices.
+ debug!("TextRunScanner: pushing {} fragment(s)", self.clump.len());
+ for (logical_offset, old_fragment) in
+ mem::replace(&mut self.clump, DList::new()).into_iter().enumerate() {
+ let range = *new_ranges.get(logical_offset);
+ if range.is_empty() {
+ debug!("Elided an `UnscannedTextFragment` because it was zero-length after \
+ compression; {}",
+ old_fragment);
+ continue
}
- } // End of match.
- let end = self.clump.end(); // FIXME: borrow checker workaround
- self.clump.reset(end, CharIndex(0));
+ let text_inline_size = old_fragment.border_box.size.inline;
+ let new_text_fragment_info =
+ ScannedTextFragmentInfo::new(run.clone(), range, text_inline_size);
+ let new_metrics = new_text_fragment_info.run.metrics_for_range(&range);
+ let bounding_box_size = bounding_box_for_run_metrics(&new_metrics,
+ old_fragment.style.writing_mode);
+ let mut new_fragment = old_fragment.transform(bounding_box_size,
+ new_text_fragment_info);
+ let &NewLinePositions(ref mut new_line_positions) =
+ new_line_positions.get_mut(logical_offset);
+ new_fragment.new_line_pos = mem::replace(new_line_positions, Vec::new());
+ out_fragments.push(new_fragment)
+ }
- new_whitespace
- } // End of `flush_clump_to_list`.
+ last_whitespace
+ }
}
+struct NewLinePositions(Vec<CharIndex>);
#[inline]
fn bounding_box_for_run_metrics(metrics: &RunMetrics, writing_mode: WritingMode)
@@ -303,3 +223,5 @@ pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) ->
line_height::Length(l) => l
}
}
+
+
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs
index c4085522692..3abc146e496 100644
--- a/components/layout/wrapper.rs
+++ b/components/layout/wrapper.rs
@@ -36,8 +36,9 @@ use util::{LayoutDataAccess, LayoutDataWrapper, PrivateLayoutData, OpaqueNodeMet
use gfx::display_list::OpaqueNode;
use script::dom::bindings::cell::{Ref, RefMut};
-use script::dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementCast, HTMLImageElementCast};
-use script::dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, TextCast};
+use script::dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementCast};
+use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementCast, HTMLInputElementCast};
+use script::dom::bindings::codegen::InheritTypes::{TextCast};
use script::dom::bindings::js::JS;
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId};
use script::dom::element::{HTMLLinkElementTypeId, LayoutElementHelpers, RawLayoutElementHelpers};
@@ -213,28 +214,36 @@ impl<'ln> LayoutNode<'ln> {
}
}
- /// Iterates over this node and all its descendants, in preorder.
- ///
- /// FIXME(pcwalton): Terribly inefficient. We should use parallelism.
pub fn traverse_preorder(self) -> LayoutTreeIterator<'ln> {
- let mut nodes = vec!();
- gather_layout_nodes(self, &mut nodes, false);
- LayoutTreeIterator::new(nodes)
+ LayoutTreeIterator::new(self)
+ }
+
+ fn last_child(self) -> Option<LayoutNode<'ln>> {
+ unsafe {
+ self.get_jsmanaged().last_child_ref().map(|node| self.new_with_this_lifetime(&node))
+ }
}
/// Returns an iterator over this node's children.
pub fn children(self) -> LayoutNodeChildrenIterator<'ln> {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.
- fn first_child<T: TLayoutNode>(this: &T) -> Option<T> {
+ fn first_child<T: TLayoutNode>(this: T) -> Option<T> {
this.first_child()
}
LayoutNodeChildrenIterator {
- current_node: first_child(&self),
+ current: first_child(self),
}
}
+ pub fn rev_children(self) -> LayoutNodeReverseChildrenIterator<'ln> {
+ LayoutNodeReverseChildrenIterator {
+ current: self.last_child()
+ }
+
+ }
+
pub unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> {
&self.node
}
@@ -290,6 +299,12 @@ impl<'ln> TNode<'ln, LayoutElement<'ln>> for LayoutNode<'ln> {
}
}
+ fn last_child(self) -> Option<LayoutNode<'ln>> {
+ unsafe {
+ self.node.last_child_ref().map(|node| self.new_with_this_lifetime(&node))
+ }
+ }
+
fn prev_sibling(self) -> Option<LayoutNode<'ln>> {
unsafe {
self.node.prev_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
@@ -389,59 +404,48 @@ impl<'ln> TNode<'ln, LayoutElement<'ln>> for LayoutNode<'ln> {
}
pub struct LayoutNodeChildrenIterator<'a> {
- current_node: Option<LayoutNode<'a>>,
+ current: Option<LayoutNode<'a>>,
}
impl<'a> Iterator<LayoutNode<'a>> for LayoutNodeChildrenIterator<'a> {
fn next(&mut self) -> Option<LayoutNode<'a>> {
- let node = self.current_node.clone();
- self.current_node = node.clone().and_then(|node| {
- node.next_sibling()
- });
+ let node = self.current;
+ self.current = node.and_then(|node| node.next_sibling());
+ node
+ }
+}
+
+pub struct LayoutNodeReverseChildrenIterator<'a> {
+ current: Option<LayoutNode<'a>>,
+}
+
+impl<'a> Iterator<LayoutNode<'a>> for LayoutNodeReverseChildrenIterator<'a> {
+ fn next(&mut self) -> Option<LayoutNode<'a>> {
+ let node = self.current;
+ self.current = node.and_then(|node| node.prev_sibling());
node
}
}
-// FIXME: Do this without precomputing a vector of refs.
-// Easy for preorder; harder for postorder.
-//
-// FIXME(pcwalton): Parallelism! Eventually this should just be nuked.
pub struct LayoutTreeIterator<'a> {
- nodes: Vec<LayoutNode<'a>>,
- index: uint,
+ stack: Vec<LayoutNode<'a>>,
}
impl<'a> LayoutTreeIterator<'a> {
- fn new(nodes: Vec<LayoutNode<'a>>) -> LayoutTreeIterator<'a> {
+ fn new(root: LayoutNode<'a>) -> LayoutTreeIterator<'a> {
+ let mut stack = vec!();
+ stack.push(root);
LayoutTreeIterator {
- nodes: nodes,
- index: 0,
+ stack: stack
}
}
}
impl<'a> Iterator<LayoutNode<'a>> for LayoutTreeIterator<'a> {
fn next(&mut self) -> Option<LayoutNode<'a>> {
- if self.index >= self.nodes.len() {
- None
- } else {
- let v = self.nodes[self.index].clone();
- self.index += 1;
- Some(v)
- }
- }
-}
-
-/// FIXME(pcwalton): This is super inefficient.
-fn gather_layout_nodes<'a>(cur: LayoutNode<'a>, refs: &mut Vec<LayoutNode<'a>>, postorder: bool) {
- if !postorder {
- refs.push(cur.clone());
- }
- for kid in cur.children() {
- gather_layout_nodes(kid, refs, postorder)
- }
- if postorder {
- refs.push(cur.clone());
+ let ret = self.stack.pop();
+ ret.map(|node| self.stack.extend(node.rev_children()));
+ ret
}
}
@@ -498,6 +502,7 @@ impl<'le> TElement<'le> for LayoutElement<'le> {
}
}
+ #[inline]
fn get_hover_state(self) -> bool {
unsafe {
self.element.node().get_hover_state_for_layout()
@@ -511,18 +516,21 @@ impl<'le> TElement<'le> for LayoutElement<'le> {
}
}
+ #[inline]
fn get_disabled_state(self) -> bool {
unsafe {
self.element.node().get_disabled_state_for_layout()
}
}
+ #[inline]
fn get_enabled_state(self) -> bool {
unsafe {
self.element.node().get_enabled_state_for_layout()
}
}
+ #[inline]
fn has_class(self, name: &Atom) -> bool {
unsafe {
self.element.has_class_for_layout(name)
@@ -735,10 +743,12 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
}
}
+ #[inline]
pub fn get_pseudo_element_type(&self) -> PseudoElementType {
self.pseudo
}
+ #[inline]
pub fn get_normal_display(&self) -> display::T {
let mut layout_data_ref = self.mutate_layout_data();
let node_layout_data_wrapper = layout_data_ref.as_mut().unwrap();
@@ -746,6 +756,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
style.get_box().display
}
+ #[inline]
pub fn get_before_display(&self) -> display::T {
let mut layout_data_ref = self.mutate_layout_data();
let node_layout_data_wrapper = layout_data_ref.as_mut().unwrap();
@@ -753,6 +764,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
style.get_box().display
}
+ #[inline]
pub fn get_after_display(&self) -> display::T {
let mut layout_data_ref = self.mutate_layout_data();
let node_layout_data_wrapper = layout_data_ref.as_mut().unwrap();
@@ -760,12 +772,14 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
style.get_box().display
}
+ #[inline]
pub fn has_before_pseudo(&self) -> bool {
let layout_data_wrapper = self.borrow_layout_data();
let layout_data_wrapper_ref = layout_data_wrapper.as_ref().unwrap();
layout_data_wrapper_ref.data.before_style.is_some()
}
+ #[inline]
pub fn has_after_pseudo(&self) -> bool {
let layout_data_wrapper = self.borrow_layout_data();
let layout_data_wrapper_ref = layout_data_wrapper.as_ref().unwrap();
diff --git a/components/net/image_cache_task.rs b/components/net/image_cache_task.rs
index e5fbf856fe7..878d6420c24 100644
--- a/components/net/image_cache_task.rs
+++ b/components/net/image_cache_task.rs
@@ -6,6 +6,7 @@ use image::base::{Image, load_from_memory};
use resource_task;
use resource_task::{LoadData, ResourceTask};
+use servo_util::taskpool::TaskPool;
use std::comm::{channel, Receiver, Sender};
use std::collections::hashmap::HashMap;
use std::mem::replace;
@@ -79,7 +80,7 @@ impl<E, S: Encoder<E>> Encodable<S, E> for ImageCacheTask {
type DecoderFactory = fn() -> (proc(&[u8]) : 'static -> Option<Image>);
impl ImageCacheTask {
- pub fn new(resource_task: ResourceTask) -> ImageCacheTask {
+ pub fn new(resource_task: ResourceTask, task_pool: TaskPool) -> ImageCacheTask {
let (chan, port) = channel();
let chan_clone = chan.clone();
@@ -90,7 +91,8 @@ impl ImageCacheTask {
chan: chan_clone,
state_map: HashMap::new(),
wait_map: HashMap::new(),
- need_exit: None
+ need_exit: None,
+ task_pool: task_pool,
};
cache.run();
});
@@ -100,11 +102,11 @@ impl ImageCacheTask {
}
}
- pub fn new_sync(resource_task: ResourceTask) -> ImageCacheTask {
+ pub fn new_sync(resource_task: ResourceTask, task_pool: TaskPool) -> ImageCacheTask {
let (chan, port) = channel();
spawn(proc() {
- let inner_cache = ImageCacheTask::new(resource_task);
+ let inner_cache = ImageCacheTask::new(resource_task, task_pool);
loop {
let msg: Msg = port.recv();
@@ -140,6 +142,7 @@ struct ImageCache {
/// List of clients waiting on a WaitForImage response
wait_map: HashMap<Url, Arc<Mutex<Vec<Sender<ImageResponseMsg>>>>>,
need_exit: Option<Sender<()>>,
+ task_pool: TaskPool,
}
#[deriving(Clone)]
@@ -314,7 +317,7 @@ impl ImageCache {
let to_cache = self.chan.clone();
let url_clone = url.clone();
- spawn(proc() {
+ self.task_pool.execute(proc() {
let url = url_clone;
debug!("image_cache_task: started image decode for {:s}", url.serialize());
let image = load_from_memory(data.as_slice());
@@ -493,6 +496,7 @@ mod tests {
use resource_task;
use resource_task::{ResourceTask, Metadata, start_sending};
use image::base::test_image_bin;
+ use servo_util::taskpool::TaskPool;
use std::comm;
use url::Url;
@@ -581,7 +585,7 @@ mod tests {
fn should_exit_on_request() {
let mock_resource_task = mock_resource_task(box DoesNothing);
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
image_cache_task.exit();
mock_resource_task.send(resource_task::Exit);
@@ -592,7 +596,7 @@ mod tests {
fn should_fail_if_unprefetched_image_is_requested() {
let mock_resource_task = mock_resource_task(box DoesNothing);
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
let (chan, port) = channel();
@@ -606,7 +610,7 @@ mod tests {
let mock_resource_task = mock_resource_task(box JustSendOK { url_requested_chan: url_requested_chan});
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
image_cache_task.send(Prefetch(url));
@@ -621,7 +625,7 @@ mod tests {
let mock_resource_task = mock_resource_task(box JustSendOK { url_requested_chan: url_requested_chan});
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
image_cache_task.send(Prefetch(url.clone()));
@@ -641,7 +645,7 @@ mod tests {
let mock_resource_task = mock_resource_task(box WaitSendTestImage{wait_port: wait_port});
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
image_cache_task.send(Prefetch(url.clone()));
@@ -658,7 +662,7 @@ mod tests {
fn should_return_decoded_image_data_if_data_has_arrived() {
let mock_resource_task = mock_resource_task(box SendTestImage);
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
let join_port = image_cache_task.wait_for_store();
@@ -684,7 +688,7 @@ mod tests {
fn should_return_decoded_image_data_for_multiple_requests() {
let mock_resource_task = mock_resource_task(box SendTestImage);
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
let join_port = image_cache_task.wait_for_store();
@@ -732,7 +736,7 @@ mod tests {
}
});
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
image_cache_task.send(Prefetch(url.clone()));
@@ -779,7 +783,7 @@ mod tests {
}
});
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
image_cache_task.send(Prefetch(url.clone()));
@@ -808,7 +812,7 @@ mod tests {
fn should_return_failed_if_image_bin_cannot_be_fetched() {
let mock_resource_task = mock_resource_task(box SendTestImageErr);
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
let join_port = image_cache_task.wait_for_store_prefetched();
@@ -834,7 +838,7 @@ mod tests {
fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_fetched() {
let mock_resource_task = mock_resource_task(box SendTestImageErr);
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
let join_port = image_cache_task.wait_for_store_prefetched();
@@ -868,7 +872,7 @@ mod tests {
fn should_return_failed_if_image_decode_fails() {
let mock_resource_task = mock_resource_task(box SendBogusImage);
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
let join_port = image_cache_task.wait_for_store();
@@ -896,7 +900,7 @@ mod tests {
fn should_return_image_on_wait_if_image_is_already_loaded() {
let mock_resource_task = mock_resource_task(box SendTestImage);
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
let join_port = image_cache_task.wait_for_store();
@@ -924,7 +928,7 @@ mod tests {
let mock_resource_task = mock_resource_task(box WaitSendTestImage {wait_port: wait_port});
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
image_cache_task.send(Prefetch(url.clone()));
@@ -950,7 +954,7 @@ mod tests {
let mock_resource_task = mock_resource_task(box WaitSendTestImageErr{wait_port: wait_port});
- let image_cache_task = ImageCacheTask::new(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
image_cache_task.send(Prefetch(url.clone()));
@@ -974,7 +978,7 @@ mod tests {
fn sync_cache_should_wait_for_images() {
let mock_resource_task = mock_resource_task(box SendTestImage);
- let image_cache_task = ImageCacheTask::new_sync(mock_resource_task.clone());
+ let image_cache_task = ImageCacheTask::new_sync(mock_resource_task.clone(), TaskPool::new(4));
let url = Url::parse("file:///").unwrap();
image_cache_task.send(Prefetch(url.clone()));
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 724f9423bb3..2743cf4b268 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -381,6 +381,7 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
pub trait NodeHelpers<'a> {
fn ancestors(self) -> AncestorIterator<'a>;
fn children(self) -> AbstractNodeChildrenIterator<'a>;
+ fn rev_children(self) -> ReverseChildrenIterator<'a>;
fn child_elements(self) -> ChildElementIterator<'a>;
fn following_siblings(self) -> AbstractNodeChildrenIterator<'a>;
fn is_in_doc(self) -> bool;
@@ -441,7 +442,6 @@ pub trait NodeHelpers<'a> {
fn debug_str(self) -> String;
fn traverse_preorder(self) -> TreeIterator<'a>;
- fn sequential_traverse_postorder(self) -> TreeIterator<'a>;
fn inclusively_following_siblings(self) -> AbstractNodeChildrenIterator<'a>;
fn to_trusted_node_address(self) -> TrustedNodeAddress;
@@ -658,21 +658,12 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
/// Iterates over this node and all its descendants, in preorder.
fn traverse_preorder(self) -> TreeIterator<'a> {
- let mut nodes = vec!();
- gather_abstract_nodes(self, &mut nodes, false);
- TreeIterator::new(nodes)
- }
-
- /// Iterates over this node and all its descendants, in postorder.
- fn sequential_traverse_postorder(self) -> TreeIterator<'a> {
- let mut nodes = vec!();
- gather_abstract_nodes(self, &mut nodes, true);
- TreeIterator::new(nodes)
+ TreeIterator::new(self)
}
fn inclusively_following_siblings(self) -> AbstractNodeChildrenIterator<'a> {
AbstractNodeChildrenIterator {
- current_node: Some(self.clone()),
+ current: Some(self.clone()),
}
}
@@ -682,7 +673,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
fn following_siblings(self) -> AbstractNodeChildrenIterator<'a> {
AbstractNodeChildrenIterator {
- current_node: self.next_sibling().root().map(|next| next.clone()),
+ current: self.next_sibling().root().map(|next| next.clone()),
}
}
@@ -774,7 +765,13 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
fn children(self) -> AbstractNodeChildrenIterator<'a> {
AbstractNodeChildrenIterator {
- current_node: self.first_child.get().map(|node| (*node.root()).clone()),
+ current: self.first_child.get().map(|node| (*node.root()).clone()),
+ }
+ }
+
+ fn rev_children(self) -> ReverseChildrenIterator<'a> {
+ ReverseChildrenIterator {
+ current: self.last_child.get().map(|node| *node.root().deref()),
}
}
@@ -974,15 +971,25 @@ pub type ChildElementIterator<'a> = Map<'a, JSRef<'a, Node>,
Filter<'a, JSRef<'a, Node>, AbstractNodeChildrenIterator<'a>>>;
pub struct AbstractNodeChildrenIterator<'a> {
- current_node: Option<JSRef<'a, Node>>,
+ current: Option<JSRef<'a, Node>>,
}
impl<'a> Iterator<JSRef<'a, Node>> for AbstractNodeChildrenIterator<'a> {
fn next(&mut self) -> Option<JSRef<'a, Node>> {
- let node = self.current_node.clone();
- self.current_node = node.clone().and_then(|node| {
- node.next_sibling().map(|node| (*node.root()).clone())
- });
+ let node = self.current;
+ self.current = node.and_then(|node| node.next_sibling().map(|node| *node.root().deref()));
+ node
+ }
+}
+
+pub struct ReverseChildrenIterator<'a> {
+ current: Option<JSRef<'a, Node>>,
+}
+
+impl<'a> Iterator<JSRef<'a, Node>> for ReverseChildrenIterator<'a> {
+ fn next(&mut self) -> Option<JSRef<'a, Node>> {
+ let node = self.current;
+ self.current = node.and_then(|node| node.prev_sibling().map(|node| *node.root().deref()));
node
}
}
@@ -993,43 +1000,32 @@ pub struct AncestorIterator<'a> {
impl<'a> Iterator<JSRef<'a, Node>> for AncestorIterator<'a> {
fn next(&mut self) -> Option<JSRef<'a, Node>> {
- if self.current.is_none() {
- return None;
- }
-
- // FIXME: Do we need two clones here?
- let x = self.current.as_ref().unwrap().clone();
- self.current = x.parent_node().map(|node| (*node.root()).clone());
- Some(x)
+ let node = self.current;
+ self.current = node.and_then(|node| node.parent_node().map(|node| *node.root().deref()));
+ node
}
}
-// FIXME: Do this without precomputing a vector of refs.
-// Easy for preorder; harder for postorder.
pub struct TreeIterator<'a> {
- nodes: Vec<JSRef<'a, Node>>,
- index: uint,
+ stack: Vec<JSRef<'a, Node>>,
}
impl<'a> TreeIterator<'a> {
- fn new(nodes: Vec<JSRef<'a, Node>>) -> TreeIterator<'a> {
+ fn new(root: JSRef<'a, Node>) -> TreeIterator<'a> {
+ let mut stack = vec!();
+ stack.push(root);
+
TreeIterator {
- nodes: nodes,
- index: 0,
+ stack: stack,
}
}
}
impl<'a> Iterator<JSRef<'a, Node>> for TreeIterator<'a> {
fn next(&mut self) -> Option<JSRef<'a, Node>> {
- if self.index >= self.nodes.len() {
- None
- } else {
- let v = self.nodes[self.index];
- let v = v.clone();
- self.index += 1;
- Some(v)
- }
+ let ret = self.stack.pop();
+ ret.map(|node| self.stack.extend(node.rev_children()));
+ ret
}
}
@@ -1116,18 +1112,6 @@ impl<'a> Iterator<JSRef<'a, Node>> for NodeIterator {
}
}
-fn gather_abstract_nodes<'a>(cur: JSRef<'a, Node>, refs: &mut Vec<JSRef<'a, Node>>, postorder: bool) {
- if !postorder {
- refs.push(cur.clone());
- }
- for kid in cur.children() {
- gather_abstract_nodes(kid, refs, postorder)
- }
- if postorder {
- refs.push(cur.clone());
- }
-}
-
/// Specifies whether children must be recursively cloned or not.
#[deriving(PartialEq)]
pub enum CloneChildrenFlag {
@@ -2209,6 +2193,16 @@ impl<'a> style::TNode<'a, JSRef<'a, Element>> for JSRef<'a, Node> {
first_child(self).map(|node| *node.root())
}
+ fn last_child(self) -> Option<JSRef<'a, Node>> {
+ // FIXME(zwarich): Remove this when UFCS lands and there is a better way
+ // of disambiguating methods.
+ fn last_child<'a, T: NodeHelpers<'a>>(this: T) -> Option<Temporary<Node>> {
+ this.last_child()
+ }
+
+ last_child(self).map(|node| *node.root())
+ }
+
fn prev_sibling(self) -> Option<JSRef<'a, Node>> {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.
diff --git a/components/style/node.rs b/components/style/node.rs
index ea0d8a614c0..cebac4bd6f8 100644
--- a/components/style/node.rs
+++ b/components/style/node.rs
@@ -13,6 +13,7 @@ use string_cache::{Atom, Namespace};
pub trait TNode<'a, E: TElement<'a>> : Clone + Copy {
fn parent_node(self) -> Option<Self>;
fn first_child(self) -> Option<Self>;
+ fn last_child(self) -> Option<Self>;
fn prev_sibling(self) -> Option<Self>;
fn next_sibling(self) -> Option<Self>;
fn is_document(self) -> bool;
@@ -57,4 +58,3 @@ pub trait TElementAttributes : Copy {
fn get_length_attribute(self, attribute: LengthAttribute) -> LengthOrPercentageOrAuto;
fn get_integer_attribute(self, attribute: IntegerAttribute) -> Option<i32>;
}
-
diff --git a/components/util/cache.rs b/components/util/cache.rs
index dd45ee98cc0..19f861a1d3c 100644
--- a/components/util/cache.rs
+++ b/components/util/cache.rs
@@ -49,6 +49,13 @@ impl<K: Clone + PartialEq + Eq + Hash, V: Clone> Cache<K,V> for HashCache<K,V> {
fn evict_all(&mut self) {
self.entries.clear();
}
+
+}
+
+impl<K,V> HashCache<K,V> where K: Clone + PartialEq + Eq + Hash, V: Clone {
+ pub fn find_equiv<'a,Q>(&'a self, key: &Q) -> Option<&'a V> where Q: Hash + Equiv<K> {
+ self.entries.find_equiv(key)
+ }
}
#[test]
diff --git a/components/util/dlist.rs b/components/util/dlist.rs
new file mode 100644
index 00000000000..14a1b5d4cdf
--- /dev/null
+++ b/components/util/dlist.rs
@@ -0,0 +1,68 @@
+/* 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/. */
+
+//! Utility functions for doubly-linked lists.
+
+use std::collections::DList;
+use std::mem;
+use std::ptr;
+
+struct RawDList<T> {
+ length: uint,
+ head: Option<Box<RawNode<T>>>,
+ tail: *mut RawNode<T>,
+}
+
+#[allow(dead_code)]
+struct RawNode<T> {
+ next: Option<Box<RawNode<T>>>,
+ prev: *mut RawNode<T>,
+ value: T,
+}
+
+#[unsafe_destructor]
+impl<T> Drop for RawDList<T> {
+ fn drop(&mut self) {
+ fail!("shouldn't happen")
+ }
+}
+
+/// Workaround for a missing method on Rust's `DList` type. Splits the head off a list in O(1)
+/// time.
+pub fn split<T>(list: &mut DList<T>) -> DList<T> {
+ let list = unsafe {
+ mem::transmute::<&mut DList<T>,&mut RawDList<T>>(list)
+ };
+
+ if list.length == 0 {
+ fail!("split_dlist(): empty list")
+ }
+ let mut head_node = mem::replace(&mut list.head, None);
+ let head_node_ptr: *mut RawNode<T> = &mut **head_node.as_mut().unwrap();
+ let mut head_list = RawDList {
+ length: 1,
+ head: head_node,
+ tail: head_node_ptr,
+ };
+ debug_assert!(list.head.is_none());
+ mem::swap(&mut head_list.head.as_mut().unwrap().next, &mut list.head);
+ debug_assert!(head_list.head.as_mut().unwrap().next.is_none());
+ debug_assert!(head_list.head.as_mut().unwrap().prev.is_null());
+ head_list.head.as_mut().unwrap().prev = ptr::null_mut();
+
+ list.length -= 1;
+ if list.length == 0 {
+ list.tail = ptr::null_mut()
+ } else {
+ if list.length == 1 {
+ list.tail = &mut **list.head.as_mut().unwrap() as *mut RawNode<T>
+ }
+ list.head.as_mut().unwrap().prev = ptr::null_mut()
+ }
+
+ unsafe {
+ mem::transmute::<RawDList<T>,DList<T>>(head_list)
+ }
+}
+
diff --git a/components/util/lib.rs b/components/util/lib.rs
index f5fd08dc24e..a53f3a1c3d9 100644
--- a/components/util/lib.rs
+++ b/components/util/lib.rs
@@ -36,6 +36,7 @@ use std::sync::Arc;
pub mod bloom;
pub mod cache;
pub mod debug_utils;
+pub mod dlist;
pub mod fnv;
pub mod geometry;
pub mod logical_geometry;
@@ -50,6 +51,7 @@ pub mod str;
pub mod task;
pub mod tid;
pub mod time;
+pub mod taskpool;
pub mod vec;
pub mod workqueue;
diff --git a/components/util/opts.rs b/components/util/opts.rs
index 86eb383cbc7..3805a03ec04 100644
--- a/components/util/opts.rs
+++ b/components/util/opts.rs
@@ -74,6 +74,9 @@ pub struct Opts {
/// debugging purposes (`--show-debug-borders`).
pub show_debug_borders: bool,
+ /// True if we should show borders on all fragments for debugging purposes (`--show-debug-fragment-borders`).
+ pub show_debug_fragment_borders: bool,
+
/// If set with --disable-text-aa, disable antialiasing on fonts. This is primarily useful for reftests
/// where pixel perfect results are required when using fonts such as the Ahem
/// font for layout tests.
@@ -140,6 +143,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
getopts::optflag("f", "hard-fail", "Exit on task failure instead of displaying about:failure"),
getopts::optflag("b", "bubble-widths", "Bubble intrinsic widths separately like other engines"),
getopts::optflag("", "show-debug-borders", "Show debugging borders on layers and tiles."),
+ getopts::optflag("", "show-debug-fragment-borders", "Show debugging borders on fragments."),
getopts::optflag("", "disable-text-aa", "Disable antialiasing for text rendering."),
getopts::optflag("", "trace-layout", "Write layout trace to external file for debugging."),
getopts::optflagopt("", "devtools", "Start remote devtools server on port", "6000"),
@@ -242,6 +246,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
hard_fail: opt_match.opt_present("f"),
bubble_inline_sizes_separately: bubble_inline_sizes_separately,
show_debug_borders: opt_match.opt_present("show-debug-borders"),
+ show_debug_fragment_borders: opt_match.opt_present("show-debug-fragment-borders"),
enable_text_antialiasing: !opt_match.opt_present("disable-text-aa"),
trace_layout: trace_layout,
devtools_port: devtools_port,
diff --git a/components/util/taskpool.rs b/components/util/taskpool.rs
new file mode 100644
index 00000000000..0a2fafb2ab3
--- /dev/null
+++ b/components/util/taskpool.rs
@@ -0,0 +1,53 @@
+/* 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/. */
+
+//! A load-balancing task pool.
+//!
+//! This differs in implementation from std::sync::TaskPool in that each job is
+//! up for grabs by any of the child tasks in the pool.
+//!
+
+//
+// This is based on the cargo task pool.
+// https://github.com/rust-lang/cargo/blob/master/src/cargo/util/pool.rs
+//
+// The only difference is that a normal channel is used instead of a sync_channel.
+//
+
+use std::sync::{Arc, Mutex};
+
+pub struct TaskPool {
+ tx: Sender<proc():Send>,
+}
+
+impl TaskPool {
+ pub fn new(tasks: uint) -> TaskPool {
+ assert!(tasks > 0);
+ let (tx, rx) = channel();
+
+ let state = Arc::new(Mutex::new(rx));
+
+ for _ in range(0, tasks) {
+ let state = state.clone();
+ spawn(proc() worker(&*state));
+ }
+
+ return TaskPool { tx: tx };
+
+ fn worker(rx: &Mutex<Receiver<proc():Send>>) {
+ loop {
+ let job = rx.lock().recv_opt();
+ match job {
+ Ok(job) => job(),
+ Err(..) => break,
+ }
+ }
+ }
+ }
+
+ pub fn execute(&self, job: proc():Send) {
+ self.tx.send(job);
+ }
+}
+
diff --git a/ports/android/glut_app/Cargo.lock b/ports/android/glut_app/Cargo.lock
index 5fad2d1bea9..ad9b312128a 100644
--- a/ports/android/glut_app/Cargo.lock
+++ b/ports/android/glut_app/Cargo.lock
@@ -28,7 +28,7 @@ source = "git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f2
dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"egl 0.1.0 (git+https://github.com/servo/rust-egl#88f2a13812ddbce2bf2317221663a61c31b3e220)",
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#90add8d65273c8a46aa16d73959e29a51d0c282d)",
@@ -59,7 +59,7 @@ dependencies = [
"alert 0.1.0 (git+https://github.com/servo/rust-alert#fdc24f13be8d8a2d15214ec228d166b3221b809e)",
"azure 0.1.0 (git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f20957dd112d)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"devtools 0.0.1",
"devtools_traits 0.0.1",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#90add8d65273c8a46aa16d73959e29a51d0c282d)",
@@ -91,7 +91,7 @@ dependencies = [
[[package]]
name = "core_text"
version = "0.1.0"
-source = "git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d"
+source = "git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e"
dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
@@ -100,7 +100,7 @@ dependencies = [
[[package]]
name = "cssparser"
version = "0.1.0"
-source = "git+https://github.com/servo/rust-cssparser#22146ce095cb62df39d459c3a79d1486041f96f6"
+source = "git+https://github.com/servo/rust-cssparser#7b0549a5d122135848b8813ec401112ab588063c"
dependencies = [
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#28eafb604a92c7786685b46c0fc02682ba3ab265)",
]
@@ -174,7 +174,7 @@ dependencies = [
"azure 0.1.0 (git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f20957dd112d)",
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"fontconfig 0.1.0 (git+https://github.com/servo/rust-fontconfig#b16c1e12ecb74b1e4e9a9b23c2b98580a34cf201)",
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#90add8d65273c8a46aa16d73959e29a51d0c282d)",
@@ -382,7 +382,7 @@ name = "script"
version = "0.0.1"
dependencies = [
"canvas 0.0.1",
- "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#22146ce095cb62df39d459c3a79d1486041f96f6)",
+ "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#7b0549a5d122135848b8813ec401112ab588063c)",
"devtools_traits 0.0.1",
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#28eafb604a92c7786685b46c0fc02682ba3ab265)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#90add8d65273c8a46aa16d73959e29a51d0c282d)",
@@ -469,7 +469,7 @@ dependencies = [
name = "style"
version = "0.0.1"
dependencies = [
- "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#22146ce095cb62df39d459c3a79d1486041f96f6)",
+ "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#7b0549a5d122135848b8813ec401112ab588063c)",
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#28eafb604a92c7786685b46c0fc02682ba3ab265)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#90add8d65273c8a46aa16d73959e29a51d0c282d)",
"lazy_static 0.1.0 (git+https://github.com/Kimundi/lazy-static.rs#e62a65372f1dd9019e37eb9381d819edff80e360)",
diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock
index 545b0c192b0..7a17c954194 100644
--- a/ports/cef/Cargo.lock
+++ b/ports/cef/Cargo.lock
@@ -4,7 +4,7 @@ version = "0.0.1"
dependencies = [
"azure 0.1.0 (git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f20957dd112d)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"devtools 0.0.1",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
"gfx 0.0.1",
@@ -40,7 +40,7 @@ source = "git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f2
dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"egl 0.1.0 (git+https://github.com/servo/rust-egl#88f2a13812ddbce2bf2317221663a61c31b3e220)",
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
@@ -71,7 +71,7 @@ dependencies = [
"alert 0.1.0 (git+https://github.com/servo/rust-alert#fdc24f13be8d8a2d15214ec228d166b3221b809e)",
"azure 0.1.0 (git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f20957dd112d)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"devtools 0.0.1",
"devtools_traits 0.0.1",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
@@ -103,7 +103,7 @@ dependencies = [
[[package]]
name = "core_text"
version = "0.1.0"
-source = "git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d"
+source = "git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e"
dependencies = [
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
@@ -112,7 +112,7 @@ dependencies = [
[[package]]
name = "cssparser"
version = "0.1.0"
-source = "git+https://github.com/servo/rust-cssparser#22146ce095cb62df39d459c3a79d1486041f96f6"
+source = "git+https://github.com/servo/rust-cssparser#7b0549a5d122135848b8813ec401112ab588063c"
dependencies = [
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#28eafb604a92c7786685b46c0fc02682ba3ab265)",
]
@@ -186,7 +186,7 @@ dependencies = [
"azure 0.1.0 (git+https://github.com/servo/rust-azure#b357751c04a89a87e6ef1f0cebe5f20957dd112d)",
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation#166a601ff3e0fc3a64ca1a9090d02c8d4f22b61a)",
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics#6a9919f8a912cc67571b891ba198d5325964a104)",
- "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#1ad11072b31657eeccaf4879c6e98723d488bd3d)",
+ "core_text 0.1.0 (git+https://github.com/servo/rust-core-text#967a97fa7e9ae47f96aee5e48f5fb0be1345d89e)",
"fontconfig 0.1.0 (git+https://github.com/servo/rust-fontconfig#b16c1e12ecb74b1e4e9a9b23c2b98580a34cf201)",
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype#0b03da276e4bdeae2300596dabc4ccb16733ad70)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
@@ -399,7 +399,7 @@ name = "script"
version = "0.0.1"
dependencies = [
"canvas 0.0.1",
- "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#22146ce095cb62df39d459c3a79d1486041f96f6)",
+ "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#7b0549a5d122135848b8813ec401112ab588063c)",
"devtools_traits 0.0.1",
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#28eafb604a92c7786685b46c0fc02682ba3ab265)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
@@ -487,7 +487,7 @@ dependencies = [
name = "style"
version = "0.0.1"
dependencies = [
- "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#22146ce095cb62df39d459c3a79d1486041f96f6)",
+ "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser#7b0549a5d122135848b8813ec401112ab588063c)",
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#28eafb604a92c7786685b46c0fc02682ba3ab265)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom#b001a76e907befaae1d0d6dd259418a22092da86)",
"lazy_static 0.1.0 (git+https://github.com/Kimundi/lazy-static.rs#e62a65372f1dd9019e37eb9381d819edff80e360)",
diff --git a/ports/cef/core.rs b/ports/cef/core.rs
index b427d8d85b7..cdde5e9a4bf 100644
--- a/ports/cef/core.rs
+++ b/ports/cef/core.rs
@@ -67,6 +67,7 @@ pub extern "C" fn cef_run_message_loop() {
hard_fail: false,
bubble_inline_sizes_separately: false,
show_debug_borders: false,
+ show_debug_fragment_borders: false,
enable_text_antialiasing: true,
trace_layout: false,
devtools_port: None,
diff --git a/src/lib.rs b/src/lib.rs
index 64411f478c8..43bb4760fda 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -51,6 +51,8 @@ use servo_util::time::TimeProfiler;
use servo_util::memory::MemoryProfiler;
#[cfg(not(test))]
use servo_util::opts;
+#[cfg(not(test))]
+use servo_util::taskpool::TaskPool;
#[cfg(not(test))]
use green::GreenTaskBuilder;
@@ -79,6 +81,7 @@ pub fn run<Window: WindowMethods>(window: Option<Rc<Window>>) {
});
let time_profiler_chan_clone = time_profiler_chan.clone();
+ let shared_task_pool = TaskPool::new(8);
let (result_chan, result_port) = channel();
TaskBuilder::new()
@@ -90,9 +93,9 @@ pub fn run<Window: WindowMethods>(window: Option<Rc<Window>>) {
// image load or we risk emitting an output file missing the
// image.
let image_cache_task = if opts.output_file.is_some() {
- ImageCacheTask::new_sync(resource_task.clone())
+ ImageCacheTask::new_sync(resource_task.clone(), shared_task_pool)
} else {
- ImageCacheTask::new(resource_task.clone())
+ ImageCacheTask::new(resource_task.clone(), shared_task_pool)
};
let font_cache_task = FontCacheTask::new(resource_task.clone());
let constellation_chan = Constellation::<layout::layout_task::LayoutTask,
diff --git a/tests/wpt/include.ini b/tests/wpt/include.ini
index bb34afa4482..55e1f50c925 100644
--- a/tests/wpt/include.ini
+++ b/tests/wpt/include.ini
@@ -77,3 +77,11 @@ skip: true
skip: true
[XMLHttpRequest]
skip: false
+[old-tests]
+ skip: true
+ [submission]
+ skip: true
+ [Opera]
+ skip: true
+ [script_scheduling]
+ skip: false
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/005.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/005.html.ini
new file mode 100644
index 00000000000..8b1d1c690e0
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/005.html.ini
@@ -0,0 +1,5 @@
+[005.html]
+ type: testharness
+ [ scheduler: document.write inline in markup ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/006.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/006.html.ini
new file mode 100644
index 00000000000..54af1212e5f
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/006.html.ini
@@ -0,0 +1,5 @@
+[006.html]
+ type: testharness
+ [ scheduler: document.write inline - multiple]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/007.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/007.html.ini
new file mode 100644
index 00000000000..7351254d579
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/007.html.ini
@@ -0,0 +1,5 @@
+[007.html]
+ type: testharness
+ [ scheduler: document.write external]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/008.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/008.html.ini
new file mode 100644
index 00000000000..f88a254e8ff
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/008.html.ini
@@ -0,0 +1,5 @@
+[008.html]
+ type: testharness
+ [ scheduler: document.write external - multiple]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/009.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/009.html.ini
new file mode 100644
index 00000000000..36a6b79c88f
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/009.html.ini
@@ -0,0 +1,5 @@
+[009.html]
+ type: testharness
+ [ scheduler: document.write external - multiple with doc.write]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/010.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/010.html.ini
new file mode 100644
index 00000000000..20732c52903
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/010.html.ini
@@ -0,0 +1,5 @@
+[010.html]
+ type: testharness
+ [ scheduler: document.write external + inline - multiple with doc.write]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/011.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/011.html.ini
new file mode 100644
index 00000000000..91ae46d456f
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/011.html.ini
@@ -0,0 +1,5 @@
+[011.html]
+ type: testharness
+ [ scheduler: document.write external + inline - multiple with doc.write + subsequent markup]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/012.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/012.html.ini
new file mode 100644
index 00000000000..97e1a8c2e66
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/012.html.ini
@@ -0,0 +1,5 @@
+[012.html]
+ type: testharness
+ [ scheduler: document.write external and onload events ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/013.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/013.html.ini
new file mode 100644
index 00000000000..ccb3f3090d7
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/013.html.ini
@@ -0,0 +1,5 @@
+[013.html]
+ type: testharness
+ [ scheduler: DOM added inline script earlier in document]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/015.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/015.html.ini
new file mode 100644
index 00000000000..0eb052e7dda
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/015.html.ini
@@ -0,0 +1,5 @@
+[015.html]
+ type: testharness
+ [ scheduler: DOM added inline+external+inline script earlier in document]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/015a.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/015a.html.ini
new file mode 100644
index 00000000000..f13a4ad5783
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/015a.html.ini
@@ -0,0 +1,5 @@
+[015a.html]
+ type: testharness
+ [ scheduler: DOM added inline+external+inline script earlier in document]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/016.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/016.html.ini
new file mode 100644
index 00000000000..bf00a2bf3f8
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/016.html.ini
@@ -0,0 +1,5 @@
+[016.html]
+ type: testharness
+ [ scheduler: DOM added inline script later in document]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/017.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/017.html.ini
new file mode 100644
index 00000000000..c53367410e5
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/017.html.ini
@@ -0,0 +1,5 @@
+[017.html]
+ type: testharness
+ [ scheduler: multiple DOM added scripts later in document]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/018.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/018.html.ini
new file mode 100644
index 00000000000..51779a58e20
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/018.html.ini
@@ -0,0 +1,5 @@
+[018.html]
+ type: testharness
+ [ scheduler: DOM added scripts and doc.write]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/019.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/019.html.ini
new file mode 100644
index 00000000000..d84f65ea52b
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/019.html.ini
@@ -0,0 +1,5 @@
+[019.html]
+ type: testharness
+ [ scheduler: DOM added scripts and event handling ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/020.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/020.html.ini
new file mode 100644
index 00000000000..5fe0007df72
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/020.html.ini
@@ -0,0 +1,5 @@
+[020.html]
+ type: testharness
+ [ scheduler: DOM added script with data: URL ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/022.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/022.html.ini
new file mode 100644
index 00000000000..86432e7f001
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/022.html.ini
@@ -0,0 +1,5 @@
+[022.html]
+ type: testharness
+ [ scheduler: DOM added script, late .src ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/023.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/023.html.ini
new file mode 100644
index 00000000000..f0fbd642ec7
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/023.html.ini
@@ -0,0 +1,6 @@
+[023.html]
+ type: testharness
+ expected: TIMEOUT
+ [ scheduler: DOM added script, even later .src ]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/024.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/024.html.ini
new file mode 100644
index 00000000000..34063b39d78
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/024.html.ini
@@ -0,0 +1,5 @@
+[024.html]
+ type: testharness
+ [ scheduler: DOM added script, .src set twice]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/025.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/025.html.ini
new file mode 100644
index 00000000000..4c6825d633a
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/025.html.ini
@@ -0,0 +1,5 @@
+[025.html]
+ type: testharness
+ [ scheduler: DOM added script, .src set on script with content]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/026.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/026.html.ini
new file mode 100644
index 00000000000..3d19bbb0ffd
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/026.html.ini
@@ -0,0 +1,5 @@
+[026.html]
+ type: testharness
+ [ scheduler: doc write added script, .src set later]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/027.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/027.html.ini
new file mode 100644
index 00000000000..754f603ba37
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/027.html.ini
@@ -0,0 +1,5 @@
+[027.html]
+ type: testharness
+ [ scheduler: doc write added script with content, .src set later]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/028.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/028.html.ini
new file mode 100644
index 00000000000..52f13d00053
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/028.html.ini
@@ -0,0 +1,5 @@
+[028.html]
+ type: testharness
+ [ scheduler: javascript: URL]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/029.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/029.html.ini
new file mode 100644
index 00000000000..a4e1f50fc71
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/029.html.ini
@@ -0,0 +1,5 @@
+[029.html]
+ type: testharness
+ [ scheduler: javascript: URL in HREF]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/030.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/030.html.ini
new file mode 100644
index 00000000000..3024520ff0f
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/030.html.ini
@@ -0,0 +1,3 @@
+[030.html]
+ type: testharness
+ disabled: flaky
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/031.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/031.html.ini
new file mode 100644
index 00000000000..3a3b16289bd
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/031.html.ini
@@ -0,0 +1,5 @@
+[031.html]
+ type: testharness
+ [ scheduler: focus and blur events]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/033.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/033.html.ini
new file mode 100644
index 00000000000..8a66ded9232
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/033.html.ini
@@ -0,0 +1,5 @@
+[033.html]
+ type: testharness
+ [ scheduler: innerHTML and scripts moved in DOM]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/034.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/034.html.ini
new file mode 100644
index 00000000000..b1b921d5860
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/034.html.ini
@@ -0,0 +1,5 @@
+[034.html]
+ type: testharness
+ [ scheduler: innerHTML adding frames with JS in]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/035.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/035.html.ini
new file mode 100644
index 00000000000..1f668433485
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/035.html.ini
@@ -0,0 +1,5 @@
+[035.html]
+ type: testharness
+ [ scheduler: innerHTML adding frames with JS in and moving scripts]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/036.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/036.html.ini
new file mode 100644
index 00000000000..f1f5fa4da38
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/036.html.ini
@@ -0,0 +1,5 @@
+[036.html]
+ type: testharness
+ [ scheduler: DOM cloning]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/037.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/037.html.ini
new file mode 100644
index 00000000000..52efbc68148
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/037.html.ini
@@ -0,0 +1,5 @@
+[037.html]
+ type: testharness
+ [ scheduler: DOM movement with appendChild, inline]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/038.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/038.html.ini
new file mode 100644
index 00000000000..174d761ea84
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/038.html.ini
@@ -0,0 +1,5 @@
+[038.html]
+ type: testharness
+ [ scheduler: DOM movement with appendChild, external]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/039.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/039.html.ini
new file mode 100644
index 00000000000..b4cf0682ffc
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/039.html.ini
@@ -0,0 +1,3 @@
+[039.html]
+ type: testharness
+ expected: CRASH
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/040.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/040.html.ini
new file mode 100644
index 00000000000..01208d5bb42
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/040.html.ini
@@ -0,0 +1,5 @@
+[040.html]
+ type: testharness
+ [ scheduler: IFRAMEs added with DOM (innerHTML), javascript: URL]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/041.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/041.html.ini
new file mode 100644
index 00000000000..1aa57a18d9c
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/041.html.ini
@@ -0,0 +1,5 @@
+[041.html]
+ type: testharness
+ [ scheduler: document.write scripts that write scripts]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/042.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/042.html.ini
new file mode 100644
index 00000000000..9a2d58fe39b
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/042.html.ini
@@ -0,0 +1,5 @@
+[042.html]
+ type: testharness
+ [ scheduler: DOM mutation events when adding scripts: DOMNodeInserted ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/043.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/043.html.ini
new file mode 100644
index 00000000000..be2fbd3b460
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/043.html.ini
@@ -0,0 +1,5 @@
+[043.html]
+ type: testharness
+ [ scheduler: DOM mutation events when adding external scripts: DOMNodeInserted ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/044.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/044.html.ini
new file mode 100644
index 00000000000..1e6f0d681d1
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/044.html.ini
@@ -0,0 +1,5 @@
+[044.html]
+ type: testharness
+ [ scheduler: DOM mutation events when adding scripts: DOMNodeInsertedIntoDocument ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/045.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/045.html.ini
new file mode 100644
index 00000000000..60286828854
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/045.html.ini
@@ -0,0 +1,5 @@
+[045.html]
+ type: testharness
+ [ scheduler: DOM mutation events when adding external scripts: DOMNodeInsertedIntoDocument ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/046.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/046.html.ini
new file mode 100644
index 00000000000..75d42b69a57
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/046.html.ini
@@ -0,0 +1,5 @@
+[046.html]
+ type: testharness
+ [ scheduler: no readystatechange events when adding external scripts ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/047.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/047.html.ini
new file mode 100644
index 00000000000..9c1ceeaa4d9
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/047.html.ini
@@ -0,0 +1,5 @@
+[047.html]
+ type: testharness
+ [ scheduler: adding and removing external script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/048.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/048.html.ini
new file mode 100644
index 00000000000..a62ede9a84a
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/048.html.ini
@@ -0,0 +1,5 @@
+[048.html]
+ type: testharness
+ [ scheduler: adding inline script which sets its own .src ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/049.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/049.html.ini
new file mode 100644
index 00000000000..fcc9435392a
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/049.html.ini
@@ -0,0 +1,5 @@
+[049.html]
+ type: testharness
+ [ scheduler: adding external script but removeAttribute( src ) before it runs]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/050.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/050.html.ini
new file mode 100644
index 00000000000..2bfc46d9285
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/050.html.ini
@@ -0,0 +1,5 @@
+[050.html]
+ type: testharness
+ [ scheduler: adding external script that removes all scripts from document]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/051.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/051.html.ini
new file mode 100644
index 00000000000..c524ee1bc17
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/051.html.ini
@@ -0,0 +1,5 @@
+[051.html]
+ type: testharness
+ [ scheduler: interaction of parsing and script execution - script added through DOM]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/052.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/052.html.ini
new file mode 100644
index 00000000000..ddda41aa5a3
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/052.html.ini
@@ -0,0 +1,5 @@
+[052.html]
+ type: testharness
+ [ scheduler: interaction of parsing and script execution - external script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/053.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/053.html.ini
new file mode 100644
index 00000000000..552647fe0a4
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/053.html.ini
@@ -0,0 +1,5 @@
+[053.html]
+ type: testharness
+ [ scheduler: adding external script that removes itself from document when loading]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/054.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/054.html.ini
new file mode 100644
index 00000000000..3e7b70542bf
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/054.html.ini
@@ -0,0 +1,5 @@
+[054.html]
+ type: testharness
+ [ scheduler: removing newly inserted script from DOMNodeInserted handler - external script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/055.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/055.html.ini
new file mode 100644
index 00000000000..9600b104f9d
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/055.html.ini
@@ -0,0 +1,5 @@
+[055.html]
+ type: testharness
+ [ scheduler: removing newly inserted script from DOMNodeInserted handler - inline script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/056.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/056.html.ini
new file mode 100644
index 00000000000..ef0e50bedb3
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/056.html.ini
@@ -0,0 +1,5 @@
+[056.html]
+ type: testharness
+ [ scheduler: appending code to initially empty SCRIPT tag in DOM ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/068.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/068.html.ini
new file mode 100644
index 00000000000..9cb8f043f41
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/068.html.ini
@@ -0,0 +1,3 @@
+[068.html]
+ type: testharness
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/069.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/069.html.ini
new file mode 100644
index 00000000000..c0a3251892a
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/069.html.ini
@@ -0,0 +1,6 @@
+[069.html]
+ type: testharness
+ expected: TIMEOUT
+ [scheduler: external files added through DOM should not block further parsing while loading]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/070.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/070.html.ini
new file mode 100644
index 00000000000..34774a78439
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/070.html.ini
@@ -0,0 +1,3 @@
+[070.html]
+ type: testharness
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/071.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/071.html.ini
new file mode 100644
index 00000000000..225469776b1
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/071.html.ini
@@ -0,0 +1,3 @@
+[071.html]
+ type: testharness
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/072.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/072.html.ini
new file mode 100644
index 00000000000..5ad9d625a46
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/072.html.ini
@@ -0,0 +1,3 @@
+[072.html]
+ type: testharness
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/073.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/073.html.ini
new file mode 100644
index 00000000000..537e3e7c333
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/073.html.ini
@@ -0,0 +1,3 @@
+[073.html]
+ type: testharness
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/074.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/074.html.ini
new file mode 100644
index 00000000000..a894f1b162c
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/074.html.ini
@@ -0,0 +1,3 @@
+[074.html]
+ type: testharness
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/075.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/075.html.ini
new file mode 100644
index 00000000000..bafaab9102f
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/075.html.ini
@@ -0,0 +1,5 @@
+[075.html]
+ type: testharness
+ [dispatchEvent from child frame during document.write :-o ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/076.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/076.html.ini
new file mode 100644
index 00000000000..6da81e6bb68
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/076.html.ini
@@ -0,0 +1,5 @@
+[076.html]
+ type: testharness
+ [ scheduler: adding and removing external and inline scripts ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/077.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/077.html.ini
new file mode 100644
index 00000000000..71077979c71
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/077.html.ini
@@ -0,0 +1,5 @@
+[077.html]
+ type: testharness
+ [ adding several types of scripts through the DOM and removing some of them confuses scheduler ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/078.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/078.html.ini
new file mode 100644
index 00000000000..6ce0192273a
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/078.html.ini
@@ -0,0 +1,5 @@
+[078.html]
+ type: testharness
+ [ adding several types of scripts through the DOM and removing some of them confuses scheduler (slow-loading scripts) ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/079.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/079.html.ini
new file mode 100644
index 00000000000..95f70e89e46
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/079.html.ini
@@ -0,0 +1,6 @@
+[079.html]
+ type: testharness
+ expected: TIMEOUT
+ [ setting location to javascript URL from event handler ]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/080.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/080.html.ini
new file mode 100644
index 00000000000..eec03d6e781
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/080.html.ini
@@ -0,0 +1,3 @@
+[080.html]
+ type: testharness
+ disabled: flaky
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/081.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/081.html.ini
new file mode 100644
index 00000000000..298e96afb43
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/081.html.ini
@@ -0,0 +1,5 @@
+[081.html]
+ type: testharness
+ [ scheduler: slow loading external script added with DOM (appendChild)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/082.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/082.html.ini
new file mode 100644
index 00000000000..8b8e5f9f8c4
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/082.html.ini
@@ -0,0 +1,5 @@
+[082.html]
+ type: testharness
+ [ scheduler: multiple slow loading external scripts added with DOM (appendChild)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/083.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/083.html.ini
new file mode 100644
index 00000000000..9272fa0716d
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/083.html.ini
@@ -0,0 +1,5 @@
+[083.html]
+ type: testharness
+ [ scheduler: event listener defined by script in a document in history]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/084.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/084.html.ini
new file mode 100644
index 00000000000..6268eb738fb
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/084.html.ini
@@ -0,0 +1,5 @@
+[084.html]
+ type: testharness
+ [ scheduler: event listener defined by script in a removed IFRAME]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/085.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/085.html.ini
new file mode 100644
index 00000000000..989c0d47974
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/085.html.ini
@@ -0,0 +1,5 @@
+[085.html]
+ type: testharness
+ [ scheduler: async script and slow-loading defer script]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/086.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/086.html.ini
new file mode 100644
index 00000000000..cd50dc032c5
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/086.html.ini
@@ -0,0 +1,5 @@
+[086.html]
+ type: testharness
+ [ scheduler: async script and slow-loading async script]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/088.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/088.html.ini
new file mode 100644
index 00000000000..aee34579ac2
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/088.html.ini
@@ -0,0 +1,5 @@
+[088.html]
+ type: testharness
+ [ scheduler: multiple scripts with defer and async attributes]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/091.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/091.html.ini
new file mode 100644
index 00000000000..0005354951a
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/091.html.ini
@@ -0,0 +1,5 @@
+[091.html]
+ type: testharness
+ [ scheduler: force-async off on non-parser-inserted script]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/092.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/092.html.ini
new file mode 100644
index 00000000000..53ace1e41ae
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/092.html.ini
@@ -0,0 +1,5 @@
+[092.html]
+ type: testharness
+ [ scheduler: defer script and slow-loading non-async external script]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/094.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/094.html.ini
new file mode 100644
index 00000000000..b89f6319d28
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/094.html.ini
@@ -0,0 +1,5 @@
+[094.html]
+ type: testharness
+ [ scheduler: parser-created defer script after document load]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/095.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/095.html.ini
new file mode 100644
index 00000000000..e932e6afebf
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/095.html.ini
@@ -0,0 +1,5 @@
+[095.html]
+ type: testharness
+ [ scheduler: slow-loading script added from defer blocking load event]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/096.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/096.html.ini
new file mode 100644
index 00000000000..7647c26e9f9
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/096.html.ini
@@ -0,0 +1,5 @@
+[096.html]
+ type: testharness
+ [ scheduler: defer script added from document.write relative to DOMContentLoaded]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/097.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/097.html.ini
new file mode 100644
index 00000000000..8bf7322803a
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/097.html.ini
@@ -0,0 +1,5 @@
+[097.html]
+ type: testharness
+ [ scheduler: slow-loading async script added from document.write]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/098.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/098.html.ini
new file mode 100644
index 00000000000..5b0aa1e5e0c
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/098.html.ini
@@ -0,0 +1,5 @@
+[098.html]
+ type: testharness
+ [ scheduler: defer script added from document.write]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/099.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/099.html.ini
new file mode 100644
index 00000000000..f6dd8734342
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/099.html.ini
@@ -0,0 +1,3 @@
+[099.html]
+ type: testharness
+ disabled: flaky
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/100.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/100.html.ini
new file mode 100644
index 00000000000..d0b686d15b6
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/100.html.ini
@@ -0,0 +1,5 @@
+[100.html]
+ type: testharness
+ [ scheduler: defer adding iframe containing script]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/101.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/101.html.ini
new file mode 100644
index 00000000000..19f83b1602e
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/101.html.ini
@@ -0,0 +1,5 @@
+[101.html]
+ type: testharness
+ [ scheduler: defer script after initial onload event]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/103.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/103.html.ini
new file mode 100644
index 00000000000..e14710c6d77
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/103.html.ini
@@ -0,0 +1,5 @@
+[103.html]
+ type: testharness
+ [ scheduler: removing defer attribute at runtime]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/104.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/104.html.ini
new file mode 100644
index 00000000000..7436c8d2d6c
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/104.html.ini
@@ -0,0 +1,5 @@
+[104.html]
+ type: testharness
+ [ scheduler: adding defer attribute at runtime]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/105.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/105.html.ini
new file mode 100644
index 00000000000..253a757e9a1
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/105.html.ini
@@ -0,0 +1,5 @@
+[105.html]
+ type: testharness
+ [ scheduler: adding async attribute at runtime]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/106.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/106.html.ini
new file mode 100644
index 00000000000..1c4607ae45a
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/106.html.ini
@@ -0,0 +1,5 @@
+[106.html]
+ type: testharness
+ [ scheduler: stylesheets blocking scripts]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/107.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/107.html.ini
new file mode 100644
index 00000000000..1ed3d334188
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/107.html.ini
@@ -0,0 +1,5 @@
+[107.html]
+ type: testharness
+ [ scheduler: stylesheets blocking scripts document.write]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/108.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/108.html.ini
new file mode 100644
index 00000000000..590c920a3d8
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/108.html.ini
@@ -0,0 +1,5 @@
+[108.html]
+ type: testharness
+ [ scheduler: javascript URL in iframe]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/109.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/109.html.ini
new file mode 100644
index 00000000000..1292ebc1fc4
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/109.html.ini
@@ -0,0 +1,5 @@
+[109.html]
+ type: testharness
+ [ scheduler: javascript URL in iframe, src set via DOM]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/110.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/110.html.ini
new file mode 100644
index 00000000000..6a6079d5481
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/110.html.ini
@@ -0,0 +1,5 @@
+[110.html]
+ type: testharness
+ [ scheduler: removing defer script at runtime]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/111.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/111.html.ini
new file mode 100644
index 00000000000..b48570d329b
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/111.html.ini
@@ -0,0 +1,5 @@
+[111.html]
+ type: testharness
+ [ scheduler: removing async attribute at runtime]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/116.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/116.html.ini
new file mode 100644
index 00000000000..adb954dc246
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/116.html.ini
@@ -0,0 +1,6 @@
+[116.html]
+ type: testharness
+ expected: TIMEOUT
+ [scheduler: adding script to head of frameset document]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/117.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/117.html.ini
new file mode 100644
index 00000000000..bb29063639b
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/117.html.ini
@@ -0,0 +1,5 @@
+[117.html]
+ type: testharness
+ [scheduler: inline script created with createContextualFragment]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/118.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/118.html.ini
new file mode 100644
index 00000000000..7d6683b9635
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/118.html.ini
@@ -0,0 +1,5 @@
+[118.html]
+ type: testharness
+ [scheduler: external script created with createContextualFragment]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/119.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/119.html.ini
new file mode 100644
index 00000000000..db2cb45f8db
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/119.html.ini
@@ -0,0 +1,5 @@
+[119.html]
+ type: testharness
+ [scheduler: external defer script created with createContextualFragment]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/120.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/120.html.ini
new file mode 100644
index 00000000000..522ce72d541
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/120.html.ini
@@ -0,0 +1,6 @@
+[120.html]
+ type: testharness
+ expected: TIMEOUT
+ [scheduler: script created without a window ]
+ expected: NOTRUN
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/122.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/122.html.ini
new file mode 100644
index 00000000000..941e581f20c
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/122.html.ini
@@ -0,0 +1,8 @@
+[122.html]
+ type: testharness
+ [scheduler: altering the type attribute and adding/removing external script ]
+ expected: FAIL
+
+ [Reinserted script async IDL attribute]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/123.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/123.html.ini
new file mode 100644
index 00000000000..cb08c989a08
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/123.html.ini
@@ -0,0 +1,5 @@
+[123.html]
+ type: testharness
+ [scheduler: altering the type attribute and adding/removing external script with async=false ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/124.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/124.html.ini
new file mode 100644
index 00000000000..99948245ba0
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/124.html.ini
@@ -0,0 +1,5 @@
+[124.html]
+ type: testharness
+ [scheduler: altering the type attribute and changing script data inline script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/125.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/125.html.ini
new file mode 100644
index 00000000000..e6269fe2954
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/125.html.ini
@@ -0,0 +1,5 @@
+[125.html]
+ type: testharness
+ [scheduler: altering the type attribute and changing script data external script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/126.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/126.html.ini
new file mode 100644
index 00000000000..f4bb635c593
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/126.html.ini
@@ -0,0 +1,5 @@
+[126.html]
+ type: testharness
+ [scheduler: altering the type attribute and changing script data external script async=false ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/127.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/127.html.ini
new file mode 100644
index 00000000000..803e846492f
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/127.html.ini
@@ -0,0 +1,5 @@
+[127.html]
+ type: testharness
+ [scheduler: appending non-text children to script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/128.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/128.html.ini
new file mode 100644
index 00000000000..c89e48eb931
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/128.html.ini
@@ -0,0 +1,5 @@
+[128.html]
+ type: testharness
+ [scheduler: appending script element to script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/129.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/129.html.ini
new file mode 100644
index 00000000000..e18cfba0012
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/129.html.ini
@@ -0,0 +1,5 @@
+[129.html]
+ type: testharness
+ [scheduler: appending multiple script elements]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/130.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/130.html.ini
new file mode 100644
index 00000000000..07a5de2740e
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/130.html.ini
@@ -0,0 +1,5 @@
+[130.html]
+ type: testharness
+ [scheduler: appending external script element to script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/132.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/132.html.ini
new file mode 100644
index 00000000000..e5c91b0e530
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/132.html.ini
@@ -0,0 +1,5 @@
+[132.html]
+ type: testharness
+ [scheduler: external svg script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/133.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/133.html.ini
new file mode 100644
index 00000000000..91c80df2d42
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/133.html.ini
@@ -0,0 +1,5 @@
+[133.html]
+ type: testharness
+ [scheduler: inline HTML script added by SVG script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/134.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/134.html.ini
new file mode 100644
index 00000000000..a01a182559d
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/134.html.ini
@@ -0,0 +1,5 @@
+[134.html]
+ type: testharness
+ [scheduler: external HTML script added by SVG script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/135.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/135.html.ini
new file mode 100644
index 00000000000..377501f7778
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/135.html.ini
@@ -0,0 +1,5 @@
+[135.html]
+ type: testharness
+ [scheduler: external SVG script added by SVG script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/136.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/136.html.ini
new file mode 100644
index 00000000000..1b004e27442
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/136.html.ini
@@ -0,0 +1,5 @@
+[136.html]
+ type: testharness
+ [scheduler: DOM added external SVG script, force-async? ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/137.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/137.html.ini
new file mode 100644
index 00000000000..60d25da62d0
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/137.html.ini
@@ -0,0 +1,5 @@
+[137.html]
+ type: testharness
+ [scheduler: SVG script empty xlink:href]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/138.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/138.html.ini
new file mode 100644
index 00000000000..9ed9fac3f38
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/138.html.ini
@@ -0,0 +1,5 @@
+[138.html]
+ type: testharness
+ [scheduler: SVG script nested inlines]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/139.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/139.html.ini
new file mode 100644
index 00000000000..e25521e5d78
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/139.html.ini
@@ -0,0 +1,5 @@
+[139.html]
+ type: testharness
+ [scheduler: SVG script nested external in inline]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/140.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/140.html.ini
new file mode 100644
index 00000000000..0adde53fa01
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/140.html.ini
@@ -0,0 +1,5 @@
+[140.html]
+ type: testharness
+ [scheduler: SVG script nested inline in external]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/141.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/141.html.ini
new file mode 100644
index 00000000000..3a624abf612
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/141.html.ini
@@ -0,0 +1,5 @@
+[141.html]
+ type: testharness
+ [scheduler: SVG inline script that document.writes inline script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/142.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/142.html.ini
new file mode 100644
index 00000000000..ccbb572791f
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/142.html.ini
@@ -0,0 +1,5 @@
+[142.html]
+ type: testharness
+ [scheduler: SVG inline script that document.writes external script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/143.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/143.html.ini
new file mode 100644
index 00000000000..7d5beedc6c0
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/143.html.ini
@@ -0,0 +1,5 @@
+[143.html]
+ type: testharness
+ [scheduler: SVG nested inline script that document.writes inline script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/144.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/144.html.ini
new file mode 100644
index 00000000000..3ecec584b46
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/144.html.ini
@@ -0,0 +1,5 @@
+[144.html]
+ type: testharness
+ [scheduler: SVG inline script changing the type attribute ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/145.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/145.html.ini
new file mode 100644
index 00000000000..b4836dc60d5
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/145.html.ini
@@ -0,0 +1,5 @@
+[145.html]
+ type: testharness
+ [scheduler: SVG inline script adding text to empty script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/146.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/146.html.ini
new file mode 100644
index 00000000000..c5cde10199c
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/146.html.ini
@@ -0,0 +1,5 @@
+[146.html]
+ type: testharness
+ [scheduler: SVG script adding src attribute ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/147.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/147.html.ini
new file mode 100644
index 00000000000..a25122a5700
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/147.html.ini
@@ -0,0 +1,5 @@
+[147.html]
+ type: testharness
+ [scheduler: insert multiple inline scripts; first script moves subsequent scripts ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/148.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/148.html.ini
new file mode 100644
index 00000000000..ba194bd5e8a
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/148.html.ini
@@ -0,0 +1,5 @@
+[148.html]
+ type: testharness
+ [scheduler: insert multiple inline scripts; first script deletes subsequent script ]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/149.html.ini b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/149.html.ini
new file mode 100644
index 00000000000..6169104f1ec
--- /dev/null
+++ b/tests/wpt/metadata/old-tests/submission/Opera/script_scheduling/149.html.ini
@@ -0,0 +1,20 @@
+[149.html]
+ type: testharness
+ [for=\'window\' event=\'onload()\' parser inserted executes immediately]
+ expected: FAIL
+
+ [for=\'window\' event=\'onload\' parser inserted executes immediately]
+ expected: FAIL
+
+ [for=\' WINdow\t\n\' event=\'ONload\t\n\' parser inserted executes immediately]
+ expected: FAIL
+
+ [for=\'window\' event=\'onload()\' dom inserted executes immediately]
+ expected: FAIL
+
+ [for=\'window\' event=\'onload\' dom inserted executes immediately]
+ expected: FAIL
+
+ [for=\' WINdow\t\n\' event=\'ONload\t\n\' dom inserted executes immediately]
+ expected: FAIL
+