Merge branch 'master' into bump-gecko-media

This commit is contained in:
Marcin Mielniczuk 2017-12-18 15:29:20 +01:00 committed by GitHub
commit b35c6bc14e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
131 changed files with 2480 additions and 1444 deletions

34
.taskcluster.yml Normal file
View file

@ -0,0 +1,34 @@
version: 0
metadata:
name: servo
description: >-
A modern, high-performance browser engine designed for both application
and embedded use.
owner: '{{ event.head.user.email }}'
source: '{{ event.head.repo.url }}'
tasks:
- provisionerId: '{{ taskcluster.docker.provisionerId }}'
workerType: '{{ taskcluster.docker.workerType }}'
extra:
github:
events: []
payload:
maxRunTime: 3600
image: servobrowser/servo-linux-dev
command:
- /bin/bash
- '--login'
- '-c'
- '-x'
- >-
git clone {{event.head.repo.url}} servo &&
cd servo &&
git config advice.detachedHead false &&
git checkout {{event.head.sha}} &&
etc/ci/taskcluster-test.sh
metadata:
name: linux-tests
description: Run Linux tests.
owner: '{{ event.head.user.email }}'
source: '{{ event.head.repo.url }}'

223
Cargo.lock generated
View file

@ -47,11 +47,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "app_units" name = "app_units"
version = "0.6.0" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -143,7 +143,7 @@ version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -204,7 +204,7 @@ version = "0.0.1"
dependencies = [ dependencies = [
"ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_config 0.0.1", "servo_config 0.0.1",
] ]
@ -287,8 +287,8 @@ dependencies = [
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"offscreen_gl_context 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "offscreen_gl_context 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1", "servo_config 0.0.1",
"webrender 0.56.0 (git+https://github.com/servo/webrender)", "webrender 0.56.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -303,9 +303,9 @@ dependencies = [
"malloc_size_of_derive 0.0.1", "malloc_size_of_derive 0.0.1",
"nonzero 0.0.1", "nonzero 0.0.1",
"offscreen_gl_context 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "offscreen_gl_context 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_config 0.0.1", "servo_config 0.0.1",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -324,7 +324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -358,6 +358,15 @@ dependencies = [
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "chrono"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "clang-sys" name = "clang-sys"
version = "0.21.1" version = "0.21.1"
@ -459,8 +468,8 @@ dependencies = [
"servo_url 0.0.1", "servo_url 0.0.1",
"style_traits 0.0.1", "style_traits 0.0.1",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender 0.56.0 (git+https://github.com/servo/webrender)", "webrender 0.56.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -491,13 +500,13 @@ dependencies = [
"net_traits 0.0.1", "net_traits 0.0.1",
"profile_traits 0.0.1", "profile_traits 0.0.1",
"script_traits 0.0.1", "script_traits 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_config 0.0.1", "servo_config 0.0.1",
"servo_rand 0.0.1", "servo_rand 0.0.1",
"servo_remutex 0.0.1", "servo_remutex 0.0.1",
"servo_url 0.0.1", "servo_url 0.0.1",
"style_traits 0.0.1", "style_traits 0.0.1",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
"webvr_traits 0.0.1", "webvr_traits 0.0.1",
] ]
@ -560,7 +569,7 @@ dependencies = [
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -704,7 +713,7 @@ dependencies = [
"ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1", "msg 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -720,7 +729,7 @@ dependencies = [
"malloc_size_of 0.0.1", "malloc_size_of 0.0.1",
"malloc_size_of_derive 0.0.1", "malloc_size_of_derive 0.0.1",
"msg 0.0.1", "msg 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_url 0.0.1", "servo_url 0.0.1",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -768,8 +777,8 @@ dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -799,7 +808,7 @@ dependencies = [
"servo_geometry 0.0.1", "servo_geometry 0.0.1",
"servo_url 0.0.1", "servo_url 0.0.1",
"style_traits 0.0.1", "style_traits 0.0.1",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -893,7 +902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -1049,7 +1058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "gfx" name = "gfx"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1072,7 +1081,7 @@ dependencies = [
"net_traits 0.0.1", "net_traits 0.0.1",
"ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"range 0.0.1", "range 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_allocator 0.0.1", "servo_allocator 0.0.1",
"servo_arc 0.0.1", "servo_arc 0.0.1",
@ -1087,7 +1096,7 @@ dependencies = [
"truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
"xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1109,7 +1118,7 @@ dependencies = [
"malloc_size_of 0.0.1", "malloc_size_of 0.0.1",
"malloc_size_of_derive 0.0.1", "malloc_size_of_derive 0.0.1",
"range 0.0.1", "range 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -1168,7 +1177,7 @@ dependencies = [
"servo_url 0.0.1", "servo_url 0.0.1",
"style_traits 0.0.1", "style_traits 0.0.1",
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1283,7 +1292,7 @@ dependencies = [
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1378,7 +1387,7 @@ dependencies = [
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1454,7 +1463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "layout" name = "layout"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas_traits 0.0.1", "canvas_traits 0.0.1",
@ -1477,7 +1486,7 @@ dependencies = [
"script_layout_interface 0.0.1", "script_layout_interface 0.0.1",
"script_traits 0.0.1", "script_traits 0.0.1",
"selectors 0.19.0", "selectors 0.19.0",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_arc 0.0.1", "servo_arc 0.0.1",
"servo_atoms 0.0.1", "servo_atoms 0.0.1",
@ -1489,7 +1498,7 @@ dependencies = [
"style_traits 0.0.1", "style_traits 0.0.1",
"unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -1504,7 +1513,7 @@ dependencies = [
name = "layout_thread" name = "layout_thread"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1539,7 +1548,7 @@ dependencies = [
"servo_url 0.0.1", "servo_url 0.0.1",
"style 0.0.1", "style 0.0.1",
"style_traits 0.0.1", "style_traits 0.0.1",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -1554,7 +1563,7 @@ dependencies = [
"profile_traits 0.0.1", "profile_traits 0.0.1",
"script_traits 0.0.1", "script_traits 0.0.1",
"servo_url 0.0.1", "servo_url 0.0.1",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -1635,8 +1644,8 @@ dependencies = [
"style 0.0.1", "style 0.0.1",
"style_traits 0.0.1", "style_traits 0.0.1",
"webdriver_server 0.0.1", "webdriver_server 0.0.1",
"webrender 0.56.0 (git+https://github.com/servo/webrender)", "webrender 0.56.1 (git+https://github.com/servo/webrender)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
"webvr 0.0.1", "webvr 0.0.1",
"webvr_traits 0.0.1", "webvr_traits 0.0.1",
] ]
@ -1679,7 +1688,7 @@ dependencies = [
name = "malloc_size_of" name = "malloc_size_of"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hashglobe 0.1.0", "hashglobe 0.1.0",
@ -1689,7 +1698,7 @@ dependencies = [
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
"xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1717,8 +1726,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1907,8 +1916,8 @@ dependencies = [
"malloc_size_of 0.0.1", "malloc_size_of 0.0.1",
"malloc_size_of_derive 0.0.1", "malloc_size_of_derive 0.0.1",
"nonzero 0.0.1", "nonzero 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -1942,7 +1951,7 @@ dependencies = [
"net_traits 0.0.1", "net_traits 0.0.1",
"openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
"profile_traits 0.0.1", "profile_traits 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-websocket 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "servo-websocket 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1", "servo_config 0.0.1",
@ -1953,7 +1962,7 @@ dependencies = [
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -2005,12 +2014,12 @@ dependencies = [
"malloc_size_of_derive 0.0.1", "malloc_size_of_derive 0.0.1",
"msg 0.0.1", "msg 0.0.1",
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_config 0.0.1", "servo_config 0.0.1",
"servo_url 0.0.1", "servo_url 0.0.1",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -2034,7 +2043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "nonzero" name = "nonzero"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -2044,6 +2053,16 @@ dependencies = [
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "num"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.34" version = "0.1.34"
@ -2126,7 +2145,7 @@ dependencies = [
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2327,7 +2346,7 @@ dependencies = [
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"profile_traits 0.0.1", "profile_traits 0.0.1",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1", "servo_config 0.0.1",
"task_info 0.0.1", "task_info 0.0.1",
@ -2352,7 +2371,7 @@ dependencies = [
"energymon 0.3.0 (git+https://github.com/energymon/energymon-rust.git)", "energymon 0.3.0 (git+https://github.com/energymon/energymon-rust.git)",
"ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_config 0.0.1", "servo_config 0.0.1",
"signpost 0.1.0 (git+https://github.com/pcwalton/signpost.git)", "signpost 0.1.0 (git+https://github.com/pcwalton/signpost.git)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2395,7 +2414,7 @@ dependencies = [
"malloc_size_of 0.0.1", "malloc_size_of 0.0.1",
"malloc_size_of_derive 0.0.1", "malloc_size_of_derive 0.0.1",
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -2478,8 +2497,8 @@ version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"android_injected_glue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "android_injected_glue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2530,7 +2549,7 @@ name = "script"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"angle 0.5.0 (git+https://github.com/servo/angle?branch=servo)", "angle 0.5.0 (git+https://github.com/servo/angle?branch=servo)",
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"audio-video-metadata 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "audio-video-metadata 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2538,6 +2557,7 @@ dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas_traits 0.0.1", "canvas_traits 0.0.1",
"caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2585,7 +2605,7 @@ dependencies = [
"script_plugins 0.0.1", "script_plugins 0.0.1",
"script_traits 0.0.1", "script_traits 0.0.1",
"selectors 0.19.0", "selectors 0.19.0",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_allocator 0.0.1", "servo_allocator 0.0.1",
"servo_arc 0.0.1", "servo_arc 0.0.1",
@ -2604,7 +2624,7 @@ dependencies = [
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "utf-8 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
"webvr_traits 0.0.1", "webvr_traits 0.0.1",
"xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2613,7 +2633,7 @@ dependencies = [
name = "script_layout_interface" name = "script_layout_interface"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas_traits 0.0.1", "canvas_traits 0.0.1",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2637,7 +2657,7 @@ dependencies = [
"servo_atoms 0.0.1", "servo_atoms 0.0.1",
"servo_url 0.0.1", "servo_url 0.0.1",
"style 0.0.1", "style 0.0.1",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -2682,13 +2702,13 @@ dependencies = [
"net_traits 0.0.1", "net_traits 0.0.1",
"profile_traits 0.0.1", "profile_traits 0.0.1",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_atoms 0.0.1", "servo_atoms 0.0.1",
"servo_url 0.0.1", "servo_url 0.0.1",
"style_traits 0.0.1", "style_traits 0.0.1",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
"webvr_traits 0.0.1", "webvr_traits 0.0.1",
] ]
@ -2731,10 +2751,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.14" version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/gankro/serde?branch=deserialize_from_enums3#fc6117367ef974fb2d3b2017c21c375d34823415"
dependencies = [ dependencies = [
"serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -2742,23 +2762,23 @@ name = "serde_bytes"
version = "0.10.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.14" version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/gankro/serde?branch=deserialize_from_enums3#fc6117367ef974fb2d3b2017c21c375d34823415"
dependencies = [ dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive_internals 0.17.0 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "serde_derive_internals" name = "serde_derive_internals"
version = "0.16.0" version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/gankro/serde?branch=deserialize_from_enums3#fc6117367ef974fb2d3b2017c21c375d34823415"
dependencies = [ dependencies = [
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2772,7 +2792,7 @@ dependencies = [
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -2900,7 +2920,7 @@ name = "servo_arc"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2924,7 +2944,7 @@ dependencies = [
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_geometry 0.0.1", "servo_geometry 0.0.1",
"servo_url 0.0.1", "servo_url 0.0.1",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2942,7 +2962,7 @@ dependencies = [
name = "servo_geometry" name = "servo_geometry"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of 0.0.1", "malloc_size_of 0.0.1",
"malloc_size_of_derive 0.0.1", "malloc_size_of_derive 0.0.1",
@ -2979,7 +2999,7 @@ version = "0.0.1"
dependencies = [ dependencies = [
"malloc_size_of 0.0.1", "malloc_size_of 0.0.1",
"malloc_size_of_derive 0.0.1", "malloc_size_of_derive 0.0.1",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_rand 0.0.1", "servo_rand 0.0.1",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3062,7 +3082,7 @@ dependencies = [
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -3092,7 +3112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "style" name = "style"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bindgen 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", "bindgen 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3125,7 +3145,7 @@ dependencies = [
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.19.0", "selectors 0.19.0",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_arc 0.0.1", "servo_arc 0.0.1",
"servo_atoms 0.0.1", "servo_atoms 0.0.1",
"servo_config 0.0.1", "servo_config 0.0.1",
@ -3156,7 +3176,7 @@ dependencies = [
name = "style_tests" name = "style_tests"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3178,17 +3198,17 @@ dependencies = [
name = "style_traits" name = "style_traits"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of 0.0.1", "malloc_size_of 0.0.1",
"malloc_size_of_derive 0.0.1", "malloc_size_of_derive 0.0.1",
"selectors 0.19.0", "selectors 0.19.0",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"servo_arc 0.0.1", "servo_arc 0.0.1",
"servo_atoms 0.0.1", "servo_atoms 0.0.1",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
@ -3344,7 +3364,7 @@ name = "toml"
version = "0.4.5" version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -3392,8 +3412,8 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -3447,7 +3467,7 @@ name = "url_serde"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -3479,7 +3499,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -3546,10 +3566,10 @@ dependencies = [
[[package]] [[package]]
name = "webrender" name = "webrender"
version = "0.56.0" version = "0.56.1"
source = "git+https://github.com/servo/webrender#0e80c9d04f84fd02de94bb61c5a5b4b5d16d94b5" source = "git+https://github.com/servo/webrender#67f7e0edeabba6861250922d47f8c6a1b2232d4b"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3569,15 +3589,15 @@ dependencies = [
"smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.56.0 (git+https://github.com/servo/webrender)", "webrender_api 0.56.1 (git+https://github.com/servo/webrender)",
] ]
[[package]] [[package]]
name = "webrender_api" name = "webrender_api"
version = "0.56.0" version = "0.56.1"
source = "git+https://github.com/servo/webrender#0e80c9d04f84fd02de94bb61c5a5b4b5d16d94b5" source = "git+https://github.com/servo/webrender#67f7e0edeabba6861250922d47f8c6a1b2232d4b"
dependencies = [ dependencies = [
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3586,7 +3606,8 @@ dependencies = [
"dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"serde_derive 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -3612,7 +3633,7 @@ dependencies = [
"ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1", "msg 0.0.1",
"rust-webvr-api 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "rust-webvr-api 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)",
] ]
[[package]] [[package]]
@ -3732,7 +3753,7 @@ dependencies = [
"checksum angle 0.5.0 (git+https://github.com/servo/angle?branch=servo)" = "<none>" "checksum angle 0.5.0 (git+https://github.com/servo/angle?branch=servo)" = "<none>"
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
"checksum app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29069a9b483f7780aebb55dafb360c6225eefdc1f98c8d336a65148fd10c37b1" "checksum app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4720c83543de184d9f6add2fdb8e8031543497b8506620884c16e125b493c09"
"checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2" "checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2"
"checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21" "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" "checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
@ -3763,6 +3784,7 @@ dependencies = [
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d" "checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86765cb42c2a2c497e142af72517c1b4d7ae5bb2f25dfa77a5c69642f2342d89" "checksum cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86765cb42c2a2c497e142af72517c1b4d7ae5bb2f25dfa77a5c69642f2342d89"
"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9"
"checksum clang-sys 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00048189ee171715296dfe3b2fcfd439563c7bfec0d98d3976ce3402d62c8f07" "checksum clang-sys 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00048189ee171715296dfe3b2fcfd439563c7bfec0d98d3976ce3402d62c8f07"
"checksum clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc34bf7d5d66268b466b9852bca925ec1d2650654dab4da081e63fd230145c2e" "checksum clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc34bf7d5d66268b466b9852bca925ec1d2650654dab4da081e63fd230145c2e"
"checksum clipboard 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd3a9a938558f33ec1baaa6ca631a69c104aafaacbc66868d9ad28cf5f30564f" "checksum clipboard 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd3a9a938558f33ec1baaa6ca631a69c104aafaacbc66868d9ad28cf5f30564f"
@ -3882,6 +3904,7 @@ dependencies = [
"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" "checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce" "checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40"
"checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37" "checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37"
"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44" "checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44"
@ -3938,10 +3961,10 @@ dependencies = [
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb6a7637a47663ee073391a139ed07851f27ed2532c2abc88c6bf27a16cdf34" "checksum serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)" = "<none>"
"checksum serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a73f5ad9bb83e1e407254c7a355f4efdaffe3c1442fc0657ddb8b9b6b225655" "checksum serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a73f5ad9bb83e1e407254c7a355f4efdaffe3c1442fc0657ddb8b9b6b225655"
"checksum serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "812ff66056fd9a9a5b7c119714243b0862cf98340e7d4b5ee05a932c40d5ea6c" "checksum serde_derive 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)" = "<none>"
"checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" "checksum serde_derive_internals 0.17.0 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)" = "<none>"
"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
"checksum servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21069a884c33fe6ee596975e1f3849ed88c4ec857fbaf11d33672d8ebe051217" "checksum servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21069a884c33fe6ee596975e1f3849ed88c4ec857fbaf11d33672d8ebe051217"
"checksum servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93f799b649b4a2bf362398910eca35240704c7e765e780349b2bb1070d892262" "checksum servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93f799b649b4a2bf362398910eca35240704c7e765e780349b2bb1070d892262"
@ -4005,8 +4028,8 @@ dependencies = [
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
"checksum webdriver 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6577005cf83a9df4ba39910f8baf3b835b5e4a0a5e9a0d71f3eceae6214ebf28" "checksum webdriver 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6577005cf83a9df4ba39910f8baf3b835b5e4a0a5e9a0d71f3eceae6214ebf28"
"checksum webrender 0.56.0 (git+https://github.com/servo/webrender)" = "<none>" "checksum webrender 0.56.1 (git+https://github.com/servo/webrender)" = "<none>"
"checksum webrender_api 0.56.0 (git+https://github.com/servo/webrender)" = "<none>" "checksum webrender_api 0.56.1 (git+https://github.com/servo/webrender)" = "<none>"
"checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb" "checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

View file

@ -24,6 +24,9 @@ opt-level = 3
# lto = false # lto = false
[patch.crates-io] [patch.crates-io]
serde = { git = "https://github.com/gankro/serde", branch = "deserialize_from_enums3" }
serde_derive = { git = "https://github.com/gankro/serde", branch = "deserialize_from_enums3", feature="deserialize_from" }
# If you need to temporarily test Servo with a local fork of some upstream # If you need to temporarily test Servo with a local fork of some upstream
# crate, add that here. Use the form: # crate, add that here. Use the form:
# #

View file

@ -4,7 +4,7 @@
Servo is a prototype web browser engine written in the Servo is a prototype web browser engine written in the
[Rust](https://github.com/rust-lang/rust) language. It is currently developed on [Rust](https://github.com/rust-lang/rust) language. It is currently developed on
64-bit OS X, 64-bit Linux, and Android. 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android.
Servo welcomes contribution from everyone. See Servo welcomes contribution from everyone. See
[`CONTRIBUTING.md`](CONTRIBUTING.md) and [`HACKING_QUICKSTART.md`](docs/HACKING_QUICKSTART.md) [`CONTRIBUTING.md`](CONTRIBUTING.md) and [`HACKING_QUICKSTART.md`](docs/HACKING_QUICKSTART.md)

View file

@ -11,7 +11,7 @@ use azure::azure_hl::SurfacePattern;
use canvas_traits::canvas::*; use canvas_traits::canvas::*;
use cssparser::RGBA; use cssparser::RGBA;
use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D}; use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D};
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{IpcSender, IpcReceiver};
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::mem; use std::mem;
@ -118,9 +118,8 @@ impl<'a> CanvasPaintThread<'a> {
/// communicate with it. /// communicate with it.
pub fn start(size: Size2D<i32>, pub fn start(size: Size2D<i32>,
webrender_api_sender: webrender_api::RenderApiSender, webrender_api_sender: webrender_api::RenderApiSender,
antialias: bool) antialias: bool,
-> IpcSender<CanvasMsg> { receiver: IpcReceiver<CanvasMsg>) {
let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap();
let antialias = if antialias { let antialias = if antialias {
AntialiasMode::Default AntialiasMode::Default
} else { } else {
@ -216,8 +215,6 @@ impl<'a> CanvasPaintThread<'a> {
} }
} }
}).expect("Thread spawning failed"); }).expect("Thread spawning failed");
sender
} }
fn save_context_state(&mut self) { fn save_context_state(&mut self) {

View file

@ -167,10 +167,7 @@ impl<'a> Iterator for FullyActiveBrowsingContextsIterator<'a> {
type Item = &'a BrowsingContext; type Item = &'a BrowsingContext;
fn next(&mut self) -> Option<&'a BrowsingContext> { fn next(&mut self) -> Option<&'a BrowsingContext> {
loop { loop {
let browsing_context_id = match self.stack.pop() { let browsing_context_id = self.stack.pop()?;
Some(browsing_context_id) => browsing_context_id,
None => return None,
};
let browsing_context = match self.browsing_contexts.get(&browsing_context_id) { let browsing_context = match self.browsing_contexts.get(&browsing_context_id) {
Some(browsing_context) => browsing_context, Some(browsing_context) => browsing_context,
None => { None => {
@ -212,10 +209,7 @@ impl<'a> Iterator for AllBrowsingContextsIterator<'a> {
fn next(&mut self) -> Option<&'a BrowsingContext> { fn next(&mut self) -> Option<&'a BrowsingContext> {
let pipelines = self.pipelines; let pipelines = self.pipelines;
loop { loop {
let browsing_context_id = match self.stack.pop() { let browsing_context_id = self.stack.pop()?;
Some(browsing_context_id) => browsing_context_id,
None => return None,
};
let browsing_context = match self.browsing_contexts.get(&browsing_context_id) { let browsing_context = match self.browsing_contexts.get(&browsing_context_id) {
Some(browsing_context) => browsing_context, Some(browsing_context) => browsing_context,
None => { None => {

View file

@ -1235,9 +1235,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.embedder_proxy.send(EmbedderMsg::HeadParsed(source_top_ctx_id)); self.embedder_proxy.send(EmbedderMsg::HeadParsed(source_top_ctx_id));
} }
} }
FromScriptMsg::CreateCanvasPaintThread(size, sender) => { FromScriptMsg::CreateCanvasPaintThread(size, receiver) => {
debug!("constellation got create-canvas-paint-thread message"); debug!("constellation got create-canvas-paint-thread message");
self.handle_create_canvas_paint_thread_msg(&size, sender) self.handle_create_canvas_paint_thread_msg(&size, receiver)
} }
FromScriptMsg::NodeStatus(message) => { FromScriptMsg::NodeStatus(message) => {
debug!("constellation got NodeStatus message"); debug!("constellation got NodeStatus message");
@ -2264,13 +2264,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
fn handle_create_canvas_paint_thread_msg( fn handle_create_canvas_paint_thread_msg(
&mut self, &mut self,
size: &Size2D<i32>, size: &Size2D<i32>,
response_sender: IpcSender<IpcSender<CanvasMsg>>) { receiver: IpcReceiver<CanvasMsg>) {
let webrender_api = self.webrender_api_sender.clone(); let webrender_api = self.webrender_api_sender.clone();
let sender = CanvasPaintThread::start(*size, webrender_api, CanvasPaintThread::start(*size,
opts::get().enable_canvas_antialiasing); webrender_api,
if let Err(e) = response_sender.send(sender) { opts::get().enable_canvas_antialiasing,
warn!("Create canvas paint thread response failed ({})", e); receiver);
}
} }
fn handle_webdriver_msg(&mut self, msg: WebDriverCommandMsg) { fn handle_webdriver_msg(&mut self, msg: WebDriverCommandMsg) {

View file

@ -720,6 +720,15 @@ pub struct GradientDisplayItem {
/// Contains all gradient data. Included start, end point and color stops. /// Contains all gradient data. Included start, end point and color stops.
pub gradient: Gradient, pub gradient: Gradient,
/// The size of a single gradient tile.
///
/// The gradient may fill an entire element background
/// but it can be composed from many smaller copys of
/// the same gradient.
///
/// Without tiles, the tile will be the same size as the background.
pub tile: Size2D<Au>,
} }
/// Paints a radial gradient. /// Paints a radial gradient.
@ -745,6 +754,15 @@ pub struct RadialGradientDisplayItem {
/// Contains all gradient data. /// Contains all gradient data.
pub gradient: RadialGradient, pub gradient: RadialGradient,
/// The size of a single gradient tile.
///
/// The gradient may fill an entire element background
/// but it can be composed from many smaller copys of
/// the same gradient.
///
/// Without tiles, the tile will be the same size as the background.
pub tile: Size2D<Au>,
} }
/// A normal border, supporting CSS border styles. /// A normal border, supporting CSS border styles.

View file

@ -69,11 +69,7 @@ impl FontHandle {
/// Cache all the data needed for basic horizontal kerning. This is used only as a fallback or /// Cache all the data needed for basic horizontal kerning. This is used only as a fallback or
/// fast path (when the GPOS table is missing or unnecessary) so it needn't handle every case. /// fast path (when the GPOS table is missing or unnecessary) so it needn't handle every case.
fn find_h_kern_subtable(&self) -> Option<CachedKernTable> { fn find_h_kern_subtable(&self) -> Option<CachedKernTable> {
let font_table = match self.table_for_tag(KERN) { let font_table = self.table_for_tag(KERN)?;
Some(table) => table,
None => return None
};
let mut result = CachedKernTable { let mut result = CachedKernTable {
font_table: font_table, font_table: font_table,
pair_data_range: 0..0, pair_data_range: 0..0,

View file

@ -149,10 +149,7 @@ impl<'a> Iterator for CharacterSliceIterator<'a> {
// inline(always) due to the inefficient rt failures messing up inline heuristics, I think. // inline(always) due to the inefficient rt failures messing up inline heuristics, I think.
#[inline(always)] #[inline(always)]
fn next(&mut self) -> Option<TextRunSlice<'a>> { fn next(&mut self) -> Option<TextRunSlice<'a>> {
let glyph_run = match self.glyph_run { let glyph_run = self.glyph_run?;
None => return None,
Some(glyph_run) => glyph_run,
};
debug_assert!(!self.range.is_empty()); debug_assert!(!self.range.is_empty());
let byte_start = self.range.begin(); let byte_start = self.range.begin();

View file

@ -1051,13 +1051,9 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S>
fn next(&mut self) -> Option<&'a T> { fn next(&mut self) -> Option<&'a T> {
loop { loop {
match self.iter.next() { let elt = self.iter.next()?;
None => return None, if self.other.contains(elt) {
Some(elt) => { return Some(elt);
if self.other.contains(elt) {
return Some(elt);
}
}
} }
} }
} }
@ -1091,13 +1087,9 @@ impl<'a, T, S> Iterator for Difference<'a, T, S>
fn next(&mut self) -> Option<&'a T> { fn next(&mut self) -> Option<&'a T> {
loop { loop {
match self.iter.next() { let elt = self.iter.next()?;
None => return None, if !self.other.contains(elt) {
Some(elt) => { return Some(elt);
if !self.other.contains(elt) {
return Some(elt);
}
}
} }
} }
} }

View file

@ -10,7 +10,7 @@ name = "layout"
path = "lib.rs" path = "lib.rs"
[dependencies] [dependencies]
app_units = "0.6" app_units = "0.6.1"
atomic_refcell = "0.1" atomic_refcell = "0.1"
bitflags = "1.0" bitflags = "1.0"
canvas_traits = {path = "../canvas_traits"} canvas_traits = {path = "../canvas_traits"}
@ -41,7 +41,7 @@ serde_json = "1.0"
servo_config = {path = "../config"} servo_config = {path = "../config"}
servo_url = {path = "../url"} servo_url = {path = "../url"}
smallvec = "0.6" smallvec = "0.6"
style = {path = "../style"} style = {path = "../style", features = ["servo"]}
style_traits = {path = "../style_traits"} style_traits = {path = "../style_traits"}
unicode-bidi = {version = "0.3", features = ["with_serde"]} unicode-bidi = {version = "0.3", features = ["with_serde"]}
unicode-script = {version = "0.1", features = ["harfbuzz"]} unicode-script = {version = "0.1", features = ["harfbuzz"]}

View file

@ -5,7 +5,7 @@
//! CSS transitions and animations. //! CSS transitions and animations.
use context::LayoutContext; use context::LayoutContext;
use flow::{self, Flow}; use flow::{Flow, GetBaseFlow};
use fnv::FnvHashMap; use fnv::FnvHashMap;
use gfx::display_list::OpaqueNode; use gfx::display_list::OpaqueNode;
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
@ -170,7 +170,7 @@ pub fn recalc_style_for_animations(context: &LayoutContext,
} }
}); });
let base = flow::mut_base(flow); let base = flow.mut_base();
base.restyle_damage.insert(damage); base.restyle_damage.insert(damage);
for kid in base.children.iter_mut() { for kid in base.children.iter_mut() {
recalc_style_for_animations(context, kid, animations) recalc_style_for_animations(context, kid, animations)

View file

@ -34,7 +34,7 @@ use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags
use display_list_builder::StackingContextCollectionState; use display_list_builder::StackingContextCollectionState;
use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
use floats::{ClearType, FloatKind, Floats, PlacementInfo}; use floats::{ClearType, FloatKind, Floats, PlacementInfo};
use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag}; use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag, GetBaseFlow};
use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, OpaqueFlow, FragmentationContext, FlowFlags}; use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, OpaqueFlow, FragmentationContext, FlowFlags};
use flow_list::FlowList; use flow_list::FlowList;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow, FragmentFlags}; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow, FragmentFlags};
@ -708,7 +708,7 @@ impl BlockFlow {
// Shift all kids down (or up, if margins are negative) if necessary. // Shift all kids down (or up, if margins are negative) if necessary.
if block_start_margin_value != Au(0) { if block_start_margin_value != Au(0) {
for kid in self.base.child_iter_mut() { for kid in self.base.child_iter_mut() {
let kid_base = flow::mut_base(kid); let kid_base = kid.mut_base();
kid_base.position.start.b = kid_base.position.start.b + block_start_margin_value kid_base.position.start.b = kid_base.position.start.b + block_start_margin_value
} }
} }
@ -744,7 +744,7 @@ impl BlockFlow {
/// is also needed to handle RTL.) /// is also needed to handle RTL.)
fn propagate_early_absolute_position_info_to_children(&mut self) { fn propagate_early_absolute_position_info_to_children(&mut self) {
for kid in self.base.child_iter_mut() { for kid in self.base.child_iter_mut() {
flow::mut_base(kid).early_absolute_position_info = EarlyAbsolutePositionInfo { kid.mut_base().early_absolute_position_info = EarlyAbsolutePositionInfo {
relative_containing_block_size: self.fragment.content_box().size, relative_containing_block_size: self.fragment.content_box().size,
relative_containing_block_mode: self.fragment.style().writing_mode, relative_containing_block_mode: self.fragment.style().writing_mode,
} }
@ -816,19 +816,19 @@ impl BlockFlow {
let thread_id = self.base.thread_id; let thread_id = self.base.thread_id;
let (mut had_floated_children, mut had_children_with_clearance) = (false, false); let (mut had_floated_children, mut had_children_with_clearance) = (false, false);
for (child_index, kid) in self.base.child_iter_mut().enumerate() { for (child_index, kid) in self.base.child_iter_mut().enumerate() {
if flow::base(kid).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
// Assume that the *hypothetical box* for an absolute flow starts immediately // Assume that the *hypothetical box* for an absolute flow starts immediately
// after the margin-end border edge of the previous flow. // after the margin-end border edge of the previous flow.
if flow::base(kid).flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { if kid.base().flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) {
let previous_bottom_margin = margin_collapse_info.current_float_ceiling(); let previous_bottom_margin = margin_collapse_info.current_float_ceiling();
flow::mut_base(kid).position.start.b = cur_b + kid.mut_base().position.start.b = cur_b +
flow::base(kid).collapsible_margins kid.base().collapsible_margins
.block_start_margin_for_noncollapsible_context() + .block_start_margin_for_noncollapsible_context() +
previous_bottom_margin previous_bottom_margin
} }
kid.place_float_if_applicable(); kid.place_float_if_applicable();
if !flow::base(kid).flags.is_float() { if !kid.base().flags.is_float() {
kid.assign_block_size_for_inorder_child_if_necessary(layout_context, kid.assign_block_size_for_inorder_child_if_necessary(layout_context,
thread_id, thread_id,
content_box); content_box);
@ -852,10 +852,10 @@ impl BlockFlow {
// Assign block-size now for the child if it might have floats in and we couldn't // Assign block-size now for the child if it might have floats in and we couldn't
// before. // before.
flow::mut_base(kid).floats = floats.clone(); kid.mut_base().floats = floats.clone();
if flow::base(kid).flags.is_float() { if kid.base().flags.is_float() {
had_floated_children = true; had_floated_children = true;
flow::mut_base(kid).position.start.b = cur_b; kid.mut_base().position.start.b = cur_b;
{ {
let kid_block = kid.as_mut_block(); let kid_block = kid.as_mut_block();
let float_ceiling = margin_collapse_info.current_float_ceiling(); let float_ceiling = margin_collapse_info.current_float_ceiling();
@ -863,7 +863,7 @@ impl BlockFlow {
} }
kid.place_float_if_applicable(); kid.place_float_if_applicable();
let kid_base = flow::mut_base(kid); let kid_base = kid.mut_base();
floats = kid_base.floats.clone(); floats = kid_base.floats.clone();
continue continue
} }
@ -875,8 +875,8 @@ impl BlockFlow {
// complicated with margin collapse. Possibly the right thing to do is to lay out // complicated with margin collapse. Possibly the right thing to do is to lay out
// the block again in this rare case. (Note that WebKit can lay blocks out twice; // the block again in this rare case. (Note that WebKit can lay blocks out twice;
// this may be related, although I haven't looked into it closely.) // this may be related, although I haven't looked into it closely.)
if flow::base(kid).flags.clears_floats() { if kid.base().flags.clears_floats() {
flow::mut_base(kid).floats = Floats::new(self.fragment.style.writing_mode) kid.mut_base().floats = Floats::new(self.fragment.style.writing_mode)
} }
// Lay the child out if this was an in-order traversal. // Lay the child out if this was an in-order traversal.
@ -887,26 +887,26 @@ impl BlockFlow {
if !had_children_with_clearance && if !had_children_with_clearance &&
floats.is_present() && floats.is_present() &&
(flow::base(kid).flags.contains(FlowFlags::CLEARS_LEFT) || (kid.base().flags.contains(FlowFlags::CLEARS_LEFT) ||
flow::base(kid).flags.contains(FlowFlags::CLEARS_RIGHT)) { kid.base().flags.contains(FlowFlags::CLEARS_RIGHT)) {
had_children_with_clearance = true had_children_with_clearance = true
} }
// Handle any (possibly collapsed) top margin. // Handle any (possibly collapsed) top margin.
let delta = margin_collapse_info.advance_block_start_margin( let delta = margin_collapse_info.advance_block_start_margin(
&flow::base(kid).collapsible_margins, &kid.base().collapsible_margins,
!had_children_with_clearance); !had_children_with_clearance);
translate_including_floats(&mut cur_b, delta, &mut floats); translate_including_floats(&mut cur_b, delta, &mut floats);
// Collapse-through margins should be placed at the top edge, // Collapse-through margins should be placed at the top edge,
// so we'll handle the delta after the bottom margin is processed // so we'll handle the delta after the bottom margin is processed
if let CollapsibleMargins::CollapseThrough(_) = flow::base(kid).collapsible_margins { if let CollapsibleMargins::CollapseThrough(_) = kid.base().collapsible_margins {
cur_b = cur_b - delta; cur_b = cur_b - delta;
} }
// Clear past the floats that came in, if necessary. // Clear past the floats that came in, if necessary.
let clearance = match (flow::base(kid).flags.contains(FlowFlags::CLEARS_LEFT), let clearance = match (kid.base().flags.contains(FlowFlags::CLEARS_LEFT),
flow::base(kid).flags.contains(FlowFlags::CLEARS_RIGHT)) { kid.base().flags.contains(FlowFlags::CLEARS_RIGHT)) {
(false, false) => Au(0), (false, false) => Au(0),
(true, false) => floats.clearance(ClearType::Left), (true, false) => floats.clearance(ClearType::Left),
(false, true) => floats.clearance(ClearType::Right), (false, true) => floats.clearance(ClearType::Right),
@ -915,19 +915,19 @@ impl BlockFlow {
translate_including_floats(&mut cur_b, clearance, &mut floats); translate_including_floats(&mut cur_b, clearance, &mut floats);
// At this point, `cur_b` is at the border edge of the child. // At this point, `cur_b` is at the border edge of the child.
flow::mut_base(kid).position.start.b = cur_b; kid.mut_base().position.start.b = cur_b;
// Now pull out the child's outgoing floats. We didn't do this immediately after // Now pull out the child's outgoing floats. We didn't do this immediately after
// the `assign_block_size_for_inorder_child_if_necessary` call because clearance on // the `assign_block_size_for_inorder_child_if_necessary` call because clearance on
// a block operates on the floats that come *in*, not the floats that go *out*. // a block operates on the floats that come *in*, not the floats that go *out*.
if need_to_process_child_floats { if need_to_process_child_floats {
floats = flow::mut_base(kid).floats.clone() floats = kid.mut_base().floats.clone()
} }
// Move past the child's border box. Do not use the `translate_including_floats` // Move past the child's border box. Do not use the `translate_including_floats`
// function here because the child has already translated floats past its border // function here because the child has already translated floats past its border
// box. // box.
let kid_base = flow::mut_base(kid); let kid_base = kid.mut_base();
cur_b = cur_b + kid_base.position.size.block; cur_b = cur_b + kid_base.position.size.block;
// Handle any (possibly collapsed) block-end margin. // Handle any (possibly collapsed) block-end margin.
@ -1371,11 +1371,11 @@ impl BlockFlow {
let mut iterator = self.base.child_iter_mut().enumerate().peekable(); let mut iterator = self.base.child_iter_mut().enumerate().peekable();
while let Some((i, kid)) = iterator.next() { while let Some((i, kid)) = iterator.next() {
flow::mut_base(kid).block_container_explicit_block_size = explicit_content_size; kid.mut_base().block_container_explicit_block_size = explicit_content_size;
// The inline-start margin edge of the child flow is at our inline-start content edge, // The inline-start margin edge of the child flow is at our inline-start content edge,
// and its inline-size is our content inline-size. // and its inline-size is our content inline-size.
let kid_mode = flow::base(kid).writing_mode; let kid_mode = kid.base().writing_mode;
{ {
// Don't assign positions to children unless they're going to be reflowed. // Don't assign positions to children unless they're going to be reflowed.
// Otherwise, the position we assign might be incorrect and never fixed up. (Issue // Otherwise, the position we assign might be incorrect and never fixed up. (Issue
@ -1385,7 +1385,7 @@ impl BlockFlow {
// `assign_block_size()`, which won't do anything unless `REFLOW` is set. So, if a // `assign_block_size()`, which won't do anything unless `REFLOW` is set. So, if a
// float child does not have `REFLOW` set, we must be careful to avoid touching its // float child does not have `REFLOW` set, we must be careful to avoid touching its
// inline position, as no logic will run afterward to set its true value. // inline position, as no logic will run afterward to set its true value.
let kid_base = flow::mut_base(kid); let kid_base = kid.mut_base();
let reflow_damage = if kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { let reflow_damage = if kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
ServoRestyleDamage::REFLOW_OUT_OF_FLOW ServoRestyleDamage::REFLOW_OUT_OF_FLOW
} else { } else {
@ -1418,7 +1418,7 @@ impl BlockFlow {
// //
// TODO(#2265, pcwalton): Do this in the cascade instead. // TODO(#2265, pcwalton): Do this in the cascade instead.
let containing_block_text_align = self.fragment.style().get_inheritedtext().text_align; let containing_block_text_align = self.fragment.style().get_inheritedtext().text_align;
flow::mut_base(kid).flags.set_text_align(containing_block_text_align); kid.mut_base().flags.set_text_align(containing_block_text_align);
// Handle `text-indent` on behalf of any inline children that we have. This is // Handle `text-indent` on behalf of any inline children that we have. This is
// necessary because any percentages are relative to the containing block, which only // necessary because any percentages are relative to the containing block, which only
@ -1554,7 +1554,7 @@ impl BlockFlow {
// Assign final-final inline sizes on all our children. // Assign final-final inline sizes on all our children.
self.assign_inline_sizes(layout_context); self.assign_inline_sizes(layout_context);
// Re-run layout on our children. // Re-run layout on our children.
for child in flow::mut_base(self).children.iter_mut() { for child in self.base.child_iter_mut() {
sequential::reflow(child, layout_context, RelayoutMode::Force); sequential::reflow(child, layout_context, RelayoutMode::Force);
} }
// Assign our final-final block size. // Assign our final-final block size.
@ -1597,7 +1597,7 @@ impl BlockFlow {
} else { } else {
flags.remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); flags.remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS);
for kid in self.base.children.iter() { for kid in self.base.children.iter() {
if flow::base(kid).flags.contains(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS) { if kid.base().flags.contains(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS) {
flags.insert(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); flags.insert(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS);
break break
} }
@ -1615,11 +1615,11 @@ impl BlockFlow {
let (mut left_float_width_accumulator, mut right_float_width_accumulator) = (Au(0), Au(0)); let (mut left_float_width_accumulator, mut right_float_width_accumulator) = (Au(0), Au(0));
let mut preferred_inline_size_of_children_without_text_or_replaced_fragments = Au(0); let mut preferred_inline_size_of_children_without_text_or_replaced_fragments = Au(0);
for kid in self.base.child_iter_mut() { for kid in self.base.child_iter_mut() {
if flow::base(kid).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) || !consult_children { if kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) || !consult_children {
continue continue
} }
let child_base = flow::mut_base(kid); let child_base = kid.mut_base();
let float_kind = child_base.flags.float_kind(); let float_kind = child_base.flags.float_kind();
computation.content_intrinsic_sizes.minimum_inline_size = computation.content_intrinsic_sizes.minimum_inline_size =
max(computation.content_intrinsic_sizes.minimum_inline_size, max(computation.content_intrinsic_sizes.minimum_inline_size,
@ -1935,14 +1935,14 @@ impl Flow for BlockFlow {
self.base.flags.contains(FlowFlags::MARGINS_CANNOT_COLLAPSE) { self.base.flags.contains(FlowFlags::MARGINS_CANNOT_COLLAPSE) {
// Root element margins should never be collapsed according to CSS § 8.3.1. // Root element margins should never be collapsed according to CSS § 8.3.1.
debug!("assign_block_size: assigning block_size for root flow {:?}", debug!("assign_block_size: assigning block_size for root flow {:?}",
flow::base(self).debug_id()); self.base().debug_id());
self.assign_block_size_block_base( self.assign_block_size_block_base(
layout_context, layout_context,
fragmentation_context, fragmentation_context,
MarginsMayCollapseFlag::MarginsMayNotCollapse) MarginsMayCollapseFlag::MarginsMayNotCollapse)
} else { } else {
debug!("assign_block_size: assigning block_size for block {:?}", debug!("assign_block_size: assigning block_size for block {:?}",
flow::base(self).debug_id()); self.base().debug_id());
self.assign_block_size_block_base( self.assign_block_size_block_base(
layout_context, layout_context,
fragmentation_context, fragmentation_context,
@ -2060,9 +2060,9 @@ impl Flow for BlockFlow {
// Process children. // Process children.
for kid in self.base.child_iter_mut() { for kid in self.base.child_iter_mut() {
if flow::base(kid).flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) || if kid.base().flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) ||
flow::base(kid).flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { kid.base().flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) {
let kid_base = flow::mut_base(kid); let kid_base = kid.mut_base();
let physical_position = kid_base.position.to_physical(kid_base.writing_mode, let physical_position = kid_base.position.to_physical(kid_base.writing_mode,
container_size_for_children); container_size_for_children);
@ -2088,7 +2088,7 @@ impl Flow for BlockFlow {
} }
} }
flow::mut_base(kid).late_absolute_position_info = kid.mut_base().late_absolute_position_info =
late_absolute_position_info_for_children; late_absolute_position_info_for_children;
} }
} }
@ -2377,7 +2377,7 @@ pub trait ISizeAndMarginsComputer {
// We also resize the block itself, to ensure that overflow is not calculated // We also resize the block itself, to ensure that overflow is not calculated
// as the inline-size of our parent. We might be smaller and we might be larger if we // as the inline-size of our parent. We might be smaller and we might be larger if we
// overflow. // overflow.
flow::mut_base(block).position.size.inline = inline_size + extra_inline_size_from_margin; block.mut_base().position.size.inline = inline_size + extra_inline_size_from_margin;
} }
/// Set the inline coordinate of the given flow if it is absolutely positioned. /// Set the inline coordinate of the given flow if it is absolutely positioned.

View file

@ -19,7 +19,7 @@ use context::{LayoutContext, with_thread_local_font_context};
use data::{LayoutDataFlags, LayoutData}; use data::{LayoutDataFlags, LayoutData};
use flex::FlexFlow; use flex::FlexFlow;
use floats::FloatKind; use floats::FloatKind;
use flow::{self, AbsoluteDescendants, Flow, FlowClass, ImmutableFlowUtils}; use flow::{AbsoluteDescendants, Flow, FlowClass, GetBaseFlow, ImmutableFlowUtils};
use flow::{FlowFlags, MutableFlowUtils, MutableOwnedFlowUtils}; use flow::{FlowFlags, MutableFlowUtils, MutableOwnedFlowUtils};
use flow_ref::FlowRef; use flow_ref::FlowRef;
use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo}; use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo};
@ -96,7 +96,7 @@ impl ConstructionResult {
match *self { match *self {
ConstructionResult::None => 0, ConstructionResult::None => 0,
ConstructionResult::ConstructionItem(_) => 0, ConstructionResult::ConstructionItem(_) => 0,
ConstructionResult::Flow(ref flow_ref, _) => flow::base(&**flow_ref).debug_id(), ConstructionResult::Flow(ref flow_ref, _) => flow_ref.base().debug_id(),
} }
} }
} }
@ -497,7 +497,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
ConstructionResult::Flow(kid_flow, AbsoluteDescendants::new()); ConstructionResult::Flow(kid_flow, AbsoluteDescendants::new());
self.set_flow_construction_result(&kid, construction_result) self.set_flow_construction_result(&kid, construction_result)
} else { } else {
if !flow::base(&*kid_flow).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if !kid_flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
// Flush any inline fragments that we were gathering up. This allows us to // Flush any inline fragments that we were gathering up. This allows us to
// handle {ib} splits. // handle {ib} splits.
let old_inline_fragment_accumulator = let old_inline_fragment_accumulator =
@ -625,7 +625,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
flow.set_absolute_descendants(abs_descendants); flow.set_absolute_descendants(abs_descendants);
abs_descendants = AbsoluteDescendants::new(); abs_descendants = AbsoluteDescendants::new();
if flow::base(&*flow).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
// This is now the only absolute flow in the subtree which hasn't yet // This is now the only absolute flow in the subtree which hasn't yet
// reached its CB. // reached its CB.
abs_descendants.push(flow.clone()); abs_descendants.push(flow.clone());
@ -780,7 +780,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
match kid.get_construction_result() { match kid.get_construction_result() {
ConstructionResult::None => {} ConstructionResult::None => {}
ConstructionResult::Flow(flow, kid_abs_descendants) => { ConstructionResult::Flow(flow, kid_abs_descendants) => {
if !flow::base(&*flow).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if !flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
opt_inline_block_splits.push_back(InlineBlockSplit::new( opt_inline_block_splits.push_back(InlineBlockSplit::new(
&mut fragment_accumulator, node, self.style_context(), flow)); &mut fragment_accumulator, node, self.style_context(), flow));
abs_descendants.push_descendants(kid_abs_descendants); abs_descendants.push_descendants(kid_abs_descendants);
@ -1073,7 +1073,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
abs_descendants = AbsoluteDescendants::new(); abs_descendants = AbsoluteDescendants::new();
if flow::base(&*flow).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
// This is now the only absolute flow in the subtree which hasn't yet // This is now the only absolute flow in the subtree which hasn't yet
// reached its containing block. // reached its containing block.
abs_descendants.push(flow.clone()); abs_descendants.push(flow.clone());
@ -1144,7 +1144,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
abs_descendants = AbsoluteDescendants::new(); abs_descendants = AbsoluteDescendants::new();
if flow::base(&*wrapper_flow).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if wrapper_flow.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
// This is now the only absolute flow in the subtree which hasn't yet // This is now the only absolute flow in the subtree which hasn't yet
// reached its containing block. // reached its containing block.
abs_descendants.push(wrapper_flow.clone()); abs_descendants.push(wrapper_flow.clone());
@ -1373,7 +1373,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
} }
let flow = FlowRef::deref_mut(flow); let flow = FlowRef::deref_mut(flow);
flow::mut_base(flow).restyle_damage.insert(damage); flow.mut_base().restyle_damage.insert(damage);
flow.repair_style_and_bubble_inline_sizes(&style); flow.repair_style_and_bubble_inline_sizes(&style);
true true
} }
@ -1398,7 +1398,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
match fragment.specific { match fragment.specific {
SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => { SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => {
let flow_ref = FlowRef::deref_mut(&mut inline_block_fragment.flow_ref); let flow_ref = FlowRef::deref_mut(&mut inline_block_fragment.flow_ref);
flow::mut_base(flow_ref).restyle_damage.insert(damage); flow_ref.mut_base().restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
flow_ref.repair_style_and_bubble_inline_sizes(&style); flow_ref.repair_style_and_bubble_inline_sizes(&style);
} }
@ -1406,14 +1406,14 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
ref mut inline_absolute_hypothetical_fragment) => { ref mut inline_absolute_hypothetical_fragment) => {
let flow_ref = FlowRef::deref_mut( let flow_ref = FlowRef::deref_mut(
&mut inline_absolute_hypothetical_fragment.flow_ref); &mut inline_absolute_hypothetical_fragment.flow_ref);
flow::mut_base(flow_ref).restyle_damage.insert(damage); flow_ref.mut_base().restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
flow_ref.repair_style_and_bubble_inline_sizes(&style); flow_ref.repair_style_and_bubble_inline_sizes(&style);
} }
SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => { SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => {
let flow_ref = FlowRef::deref_mut( let flow_ref = FlowRef::deref_mut(
&mut inline_absolute_fragment.flow_ref); &mut inline_absolute_fragment.flow_ref);
flow::mut_base(flow_ref).restyle_damage.insert(damage); flow_ref.mut_base().restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
flow_ref.repair_style_and_bubble_inline_sizes(&style); flow_ref.repair_style_and_bubble_inline_sizes(&style);
} }
@ -1660,7 +1660,7 @@ impl<ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNode
fn set_flow_construction_result(self, mut result: ConstructionResult) { fn set_flow_construction_result(self, mut result: ConstructionResult) {
if self.can_be_fragmented() { if self.can_be_fragmented() {
if let ConstructionResult::Flow(ref mut flow, _) = result { if let ConstructionResult::Flow(ref mut flow, _) = result {
flow::mut_base(FlowRef::deref_mut(flow)).flags.insert(FlowFlags::CAN_BE_FRAGMENTED); FlowRef::deref_mut(flow).mut_base().flags.insert(FlowFlags::CAN_BE_FRAGMENTED);
} }
} }
@ -1732,11 +1732,11 @@ impl FlowConstructionUtils for FlowRef {
/// Adds a new flow as a child of this flow. Fails if this flow is marked as a leaf. /// Adds a new flow as a child of this flow. Fails if this flow is marked as a leaf.
fn add_new_child(&mut self, mut new_child: FlowRef) { fn add_new_child(&mut self, mut new_child: FlowRef) {
{ {
let kid_base = flow::mut_base(FlowRef::deref_mut(&mut new_child)); let kid_base = FlowRef::deref_mut(&mut new_child).mut_base();
kid_base.parallel.parent = parallel::mut_owned_flow_to_unsafe_flow(self); kid_base.parallel.parent = parallel::mut_owned_flow_to_unsafe_flow(self);
} }
let base = flow::mut_base(FlowRef::deref_mut(self)); let base = FlowRef::deref_mut(self).mut_base();
base.children.push_back(new_child); base.children.push_back(new_child);
let _ = base.parallel.children_count.fetch_add(1, Ordering::Relaxed); let _ = base.parallel.children_count.fetch_add(1, Ordering::Relaxed);
} }
@ -1750,7 +1750,7 @@ impl FlowConstructionUtils for FlowRef {
fn finish(&mut self) { fn finish(&mut self) {
if !opts::get().bubble_inline_sizes_separately { if !opts::get().bubble_inline_sizes_separately {
FlowRef::deref_mut(self).bubble_inline_sizes(); FlowRef::deref_mut(self).bubble_inline_sizes();
flow::mut_base(FlowRef::deref_mut(self)).restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES); FlowRef::deref_mut(self).mut_base().restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES);
} }
} }
} }
@ -1951,7 +1951,7 @@ impl Legalizer {
} }
(FlowClass::Flex, FlowClass::Inline) => { (FlowClass::Flex, FlowClass::Inline) => {
flow::mut_base(FlowRef::deref_mut(child)).flags.insert(FlowFlags::MARGINS_CANNOT_COLLAPSE); FlowRef::deref_mut(child).mut_base().flags.insert(FlowFlags::MARGINS_CANNOT_COLLAPSE);
let mut block_wrapper = let mut block_wrapper =
Legalizer::create_anonymous_flow(context, Legalizer::create_anonymous_flow(context,
parent, parent,

View file

@ -58,6 +58,7 @@ use style::computed_values::position::T as StylePosition;
use style::computed_values::visibility::T as Visibility; use style::computed_values::visibility::T as Visibility;
use style::logical_geometry::{LogicalMargin, LogicalPoint, LogicalRect, LogicalSize, WritingMode}; use style::logical_geometry::{LogicalMargin, LogicalPoint, LogicalRect, LogicalSize, WritingMode};
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::properties::longhands::background_origin::single_value::computed_value::T as BackgroundOrigin;
use style::properties::longhands::border_image_repeat::computed_value::RepeatKeyword; use style::properties::longhands::border_image_repeat::computed_value::RepeatKeyword;
use style::properties::style_structs; use style::properties::style_structs;
use style::servo::restyle_damage::ServoRestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage;
@ -503,30 +504,16 @@ pub trait FragmentDisplayListBuilding {
size: Size2D<Au>) size: Size2D<Au>)
-> Option<WebRenderImageInfo>; -> Option<WebRenderImageInfo>;
fn convert_linear_gradient(&self,
bounds: &Rect<Au>,
stops: &[GradientItem],
direction: &LineDirection,
repeating: bool)
-> display_list::Gradient;
fn convert_radial_gradient(&self,
bounds: &Rect<Au>,
stops: &[GradientItem],
shape: &EndingShape,
center: &Position,
repeating: bool)
-> display_list::RadialGradient;
/// Adds the display items necessary to paint the background linear gradient of this fragment /// Adds the display items necessary to paint the background linear gradient of this fragment
/// to the appropriate section of the display list. /// to the appropriate section of the display list.
fn build_display_list_for_background_gradient(&self, fn build_display_list_for_background_gradient(&self,
state: &mut DisplayListBuildState, state: &mut DisplayListBuildState,
display_list_section: DisplayListSection, display_list_section: DisplayListSection,
absolute_bounds: &Rect<Au>, absolute_bounds: Rect<Au>,
clip: &LocalClip, clip: &LocalClip,
gradient: &Gradient, gradient: &Gradient,
style: &ComputedValues); style: &ComputedValues,
index: usize);
/// Adds the display items necessary to paint the borders of this fragment to a display list if /// Adds the display items necessary to paint the borders of this fragment to a display list if
/// necessary. /// necessary.
@ -819,6 +806,120 @@ fn convert_gradient_stops(gradient_items: &[GradientItem],
stops stops
} }
fn convert_linear_gradient(size: Size2D<Au>,
stops: &[GradientItem],
direction: LineDirection,
repeating: bool)
-> display_list::Gradient {
let angle = match direction {
LineDirection::Angle(angle) => angle.radians(),
LineDirection::Horizontal(x) => {
match x {
X::Left => Angle::Deg(270.).radians(),
X::Right => Angle::Deg(90.).radians(),
}
},
LineDirection::Vertical(y) => {
match y {
Y::Top => Angle::Deg(0.).radians(),
Y::Bottom => Angle::Deg(180.).radians(),
}
},
LineDirection::Corner(horizontal, vertical) => {
// This the angle for one of the diagonals of the box. Our angle
// will either be this one, this one + PI, or one of the other
// two perpendicular angles.
let atan = (size.height.to_f32_px() /
size.width.to_f32_px()).atan();
match (horizontal, vertical) {
(X::Right, Y::Bottom)
=> f32::consts::PI - atan,
(X::Left, Y::Bottom)
=> f32::consts::PI + atan,
(X::Right, Y::Top)
=> atan,
(X::Left, Y::Top)
=> -atan,
}
}
};
// Get correct gradient line length, based on:
// https://drafts.csswg.org/css-images-3/#linear-gradients
let dir = Point2D::new(angle.sin(), -angle.cos());
let line_length = (dir.x * size.width.to_f32_px()).abs() +
(dir.y * size.height.to_f32_px()).abs();
let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt();
// This is the vector between the center and the ending point; i.e. half
// of the distance between the starting point and the ending point.
let delta = Vector2D::new(Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0),
Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0));
// This is the length of the gradient line.
let length = Au::from_f32_px(
(delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0));
let mut stops = convert_gradient_stops(stops, length);
// Only clamped gradients need to be fixed because in repeating gradients
// there is no "first" or "last" stop because they repeat infinitly in
// both directions, so the rendering is always correct.
if !repeating {
fix_gradient_stops(&mut stops);
}
let center = Point2D::new(size.width / 2, size.height / 2);
display_list::Gradient {
start_point: center - delta,
end_point: center + delta,
stops: stops,
repeating: repeating,
}
}
fn convert_radial_gradient(size: Size2D<Au>,
stops: &[GradientItem],
shape: EndingShape,
center: Position,
repeating: bool)
-> display_list::RadialGradient {
let center = Point2D::new(center.horizontal.to_used_value(size.width),
center.vertical.to_used_value(size.height));
let radius = match shape {
GenericEndingShape::Circle(Circle::Radius(length)) => {
let length = Au::from(length);
Size2D::new(length, length)
},
GenericEndingShape::Circle(Circle::Extent(extent)) => {
convert_circle_size_keyword(extent, &size, &center)
},
GenericEndingShape::Ellipse(Ellipse::Radii(x, y)) => {
Size2D::new(x.to_used_value(size.width), y.to_used_value(size.height))
},
GenericEndingShape::Ellipse(Ellipse::Extent(extent)) => {
convert_ellipse_size_keyword(extent, &size, &center)
},
};
let mut stops = convert_gradient_stops(stops, radius.width);
// Repeating gradients have no last stops that can be ignored. So
// fixup is not necessary but may actually break the gradient.
if !repeating {
fix_gradient_stops(&mut stops);
}
display_list::RadialGradient {
center: center,
radius: radius,
stops: stops,
repeating: repeating,
}
}
#[inline] #[inline]
/// Duplicate the first and last stops if necessary. /// Duplicate the first and last stops if necessary.
/// ///
@ -1023,10 +1124,11 @@ impl FragmentDisplayListBuilding for Fragment {
Either::Second(Image::Gradient(ref gradient)) => { Either::Second(Image::Gradient(ref gradient)) => {
self.build_display_list_for_background_gradient(state, self.build_display_list_for_background_gradient(state,
display_list_section, display_list_section,
&absolute_bounds, *absolute_bounds,
&clip, &clip,
gradient, gradient,
style); style,
i);
} }
Either::Second(Image::Url(ref image_url)) => { Either::Second(Image::Url(ref image_url)) => {
if let Some(url) = image_url.url() { if let Some(url) = image_url.url() {
@ -1310,162 +1412,112 @@ impl FragmentDisplayListBuilding for Fragment {
Some(webrender_image) Some(webrender_image)
} }
fn convert_linear_gradient(&self,
bounds: &Rect<Au>,
stops: &[GradientItem],
direction: &LineDirection,
repeating: bool)
-> display_list::Gradient {
let angle = match *direction {
LineDirection::Angle(angle) => angle.radians(),
LineDirection::Horizontal(x) => {
match x {
X::Left => Angle::Deg(270.).radians(),
X::Right => Angle::Deg(90.).radians(),
}
},
LineDirection::Vertical(y) => {
match y {
Y::Top => Angle::Deg(0.).radians(),
Y::Bottom => Angle::Deg(180.).radians(),
}
},
LineDirection::Corner(horizontal, vertical) => {
// This the angle for one of the diagonals of the box. Our angle
// will either be this one, this one + PI, or one of the other
// two perpendicular angles.
let atan = (bounds.size.height.to_f32_px() /
bounds.size.width.to_f32_px()).atan();
match (horizontal, vertical) {
(X::Right, Y::Bottom)
=> f32::consts::PI - atan,
(X::Left, Y::Bottom)
=> f32::consts::PI + atan,
(X::Right, Y::Top)
=> atan,
(X::Left, Y::Top)
=> -atan,
}
}
};
// Get correct gradient line length, based on:
// https://drafts.csswg.org/css-images-3/#linear-gradients
let dir = Point2D::new(angle.sin(), -angle.cos());
let line_length = (dir.x * bounds.size.width.to_f32_px()).abs() +
(dir.y * bounds.size.height.to_f32_px()).abs();
let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt();
// This is the vector between the center and the ending point; i.e. half
// of the distance between the starting point and the ending point.
let delta = Vector2D::new(Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0),
Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0));
// This is the length of the gradient line.
let length = Au::from_f32_px(
(delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0));
let mut stops = convert_gradient_stops(stops, length);
// Only clamped gradients need to be fixed because in repeating gradients
// there is no "first" or "last" stop because they repeat infinitly in
// both directions, so the rendering is always correct.
if !repeating {
fix_gradient_stops(&mut stops);
}
let center = Point2D::new(bounds.size.width / 2, bounds.size.height / 2);
display_list::Gradient {
start_point: center - delta,
end_point: center + delta,
stops: stops,
repeating: repeating,
}
}
fn convert_radial_gradient(&self,
bounds: &Rect<Au>,
stops: &[GradientItem],
shape: &EndingShape,
center: &Position,
repeating: bool)
-> display_list::RadialGradient {
let center = Point2D::new(center.horizontal.to_used_value(bounds.size.width),
center.vertical.to_used_value(bounds.size.height));
let radius = match *shape {
GenericEndingShape::Circle(Circle::Radius(length)) => {
let length = Au::from(length);
Size2D::new(length, length)
},
GenericEndingShape::Circle(Circle::Extent(extent)) => {
convert_circle_size_keyword(extent, &bounds.size, &center)
},
GenericEndingShape::Ellipse(Ellipse::Radii(x, y)) => {
Size2D::new(x.to_used_value(bounds.size.width), y.to_used_value(bounds.size.height))
},
GenericEndingShape::Ellipse(Ellipse::Extent(extent)) => {
convert_ellipse_size_keyword(extent, &bounds.size, &center)
},
};
let mut stops = convert_gradient_stops(stops, radius.width);
// Repeating gradients have no last stops that can be ignored. So
// fixup is not necessary but may actually break the gradient.
if !repeating {
fix_gradient_stops(&mut stops);
}
display_list::RadialGradient {
center: center,
radius: radius,
stops: stops,
repeating: repeating,
}
}
fn build_display_list_for_background_gradient(&self, fn build_display_list_for_background_gradient(&self,
state: &mut DisplayListBuildState, state: &mut DisplayListBuildState,
display_list_section: DisplayListSection, display_list_section: DisplayListSection,
absolute_bounds: &Rect<Au>, absolute_bounds: Rect<Au>,
clip: &LocalClip, clip: &LocalClip,
gradient: &Gradient, gradient: &Gradient,
style: &ComputedValues) { style: &ComputedValues,
let border = self.border_width().to_physical(style.writing_mode); index: usize) {
let mut bounds = *absolute_bounds; // Calculate where the first "tile" needs to be placed on one axis.
bounds.origin.x = bounds.origin.x + border.left; // * base is the beginning of the visible area
bounds.origin.y = bounds.origin.y + border.top; // * start is the current "tile" position
bounds.size.width = bounds.size.width - border.horizontal(); // * tile is the length of the "tile"
bounds.size.height = bounds.size.height - border.vertical(); // Returns a difference between start and new start.
// It holds that base - tile < start - diff <= base
fn get_first_tile(base: Au, start: Au, tile: Au) -> Au {
if tile == Au(0) {
return Au(0);
}
if start > base {
((start - base) / tile + 1) * tile
} else {
((base - start) / tile) * tile
}
}
let base = state.create_base_display_item(&bounds, let bg = style.get_background();
let bg_origin = get_cyclic(&bg.background_origin.0, index).clone();
let bg_size = get_cyclic(&bg.background_size.0, index).clone();
let bg_position_x = get_cyclic(&bg.background_position_x.0, index).clone();
let bg_position_y = get_cyclic(&bg.background_position_y.0, index).clone();
let mut bounds = absolute_bounds;
match bg_origin {
BackgroundOrigin::BorderBox => {}
BackgroundOrigin::PaddingBox => {
let border = style.logical_border_width().to_physical(style.writing_mode);
bounds.origin.x += border.left;
bounds.origin.y += border.top;
bounds.size.width -= border.horizontal();
bounds.size.height -= border.vertical();
}
BackgroundOrigin::ContentBox => {
let border_padding = self.border_padding.to_physical(style.writing_mode);
bounds.origin.x += border_padding.left;
bounds.origin.y += border_padding.top;
bounds.size.width -= border_padding.horizontal();
bounds.size.height -= border_padding.vertical();
}
}
bounds.origin.x += bg_position_x.to_used_value(bounds.size.width);
bounds.origin.y += bg_position_y.to_used_value(bounds.size.height);
let tile = match bg_size {
BackgroundSize::Cover | BackgroundSize::Contain => bounds.size,
BackgroundSize::Explicit { width, height } => {
Size2D::new(
MaybeAuto::from_style(width, bounds.size.width)
.specified_or_default(bounds.size.width),
MaybeAuto::from_style(height, bounds.size.height)
.specified_or_default(bounds.size.height))
}
};
let diff_x = get_first_tile(absolute_bounds.origin.x,
bounds.origin.x,
tile.width);
let diff_y = get_first_tile(absolute_bounds.origin.y,
bounds.origin.y,
tile.height);
let tiled_bounds = Rect::new(
Point2D::new(bounds.origin.x - diff_x, bounds.origin.y - diff_y),
Size2D::new(absolute_bounds.size.width + diff_x,
absolute_bounds.size.height + diff_y));
let base = state.create_base_display_item(&tiled_bounds,
*clip, *clip,
self.node, self.node,
style.get_cursor(Cursor::Default), style.get_cursor(Cursor::Default),
display_list_section); display_list_section);
let display_item = match gradient.kind { let display_item = match gradient.kind {
GradientKind::Linear(ref angle_or_corner) => { GradientKind::Linear(angle_or_corner) => {
let gradient = self.convert_linear_gradient(&bounds, let gradient = convert_linear_gradient(
&gradient.items[..], tile,
angle_or_corner, &gradient.items[..],
gradient.repeating); angle_or_corner,
gradient.repeating);
DisplayItem::Gradient(Box::new(GradientDisplayItem { DisplayItem::Gradient(Box::new(GradientDisplayItem {
base: base, base: base,
gradient: gradient, gradient: gradient,
tile: tile,
})) }))
} }
GradientKind::Radial(ref shape, ref center, _angle) => { GradientKind::Radial(shape, center, _angle) => {
let gradient = self.convert_radial_gradient(&bounds, let gradient = convert_radial_gradient(
&gradient.items[..], tile,
shape, &gradient.items[..],
center, shape,
gradient.repeating); center,
gradient.repeating);
DisplayItem::RadialGradient(Box::new(RadialGradientDisplayItem { DisplayItem::RadialGradient(Box::new(RadialGradientDisplayItem {
base: base, base: base,
gradient: gradient, gradient: gradient,
tile: tile,
})) }))
} }
}; };
@ -1594,10 +1646,10 @@ impl FragmentDisplayListBuilding for Fragment {
Either::Second(Image::Gradient(ref gradient)) => { Either::Second(Image::Gradient(ref gradient)) => {
match gradient.kind { match gradient.kind {
GradientKind::Linear(angle_or_corner) => { GradientKind::Linear(angle_or_corner) => {
let grad = self.convert_linear_gradient(&bounds, let grad = convert_linear_gradient(bounds.size,
&gradient.items[..], &gradient.items[..],
&angle_or_corner, angle_or_corner,
gradient.repeating); gradient.repeating);
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem { state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
base: base, base: base,
@ -1610,12 +1662,12 @@ impl FragmentDisplayListBuilding for Fragment {
}), }),
}))); })));
} }
GradientKind::Radial(ref shape, ref center, _angle) => { GradientKind::Radial(shape, center, _angle) => {
let grad = self.convert_radial_gradient(&bounds, let grad = convert_radial_gradient(bounds.size,
&gradient.items[..], &gradient.items[..],
shape, shape,
center, center,
gradient.repeating); gradient.repeating);
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem { state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
base: base, base: base,
border_widths: border.to_physical(style.writing_mode), border_widths: border.to_physical(style.writing_mode),
@ -1700,7 +1752,7 @@ impl FragmentDisplayListBuilding for Fragment {
style: &ComputedValues, style: &ComputedValues,
bounds: &Rect<Au>, bounds: &Rect<Au>,
clip: &Rect<Au>) { clip: &Rect<Au>) {
use style::values::Either; use style::values::specified::outline::OutlineStyle;
let width = Au::from(style.get_outline().outline_width); let width = Au::from(style.get_outline().outline_width);
if width == Au(0) { if width == Au(0) {
@ -1708,9 +1760,9 @@ impl FragmentDisplayListBuilding for Fragment {
} }
let outline_style = match style.get_outline().outline_style { let outline_style = match style.get_outline().outline_style {
Either::First(_auto) => BorderStyle::Solid, OutlineStyle::Auto => BorderStyle::Solid,
Either::Second(BorderStyle::None) => return, OutlineStyle::Other(BorderStyle::None) => return,
Either::Second(border_style) => border_style OutlineStyle::Other(border_style) => border_style
}; };
// Outlines are not accounted for in the dimensions of the border box, so adjust the // Outlines are not accounted for in the dimensions of the border box, so adjust the

View file

@ -13,8 +13,7 @@ use display_list_builder::{DisplayListBuildState, FlexFlowDisplayListBuilding};
use display_list_builder::StackingContextCollectionState; use display_list_builder::StackingContextCollectionState;
use euclid::Point2D; use euclid::Point2D;
use floats::FloatKind; use floats::FloatKind;
use flow; use flow::{Flow, FlowClass, GetBaseFlow, ImmutableFlowUtils, OpaqueFlow, FlowFlags};
use flow::{Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow, FlowFlags};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use layout_debug; use layout_debug;
use model::{AdjoiningMargins, CollapsibleMargins}; use model::{AdjoiningMargins, CollapsibleMargins};
@ -451,7 +450,7 @@ impl FlexFlow {
let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes(); let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes();
if !fixed_width { if !fixed_width {
for kid in self.block_flow.base.children.iter_mut() { for kid in self.block_flow.base.children.iter_mut() {
let base = flow::mut_base(kid); let base = kid.mut_base();
let is_absolutely_positioned = base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); let is_absolutely_positioned = base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
if !is_absolutely_positioned { if !is_absolutely_positioned {
let flex_item_inline_sizes = IntrinsicISizes { let flex_item_inline_sizes = IntrinsicISizes {
@ -477,7 +476,7 @@ impl FlexFlow {
let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes(); let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes();
if !fixed_width { if !fixed_width {
for kid in self.block_flow.base.children.iter_mut() { for kid in self.block_flow.base.children.iter_mut() {
let base = flow::mut_base(kid); let base = kid.mut_base();
let is_absolutely_positioned = base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); let is_absolutely_positioned = base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
if !is_absolutely_positioned { if !is_absolutely_positioned {
computation.content_intrinsic_sizes.minimum_inline_size = computation.content_intrinsic_sizes.minimum_inline_size =
@ -519,7 +518,7 @@ impl FlexFlow {
let mut children = self.block_flow.base.children.random_access_mut(); let mut children = self.block_flow.base.children.random_access_mut();
for kid in &mut self.items { for kid in &mut self.items {
let kid_base = flow::mut_base(children.get(kid.index)); let kid_base = children.get(kid.index).mut_base();
kid_base.block_container_explicit_block_size = container_block_size; kid_base.block_container_explicit_block_size = container_block_size;
if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) { if kid_base.flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) {
// The inline-start margin edge of the child flow is at our inline-start content // The inline-start margin edge of the child flow is at our inline-start content
@ -667,7 +666,7 @@ impl FlexFlow {
let mut children = self.block_flow.base.children.random_access_mut(); let mut children = self.block_flow.base.children.random_access_mut();
for item in &mut self.items { for item in &mut self.items {
let base = flow::mut_base(children.get(item.index)); let base = children.get(item.index).mut_base();
if !self.main_reverse { if !self.main_reverse {
base.position.start.b = cur_b; base.position.start.b = cur_b;
cur_b = cur_b + base.position.size.block; cur_b = cur_b + base.position.size.block;

View file

@ -4,7 +4,7 @@
use app_units::{Au, MAX_AU}; use app_units::{Au, MAX_AU};
use block::FormattingContextType; use block::FormattingContextType;
use flow::{self, Flow, FlowFlags, ImmutableFlowUtils}; use flow::{Flow, FlowFlags, GetBaseFlow, ImmutableFlowUtils};
use persistent_list::PersistentList; use persistent_list::PersistentList;
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::fmt; use std::fmt;
@ -458,7 +458,7 @@ impl SpeculatedFloatPlacement {
/// Given the speculated inline size of the floats out for the inorder predecessor of this /// Given the speculated inline size of the floats out for the inorder predecessor of this
/// flow, computes the speculated inline size of the floats flowing in. /// flow, computes the speculated inline size of the floats flowing in.
pub fn compute_floats_in(&mut self, flow: &mut Flow) { pub fn compute_floats_in(&mut self, flow: &mut Flow) {
let base_flow = flow::base(flow); let base_flow = flow.base();
if base_flow.flags.contains(FlowFlags::CLEARS_LEFT) { if base_flow.flags.contains(FlowFlags::CLEARS_LEFT) {
self.left = Au(0) self.left = Au(0)
} }
@ -491,7 +491,7 @@ impl SpeculatedFloatPlacement {
} }
} }
let base_flow = flow::base(flow); let base_flow = flow.base();
if !base_flow.flags.is_float() { if !base_flow.flags.is_float() {
return return
} }
@ -522,7 +522,7 @@ impl SpeculatedFloatPlacement {
/// Given a flow, computes the speculated inline size of the floats in of its first child. /// Given a flow, computes the speculated inline size of the floats in of its first child.
pub fn compute_floats_in_for_first_child(parent_flow: &mut Flow) -> SpeculatedFloatPlacement { pub fn compute_floats_in_for_first_child(parent_flow: &mut Flow) -> SpeculatedFloatPlacement {
if !parent_flow.is_block_like() { if !parent_flow.is_block_like() {
return flow::base(parent_flow).speculated_float_placement_in return parent_flow.base().speculated_float_placement_in
} }
let parent_block_flow = parent_flow.as_block(); let parent_block_flow = parent_flow.as_block();

View file

@ -76,6 +76,30 @@ use table_wrapper::TableWrapperFlow;
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub unsafe trait HasBaseFlow {} pub unsafe trait HasBaseFlow {}
/// Methods to get the `BaseFlow` from any `HasBaseFlow` type.
pub trait GetBaseFlow {
fn base(&self) -> &BaseFlow;
fn mut_base(&mut self) -> &mut BaseFlow;
}
impl<T: HasBaseFlow + ?Sized> GetBaseFlow for T {
#[inline(always)]
#[allow(unsafe_code)]
fn base(&self) -> &BaseFlow {
let ptr: *const Self = self;
let ptr = ptr as *const BaseFlow;
unsafe { &*ptr }
}
#[inline(always)]
#[allow(unsafe_code)]
fn mut_base(&mut self) -> &mut BaseFlow {
let ptr: *mut Self = self;
let ptr = ptr as *mut BaseFlow;
unsafe { &mut *ptr }
}
}
/// Virtual methods that make up a float context. /// Virtual methods that make up a float context.
/// ///
/// Note that virtual methods have a cost; we should not overuse them in Servo. Consider adding /// Note that virtual methods have a cost; we should not overuse them in Servo. Consider adding
@ -224,8 +248,8 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
layout_context: &LayoutContext, layout_context: &LayoutContext,
_fragmentation_context: Option<FragmentationContext>) _fragmentation_context: Option<FragmentationContext>)
-> Option<Arc<Flow>> { -> Option<Arc<Flow>> {
fn recursive_assign_block_size<F: ?Sized + Flow>(flow: &mut F, ctx: &LayoutContext) { fn recursive_assign_block_size<F: ?Sized + Flow + GetBaseFlow>(flow: &mut F, ctx: &LayoutContext) {
for child in mut_base(flow).children.iter_mut() { for child in flow.mut_base().child_iter_mut() {
recursive_assign_block_size(child, ctx) recursive_assign_block_size(child, ctx)
} }
flow.assign_block_size(ctx); flow.assign_block_size(ctx);
@ -251,12 +275,12 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
parent_thread_id: u8, parent_thread_id: u8,
_content_box: LogicalRect<Au>) _content_box: LogicalRect<Au>)
-> bool { -> bool {
let might_have_floats_in_or_out = base(self).might_have_floats_in() || let might_have_floats_in_or_out = self.base().might_have_floats_in() ||
base(self).might_have_floats_out(); self.base().might_have_floats_out();
if might_have_floats_in_or_out { if might_have_floats_in_or_out {
mut_base(self).thread_id = parent_thread_id; self.mut_base().thread_id = parent_thread_id;
self.assign_block_size(layout_context); self.assign_block_size(layout_context);
mut_base(self).restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); self.mut_base().restyle_damage.remove(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW);
} }
might_have_floats_in_or_out might_have_floats_in_or_out
} }
@ -264,9 +288,9 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
fn get_overflow_in_parent_coordinates(&self) -> Overflow { fn get_overflow_in_parent_coordinates(&self) -> Overflow {
// FIXME(#2795): Get the real container size. // FIXME(#2795): Get the real container size.
let container_size = Size2D::zero(); let container_size = Size2D::zero();
let position = base(self).position.to_physical(base(self).writing_mode, container_size); let position = self.base().position.to_physical(self.base().writing_mode, container_size);
let mut overflow = base(self).overflow; let mut overflow = self.base().overflow;
match self.class() { match self.class() {
FlowClass::Block | FlowClass::TableCaption | FlowClass::TableCell => {} FlowClass::Block | FlowClass::TableCaption | FlowClass::TableCell => {}
@ -277,9 +301,9 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
} }
let border_box = self.as_block().fragment.stacking_relative_border_box( let border_box = self.as_block().fragment.stacking_relative_border_box(
&base(self).stacking_relative_position, &self.base().stacking_relative_position,
&base(self).early_absolute_position_info.relative_containing_block_size, &self.base().early_absolute_position_info.relative_containing_block_size,
base(self).early_absolute_position_info.relative_containing_block_mode, self.base().early_absolute_position_info.relative_containing_block_mode,
CoordinateSystem::Own); CoordinateSystem::Own);
if StyleOverflow::Visible != self.as_block().fragment.style.get_box().overflow_x { if StyleOverflow::Visible != self.as_block().fragment.style.get_box().overflow_x {
overflow.paint.origin.x = Au(0); overflow.paint.origin.x = Au(0);
@ -341,13 +365,13 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
FlowClass::Block | FlowClass::Block |
FlowClass::TableCaption | FlowClass::TableCaption |
FlowClass::TableCell => { FlowClass::TableCell => {
for kid in mut_base(self).children.iter_mut() { for kid in self.mut_base().children.iter_mut() {
overflow.union(&kid.get_overflow_in_parent_coordinates()); overflow.union(&kid.get_overflow_in_parent_coordinates());
} }
} }
_ => {} _ => {}
} }
mut_base(self).overflow = overflow self.mut_base().overflow = overflow
} }
/// Phase 4 of reflow: Compute the stacking-relative position (origin of the content box, /// Phase 4 of reflow: Compute the stacking-relative position (origin of the content box,
@ -406,7 +430,7 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
fn contains_positioned_fragments(&self) -> bool { fn contains_positioned_fragments(&self) -> bool {
self.contains_relatively_positioned_fragments() || self.contains_relatively_positioned_fragments() ||
base(self).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) self.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED)
} }
fn contains_relatively_positioned_fragments(&self) -> bool { fn contains_relatively_positioned_fragments(&self) -> bool {
@ -448,41 +472,13 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
fn print_extra_flow_children(&self, _: &mut PrintTree) { } fn print_extra_flow_children(&self, _: &mut PrintTree) { }
fn clipping_and_scrolling(&self) -> ClippingAndScrolling { fn clipping_and_scrolling(&self) -> ClippingAndScrolling {
match base(self).clipping_and_scrolling { match self.base().clipping_and_scrolling {
Some(info) => info, Some(info) => info,
None => unreachable!("Tried to access scroll root id on Flow before assignment"), None => unreachable!("Tried to access scroll root id on Flow before assignment"),
} }
} }
} }
// Base access
#[inline(always)]
#[allow(unsafe_code)]
pub fn base<T: ?Sized + HasBaseFlow>(this: &T) -> &BaseFlow {
let ptr: *const T = this;
let ptr = ptr as *const BaseFlow;
unsafe { &*ptr }
}
/// Iterates over the children of this immutable flow.
pub fn child_iter<'a>(flow: &'a Flow) -> FlowListIterator {
base(flow).children.iter()
}
#[inline(always)]
#[allow(unsafe_code)]
pub fn mut_base<T: ?Sized + HasBaseFlow>(this: &mut T) -> &mut BaseFlow {
let ptr: *mut T = this;
let ptr = ptr as *mut BaseFlow;
unsafe { &mut *ptr }
}
/// Iterates over the children of this flow.
pub fn child_iter_mut<'a>(flow: &'a mut Flow) -> MutFlowListIterator<'a> {
mut_base(flow).children.iter_mut()
}
pub trait ImmutableFlowUtils { pub trait ImmutableFlowUtils {
// Convenience functions // Convenience functions
@ -1106,6 +1102,11 @@ impl BaseFlow {
} }
} }
/// Iterates over the children of this immutable flow.
pub fn child_iter(&self) -> FlowListIterator {
self.children.iter()
}
pub fn child_iter_mut(&mut self) -> MutFlowListIterator { pub fn child_iter_mut(&mut self) -> MutFlowListIterator {
self.children.iter_mut() self.children.iter_mut()
} }
@ -1216,12 +1217,12 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
/// Returns true if this flow has no children. /// Returns true if this flow has no children.
fn is_leaf(self) -> bool { fn is_leaf(self) -> bool {
base(self).children.is_empty() self.base().children.is_empty()
} }
/// Returns the number of children that this flow possesses. /// Returns the number of children that this flow possesses.
fn child_count(self) -> usize { fn child_count(self) -> usize {
base(self).children.len() self.base().children.len()
} }
/// Return true if this flow is a Block Container. /// Return true if this flow is a Block Container.
@ -1267,14 +1268,14 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
fn print_with_tree(self, print_tree: &mut PrintTree) { fn print_with_tree(self, print_tree: &mut PrintTree) {
print_tree.new_level(format!("{:?}", self)); print_tree.new_level(format!("{:?}", self));
self.print_extra_flow_children(print_tree); self.print_extra_flow_children(print_tree);
for kid in child_iter(self) { for kid in self.base().child_iter() {
kid.print_with_tree(print_tree); kid.print_with_tree(print_tree);
} }
print_tree.end_level(); print_tree.end_level();
} }
fn floats_might_flow_through(self) -> bool { fn floats_might_flow_through(self) -> bool {
if !base(self).might_have_floats_in() && !base(self).might_have_floats_out() { if !self.base().might_have_floats_in() && !self.base().might_have_floats_out() {
return false return false
} }
if self.is_root() { if self.is_root() {
@ -1287,15 +1288,15 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
} }
fn baseline_offset_of_last_line_box_in_flow(self) -> Option<Au> { fn baseline_offset_of_last_line_box_in_flow(self) -> Option<Au> {
for kid in base(self).children.iter().rev() { for kid in self.base().children.iter().rev() {
if kid.is_inline_flow() { if kid.is_inline_flow() {
if let Some(baseline_offset) = kid.as_inline().baseline_offset_of_last_line() { if let Some(baseline_offset) = kid.as_inline().baseline_offset_of_last_line() {
return Some(base(kid).position.start.b + baseline_offset) return Some(kid.base().position.start.b + baseline_offset)
} }
} }
if kid.is_block_like() && !base(kid).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if kid.is_block_like() && !kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
if let Some(baseline_offset) = kid.baseline_offset_of_last_line_box_in_flow() { if let Some(baseline_offset) = kid.baseline_offset_of_last_line_box_in_flow() {
return Some(base(kid).position.start.b + baseline_offset) return Some(kid.base().position.start.b + baseline_offset)
} }
} }
} }
@ -1308,7 +1309,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
/// calling them individually, since there is no reason not to perform both operations. /// calling them individually, since there is no reason not to perform both operations.
fn repair_style_and_bubble_inline_sizes(self, style: &::ServoArc<ComputedValues>) { fn repair_style_and_bubble_inline_sizes(self, style: &::ServoArc<ComputedValues>) {
self.repair_style(style); self.repair_style(style);
mut_base(self).update_flags_if_needed(style); self.mut_base().update_flags_if_needed(style);
self.bubble_inline_sizes(); self.bubble_inline_sizes();
} }
} }
@ -1323,11 +1324,11 @@ impl MutableOwnedFlowUtils for FlowRef {
/// construction is allowed to possess. /// construction is allowed to possess.
fn set_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants) { fn set_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants) {
let this = self.clone(); let this = self.clone();
let base = mut_base(FlowRef::deref_mut(self)); let base = FlowRef::deref_mut(self).mut_base();
base.abs_descendants = abs_descendants; base.abs_descendants = abs_descendants;
for descendant_link in base.abs_descendants.descendant_links.iter_mut() { for descendant_link in base.abs_descendants.descendant_links.iter_mut() {
debug_assert!(!descendant_link.has_reached_containing_block); debug_assert!(!descendant_link.has_reached_containing_block);
let descendant_base = mut_base(FlowRef::deref_mut(&mut descendant_link.flow)); let descendant_base = FlowRef::deref_mut(&mut descendant_link.flow).mut_base();
descendant_base.absolute_cb.set(this.clone()); descendant_base.absolute_cb.set(this.clone());
} }
} }
@ -1353,10 +1354,10 @@ impl MutableOwnedFlowUtils for FlowRef {
}); });
let this = self.clone(); let this = self.clone();
let base = mut_base(FlowRef::deref_mut(self)); let base = FlowRef::deref_mut(self).mut_base();
base.abs_descendants = applicable_absolute_descendants; base.abs_descendants = applicable_absolute_descendants;
for descendant_link in base.abs_descendants.iter() { for descendant_link in base.abs_descendants.iter() {
let descendant_base = mut_base(descendant_link); let descendant_base = descendant_link.mut_base();
descendant_base.absolute_cb.set(this.clone()); descendant_base.absolute_cb.set(this.clone());
} }
} }

View file

@ -12,7 +12,7 @@ use canvas_traits::canvas::CanvasMsg;
use context::{LayoutContext, with_thread_local_font_context}; use context::{LayoutContext, with_thread_local_font_context};
use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D}; use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D};
use floats::ClearType; use floats::ClearType;
use flow::{self, ImmutableFlowUtils}; use flow::{GetBaseFlow, ImmutableFlowUtils};
use flow_ref::FlowRef; use flow_ref::FlowRef;
use gfx; use gfx;
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode}; use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
@ -232,7 +232,7 @@ impl SpecificFragmentInfo {
SpecificFragmentInfo::InlineBlock(ref info) => &info.flow_ref, SpecificFragmentInfo::InlineBlock(ref info) => &info.flow_ref,
}; };
flow::base(&**flow).restyle_damage flow.base().restyle_damage
} }
pub fn get_type(&self) -> &'static str { pub fn get_type(&self) -> &'static str {
@ -1750,22 +1750,17 @@ impl Fragment {
let character_breaking_strategy = let character_breaking_strategy =
text_fragment_info.run.character_slices_in_range(&text_fragment_info.range); text_fragment_info.run.character_slices_in_range(&text_fragment_info.range);
match self.calculate_split_position_using_breaking_strategy(character_breaking_strategy,
max_inline_size, let split_info = self.calculate_split_position_using_breaking_strategy(
SplitOptions::empty()) { character_breaking_strategy,
None => None, max_inline_size,
Some(split_info) => { SplitOptions::empty())?;
match split_info.inline_start {
None => None, let split = split_info.inline_start?;
Some(split) => { Some(TruncationResult {
Some(TruncationResult { split: split,
split: split, text_run: split_info.text_run.clone(),
text_run: split_info.text_run.clone(), })
})
}
}
}
}
} }
/// A helper method that uses the breaking strategy described by `slice_iterator` (at present, /// A helper method that uses the breaking strategy described by `slice_iterator` (at present,
@ -2617,11 +2612,11 @@ impl Fragment {
match self.specific { match self.specific {
SpecificFragmentInfo::InlineBlock(ref info) => { SpecificFragmentInfo::InlineBlock(ref info) => {
let block_flow = info.flow_ref.as_block(); let block_flow = info.flow_ref.as_block();
overflow.union(&flow::base(block_flow).overflow); overflow.union(&block_flow.base().overflow);
} }
SpecificFragmentInfo::InlineAbsolute(ref info) => { SpecificFragmentInfo::InlineAbsolute(ref info) => {
let block_flow = info.flow_ref.as_block(); let block_flow = info.flow_ref.as_block();
overflow.union(&flow::base(block_flow).overflow); overflow.union(&block_flow.base().overflow);
} }
_ => (), _ => (),
} }

View file

@ -9,7 +9,7 @@
//! as possible. //! as possible.
use context::{LayoutContext, with_thread_local_font_context}; use context::{LayoutContext, with_thread_local_font_context};
use flow::{self, Flow, FlowFlags, ImmutableFlowUtils}; use flow::{Flow, FlowFlags, GetBaseFlow, ImmutableFlowUtils};
use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo}; use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
use gfx::display_list::OpaqueNode; use gfx::display_list::OpaqueNode;
use script_layout_interface::wrapper_traits::PseudoElementType; use script_layout_interface::wrapper_traits::PseudoElementType;
@ -132,8 +132,8 @@ impl<'a> InorderFlowTraversal for ResolveGeneratedContent<'a> {
#[inline] #[inline]
fn should_process_subtree(&mut self, flow: &mut Flow) -> bool { fn should_process_subtree(&mut self, flow: &mut Flow) -> bool {
flow::base(flow).restyle_damage.intersects(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT) || flow.base().restyle_damage.intersects(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT) ||
flow::base(flow).flags.intersects(FlowFlags::AFFECTS_COUNTERS | FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN) flow.base().flags.intersects(FlowFlags::AFFECTS_COUNTERS | FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN)
} }
} }
@ -311,9 +311,9 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> {
&quotes.0[self.traversal.quote as usize] &quotes.0[self.traversal.quote as usize]
}; };
if close { if close {
close_quote.clone() close_quote.to_string()
} else { } else {
open_quote.clone() open_quote.to_string()
} }
} }
} }

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use flow::{self, FlowFlags, Flow}; use flow::{FlowFlags, Flow, GetBaseFlow};
use style::computed_values::float::T as Float; use style::computed_values::float::T as Float;
use style::selector_parser::RestyleDamage; use style::selector_parser::RestyleDamage;
use style::servo::restyle_damage::ServoRestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage;
@ -30,20 +30,20 @@ pub trait LayoutDamageComputation {
impl<'a> LayoutDamageComputation for &'a mut Flow { impl<'a> LayoutDamageComputation for &'a mut Flow {
fn compute_layout_damage(self) -> SpecialRestyleDamage { fn compute_layout_damage(self) -> SpecialRestyleDamage {
let mut special_damage = SpecialRestyleDamage::empty(); let mut special_damage = SpecialRestyleDamage::empty();
let is_absolutely_positioned = flow::base(self).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); let is_absolutely_positioned = self.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
// In addition to damage, we use this phase to compute whether nodes affect CSS counters. // In addition to damage, we use this phase to compute whether nodes affect CSS counters.
let mut has_counter_affecting_children = false; let mut has_counter_affecting_children = false;
{ {
let self_base = flow::mut_base(self); let self_base = self.mut_base();
// Take a snapshot of the parent damage before updating it with damage from children. // Take a snapshot of the parent damage before updating it with damage from children.
let parent_damage = self_base.restyle_damage; let parent_damage = self_base.restyle_damage;
for kid in self_base.children.iter_mut() { for kid in self_base.children.iter_mut() {
let child_is_absolutely_positioned = let child_is_absolutely_positioned =
flow::base(kid).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
flow::mut_base(kid).restyle_damage.insert( kid.mut_base().restyle_damage.insert(
parent_damage.damage_for_child(is_absolutely_positioned, parent_damage.damage_for_child(is_absolutely_positioned,
child_is_absolutely_positioned)); child_is_absolutely_positioned));
{ {
@ -51,16 +51,16 @@ impl<'a> LayoutDamageComputation for &'a mut Flow {
special_damage.insert(kid.compute_layout_damage()); special_damage.insert(kid.compute_layout_damage());
} }
self_base.restyle_damage self_base.restyle_damage
.insert(flow::base(kid).restyle_damage.damage_for_parent( .insert(kid.base().restyle_damage.damage_for_parent(
child_is_absolutely_positioned)); child_is_absolutely_positioned));
has_counter_affecting_children = has_counter_affecting_children || has_counter_affecting_children = has_counter_affecting_children ||
flow::base(kid).flags.intersects(FlowFlags::AFFECTS_COUNTERS | kid.base().flags.intersects(FlowFlags::AFFECTS_COUNTERS |
FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN); FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN);
} }
} }
let self_base = flow::mut_base(self); let self_base = self.mut_base();
if self_base.flags.float_kind() != Float::None && if self_base.flags.float_kind() != Float::None &&
self_base.restyle_damage.intersects(ServoRestyleDamage::REFLOW) { self_base.restyle_damage.intersects(ServoRestyleDamage::REFLOW) {
special_damage.insert(SpecialRestyleDamage::REFLOW_ENTIRE_DOCUMENT); special_damage.insert(SpecialRestyleDamage::REFLOW_ENTIRE_DOCUMENT);
@ -76,7 +76,7 @@ impl<'a> LayoutDamageComputation for &'a mut Flow {
} }
fn reflow_entire_document(self) { fn reflow_entire_document(self) {
let self_base = flow::mut_base(self); let self_base = self.mut_base();
self_base.restyle_damage.insert(RestyleDamage::rebuild_and_reflow()); self_base.restyle_damage.insert(RestyleDamage::rebuild_and_reflow());
self_base.restyle_damage.remove(ServoRestyleDamage::RECONSTRUCT_FLOW); self_base.restyle_damage.remove(ServoRestyleDamage::RECONSTRUCT_FLOW);
for kid in self_base.children.iter_mut() { for kid in self_base.children.iter_mut() {

View file

@ -12,8 +12,8 @@ use display_list_builder::{DisplayListBuildState, InlineFlowDisplayListBuilding}
use display_list_builder::StackingContextCollectionState; use display_list_builder::StackingContextCollectionState;
use euclid::{Point2D, Size2D}; use euclid::{Point2D, Size2D};
use floats::{FloatKind, Floats, PlacementInfo}; use floats::{FloatKind, Floats, PlacementInfo};
use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag}; use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag};
use flow::{FlowFlags, EarlyAbsolutePositionInfo, OpaqueFlow}; use flow::{FlowFlags, EarlyAbsolutePositionInfo, GetBaseFlow, OpaqueFlow};
use flow_ref::FlowRef; use flow_ref::FlowRef;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
use fragment::FragmentFlags; use fragment::FragmentFlags;
@ -1315,7 +1315,7 @@ impl Flow for InlineFlow {
let writing_mode = self.base.writing_mode; let writing_mode = self.base.writing_mode;
for kid in self.base.child_iter_mut() { for kid in self.base.child_iter_mut() {
flow::mut_base(kid).floats = Floats::new(writing_mode); kid.mut_base().floats = Floats::new(writing_mode);
} }
self.base.flags.remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); self.base.flags.remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS);
@ -1423,7 +1423,7 @@ impl Flow for InlineFlow {
// sizes down to them. // sizes down to them.
let block_container_explicit_block_size = self.base.block_container_explicit_block_size; let block_container_explicit_block_size = self.base.block_container_explicit_block_size;
for kid in self.base.child_iter_mut() { for kid in self.base.child_iter_mut() {
let kid_base = flow::mut_base(kid); let kid_base = kid.mut_base();
kid_base.block_container_inline_size = inline_size; kid_base.block_container_inline_size = inline_size;
kid_base.block_container_writing_mode = container_mode; kid_base.block_container_writing_mode = container_mode;
@ -1524,14 +1524,14 @@ impl Flow for InlineFlow {
match f.specific { match f.specific {
SpecificFragmentInfo::InlineBlock(ref mut info) => { SpecificFragmentInfo::InlineBlock(ref mut info) => {
let block = FlowRef::deref_mut(&mut info.flow_ref); let block = FlowRef::deref_mut(&mut info.flow_ref);
flow::mut_base(block).early_absolute_position_info = EarlyAbsolutePositionInfo { block.mut_base().early_absolute_position_info = EarlyAbsolutePositionInfo {
relative_containing_block_size: containing_block_size, relative_containing_block_size: containing_block_size,
relative_containing_block_mode: writing_mode, relative_containing_block_mode: writing_mode,
}; };
} }
SpecificFragmentInfo::InlineAbsolute(ref mut info) => { SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
let block = FlowRef::deref_mut(&mut info.flow_ref); let block = FlowRef::deref_mut(&mut info.flow_ref);
flow::mut_base(block).early_absolute_position_info = EarlyAbsolutePositionInfo { block.mut_base().early_absolute_position_info = EarlyAbsolutePositionInfo {
relative_containing_block_size: containing_block_size, relative_containing_block_size: containing_block_size,
relative_containing_block_mode: writing_mode, relative_containing_block_mode: writing_mode,
}; };
@ -1757,7 +1757,7 @@ impl fmt::Debug for InlineFlow {
"{:?}({:x}) {:?}", "{:?}({:x}) {:?}",
self.class(), self.class(),
self.base.debug_id(), self.base.debug_id(),
flow::base(self)) self.base())
} }
} }

View file

@ -5,7 +5,7 @@
//! Supports writing a trace file created during each layout scope //! Supports writing a trace file created during each layout scope
//! that can be viewed by an external tool to make layout debugging easier. //! that can be viewed by an external tool to make layout debugging easier.
use flow; use flow::GetBaseFlow;
use flow_ref::FlowRef; use flow_ref::FlowRef;
use serde_json::{to_string, to_value, Value}; use serde_json::{to_string, to_value, Value};
use std::borrow::ToOwned; use std::borrow::ToOwned;
@ -63,7 +63,7 @@ impl Scope {
pub fn new(name: String) -> Scope { pub fn new(name: String) -> Scope {
STATE_KEY.with(|ref r| { STATE_KEY.with(|ref r| {
if let Some(ref mut state) = *r.borrow_mut() { if let Some(ref mut state) = *r.borrow_mut() {
let flow_trace = to_value(&flow::base(&*state.flow_root)).unwrap(); let flow_trace = to_value(&state.flow_root.base()).unwrap();
let data = Box::new(ScopeData::new(name.clone(), flow_trace)); let data = Box::new(ScopeData::new(name.clone(), flow_trace));
state.scope_stack.push(data); state.scope_stack.push(data);
} }
@ -78,7 +78,7 @@ impl Drop for Scope {
STATE_KEY.with(|ref r| { STATE_KEY.with(|ref r| {
if let Some(ref mut state) = *r.borrow_mut() { if let Some(ref mut state) = *r.borrow_mut() {
let mut current_scope = state.scope_stack.pop().unwrap(); let mut current_scope = state.scope_stack.pop().unwrap();
current_scope.post = to_value(&flow::base(&*state.flow_root)).unwrap(); current_scope.post = to_value(&state.flow_root.base()).unwrap();
let previous_scope = state.scope_stack.last_mut().unwrap(); let previous_scope = state.scope_stack.last_mut().unwrap();
previous_scope.children.push(current_scope); previous_scope.children.push(current_scope);
} }
@ -100,7 +100,7 @@ pub fn begin_trace(flow_root: FlowRef) {
assert!(STATE_KEY.with(|ref r| r.borrow().is_none())); assert!(STATE_KEY.with(|ref r| r.borrow().is_none()));
STATE_KEY.with(|ref r| { STATE_KEY.with(|ref r| {
let flow_trace = to_value(&flow::base(&*flow_root)).unwrap(); let flow_trace = to_value(&flow_root.base()).unwrap();
let state = State { let state = State {
scope_stack: vec![Box::new(ScopeData::new("root".to_owned(), flow_trace))], scope_stack: vec![Box::new(ScopeData::new("root".to_owned(), flow_trace))],
flow_root: flow_root.clone(), flow_root: flow_root.clone(),
@ -116,7 +116,7 @@ pub fn end_trace(generation: u32) {
let mut thread_state = STATE_KEY.with(|ref r| r.borrow_mut().take().unwrap()); let mut thread_state = STATE_KEY.with(|ref r| r.borrow_mut().take().unwrap());
assert!(thread_state.scope_stack.len() == 1); assert!(thread_state.scope_stack.len() == 1);
let mut root_scope = thread_state.scope_stack.pop().unwrap(); let mut root_scope = thread_state.scope_stack.pop().unwrap();
root_scope.post = to_value(&flow::base(&*thread_state.flow_root)).unwrap(); root_scope.post = to_value(&thread_state.flow_root.base()).unwrap();
let result = to_string(&root_scope).unwrap(); let result = to_string(&root_scope).unwrap();
let mut file = File::create(format!("layout_trace-{}.json", generation)).unwrap(); let mut file = File::create(format!("layout_trace-{}.json", generation)).unwrap();

View file

@ -13,7 +13,7 @@ use context::LayoutContext;
use display_list_builder::{DisplayListBuildState, StackingContextCollectionState}; use display_list_builder::{DisplayListBuildState, StackingContextCollectionState};
use euclid::{Point2D, Vector2D}; use euclid::{Point2D, Vector2D};
use floats::FloatKind; use floats::FloatKind;
use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext}; use flow::{Flow, FlowClass, OpaqueFlow, FragmentationContext, GetBaseFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx_traits::print_tree::PrintTree; use gfx_traits::print_tree::PrintTree;
use std::cmp::{min, max}; use std::cmp::{min, max};
@ -180,7 +180,7 @@ impl Flow for MulticolFlow {
let pitch = LogicalSize::new(self.block_flow.base.writing_mode, self.column_pitch, Au(0)); let pitch = LogicalSize::new(self.block_flow.base.writing_mode, self.column_pitch, Au(0));
let pitch = pitch.to_physical(self.block_flow.base.writing_mode); let pitch = pitch.to_physical(self.block_flow.base.writing_mode);
for (i, child) in self.block_flow.base.children.iter_mut().enumerate() { for (i, child) in self.block_flow.base.children.iter_mut().enumerate() {
let point = &mut mut_base(child).stacking_relative_position; let point = &mut child.mut_base().stacking_relative_position;
*point = *point + Vector2D::new(pitch.width * i as i32, pitch.height * i as i32); *point = *point + Vector2D::new(pitch.width * i as i32, pitch.height * i as i32);
} }
} }

View file

@ -10,7 +10,7 @@
use block::BlockFlow; use block::BlockFlow;
use context::LayoutContext; use context::LayoutContext;
use flow::{self, Flow}; use flow::{Flow, GetBaseFlow};
use flow_ref::FlowRef; use flow_ref::FlowRef;
use profile_traits::time::{self, TimerMetadata, profile}; use profile_traits::time::{self, TimerMetadata, profile};
use rayon; use rayon;
@ -84,7 +84,7 @@ fn bottom_up_flow(mut unsafe_flow: UnsafeFlow,
} }
let base = flow::mut_base(flow); let base = flow.mut_base();
// Reset the count of children for the next layout traversal. // Reset the count of children for the next layout traversal.
base.parallel.children_count.store(base.children.len() as isize, base.parallel.children_count.store(base.children.len() as isize,
@ -103,7 +103,7 @@ fn bottom_up_flow(mut unsafe_flow: UnsafeFlow,
let parent: &mut Flow = unsafe { let parent: &mut Flow = unsafe {
&mut *(unsafe_parent.0 as *mut Flow) &mut *(unsafe_parent.0 as *mut Flow)
}; };
let parent_base = flow::mut_base(parent); let parent_base = parent.mut_base();
if parent_base.parallel.children_count.fetch_sub(1, Ordering::Relaxed) == 1 { if parent_base.parallel.children_count.fetch_sub(1, Ordering::Relaxed) == 1 {
// We were the last child of our parent. Reflow our parent. // We were the last child of our parent. Reflow our parent.
unsafe_flow = unsafe_parent unsafe_flow = unsafe_parent
@ -127,7 +127,7 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow],
unsafe { unsafe {
// Get a real flow. // Get a real flow.
let flow: &mut Flow = mem::transmute(*unsafe_flow); let flow: &mut Flow = mem::transmute(*unsafe_flow);
flow::mut_base(flow).thread_id = flow.mut_base().thread_id =
pool.current_thread_index().unwrap() as u8; pool.current_thread_index().unwrap() as u8;
if assign_isize_traversal.should_process(flow) { if assign_isize_traversal.should_process(flow) {
@ -136,7 +136,7 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow],
} }
// Possibly enqueue the children. // Possibly enqueue the children.
for kid in flow::child_iter_mut(flow) { for kid in flow.mut_base().child_iter_mut() {
had_children = true; had_children = true;
discovered_child_flows.push(UnsafeFlow(kid)); discovered_child_flows.push(UnsafeFlow(kid));
} }

View file

@ -8,7 +8,7 @@ use app_units::Au;
use construct::ConstructionResult; use construct::ConstructionResult;
use context::LayoutContext; use context::LayoutContext;
use euclid::{Point2D, Vector2D, Rect, Size2D}; use euclid::{Point2D, Vector2D, Rect, Size2D};
use flow::{self, Flow}; use flow::{Flow, GetBaseFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use gfx::display_list::{DisplayList, OpaqueNode, ScrollOffsetMap}; use gfx::display_list::{DisplayList, OpaqueNode, ScrollOffsetMap};
use inline::InlineFragmentNodeFlags; use inline::InlineFragmentNodeFlags;
@ -774,7 +774,7 @@ where
let position = maybe_data.map_or(Point2D::zero(), |data| { let position = maybe_data.map_or(Point2D::zero(), |data| {
match (*data).flow_construction_result { match (*data).flow_construction_result {
ConstructionResult::Flow(ref flow_ref, _) => ConstructionResult::Flow(ref flow_ref, _) =>
flow::base(flow_ref.deref()).stacking_relative_position.to_point(), flow_ref.deref().base().stacking_relative_position.to_point(),
// TODO(dzbarsky) search parents until we find node with a flow ref. // TODO(dzbarsky) search parents until we find node with a flow ref.
// https://github.com/servo/servo/issues/8307 // https://github.com/servo/servo/issues/8307
_ => Point2D::zero() _ => Point2D::zero()

View file

@ -9,7 +9,7 @@ use context::LayoutContext;
use display_list_builder::{DisplayListBuildState, StackingContextCollectionState}; use display_list_builder::{DisplayListBuildState, StackingContextCollectionState};
use euclid::{Point2D, Vector2D}; use euclid::{Point2D, Vector2D};
use floats::SpeculatedFloatPlacement; use floats::SpeculatedFloatPlacement;
use flow::{self, Flow, ImmutableFlowUtils, FlowFlags}; use flow::{Flow, ImmutableFlowUtils, FlowFlags, GetBaseFlow};
use fragment::{FragmentBorderBoxIterator, CoordinateSystem}; use fragment::{FragmentBorderBoxIterator, CoordinateSystem};
use generated_content::ResolveGeneratedContent; use generated_content::ResolveGeneratedContent;
use incremental::RelayoutMode; use incremental::RelayoutMode;
@ -31,7 +31,7 @@ pub fn reflow(root: &mut Flow, layout_context: &LayoutContext, relayout_mode: Re
// Force reflow children during this traversal. This is needed when we failed // Force reflow children during this traversal. This is needed when we failed
// the float speculation of a block formatting context and need to fix it. // the float speculation of a block formatting context and need to fix it.
if relayout_mode == RelayoutMode::Force { if relayout_mode == RelayoutMode::Force {
flow::mut_base(flow) flow.mut_base()
.restyle_damage .restyle_damage
.insert(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW); .insert(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW);
} }
@ -40,7 +40,7 @@ pub fn reflow(root: &mut Flow, layout_context: &LayoutContext, relayout_mode: Re
assign_inline_sizes.process(flow); assign_inline_sizes.process(flow);
} }
for kid in flow::child_iter_mut(flow) { for kid in flow.mut_base().child_iter_mut() {
doit(kid, assign_inline_sizes, assign_block_sizes, relayout_mode); doit(kid, assign_inline_sizes, assign_block_sizes, relayout_mode);
} }
@ -87,11 +87,11 @@ pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut Flow, iterator
stacking_context_position: &Point2D<Au>) { stacking_context_position: &Point2D<Au>) {
flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position); flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position);
for kid in flow::mut_base(flow).child_iter_mut() { for kid in flow.mut_base().child_iter_mut() {
let mut stacking_context_position = *stacking_context_position; let mut stacking_context_position = *stacking_context_position;
if kid.is_block_flow() && kid.as_block().fragment.establishes_stacking_context() { if kid.is_block_flow() && kid.as_block().fragment.establishes_stacking_context() {
stacking_context_position = Point2D::new(kid.as_block().fragment.margin.inline_start, Au(0)) + stacking_context_position = Point2D::new(kid.as_block().fragment.margin.inline_start, Au(0)) +
flow::base(kid).stacking_relative_position + kid.base().stacking_relative_position +
stacking_context_position.to_vector(); stacking_context_position.to_vector();
let relative_position = kid.as_block() let relative_position = kid.as_block()
.stacking_relative_border_box(CoordinateSystem::Own); .stacking_relative_border_box(CoordinateSystem::Own);
@ -112,17 +112,17 @@ pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut Flow, iterator
} }
pub fn store_overflow(layout_context: &LayoutContext, flow: &mut Flow) { pub fn store_overflow(layout_context: &LayoutContext, flow: &mut Flow) {
if !flow::base(flow).restyle_damage.contains(ServoRestyleDamage::STORE_OVERFLOW) { if !flow.base().restyle_damage.contains(ServoRestyleDamage::STORE_OVERFLOW) {
return; return;
} }
for kid in flow::mut_base(flow).child_iter_mut() { for kid in flow.mut_base().child_iter_mut() {
store_overflow(layout_context, kid); store_overflow(layout_context, kid);
} }
flow.store_overflow(layout_context); flow.store_overflow(layout_context);
flow::mut_base(flow) flow.mut_base()
.restyle_damage .restyle_damage
.remove(ServoRestyleDamage::STORE_OVERFLOW); .remove(ServoRestyleDamage::STORE_OVERFLOW);
} }
@ -131,22 +131,22 @@ pub fn store_overflow(layout_context: &LayoutContext, flow: &mut Flow) {
/// given flow. This is needed to speculatively calculate the inline sizes of block formatting /// given flow. This is needed to speculatively calculate the inline sizes of block formatting
/// contexts. The speculation typically succeeds, but if it doesn't we have to lay it out again. /// contexts. The speculation typically succeeds, but if it doesn't we have to lay it out again.
pub fn guess_float_placement(flow: &mut Flow) { pub fn guess_float_placement(flow: &mut Flow) {
if !flow::base(flow).restyle_damage.intersects(ServoRestyleDamage::REFLOW) { if !flow.base().restyle_damage.intersects(ServoRestyleDamage::REFLOW) {
return; return;
} }
let mut floats_in = SpeculatedFloatPlacement::compute_floats_in_for_first_child(flow); let mut floats_in = SpeculatedFloatPlacement::compute_floats_in_for_first_child(flow);
for kid in flow::mut_base(flow).child_iter_mut() { for kid in flow.mut_base().child_iter_mut() {
if flow::base(kid).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
// Do not propagate floats in or out, but do propogate between kids. // Do not propagate floats in or out, but do propogate between kids.
guess_float_placement(kid); guess_float_placement(kid);
} else { } else {
floats_in.compute_floats_in(kid); floats_in.compute_floats_in(kid);
flow::mut_base(kid).speculated_float_placement_in = floats_in; kid.mut_base().speculated_float_placement_in = floats_in;
guess_float_placement(kid); guess_float_placement(kid);
floats_in = flow::base(kid).speculated_float_placement_out; floats_in = kid.base().speculated_float_placement_out;
} }
} }
floats_in.compute_floats_out(flow); floats_in.compute_floats_out(flow);
flow::mut_base(flow).speculated_float_placement_out = floats_in flow.mut_base().speculated_float_placement_out = floats_in
} }

View file

@ -13,8 +13,7 @@ use context::LayoutContext;
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState}; use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState};
use euclid::Point2D; use euclid::Point2D;
use flow; use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, GetBaseFlow, OpaqueFlow};
use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
use flow_list::MutFlowListIterator; use flow_list::MutFlowListIterator;
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx_traits::print_tree::PrintTree; use gfx_traits::print_tree::PrintTree;
@ -752,12 +751,12 @@ impl TableLikeFlow for BlockFlow {
} }
// At this point, `current_block_offset` is at the border edge of the child. // At this point, `current_block_offset` is at the border edge of the child.
flow::mut_base(kid).position.start.b = current_block_offset; kid.mut_base().position.start.b = current_block_offset;
// Move past the child's border box. Do not use the `translate_including_floats` // Move past the child's border box. Do not use the `translate_including_floats`
// function here because the child has already translated floats past its border // function here because the child has already translated floats past its border
// box. // box.
let kid_base = flow::mut_base(kid); let kid_base = kid.mut_base();
current_block_offset = current_block_offset + kid_base.position.size.block; current_block_offset = current_block_offset + kid_base.position.size.block;
} }
@ -796,7 +795,7 @@ impl TableLikeFlow for BlockFlow {
// Write in the size of the relative containing block for children. (This information // Write in the size of the relative containing block for children. (This information
// is also needed to handle RTL.) // is also needed to handle RTL.)
for kid in self.base.child_iter_mut() { for kid in self.base.child_iter_mut() {
flow::mut_base(kid).early_absolute_position_info = EarlyAbsolutePositionInfo { kid.mut_base().early_absolute_position_info = EarlyAbsolutePositionInfo {
relative_containing_block_size: self.fragment.content_box().size, relative_containing_block_size: self.fragment.content_box().size,
relative_containing_block_mode: self.fragment.style().writing_mode, relative_containing_block_mode: self.fragment.style().writing_mode,
}; };
@ -856,7 +855,7 @@ impl<'a> Iterator for TableRowIterator<'a> {
match self.kids.next() { match self.kids.next() {
Some(kid) => { Some(kid) => {
if kid.is_table_rowgroup() { if kid.is_table_rowgroup() {
self.grandkids = Some(flow::mut_base(kid).child_iter_mut()); self.grandkids = Some(kid.mut_base().child_iter_mut());
self.next() self.next()
} else if kid.is_table_row() { } else if kid.is_table_row() {
Some(kid.as_mut_table_row()) Some(kid.as_mut_table_row())

View file

@ -13,7 +13,7 @@ use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags}; use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags};
use display_list_builder::StackingContextCollectionState; use display_list_builder::StackingContextCollectionState;
use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
use flow::{self, Flow, FlowClass, FlowFlags, OpaqueFlow}; use flow::{Flow, FlowClass, FlowFlags, GetBaseFlow, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx_traits::print_tree::PrintTree; use gfx_traits::print_tree::PrintTree;
use layout_debug; use layout_debug;
@ -101,8 +101,8 @@ impl TableCellFlow {
// Note to the reader: this code has been tested with negative margins. // Note to the reader: this code has been tested with negative margins.
// We end up with a "end" that's before the "start," but the math still works out. // We end up with a "end" that's before the "start," but the math still works out.
let mut extents = None; let mut extents = None;
for kid in flow::base(self).children.iter() { for kid in self.base().children.iter() {
let kid_base = flow::base(kid); let kid_base = kid.base();
if kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
continue continue
} }
@ -128,7 +128,7 @@ impl TableCellFlow {
}; };
let kids_size = last_end - first_start; let kids_size = last_end - first_start;
let self_size = flow::base(self).position.size.block - let self_size = self.base().position.size.block -
self.block_flow.fragment.border_padding.block_start_end(); self.block_flow.fragment.border_padding.block_start_end();
let kids_self_gap = self_size - kids_size; let kids_self_gap = self_size - kids_size;
@ -143,8 +143,8 @@ impl TableCellFlow {
return return
} }
for kid in flow::mut_base(self).children.iter_mut() { for kid in self.mut_base().children.iter_mut() {
let kid_base = flow::mut_base(kid); let kid_base = kid.mut_base();
if !kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { if !kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) {
kid_base.position.start.b += offset kid_base.position.start.b += offset
} }

View file

@ -13,7 +13,7 @@ use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags}; use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags};
use display_list_builder::StackingContextCollectionState; use display_list_builder::StackingContextCollectionState;
use euclid::Point2D; use euclid::Point2D;
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; use flow::{EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, GetBaseFlow, OpaqueFlow};
use flow_list::MutFlowListIterator; use flow_list::MutFlowListIterator;
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx_traits::print_tree::PrintTree; use gfx_traits::print_tree::PrintTree;
@ -126,7 +126,7 @@ impl TableRowFlow {
- self.block_flow.fragment.margin; - self.block_flow.fragment.margin;
for kid in self.block_flow.base.child_iter_mut() { for kid in self.block_flow.base.child_iter_mut() {
kid.place_float_if_applicable(); kid.place_float_if_applicable();
if !flow::base(kid).flags.is_float() { if !kid.base().flags.is_float() {
kid.assign_block_size_for_inorder_child_if_necessary(layout_context, kid.assign_block_size_for_inorder_child_if_necessary(layout_context,
thread_id, thread_id,
content_box); content_box);
@ -143,7 +143,7 @@ impl TableRowFlow {
child_specified_block_size + child_specified_block_size +
child_fragment.border_padding.block_start_end()); child_fragment.border_padding.block_start_end());
} }
let child_node = flow::mut_base(kid); let child_node = kid.mut_base();
child_node.position.start.b = Au(0); child_node.position.start.b = Au(0);
max_block_size = max(max_block_size, child_node.position.size.block); max_block_size = max(max_block_size, child_node.position.size.block);
} }
@ -301,7 +301,7 @@ impl Flow for TableRowFlow {
// Collect minimum and preferred inline-sizes of the cell for automatic table layout // Collect minimum and preferred inline-sizes of the cell for automatic table layout
// calculation. // calculation.
let child_base = flow::mut_base(kid); let child_base = kid.mut_base();
let child_column_inline_size = ColumnIntrinsicInlineSize { let child_column_inline_size = ColumnIntrinsicInlineSize {
minimum_length: match child_specified_inline_size { minimum_length: match child_specified_inline_size {
LengthOrPercentageOrAuto::Auto | LengthOrPercentageOrAuto::Auto |

View file

@ -7,7 +7,7 @@
use construct::FlowConstructor; use construct::FlowConstructor;
use context::LayoutContext; use context::LayoutContext;
use display_list_builder::DisplayListBuildState; use display_list_builder::DisplayListBuildState;
use flow::{self, FlowFlags, Flow, ImmutableFlowUtils}; use flow::{FlowFlags, Flow, GetBaseFlow, ImmutableFlowUtils};
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode}; use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use servo_config::opts; use servo_config::opts;
use style::context::{SharedStyleContext, StyleContext}; use style::context::{SharedStyleContext, StyleContext};
@ -110,7 +110,7 @@ pub trait PreorderFlowTraversal {
if self.should_process(flow) { if self.should_process(flow) {
self.process(flow); self.process(flow);
} }
for kid in flow::child_iter_mut(flow) { for kid in flow.mut_base().child_iter_mut() {
self.traverse(kid); self.traverse(kid);
} }
} }
@ -125,7 +125,7 @@ pub trait PreorderFlowTraversal {
if self.should_process(flow) { if self.should_process(flow) {
self.process(flow); self.process(flow);
} }
for descendant_link in flow::mut_base(flow).abs_descendants.iter() { for descendant_link in flow.mut_base().abs_descendants.iter() {
self.traverse_absolute_flows(descendant_link) self.traverse_absolute_flows(descendant_link)
} }
} }
@ -145,7 +145,7 @@ pub trait PostorderFlowTraversal {
/// Traverses the tree in postorder. /// Traverses the tree in postorder.
fn traverse(&self, flow: &mut Flow) { fn traverse(&self, flow: &mut Flow) {
for kid in flow::child_iter_mut(flow) { for kid in flow.mut_base().child_iter_mut() {
self.traverse(kid); self.traverse(kid);
} }
if self.should_process(flow) { if self.should_process(flow) {
@ -171,7 +171,7 @@ pub trait InorderFlowTraversal {
return; return;
} }
self.process(flow, level); self.process(flow, level);
for kid in flow::child_iter_mut(flow) { for kid in flow.mut_base().child_iter_mut() {
self.traverse(kid, level + 1); self.traverse(kid, level + 1);
} }
} }
@ -226,12 +226,12 @@ impl<'a> PostorderFlowTraversal for BubbleISizes<'a> {
#[inline] #[inline]
fn process(&self, flow: &mut Flow) { fn process(&self, flow: &mut Flow) {
flow.bubble_inline_sizes(); flow.bubble_inline_sizes();
flow::mut_base(flow).restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES); flow.mut_base().restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES);
} }
#[inline] #[inline]
fn should_process(&self, flow: &mut Flow) -> bool { fn should_process(&self, flow: &mut Flow) -> bool {
flow::base(flow).restyle_damage.contains(ServoRestyleDamage::BUBBLE_ISIZES) flow.base().restyle_damage.contains(ServoRestyleDamage::BUBBLE_ISIZES)
} }
} }
@ -249,7 +249,7 @@ impl<'a> PreorderFlowTraversal for AssignISizes<'a> {
#[inline] #[inline]
fn should_process(&self, flow: &mut Flow) -> bool { fn should_process(&self, flow: &mut Flow) -> bool {
flow::base(flow).restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) flow.base().restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW)
} }
} }
@ -278,7 +278,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizes<'a> {
#[inline] #[inline]
fn should_process(&self, flow: &mut Flow) -> bool { fn should_process(&self, flow: &mut Flow) -> bool {
let base = flow::base(flow); let base = flow.base();
base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) && base.restyle_damage.intersects(ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW) &&
// The fragmentation countainer is responsible for calling Flow::fragment recursively // The fragmentation countainer is responsible for calling Flow::fragment recursively
!base.flags.contains(FlowFlags::CAN_BE_FRAGMENTED) !base.flags.contains(FlowFlags::CAN_BE_FRAGMENTED)
@ -292,13 +292,13 @@ pub struct ComputeStackingRelativePositions<'a> {
impl<'a> PreorderFlowTraversal for ComputeStackingRelativePositions<'a> { impl<'a> PreorderFlowTraversal for ComputeStackingRelativePositions<'a> {
#[inline] #[inline]
fn should_process_subtree(&self, flow: &mut Flow) -> bool { fn should_process_subtree(&self, flow: &mut Flow) -> bool {
flow::base(flow).restyle_damage.contains(ServoRestyleDamage::REPOSITION) flow.base().restyle_damage.contains(ServoRestyleDamage::REPOSITION)
} }
#[inline] #[inline]
fn process(&self, flow: &mut Flow) { fn process(&self, flow: &mut Flow) {
flow.compute_stacking_relative_position(self.layout_context); flow.compute_stacking_relative_position(self.layout_context);
flow::mut_base(flow).restyle_damage.remove(ServoRestyleDamage::REPOSITION) flow.mut_base().restyle_damage.remove(ServoRestyleDamage::REPOSITION)
} }
} }
@ -310,15 +310,15 @@ impl<'a> BuildDisplayList<'a> {
#[inline] #[inline]
pub fn traverse(&mut self, flow: &mut Flow) { pub fn traverse(&mut self, flow: &mut Flow) {
let parent_stacking_context_id = self.state.current_stacking_context_id; let parent_stacking_context_id = self.state.current_stacking_context_id;
self.state.current_stacking_context_id = flow::base(flow).stacking_context_id; self.state.current_stacking_context_id = flow.base().stacking_context_id;
let parent_clipping_and_scrolling = self.state.current_clipping_and_scrolling; let parent_clipping_and_scrolling = self.state.current_clipping_and_scrolling;
self.state.current_clipping_and_scrolling = flow.clipping_and_scrolling(); self.state.current_clipping_and_scrolling = flow.clipping_and_scrolling();
flow.build_display_list(&mut self.state); flow.build_display_list(&mut self.state);
flow::mut_base(flow).restyle_damage.remove(ServoRestyleDamage::REPAINT); flow.mut_base().restyle_damage.remove(ServoRestyleDamage::REPAINT);
for kid in flow::child_iter_mut(flow) { for kid in flow.mut_base().child_iter_mut() {
self.traverse(kid); self.traverse(kid);
} }

View file

@ -428,7 +428,6 @@ impl WebRenderDisplayItemConverter for DisplayItem {
builder.push_border(&self.prim_info(), widths, details); builder.push_border(&self.prim_info(), widths, details);
} }
DisplayItem::Gradient(ref item) => { DisplayItem::Gradient(ref item) => {
let rect = item.base.bounds;
let start_point = item.gradient.start_point.to_pointf(); let start_point = item.gradient.start_point.to_pointf();
let end_point = item.gradient.end_point.to_pointf(); let end_point = item.gradient.end_point.to_pointf();
let extend_mode = if item.gradient.repeating { let extend_mode = if item.gradient.repeating {
@ -442,11 +441,10 @@ impl WebRenderDisplayItemConverter for DisplayItem {
extend_mode); extend_mode);
builder.push_gradient(&self.prim_info(), builder.push_gradient(&self.prim_info(),
gradient, gradient,
rect.size.to_sizef(), item.tile.to_sizef(),
webrender_api::LayoutSize::zero()); webrender_api::LayoutSize::zero());
} }
DisplayItem::RadialGradient(ref item) => { DisplayItem::RadialGradient(ref item) => {
let rect = item.base.bounds;
let center = item.gradient.center.to_pointf(); let center = item.gradient.center.to_pointf();
let radius = item.gradient.radius.to_sizef(); let radius = item.gradient.radius.to_sizef();
let extend_mode = if item.gradient.repeating { let extend_mode = if item.gradient.repeating {
@ -460,7 +458,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
extend_mode); extend_mode);
builder.push_radial_gradient(&self.prim_info(), builder.push_radial_gradient(&self.prim_info(),
gradient, gradient,
rect.size.to_sizef(), item.tile.to_sizef(),
webrender_api::LayoutSize::zero()); webrender_api::LayoutSize::zero());
} }
DisplayItem::Line(ref item) => { DisplayItem::Line(ref item) => {

View file

@ -70,7 +70,7 @@ use layout::context::RegisteredPainter;
use layout::context::RegisteredPainters; use layout::context::RegisteredPainters;
use layout::context::malloc_size_of_persistent_local_context; use layout::context::malloc_size_of_persistent_local_context;
use layout::display_list_builder::ToGfxColor; use layout::display_list_builder::ToGfxColor;
use layout::flow::{self, Flow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow::{Flow, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils};
use layout::flow_ref::FlowRef; use layout::flow_ref::FlowRef;
use layout::incremental::{LayoutDamageComputation, RelayoutMode, SpecialRestyleDamage}; use layout::incremental::{LayoutDamageComputation, RelayoutMode, SpecialRestyleDamage};
use layout::layout_debug; use layout::layout_debug;
@ -956,22 +956,22 @@ impl LayoutThread {
layout_root: &mut Flow, layout_root: &mut Flow,
layout_context: &mut LayoutContext, layout_context: &mut LayoutContext,
rw_data: &mut LayoutThreadData) { rw_data: &mut LayoutThreadData) {
let writing_mode = flow::base(layout_root).writing_mode; let writing_mode = layout_root.base().writing_mode;
let (metadata, sender) = (self.profiler_metadata(), self.time_profiler_chan.clone()); let (metadata, sender) = (self.profiler_metadata(), self.time_profiler_chan.clone());
profile(time::ProfilerCategory::LayoutDispListBuild, profile(time::ProfilerCategory::LayoutDispListBuild,
metadata.clone(), metadata.clone(),
sender.clone(), sender.clone(),
|| { || {
flow::mut_base(layout_root).stacking_relative_position = layout_root.mut_base().stacking_relative_position =
LogicalPoint::zero(writing_mode).to_physical(writing_mode, LogicalPoint::zero(writing_mode).to_physical(writing_mode,
self.viewport_size).to_vector(); self.viewport_size).to_vector();
flow::mut_base(layout_root).clip = data.page_clip_rect; layout_root.mut_base().clip = data.page_clip_rect;
let traversal = ComputeStackingRelativePositions { layout_context: layout_context }; let traversal = ComputeStackingRelativePositions { layout_context: layout_context };
traversal.traverse(layout_root); traversal.traverse(layout_root);
if flow::base(layout_root).restyle_damage.contains(ServoRestyleDamage::REPAINT) || if layout_root.base().restyle_damage.contains(ServoRestyleDamage::REPAINT) ||
rw_data.display_list.is_none() { rw_data.display_list.is_none() {
if reflow_goal.needs_display_list() { if reflow_goal.needs_display_list() {
let mut build_state = let mut build_state =
@ -980,7 +980,7 @@ impl LayoutThread {
debug!("Done building display list."); debug!("Done building display list.");
let root_size = { let root_size = {
let root_flow = flow::base(layout_root); let root_flow = layout_root.base();
if self.stylist.viewport_constraints().is_some() { if self.stylist.viewport_constraints().is_some() {
root_flow.position.size.to_physical(root_flow.writing_mode) root_flow.position.size.to_physical(root_flow.writing_mode)
} else { } else {
@ -1564,7 +1564,7 @@ impl LayoutThread {
// Perform the primary layout passes over the flow tree to compute the locations of all // Perform the primary layout passes over the flow tree to compute the locations of all
// the boxes. // the boxes.
if flow::base(&**root_flow).restyle_damage.intersects(ServoRestyleDamage::REFLOW | if root_flow.base().restyle_damage.intersects(ServoRestyleDamage::REFLOW |
ServoRestyleDamage::REFLOW_OUT_OF_FLOW) { ServoRestyleDamage::REFLOW_OUT_OF_FLOW) {
profile(time::ProfilerCategory::LayoutMain, profile(time::ProfilerCategory::LayoutMain,
self.profiler_metadata(), self.profiler_metadata(),
@ -1630,12 +1630,12 @@ impl LayoutThread {
fn reflow_all_nodes(flow: &mut Flow) { fn reflow_all_nodes(flow: &mut Flow) {
debug!("reflowing all nodes!"); debug!("reflowing all nodes!");
flow::mut_base(flow) flow.mut_base()
.restyle_damage .restyle_damage
.insert(ServoRestyleDamage::REPAINT | ServoRestyleDamage::STORE_OVERFLOW | .insert(ServoRestyleDamage::REPAINT | ServoRestyleDamage::STORE_OVERFLOW |
ServoRestyleDamage::REFLOW | ServoRestyleDamage::REPOSITION); ServoRestyleDamage::REFLOW | ServoRestyleDamage::REPOSITION);
for child in flow::child_iter_mut(flow) { for child in flow.mut_base().child_iter_mut() {
LayoutThread::reflow_all_nodes(child); LayoutThread::reflow_all_nodes(child);
} }
} }

View file

@ -479,10 +479,7 @@ impl HttpCache {
return None; return None;
} }
let entry_key = CacheKey::new(request.clone()); let entry_key = CacheKey::new(request.clone());
let resources = match self.entries.get(&entry_key) { let resources = self.entries.get(&entry_key)?.clone();
Some(ref resources) => resources.clone(),
None => return None,
};
let mut candidates = vec![]; let mut candidates = vec![];
for cached_resource in resources.iter() { for cached_resource in resources.iter() {
let mut can_be_constructed = true; let mut can_be_constructed = true;

View file

@ -39,6 +39,7 @@ byteorder = "1.0"
canvas_traits = {path = "../canvas_traits"} canvas_traits = {path = "../canvas_traits"}
caseless = "0.1.0" caseless = "0.1.0"
cookie = "0.10" cookie = "0.10"
chrono = "0.4"
cssparser = "0.23.0" cssparser = "0.23.0"
deny_public_fields = {path = "../deny_public_fields"} deny_public_fields = {path = "../deny_public_fields"}
devtools_traits = {path = "../devtools_traits"} devtools_traits = {path = "../devtools_traits"}

View file

@ -141,6 +141,13 @@ impl DocumentLoader {
!self.blocking_loads.is_empty() !self.blocking_loads.is_empty()
} }
pub fn is_only_blocked_by_iframes(&self) -> bool {
self.blocking_loads.iter().all(|load| match *load {
LoadType::Subframe(_) => true,
_ => false
})
}
pub fn inhibit_events(&mut self) { pub fn inhibit_events(&mut self) {
self.events_inhibited = true; self.events_inhibited = true;
} }

View file

@ -4,6 +4,8 @@
//! The `ByteString` struct. //! The `ByteString` struct.
use chrono::{Datelike, TimeZone};
use chrono::prelude::{Weekday, Utc};
use cssparser::CowRcStr; use cssparser::CowRcStr;
use html5ever::{LocalName, Namespace}; use html5ever::{LocalName, Namespace};
use servo_atoms::Atom; use servo_atoms::Atom;
@ -293,6 +295,13 @@ impl DOMString {
pub fn is_valid_month_string(&self) -> bool { pub fn is_valid_month_string(&self) -> bool {
parse_month_string(&*self.0).is_ok() parse_month_string(&*self.0).is_ok()
} }
/// A valid week string should be like {YYYY}-W{WW}, such as "2017-W52"
/// YYYY must be four or more digits, WW both must be two digits
/// https://html.spec.whatwg.org/multipage/#valid-week-string
pub fn is_valid_week_string(&self) -> bool {
parse_week_string(&*self.0).is_ok()
}
} }
impl Borrow<str> for DOMString { impl Borrow<str> for DOMString {
@ -445,6 +454,48 @@ fn parse_date_string(value: &str) -> Result<(u32, u32, u32), ()> {
Ok((year_int, month_int, day_int)) Ok((year_int, month_int, day_int))
} }
/// https://html.spec.whatwg.org/multipage/#parse-a-week-string
fn parse_week_string(value: &str) -> Result<(u32, u32), ()> {
// Step 1, 2, 3
let mut iterator = value.split('-');
let year = iterator.next().ok_or(())?;
// Step 4
let year_int = year.parse::<u32>().map_err(|_| ())?;
if year.len() < 4 || year_int == 0 {
return Err(());
}
// Step 5, 6
let week = iterator.next().ok_or(())?;
let (week_first, week_last) = week.split_at(1);
if week_first != "W" {
return Err(());
}
// Step 7
let week_int = week_last.parse::<u32>().map_err(|_| ())?;
if week_last.len() != 2 {
return Err(());
}
// Step 8
let max_week = max_week_in_year(year_int);
// Step 9
if week_int < 1 || week_int > max_week {
return Err(());
}
// Step 10
if iterator.next().is_some() {
return Err(());
}
// Step 11
Ok((year_int, week_int))
}
/// https://html.spec.whatwg.org/multipage/#parse-a-month-component /// https://html.spec.whatwg.org/multipage/#parse-a-month-component
fn parse_month_component(value: &str) -> Result<(u32, u32), ()> { fn parse_month_component(value: &str) -> Result<(u32, u32), ()> {
// Step 3 // Step 3
@ -495,7 +546,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
1|3|5|7|8|10|12 => Ok(31), 1|3|5|7|8|10|12 => Ok(31),
4|6|9|11 => Ok(30), 4|6|9|11 => Ok(30),
2 => { 2 => {
if year_num % 400 == 0 || (year_num % 4 == 0 && year_num % 100 != 0) { if is_leap_year(year_num) {
Ok(29) Ok(29)
} else { } else {
Ok(28) Ok(28)
@ -504,3 +555,17 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result<u32, ()> {
_ => Err(()) _ => Err(())
} }
} }
// https://html.spec.whatwg.org/multipage/#week-number-of-the-last-day
fn max_week_in_year(year: u32) -> u32 {
match Utc.ymd(year as i32, 1, 1).weekday() {
Weekday::Thu => 53,
Weekday::Wed if is_leap_year(year) => 53,
_ => 52
}
}
#[inline]
fn is_leap_year(year: u32) -> bool {
year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)
}

View file

@ -129,11 +129,10 @@ impl CanvasRenderingContext2D {
size: Size2D<i32>) size: Size2D<i32>)
-> CanvasRenderingContext2D { -> CanvasRenderingContext2D {
debug!("Creating new canvas rendering context."); debug!("Creating new canvas rendering context.");
let (sender, receiver) = ipc::channel().unwrap(); let (ipc_renderer, receiver) = ipc::channel::<CanvasMsg>().unwrap();
let script_to_constellation_chan = global.script_to_constellation_chan(); let script_to_constellation_chan = global.script_to_constellation_chan();
debug!("Asking constellation to create new canvas thread."); debug!("Asking constellation to create new canvas thread.");
script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, receiver)).unwrap();
let ipc_renderer = receiver.recv().unwrap();
debug!("Done."); debug!("Done.");
CanvasRenderingContext2D { CanvasRenderingContext2D {
reflector_: Reflector::new(), reflector_: Reflector::new(),

View file

@ -322,6 +322,7 @@ pub struct Document {
dom_content_loaded_event_start: Cell<u64>, dom_content_loaded_event_start: Cell<u64>,
dom_content_loaded_event_end: Cell<u64>, dom_content_loaded_event_end: Cell<u64>,
dom_complete: Cell<u64>, dom_complete: Cell<u64>,
top_level_dom_complete: Cell<u64>,
load_event_start: Cell<u64>, load_event_start: Cell<u64>,
load_event_end: Cell<u64>, load_event_end: Cell<u64>,
/// <https://html.spec.whatwg.org/multipage/#concept-document-https-state> /// <https://html.spec.whatwg.org/multipage/#concept-document-https-state>
@ -1627,6 +1628,12 @@ impl Document {
// asap_in_order_script_loaded. // asap_in_order_script_loaded.
let loader = self.loader.borrow(); let loader = self.loader.borrow();
// Servo measures when the top-level content (not iframes) is loaded.
if (self.top_level_dom_complete.get() == 0) && loader.is_only_blocked_by_iframes() {
update_with_current_time_ms(&self.top_level_dom_complete);
}
if loader.is_blocked() || loader.events_inhibited() { if loader.is_blocked() || loader.events_inhibited() {
// Step 6. // Step 6.
return; return;
@ -1951,6 +1958,10 @@ impl Document {
self.dom_complete.get() self.dom_complete.get()
} }
pub fn get_top_level_dom_complete(&self) -> u64 {
self.top_level_dom_complete.get()
}
pub fn get_load_event_start(&self) -> u64 { pub fn get_load_event_start(&self) -> u64 {
self.load_event_start.get() self.load_event_start.get()
} }
@ -2265,6 +2276,7 @@ impl Document {
dom_content_loaded_event_start: Cell::new(Default::default()), dom_content_loaded_event_start: Cell::new(Default::default()),
dom_content_loaded_event_end: Cell::new(Default::default()), dom_content_loaded_event_end: Cell::new(Default::default()),
dom_complete: Cell::new(Default::default()), dom_complete: Cell::new(Default::default()),
top_level_dom_complete: Cell::new(Default::default()),
load_event_start: Cell::new(Default::default()), load_event_start: Cell::new(Default::default()),
load_event_end: Cell::new(Default::default()), load_event_end: Cell::new(Default::default()),
https_state: Cell::new(HttpsState::None), https_state: Cell::new(HttpsState::None),

View file

@ -405,6 +405,18 @@ impl TextControl for HTMLInputElement {
fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>> { fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>> {
&self.textinput &self.textinput
} }
// https://html.spec.whatwg.org/multipage/#concept-input-apply
fn selection_api_applies(&self) -> bool {
match self.input_type() {
InputType::Text | InputType::Search | InputType::Url
| InputType::Tel | InputType::Password => {
true
},
_ => false
}
}
} }
impl HTMLInputElementMethods for HTMLInputElement { impl HTMLInputElementMethods for HTMLInputElement {
@ -676,38 +688,38 @@ impl HTMLInputElementMethods for HTMLInputElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn SelectionStart(&self) -> u32 { fn GetSelectionStart(&self) -> Option<u32> {
self.dom_selection_start() self.get_dom_selection_start()
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn SetSelectionStart(&self, start: u32) { fn SetSelectionStart(&self, start: Option<u32>) -> ErrorResult {
self.set_dom_selection_start(start); self.set_dom_selection_start(start)
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn SelectionEnd(&self) -> u32 { fn GetSelectionEnd(&self) -> Option<u32> {
self.dom_selection_end() self.get_dom_selection_end()
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn SetSelectionEnd(&self, end: u32) { fn SetSelectionEnd(&self, end: Option<u32>) -> ErrorResult {
self.set_dom_selection_end(end) self.set_dom_selection_end(end)
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn SelectionDirection(&self) -> DOMString { fn GetSelectionDirection(&self) -> Option<DOMString> {
self.dom_selection_direction() self.get_dom_selection_direction()
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn SetSelectionDirection(&self, direction: DOMString) { fn SetSelectionDirection(&self, direction: Option<DOMString>) -> ErrorResult {
self.set_dom_selection_direction(direction); self.set_dom_selection_direction(direction)
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange
fn SetSelectionRange(&self, start: u32, end: u32, direction: Option<DOMString>) { fn SetSelectionRange(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
self.set_dom_selection_range(start, end, direction); self.set_dom_selection_range(start, end, direction)
} }
// Select the files based on filepaths passed in, // Select the files based on filepaths passed in,
@ -993,6 +1005,12 @@ impl HTMLInputElement {
*textinput.single_line_content_mut() = "".into(); *textinput.single_line_content_mut() = "".into();
} }
} }
InputType::Week => {
let mut textinput = self.textinput.borrow_mut();
if !textinput.single_line_content().is_valid_week_string() {
*textinput.single_line_content_mut() = "".into();
}
}
InputType::Color => { InputType::Color => {
let mut textinput = self.textinput.borrow_mut(); let mut textinput = self.textinput.borrow_mut();

View file

@ -75,10 +75,7 @@ impl VirtualMethods for HTMLLegendElement {
impl HTMLLegendElementMethods for HTMLLegendElement { impl HTMLLegendElementMethods for HTMLLegendElement {
// https://html.spec.whatwg.org/multipage/#dom-legend-form // https://html.spec.whatwg.org/multipage/#dom-legend-form
fn GetForm(&self) -> Option<DomRoot<HTMLFormElement>> { fn GetForm(&self) -> Option<DomRoot<HTMLFormElement>> {
let parent = match self.upcast::<Node>().GetParentElement() { let parent = self.upcast::<Node>().GetParentElement()?;
Some(parent) => parent,
None => return None,
};
if parent.is::<HTMLFieldSetElement>() { if parent.is::<HTMLFieldSetElement>() {
return self.form_owner(); return self.form_owner();
} }

View file

@ -8,6 +8,7 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding; use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods; use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::error::ErrorResult;
use dom::bindings::inheritance::Castable; use dom::bindings::inheritance::Castable;
use dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom}; use dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
use dom::bindings::str::DOMString; use dom::bindings::str::DOMString;
@ -145,6 +146,10 @@ impl TextControl for HTMLTextAreaElement {
fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>> { fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>> {
&self.textinput &self.textinput
} }
fn selection_api_applies(&self) -> bool {
true
}
} }
impl HTMLTextAreaElementMethods for HTMLTextAreaElement { impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
@ -260,38 +265,38 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn SelectionStart(&self) -> u32 { fn GetSelectionStart(&self) -> Option<u32> {
self.dom_selection_start() self.get_dom_selection_start()
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn SetSelectionStart(&self, start: u32) { fn SetSelectionStart(&self, start: Option<u32>) -> ErrorResult {
self.set_dom_selection_start(start); self.set_dom_selection_start(start)
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn SelectionEnd(&self) -> u32 { fn GetSelectionEnd(&self) -> Option<u32> {
self.dom_selection_end() self.get_dom_selection_end()
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn SetSelectionEnd(&self, end: u32) { fn SetSelectionEnd(&self, end: Option<u32>) -> ErrorResult {
self.set_dom_selection_end(end); self.set_dom_selection_end(end)
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn SelectionDirection(&self) -> DOMString { fn GetSelectionDirection(&self) -> Option<DOMString> {
self.dom_selection_direction() self.get_dom_selection_direction()
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn SetSelectionDirection(&self, direction: DOMString) { fn SetSelectionDirection(&self, direction: Option<DOMString>) -> ErrorResult {
self.set_dom_selection_direction(direction); self.set_dom_selection_direction(direction)
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange
fn SetSelectionRange(&self, start: u32, end: u32, direction: Option<DOMString>) { fn SetSelectionRange(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
self.set_dom_selection_range(start, end, direction); self.set_dom_selection_range(start, end, direction)
} }
} }

View file

@ -86,6 +86,12 @@ impl PerformanceTimingMethods for PerformanceTiming {
fn LoadEventEnd(&self) -> u64 { fn LoadEventEnd(&self) -> u64 {
self.document.get_load_event_end() self.document.get_load_event_end()
} }
// check-tidy: no specs after this line
// Servo-only timing for when top-level content (not iframes) is complete
fn TopLevelDomComplete(&self) -> u64 {
self.document.get_top_level_dom_complete()
}
} }

View file

@ -4,6 +4,7 @@
use dom::bindings::cell::DomRefCell; use dom::bindings::cell::DomRefCell;
use dom::bindings::conversions::DerivedFrom; use dom::bindings::conversions::DerivedFrom;
use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::str::DOMString; use dom::bindings::str::DOMString;
use dom::event::{EventBubbles, EventCancelable}; use dom::event::{EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
@ -13,52 +14,108 @@ use textinput::{SelectionDirection, TextInput};
pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> { pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>>; fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>>;
fn selection_api_applies(&self) -> bool;
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn dom_selection_start(&self) -> u32 { fn get_dom_selection_start(&self) -> Option<u32> {
self.textinput().borrow().get_selection_start() // Step 1
if !self.selection_api_applies() {
return None;
}
// Steps 2-3
Some(self.selection_start())
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn set_dom_selection_start(&self, start: u32) { fn set_dom_selection_start(&self, start: Option<u32>) -> ErrorResult {
// Step 1
if !self.selection_api_applies() {
return Err(Error::InvalidState);
}
// Step 2 // Step 2
let mut end = self.dom_selection_end(); let mut end = self.selection_end();
// Step 3 // Step 3
if end < start { if let Some(s) = start {
end = start; if end < s {
end = s;
}
} }
// Step 4 // Step 4
self.set_selection_range(start, end, self.selection_direction()); self.set_selection_range(start, Some(end), Some(self.selection_direction()));
Ok(())
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn dom_selection_end(&self) -> u32 { fn get_dom_selection_end(&self) -> Option<u32> {
self.textinput().borrow().get_absolute_insertion_point() as u32 // Step 1
if !self.selection_api_applies() {
return None;
}
// Steps 2-3
Some(self.selection_end())
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn set_dom_selection_end(&self, end: u32) { fn set_dom_selection_end(&self, end: Option<u32>) -> ErrorResult {
self.set_selection_range(self.dom_selection_start(), end, self.selection_direction()); // Step 1
if !self.selection_api_applies() {
return Err(Error::InvalidState);
}
// Step 2
self.set_selection_range(Some(self.selection_start()), end, Some(self.selection_direction()));
Ok(())
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn dom_selection_direction(&self) -> DOMString { fn get_dom_selection_direction(&self) -> Option<DOMString> {
DOMString::from(self.selection_direction()) // Step 1
if !self.selection_api_applies() {
return None;
}
Some(DOMString::from(self.selection_direction()))
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn set_dom_selection_direction(&self, direction: DOMString) { fn set_dom_selection_direction(&self, direction: Option<DOMString>) -> ErrorResult {
self.textinput().borrow_mut().selection_direction = SelectionDirection::from(direction); // Step 1
if !self.selection_api_applies() {
return Err(Error::InvalidState);
}
// Step 2
self.set_selection_range(
Some(self.selection_start()),
Some(self.selection_end()),
direction.map(|d| SelectionDirection::from(d))
);
Ok(())
} }
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange
fn set_dom_selection_range(&self, start: u32, end: u32, direction: Option<DOMString>) { fn set_dom_selection_range(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
// Step 4 // Step 1
let direction = direction.map_or(SelectionDirection::None, |d| SelectionDirection::from(d)); if !self.selection_api_applies() {
return Err(Error::InvalidState);
}
self.set_selection_range(start, end, direction); // Step 2
self.set_selection_range(Some(start), Some(end), direction.map(|d| SelectionDirection::from(d)));
Ok(())
}
fn selection_start(&self) -> u32 {
self.textinput().borrow().get_selection_start()
}
fn selection_end(&self) -> u32 {
self.textinput().borrow().get_absolute_insertion_point() as u32
} }
fn selection_direction(&self) -> SelectionDirection { fn selection_direction(&self) -> SelectionDirection {
@ -66,12 +123,15 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
} }
// https://html.spec.whatwg.org/multipage/#set-the-selection-range // https://html.spec.whatwg.org/multipage/#set-the-selection-range
fn set_selection_range(&self, start: u32, end: u32, direction: SelectionDirection) { fn set_selection_range(&self, start: Option<u32>, end: Option<u32>, direction: Option<SelectionDirection>) {
// Step 5 // Step 1
self.textinput().borrow_mut().selection_direction = direction; let start = start.unwrap_or(0);
// Step 3 // Step 2
self.textinput().borrow_mut().set_selection_range(start, end); let end = end.unwrap_or(0);
// Steps 3-5
self.textinput().borrow_mut().set_selection_range(start, end, direction.unwrap_or(SelectionDirection::None));
// Step 6 // Step 6
let window = window_from_node(self); let window = window_from_node(self);

View file

@ -90,13 +90,17 @@ interface HTMLInputElement : HTMLElement {
readonly attribute NodeList labels; readonly attribute NodeList labels;
//void select(); //void select();
attribute unsigned long selectionStart; [SetterThrows]
attribute unsigned long selectionEnd; attribute unsigned long? selectionStart;
attribute DOMString selectionDirection; [SetterThrows]
attribute unsigned long? selectionEnd;
[SetterThrows]
attribute DOMString? selectionDirection;
//void setRangeText(DOMString replacement); //void setRangeText(DOMString replacement);
//void setRangeText(DOMString replacement, unsigned long start, unsigned long end, //void setRangeText(DOMString replacement, unsigned long start, unsigned long end,
// optional SelectionMode selectionMode = "preserve"); // optional SelectionMode selectionMode = "preserve");
void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction); [Throws]
void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction);
// also has obsolete members // also has obsolete members

View file

@ -51,11 +51,15 @@ interface HTMLTextAreaElement : HTMLElement {
readonly attribute NodeList labels; readonly attribute NodeList labels;
// void select(); // void select();
attribute unsigned long selectionStart; [SetterThrows]
attribute unsigned long selectionEnd; attribute unsigned long? selectionStart;
attribute DOMString selectionDirection; [SetterThrows]
attribute unsigned long? selectionEnd;
[SetterThrows]
attribute DOMString? selectionDirection;
// void setRangeText(DOMString replacement); // void setRangeText(DOMString replacement);
// void setRangeText(DOMString replacement, unsigned long start, unsigned long end, // void setRangeText(DOMString replacement, unsigned long start, unsigned long end,
// optional SelectionMode selectionMode = "preserve"); // optional SelectionMode selectionMode = "preserve");
void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction); [Throws]
void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction);
}; };

View file

@ -29,4 +29,7 @@ interface PerformanceTiming {
readonly attribute unsigned long long domComplete; readonly attribute unsigned long long domComplete;
readonly attribute unsigned long long loadEventStart; readonly attribute unsigned long long loadEventStart;
readonly attribute unsigned long long loadEventEnd; readonly attribute unsigned long long loadEventEnd;
/* Servo-onnly attribute for measuring when the top-level document (not iframes) is complete. */
[Pref="dom.testperf.enabled"]
readonly attribute unsigned long long topLevelDomComplete;
}; };

View file

@ -31,6 +31,7 @@ extern crate bluetooth_traits;
extern crate byteorder; extern crate byteorder;
extern crate canvas_traits; extern crate canvas_traits;
extern crate caseless; extern crate caseless;
extern crate chrono;
extern crate cookie as cookie_rs; extern crate cookie as cookie_rs;
#[macro_use] extern crate cssparser; #[macro_use] extern crate cssparser;
#[macro_use] extern crate deny_public_fields; #[macro_use] extern crate deny_public_fields;

View file

@ -21,7 +21,7 @@ pub enum Selection {
NotSelected NotSelected
} }
#[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq)]
pub enum SelectionDirection { pub enum SelectionDirection {
Forward, Forward,
Backward, Backward,
@ -825,7 +825,7 @@ impl<T: ClipboardProvider> TextInput<T> {
} }
} }
pub fn set_selection_range(&mut self, start: u32, end: u32) { pub fn set_selection_range(&mut self, start: u32, end: u32, direction: SelectionDirection) {
let mut start = start as usize; let mut start = start as usize;
let mut end = end as usize; let mut end = end as usize;
let text_end = self.get_content().len(); let text_end = self.get_content().len();
@ -837,7 +837,9 @@ impl<T: ClipboardProvider> TextInput<T> {
start = end; start = end;
} }
match self.selection_direction { self.selection_direction = direction;
match direction {
SelectionDirection::None | SelectionDirection::None |
SelectionDirection::Forward => { SelectionDirection::Forward => {
self.selection_begin = Some(self.get_text_point_for_absolute_point(start)); self.selection_begin = Some(self.get_text_point_for_absolute_point(start));

View file

@ -79,7 +79,7 @@ pub enum ScriptMsg {
ChangeRunningAnimationsState(AnimationState), ChangeRunningAnimationsState(AnimationState),
/// Requests that a new 2D canvas thread be created. (This is done in the constellation because /// Requests that a new 2D canvas thread be created. (This is done in the constellation because
/// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.) /// 2D canvases may use the GPU and we don't want to give untrusted content access to the GPU.)
CreateCanvasPaintThread(Size2D<i32>, IpcSender<IpcSender<CanvasMsg>>), CreateCanvasPaintThread(Size2D<i32>, IpcReceiver<CanvasMsg>),
/// Notifies the constellation that this frame has received focus. /// Notifies the constellation that this frame has received focus.
Focus, Focus,
/// Forward an event that was sent to the parent window. /// Forward an event that was sent to the parent window.

View file

@ -264,12 +264,23 @@ fn complex_selector_specificity<Impl>(mut iter: slice::Iter<Component<Impl>>)
-> Specificity -> Specificity
where Impl: SelectorImpl where Impl: SelectorImpl
{ {
fn simple_selector_specificity<Impl>(simple_selector: &Component<Impl>, fn simple_selector_specificity<Impl>(
specificity: &mut Specificity) simple_selector: &Component<Impl>,
where Impl: SelectorImpl specificity: &mut Specificity,
)
where
Impl: SelectorImpl
{ {
match *simple_selector { match *simple_selector {
Component::Combinator(..) => unreachable!(), Component::Combinator(..) => unreachable!(),
// FIXME(emilio): Spec doesn't define any particular specificity for
// ::slotted(), so apply the general rule for pseudos per:
//
// https://github.com/w3c/csswg-drafts/issues/1915
//
// Though other engines compute it dynamically, so maybe we should
// do that instead, eventually.
Component::Slotted(..) |
Component::PseudoElement(..) | Component::PseudoElement(..) |
Component::LocalName(..) => { Component::LocalName(..) => {
specificity.element_selectors += 1 specificity.element_selectors += 1

View file

@ -72,14 +72,24 @@ pub fn matches_selector_list<E>(
where where
E: Element E: Element
{ {
selector_list.0.iter().any(|selector| { // This is pretty much any(..) but manually inlined because the compiler
matches_selector(selector, // refuses to do so from querySelector / querySelectorAll.
0, for selector in &selector_list.0 {
None, let matches = matches_selector(
element, selector,
context, 0,
&mut |_, _| {}) None,
}) element,
context,
&mut |_, _| {},
);
if matches {
return true;
}
}
false
} }
#[inline(always)] #[inline(always)]
@ -393,6 +403,9 @@ where
element.parent_element() element.parent_element()
} }
Combinator::SlotAssignment => {
element.assigned_slot()
}
Combinator::PseudoElement => { Combinator::PseudoElement => {
element.pseudo_element_originating_element() element.pseudo_element_originating_element()
} }
@ -453,6 +466,7 @@ where
} }
Combinator::Child | Combinator::Child |
Combinator::Descendant | Combinator::Descendant |
Combinator::SlotAssignment |
Combinator::PseudoElement => { Combinator::PseudoElement => {
SelectorMatchingResult::NotMatchedGlobally SelectorMatchingResult::NotMatchedGlobally
} }
@ -541,6 +555,21 @@ where
{ {
match *selector { match *selector {
Component::Combinator(_) => unreachable!(), Component::Combinator(_) => unreachable!(),
Component::Slotted(ref selectors) => {
context.shared.nesting_level += 1;
let result =
element.assigned_slot().is_some() &&
selectors.iter().any(|s| {
matches_complex_selector(
s.iter(),
element,
context.shared,
flags_setter,
)
});
context.shared.nesting_level -= 1;
result
}
Component::PseudoElement(ref pseudo) => { Component::PseudoElement(ref pseudo) => {
element.match_pseudo_element(pseudo, context.shared) element.match_pseudo_element(pseudo, context.shared)
} }

View file

@ -55,6 +55,7 @@ pub enum SelectorParseErrorKind<'i> {
EmptySelector, EmptySelector,
DanglingCombinator, DanglingCombinator,
NonSimpleSelectorInNegation, NonSimpleSelectorInNegation,
NonCompoundSelector,
UnexpectedTokenInAttributeSelector(Token<'i>), UnexpectedTokenInAttributeSelector(Token<'i>),
PseudoElementExpectedColon(Token<'i>), PseudoElementExpectedColon(Token<'i>),
PseudoElementExpectedIdent(Token<'i>), PseudoElementExpectedIdent(Token<'i>),
@ -127,10 +128,15 @@ pub trait Parser<'i> {
/// Whether the name is a pseudo-element that can be specified with /// Whether the name is a pseudo-element that can be specified with
/// the single colon syntax in addition to the double-colon syntax. /// the single colon syntax in addition to the double-colon syntax.
fn is_pseudo_element_allows_single_colon(name: &CowRcStr<'i>) -> bool { fn pseudo_element_allows_single_colon(name: &str) -> bool {
is_css2_pseudo_element(name) is_css2_pseudo_element(name)
} }
/// Whether to parse the `::slotted()` pseudo-element.
fn parse_slotted(&self) -> bool {
false
}
/// This function can return an "Err" pseudo-element in order to support CSS2.1 /// This function can return an "Err" pseudo-element in order to support CSS2.1
/// pseudo-elements. /// pseudo-elements.
fn parse_non_ts_pseudo_class( fn parse_non_ts_pseudo_class(
@ -209,6 +215,33 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
} }
} }
/// Parse a comma separated list of compound selectors.
pub fn parse_compound_selector_list<'i, 't, P, Impl>(
parser: &P,
input: &mut CssParser<'i, 't>,
) -> Result<Box<[Selector<Impl>]>, ParseError<'i, P::Error>>
where
P: Parser<'i, Impl=Impl>,
Impl: SelectorImpl,
{
let location = input.current_source_location();
let selectors = input.parse_comma_separated(|input| {
Selector::parse(parser, input)
})?;
// Ensure they're actually all compound selectors.
if selectors
.iter()
.flat_map(|x| x.iter_raw_match_order())
.any(|s| s.is_combinator()) {
return Err(location.new_custom_error(
SelectorParseErrorKind::NonCompoundSelector
))
}
Ok(selectors.into_boxed_slice())
}
/// Ancestor hashes for the bloom filter. We precompute these and store them /// Ancestor hashes for the bloom filter. We precompute these and store them
/// inline with selectors to optimize cache performance during matching. /// inline with selectors to optimize cache performance during matching.
/// This matters a lot. /// This matters a lot.
@ -325,6 +358,13 @@ impl<Impl: SelectorImpl> SelectorMethods for Component<Impl> {
} }
match *self { match *self {
Slotted(ref selectors) => {
for selector in selectors.iter() {
if !selector.visit(visitor) {
return false;
}
}
}
Negation(ref negated) => { Negation(ref negated) => {
for component in negated.iter() { for component in negated.iter() {
if !component.visit(visitor) { if !component.visit(visitor) {
@ -630,15 +670,20 @@ pub enum Combinator {
/// combinator for this, we will need to fix up the way hashes are computed /// combinator for this, we will need to fix up the way hashes are computed
/// for revalidation selectors. /// for revalidation selectors.
PseudoElement, PseudoElement,
/// Another combinator used for ::slotted(), which represent the jump from
/// a node to its assigned slot.
SlotAssignment,
} }
impl Combinator { impl Combinator {
/// Returns true if this combinator is a child or descendant combinator. /// Returns true if this combinator is a child or descendant combinator.
#[inline] #[inline]
pub fn is_ancestor(&self) -> bool { pub fn is_ancestor(&self) -> bool {
matches!(*self, Combinator::Child | matches!(*self,
Combinator::Descendant | Combinator::Child |
Combinator::PseudoElement) Combinator::Descendant |
Combinator::PseudoElement |
Combinator::SlotAssignment)
} }
/// Returns true if this combinator is a pseudo-element combinator. /// Returns true if this combinator is a pseudo-element combinator.
@ -688,16 +733,16 @@ pub enum Component<Impl: SelectorImpl> {
// Use a Box in the less common cases with more data to keep size_of::<Component>() small. // Use a Box in the less common cases with more data to keep size_of::<Component>() small.
AttributeOther(Box<AttrSelectorWithNamespace<Impl>>), AttributeOther(Box<AttrSelectorWithNamespace<Impl>>),
// Pseudo-classes /// Pseudo-classes
// ///
// CSS3 Negation only takes a simple simple selector, but we still need to /// CSS3 Negation only takes a simple simple selector, but we still need to
// treat it as a compound selector because it might be a type selector which /// treat it as a compound selector because it might be a type selector
// we represent as a namespace and a localname. /// which we represent as a namespace and a localname.
// ///
// Note: if/when we upgrade this to CSS4, which supports combinators, we /// Note: if/when we upgrade this to CSS4, which supports combinators, we
// need to think about how this should interact with visit_complex_selector, /// need to think about how this should interact with
// and what the consumers of those APIs should do about the presence of /// visit_complex_selector, and what the consumers of those APIs should do
// combinators in negation. /// about the presence of combinators in negation.
Negation(Box<[Component<Impl>]>), Negation(Box<[Component<Impl>]>),
FirstChild, LastChild, OnlyChild, FirstChild, LastChild, OnlyChild,
Root, Root,
@ -711,6 +756,13 @@ pub enum Component<Impl: SelectorImpl> {
LastOfType, LastOfType,
OnlyOfType, OnlyOfType,
NonTSPseudoClass(Impl::NonTSPseudoClass), NonTSPseudoClass(Impl::NonTSPseudoClass),
/// The ::slotted() pseudo-element (which isn't actually a pseudo-element,
/// and probably should be a pseudo-class):
///
/// https://drafts.csswg.org/css-scoping/#slotted-pseudo
///
/// The selectors here are compound selectors, that is, no combinators.
Slotted(Box<[Selector<Impl>]>),
PseudoElement(Impl::PseudoElement), PseudoElement(Impl::PseudoElement),
} }
@ -840,13 +892,15 @@ impl<Impl: SelectorImpl> ToCss for Selector<Impl> {
let mut perform_step_2 = true; let mut perform_step_2 = true;
if first_non_namespace == compound.len() - 1 { if first_non_namespace == compound.len() - 1 {
match (combinators.peek(), &compound[first_non_namespace]) { match (combinators.peek(), &compound[first_non_namespace]) {
// We have to be careful here, because if there is a pseudo // We have to be careful here, because if there is a
// element "combinator" there isn't really just the one // pseudo element "combinator" there isn't really just
// simple selector. Technically this compound selector // the one simple selector. Technically this compound
// contains the pseudo element selector as // selector contains the pseudo element selector as well
// well--Combinator::PseudoElement doesn't exist in the // -- Combinator::PseudoElement, just like
// Combinator::SlotAssignment, don't exist in the
// spec. // spec.
(Some(&&Component::Combinator(Combinator::PseudoElement)), _) => (), (Some(&&Component::Combinator(Combinator::PseudoElement)), _) |
(Some(&&Component::Combinator(Combinator::SlotAssignment)), _) => (),
(_, &Component::ExplicitUniversalType) => { (_, &Component::ExplicitUniversalType) => {
// Iterate over everything so we serialize the namespace // Iterate over everything so we serialize the namespace
// too. // too.
@ -914,6 +968,7 @@ impl ToCss for Combinator {
Combinator::NextSibling => dest.write_str(" + "), Combinator::NextSibling => dest.write_str(" + "),
Combinator::LaterSibling => dest.write_str(" ~ "), Combinator::LaterSibling => dest.write_str(" ~ "),
Combinator::PseudoElement => Ok(()), Combinator::PseudoElement => Ok(()),
Combinator::SlotAssignment => Ok(()),
} }
} }
} }
@ -942,6 +997,16 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
Combinator(ref c) => { Combinator(ref c) => {
c.to_css(dest) c.to_css(dest)
} }
Slotted(ref selectors) => {
dest.write_str("::slotted(")?;
let mut iter = selectors.iter();
iter.next().expect("At least one selector").to_css(dest)?;
for other in iter {
dest.write_str(", ")?;
other.to_css(dest)?;
}
dest.write_char(')')
}
PseudoElement(ref p) => { PseudoElement(ref p) => {
p.to_css(dest) p.to_css(dest)
} }
@ -1092,10 +1157,14 @@ where
let mut builder = SelectorBuilder::default(); let mut builder = SelectorBuilder::default();
let mut has_pseudo_element; let mut has_pseudo_element;
let mut slotted;
'outer_loop: loop { 'outer_loop: loop {
// Parse a sequence of simple selectors. // Parse a sequence of simple selectors.
has_pseudo_element = match parse_compound_selector(parser, input, &mut builder)? { match parse_compound_selector(parser, input, &mut builder)? {
Some(has_pseudo_element) => has_pseudo_element, Some((has_pseudo, slot)) => {
has_pseudo_element = has_pseudo;
slotted = slot;
}
None => { None => {
return Err(input.new_custom_error(if builder.has_combinators() { return Err(input.new_custom_error(if builder.has_combinators() {
SelectorParseErrorKind::DanglingCombinator SelectorParseErrorKind::DanglingCombinator
@ -1104,7 +1173,8 @@ where
})) }))
} }
}; };
if has_pseudo_element {
if has_pseudo_element || slotted {
break; break;
} }
@ -1235,6 +1305,7 @@ where
enum SimpleSelectorParseResult<Impl: SelectorImpl> { enum SimpleSelectorParseResult<Impl: SelectorImpl> {
SimpleSelector(Component<Impl>), SimpleSelector(Component<Impl>),
PseudoElement(Impl::PseudoElement), PseudoElement(Impl::PseudoElement),
SlottedPseudo(Box<[Selector<Impl>]>),
} }
#[derive(Debug)] #[derive(Debug)]
@ -1547,7 +1618,8 @@ where
None => { None => {
return Err(input.new_custom_error(SelectorParseErrorKind::EmptyNegation)); return Err(input.new_custom_error(SelectorParseErrorKind::EmptyNegation));
}, },
Some(SimpleSelectorParseResult::PseudoElement(_)) => { Some(SimpleSelectorParseResult::PseudoElement(_)) |
Some(SimpleSelectorParseResult::SlottedPseudo(_)) => {
return Err(input.new_custom_error(SelectorParseErrorKind::NonSimpleSelectorInNegation)); return Err(input.new_custom_error(SelectorParseErrorKind::NonSimpleSelectorInNegation));
} }
} }
@ -1564,12 +1636,13 @@ where
/// `Err(())` means invalid selector. /// `Err(())` means invalid selector.
/// `Ok(None)` is an empty selector /// `Ok(None)` is an empty selector
/// ///
/// The boolean represent whether a pseudo-element has been parsed. /// The booleans represent whether a pseudo-element has been parsed, and whether
/// ::slotted() has been parsed, respectively.
fn parse_compound_selector<'i, 't, P, Impl>( fn parse_compound_selector<'i, 't, P, Impl>(
parser: &P, parser: &P,
input: &mut CssParser<'i, 't>, input: &mut CssParser<'i, 't>,
builder: &mut SelectorBuilder<Impl>, builder: &mut SelectorBuilder<Impl>,
) -> Result<Option<bool>, ParseError<'i, P::Error>> ) -> Result<Option<(bool, bool)>, ParseError<'i, P::Error>>
where where
P: Parser<'i, Impl=Impl>, P: Parser<'i, Impl=Impl>,
Impl: SelectorImpl, Impl: SelectorImpl,
@ -1577,6 +1650,7 @@ where
input.skip_whitespace(); input.skip_whitespace();
let mut empty = true; let mut empty = true;
let mut slot = false;
if !parse_type_selector(parser, input, builder)? { if !parse_type_selector(parser, input, builder)? {
if let Some(url) = parser.default_namespace() { if let Some(url) = parser.default_namespace() {
// If there was no explicit type selector, but there is a // If there was no explicit type selector, but there is a
@ -1590,13 +1664,18 @@ where
let mut pseudo = false; let mut pseudo = false;
loop { loop {
match parse_one_simple_selector(parser, input, /* inside_negation = */ false)? { let parse_result =
None => break, match parse_one_simple_selector(parser, input, /* inside_negation = */ false)? {
Some(SimpleSelectorParseResult::SimpleSelector(s)) => { None => break,
Some(result) => result,
};
match parse_result {
SimpleSelectorParseResult::SimpleSelector(s) => {
builder.push_simple_selector(s); builder.push_simple_selector(s);
empty = false empty = false
} }
Some(SimpleSelectorParseResult::PseudoElement(p)) => { SimpleSelectorParseResult::PseudoElement(p) => {
// Try to parse state to its right. There are only 3 allowable // Try to parse state to its right. There are only 3 allowable
// state selectors that can go on pseudo-elements. // state selectors that can go on pseudo-elements.
let mut state_selectors = SmallVec::<[Component<Impl>; 3]>::new(); let mut state_selectors = SmallVec::<[Component<Impl>; 3]>::new();
@ -1645,13 +1724,25 @@ where
empty = false; empty = false;
break break
} }
SimpleSelectorParseResult::SlottedPseudo(selectors) => {
empty = false;
slot = true;
if !builder.is_empty() {
builder.push_combinator(Combinator::SlotAssignment);
}
builder.push_simple_selector(Component::Slotted(selectors));
// FIXME(emilio): ::slotted() should support ::before and
// ::after after it, so we shouldn't break, but we shouldn't
// push more type selectors either.
break;
}
} }
} }
if empty { if empty {
// An empty selector is invalid. // An empty selector is invalid.
Ok(None) Ok(None)
} else { } else {
Ok(Some(pseudo)) Ok(Some((pseudo, slot)))
} }
} }
@ -1701,7 +1792,7 @@ where
/// Returns whether the name corresponds to a CSS2 pseudo-element that /// Returns whether the name corresponds to a CSS2 pseudo-element that
/// can be specified with the single colon syntax (in addition to the /// can be specified with the single colon syntax (in addition to the
/// double-colon syntax, which can be used for all pseudo-elements). /// double-colon syntax, which can be used for all pseudo-elements).
pub fn is_css2_pseudo_element<'i>(name: &CowRcStr<'i>) -> bool { pub fn is_css2_pseudo_element(name: &str) -> bool {
// ** Do not add to this list! ** // ** Do not add to this list! **
match_ignore_ascii_case! { name, match_ignore_ascii_case! { name,
"before" | "after" | "first-line" | "first-letter" => true, "before" | "after" | "first-line" | "first-letter" => true,
@ -1760,16 +1851,35 @@ where
)), )),
}; };
let is_pseudo_element = !is_single_colon || let is_pseudo_element = !is_single_colon ||
P::is_pseudo_element_allows_single_colon(&name); P::pseudo_element_allows_single_colon(&name);
if is_pseudo_element { if is_pseudo_element {
let pseudo_element = if is_functional { let parse_result = if is_functional {
input.parse_nested_block(|input| { if P::parse_slotted(parser) && name.eq_ignore_ascii_case("slotted") {
P::parse_functional_pseudo_element(parser, name, input) SimpleSelectorParseResult::SlottedPseudo(
})? input.parse_nested_block(|input| {
parse_compound_selector_list(
parser,
input,
)
})?
)
} else {
SimpleSelectorParseResult::PseudoElement(
input.parse_nested_block(|input| {
P::parse_functional_pseudo_element(
parser,
name,
input,
)
})?
)
}
} else { } else {
P::parse_pseudo_element(parser, location, name)? SimpleSelectorParseResult::PseudoElement(
P::parse_pseudo_element(parser, location, name)?
)
}; };
Ok(Some(SimpleSelectorParseResult::PseudoElement(pseudo_element))) Ok(Some(parse_result))
} else { } else {
let pseudo_class = if is_functional { let pseudo_class = if is_functional {
input.parse_nested_block(|input| { input.parse_nested_block(|input| {
@ -1951,6 +2061,10 @@ pub mod tests {
type Impl = DummySelectorImpl; type Impl = DummySelectorImpl;
type Error = SelectorParseErrorKind<'i>; type Error = SelectorParseErrorKind<'i>;
fn parse_slotted(&self) -> bool {
true
}
fn parse_non_ts_pseudo_class( fn parse_non_ts_pseudo_class(
&self, &self,
location: SourceLocation, location: SourceLocation,
@ -2057,9 +2171,9 @@ pub mod tests {
#[test] #[test]
fn test_parsing() { fn test_parsing() {
assert!(parse("").is_err()) ; assert!(parse("").is_err());
assert!(parse(":lang(4)").is_err()) ; assert!(parse(":lang(4)").is_err());
assert!(parse(":lang(en US)").is_err()) ; assert!(parse(":lang(en US)").is_err());
assert_eq!(parse("EeÉ"), Ok(SelectorList::from_vec(vec!( assert_eq!(parse("EeÉ"), Ok(SelectorList::from_vec(vec!(
Selector::from_vec(vec!( Selector::from_vec(vec!(
Component::LocalName(LocalName { Component::LocalName(LocalName {
@ -2366,6 +2480,16 @@ pub mod tests {
].into_boxed_slice() ].into_boxed_slice()
)), specificity(0, 0, 0)) )), specificity(0, 0, 0))
)))); ))));
assert!(parse("::slotted()").is_err());
assert!(parse("::slotted(div)").is_ok());
assert!(parse("::slotted(div).foo").is_err());
assert!(parse("::slotted(div + bar)").is_err());
assert!(parse("::slotted(div) + foo").is_err());
assert!(parse("div ::slotted(div)").is_ok());
assert!(parse("div + slot::slotted(div)").is_ok());
assert!(parse("div + slot::slotted(div.foo)").is_ok());
assert!(parse("div + slot::slotted(.foo, bar, .baz)").is_ok());
} }
#[test] #[test]

View file

@ -84,6 +84,13 @@ pub trait Element: Sized + Clone + Debug {
/// Whether this element is a `link`. /// Whether this element is a `link`.
fn is_link(&self) -> bool; fn is_link(&self) -> bool;
/// Returns the assigned <slot> element this element is assigned to.
///
/// Necessary for the `::slotted` pseudo-class.
fn assigned_slot(&self) -> Option<Self> {
None
}
fn has_id(&self, fn has_id(&self,
id: &<Self::Impl as SelectorImpl>::Identifier, id: &<Self::Impl as SelectorImpl>::Identifier,
case_sensitivity: CaseSensitivity) case_sensitivity: CaseSensitivity)

View file

@ -339,12 +339,7 @@ impl PropertyAnimation {
longhand, longhand,
old_style, old_style,
new_style, new_style,
); )?;
let animated_property = match animated_property {
Some(p) => p,
None => return None,
};
let property_animation = PropertyAnimation { let property_animation = PropertyAnimation {
property: animated_property, property: animated_property,

View file

@ -169,10 +169,8 @@ impl<E: TElement> StyleBloom<E> {
/// Pop the last element in the bloom filter and return it. /// Pop the last element in the bloom filter and return it.
#[inline] #[inline]
fn pop(&mut self) -> Option<E> { fn pop(&mut self) -> Option<E> {
let (popped_element, num_hashes) = match self.elements.pop() { let PushedElement { element, num_hashes } = self.elements.pop()?;
None => return None, let popped_element = *element;
Some(x) => (*x.element, x.num_hashes),
};
// Verify that the pushed hashes match the ones we'd get from the element. // Verify that the pushed hashes match the ones we'd get from the element.
let mut expected_hashes = vec![]; let mut expected_hashes = vec![];

View file

@ -94,6 +94,15 @@ fn generate_properties() {
} }
fn main() { fn main() {
let gecko = cfg!(feature = "gecko");
let servo = cfg!(feature = "servo");
if !(gecko || servo) {
panic!("The style crate requires enabling one of its 'servo' or 'gecko' feature flags");
}
if gecko && servo {
panic!("The style crate does not support enabling both its 'servo' or 'gecko' \
feature flags at the same time.");
}
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
println!("cargo:out_dir={}", env::var("OUT_DIR").unwrap()); println!("cargo:out_dir={}", env::var("OUT_DIR").unwrap());
generate_properties(); generate_properties();

View file

@ -116,6 +116,21 @@ impl Default for StyleSystemOptions {
} }
} }
impl StyleSystemOptions {
#[cfg(feature = "servo")]
/// On Gecko's nightly build?
pub fn is_nightly(&self) -> bool {
false
}
#[cfg(feature = "gecko")]
/// On Gecko's nightly build?
#[inline]
pub fn is_nightly(&self) -> bool {
structs::GECKO_IS_NIGHTLY
}
}
/// A shared style context. /// A shared style context.
/// ///
/// There's exactly one of these during a given restyle traversal, and it's /// There's exactly one of these during a given restyle traversal, and it's

View file

@ -153,10 +153,7 @@ where
K: Borrow<Q>, K: Borrow<Q>,
Q: PrecomputedHash + Hash + Eq, Q: PrecomputedHash + Hash + Eq,
{ {
let index = match self.index.iter().position(|k| k.borrow() == key) { let index = self.index.iter().position(|k| k.borrow() == key)?;
Some(p) => p,
None => return None,
};
self.index.remove(index); self.index.remove(index);
self.values.remove(key) self.values.remove(key)
} }
@ -194,10 +191,7 @@ where
type Item = (&'a K, &'a V); type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let key = match self.inner.index.get(self.pos) { let key = self.inner.index.get(self.pos)?;
Some(k) => k,
None => return None,
};
self.pos += 1; self.pos += 1;
let value = &self.inner.values[key]; let value = &self.inner.values[key];

View file

@ -78,14 +78,10 @@ where
fn next(&mut self) -> Option<N> { fn next(&mut self) -> Option<N> {
loop { loop {
match self.0.next() { let n = self.0.next()?;
Some(n) => { // Filter out nodes that layout should ignore.
// Filter out nodes that layout should ignore. if n.is_text_node() || n.is_element() {
if n.is_text_node() || n.is_element() { return Some(n)
return Some(n)
}
}
None => return None,
} }
} }
} }
@ -100,13 +96,9 @@ where
type Item = N; type Item = N;
fn next(&mut self) -> Option<N> { fn next(&mut self) -> Option<N> {
match self.0.take() { let n = self.0.take()?;
Some(n) => { self.0 = n.next_sibling();
self.0 = n.next_sibling(); Some(n)
Some(n)
}
None => None,
}
} }
} }
@ -124,11 +116,7 @@ where
#[inline] #[inline]
fn next(&mut self) -> Option<N> { fn next(&mut self) -> Option<N> {
let prev = match self.previous.take() { let prev = self.previous.take()?;
None => return None,
Some(n) => n,
};
self.previous = prev.next_in_preorder(Some(self.scope)); self.previous = prev.next_in_preorder(Some(self.scope));
self.previous self.previous
} }

View file

@ -7,7 +7,7 @@
#![deny(missing_docs)] #![deny(missing_docs)]
use context::{StyleContext, ThreadLocalStyleContext}; use context::{StyleContext, ThreadLocalStyleContext, TraversalStatistics};
use dom::{SendNode, TElement, TNode}; use dom::{SendNode, TElement, TNode};
use parallel; use parallel;
use parallel::{DispatchMode, WORK_UNIT_MAX}; use parallel::{DispatchMode, WORK_UNIT_MAX};
@ -25,11 +25,15 @@ use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};
/// processing, until we arrive at a wide enough level in the DOM that the /// processing, until we arrive at a wide enough level in the DOM that the
/// parallel traversal would parallelize it. If a thread pool is provided, we /// parallel traversal would parallelize it. If a thread pool is provided, we
/// then transfer control over to the parallel traversal. /// then transfer control over to the parallel traversal.
///
/// Returns true if the traversal was parallel, and also returns the statistics
/// object containing information on nodes traversed (on nightly only). Not
/// all of its fields will be initialized since we don't call finish().
pub fn traverse_dom<E, D>( pub fn traverse_dom<E, D>(
traversal: &D, traversal: &D,
token: PreTraverseToken<E>, token: PreTraverseToken<E>,
pool: Option<&rayon::ThreadPool> pool: Option<&rayon::ThreadPool>
) ) -> (bool, Option<TraversalStatistics>)
where where
E: TElement, E: TElement,
D: DomTraversal<E>, D: DomTraversal<E>,
@ -38,6 +42,8 @@ where
token.traversal_root().expect("Should've ensured we needed to traverse"); token.traversal_root().expect("Should've ensured we needed to traverse");
let dump_stats = traversal.shared_context().options.dump_style_statistics; let dump_stats = traversal.shared_context().options.dump_style_statistics;
let is_nightly = traversal.shared_context().options.is_nightly();
let mut used_parallel = false;
let start_time = if dump_stats { Some(time::precise_time_s()) } else { None }; let start_time = if dump_stats { Some(time::precise_time_s()) } else { None };
// Declare the main-thread context, as well as the worker-thread contexts, // Declare the main-thread context, as well as the worker-thread contexts,
@ -84,6 +90,7 @@ where
// moving to the next level in the dom so that we can pass the same // moving to the next level in the dom so that we can pass the same
// depth for all the children. // depth for all the children.
if pool.is_some() && discovered.len() > WORK_UNIT_MAX { if pool.is_some() && discovered.len() > WORK_UNIT_MAX {
used_parallel = true;
let pool = pool.unwrap(); let pool = pool.unwrap();
maybe_tls = Some(ScopedTLS::<ThreadLocalStyleContext<E>>::new(pool)); maybe_tls = Some(ScopedTLS::<ThreadLocalStyleContext<E>>::new(pool));
let root_opaque = root.as_node().opaque(); let root_opaque = root.as_node().opaque();
@ -108,9 +115,9 @@ where
nodes_remaining_at_current_depth = discovered.len(); nodes_remaining_at_current_depth = discovered.len();
} }
} }
let mut maybe_stats = None;
// Dump statistics to stdout if requested. // Accumulate statistics
if dump_stats { if dump_stats || is_nightly {
let mut aggregate = let mut aggregate =
mem::replace(&mut context.thread_local.statistics, Default::default()); mem::replace(&mut context.thread_local.statistics, Default::default());
let parallel = maybe_tls.is_some(); let parallel = maybe_tls.is_some();
@ -123,9 +130,14 @@ where
} }
}); });
} }
aggregate.finish(traversal, parallel, start_time.unwrap());
if aggregate.is_large_traversal() { // dump to stdout if requested
println!("{}", aggregate); if dump_stats && aggregate.is_large_traversal() {
aggregate.finish(traversal, parallel, start_time.unwrap());
println!("{}", aggregate);
} }
maybe_stats = Some(aggregate);
} }
(used_parallel, maybe_stats)
} }

View file

@ -5,6 +5,7 @@
//! Data needed to style a Gecko document. //! Data needed to style a Gecko document.
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use context::TraversalStatistics;
use dom::TElement; use dom::TElement;
use gecko_bindings::bindings::{self, RawServoStyleSet}; use gecko_bindings::bindings::{self, RawServoStyleSet};
use gecko_bindings::structs::{RawGeckoPresContextOwned, ServoStyleSetSizes, ServoStyleSheet}; use gecko_bindings::structs::{RawGeckoPresContextOwned, ServoStyleSetSizes, ServoStyleSheet};
@ -16,6 +17,7 @@ use media_queries::{Device, MediaList};
use properties::ComputedValues; use properties::ComputedValues;
use servo_arc::Arc; use servo_arc::Arc;
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard}; use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
use std::sync::atomic::{AtomicUsize, Ordering};
use stylesheets::{StylesheetContents, StylesheetInDocument}; use stylesheets::{StylesheetContents, StylesheetInDocument};
use stylist::Stylist; use stylist::Stylist;
@ -107,11 +109,40 @@ impl StylesheetInDocument for GeckoStyleSheet {
} }
} }
#[derive(Default)]
/// Helper struct for counting traversals
pub struct TraversalCount {
/// Total number of events
pub total_count: AtomicUsize,
/// Number of events which were parallel
pub parallel_count: AtomicUsize
}
impl TraversalCount {
fn record(&self, parallel: bool, count: u32) {
self.total_count.fetch_add(count as usize, Ordering::Relaxed);
if parallel {
self.parallel_count.fetch_add(count as usize, Ordering::Relaxed);
}
}
fn get(&self) -> (u32, u32) {
(self.total_count.load(Ordering::Relaxed) as u32,
self.parallel_count.load(Ordering::Relaxed) as u32)
}
}
/// The container for data that a Servo-backed Gecko document needs to style /// The container for data that a Servo-backed Gecko document needs to style
/// itself. /// itself.
pub struct PerDocumentStyleDataImpl { pub struct PerDocumentStyleDataImpl {
/// Rule processor. /// Rule processor.
pub stylist: Stylist, pub stylist: Stylist,
/// Counter for traversals that could have been parallel, for telemetry
pub traversal_count: TraversalCount,
/// Counter for traversals, weighted by elements traversed,
pub traversal_count_traversed: TraversalCount,
/// Counter for traversals, weighted by elements styled,
pub traversal_count_styled: TraversalCount,
} }
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics /// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
@ -133,6 +164,9 @@ impl PerDocumentStyleData {
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl { PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
stylist: Stylist::new(device, quirks_mode.into()), stylist: Stylist::new(device, quirks_mode.into()),
traversal_count: Default::default(),
traversal_count_traversed: Default::default(),
traversal_count_styled: Default::default(),
})) }))
} }
@ -147,6 +181,21 @@ impl PerDocumentStyleData {
} }
} }
impl Drop for PerDocumentStyleDataImpl {
fn drop(&mut self) {
if !structs::GECKO_IS_NIGHTLY {
return
}
let (total, parallel) = self.traversal_count.get();
let (total_t, parallel_t) = self.traversal_count_traversed.get();
let (total_s, parallel_s) = self.traversal_count_styled.get();
unsafe { bindings::Gecko_RecordTraversalStatistics(total, parallel,
total_t, parallel_t,
total_s, parallel_s) }
}
}
impl PerDocumentStyleDataImpl { impl PerDocumentStyleDataImpl {
/// Recreate the style data if the stylesheets have changed. /// Recreate the style data if the stylesheets have changed.
pub fn flush_stylesheets<E>( pub fn flush_stylesheets<E>(
@ -209,6 +258,15 @@ impl PerDocumentStyleDataImpl {
pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) { pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
self.stylist.add_size_of(ops, sizes); self.stylist.add_size_of(ops, sizes);
} }
/// Record that a traversal happened for later collection as telemetry
pub fn record_traversal(&self, was_parallel: bool, stats: Option<TraversalStatistics>) {
self.traversal_count.record(was_parallel, 1);
if let Some(stats) = stats {
self.traversal_count_traversed.record(was_parallel, stats.elements_traversed);
self.traversal_count_styled.record(was_parallel, stats.elements_styled);
}
}
} }
unsafe impl HasFFI for PerDocumentStyleData { unsafe impl HasFFI for PerDocumentStyleData {

View file

@ -499,6 +499,8 @@ extern "C" {
pub fn Servo_SelectorList_Drop ( ptr : RawServoSelectorListOwned , ) ; pub fn Servo_SelectorList_Drop ( ptr : RawServoSelectorListOwned , ) ;
} extern "C" { } extern "C" {
pub fn Servo_SourceSizeList_Drop ( ptr : RawServoSourceSizeListOwned , ) ; pub fn Servo_SourceSizeList_Drop ( ptr : RawServoSourceSizeListOwned , ) ;
} extern "C" {
pub fn Gecko_RecordTraversalStatistics ( total : u32 , parallel : u32 , total_t : u32 , parallel_t : u32 , total_s : u32 , parallel_s : u32 , ) ;
} extern "C" { } extern "C" {
pub fn Gecko_IsInDocument ( node : RawGeckoNodeBorrowed , ) -> bool ; pub fn Gecko_IsInDocument ( node : RawGeckoNodeBorrowed , ) -> bool ;
} extern "C" { } extern "C" {

File diff suppressed because one or more lines are too long

View file

@ -9,9 +9,9 @@ use element_state::{DocumentState, ElementState};
use gecko_bindings::structs::CSSPseudoClassType; use gecko_bindings::structs::CSSPseudoClassType;
use gecko_bindings::structs::RawServoSelectorList; use gecko_bindings::structs::RawServoSelectorList;
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI}; use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
use selector_parser::{Direction, SelectorParser, PseudoElementCascadeType}; use selector_parser::{Direction, SelectorParser};
use selectors::SelectorList; use selectors::SelectorList;
use selectors::parser::{Selector, SelectorMethods, SelectorParseErrorKind}; use selectors::parser::{self as selector_parser, Selector, SelectorMethods, SelectorParseErrorKind};
use selectors::visitor::SelectorVisitor; use selectors::visitor::SelectorVisitor;
use std::fmt; use std::fmt;
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
@ -333,9 +333,10 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
type Impl = SelectorImpl; type Impl = SelectorImpl;
type Error = StyleParseErrorKind<'i>; type Error = StyleParseErrorKind<'i>;
fn is_pseudo_element_allows_single_colon(name: &CowRcStr<'i>) -> bool { fn pseudo_element_allows_single_colon(name: &str) -> bool {
// FIXME: -moz-tree check should probably be ascii-case-insensitive.
::selectors::parser::is_css2_pseudo_element(name) || ::selectors::parser::is_css2_pseudo_element(name) ||
name.starts_with("-moz-tree-") // tree pseudo-elements name.starts_with("-moz-tree-")
} }
fn parse_non_ts_pseudo_class( fn parse_non_ts_pseudo_class(
@ -399,16 +400,12 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
NonTSPseudoClass::Dir(Box::new(direction)) NonTSPseudoClass::Dir(Box::new(direction))
}, },
"-moz-any" => { "-moz-any" => {
let selectors = parser.parse_comma_separated(|input| { NonTSPseudoClass::MozAny(
Selector::parse(self, input) selector_parser::parse_compound_selector_list(
})?; self,
// Selectors inside `:-moz-any` may not include combinators. parser,
if selectors.iter().flat_map(|x| x.iter_raw_match_order()).any(|s| s.is_combinator()) { )?
return Err(parser.new_custom_error( )
SelectorParseErrorKind::UnexpectedIdent("-moz-any".into())
))
}
NonTSPseudoClass::MozAny(selectors.into_boxed_slice())
} }
_ => return Err(parser.new_custom_error( _ => return Err(parser.new_custom_error(
SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone()) SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone())
@ -431,6 +428,8 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
) -> Result<PseudoElement, ParseError<'i>> { ) -> Result<PseudoElement, ParseError<'i>> {
PseudoElement::from_slice(&name, self.in_user_agent_stylesheet()) PseudoElement::from_slice(&name, self.in_user_agent_stylesheet())
.or_else(|| { .or_else(|| {
// FIXME: -moz-tree check should probably be
// ascii-case-insensitive.
if name.starts_with("-moz-tree-") { if name.starts_with("-moz-tree-") {
PseudoElement::tree_pseudo_element(&name, Box::new([])) PseudoElement::tree_pseudo_element(&name, Box::new([]))
} else { } else {
@ -445,9 +444,10 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
name: CowRcStr<'i>, name: CowRcStr<'i>,
parser: &mut Parser<'i, 't>, parser: &mut Parser<'i, 't>,
) -> Result<PseudoElement, ParseError<'i>> { ) -> Result<PseudoElement, ParseError<'i>> {
// FIXME: -moz-tree check should probably be ascii-case-insensitive.
if name.starts_with("-moz-tree-") { if name.starts_with("-moz-tree-") {
// Tree pseudo-elements can have zero or more arguments, // Tree pseudo-elements can have zero or more arguments, separated
// separated by either comma or space. // by either comma or space.
let mut args = Vec::new(); let mut args = Vec::new();
loop { loop {
let location = parser.current_source_location(); let location = parser.current_source_location();
@ -477,12 +477,6 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
} }
impl SelectorImpl { impl SelectorImpl {
#[inline]
/// Legacy alias for PseudoElement::cascade_type.
pub fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
pseudo.cascade_type()
}
/// A helper to traverse each eagerly cascaded pseudo-element, executing /// A helper to traverse each eagerly cascaded pseudo-element, executing
/// `fun` on it. /// `fun` on it.
#[inline] #[inline]

View file

@ -428,10 +428,7 @@ impl<'lb> GeckoXBLBinding<'lb> {
if !binding.anon_content().is_null() { if !binding.anon_content().is_null() {
return Some(binding); return Some(binding);
} }
binding = match binding.base_binding() { binding = binding.base_binding()?;
Some(b) => b,
None => return None,
};
} }
} }
@ -1006,20 +1003,14 @@ impl<'le> TElement for GeckoElement<'le> {
fn closest_non_native_anonymous_ancestor(&self) -> Option<Self> { fn closest_non_native_anonymous_ancestor(&self) -> Option<Self> {
debug_assert!(self.is_native_anonymous()); debug_assert!(self.is_native_anonymous());
let mut parent = match self.traversal_parent() { let mut parent = self.traversal_parent()?;
Some(e) => e,
None => return None,
};
loop { loop {
if !parent.is_native_anonymous() { if !parent.is_native_anonymous() {
return Some(parent); return Some(parent);
} }
parent = match parent.traversal_parent() { parent = parent.traversal_parent()?;
Some(p) => p,
None => return None,
};
} }
} }
@ -1054,16 +1045,10 @@ impl<'le> TElement for GeckoElement<'le> {
fn get_smil_override(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> { fn get_smil_override(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
unsafe { unsafe {
let slots = match self.get_extended_slots() { let slots = self.get_extended_slots()?;
Some(s) => s,
None => return None,
};
let base_declaration: &structs::DeclarationBlock = let base_declaration: &structs::DeclarationBlock =
match slots.mSMILOverrideStyleDeclaration.mRawPtr.as_ref() { slots.mSMILOverrideStyleDeclaration.mRawPtr.as_ref()?;
Some(decl) => decl,
None => return None,
};
assert_eq!(base_declaration.mType, structs::StyleBackendType_Servo); assert_eq!(base_declaration.mType, structs::StyleBackendType_Servo);
let declaration: &structs::ServoDeclarationBlock = let declaration: &structs::ServoDeclarationBlock =
@ -1074,11 +1059,7 @@ impl<'le> TElement for GeckoElement<'le> {
base_declaration as *const structs::DeclarationBlock base_declaration as *const structs::DeclarationBlock
); );
let raw: &structs::RawServoDeclarationBlock = let raw: &structs::RawServoDeclarationBlock = declaration.mRaw.mRawPtr.as_ref()?;
match declaration.mRaw.mRawPtr.as_ref() {
Some(decl) => decl,
None => return None,
};
Some(Locked::<PropertyDeclarationBlock>::as_arc( Some(Locked::<PropertyDeclarationBlock>::as_arc(
&*(&raw as *const &structs::RawServoDeclarationBlock) &*(&raw as *const &structs::RawServoDeclarationBlock)

View file

@ -127,10 +127,7 @@ impl<'a, E> ElementWrapper<'a, E>
if lang.is_some() { if lang.is_some() {
return lang; return lang;
} }
match current.parent_element() { current = current.parent_element()?;
Some(parent) => current = parent,
None => return None,
}
} }
} }
} }

View file

@ -149,8 +149,10 @@ pub trait Parse : Sized {
/// Parse a value of this type. /// Parse a value of this type.
/// ///
/// Returns an error on failure. /// Returns an error on failure.
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) fn parse<'i, 't>(
-> Result<Self, ParseError<'i>>; context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>>;
} }
impl<T> Parse for Vec<T> impl<T> Parse for Vec<T>

View file

@ -140,14 +140,9 @@ impl<'a> Iterator for NormalDeclarationIterator<'a> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
loop { loop {
let next = self.0.iter.next(); let (decl, importance) = self.0.iter.next()?;
match next { if !importance {
Some((decl, importance)) => { return Some(decl);
if !importance {
return Some(decl);
}
},
None => return None,
} }
} }
} }
@ -171,7 +166,7 @@ impl<'a, 'cx, 'cx_a:'cx> AnimationValueIterator<'a, 'cx, 'cx_a> {
declarations: &'a PropertyDeclarationBlock, declarations: &'a PropertyDeclarationBlock,
context: &'cx mut Context<'cx_a>, context: &'cx mut Context<'cx_a>,
default_values: &'a ComputedValues, default_values: &'a ComputedValues,
extra_custom_properties: Option<&'a Arc<::custom_properties::CustomPropertiesMap>>, extra_custom_properties: Option<&'a Arc<::custom_properties::CustomPropertiesMap>>,
) -> AnimationValueIterator<'a, 'cx, 'cx_a> { ) -> AnimationValueIterator<'a, 'cx, 'cx_a> {
AnimationValueIterator { AnimationValueIterator {
iter: declarations.normal_declaration_iter(), iter: declarations.normal_declaration_iter(),
@ -187,11 +182,7 @@ impl<'a, 'cx, 'cx_a:'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> {
#[inline] #[inline]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
loop { loop {
let next = self.iter.next(); let decl = self.iter.next()?;
let decl = match next {
Some(decl) => decl,
None => return None,
};
let animation = AnimationValue::from_declaration( let animation = AnimationValue::from_declaration(
decl, decl,

View file

@ -61,6 +61,7 @@ use values::{self, Auto, CustomIdent, Either, KeyframesName, None_};
use values::computed::{NonNegativeLength, ToComputedValue, Percentage}; use values::computed::{NonNegativeLength, ToComputedValue, Percentage};
use values::computed::font::{FontSize, SingleFontFamily}; use values::computed::font::{FontSize, SingleFontFamily};
use values::computed::effects::{BoxShadow, Filter, SimpleShadow}; use values::computed::effects::{BoxShadow, Filter, SimpleShadow};
use values::computed::outline::OutlineStyle;
use computed_values::border_style; use computed_values::border_style;
pub mod style_structs { pub mod style_structs {
@ -2348,10 +2349,10 @@ fn static_assert() {
// cast + static_asserts // cast + static_asserts
let result = match v { let result = match v {
% for value in border_style_keyword.values_for('gecko'): % for value in border_style_keyword.values_for('gecko'):
Either::Second(border_style::T::${to_camel_case(value)}) => OutlineStyle::Other(border_style::T::${to_camel_case(value)}) =>
structs::${border_style_keyword.gecko_constant(value)} ${border_style_keyword.maybe_cast("u8")}, structs::${border_style_keyword.gecko_constant(value)} ${border_style_keyword.maybe_cast("u8")},
% endfor % endfor
Either::First(Auto) => OutlineStyle::Auto =>
structs::${border_style_keyword.gecko_constant('auto')} ${border_style_keyword.maybe_cast("u8")}, structs::${border_style_keyword.gecko_constant('auto')} ${border_style_keyword.maybe_cast("u8")},
}; };
${set_gecko_property("mOutlineStyle", "result")} ${set_gecko_property("mOutlineStyle", "result")}
@ -2378,10 +2379,10 @@ fn static_assert() {
match ${get_gecko_property("mOutlineStyle")} ${border_style_keyword.maybe_cast("u32")} { match ${get_gecko_property("mOutlineStyle")} ${border_style_keyword.maybe_cast("u32")} {
% for value in border_style_keyword.values_for('gecko'): % for value in border_style_keyword.values_for('gecko'):
structs::${border_style_keyword.gecko_constant(value)} => { structs::${border_style_keyword.gecko_constant(value)} => {
Either::Second(border_style::T::${to_camel_case(value)}) OutlineStyle::Other(border_style::T::${to_camel_case(value)})
}, },
% endfor % endfor
structs::${border_style_keyword.gecko_constant('auto')} => Either::First(Auto), structs::${border_style_keyword.gecko_constant('auto')} => OutlineStyle::Auto,
% if border_style_keyword.gecko_inexhaustive: % if border_style_keyword.gecko_inexhaustive:
x => panic!("Found unexpected value in style struct for outline_style property: {:?}", x), x => panic!("Found unexpected value in style struct for outline_style property: {:?}", x),
% endif % endif
@ -3618,11 +3619,11 @@ fn static_assert() {
if self.gecko.mWillChange.len() == 0 { if self.gecko.mWillChange.len() == 0 {
T::Auto T::Auto
} else { } else {
T::AnimateableFeatures( let custom_idents: Vec<CustomIdent> = self.gecko.mWillChange.iter().map(|gecko_atom| {
self.gecko.mWillChange.iter().map(|gecko_atom| { CustomIdent((gecko_atom.mRawPtr as *mut nsAtom).into())
CustomIdent((gecko_atom.mRawPtr as *mut nsAtom).into()) }).collect();
}).collect()
) T::AnimateableFeatures(custom_idents.into_boxed_slice())
} }
} }
@ -4228,8 +4229,11 @@ fn static_assert() {
let ref gecko_quote_values = *self.gecko.mQuotes.mRawPtr; let ref gecko_quote_values = *self.gecko.mQuotes.mRawPtr;
longhands::quotes::computed_value::T( longhands::quotes::computed_value::T(
gecko_quote_values.mQuotePairs.iter().map(|gecko_pair| { gecko_quote_values.mQuotePairs.iter().map(|gecko_pair| {
(gecko_pair.first.to_string(), gecko_pair.second.to_string()) (
}).collect() gecko_pair.first.to_string().into_boxed_str(),
gecko_pair.second.to_string().into_boxed_str(),
)
}).collect::<Vec<_>>().into_boxed_slice()
) )
} }
} }

View file

@ -262,7 +262,7 @@ impl AnimatedProperty {
% for prop in data.longhands: % for prop in data.longhands:
% if prop.animatable: % if prop.animatable:
AnimatedProperty::${prop.camel_case}(ref from, ref to) => { AnimatedProperty::${prop.camel_case}(ref from, ref to) => {
// https://w3c.github.io/web-animations/#discrete-animation-type // https://drafts.csswg.org/web-animations/#discrete-animation-type
% if prop.animation_value_type == "discrete": % if prop.animation_value_type == "discrete":
let value = if progress < 0.5 { from.clone() } else { to.clone() }; let value = if progress < 0.5 { from.clone() } else { to.clone() };
% else: % else:
@ -2833,7 +2833,7 @@ impl ComputeSquaredDistance for AnimatedFilterList {
/// ///
/// border-top-color, border-color, border-top, border /// border-top-color, border-color, border-top, border
/// ///
/// [property-order] https://w3c.github.io/web-animations/#calculating-computed-keyframes /// [property-order] https://drafts.csswg.org/web-animations/#calculating-computed-keyframes
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn compare_property_priority(a: &PropertyId, b: &PropertyId) -> cmp::Ordering { pub fn compare_property_priority(a: &PropertyId, b: &PropertyId) -> cmp::Ordering {
match (a.as_shorthand(), b.as_shorthand()) { match (a.as_shorthand(), b.as_shorthand()) {

View file

@ -881,62 +881,14 @@ ${helpers.single_keyword("-moz-orient",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-orient)", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-orient)",
animation_value_type="discrete")} animation_value_type="discrete")}
<%helpers:longhand name="will-change" products="gecko" animation_value_type="discrete" ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-will-change/#will-change"> "will-change",
use std::fmt; "WillChange",
use style_traits::ToCss; "computed::WillChange::auto()",
use values::CustomIdent; products="gecko",
animation_value_type="discrete",
pub mod computed_value { spec="https://drafts.csswg.org/css-will-change/#will-change"
pub use super::SpecifiedValue as T; )}
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
pub enum SpecifiedValue {
Auto,
AnimateableFeatures(Vec<CustomIdent>),
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
SpecifiedValue::Auto => dest.write_str("auto"),
SpecifiedValue::AnimateableFeatures(ref features) => {
let (first, rest) = features.split_first().unwrap();
first.to_css(dest)?;
for feature in rest {
dest.write_str(", ")?;
feature.to_css(dest)?;
}
Ok(())
}
}
}
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::Auto
}
/// auto | <animateable-feature>#
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
Ok(computed_value::T::Auto)
} else {
input.parse_comma_separated(|i| {
let location = i.current_source_location();
CustomIdent::from_ident(location, i.expect_ident()?, &[
"will-change",
"none",
"all",
"auto",
])
}).map(SpecifiedValue::AnimateableFeatures)
}
}
</%helpers:longhand>
${helpers.predefined_type( ${helpers.predefined_type(
"shape-image-threshold", "Opacity", "0.0", "shape-image-threshold", "Opacity", "0.0",

View file

@ -95,116 +95,19 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
</%helpers:longhand> </%helpers:longhand>
% endif % endif
<%helpers:longhand name="list-style-image" animation_value_type="discrete" ${helpers.predefined_type("list-style-image",
boxed="${product == 'gecko'}" "ListStyleImage",
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image"> initial_value="specified::ListStyleImage::none()",
use values::specified::UrlOrNone; initial_specified_value="specified::ListStyleImage::none()",
pub use self::computed_value::T as SpecifiedValue; animation_value_type="discrete",
boxed=product == "gecko",
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image")}
pub mod computed_value { ${helpers.predefined_type("quotes",
use values::specified::UrlOrNone; "Quotes",
"computed::Quotes::get_initial_value()",
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] animation_value_type="discrete",
pub struct T(pub UrlOrNone); spec="https://drafts.csswg.org/css-content/#propdef-quotes")}
// FIXME(nox): This is wrong, there are different types for specified
// and computed URLs in Servo.
trivial_to_computed_value!(T);
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T(Either::Second(None_))
}
#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue(Either::Second(None_))
}
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
% if product == "gecko":
let mut value = input.try(|input| UrlOrNone::parse(context, input))?;
if let Either::First(ref mut url) = value {
url.build_image_value();
}
% else :
let value = input.try(|input| UrlOrNone::parse(context, input))?;
% endif
return Ok(SpecifiedValue(value));
}
</%helpers:longhand>
<%helpers:longhand name="quotes" animation_value_type="discrete"
spec="https://drafts.csswg.org/css-content/#propdef-quotes">
use cssparser::serialize_string;
use std::fmt;
use style_traits::ToCss;
pub use self::computed_value::T as SpecifiedValue;
pub mod computed_value {
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
pub struct T(pub Vec<(String, String)>);
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if self.0.is_empty() {
return dest.write_str("none")
}
let mut first = true;
for pair in &self.0 {
if !first {
dest.write_str(" ")?;
}
first = false;
serialize_string(&*pair.0, dest)?;
dest.write_str(" ")?;
serialize_string(&*pair.1, dest)?;
}
Ok(())
}
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T(vec![
("\u{201c}".to_owned(), "\u{201d}".to_owned()),
("\u{2018}".to_owned(), "\u{2019}".to_owned()),
])
}
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue(Vec::new()))
}
let mut quotes = Vec::new();
loop {
let location = input.current_source_location();
let first = match input.next() {
Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
Err(_) => break,
};
let location = input.current_source_location();
let second = match input.next() {
Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
Err(e) => return Err(e.into()),
};
quotes.push((first, second))
}
if !quotes.is_empty() {
Ok(SpecifiedValue(quotes))
} else {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
</%helpers:longhand>
${helpers.predefined_type("-moz-image-region", ${helpers.predefined_type("-moz-image-region",
"ClipRectOrAuto", "ClipRectOrAuto",

View file

@ -20,51 +20,14 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-ui/#propdef-outline-color", spec="https://drafts.csswg.org/css-ui/#propdef-outline-color",
)} )}
<%helpers:longhand name="outline-style" animation_value_type="discrete" ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-ui/#propdef-outline-style"> "outline-style",
use values::specified::BorderStyle; "OutlineStyle",
"computed::OutlineStyle::none()",
pub type SpecifiedValue = Either<Auto, BorderStyle>; initial_specified_value="specified::OutlineStyle::none()",
animation_value_type="discrete",
impl SpecifiedValue { spec="https://drafts.csswg.org/css-ui/#propdef-outline-style",
#[inline] )}
pub fn none_or_hidden(&self) -> bool {
match *self {
Either::First(ref _auto) => false,
Either::Second(ref border_style) => border_style.none_or_hidden()
}
}
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
Either::Second(BorderStyle::None)
}
#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
Either::Second(BorderStyle::None)
}
pub mod computed_value {
pub type T = super::SpecifiedValue;
}
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
SpecifiedValue::parse(context, input)
.and_then(|result| {
if let Either::Second(BorderStyle::Hidden) = result {
// The outline-style property accepts the same values as
// border-style, except that 'hidden' is not a legal outline
// style.
Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent("hidden".into())))
} else {
Ok(result)
}
})
}
</%helpers:longhand>
${helpers.predefined_type("outline-width", ${helpers.predefined_type("outline-width",
"BorderSideWidth", "BorderSideWidth",

View file

@ -257,7 +257,6 @@ ${helpers.predefined_type("object-position",
"computed::NonNegativeLengthOrPercentage::zero()", "computed::NonNegativeLengthOrPercentage::zero()",
spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-gap" % kind, spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-gap" % kind,
animation_value_type="NonNegativeLengthOrPercentage", animation_value_type="NonNegativeLengthOrPercentage",
gecko_pref="layout.css.grid.enabled",
products="gecko")} products="gecko")}
% for range in ["start", "end"]: % for range in ["start", "end"]:
@ -267,7 +266,6 @@ ${helpers.predefined_type("object-position",
animation_value_type="discrete", animation_value_type="discrete",
spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-%s" % (kind, range), spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-%s" % (kind, range),
products="gecko", products="gecko",
gecko_pref="layout.css.grid.enabled",
boxed=True)} boxed=True)}
% endfor % endfor
@ -279,7 +277,6 @@ ${helpers.predefined_type("object-position",
animation_value_type="discrete", animation_value_type="discrete",
spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-%ss" % kind, spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-%ss" % kind,
products="gecko", products="gecko",
gecko_pref="layout.css.grid.enabled",
boxed=True)} boxed=True)}
${helpers.predefined_type("grid-template-%ss" % kind, ${helpers.predefined_type("grid-template-%ss" % kind,
@ -288,7 +285,6 @@ ${helpers.predefined_type("object-position",
products="gecko", products="gecko",
spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-%ss" % kind, spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-%ss" % kind,
boxed=True, boxed=True,
gecko_pref="layout.css.grid.enabled",
animation_value_type="discrete")} animation_value_type="discrete")}
% endfor % endfor
@ -298,7 +294,6 @@ ${helpers.predefined_type("grid-auto-flow",
initial_value="computed::GridAutoFlow::row()", initial_value="computed::GridAutoFlow::row()",
products="gecko", products="gecko",
animation_value_type="discrete", animation_value_type="discrete",
gecko_pref="layout.css.grid.enabled",
spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-flow")} spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-flow")}
${helpers.predefined_type("grid-template-areas", ${helpers.predefined_type("grid-template-areas",
@ -306,6 +301,5 @@ ${helpers.predefined_type("grid-template-areas",
initial_value="computed::GridTemplateAreas::none()", initial_value="computed::GridTemplateAreas::none()",
products="gecko", products="gecko",
animation_value_type="discrete", animation_value_type="discrete",
gecko_pref="layout.css.grid.enabled",
boxed=True, boxed=True,
spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-areas")} spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-areas")}

View file

@ -850,11 +850,13 @@ impl ShorthandId {
/// Finds and returns an appendable value for the given declarations. /// Finds and returns an appendable value for the given declarations.
/// ///
/// Returns the optional appendable value. /// Returns the optional appendable value.
pub fn get_shorthand_appendable_value<'a, I>(self, pub fn get_shorthand_appendable_value<'a, I>(
declarations: I) self,
-> Option<AppendableValue<'a, I::IntoIter>> declarations: I,
where I: IntoIterator<Item=&'a PropertyDeclaration>, ) -> Option<AppendableValue<'a, I::IntoIter>>
I::IntoIter: Clone, where
I: IntoIterator<Item=&'a PropertyDeclaration>,
I::IntoIter: Clone,
{ {
let declarations = declarations.into_iter(); let declarations = declarations.into_iter();
@ -862,10 +864,7 @@ impl ShorthandId {
let mut declarations2 = declarations.clone(); let mut declarations2 = declarations.clone();
let mut declarations3 = declarations.clone(); let mut declarations3 = declarations.clone();
let first_declaration = match declarations2.next() { let first_declaration = declarations2.next()?;
Some(declaration) => declaration,
None => return None
};
// https://drafts.csswg.org/css-variables/#variables-in-shorthands // https://drafts.csswg.org/css-variables/#variables-in-shorthands
if let Some(css) = first_declaration.with_variables_from_shorthand(self) { if let Some(css) = first_declaration.with_variables_from_shorthand(self) {

View file

@ -103,7 +103,6 @@
</%helpers:shorthand> </%helpers:shorthand>
<%helpers:shorthand name="grid-gap" sub_properties="grid-row-gap grid-column-gap" <%helpers:shorthand name="grid-gap" sub_properties="grid-row-gap grid-column-gap"
gecko_pref="layout.css.grid.enabled"
spec="https://drafts.csswg.org/css-grid/#propdef-grid-gap" spec="https://drafts.csswg.org/css-grid/#propdef-grid-gap"
products="gecko"> products="gecko">
use properties::longhands::{grid_row_gap, grid_column_gap}; use properties::longhands::{grid_row_gap, grid_column_gap};
@ -135,7 +134,6 @@
% for kind in ["row", "column"]: % for kind in ["row", "column"]:
<%helpers:shorthand name="grid-${kind}" sub_properties="grid-${kind}-start grid-${kind}-end" <%helpers:shorthand name="grid-${kind}" sub_properties="grid-${kind}-start grid-${kind}-end"
gecko_pref="layout.css.grid.enabled"
spec="https://drafts.csswg.org/css-grid/#propdef-grid-${kind}" spec="https://drafts.csswg.org/css-grid/#propdef-grid-${kind}"
products="gecko"> products="gecko">
use values::specified::GridLine; use values::specified::GridLine;
@ -175,7 +173,6 @@
% endfor % endfor
<%helpers:shorthand name="grid-area" <%helpers:shorthand name="grid-area"
gecko_pref="layout.css.grid.enabled"
sub_properties="grid-row-start grid-row-end grid-column-start grid-column-end" sub_properties="grid-row-start grid-row-end grid-column-start grid-column-end"
spec="https://drafts.csswg.org/css-grid/#propdef-grid-area" spec="https://drafts.csswg.org/css-grid/#propdef-grid-area"
products="gecko"> products="gecko">
@ -241,7 +238,6 @@
</%helpers:shorthand> </%helpers:shorthand>
<%helpers:shorthand name="grid-template" <%helpers:shorthand name="grid-template"
gecko_pref="layout.css.grid.enabled"
sub_properties="grid-template-rows grid-template-columns grid-template-areas" sub_properties="grid-template-rows grid-template-columns grid-template-areas"
spec="https://drafts.csswg.org/css-grid/#propdef-grid-template" spec="https://drafts.csswg.org/css-grid/#propdef-grid-template"
products="gecko"> products="gecko">
@ -463,7 +459,6 @@
</%helpers:shorthand> </%helpers:shorthand>
<%helpers:shorthand name="grid" <%helpers:shorthand name="grid"
gecko_pref="layout.css.grid.enabled"
sub_properties="grid-template-rows grid-template-columns grid-template-areas sub_properties="grid-template-rows grid-template-columns grid-template-areas
grid-auto-rows grid-auto-columns grid-auto-flow" grid-auto-rows grid-auto-columns grid-auto-flow"
spec="https://drafts.csswg.org/css-grid/#propdef-grid" spec="https://drafts.csswg.org/css-grid/#propdef-grid"

View file

@ -102,20 +102,16 @@ impl RuleCache {
return None; return None;
} }
let rules = match builder_with_early_props.rules { let rules = builder_with_early_props.rules.as_ref()?;
Some(ref rules) => rules, let cached_values = self.map.get(rules)?;
None => return None,
};
self.map.get(rules).and_then(|cached_values| { for &(ref conditions, ref values) in cached_values.iter() {
for &(ref conditions, ref values) in cached_values.iter() { if conditions.matches(builder_with_early_props) {
if conditions.matches(builder_with_early_props) { debug!("Using cached reset style with conditions {:?}", conditions);
debug!("Using cached reset style with conditions {:?}", conditions); return Some(&**values)
return Some(&**values)
}
} }
None }
}) None
} }
/// Inserts a node into the rules cache if possible. /// Inserts a node into the rules cache if possible.

View file

@ -547,12 +547,6 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
} }
impl SelectorImpl { impl SelectorImpl {
/// Returns the pseudo-element cascade type of the given `pseudo`.
#[inline]
pub fn pseudo_element_cascade_type(pseudo: &PseudoElement) -> PseudoElementCascadeType {
pseudo.cascade_type()
}
/// A helper to traverse each eagerly cascaded pseudo-element, executing /// A helper to traverse each eagerly cascaded pseudo-element, executing
/// `fun` on it. /// `fun` on it.
#[inline] #[inline]

View file

@ -376,11 +376,7 @@ where
originating_element_style.style(), originating_element_style.style(),
pseudo, pseudo,
VisitedHandlingMode::AllLinksUnvisited VisitedHandlingMode::AllLinksUnvisited
); )?;
let rules = match rules {
Some(rules) => rules,
None => return None,
};
let mut visited_rules = None; let mut visited_rules = None;
if originating_element_style.style().visited_style().is_some() { if originating_element_style.style().visited_style().is_some() {

View file

@ -80,10 +80,7 @@ where
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
loop { loop {
if self.current.is_none() { if self.current.is_none() {
let next_origin = match self.origins.next() { let next_origin = self.origins.next()?;
Some(o) => o,
None => return None,
};
self.current = self.current =
Some((next_origin, self.collections.borrow_for_origin(&next_origin).iter())); Some((next_origin, self.collections.borrow_for_origin(&next_origin).iter()));
@ -238,10 +235,7 @@ where
use std::mem; use std::mem;
loop { loop {
let potential_sheet = match self.iter.next() { let potential_sheet = self.iter.next()?;
Some(s) => s,
None => return None,
};
let dirty = mem::replace(&mut potential_sheet.dirty, false); let dirty = mem::replace(&mut potential_sheet.dirty, false);
if dirty { if dirty {

View file

@ -89,10 +89,7 @@ impl Iterator for OriginSetIterator {
fn next(&mut self) -> Option<Origin> { fn next(&mut self) -> Option<Origin> {
loop { loop {
let origin = match Origin::from_index(self.cur) { let origin = Origin::from_index(self.cur)?;
Some(origin) => origin,
None => return None,
};
self.cur += 1; self.cur += 1;
@ -184,10 +181,7 @@ impl<'a, T> Iterator for PerOriginIter<'a, T> where T: 'a {
type Item = (&'a T, Origin); type Item = (&'a T, Origin);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let origin = match Origin::from_index(self.cur) { let origin = Origin::from_index(self.cur)?;
Some(origin) => origin,
None => return None,
};
self.cur += if self.rev { -1 } else { 1 }; self.cur += if self.rev { -1 } else { 1 };
@ -211,10 +205,7 @@ impl<'a, T> Iterator for PerOriginIterMut<'a, T> where T: 'a {
type Item = (&'a mut T, Origin); type Item = (&'a mut T, Origin);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let origin = match Origin::from_index(self.cur) { let origin = Origin::from_index(self.cur)?;
Some(origin) => origin,
None => return None,
};
self.cur += 1; self.cur += 1;

View file

@ -196,11 +196,7 @@ impl<'a> Iterator for DocumentCascadeDataIter<'a> {
type Item = (&'a CascadeData, Origin); type Item = (&'a CascadeData, Origin);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let (_, origin) = match self.iter.next() { let (_, origin) = self.iter.next()?;
Some(o) => o,
None => return None,
};
Some((self.cascade_data.borrow_for_origin(origin), origin)) Some((self.cascade_data.borrow_for_origin(origin), origin))
} }
} }
@ -670,7 +666,7 @@ impl Stylist {
parent, parent,
cascade_flags, cascade_flags,
font_metrics, font_metrics,
&rule_node rule_node
) )
} }
@ -683,37 +679,19 @@ impl Stylist {
parent: Option<&ComputedValues>, parent: Option<&ComputedValues>,
cascade_flags: CascadeFlags, cascade_flags: CascadeFlags,
font_metrics: &FontMetricsProvider, font_metrics: &FontMetricsProvider,
rule_node: &StrongRuleNode rule_node: StrongRuleNode
) -> Arc<ComputedValues> { ) -> Arc<ComputedValues> {
// NOTE(emilio): We skip calculating the proper layout parent style self.compute_pseudo_element_style_with_inputs(
// here. &CascadeInputs {
// rules: Some(rule_node),
// It'd be fine to assert that this isn't called with a parent style visited_rules: None,
// where display contents is in effect, but in practice this is hard to },
// do for stuff like :-moz-fieldset-content with a pseudo,
// <fieldset style="display: contents">. That is, the computed value of
// display for the fieldset is "contents", even though it's not the used
// value, so we don't need to adjust in a different way anyway.
//
// In practice, I don't think any anonymous content can be a direct
// descendant of a display: contents element where display: contents is
// the actual used value, and the computed value of it would need
// blockification.
properties::cascade(
&self.device,
Some(pseudo),
rule_node,
guards, guards,
parent, parent,
parent,
parent,
None,
font_metrics, font_metrics,
cascade_flags, cascade_flags,
self.quirks_mode, ).unwrap()
/* rule_cache = */ None,
&mut Default::default(),
)
} }
/// Returns the rule node for given precomputed pseudo-element. /// Returns the rule node for given precomputed pseudo-element.
@ -839,8 +817,9 @@ impl Stylist {
&cascade_inputs, &cascade_inputs,
pseudo, pseudo,
guards, guards,
parent_style, Some(parent_style),
font_metrics, font_metrics,
CascadeFlags::empty(),
) )
} }
@ -853,8 +832,9 @@ impl Stylist {
inputs: &CascadeInputs, inputs: &CascadeInputs,
pseudo: &PseudoElement, pseudo: &PseudoElement,
guards: &StylesheetGuards, guards: &StylesheetGuards,
parent_style: &ComputedValues, parent_style: Option<&ComputedValues>,
font_metrics: &FontMetricsProvider font_metrics: &FontMetricsProvider,
cascade_flags: CascadeFlags,
) -> Option<Arc<ComputedValues>> { ) -> Option<Arc<ComputedValues>> {
// We may have only visited rules in cases when we are actually // We may have only visited rules in cases when we are actually
// resolving, not probing, pseudo-element style. // resolving, not probing, pseudo-element style.
@ -867,6 +847,13 @@ impl Stylist {
// pseudos other than before and after, so it's probably ok. // pseudos other than before and after, so it's probably ok.
// //
// (Though the flags don't indicate so!) // (Though the flags don't indicate so!)
//
// It'd be fine to assert that this isn't called with a parent style
// where display contents is in effect, but in practice this is hard to
// do for stuff like :-moz-fieldset-content with a
// <fieldset style="display: contents">. That is, the computed value of
// display for the fieldset is "contents", even though it's not the used
// value, so we don't need to adjust in a different way anyway.
Some(self.compute_style_with_inputs( Some(self.compute_style_with_inputs(
inputs, inputs,
Some(pseudo), Some(pseudo),
@ -875,7 +862,7 @@ impl Stylist {
parent_style, parent_style,
parent_style, parent_style,
font_metrics, font_metrics,
CascadeFlags::empty(), cascade_flags,
)) ))
} }
@ -899,15 +886,18 @@ impl Stylist {
inputs: &CascadeInputs, inputs: &CascadeInputs,
pseudo: Option<&PseudoElement>, pseudo: Option<&PseudoElement>,
guards: &StylesheetGuards, guards: &StylesheetGuards,
parent_style: &ComputedValues, parent_style: Option<&ComputedValues>,
parent_style_ignoring_first_line: &ComputedValues, parent_style_ignoring_first_line: Option<&ComputedValues>,
layout_parent_style: &ComputedValues, layout_parent_style: Option<&ComputedValues>,
font_metrics: &FontMetricsProvider, font_metrics: &FontMetricsProvider,
cascade_flags: CascadeFlags cascade_flags: CascadeFlags
) -> Arc<ComputedValues> { ) -> Arc<ComputedValues> {
// We need to compute visited values if we have visited rules or if our // We need to compute visited values if we have visited rules or if our
// parent has visited values. // parent has visited values.
let visited_values = if inputs.visited_rules.is_some() || parent_style.visited_style().is_some() { let mut visited_values = None;
if inputs.visited_rules.is_some() ||
parent_style.and_then(|s| s.visited_style()).is_some()
{
// At this point inputs may have visited rules, or rules, or both, // At this point inputs may have visited rules, or rules, or both,
// or neither (e.g. if it's a text style it may have neither). So // or neither (e.g. if it's a text style it may have neither). So
// we have to be a bit careful here. // we have to be a bit careful here.
@ -927,31 +917,35 @@ impl Stylist {
// We want to use the visited bits (if any) from our parent // We want to use the visited bits (if any) from our parent
// style as our parent. // style as our parent.
inherited_style = inherited_style =
parent_style.visited_style().unwrap_or(parent_style); parent_style.map(|parent_style| {
parent_style.visited_style().unwrap_or(parent_style)
});
inherited_style_ignoring_first_line = inherited_style_ignoring_first_line =
parent_style_ignoring_first_line.visited_style().unwrap_or(parent_style_ignoring_first_line); parent_style_ignoring_first_line.map(|parent_style| {
parent_style.visited_style().unwrap_or(parent_style)
});
layout_parent_style_for_visited = layout_parent_style_for_visited =
layout_parent_style.visited_style().unwrap_or(layout_parent_style); layout_parent_style.map(|parent_style| {
parent_style.visited_style().unwrap_or(parent_style)
});
} }
Some(properties::cascade( visited_values = Some(properties::cascade(
&self.device, &self.device,
pseudo, pseudo,
rule_node, rule_node,
guards, guards,
Some(inherited_style), inherited_style,
Some(inherited_style_ignoring_first_line), inherited_style_ignoring_first_line,
Some(layout_parent_style_for_visited), layout_parent_style_for_visited,
None, None,
font_metrics, font_metrics,
cascade_flags | CascadeFlags::VISITED_DEPENDENT_ONLY, cascade_flags | CascadeFlags::VISITED_DEPENDENT_ONLY,
self.quirks_mode, self.quirks_mode,
/* rule_cache = */ None, /* rule_cache = */ None,
&mut Default::default(), &mut Default::default(),
)) ));
} else { }
None
};
// We may not have non-visited rules, if we only had visited ones. In // We may not have non-visited rules, if we only had visited ones. In
// that case we want to use the root rulenode for our non-visited rules. // that case we want to use the root rulenode for our non-visited rules.
@ -966,9 +960,9 @@ impl Stylist {
pseudo, pseudo,
rules, rules,
guards, guards,
Some(parent_style), parent_style,
Some(parent_style_ignoring_first_line), parent_style_ignoring_first_line,
Some(layout_parent_style), layout_parent_style,
visited_values, visited_values,
font_metrics, font_metrics,
cascade_flags, cascade_flags,
@ -1232,7 +1226,10 @@ impl Stylist {
debug!("Determining if style is shareable: pseudo: {}", debug!("Determining if style is shareable: pseudo: {}",
pseudo_element.is_some()); pseudo_element.is_some());
let only_default_rules = rule_inclusion == RuleInclusion::DefaultOnly; let only_default_rules =
rule_inclusion == RuleInclusion::DefaultOnly;
let matches_user_and_author_rules =
rule_hash_target.matches_user_and_author_rules();
// Step 1: Normal user-agent rules. // Step 1: Normal user-agent rules.
if let Some(map) = self.cascade_data.user_agent.cascade_data.borrow_for_pseudo(pseudo_element) { if let Some(map) = self.cascade_data.user_agent.cascade_data.borrow_for_pseudo(pseudo_element) {
@ -1271,7 +1268,7 @@ impl Stylist {
// rule_hash_target.matches_user_and_author_rules()) // rule_hash_target.matches_user_and_author_rules())
// //
// Which may be more what you would probably expect. // Which may be more what you would probably expect.
if rule_hash_target.matches_user_and_author_rules() { if matches_user_and_author_rules {
// Step 3a: User normal rules. // Step 3a: User normal rules.
if let Some(map) = self.cascade_data.user.borrow_for_pseudo(pseudo_element) { if let Some(map) = self.cascade_data.user.borrow_for_pseudo(pseudo_element) {
map.get_all_matching_rules( map.get_all_matching_rules(
@ -1315,24 +1312,20 @@ impl Stylist {
} }
}); });
if rule_hash_target.matches_user_and_author_rules() && !only_default_rules { if matches_user_and_author_rules && !only_default_rules &&
// Gecko skips author normal rules if cutting off inheritance. !cut_off_inheritance
// See nsStyleSet::FileRules(). {
if !cut_off_inheritance { // Step 3c: Author normal rules.
// Step 3c: Author normal rules. if let Some(map) = self.cascade_data.author.borrow_for_pseudo(pseudo_element) {
if let Some(map) = self.cascade_data.author.borrow_for_pseudo(pseudo_element) { map.get_all_matching_rules(
map.get_all_matching_rules( element,
element, &rule_hash_target,
&rule_hash_target, applicable_declarations,
applicable_declarations, context,
context, self.quirks_mode,
self.quirks_mode, flags_setter,
flags_setter, CascadeLevel::AuthorNormal
CascadeLevel::AuthorNormal );
);
}
} else {
debug!("skipping author normal rules due to cut off inheritance");
} }
} else { } else {
debug!("skipping author normal rules"); debug!("skipping author normal rules");

View file

@ -48,15 +48,15 @@ pub trait Animate: Sized {
/// An animation procedure. /// An animation procedure.
/// ///
/// <https://w3c.github.io/web-animations/#procedures-for-animating-properties> /// <https://drafts.csswg.org/web-animations/#procedures-for-animating-properties>
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum Procedure { pub enum Procedure {
/// <https://w3c.github.io/web-animations/#animation-interpolation> /// <https://drafts.csswg.org/web-animations/#animation-interpolation>
Interpolate { progress: f64 }, Interpolate { progress: f64 },
/// <https://w3c.github.io/web-animations/#animation-addition> /// <https://drafts.csswg.org/web-animations/#animation-addition>
Add, Add,
/// <https://w3c.github.io/web-animations/#animation-accumulation> /// <https://drafts.csswg.org/web-animations/#animation-accumulation>
Accumulate { count: u64 }, Accumulate { count: u64 },
} }

View file

@ -9,7 +9,8 @@ use values::computed::length::LengthOrPercentage;
use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
use values::generics::box_::VerticalAlign as GenericVerticalAlign; use values::generics::box_::VerticalAlign as GenericVerticalAlign;
pub use values::specified::box_::{AnimationName, OverflowClipBox, OverscrollBehavior, ScrollSnapType}; pub use values::specified::box_::{AnimationName, OverflowClipBox, OverscrollBehavior};
pub use values::specified::box_::{ScrollSnapType, WillChange};
/// A computed value for the `vertical-align` property. /// A computed value for the `vertical-align` property.
pub type VerticalAlign = GenericVerticalAlign<LengthOrPercentage>; pub type VerticalAlign = GenericVerticalAlign<LengthOrPercentage>;

View file

@ -0,0 +1,26 @@
/* 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/. */
//! `list` computed values.
pub use values::specified::list::{ListStyleImage, Quotes};
impl Quotes {
/// Initial value for `quotes`.
///
/// FIXME(emilio): This should ideally not allocate.
#[inline]
pub fn get_initial_value() -> Quotes {
Quotes(vec![
(
"\u{201c}".to_owned().into_boxed_str(),
"\u{201d}".to_owned().into_boxed_str(),
),
(
"\u{2018}".to_owned().into_boxed_str(),
"\u{2019}".to_owned().into_boxed_str(),
),
].into_boxed_slice())
}
}

View file

@ -41,7 +41,7 @@ pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, Font
pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings}; pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings};
pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang}; pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang};
pub use self::box_::{AnimationIterationCount, AnimationName, OverscrollBehavior}; pub use self::box_::{AnimationIterationCount, AnimationName, OverscrollBehavior};
pub use self::box_::{OverflowClipBox, ScrollSnapType, VerticalAlign}; pub use self::box_::{OverflowClipBox, ScrollSnapType, VerticalAlign, WillChange};
pub use self::color::{Color, ColorPropertyValue, RGBAColor}; pub use self::color::{Color, ColorPropertyValue, RGBAColor};
pub use self::effects::{BoxShadow, Filter, SimpleShadow}; pub use self::effects::{BoxShadow, Filter, SimpleShadow};
pub use self::flex::FlexBasis; pub use self::flex::FlexBasis;
@ -54,6 +54,8 @@ pub use super::specified::{BorderStyle, TextDecorationLine};
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage}; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage};
pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength}; pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength};
pub use self::length::{CSSPixelLength, NonNegativeLength, NonNegativeLengthOrPercentage}; pub use self::length::{CSSPixelLength, NonNegativeLength, NonNegativeLengthOrPercentage};
pub use self::list::{ListStyleImage, Quotes};
pub use self::outline::OutlineStyle;
pub use self::percentage::Percentage; pub use self::percentage::Percentage;
pub use self::position::{Position, GridAutoFlow, GridTemplateAreas}; pub use self::position::{Position, GridAutoFlow, GridTemplateAreas};
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth}; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth};
@ -79,6 +81,8 @@ pub mod image;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub mod gecko; pub mod gecko;
pub mod length; pub mod length;
pub mod list;
pub mod outline;
pub mod percentage; pub mod percentage;
pub mod position; pub mod position;
pub mod rect; pub mod rect;
@ -397,6 +401,7 @@ trivial_to_computed_value!(BorderStyle);
trivial_to_computed_value!(Cursor); trivial_to_computed_value!(Cursor);
trivial_to_computed_value!(Namespace); trivial_to_computed_value!(Namespace);
trivial_to_computed_value!(String); trivial_to_computed_value!(String);
trivial_to_computed_value!(Box<str>);
/// A `<number>` value. /// A `<number>` value.
pub type Number = CSSFloat; pub type Number = CSSFloat;

View file

@ -0,0 +1,7 @@
/* 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/. */
//! Computed values for outline properties
pub use values::specified::OutlineStyle;

View file

@ -59,12 +59,16 @@ where
} }
if let Some(ref i) = self.line_num { if let Some(ref i) = self.line_num {
dest.write_str(" ")?; if self.is_span {
dest.write_str(" ")?;
}
i.to_css(dest)?; i.to_css(dest)?;
} }
if let Some(ref s) = self.ident { if let Some(ref s) = self.ident {
dest.write_str(" ")?; if self.is_span || self.line_num.is_some() {
dest.write_str(" ")?;
}
s.to_css(dest)?; s.to_css(dest)?;
} }

View file

@ -46,11 +46,13 @@ impl BackgroundSize {
} }
/// One of the keywords for `background-repeat`. /// One of the keywords for `background-repeat`.
define_css_keyword_enum! { RepeatKeyword: #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
"repeat" => Repeat, #[allow(missing_docs)]
"space" => Space, pub enum RepeatKeyword {
"round" => Round, Repeat,
"no-repeat" => NoRepeat Space,
Round,
NoRepeat,
} }
/// The specified value for the `background-repeat` property. /// The specified value for the `background-repeat` property.

View file

@ -9,6 +9,7 @@ use cssparser::Parser;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use std::fmt; use std::fmt;
use style_traits::{ParseError, ToCss}; use style_traits::{ParseError, ToCss};
use values::CustomIdent;
use values::KeyframesName; use values::KeyframesName;
use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
use values::generics::box_::VerticalAlign as GenericVerticalAlign; use values::generics::box_::VerticalAlign as GenericVerticalAlign;
@ -130,3 +131,49 @@ define_css_keyword_enum! { OverflowClipBox:
"content-box" => ContentBox, "content-box" => ContentBox,
} }
add_impls_for_keyword_enum!(OverflowClipBox); add_impls_for_keyword_enum!(OverflowClipBox);
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
/// Provides a rendering hint to the user agent,
/// stating what kinds of changes the author expects
/// to perform on the element
///
/// <https://drafts.csswg.org/css-will-change/#will-change>
pub enum WillChange {
/// Expresses no particular intent
Auto,
#[css(comma, iterable)]
/// <custom-ident>
AnimateableFeatures(Box<[CustomIdent]>),
}
impl WillChange {
#[inline]
/// Get default value of `will-change` as `auto`
pub fn auto() -> WillChange {
WillChange::Auto
}
}
impl Parse for WillChange {
/// auto | <animateable-feature>#
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>
) -> Result<WillChange, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
return Ok(WillChange::Auto);
}
let custom_idents = input.parse_comma_separated(|i| {
let location = i.current_source_location();
CustomIdent::from_ident(location, i.expect_ident()?, &[
"will-change",
"none",
"all",
"auto",
])
})?;
Ok(WillChange::AnimateableFeatures(custom_idents.into_boxed_slice()))
}
}

View file

@ -0,0 +1,106 @@
/* 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/. */
//! `list` specified values.
use cssparser::{Parser, Token};
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::{ParseError, StyleParseErrorKind, ToCss};
use values::{Either, None_};
use values::specified::UrlOrNone;
/// Specified and computed `list-style-image` property.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
pub struct ListStyleImage(pub UrlOrNone);
// FIXME(nox): This is wrong, there are different types for specified
// and computed URLs in Servo.
trivial_to_computed_value!(ListStyleImage);
impl ListStyleImage {
/// Initial specified value for `list-style-image`.
#[inline]
pub fn none() -> ListStyleImage {
ListStyleImage(Either::Second(None_))
}
}
impl Parse for ListStyleImage {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<ListStyleImage, ParseError<'i>> {
#[allow(unused_mut)]
let mut value = input.try(|input| UrlOrNone::parse(context, input))?;
#[cfg(feature = "gecko")]
{
if let Either::First(ref mut url) = value {
url.build_image_value();
}
}
return Ok(ListStyleImage(value));
}
}
/// Specified and computed `quote` property.
///
/// FIXME(emilio): It's a shame that this allocates all the time it's computed,
/// probably should just be refcounted.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
pub struct Quotes(pub Box<[(Box<str>, Box<str>)]>);
impl ToCss for Quotes {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
let mut iter = self.0.iter();
match iter.next() {
Some(&(ref l, ref r)) => {
l.to_css(dest)?;
dest.write_char(' ')?;
r.to_css(dest)?;
}
None => return dest.write_str("none"),
}
for &(ref l, ref r) in iter {
dest.write_char(' ')?;
l.to_css(dest)?;
dest.write_char(' ')?;
r.to_css(dest)?;
}
Ok(())
}
}
impl Parse for Quotes {
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Quotes, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(Quotes(Vec::new().into_boxed_slice()))
}
let mut quotes = Vec::new();
loop {
let location = input.current_source_location();
let first = match input.next() {
Ok(&Token::QuotedString(ref value)) => {
value.as_ref().to_owned().into_boxed_str()
},
Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
Err(_) => break,
};
let second =
input.expect_string()?.as_ref().to_owned().into_boxed_str();
quotes.push((first, second))
}
if !quotes.is_empty() {
Ok(Quotes(quotes.into_boxed_slice()))
} else {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
}

View file

@ -35,7 +35,7 @@ pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, Font
pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings}; pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings};
pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang}; pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang};
pub use self::box_::{AnimationIterationCount, AnimationName, OverscrollBehavior}; pub use self::box_::{AnimationIterationCount, AnimationName, OverscrollBehavior};
pub use self::box_::{OverflowClipBox, ScrollSnapType, VerticalAlign}; pub use self::box_::{OverflowClipBox, ScrollSnapType, VerticalAlign, WillChange};
pub use self::color::{Color, ColorPropertyValue, RGBAColor}; pub use self::color::{Color, ColorPropertyValue, RGBAColor};
pub use self::effects::{BoxShadow, Filter, SimpleShadow}; pub use self::effects::{BoxShadow, Filter, SimpleShadow};
pub use self::flex::FlexBasis; pub use self::flex::FlexBasis;
@ -49,6 +49,8 @@ pub use self::length::{LengthOrPercentage, LengthOrPercentageOrAuto};
pub use self::length::{LengthOrPercentageOrNone, MaxLength, MozLength}; pub use self::length::{LengthOrPercentageOrNone, MaxLength, MozLength};
pub use self::length::{NoCalcLength, ViewportPercentageLength}; pub use self::length::{NoCalcLength, ViewportPercentageLength};
pub use self::length::NonNegativeLengthOrPercentage; pub use self::length::NonNegativeLengthOrPercentage;
pub use self::list::{ListStyleImage, Quotes};
pub use self::outline::OutlineStyle;
pub use self::rect::LengthOrNumberRect; pub use self::rect::LengthOrNumberRect;
pub use self::percentage::Percentage; pub use self::percentage::Percentage;
pub use self::position::{Position, PositionComponent, GridAutoFlow, GridTemplateAreas}; pub use self::position::{Position, PositionComponent, GridAutoFlow, GridTemplateAreas};
@ -78,6 +80,8 @@ pub mod gecko;
pub mod grid; pub mod grid;
pub mod image; pub mod image;
pub mod length; pub mod length;
pub mod list;
pub mod outline;
pub mod percentage; pub mod percentage;
pub mod position; pub mod position;
pub mod rect; pub mod rect;

View file

@ -0,0 +1,56 @@
/* 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/. */
//! Specified values for outline properties
use cssparser::Parser;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseErrorKind;
use style_traits::ParseError;
use values::specified::BorderStyle;
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord)]
#[derive(PartialEq, PartialOrd, ToComputedValue, ToCss)]
/// <https://drafts.csswg.org/css-ui/#propdef-outline-style>
pub enum OutlineStyle {
/// auto
Auto,
/// <border-style>
Other(BorderStyle),
}
impl OutlineStyle {
#[inline]
/// Get default value as None
pub fn none() -> OutlineStyle {
OutlineStyle::Other(BorderStyle::None)
}
#[inline]
/// Get value for None or Hidden
pub fn none_or_hidden(&self) -> bool {
match *self {
OutlineStyle::Auto => false,
OutlineStyle::Other(ref border_style) => border_style.none_or_hidden()
}
}
}
impl Parse for OutlineStyle {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>
) -> Result<OutlineStyle, ParseError<'i>> {
if let Ok(border_style) = input.try(|i| BorderStyle::parse(context, i)) {
if let BorderStyle::Hidden = border_style {
return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent("hidden".into())));
}
return Ok(OutlineStyle::Other(border_style));
}
input.expect_ident_matching("auto")?;
Ok(OutlineStyle::Auto)
}
}

View file

@ -42,17 +42,21 @@ pub enum PositionComponent<S> {
Side(S, Option<LengthOrPercentage>), Side(S, Option<LengthOrPercentage>),
} }
define_css_keyword_enum! { X: /// A keyword for the X direction.
"left" => Left, #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
"right" => Right, #[allow(missing_docs)]
pub enum X {
Left,
Right,
} }
add_impls_for_keyword_enum!(X);
define_css_keyword_enum! { Y: /// A keyword for the Y direction.
"top" => Top, #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
"bottom" => Bottom, #[allow(missing_docs)]
pub enum Y {
Top,
Bottom,
} }
add_impls_for_keyword_enum!(Y);
impl Parse for Position { impl Parse for Position {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {

View file

@ -406,3 +406,41 @@ pub fn where_predicate(
)], )],
}) })
} }
/// Transforms "FooBar" to "foo-bar".
///
/// If the first Camel segment is "Moz", "Webkit", or "Servo", the result string
/// is prepended with "-".
pub fn to_css_identifier(mut camel_case: &str) -> String {
camel_case = camel_case.trim_right_matches('_');
let mut first = true;
let mut result = String::with_capacity(camel_case.len());
while let Some(segment) = split_camel_segment(&mut camel_case) {
if first {
match segment {
"Moz" | "Webkit" | "Servo" => first = false,
_ => {},
}
}
if !first {
result.push_str("-");
}
first = false;
result.push_str(&segment.to_lowercase());
}
result
}
/// Given "FooBar", returns "Foo" and sets `camel_case` to "Bar".
fn split_camel_segment<'input>(camel_case: &mut &'input str) -> Option<&'input str> {
let index = match camel_case.chars().next() {
None => return None,
Some(ch) => ch.len_utf8(),
};
let end_position = camel_case[index..]
.find(char::is_uppercase)
.map_or(camel_case.len(), |pos| index + pos);
let result = &camel_case[..end_position];
*camel_case = &camel_case[end_position..];
Some(result)
}

View file

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![recursion_limit = "128"]
#[macro_use] extern crate darling; #[macro_use] extern crate darling;
extern crate proc_macro; extern crate proc_macro;
#[macro_use] extern crate quote; #[macro_use] extern crate quote;
@ -13,6 +15,7 @@ use proc_macro::TokenStream;
mod animate; mod animate;
mod cg; mod cg;
mod compute_squared_distance; mod compute_squared_distance;
mod parse;
mod to_animated_value; mod to_animated_value;
mod to_animated_zero; mod to_animated_zero;
mod to_computed_value; mod to_computed_value;
@ -36,6 +39,12 @@ pub fn derive_to_animated_value(stream: TokenStream) -> TokenStream {
to_animated_value::derive(input).to_string().parse().unwrap() to_animated_value::derive(input).to_string().parse().unwrap()
} }
#[proc_macro_derive(Parse)]
pub fn derive_parse(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
parse::derive(input).to_string().parse().unwrap()
}
#[proc_macro_derive(ToAnimatedZero, attributes(animation))] #[proc_macro_derive(ToAnimatedZero, attributes(animation))]
pub fn derive_to_animated_zero(stream: TokenStream) -> TokenStream { pub fn derive_to_animated_zero(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap(); let input = syn::parse_derive_input(&stream.to_string()).unwrap();

View file

@ -0,0 +1,74 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cg;
use quote::Tokens;
use syn::DeriveInput;
use synstructure;
pub fn derive(input: DeriveInput) -> Tokens {
let name = &input.ident;
let mut match_body = quote! {};
let style = synstructure::BindStyle::Ref.into();
synstructure::each_variant(&input, &style, |bindings, variant| {
assert!(
bindings.is_empty(),
"Parse is only supported for single-variant enums for now"
);
let identifier = cg::to_css_identifier(variant.ident.as_ref());
match_body = quote! {
#match_body
#identifier => Ok(#name::#variant),
}
});
let parse_trait_impl = quote! {
impl ::parser::Parse for #name {
#[inline]
fn parse<'i, 't>(
_: &::parser::ParserContext,
input: &mut ::cssparser::Parser<'i, 't>,
) -> Result<Self, ::style_traits::ParseError<'i>> {
Self::parse(input)
}
}
};
// TODO(emilio): It'd be nice to get rid of these, but that makes the
// conversion harder...
let methods_impl = quote! {
impl #name {
/// Parse this keyword.
#[inline]
pub fn parse<'i, 't>(
input: &mut ::cssparser::Parser<'i, 't>,
) -> Result<Self, ::style_traits::ParseError<'i>> {
let location = input.current_source_location();
let ident = input.expect_ident()?;
Self::from_ident(ident.as_ref()).map_err(|()| {
location.new_unexpected_token_error(
::cssparser::Token::Ident(ident.clone())
)
})
}
/// Parse this keyword from a string slice.
#[inline]
pub fn from_ident(ident: &str) -> Result<Self, ()> {
match_ignore_ascii_case! { ident,
#match_body
_ => Err(()),
}
}
}
};
quote! {
#parse_trait_impl
#methods_impl
}
}

View file

@ -16,7 +16,7 @@ pub fn derive(input: DeriveInput) -> Tokens {
let input_attrs = cg::parse_input_attrs::<CssInputAttrs>(&input); let input_attrs = cg::parse_input_attrs::<CssInputAttrs>(&input);
let style = synstructure::BindStyle::Ref.into(); let style = synstructure::BindStyle::Ref.into();
let match_body = synstructure::each_variant(&input, &style, |bindings, variant| { let match_body = synstructure::each_variant(&input, &style, |bindings, variant| {
let mut identifier = to_css_identifier(variant.ident.as_ref()); let mut identifier = cg::to_css_identifier(variant.ident.as_ref());
let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(variant); let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(variant);
let separator = if variant_attrs.comma { ", " } else { " " }; let separator = if variant_attrs.comma { ", " } else { " " };
@ -27,7 +27,7 @@ pub fn derive(input: DeriveInput) -> Tokens {
let mut expr = if !bindings.is_empty() { let mut expr = if !bindings.is_empty() {
let mut expr = quote! {}; let mut expr = quote! {};
if variant_attrs.function && variant_attrs.iterable { if variant_attrs.iterable {
assert_eq!(bindings.len(), 1); assert_eq!(bindings.len(), 1);
let binding = &bindings[0]; let binding = &bindings[0];
expr = quote! { expr = quote! {
@ -118,41 +118,3 @@ struct CssVariantAttrs {
comma: bool, comma: bool,
dimension: bool, dimension: bool,
} }
/// Transforms "FooBar" to "foo-bar".
///
/// If the first Camel segment is "Moz" or "Webkit", the result string
/// is prepended with "-".
fn to_css_identifier(mut camel_case: &str) -> String {
camel_case = camel_case.trim_right_matches('_');
let mut first = true;
let mut result = String::with_capacity(camel_case.len());
while let Some(segment) = split_camel_segment(&mut camel_case) {
if first {
match segment {
"Moz" | "Webkit" => first = false,
_ => {},
}
}
if !first {
result.push_str("-");
}
first = false;
result.push_str(&segment.to_lowercase());
}
result
}
/// Given "FooBar", returns "Foo" and sets `camel_case` to "Bar".
fn split_camel_segment<'input>(camel_case: &mut &'input str) -> Option<&'input str> {
let index = match camel_case.chars().next() {
None => return None,
Some(ch) => ch.len_utf8(),
};
let end_position = camel_case[index..]
.find(char::is_uppercase)
.map_or(camel_case.len(), |pos| index + pos);
let result = &camel_case[..end_position];
*camel_case = &camel_case[end_position..];
Some(result)
}

Some files were not shown because too many files have changed in this diff Show more