diff --git a/.taskcluster.yml b/.taskcluster.yml new file mode 100644 index 00000000000..cc79679d05f --- /dev/null +++ b/.taskcluster.yml @@ -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 }}' + diff --git a/Cargo.lock b/Cargo.lock index c381d7b8781..95d57187cac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,11 +47,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "app_units" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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]] @@ -143,7 +143,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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]] @@ -204,7 +204,7 @@ version = "0.0.1" dependencies = [ "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)", - "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", ] @@ -287,8 +287,8 @@ dependencies = [ "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)", "servo_config 0.0.1", - "webrender 0.56.0 (git+https://github.com/servo/webrender)", - "webrender_api 0.56.0 (git+https://github.com/servo/webrender)", + "webrender 0.56.1 (git+https://github.com/servo/webrender)", + "webrender_api 0.56.1 (git+https://github.com/servo/webrender)", ] [[package]] @@ -303,9 +303,9 @@ dependencies = [ "malloc_size_of_derive 0.0.1", "nonzero 0.0.1", "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", - "webrender_api 0.56.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.56.1 (git+https://github.com/servo/webrender)", ] [[package]] @@ -324,7 +324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "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)", "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)", @@ -358,6 +358,15 @@ dependencies = [ "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]] name = "clang-sys" version = "0.21.1" @@ -459,8 +468,8 @@ dependencies = [ "servo_url 0.0.1", "style_traits 0.0.1", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.56.0 (git+https://github.com/servo/webrender)", - "webrender_api 0.56.0 (git+https://github.com/servo/webrender)", + "webrender 0.56.1 (git+https://github.com/servo/webrender)", + "webrender_api 0.56.1 (git+https://github.com/servo/webrender)", ] [[package]] @@ -491,13 +500,13 @@ dependencies = [ "net_traits 0.0.1", "profile_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_rand 0.0.1", "servo_remutex 0.0.1", "servo_url 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", ] @@ -560,7 +569,7 @@ dependencies = [ "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)", "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)", "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)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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_derive 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", "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)", "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)", - "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 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)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -799,7 +808,7 @@ dependencies = [ "servo_geometry 0.0.1", "servo_url 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)", ] @@ -893,7 +902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "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]] @@ -1049,7 +1058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "gfx" version = "0.0.1" 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)", "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)", @@ -1072,7 +1081,7 @@ dependencies = [ "net_traits 0.0.1", "ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "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_allocator 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)", "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)", - "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)", "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_derive 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]] @@ -1168,7 +1177,7 @@ dependencies = [ "servo_url 0.0.1", "style_traits 0.0.1", "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)", "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)", "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)", - "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)", "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)", "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)", - "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)", ] @@ -1454,7 +1463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "layout" version = "0.0.1" 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)", "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "canvas_traits 0.0.1", @@ -1477,7 +1486,7 @@ dependencies = [ "script_layout_interface 0.0.1", "script_traits 0.0.1", "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)", "servo_arc 0.0.1", "servo_atoms 0.0.1", @@ -1489,7 +1498,7 @@ dependencies = [ "style_traits 0.0.1", "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)", - "webrender_api 0.56.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.56.1 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1504,7 +1513,7 @@ dependencies = [ name = "layout_thread" version = "0.0.1" 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)", "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)", @@ -1539,7 +1548,7 @@ dependencies = [ "servo_url 0.0.1", "style 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]] @@ -1554,7 +1563,7 @@ dependencies = [ "profile_traits 0.0.1", "script_traits 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]] @@ -1635,8 +1644,8 @@ dependencies = [ "style 0.0.1", "style_traits 0.0.1", "webdriver_server 0.0.1", - "webrender 0.56.0 (git+https://github.com/servo/webrender)", - "webrender_api 0.56.0 (git+https://github.com/servo/webrender)", + "webrender 0.56.1 (git+https://github.com/servo/webrender)", + "webrender_api 0.56.1 (git+https://github.com/servo/webrender)", "webvr 0.0.1", "webvr_traits 0.0.1", ] @@ -1679,7 +1688,7 @@ dependencies = [ name = "malloc_size_of" version = "0.0.1" 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)", "euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashglobe 0.1.0", @@ -1689,7 +1698,7 @@ dependencies = [ "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)", "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)", ] @@ -1717,8 +1726,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 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)", "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_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_derive 0.0.1", "nonzero 0.0.1", - "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.56.0 (git+https://github.com/servo/webrender)", + "serde 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)", + "webrender_api 0.56.1 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1942,7 +1951,7 @@ dependencies = [ "net_traits 0.0.1", "openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "servo-websocket 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "servo_config 0.0.1", @@ -1953,7 +1962,7 @@ dependencies = [ "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)", "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]] @@ -2005,12 +2014,12 @@ dependencies = [ "malloc_size_of_derive 0.0.1", "msg 0.0.1", "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_url 0.0.1", "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)", - "webrender_api 0.56.0 (git+https://github.com/servo/webrender)", + "webrender_api 0.56.1 (git+https://github.com/servo/webrender)", ] [[package]] @@ -2034,7 +2043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "nonzero" version = "0.0.1" 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]] @@ -2044,6 +2053,16 @@ dependencies = [ "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]] name = "num-integer" version = "0.1.34" @@ -2126,7 +2145,7 @@ dependencies = [ "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)", "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)", "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)", @@ -2327,7 +2346,7 @@ dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "profile_traits 0.0.1", "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)", "servo_config 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)", "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)", - "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", "signpost 0.1.0 (git+https://github.com/pcwalton/signpost.git)", "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_derive 0.0.1", "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]] @@ -2478,8 +2497,8 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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_derive 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)", ] @@ -2530,7 +2549,7 @@ name = "script" version = "0.0.1" dependencies = [ "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)", "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)", @@ -2538,6 +2557,7 @@ dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "canvas_traits 0.0.1", "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)", "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)", @@ -2585,7 +2605,7 @@ dependencies = [ "script_plugins 0.0.1", "script_traits 0.0.1", "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)", "servo_allocator 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)", "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)", - "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", "xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2613,7 +2633,7 @@ dependencies = [ name = "script_layout_interface" version = "0.0.1" 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)", "canvas_traits 0.0.1", "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2637,7 +2657,7 @@ dependencies = [ "servo_atoms 0.0.1", "servo_url 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]] @@ -2682,13 +2702,13 @@ dependencies = [ "net_traits 0.0.1", "profile_traits 0.0.1", "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_url 0.0.1", "style_traits 0.0.1", "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)", - "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", ] @@ -2731,10 +2751,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "1.0.23" +source = "git+https://github.com/gankro/serde?branch=deserialize_from_enums3#fc6117367ef974fb2d3b2017c21c375d34823415" 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]] @@ -2742,23 +2762,23 @@ name = "serde_bytes" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "serde_derive" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "1.0.23" +source = "git+https://github.com/gankro/serde?branch=deserialize_from_enums3#fc6117367ef974fb2d3b2017c21c375d34823415" dependencies = [ "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)", ] [[package]] name = "serde_derive_internals" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.17.0" +source = "git+https://github.com/gankro/serde?branch=deserialize_from_enums3#fc6117367ef974fb2d3b2017c21c375d34823415" dependencies = [ "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)", @@ -2772,7 +2792,7 @@ dependencies = [ "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)", "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]] @@ -2900,7 +2920,7 @@ name = "servo_arc" version = "0.0.1" dependencies = [ "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)", ] @@ -2924,7 +2944,7 @@ dependencies = [ "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)", "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_url 0.0.1", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2942,7 +2962,7 @@ dependencies = [ name = "servo_geometry" version = "0.0.1" 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)", "malloc_size_of 0.0.1", "malloc_size_of_derive 0.0.1", @@ -2979,7 +2999,7 @@ version = "0.0.1" dependencies = [ "malloc_size_of 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", "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)", @@ -3062,7 +3082,7 @@ dependencies = [ "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)", "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_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" version = "0.0.1" 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)", "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)", @@ -3125,7 +3145,7 @@ dependencies = [ "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)", "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_atoms 0.0.1", "servo_config 0.0.1", @@ -3156,7 +3176,7 @@ dependencies = [ name = "style_tests" version = "0.0.1" 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)", "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)", @@ -3178,17 +3198,17 @@ dependencies = [ name = "style_traits" version = "0.0.1" 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)", "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)", "malloc_size_of 0.0.1", "malloc_size_of_derive 0.0.1", "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_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]] @@ -3344,7 +3364,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] @@ -3392,8 +3412,8 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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_derive 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)", ] [[package]] @@ -3447,7 +3467,7 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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)", ] @@ -3479,7 +3499,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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]] @@ -3546,10 +3566,10 @@ dependencies = [ [[package]] name = "webrender" -version = "0.56.0" -source = "git+https://github.com/servo/webrender#0e80c9d04f84fd02de94bb61c5a5b4b5d16d94b5" +version = "0.56.1" +source = "git+https://github.com/servo/webrender#67f7e0edeabba6861250922d47f8c6a1b2232d4b" 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)", "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)", @@ -3569,15 +3589,15 @@ dependencies = [ "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)", "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]] name = "webrender_api" -version = "0.56.0" -source = "git+https://github.com/servo/webrender#0e80c9d04f84fd02de94bb61c5a5b4b5d16d94b5" +version = "0.56.1" +source = "git+https://github.com/servo/webrender#67f7e0edeabba6861250922d47f8c6a1b2232d4b" 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)", "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)", @@ -3586,7 +3606,8 @@ dependencies = [ "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)", "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)", ] @@ -3612,7 +3633,7 @@ dependencies = [ "ipc-channel 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "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]] @@ -3732,7 +3753,7 @@ dependencies = [ "checksum angle 0.5.0 (git+https://github.com/servo/angle?branch=servo)" = "" "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 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 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" @@ -3763,6 +3784,7 @@ dependencies = [ "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 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 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" @@ -3882,6 +3904,7 @@ dependencies = [ "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 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-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" @@ -3938,10 +3961,10 @@ dependencies = [ "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-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)" = "" "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_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" +"checksum serde_derive 1.0.23 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)" = "" +"checksum serde_derive_internals 0.17.0 (git+https://github.com/gankro/serde?branch=deserialize_from_enums3)" = "" "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-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 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 webrender 0.56.0 (git+https://github.com/servo/webrender)" = "" -"checksum webrender_api 0.56.0 (git+https://github.com/servo/webrender)" = "" +"checksum webrender 0.56.1 (git+https://github.com/servo/webrender)" = "" +"checksum webrender_api 0.56.1 (git+https://github.com/servo/webrender)" = "" "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-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 3bde2968df8..fdcd1e9f0fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,9 @@ opt-level = 3 # lto = false [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 # crate, add that here. Use the form: # diff --git a/README.md b/README.md index 2660f44bff8..854dafc6b9a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Servo is a prototype web browser engine written in the [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 [`CONTRIBUTING.md`](CONTRIBUTING.md) and [`HACKING_QUICKSTART.md`](docs/HACKING_QUICKSTART.md) diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index 28b7fec5413..a985ac7a999 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -11,7 +11,7 @@ use azure::azure_hl::SurfacePattern; use canvas_traits::canvas::*; use cssparser::RGBA; use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D}; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::{IpcSender, IpcReceiver}; use num_traits::ToPrimitive; use std::borrow::ToOwned; use std::mem; @@ -118,9 +118,8 @@ impl<'a> CanvasPaintThread<'a> { /// communicate with it. pub fn start(size: Size2D, webrender_api_sender: webrender_api::RenderApiSender, - antialias: bool) - -> IpcSender { - let (sender, receiver) = ipc::channel::().unwrap(); + antialias: bool, + receiver: IpcReceiver) { let antialias = if antialias { AntialiasMode::Default } else { @@ -216,8 +215,6 @@ impl<'a> CanvasPaintThread<'a> { } } }).expect("Thread spawning failed"); - - sender } fn save_context_state(&mut self) { diff --git a/components/constellation/browsingcontext.rs b/components/constellation/browsingcontext.rs index 938cf5ef09a..a7d617164bc 100644 --- a/components/constellation/browsingcontext.rs +++ b/components/constellation/browsingcontext.rs @@ -167,10 +167,7 @@ impl<'a> Iterator for FullyActiveBrowsingContextsIterator<'a> { type Item = &'a BrowsingContext; fn next(&mut self) -> Option<&'a BrowsingContext> { loop { - let browsing_context_id = match self.stack.pop() { - Some(browsing_context_id) => browsing_context_id, - None => return None, - }; + let browsing_context_id = self.stack.pop()?; let browsing_context = match self.browsing_contexts.get(&browsing_context_id) { Some(browsing_context) => browsing_context, None => { @@ -212,10 +209,7 @@ impl<'a> Iterator for AllBrowsingContextsIterator<'a> { fn next(&mut self) -> Option<&'a BrowsingContext> { let pipelines = self.pipelines; loop { - let browsing_context_id = match self.stack.pop() { - Some(browsing_context_id) => browsing_context_id, - None => return None, - }; + let browsing_context_id = self.stack.pop()?; let browsing_context = match self.browsing_contexts.get(&browsing_context_id) { Some(browsing_context) => browsing_context, None => { diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index ec023e3971b..7539a4f149e 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -1235,9 +1235,9 @@ impl Constellation 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"); - self.handle_create_canvas_paint_thread_msg(&size, sender) + self.handle_create_canvas_paint_thread_msg(&size, receiver) } FromScriptMsg::NodeStatus(message) => { debug!("constellation got NodeStatus message"); @@ -2264,13 +2264,12 @@ impl Constellation fn handle_create_canvas_paint_thread_msg( &mut self, size: &Size2D, - response_sender: IpcSender>) { + receiver: IpcReceiver) { let webrender_api = self.webrender_api_sender.clone(); - let sender = CanvasPaintThread::start(*size, webrender_api, - opts::get().enable_canvas_antialiasing); - if let Err(e) = response_sender.send(sender) { - warn!("Create canvas paint thread response failed ({})", e); - } + CanvasPaintThread::start(*size, + webrender_api, + opts::get().enable_canvas_antialiasing, + receiver); } fn handle_webdriver_msg(&mut self, msg: WebDriverCommandMsg) { diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 9c8ef998fbf..98b78ef5c5d 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -720,6 +720,15 @@ pub struct GradientDisplayItem { /// Contains all gradient data. Included start, end point and color stops. 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, } /// Paints a radial gradient. @@ -745,6 +754,15 @@ pub struct RadialGradientDisplayItem { /// Contains all gradient data. 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, } /// A normal border, supporting CSS border styles. diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs index 3ecef760a15..beb8f9f4f2f 100644 --- a/components/gfx/platform/macos/font.rs +++ b/components/gfx/platform/macos/font.rs @@ -69,11 +69,7 @@ impl FontHandle { /// 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. fn find_h_kern_subtable(&self) -> Option { - let font_table = match self.table_for_tag(KERN) { - Some(table) => table, - None => return None - }; - + let font_table = self.table_for_tag(KERN)?; let mut result = CachedKernTable { font_table: font_table, pair_data_range: 0..0, diff --git a/components/gfx/text/text_run.rs b/components/gfx/text/text_run.rs index e66b6550dc3..8121140e480 100644 --- a/components/gfx/text/text_run.rs +++ b/components/gfx/text/text_run.rs @@ -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)] fn next(&mut self) -> Option> { - let glyph_run = match self.glyph_run { - None => return None, - Some(glyph_run) => glyph_run, - }; + let glyph_run = self.glyph_run?; debug_assert!(!self.range.is_empty()); let byte_start = self.range.begin(); diff --git a/components/hashglobe/src/hash_set.rs b/components/hashglobe/src/hash_set.rs index e21880453c8..320a521bc6b 100644 --- a/components/hashglobe/src/hash_set.rs +++ b/components/hashglobe/src/hash_set.rs @@ -1051,13 +1051,9 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S> fn next(&mut self) -> Option<&'a T> { loop { - match self.iter.next() { - None => return None, - Some(elt) => { - if self.other.contains(elt) { - return Some(elt); - } - } + let elt = self.iter.next()?; + 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> { loop { - match self.iter.next() { - None => return None, - Some(elt) => { - if !self.other.contains(elt) { - return Some(elt); - } - } + let elt = self.iter.next()?; + if !self.other.contains(elt) { + return Some(elt); } } } diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index a25a6705eea..60cf29ca3c2 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -10,7 +10,7 @@ name = "layout" path = "lib.rs" [dependencies] -app_units = "0.6" +app_units = "0.6.1" atomic_refcell = "0.1" bitflags = "1.0" canvas_traits = {path = "../canvas_traits"} @@ -41,7 +41,7 @@ serde_json = "1.0" servo_config = {path = "../config"} servo_url = {path = "../url"} smallvec = "0.6" -style = {path = "../style"} +style = {path = "../style", features = ["servo"]} style_traits = {path = "../style_traits"} unicode-bidi = {version = "0.3", features = ["with_serde"]} unicode-script = {version = "0.1", features = ["harfbuzz"]} diff --git a/components/layout/animation.rs b/components/layout/animation.rs index 19f621f7fdc..a3c364a7851 100644 --- a/components/layout/animation.rs +++ b/components/layout/animation.rs @@ -5,7 +5,7 @@ //! CSS transitions and animations. use context::LayoutContext; -use flow::{self, Flow}; +use flow::{Flow, GetBaseFlow}; use fnv::FnvHashMap; use gfx::display_list::OpaqueNode; 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); for kid in base.children.iter_mut() { recalc_style_for_animations(context, kid, animations) diff --git a/components/layout/block.rs b/components/layout/block.rs index 2a539031195..f615c5aa469 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -34,7 +34,7 @@ use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags use display_list_builder::StackingContextCollectionState; use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; 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_list::FlowList; 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. if block_start_margin_value != Au(0) { 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 } } @@ -744,7 +744,7 @@ impl BlockFlow { /// is also needed to handle RTL.) fn propagate_early_absolute_position_info_to_children(&mut self) { 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_mode: self.fragment.style().writing_mode, } @@ -816,19 +816,19 @@ impl BlockFlow { let thread_id = self.base.thread_id; let (mut had_floated_children, mut had_children_with_clearance) = (false, false); 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 // 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(); - flow::mut_base(kid).position.start.b = cur_b + - flow::base(kid).collapsible_margins + kid.mut_base().position.start.b = cur_b + + kid.base().collapsible_margins .block_start_margin_for_noncollapsible_context() + previous_bottom_margin } 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, thread_id, 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 // before. - flow::mut_base(kid).floats = floats.clone(); - if flow::base(kid).flags.is_float() { + kid.mut_base().floats = floats.clone(); + if kid.base().flags.is_float() { 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 float_ceiling = margin_collapse_info.current_float_ceiling(); @@ -863,7 +863,7 @@ impl BlockFlow { } kid.place_float_if_applicable(); - let kid_base = flow::mut_base(kid); + let kid_base = kid.mut_base(); floats = kid_base.floats.clone(); continue } @@ -875,8 +875,8 @@ impl BlockFlow { // 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; // this may be related, although I haven't looked into it closely.) - if flow::base(kid).flags.clears_floats() { - flow::mut_base(kid).floats = Floats::new(self.fragment.style.writing_mode) + if kid.base().flags.clears_floats() { + kid.mut_base().floats = Floats::new(self.fragment.style.writing_mode) } // Lay the child out if this was an in-order traversal. @@ -887,26 +887,26 @@ impl BlockFlow { if !had_children_with_clearance && floats.is_present() && - (flow::base(kid).flags.contains(FlowFlags::CLEARS_LEFT) || - flow::base(kid).flags.contains(FlowFlags::CLEARS_RIGHT)) { + (kid.base().flags.contains(FlowFlags::CLEARS_LEFT) || + kid.base().flags.contains(FlowFlags::CLEARS_RIGHT)) { had_children_with_clearance = true } // Handle any (possibly collapsed) top margin. let delta = margin_collapse_info.advance_block_start_margin( - &flow::base(kid).collapsible_margins, + &kid.base().collapsible_margins, !had_children_with_clearance); translate_including_floats(&mut cur_b, delta, &mut floats); // Collapse-through margins should be placed at the top edge, // 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; } // Clear past the floats that came in, if necessary. - let clearance = match (flow::base(kid).flags.contains(FlowFlags::CLEARS_LEFT), - flow::base(kid).flags.contains(FlowFlags::CLEARS_RIGHT)) { + let clearance = match (kid.base().flags.contains(FlowFlags::CLEARS_LEFT), + kid.base().flags.contains(FlowFlags::CLEARS_RIGHT)) { (false, false) => Au(0), (true, false) => floats.clearance(ClearType::Left), (false, true) => floats.clearance(ClearType::Right), @@ -915,19 +915,19 @@ impl BlockFlow { translate_including_floats(&mut cur_b, clearance, &mut floats); // 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 // 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*. 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` // function here because the child has already translated floats past its border // box. - let kid_base = flow::mut_base(kid); + let kid_base = kid.mut_base(); cur_b = cur_b + kid_base.position.size.block; // Handle any (possibly collapsed) block-end margin. @@ -1371,11 +1371,11 @@ impl BlockFlow { let mut iterator = self.base.child_iter_mut().enumerate().peekable(); 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, // 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. // 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 // 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. - 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) { ServoRestyleDamage::REFLOW_OUT_OF_FLOW } else { @@ -1418,7 +1418,7 @@ impl BlockFlow { // // TODO(#2265, pcwalton): Do this in the cascade instead. 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 // 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. self.assign_inline_sizes(layout_context); // 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); } // Assign our final-final block size. @@ -1597,7 +1597,7 @@ impl BlockFlow { } else { flags.remove(FlowFlags::CONTAINS_TEXT_OR_REPLACED_FRAGMENTS); 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); break } @@ -1615,11 +1615,11 @@ impl BlockFlow { 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); 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 } - let child_base = flow::mut_base(kid); + let child_base = kid.mut_base(); let float_kind = child_base.flags.float_kind(); 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) { // Root element margins should never be collapsed according to CSS § 8.3.1. 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( layout_context, fragmentation_context, MarginsMayCollapseFlag::MarginsMayNotCollapse) } else { debug!("assign_block_size: assigning block_size for block {:?}", - flow::base(self).debug_id()); + self.base().debug_id()); self.assign_block_size_block_base( layout_context, fragmentation_context, @@ -2060,9 +2060,9 @@ impl Flow for BlockFlow { // Process children. for kid in self.base.child_iter_mut() { - if flow::base(kid).flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) || - flow::base(kid).flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { - let kid_base = flow::mut_base(kid); + if kid.base().flags.contains(FlowFlags::INLINE_POSITION_IS_STATIC) || + kid.base().flags.contains(FlowFlags::BLOCK_POSITION_IS_STATIC) { + let kid_base = kid.mut_base(); let physical_position = kid_base.position.to_physical(kid_base.writing_mode, 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; } } @@ -2377,7 +2377,7 @@ pub trait ISizeAndMarginsComputer { // 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 // 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. diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 07e4b783b2a..67e61b7dfcb 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -19,7 +19,7 @@ use context::{LayoutContext, with_thread_local_font_context}; use data::{LayoutDataFlags, LayoutData}; use flex::FlexFlow; use floats::FloatKind; -use flow::{self, AbsoluteDescendants, Flow, FlowClass, ImmutableFlowUtils}; +use flow::{AbsoluteDescendants, Flow, FlowClass, GetBaseFlow, ImmutableFlowUtils}; use flow::{FlowFlags, MutableFlowUtils, MutableOwnedFlowUtils}; use flow_ref::FlowRef; use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo}; @@ -96,7 +96,7 @@ impl ConstructionResult { match *self { ConstructionResult::None => 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()); self.set_flow_construction_result(&kid, construction_result) } 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 // handle {ib} splits. let old_inline_fragment_accumulator = @@ -625,7 +625,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> flow.set_absolute_descendants(abs_descendants); 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 // reached its CB. abs_descendants.push(flow.clone()); @@ -780,7 +780,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> match kid.get_construction_result() { ConstructionResult::None => {} 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( &mut fragment_accumulator, node, self.style_context(), flow)); abs_descendants.push_descendants(kid_abs_descendants); @@ -1073,7 +1073,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> 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 // reached its containing block. abs_descendants.push(flow.clone()); @@ -1144,7 +1144,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> 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 // reached its containing block. abs_descendants.push(wrapper_flow.clone()); @@ -1373,7 +1373,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> } 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); true } @@ -1398,7 +1398,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> match fragment.specific { SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => { 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? flow_ref.repair_style_and_bubble_inline_sizes(&style); } @@ -1406,14 +1406,14 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> ref mut inline_absolute_hypothetical_fragment) => { let flow_ref = FlowRef::deref_mut( &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? flow_ref.repair_style_and_bubble_inline_sizes(&style); } SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => { let flow_ref = FlowRef::deref_mut( &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? flow_ref.repair_style_and_bubble_inline_sizes(&style); } @@ -1660,7 +1660,7 @@ impl NodeUtils for ConcreteThreadSafeLayoutNode fn set_flow_construction_result(self, mut result: ConstructionResult) { if self.can_be_fragmented() { 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. 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); } - let base = flow::mut_base(FlowRef::deref_mut(self)); + let base = FlowRef::deref_mut(self).mut_base(); base.children.push_back(new_child); let _ = base.parallel.children_count.fetch_add(1, Ordering::Relaxed); } @@ -1750,7 +1750,7 @@ impl FlowConstructionUtils for FlowRef { fn finish(&mut self) { if !opts::get().bubble_inline_sizes_separately { 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) => { - 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 = Legalizer::create_anonymous_flow(context, parent, diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 1bcd251b886..28511b68569 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -58,6 +58,7 @@ use style::computed_values::position::T as StylePosition; use style::computed_values::visibility::T as Visibility; use style::logical_geometry::{LogicalMargin, LogicalPoint, LogicalRect, LogicalSize, WritingMode}; 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::style_structs; use style::servo::restyle_damage::ServoRestyleDamage; @@ -503,30 +504,16 @@ pub trait FragmentDisplayListBuilding { size: Size2D) -> Option; - fn convert_linear_gradient(&self, - bounds: &Rect, - stops: &[GradientItem], - direction: &LineDirection, - repeating: bool) - -> display_list::Gradient; - - fn convert_radial_gradient(&self, - bounds: &Rect, - 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 /// to the appropriate section of the display list. fn build_display_list_for_background_gradient(&self, state: &mut DisplayListBuildState, display_list_section: DisplayListSection, - absolute_bounds: &Rect, + absolute_bounds: Rect, clip: &LocalClip, 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 /// necessary. @@ -819,6 +806,120 @@ fn convert_gradient_stops(gradient_items: &[GradientItem], stops } +fn convert_linear_gradient(size: Size2D, + 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, + 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, ¢er) + }, + 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, ¢er) + }, + }; + + 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] /// Duplicate the first and last stops if necessary. /// @@ -1023,10 +1124,11 @@ impl FragmentDisplayListBuilding for Fragment { Either::Second(Image::Gradient(ref gradient)) => { self.build_display_list_for_background_gradient(state, display_list_section, - &absolute_bounds, + *absolute_bounds, &clip, gradient, - style); + style, + i); } Either::Second(Image::Url(ref image_url)) => { if let Some(url) = image_url.url() { @@ -1310,162 +1412,112 @@ impl FragmentDisplayListBuilding for Fragment { Some(webrender_image) } - fn convert_linear_gradient(&self, - bounds: &Rect, - 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, - 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, ¢er) - }, - 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, ¢er) - }, - }; - - 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, state: &mut DisplayListBuildState, display_list_section: DisplayListSection, - absolute_bounds: &Rect, + absolute_bounds: Rect, clip: &LocalClip, gradient: &Gradient, - style: &ComputedValues) { - let border = self.border_width().to_physical(style.writing_mode); - let mut bounds = *absolute_bounds; - bounds.origin.x = bounds.origin.x + border.left; - bounds.origin.y = bounds.origin.y + border.top; - bounds.size.width = bounds.size.width - border.horizontal(); - bounds.size.height = bounds.size.height - border.vertical(); + style: &ComputedValues, + index: usize) { + // Calculate where the first "tile" needs to be placed on one axis. + // * base is the beginning of the visible area + // * start is the current "tile" position + // * tile is the length of the "tile" + // 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, self.node, style.get_cursor(Cursor::Default), display_list_section); let display_item = match gradient.kind { - GradientKind::Linear(ref angle_or_corner) => { - let gradient = self.convert_linear_gradient(&bounds, - &gradient.items[..], - angle_or_corner, - gradient.repeating); + GradientKind::Linear(angle_or_corner) => { + let gradient = convert_linear_gradient( + tile, + &gradient.items[..], + angle_or_corner, + gradient.repeating); DisplayItem::Gradient(Box::new(GradientDisplayItem { base: base, gradient: gradient, + tile: tile, })) } - GradientKind::Radial(ref shape, ref center, _angle) => { - let gradient = self.convert_radial_gradient(&bounds, - &gradient.items[..], - shape, - center, - gradient.repeating); + GradientKind::Radial(shape, center, _angle) => { + let gradient = convert_radial_gradient( + tile, + &gradient.items[..], + shape, + center, + gradient.repeating); DisplayItem::RadialGradient(Box::new(RadialGradientDisplayItem { base: base, gradient: gradient, + tile: tile, })) } }; @@ -1594,10 +1646,10 @@ impl FragmentDisplayListBuilding for Fragment { Either::Second(Image::Gradient(ref gradient)) => { match gradient.kind { GradientKind::Linear(angle_or_corner) => { - let grad = self.convert_linear_gradient(&bounds, - &gradient.items[..], - &angle_or_corner, - gradient.repeating); + let grad = convert_linear_gradient(bounds.size, + &gradient.items[..], + angle_or_corner, + gradient.repeating); state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem { base: base, @@ -1610,12 +1662,12 @@ impl FragmentDisplayListBuilding for Fragment { }), }))); } - GradientKind::Radial(ref shape, ref center, _angle) => { - let grad = self.convert_radial_gradient(&bounds, - &gradient.items[..], - shape, - center, - gradient.repeating); + GradientKind::Radial(shape, center, _angle) => { + let grad = convert_radial_gradient(bounds.size, + &gradient.items[..], + shape, + center, + gradient.repeating); state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem { base: base, border_widths: border.to_physical(style.writing_mode), @@ -1700,7 +1752,7 @@ impl FragmentDisplayListBuilding for Fragment { style: &ComputedValues, bounds: &Rect, clip: &Rect) { - use style::values::Either; + use style::values::specified::outline::OutlineStyle; let width = Au::from(style.get_outline().outline_width); if width == Au(0) { @@ -1708,9 +1760,9 @@ impl FragmentDisplayListBuilding for Fragment { } let outline_style = match style.get_outline().outline_style { - Either::First(_auto) => BorderStyle::Solid, - Either::Second(BorderStyle::None) => return, - Either::Second(border_style) => border_style + OutlineStyle::Auto => BorderStyle::Solid, + OutlineStyle::Other(BorderStyle::None) => return, + OutlineStyle::Other(border_style) => border_style }; // Outlines are not accounted for in the dimensions of the border box, so adjust the diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 564f8ed9a5e..5cbb80263ac 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -13,8 +13,7 @@ use display_list_builder::{DisplayListBuildState, FlexFlowDisplayListBuilding}; use display_list_builder::StackingContextCollectionState; use euclid::Point2D; use floats::FloatKind; -use flow; -use flow::{Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow, FlowFlags}; +use flow::{Flow, FlowClass, GetBaseFlow, ImmutableFlowUtils, OpaqueFlow, FlowFlags}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use layout_debug; use model::{AdjoiningMargins, CollapsibleMargins}; @@ -451,7 +450,7 @@ impl FlexFlow { let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes(); if !fixed_width { 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); if !is_absolutely_positioned { let flex_item_inline_sizes = IntrinsicISizes { @@ -477,7 +476,7 @@ impl FlexFlow { let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes(); if !fixed_width { 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); if !is_absolutely_positioned { computation.content_intrinsic_sizes.minimum_inline_size = @@ -519,7 +518,7 @@ impl FlexFlow { let mut children = self.block_flow.base.children.random_access_mut(); 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; 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 @@ -667,7 +666,7 @@ impl FlexFlow { let mut children = self.block_flow.base.children.random_access_mut(); 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 { base.position.start.b = cur_b; cur_b = cur_b + base.position.size.block; diff --git a/components/layout/floats.rs b/components/layout/floats.rs index 0feb6699987..4c4d6f21f36 100644 --- a/components/layout/floats.rs +++ b/components/layout/floats.rs @@ -4,7 +4,7 @@ use app_units::{Au, MAX_AU}; use block::FormattingContextType; -use flow::{self, Flow, FlowFlags, ImmutableFlowUtils}; +use flow::{Flow, FlowFlags, GetBaseFlow, ImmutableFlowUtils}; use persistent_list::PersistentList; use std::cmp::{max, min}; use std::fmt; @@ -458,7 +458,7 @@ impl SpeculatedFloatPlacement { /// 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. 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) { 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() { return } @@ -522,7 +522,7 @@ impl SpeculatedFloatPlacement { /// 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 { 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(); diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 943ddcb71b7..e4841bd2e0f 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -76,6 +76,30 @@ use table_wrapper::TableWrapperFlow; #[allow(unsafe_code)] 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 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. /// /// 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, _fragmentation_context: Option) -> Option> { - fn recursive_assign_block_size(flow: &mut F, ctx: &LayoutContext) { - for child in mut_base(flow).children.iter_mut() { + fn recursive_assign_block_size(flow: &mut F, ctx: &LayoutContext) { + for child in flow.mut_base().child_iter_mut() { recursive_assign_block_size(child, ctx) } flow.assign_block_size(ctx); @@ -251,12 +275,12 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { parent_thread_id: u8, _content_box: LogicalRect) -> bool { - let might_have_floats_in_or_out = base(self).might_have_floats_in() || - base(self).might_have_floats_out(); + let might_have_floats_in_or_out = self.base().might_have_floats_in() || + self.base().might_have_floats_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); - 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 } @@ -264,9 +288,9 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { fn get_overflow_in_parent_coordinates(&self) -> Overflow { // FIXME(#2795): Get the real container size. 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() { 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( - &base(self).stacking_relative_position, - &base(self).early_absolute_position_info.relative_containing_block_size, - base(self).early_absolute_position_info.relative_containing_block_mode, + &self.base().stacking_relative_position, + &self.base().early_absolute_position_info.relative_containing_block_size, + self.base().early_absolute_position_info.relative_containing_block_mode, CoordinateSystem::Own); if StyleOverflow::Visible != self.as_block().fragment.style.get_box().overflow_x { overflow.paint.origin.x = Au(0); @@ -341,13 +365,13 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { FlowClass::Block | FlowClass::TableCaption | 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()); } } _ => {} } - mut_base(self).overflow = overflow + self.mut_base().overflow = overflow } /// 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 { 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 { @@ -448,41 +472,13 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { fn print_extra_flow_children(&self, _: &mut PrintTree) { } fn clipping_and_scrolling(&self) -> ClippingAndScrolling { - match base(self).clipping_and_scrolling { + match self.base().clipping_and_scrolling { Some(info) => info, None => unreachable!("Tried to access scroll root id on Flow before assignment"), } } } -// Base access - -#[inline(always)] -#[allow(unsafe_code)] -pub fn base(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(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 { // 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 { self.children.iter_mut() } @@ -1216,12 +1217,12 @@ impl<'a> ImmutableFlowUtils for &'a Flow { /// Returns true if this flow has no children. fn is_leaf(self) -> bool { - base(self).children.is_empty() + self.base().children.is_empty() } /// Returns the number of children that this flow possesses. fn child_count(self) -> usize { - base(self).children.len() + self.base().children.len() } /// 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) { print_tree.new_level(format!("{:?}", self)); 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); } print_tree.end_level(); } 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 } 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 { - for kid in base(self).children.iter().rev() { + for kid in self.base().children.iter().rev() { if kid.is_inline_flow() { 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() { - 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. fn repair_style_and_bubble_inline_sizes(self, style: &::ServoArc) { self.repair_style(style); - mut_base(self).update_flags_if_needed(style); + self.mut_base().update_flags_if_needed(style); self.bubble_inline_sizes(); } } @@ -1323,11 +1324,11 @@ impl MutableOwnedFlowUtils for FlowRef { /// construction is allowed to possess. fn set_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants) { 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; for descendant_link in base.abs_descendants.descendant_links.iter_mut() { 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()); } } @@ -1353,10 +1354,10 @@ impl MutableOwnedFlowUtils for FlowRef { }); 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; 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()); } } diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 75b49c14aab..b2a627347da 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -12,7 +12,7 @@ use canvas_traits::canvas::CanvasMsg; use context::{LayoutContext, with_thread_local_font_context}; use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D}; use floats::ClearType; -use flow::{self, ImmutableFlowUtils}; +use flow::{GetBaseFlow, ImmutableFlowUtils}; use flow_ref::FlowRef; use gfx; use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode}; @@ -232,7 +232,7 @@ impl SpecificFragmentInfo { SpecificFragmentInfo::InlineBlock(ref info) => &info.flow_ref, }; - flow::base(&**flow).restyle_damage + flow.base().restyle_damage } pub fn get_type(&self) -> &'static str { @@ -1750,22 +1750,17 @@ impl Fragment { let character_breaking_strategy = 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, - SplitOptions::empty()) { - None => None, - Some(split_info) => { - match split_info.inline_start { - None => None, - Some(split) => { - Some(TruncationResult { - split: split, - text_run: split_info.text_run.clone(), - }) - } - } - } - } + + let split_info = self.calculate_split_position_using_breaking_strategy( + character_breaking_strategy, + max_inline_size, + SplitOptions::empty())?; + + let split = split_info.inline_start?; + Some(TruncationResult { + split: split, + text_run: split_info.text_run.clone(), + }) } /// A helper method that uses the breaking strategy described by `slice_iterator` (at present, @@ -2617,11 +2612,11 @@ impl Fragment { match self.specific { SpecificFragmentInfo::InlineBlock(ref info) => { 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) => { let block_flow = info.flow_ref.as_block(); - overflow.union(&flow::base(block_flow).overflow); + overflow.union(&block_flow.base().overflow); } _ => (), } diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs index 004bcf5d9de..fd11b996872 100644 --- a/components/layout/generated_content.rs +++ b/components/layout/generated_content.rs @@ -9,7 +9,7 @@ //! as possible. 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 gfx::display_list::OpaqueNode; use script_layout_interface::wrapper_traits::PseudoElementType; @@ -132,8 +132,8 @@ impl<'a> InorderFlowTraversal for ResolveGeneratedContent<'a> { #[inline] fn should_process_subtree(&mut self, flow: &mut Flow) -> bool { - flow::base(flow).restyle_damage.intersects(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT) || - flow::base(flow).flags.intersects(FlowFlags::AFFECTS_COUNTERS | FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN) + flow.base().restyle_damage.intersects(ServoRestyleDamage::RESOLVE_GENERATED_CONTENT) || + flow.base().flags.intersects(FlowFlags::AFFECTS_COUNTERS | FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN) } } @@ -311,9 +311,9 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { "es.0[self.traversal.quote as usize] }; if close { - close_quote.clone() + close_quote.to_string() } else { - open_quote.clone() + open_quote.to_string() } } } diff --git a/components/layout/incremental.rs b/components/layout/incremental.rs index bbb2c89f55f..ff1e0813ccd 100644 --- a/components/layout/incremental.rs +++ b/components/layout/incremental.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use flow::{self, FlowFlags, Flow}; +use flow::{FlowFlags, Flow, GetBaseFlow}; use style::computed_values::float::T as Float; use style::selector_parser::RestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage; @@ -30,20 +30,20 @@ pub trait LayoutDamageComputation { impl<'a> LayoutDamageComputation for &'a mut Flow { fn compute_layout_damage(self) -> SpecialRestyleDamage { 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. 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. let parent_damage = self_base.restyle_damage; for kid in self_base.children.iter_mut() { let child_is_absolutely_positioned = - flow::base(kid).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); - flow::mut_base(kid).restyle_damage.insert( + kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED); + kid.mut_base().restyle_damage.insert( parent_damage.damage_for_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()); } 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)); 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); } } - let self_base = flow::mut_base(self); + let self_base = self.mut_base(); if self_base.flags.float_kind() != Float::None && self_base.restyle_damage.intersects(ServoRestyleDamage::REFLOW) { special_damage.insert(SpecialRestyleDamage::REFLOW_ENTIRE_DOCUMENT); @@ -76,7 +76,7 @@ impl<'a> LayoutDamageComputation for &'a mut Flow { } 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.remove(ServoRestyleDamage::RECONSTRUCT_FLOW); for kid in self_base.children.iter_mut() { diff --git a/components/layout/inline.rs b/components/layout/inline.rs index 9d4bfbc7ae4..b52b2f7fe45 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -12,8 +12,8 @@ use display_list_builder::{DisplayListBuildState, InlineFlowDisplayListBuilding} use display_list_builder::StackingContextCollectionState; use euclid::{Point2D, Size2D}; use floats::{FloatKind, Floats, PlacementInfo}; -use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag}; -use flow::{FlowFlags, EarlyAbsolutePositionInfo, OpaqueFlow}; +use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag}; +use flow::{FlowFlags, EarlyAbsolutePositionInfo, GetBaseFlow, OpaqueFlow}; use flow_ref::FlowRef; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::FragmentFlags; @@ -1315,7 +1315,7 @@ impl Flow for InlineFlow { let writing_mode = self.base.writing_mode; 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); @@ -1423,7 +1423,7 @@ impl Flow for InlineFlow { // sizes down to them. let block_container_explicit_block_size = self.base.block_container_explicit_block_size; 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_writing_mode = container_mode; @@ -1524,14 +1524,14 @@ impl Flow for InlineFlow { match f.specific { SpecificFragmentInfo::InlineBlock(ref mut info) => { 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_mode: writing_mode, }; } SpecificFragmentInfo::InlineAbsolute(ref mut info) => { 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_mode: writing_mode, }; @@ -1757,7 +1757,7 @@ impl fmt::Debug for InlineFlow { "{:?}({:x}) {:?}", self.class(), self.base.debug_id(), - flow::base(self)) + self.base()) } } diff --git a/components/layout/layout_debug.rs b/components/layout/layout_debug.rs index 1c9869c2165..466399ca8f0 100644 --- a/components/layout/layout_debug.rs +++ b/components/layout/layout_debug.rs @@ -5,7 +5,7 @@ //! Supports writing a trace file created during each layout scope //! that can be viewed by an external tool to make layout debugging easier. -use flow; +use flow::GetBaseFlow; use flow_ref::FlowRef; use serde_json::{to_string, to_value, Value}; use std::borrow::ToOwned; @@ -63,7 +63,7 @@ impl Scope { pub fn new(name: String) -> Scope { STATE_KEY.with(|ref r| { 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)); state.scope_stack.push(data); } @@ -78,7 +78,7 @@ impl Drop for Scope { STATE_KEY.with(|ref r| { if let Some(ref mut state) = *r.borrow_mut() { 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(); 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())); 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 { scope_stack: vec![Box::new(ScopeData::new("root".to_owned(), flow_trace))], 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()); assert!(thread_state.scope_stack.len() == 1); 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 mut file = File::create(format!("layout_trace-{}.json", generation)).unwrap(); diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 7b811e38772..327c475fefe 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -13,7 +13,7 @@ use context::LayoutContext; use display_list_builder::{DisplayListBuildState, StackingContextCollectionState}; use euclid::{Point2D, Vector2D}; use floats::FloatKind; -use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext}; +use flow::{Flow, FlowClass, OpaqueFlow, FragmentationContext, GetBaseFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx_traits::print_tree::PrintTree; 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 = pitch.to_physical(self.block_flow.base.writing_mode); 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); } } diff --git a/components/layout/parallel.rs b/components/layout/parallel.rs index 3793ad648a6..b555a9f51dc 100644 --- a/components/layout/parallel.rs +++ b/components/layout/parallel.rs @@ -10,7 +10,7 @@ use block::BlockFlow; use context::LayoutContext; -use flow::{self, Flow}; +use flow::{Flow, GetBaseFlow}; use flow_ref::FlowRef; use profile_traits::time::{self, TimerMetadata, profile}; 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. 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 { &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 { // We were the last child of our parent. Reflow our parent. unsafe_flow = unsafe_parent @@ -127,7 +127,7 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow], unsafe { // Get a real 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; if assign_isize_traversal.should_process(flow) { @@ -136,7 +136,7 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow], } // Possibly enqueue the children. - for kid in flow::child_iter_mut(flow) { + for kid in flow.mut_base().child_iter_mut() { had_children = true; discovered_child_flows.push(UnsafeFlow(kid)); } diff --git a/components/layout/query.rs b/components/layout/query.rs index 2fb199f4e45..36e4a9b04d3 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -8,7 +8,7 @@ use app_units::Au; use construct::ConstructionResult; use context::LayoutContext; use euclid::{Point2D, Vector2D, Rect, Size2D}; -use flow::{self, Flow}; +use flow::{Flow, GetBaseFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; use gfx::display_list::{DisplayList, OpaqueNode, ScrollOffsetMap}; use inline::InlineFragmentNodeFlags; @@ -774,7 +774,7 @@ where let position = maybe_data.map_or(Point2D::zero(), |data| { match (*data).flow_construction_result { 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. // https://github.com/servo/servo/issues/8307 _ => Point2D::zero() diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs index 57785fceee7..02f876c35ae 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -9,7 +9,7 @@ use context::LayoutContext; use display_list_builder::{DisplayListBuildState, StackingContextCollectionState}; use euclid::{Point2D, Vector2D}; use floats::SpeculatedFloatPlacement; -use flow::{self, Flow, ImmutableFlowUtils, FlowFlags}; +use flow::{Flow, ImmutableFlowUtils, FlowFlags, GetBaseFlow}; use fragment::{FragmentBorderBoxIterator, CoordinateSystem}; use generated_content::ResolveGeneratedContent; 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 // the float speculation of a block formatting context and need to fix it. if relayout_mode == RelayoutMode::Force { - flow::mut_base(flow) + flow.mut_base() .restyle_damage .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); } - 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); } @@ -87,11 +87,11 @@ pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut Flow, iterator stacking_context_position: &Point2D) { 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; 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)) + - flow::base(kid).stacking_relative_position + + kid.base().stacking_relative_position + stacking_context_position.to_vector(); let relative_position = kid.as_block() .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) { - if !flow::base(flow).restyle_damage.contains(ServoRestyleDamage::STORE_OVERFLOW) { + if !flow.base().restyle_damage.contains(ServoRestyleDamage::STORE_OVERFLOW) { 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); } flow.store_overflow(layout_context); - flow::mut_base(flow) + flow.mut_base() .restyle_damage .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 /// 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) { - if !flow::base(flow).restyle_damage.intersects(ServoRestyleDamage::REFLOW) { + if !flow.base().restyle_damage.intersects(ServoRestyleDamage::REFLOW) { return; } let mut floats_in = SpeculatedFloatPlacement::compute_floats_in_for_first_child(flow); - for kid in flow::mut_base(flow).child_iter_mut() { - if flow::base(kid).flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { + for kid in flow.mut_base().child_iter_mut() { + if kid.base().flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { // Do not propagate floats in or out, but do propogate between kids. guess_float_placement(kid); } else { 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); - floats_in = flow::base(kid).speculated_float_placement_out; + floats_in = kid.base().speculated_float_placement_out; } } 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 } diff --git a/components/layout/table.rs b/components/layout/table.rs index 37e92be32be..512db136b0c 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -13,8 +13,7 @@ use context::LayoutContext; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState}; use euclid::Point2D; -use flow; -use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; +use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, GetBaseFlow, OpaqueFlow}; use flow_list::MutFlowListIterator; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; 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. - 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` // function here because the child has already translated floats past its border // 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; } @@ -796,7 +795,7 @@ impl TableLikeFlow for BlockFlow { // Write in the size of the relative containing block for children. (This information // is also needed to handle RTL.) 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_mode: self.fragment.style().writing_mode, }; @@ -856,7 +855,7 @@ impl<'a> Iterator for TableRowIterator<'a> { match self.kids.next() { Some(kid) => { 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() } else if kid.is_table_row() { Some(kid.as_mut_table_row()) diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index cbde1a2be83..81f9e32661a 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -13,7 +13,7 @@ use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags}; use display_list_builder::StackingContextCollectionState; 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 gfx_traits::print_tree::PrintTree; use layout_debug; @@ -101,8 +101,8 @@ impl TableCellFlow { // 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. let mut extents = None; - for kid in flow::base(self).children.iter() { - let kid_base = flow::base(kid); + for kid in self.base().children.iter() { + let kid_base = kid.base(); if kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { continue } @@ -128,7 +128,7 @@ impl TableCellFlow { }; 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(); let kids_self_gap = self_size - kids_size; @@ -143,8 +143,8 @@ impl TableCellFlow { return } - for kid in flow::mut_base(self).children.iter_mut() { - let kid_base = flow::mut_base(kid); + for kid in self.mut_base().children.iter_mut() { + let kid_base = kid.mut_base(); if !kid_base.flags.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) { kid_base.position.start.b += offset } diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index 8135e9b51a2..6f2212176f7 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -13,7 +13,7 @@ use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags}; use display_list_builder::StackingContextCollectionState; use euclid::Point2D; -use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; +use flow::{EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, GetBaseFlow, OpaqueFlow}; use flow_list::MutFlowListIterator; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx_traits::print_tree::PrintTree; @@ -126,7 +126,7 @@ impl TableRowFlow { - self.block_flow.fragment.margin; for kid in self.block_flow.base.child_iter_mut() { 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, thread_id, content_box); @@ -143,7 +143,7 @@ impl TableRowFlow { child_specified_block_size + 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); 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 // calculation. - let child_base = flow::mut_base(kid); + let child_base = kid.mut_base(); let child_column_inline_size = ColumnIntrinsicInlineSize { minimum_length: match child_specified_inline_size { LengthOrPercentageOrAuto::Auto | diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index b69d6926816..8dac0180171 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -7,7 +7,7 @@ use construct::FlowConstructor; use context::LayoutContext; 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 servo_config::opts; use style::context::{SharedStyleContext, StyleContext}; @@ -110,7 +110,7 @@ pub trait PreorderFlowTraversal { if self.should_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); } } @@ -125,7 +125,7 @@ pub trait PreorderFlowTraversal { if self.should_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) } } @@ -145,7 +145,7 @@ pub trait PostorderFlowTraversal { /// Traverses the tree in postorder. 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); } if self.should_process(flow) { @@ -171,7 +171,7 @@ pub trait InorderFlowTraversal { return; } 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); } } @@ -226,12 +226,12 @@ impl<'a> PostorderFlowTraversal for BubbleISizes<'a> { #[inline] fn process(&self, flow: &mut Flow) { flow.bubble_inline_sizes(); - flow::mut_base(flow).restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES); + flow.mut_base().restyle_damage.remove(ServoRestyleDamage::BUBBLE_ISIZES); } #[inline] 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] 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] 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) && // The fragmentation countainer is responsible for calling Flow::fragment recursively !base.flags.contains(FlowFlags::CAN_BE_FRAGMENTED) @@ -292,13 +292,13 @@ pub struct ComputeStackingRelativePositions<'a> { impl<'a> PreorderFlowTraversal for ComputeStackingRelativePositions<'a> { #[inline] 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] fn process(&self, flow: &mut Flow) { 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] pub fn traverse(&mut self, flow: &mut Flow) { 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; self.state.current_clipping_and_scrolling = flow.clipping_and_scrolling(); 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); } diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index dd934c79ae1..52a19e9c70b 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -428,7 +428,6 @@ impl WebRenderDisplayItemConverter for DisplayItem { builder.push_border(&self.prim_info(), widths, details); } DisplayItem::Gradient(ref item) => { - let rect = item.base.bounds; let start_point = item.gradient.start_point.to_pointf(); let end_point = item.gradient.end_point.to_pointf(); let extend_mode = if item.gradient.repeating { @@ -442,11 +441,10 @@ impl WebRenderDisplayItemConverter for DisplayItem { extend_mode); builder.push_gradient(&self.prim_info(), gradient, - rect.size.to_sizef(), + item.tile.to_sizef(), webrender_api::LayoutSize::zero()); } DisplayItem::RadialGradient(ref item) => { - let rect = item.base.bounds; let center = item.gradient.center.to_pointf(); let radius = item.gradient.radius.to_sizef(); let extend_mode = if item.gradient.repeating { @@ -460,7 +458,7 @@ impl WebRenderDisplayItemConverter for DisplayItem { extend_mode); builder.push_radial_gradient(&self.prim_info(), gradient, - rect.size.to_sizef(), + item.tile.to_sizef(), webrender_api::LayoutSize::zero()); } DisplayItem::Line(ref item) => { diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 6ed68abcb80..8401305036f 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -70,7 +70,7 @@ use layout::context::RegisteredPainter; use layout::context::RegisteredPainters; use layout::context::malloc_size_of_persistent_local_context; 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::incremental::{LayoutDamageComputation, RelayoutMode, SpecialRestyleDamage}; use layout::layout_debug; @@ -956,22 +956,22 @@ impl LayoutThread { layout_root: &mut Flow, layout_context: &mut LayoutContext, 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()); profile(time::ProfilerCategory::LayoutDispListBuild, metadata.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, 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 }; 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() { if reflow_goal.needs_display_list() { let mut build_state = @@ -980,7 +980,7 @@ impl LayoutThread { debug!("Done building display list."); let root_size = { - let root_flow = flow::base(layout_root); + let root_flow = layout_root.base(); if self.stylist.viewport_constraints().is_some() { root_flow.position.size.to_physical(root_flow.writing_mode) } else { @@ -1564,7 +1564,7 @@ impl LayoutThread { // Perform the primary layout passes over the flow tree to compute the locations of all // 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) { profile(time::ProfilerCategory::LayoutMain, self.profiler_metadata(), @@ -1630,12 +1630,12 @@ impl LayoutThread { fn reflow_all_nodes(flow: &mut Flow) { debug!("reflowing all nodes!"); - flow::mut_base(flow) + flow.mut_base() .restyle_damage .insert(ServoRestyleDamage::REPAINT | ServoRestyleDamage::STORE_OVERFLOW | 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); } } diff --git a/components/net/http_cache.rs b/components/net/http_cache.rs index 1b7d8ad372b..6f0a71bd40e 100644 --- a/components/net/http_cache.rs +++ b/components/net/http_cache.rs @@ -479,10 +479,7 @@ impl HttpCache { return None; } let entry_key = CacheKey::new(request.clone()); - let resources = match self.entries.get(&entry_key) { - Some(ref resources) => resources.clone(), - None => return None, - }; + let resources = self.entries.get(&entry_key)?.clone(); let mut candidates = vec![]; for cached_resource in resources.iter() { let mut can_be_constructed = true; diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 5561cd7dd95..8c3c77ed27c 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -39,6 +39,7 @@ byteorder = "1.0" canvas_traits = {path = "../canvas_traits"} caseless = "0.1.0" cookie = "0.10" +chrono = "0.4" cssparser = "0.23.0" deny_public_fields = {path = "../deny_public_fields"} devtools_traits = {path = "../devtools_traits"} diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs index 9fa1f251dbc..6761f175a3f 100644 --- a/components/script/document_loader.rs +++ b/components/script/document_loader.rs @@ -141,6 +141,13 @@ impl DocumentLoader { !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) { self.events_inhibited = true; } diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 596b2db14b2..83c438a26e7 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -4,6 +4,8 @@ //! The `ByteString` struct. +use chrono::{Datelike, TimeZone}; +use chrono::prelude::{Weekday, Utc}; use cssparser::CowRcStr; use html5ever::{LocalName, Namespace}; use servo_atoms::Atom; @@ -293,6 +295,13 @@ impl DOMString { pub fn is_valid_month_string(&self) -> bool { 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 for DOMString { @@ -445,6 +454,48 @@ fn parse_date_string(value: &str) -> Result<(u32, u32, u32), ()> { 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::().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::().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 fn parse_month_component(value: &str) -> Result<(u32, u32), ()> { // Step 3 @@ -495,7 +546,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result { 1|3|5|7|8|10|12 => Ok(31), 4|6|9|11 => Ok(30), 2 => { - if year_num % 400 == 0 || (year_num % 4 == 0 && year_num % 100 != 0) { + if is_leap_year(year_num) { Ok(29) } else { Ok(28) @@ -504,3 +555,17 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result { _ => 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) +} diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 93d4981d2bb..1c9dc16c445 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -129,11 +129,10 @@ impl CanvasRenderingContext2D { size: Size2D) -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); - let (sender, receiver) = ipc::channel().unwrap(); + let (ipc_renderer, receiver) = ipc::channel::().unwrap(); let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); - script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); - let ipc_renderer = receiver.recv().unwrap(); + script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, receiver)).unwrap(); debug!("Done."); CanvasRenderingContext2D { reflector_: Reflector::new(), diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 2c27450b29b..75a54e5c6b9 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -322,6 +322,7 @@ pub struct Document { dom_content_loaded_event_start: Cell, dom_content_loaded_event_end: Cell, dom_complete: Cell, + top_level_dom_complete: Cell, load_event_start: Cell, load_event_end: Cell, /// @@ -1627,6 +1628,12 @@ impl Document { // asap_in_order_script_loaded. 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() { // Step 6. return; @@ -1951,6 +1958,10 @@ impl Document { 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 { self.load_event_start.get() } @@ -2265,6 +2276,7 @@ impl Document { dom_content_loaded_event_start: Cell::new(Default::default()), dom_content_loaded_event_end: 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_end: Cell::new(Default::default()), https_state: Cell::new(HttpsState::None), diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 047e1b6d40f..8c5699446ef 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -405,6 +405,18 @@ impl TextControl for HTMLInputElement { fn textinput(&self) -> &DomRefCell> { &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 { @@ -676,38 +688,38 @@ impl HTMLInputElementMethods for HTMLInputElement { } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart - fn SelectionStart(&self) -> u32 { - self.dom_selection_start() + fn GetSelectionStart(&self) -> Option { + self.get_dom_selection_start() } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart - fn SetSelectionStart(&self, start: u32) { - self.set_dom_selection_start(start); + fn SetSelectionStart(&self, start: Option) -> ErrorResult { + self.set_dom_selection_start(start) } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend - fn SelectionEnd(&self) -> u32 { - self.dom_selection_end() + fn GetSelectionEnd(&self) -> Option { + self.get_dom_selection_end() } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend - fn SetSelectionEnd(&self, end: u32) { + fn SetSelectionEnd(&self, end: Option) -> ErrorResult { self.set_dom_selection_end(end) } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection - fn SelectionDirection(&self) -> DOMString { - self.dom_selection_direction() + fn GetSelectionDirection(&self) -> Option { + self.get_dom_selection_direction() } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection - fn SetSelectionDirection(&self, direction: DOMString) { - self.set_dom_selection_direction(direction); + fn SetSelectionDirection(&self, direction: Option) -> ErrorResult { + self.set_dom_selection_direction(direction) } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange - fn SetSelectionRange(&self, start: u32, end: u32, direction: Option) { - self.set_dom_selection_range(start, end, direction); + fn SetSelectionRange(&self, start: u32, end: u32, direction: Option) -> ErrorResult { + self.set_dom_selection_range(start, end, direction) } // Select the files based on filepaths passed in, @@ -993,6 +1005,12 @@ impl HTMLInputElement { *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 => { let mut textinput = self.textinput.borrow_mut(); diff --git a/components/script/dom/htmllegendelement.rs b/components/script/dom/htmllegendelement.rs index 58c193fd6d5..04e8636bb03 100644 --- a/components/script/dom/htmllegendelement.rs +++ b/components/script/dom/htmllegendelement.rs @@ -75,10 +75,7 @@ impl VirtualMethods for HTMLLegendElement { impl HTMLLegendElementMethods for HTMLLegendElement { // https://html.spec.whatwg.org/multipage/#dom-legend-form fn GetForm(&self) -> Option> { - let parent = match self.upcast::().GetParentElement() { - Some(parent) => parent, - None => return None, - }; + let parent = self.upcast::().GetParentElement()?; if parent.is::() { return self.form_owner(); } diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index b9a6ad3ff69..7996eecc563 100755 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -8,6 +8,7 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding; use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; +use dom::bindings::error::ErrorResult; use dom::bindings::inheritance::Castable; use dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom}; use dom::bindings::str::DOMString; @@ -145,6 +146,10 @@ impl TextControl for HTMLTextAreaElement { fn textinput(&self) -> &DomRefCell> { &self.textinput } + + fn selection_api_applies(&self) -> bool { + true + } } impl HTMLTextAreaElementMethods for HTMLTextAreaElement { @@ -260,38 +265,38 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart - fn SelectionStart(&self) -> u32 { - self.dom_selection_start() + fn GetSelectionStart(&self) -> Option { + self.get_dom_selection_start() } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart - fn SetSelectionStart(&self, start: u32) { - self.set_dom_selection_start(start); + fn SetSelectionStart(&self, start: Option) -> ErrorResult { + self.set_dom_selection_start(start) } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend - fn SelectionEnd(&self) -> u32 { - self.dom_selection_end() + fn GetSelectionEnd(&self) -> Option { + self.get_dom_selection_end() } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend - fn SetSelectionEnd(&self, end: u32) { - self.set_dom_selection_end(end); + fn SetSelectionEnd(&self, end: Option) -> ErrorResult { + self.set_dom_selection_end(end) } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection - fn SelectionDirection(&self) -> DOMString { - self.dom_selection_direction() + fn GetSelectionDirection(&self) -> Option { + self.get_dom_selection_direction() } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection - fn SetSelectionDirection(&self, direction: DOMString) { - self.set_dom_selection_direction(direction); + fn SetSelectionDirection(&self, direction: Option) -> ErrorResult { + self.set_dom_selection_direction(direction) } // https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange - fn SetSelectionRange(&self, start: u32, end: u32, direction: Option) { - self.set_dom_selection_range(start, end, direction); + fn SetSelectionRange(&self, start: u32, end: u32, direction: Option) -> ErrorResult { + self.set_dom_selection_range(start, end, direction) } } diff --git a/components/script/dom/performancetiming.rs b/components/script/dom/performancetiming.rs index 0ede2f69b07..7df8e9d2c76 100644 --- a/components/script/dom/performancetiming.rs +++ b/components/script/dom/performancetiming.rs @@ -86,6 +86,12 @@ impl PerformanceTimingMethods for PerformanceTiming { fn LoadEventEnd(&self) -> u64 { 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() + } } diff --git a/components/script/dom/textcontrol.rs b/components/script/dom/textcontrol.rs index 2b47fcd00a4..9143c2bda23 100644 --- a/components/script/dom/textcontrol.rs +++ b/components/script/dom/textcontrol.rs @@ -4,6 +4,7 @@ use dom::bindings::cell::DomRefCell; use dom::bindings::conversions::DerivedFrom; +use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::str::DOMString; use dom::event::{EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; @@ -13,52 +14,108 @@ use textinput::{SelectionDirection, TextInput}; pub trait TextControl: DerivedFrom + DerivedFrom { fn textinput(&self) -> &DomRefCell>; + fn selection_api_applies(&self) -> bool; // https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart - fn dom_selection_start(&self) -> u32 { - self.textinput().borrow().get_selection_start() + fn get_dom_selection_start(&self) -> Option { + // 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 - fn set_dom_selection_start(&self, start: u32) { + fn set_dom_selection_start(&self, start: Option) -> ErrorResult { + // Step 1 + if !self.selection_api_applies() { + return Err(Error::InvalidState); + } + // Step 2 - let mut end = self.dom_selection_end(); + let mut end = self.selection_end(); // Step 3 - if end < start { - end = start; + if let Some(s) = start { + if end < s { + end = s; + } } // 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 - fn dom_selection_end(&self) -> u32 { - self.textinput().borrow().get_absolute_insertion_point() as u32 + fn get_dom_selection_end(&self) -> Option { + // 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 - fn set_dom_selection_end(&self, end: u32) { - self.set_selection_range(self.dom_selection_start(), end, self.selection_direction()); + fn set_dom_selection_end(&self, end: Option) -> ErrorResult { + // 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 - fn dom_selection_direction(&self) -> DOMString { - DOMString::from(self.selection_direction()) + fn get_dom_selection_direction(&self) -> Option { + // 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 - fn set_dom_selection_direction(&self, direction: DOMString) { - self.textinput().borrow_mut().selection_direction = SelectionDirection::from(direction); + fn set_dom_selection_direction(&self, direction: Option) -> ErrorResult { + // 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 - fn set_dom_selection_range(&self, start: u32, end: u32, direction: Option) { - // Step 4 - let direction = direction.map_or(SelectionDirection::None, |d| SelectionDirection::from(d)); + fn set_dom_selection_range(&self, start: u32, end: u32, direction: Option) -> ErrorResult { + // Step 1 + 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 { @@ -66,12 +123,15 @@ pub trait TextControl: DerivedFrom + DerivedFrom { } // https://html.spec.whatwg.org/multipage/#set-the-selection-range - fn set_selection_range(&self, start: u32, end: u32, direction: SelectionDirection) { - // Step 5 - self.textinput().borrow_mut().selection_direction = direction; + fn set_selection_range(&self, start: Option, end: Option, direction: Option) { + // Step 1 + let start = start.unwrap_or(0); - // Step 3 - self.textinput().borrow_mut().set_selection_range(start, end); + // Step 2 + 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 let window = window_from_node(self); diff --git a/components/script/dom/webidls/HTMLInputElement.webidl b/components/script/dom/webidls/HTMLInputElement.webidl index 29bc4b27737..93a5a7f108b 100644 --- a/components/script/dom/webidls/HTMLInputElement.webidl +++ b/components/script/dom/webidls/HTMLInputElement.webidl @@ -90,13 +90,17 @@ interface HTMLInputElement : HTMLElement { readonly attribute NodeList labels; //void select(); - attribute unsigned long selectionStart; - attribute unsigned long selectionEnd; - attribute DOMString selectionDirection; + [SetterThrows] + attribute unsigned long? selectionStart; + [SetterThrows] + attribute unsigned long? selectionEnd; + [SetterThrows] + attribute DOMString? selectionDirection; //void setRangeText(DOMString replacement); //void setRangeText(DOMString replacement, unsigned long start, unsigned long end, // 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 diff --git a/components/script/dom/webidls/HTMLTextAreaElement.webidl b/components/script/dom/webidls/HTMLTextAreaElement.webidl index 2e2e1288559..f0e8a0be118 100644 --- a/components/script/dom/webidls/HTMLTextAreaElement.webidl +++ b/components/script/dom/webidls/HTMLTextAreaElement.webidl @@ -51,11 +51,15 @@ interface HTMLTextAreaElement : HTMLElement { readonly attribute NodeList labels; // void select(); - attribute unsigned long selectionStart; - attribute unsigned long selectionEnd; - attribute DOMString selectionDirection; + [SetterThrows] + attribute unsigned long? selectionStart; + [SetterThrows] + attribute unsigned long? selectionEnd; + [SetterThrows] + attribute DOMString? selectionDirection; // void setRangeText(DOMString replacement); // void setRangeText(DOMString replacement, unsigned long start, unsigned long end, // 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); }; diff --git a/components/script/dom/webidls/PerformanceTiming.webidl b/components/script/dom/webidls/PerformanceTiming.webidl index 9186a7c56f4..e11c7011458 100644 --- a/components/script/dom/webidls/PerformanceTiming.webidl +++ b/components/script/dom/webidls/PerformanceTiming.webidl @@ -29,4 +29,7 @@ interface PerformanceTiming { readonly attribute unsigned long long domComplete; readonly attribute unsigned long long loadEventStart; 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; }; diff --git a/components/script/lib.rs b/components/script/lib.rs index 3bae98a1a06..3143342e4f6 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -31,6 +31,7 @@ extern crate bluetooth_traits; extern crate byteorder; extern crate canvas_traits; extern crate caseless; +extern crate chrono; extern crate cookie as cookie_rs; #[macro_use] extern crate cssparser; #[macro_use] extern crate deny_public_fields; diff --git a/components/script/textinput.rs b/components/script/textinput.rs index 310e0566453..0fe0024a116 100644 --- a/components/script/textinput.rs +++ b/components/script/textinput.rs @@ -21,7 +21,7 @@ pub enum Selection { NotSelected } -#[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)] +#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq)] pub enum SelectionDirection { Forward, Backward, @@ -825,7 +825,7 @@ impl TextInput { } } - 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 end = end as usize; let text_end = self.get_content().len(); @@ -837,7 +837,9 @@ impl TextInput { start = end; } - match self.selection_direction { + self.selection_direction = direction; + + match direction { SelectionDirection::None | SelectionDirection::Forward => { self.selection_begin = Some(self.get_text_point_for_absolute_point(start)); diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index a9b5f86d8fe..fdef5cf7a17 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -79,7 +79,7 @@ pub enum ScriptMsg { ChangeRunningAnimationsState(AnimationState), /// 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.) - CreateCanvasPaintThread(Size2D, IpcSender>), + CreateCanvasPaintThread(Size2D, IpcReceiver), /// Notifies the constellation that this frame has received focus. Focus, /// Forward an event that was sent to the parent window. diff --git a/components/selectors/builder.rs b/components/selectors/builder.rs index c996a6a6491..b3d61b34706 100644 --- a/components/selectors/builder.rs +++ b/components/selectors/builder.rs @@ -264,12 +264,23 @@ fn complex_selector_specificity(mut iter: slice::Iter>) -> Specificity where Impl: SelectorImpl { - fn simple_selector_specificity(simple_selector: &Component, - specificity: &mut Specificity) - where Impl: SelectorImpl + fn simple_selector_specificity( + simple_selector: &Component, + specificity: &mut Specificity, + ) + where + Impl: SelectorImpl { match *simple_selector { 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::LocalName(..) => { specificity.element_selectors += 1 diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs index a2d85e8986d..1097c288c14 100644 --- a/components/selectors/matching.rs +++ b/components/selectors/matching.rs @@ -72,14 +72,24 @@ pub fn matches_selector_list( where E: Element { - selector_list.0.iter().any(|selector| { - matches_selector(selector, - 0, - None, - element, - context, - &mut |_, _| {}) - }) + // This is pretty much any(..) but manually inlined because the compiler + // refuses to do so from querySelector / querySelectorAll. + for selector in &selector_list.0 { + let matches = matches_selector( + selector, + 0, + None, + element, + context, + &mut |_, _| {}, + ); + + if matches { + return true; + } + } + + false } #[inline(always)] @@ -393,6 +403,9 @@ where element.parent_element() } + Combinator::SlotAssignment => { + element.assigned_slot() + } Combinator::PseudoElement => { element.pseudo_element_originating_element() } @@ -453,6 +466,7 @@ where } Combinator::Child | Combinator::Descendant | + Combinator::SlotAssignment | Combinator::PseudoElement => { SelectorMatchingResult::NotMatchedGlobally } @@ -541,6 +555,21 @@ where { match *selector { 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) => { element.match_pseudo_element(pseudo, context.shared) } diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index 6be95b5d018..91417a8cf62 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -55,6 +55,7 @@ pub enum SelectorParseErrorKind<'i> { EmptySelector, DanglingCombinator, NonSimpleSelectorInNegation, + NonCompoundSelector, UnexpectedTokenInAttributeSelector(Token<'i>), PseudoElementExpectedColon(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 /// 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) } + /// 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 /// pseudo-elements. fn parse_non_ts_pseudo_class( @@ -209,6 +215,33 @@ impl SelectorList { } } +/// 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]>, 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 /// inline with selectors to optimize cache performance during matching. /// This matters a lot. @@ -325,6 +358,13 @@ impl SelectorMethods for Component { } match *self { + Slotted(ref selectors) => { + for selector in selectors.iter() { + if !selector.visit(visitor) { + return false; + } + } + } Negation(ref negated) => { for component in negated.iter() { 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 /// for revalidation selectors. PseudoElement, + /// Another combinator used for ::slotted(), which represent the jump from + /// a node to its assigned slot. + SlotAssignment, } impl Combinator { /// Returns true if this combinator is a child or descendant combinator. #[inline] pub fn is_ancestor(&self) -> bool { - matches!(*self, Combinator::Child | - Combinator::Descendant | - Combinator::PseudoElement) + matches!(*self, + Combinator::Child | + Combinator::Descendant | + Combinator::PseudoElement | + Combinator::SlotAssignment) } /// Returns true if this combinator is a pseudo-element combinator. @@ -688,16 +733,16 @@ pub enum Component { // Use a Box in the less common cases with more data to keep size_of::() small. AttributeOther(Box>), - // Pseudo-classes - // - // 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 - // we represent as a namespace and a localname. - // - // Note: if/when we upgrade this to CSS4, which supports combinators, we - // need to think about how this should interact with visit_complex_selector, - // and what the consumers of those APIs should do about the presence of - // combinators in negation. + /// Pseudo-classes + /// + /// 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 we represent as a namespace and a localname. + /// + /// Note: if/when we upgrade this to CSS4, which supports combinators, we + /// need to think about how this should interact with + /// visit_complex_selector, and what the consumers of those APIs should do + /// about the presence of combinators in negation. Negation(Box<[Component]>), FirstChild, LastChild, OnlyChild, Root, @@ -711,6 +756,13 @@ pub enum Component { LastOfType, OnlyOfType, 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]>), PseudoElement(Impl::PseudoElement), } @@ -840,13 +892,15 @@ impl ToCss for Selector { let mut perform_step_2 = true; if first_non_namespace == compound.len() - 1 { match (combinators.peek(), &compound[first_non_namespace]) { - // We have to be careful here, because if there is a pseudo - // element "combinator" there isn't really just the one - // simple selector. Technically this compound selector - // contains the pseudo element selector as - // well--Combinator::PseudoElement doesn't exist in the + // We have to be careful here, because if there is a + // pseudo element "combinator" there isn't really just + // the one simple selector. Technically this compound + // selector contains the pseudo element selector as well + // -- Combinator::PseudoElement, just like + // Combinator::SlotAssignment, don't exist in the // spec. - (Some(&&Component::Combinator(Combinator::PseudoElement)), _) => (), + (Some(&&Component::Combinator(Combinator::PseudoElement)), _) | + (Some(&&Component::Combinator(Combinator::SlotAssignment)), _) => (), (_, &Component::ExplicitUniversalType) => { // Iterate over everything so we serialize the namespace // too. @@ -914,6 +968,7 @@ impl ToCss for Combinator { Combinator::NextSibling => dest.write_str(" + "), Combinator::LaterSibling => dest.write_str(" ~ "), Combinator::PseudoElement => Ok(()), + Combinator::SlotAssignment => Ok(()), } } } @@ -942,6 +997,16 @@ impl ToCss for Component { Combinator(ref c) => { 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) => { p.to_css(dest) } @@ -1092,10 +1157,14 @@ where let mut builder = SelectorBuilder::default(); let mut has_pseudo_element; + let mut slotted; 'outer_loop: loop { // Parse a sequence of simple selectors. - has_pseudo_element = match parse_compound_selector(parser, input, &mut builder)? { - Some(has_pseudo_element) => has_pseudo_element, + match parse_compound_selector(parser, input, &mut builder)? { + Some((has_pseudo, slot)) => { + has_pseudo_element = has_pseudo; + slotted = slot; + } None => { return Err(input.new_custom_error(if builder.has_combinators() { SelectorParseErrorKind::DanglingCombinator @@ -1104,7 +1173,8 @@ where })) } }; - if has_pseudo_element { + + if has_pseudo_element || slotted { break; } @@ -1235,6 +1305,7 @@ where enum SimpleSelectorParseResult { SimpleSelector(Component), PseudoElement(Impl::PseudoElement), + SlottedPseudo(Box<[Selector]>), } #[derive(Debug)] @@ -1547,7 +1618,8 @@ where None => { 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)); } } @@ -1564,12 +1636,13 @@ where /// `Err(())` means invalid 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>( parser: &P, input: &mut CssParser<'i, 't>, builder: &mut SelectorBuilder, -) -> Result, ParseError<'i, P::Error>> +) -> Result, ParseError<'i, P::Error>> where P: Parser<'i, Impl=Impl>, Impl: SelectorImpl, @@ -1577,6 +1650,7 @@ where input.skip_whitespace(); let mut empty = true; + let mut slot = false; if !parse_type_selector(parser, input, builder)? { if let Some(url) = parser.default_namespace() { // If there was no explicit type selector, but there is a @@ -1590,13 +1664,18 @@ where let mut pseudo = false; loop { - match parse_one_simple_selector(parser, input, /* inside_negation = */ false)? { - None => break, - Some(SimpleSelectorParseResult::SimpleSelector(s)) => { + let parse_result = + match parse_one_simple_selector(parser, input, /* inside_negation = */ false)? { + None => break, + Some(result) => result, + }; + + match parse_result { + SimpleSelectorParseResult::SimpleSelector(s) => { builder.push_simple_selector(s); empty = false } - Some(SimpleSelectorParseResult::PseudoElement(p)) => { + SimpleSelectorParseResult::PseudoElement(p) => { // Try to parse state to its right. There are only 3 allowable // state selectors that can go on pseudo-elements. let mut state_selectors = SmallVec::<[Component; 3]>::new(); @@ -1645,13 +1724,25 @@ where empty = false; 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 { // An empty selector is invalid. Ok(None) } else { - Ok(Some(pseudo)) + Ok(Some((pseudo, slot))) } } @@ -1701,7 +1792,7 @@ where /// Returns whether the name corresponds to a CSS2 pseudo-element that /// can be specified with the single colon syntax (in addition to the /// 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! ** match_ignore_ascii_case! { name, "before" | "after" | "first-line" | "first-letter" => true, @@ -1760,16 +1851,35 @@ where )), }; 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 { - let pseudo_element = if is_functional { - input.parse_nested_block(|input| { - P::parse_functional_pseudo_element(parser, name, input) - })? + let parse_result = if is_functional { + if P::parse_slotted(parser) && name.eq_ignore_ascii_case("slotted") { + 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 { - 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 { let pseudo_class = if is_functional { input.parse_nested_block(|input| { @@ -1951,6 +2061,10 @@ pub mod tests { type Impl = DummySelectorImpl; type Error = SelectorParseErrorKind<'i>; + fn parse_slotted(&self) -> bool { + true + } + fn parse_non_ts_pseudo_class( &self, location: SourceLocation, @@ -2057,9 +2171,9 @@ pub mod tests { #[test] fn test_parsing() { - assert!(parse("").is_err()) ; - assert!(parse(":lang(4)").is_err()) ; - assert!(parse(":lang(en US)").is_err()) ; + assert!(parse("").is_err()); + assert!(parse(":lang(4)").is_err()); + assert!(parse(":lang(en US)").is_err()); assert_eq!(parse("EeÉ"), Ok(SelectorList::from_vec(vec!( Selector::from_vec(vec!( Component::LocalName(LocalName { @@ -2366,6 +2480,16 @@ pub mod tests { ].into_boxed_slice() )), 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] diff --git a/components/selectors/tree.rs b/components/selectors/tree.rs index d050c23a470..7a83feb83d0 100644 --- a/components/selectors/tree.rs +++ b/components/selectors/tree.rs @@ -84,6 +84,13 @@ pub trait Element: Sized + Clone + Debug { /// Whether this element is a `link`. fn is_link(&self) -> bool; + /// Returns the assigned element this element is assigned to. + /// + /// Necessary for the `::slotted` pseudo-class. + fn assigned_slot(&self) -> Option { + None + } + fn has_id(&self, id: &::Identifier, case_sensitivity: CaseSensitivity) diff --git a/components/style/animation.rs b/components/style/animation.rs index a324fa99ea9..7fc57c22f72 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -339,12 +339,7 @@ impl PropertyAnimation { longhand, old_style, new_style, - ); - - let animated_property = match animated_property { - Some(p) => p, - None => return None, - }; + )?; let property_animation = PropertyAnimation { property: animated_property, diff --git a/components/style/bloom.rs b/components/style/bloom.rs index 93f3903404f..2e85c61ff73 100644 --- a/components/style/bloom.rs +++ b/components/style/bloom.rs @@ -169,10 +169,8 @@ impl StyleBloom { /// Pop the last element in the bloom filter and return it. #[inline] fn pop(&mut self) -> Option { - let (popped_element, num_hashes) = match self.elements.pop() { - None => return None, - Some(x) => (*x.element, x.num_hashes), - }; + let PushedElement { element, num_hashes } = self.elements.pop()?; + let popped_element = *element; // Verify that the pushed hashes match the ones we'd get from the element. let mut expected_hashes = vec![]; diff --git a/components/style/build.rs b/components/style/build.rs index e34fa79ccdb..517c65f99dc 100644 --- a/components/style/build.rs +++ b/components/style/build.rs @@ -94,6 +94,15 @@ fn generate_properties() { } 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:out_dir={}", env::var("OUT_DIR").unwrap()); generate_properties(); diff --git a/components/style/context.rs b/components/style/context.rs index 7b58bfa7d9f..6c9ba7b47f6 100644 --- a/components/style/context.rs +++ b/components/style/context.rs @@ -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. /// /// There's exactly one of these during a given restyle traversal, and it's diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index 4b564da6eed..86aa135a0b8 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -153,10 +153,7 @@ where K: Borrow, Q: PrecomputedHash + Hash + Eq, { - let index = match self.index.iter().position(|k| k.borrow() == key) { - Some(p) => p, - None => return None, - }; + let index = self.index.iter().position(|k| k.borrow() == key)?; self.index.remove(index); self.values.remove(key) } @@ -194,10 +191,7 @@ where type Item = (&'a K, &'a V); fn next(&mut self) -> Option { - let key = match self.inner.index.get(self.pos) { - Some(k) => k, - None => return None, - }; + let key = self.inner.index.get(self.pos)?; self.pos += 1; let value = &self.inner.values[key]; diff --git a/components/style/dom.rs b/components/style/dom.rs index b78493272e0..90f4933b5ef 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -78,14 +78,10 @@ where fn next(&mut self) -> Option { loop { - match self.0.next() { - Some(n) => { - // Filter out nodes that layout should ignore. - if n.is_text_node() || n.is_element() { - return Some(n) - } - } - None => return None, + let n = self.0.next()?; + // Filter out nodes that layout should ignore. + if n.is_text_node() || n.is_element() { + return Some(n) } } } @@ -100,13 +96,9 @@ where type Item = N; fn next(&mut self) -> Option { - match self.0.take() { - Some(n) => { - self.0 = n.next_sibling(); - Some(n) - } - None => None, - } + let n = self.0.take()?; + self.0 = n.next_sibling(); + Some(n) } } @@ -124,11 +116,7 @@ where #[inline] fn next(&mut self) -> Option { - let prev = match self.previous.take() { - None => return None, - Some(n) => n, - }; - + let prev = self.previous.take()?; self.previous = prev.next_in_preorder(Some(self.scope)); self.previous } diff --git a/components/style/driver.rs b/components/style/driver.rs index 8040757d7c4..07beb6d40d2 100644 --- a/components/style/driver.rs +++ b/components/style/driver.rs @@ -7,7 +7,7 @@ #![deny(missing_docs)] -use context::{StyleContext, ThreadLocalStyleContext}; +use context::{StyleContext, ThreadLocalStyleContext, TraversalStatistics}; use dom::{SendNode, TElement, TNode}; use parallel; 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 /// parallel traversal would parallelize it. If a thread pool is provided, we /// 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( traversal: &D, token: PreTraverseToken, pool: Option<&rayon::ThreadPool> -) +) -> (bool, Option) where E: TElement, D: DomTraversal, @@ -38,6 +42,8 @@ where token.traversal_root().expect("Should've ensured we needed to traverse"); 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 }; // 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 // depth for all the children. if pool.is_some() && discovered.len() > WORK_UNIT_MAX { + used_parallel = true; let pool = pool.unwrap(); maybe_tls = Some(ScopedTLS::>::new(pool)); let root_opaque = root.as_node().opaque(); @@ -108,9 +115,9 @@ where nodes_remaining_at_current_depth = discovered.len(); } } - - // Dump statistics to stdout if requested. - if dump_stats { + let mut maybe_stats = None; + // Accumulate statistics + if dump_stats || is_nightly { let mut aggregate = mem::replace(&mut context.thread_local.statistics, Default::default()); let parallel = maybe_tls.is_some(); @@ -123,9 +130,14 @@ where } }); } - aggregate.finish(traversal, parallel, start_time.unwrap()); - if aggregate.is_large_traversal() { - println!("{}", aggregate); + + // dump to stdout if requested + if dump_stats && aggregate.is_large_traversal() { + aggregate.finish(traversal, parallel, start_time.unwrap()); + println!("{}", aggregate); } + maybe_stats = Some(aggregate); } + + (used_parallel, maybe_stats) } diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs index 53740eb8974..d3f5e303f75 100644 --- a/components/style/gecko/data.rs +++ b/components/style/gecko/data.rs @@ -5,6 +5,7 @@ //! Data needed to style a Gecko document. use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; +use context::TraversalStatistics; use dom::TElement; use gecko_bindings::bindings::{self, RawServoStyleSet}; use gecko_bindings::structs::{RawGeckoPresContextOwned, ServoStyleSetSizes, ServoStyleSheet}; @@ -16,6 +17,7 @@ use media_queries::{Device, MediaList}; use properties::ComputedValues; use servo_arc::Arc; use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard}; +use std::sync::atomic::{AtomicUsize, Ordering}; use stylesheets::{StylesheetContents, StylesheetInDocument}; 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 /// itself. pub struct PerDocumentStyleDataImpl { /// Rule processor. 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 @@ -133,6 +164,9 @@ impl PerDocumentStyleData { PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl { 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 { /// Recreate the style data if the stylesheets have changed. pub fn flush_stylesheets( @@ -209,6 +258,15 @@ impl PerDocumentStyleDataImpl { pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) { 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) { + 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 { diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs index d4e2bf86851..090d2096d07 100644 --- a/components/style/gecko/generated/bindings.rs +++ b/components/style/gecko/generated/bindings.rs @@ -499,6 +499,8 @@ extern "C" { pub fn Servo_SelectorList_Drop ( ptr : RawServoSelectorListOwned , ) ; } extern "C" { 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" { pub fn Gecko_IsInDocument ( node : RawGeckoNodeBorrowed , ) -> bool ; } extern "C" { diff --git a/components/style/gecko/generated/structs.rs b/components/style/gecko/generated/structs.rs index a0cd5c5cbcd..2b89e95794c 100644 --- a/components/style/gecko/generated/structs.rs +++ b/components/style/gecko/generated/structs.rs @@ -1660,7 +1660,7 @@ pub type ServoStyleContextStrong = ::gecko_bindings::sugar::ownership::Strong<:: pub static mut nsDOMAttributeMap__cycleCollectorGlobal : root :: nsDOMAttributeMap_cycleCollection ; } # [ test ] fn bindgen_test_layout_nsDOMAttributeMap ( ) { assert_eq ! ( :: std :: mem :: size_of :: < nsDOMAttributeMap > ( ) , 80usize , concat ! ( "Size of: " , stringify ! ( nsDOMAttributeMap ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < nsDOMAttributeMap > ( ) , 8usize , concat ! ( "Alignment of " , stringify ! ( nsDOMAttributeMap ) ) ) ; } # [ repr ( C ) ] pub struct nsISMILAttr__bindgen_vtable ( :: std :: os :: raw :: c_void ) ; /// - # [ repr ( C ) ] # [ derive ( Debug ) ] pub struct nsISMILAttr { pub vtable_ : * const nsISMILAttr__bindgen_vtable , } # [ test ] fn bindgen_test_layout_nsISMILAttr ( ) { assert_eq ! ( :: std :: mem :: size_of :: < nsISMILAttr > ( ) , 8usize , concat ! ( "Size of: " , stringify ! ( nsISMILAttr ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < nsISMILAttr > ( ) , 8usize , concat ! ( "Alignment of " , stringify ! ( nsISMILAttr ) ) ) ; } pub const ELEMENT_SHARED_RESTYLE_BIT_1 : root :: _bindgen_ty_85 = 8388608 ; pub const ELEMENT_SHARED_RESTYLE_BIT_2 : root :: _bindgen_ty_85 = 16777216 ; pub const ELEMENT_SHARED_RESTYLE_BIT_3 : root :: _bindgen_ty_85 = 33554432 ; pub const ELEMENT_SHARED_RESTYLE_BIT_4 : root :: _bindgen_ty_85 = 67108864 ; pub const ELEMENT_SHARED_RESTYLE_BITS : root :: _bindgen_ty_85 = 125829120 ; pub const ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO : root :: _bindgen_ty_85 = 8388608 ; pub const ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO : root :: _bindgen_ty_85 = 16777216 ; pub const ELEMENT_HAS_SNAPSHOT : root :: _bindgen_ty_85 = 33554432 ; pub const ELEMENT_HANDLED_SNAPSHOT : root :: _bindgen_ty_85 = 67108864 ; pub const ELEMENT_HAS_PENDING_RESTYLE : root :: _bindgen_ty_85 = 8388608 ; pub const ELEMENT_IS_POTENTIAL_RESTYLE_ROOT : root :: _bindgen_ty_85 = 16777216 ; pub const ELEMENT_HAS_PENDING_ANIMATION_ONLY_RESTYLE : root :: _bindgen_ty_85 = 33554432 ; pub const ELEMENT_IS_POTENTIAL_ANIMATION_ONLY_RESTYLE_ROOT : root :: _bindgen_ty_85 = 67108864 ; pub const ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR : root :: _bindgen_ty_85 = 134217728 ; pub const ELEMENT_HAS_CHILD_WITH_LATER_SIBLINGS_HINT : root :: _bindgen_ty_85 = 268435456 ; pub const ELEMENT_PENDING_RESTYLE_FLAGS : root :: _bindgen_ty_85 = 41943040 ; pub const ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS : root :: _bindgen_ty_85 = 83886080 ; pub const ELEMENT_ALL_RESTYLE_FLAGS : root :: _bindgen_ty_85 = 260046848 ; pub const ELEMENT_TYPE_SPECIFIC_BITS_OFFSET : root :: _bindgen_ty_85 = 27 ; pub type _bindgen_ty_85 = :: std :: os :: raw :: c_uint ; # [ repr ( C ) ] # [ derive ( Debug , Copy ) ] pub struct ServoBundledURI { pub mURLString : * const u8 , pub mURLStringLength : u32 , pub mExtraData : * mut root :: mozilla :: URLExtraData , } # [ test ] fn bindgen_test_layout_ServoBundledURI ( ) { assert_eq ! ( :: std :: mem :: size_of :: < ServoBundledURI > ( ) , 24usize , concat ! ( "Size of: " , stringify ! ( ServoBundledURI ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < ServoBundledURI > ( ) , 8usize , concat ! ( "Alignment of " , stringify ! ( ServoBundledURI ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const ServoBundledURI ) ) . mURLString as * const _ as usize } , 0usize , concat ! ( "Alignment of field: " , stringify ! ( ServoBundledURI ) , "::" , stringify ! ( mURLString ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const ServoBundledURI ) ) . mURLStringLength as * const _ as usize } , 8usize , concat ! ( "Alignment of field: " , stringify ! ( ServoBundledURI ) , "::" , stringify ! ( mURLStringLength ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const ServoBundledURI ) ) . mExtraData as * const _ as usize } , 16usize , concat ! ( "Alignment of field: " , stringify ! ( ServoBundledURI ) , "::" , stringify ! ( mExtraData ) ) ) ; } impl Clone for ServoBundledURI { fn clone ( & self ) -> Self { * self } } # [ repr ( C ) ] # [ derive ( Debug , Copy ) ] pub struct FontSizePrefs { pub mDefaultVariableSize : root :: nscoord , pub mDefaultFixedSize : root :: nscoord , pub mDefaultSerifSize : root :: nscoord , pub mDefaultSansSerifSize : root :: nscoord , pub mDefaultMonospaceSize : root :: nscoord , pub mDefaultCursiveSize : root :: nscoord , pub mDefaultFantasySize : root :: nscoord , } # [ test ] fn bindgen_test_layout_FontSizePrefs ( ) { assert_eq ! ( :: std :: mem :: size_of :: < FontSizePrefs > ( ) , 28usize , concat ! ( "Size of: " , stringify ! ( FontSizePrefs ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < FontSizePrefs > ( ) , 4usize , concat ! ( "Alignment of " , stringify ! ( FontSizePrefs ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultVariableSize as * const _ as usize } , 0usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultVariableSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultFixedSize as * const _ as usize } , 4usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultFixedSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultSerifSize as * const _ as usize } , 8usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultSerifSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultSansSerifSize as * const _ as usize } , 12usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultSansSerifSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultMonospaceSize as * const _ as usize } , 16usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultMonospaceSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultCursiveSize as * const _ as usize } , 20usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultCursiveSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultFantasySize as * const _ as usize } , 24usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultFantasySize ) ) ) ; } impl Clone for FontSizePrefs { fn clone ( & self ) -> Self { * self } } # [ repr ( C ) ] # [ derive ( Debug , Copy ) ] pub struct GeckoFontMetrics { pub mChSize : root :: nscoord , pub mXSize : root :: nscoord , } # [ test ] fn bindgen_test_layout_GeckoFontMetrics ( ) { assert_eq ! ( :: std :: mem :: size_of :: < GeckoFontMetrics > ( ) , 8usize , concat ! ( "Size of: " , stringify ! ( GeckoFontMetrics ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < GeckoFontMetrics > ( ) , 4usize , concat ! ( "Alignment of " , stringify ! ( GeckoFontMetrics ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const GeckoFontMetrics ) ) . mChSize as * const _ as usize } , 0usize , concat ! ( "Alignment of field: " , stringify ! ( GeckoFontMetrics ) , "::" , stringify ! ( mChSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const GeckoFontMetrics ) ) . mXSize as * const _ as usize } , 4usize , concat ! ( "Alignment of field: " , stringify ! ( GeckoFontMetrics ) , "::" , stringify ! ( mXSize ) ) ) ; } impl Clone for GeckoFontMetrics { fn clone ( & self ) -> Self { * self } } pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_after : u32 = 65 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_before : u32 = 65 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_backdrop : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_cue : u32 = 36 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_firstLetter : u32 = 3 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_firstLine : u32 = 3 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozSelection : u32 = 2 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozFocusInner : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozFocusOuter : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozListBullet : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozListNumber : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozMathAnonymous : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberWrapper : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberText : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberSpinBox : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberSpinUp : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberSpinDown : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozProgressBar : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozRangeTrack : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozRangeProgress : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozRangeThumb : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozMeterBar : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozPlaceholder : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_placeholder : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozColorSwatch : u32 = 12 ; # [ repr ( C ) ] # [ derive ( Debug , Copy ) ] pub struct nsIDOMMediaList { pub _base : root :: nsISupports , } # [ repr ( C ) ] # [ derive ( Debug , Copy , Clone ) ] pub struct nsIDOMMediaList_COMTypeInfo { pub _address : u8 , } # [ test ] fn bindgen_test_layout_nsIDOMMediaList ( ) { assert_eq ! ( :: std :: mem :: size_of :: < nsIDOMMediaList > ( ) , 8usize , concat ! ( "Size of: " , stringify ! ( nsIDOMMediaList ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < nsIDOMMediaList > ( ) , 8usize , concat ! ( "Alignment of " , stringify ! ( nsIDOMMediaList ) ) ) ; } impl Clone for nsIDOMMediaList { fn clone ( & self ) -> Self { * self } } pub type nsCSSAnonBoxes_NonInheritingBase = u8 ; pub const nsCSSAnonBoxes_NonInheriting_oofPlaceholder : root :: nsCSSAnonBoxes_NonInheriting = 0 ; pub const nsCSSAnonBoxes_NonInheriting_horizontalFramesetBorder : root :: nsCSSAnonBoxes_NonInheriting = 1 ; pub const nsCSSAnonBoxes_NonInheriting_verticalFramesetBorder : root :: nsCSSAnonBoxes_NonInheriting = 2 ; pub const nsCSSAnonBoxes_NonInheriting_framesetBlank : root :: nsCSSAnonBoxes_NonInheriting = 3 ; pub const nsCSSAnonBoxes_NonInheriting_tableColGroup : root :: nsCSSAnonBoxes_NonInheriting = 4 ; pub const nsCSSAnonBoxes_NonInheriting_tableCol : root :: nsCSSAnonBoxes_NonInheriting = 5 ; pub const nsCSSAnonBoxes_NonInheriting_pageBreak : root :: nsCSSAnonBoxes_NonInheriting = 6 ; pub const nsCSSAnonBoxes_NonInheriting__Count : root :: nsCSSAnonBoxes_NonInheriting = 7 ; pub type nsCSSAnonBoxes_NonInheriting = root :: nsCSSAnonBoxes_NonInheritingBase ; + # [ repr ( C ) ] # [ derive ( Debug ) ] pub struct nsISMILAttr { pub vtable_ : * const nsISMILAttr__bindgen_vtable , } # [ test ] fn bindgen_test_layout_nsISMILAttr ( ) { assert_eq ! ( :: std :: mem :: size_of :: < nsISMILAttr > ( ) , 8usize , concat ! ( "Size of: " , stringify ! ( nsISMILAttr ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < nsISMILAttr > ( ) , 8usize , concat ! ( "Alignment of " , stringify ! ( nsISMILAttr ) ) ) ; } pub const ELEMENT_SHARED_RESTYLE_BIT_1 : root :: _bindgen_ty_85 = 8388608 ; pub const ELEMENT_SHARED_RESTYLE_BIT_2 : root :: _bindgen_ty_85 = 16777216 ; pub const ELEMENT_SHARED_RESTYLE_BIT_3 : root :: _bindgen_ty_85 = 33554432 ; pub const ELEMENT_SHARED_RESTYLE_BIT_4 : root :: _bindgen_ty_85 = 67108864 ; pub const ELEMENT_SHARED_RESTYLE_BITS : root :: _bindgen_ty_85 = 125829120 ; pub const ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO : root :: _bindgen_ty_85 = 8388608 ; pub const ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO : root :: _bindgen_ty_85 = 16777216 ; pub const ELEMENT_HAS_SNAPSHOT : root :: _bindgen_ty_85 = 33554432 ; pub const ELEMENT_HANDLED_SNAPSHOT : root :: _bindgen_ty_85 = 67108864 ; pub const ELEMENT_HAS_PENDING_RESTYLE : root :: _bindgen_ty_85 = 8388608 ; pub const ELEMENT_IS_POTENTIAL_RESTYLE_ROOT : root :: _bindgen_ty_85 = 16777216 ; pub const ELEMENT_HAS_PENDING_ANIMATION_ONLY_RESTYLE : root :: _bindgen_ty_85 = 33554432 ; pub const ELEMENT_IS_POTENTIAL_ANIMATION_ONLY_RESTYLE_ROOT : root :: _bindgen_ty_85 = 67108864 ; pub const ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR : root :: _bindgen_ty_85 = 134217728 ; pub const ELEMENT_HAS_CHILD_WITH_LATER_SIBLINGS_HINT : root :: _bindgen_ty_85 = 268435456 ; pub const ELEMENT_PENDING_RESTYLE_FLAGS : root :: _bindgen_ty_85 = 41943040 ; pub const ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS : root :: _bindgen_ty_85 = 83886080 ; pub const ELEMENT_ALL_RESTYLE_FLAGS : root :: _bindgen_ty_85 = 260046848 ; pub const ELEMENT_TYPE_SPECIFIC_BITS_OFFSET : root :: _bindgen_ty_85 = 27 ; pub type _bindgen_ty_85 = :: std :: os :: raw :: c_uint ; pub const GECKO_IS_NIGHTLY : bool = true ; # [ repr ( C ) ] # [ derive ( Debug , Copy ) ] pub struct ServoBundledURI { pub mURLString : * const u8 , pub mURLStringLength : u32 , pub mExtraData : * mut root :: mozilla :: URLExtraData , } # [ test ] fn bindgen_test_layout_ServoBundledURI ( ) { assert_eq ! ( :: std :: mem :: size_of :: < ServoBundledURI > ( ) , 24usize , concat ! ( "Size of: " , stringify ! ( ServoBundledURI ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < ServoBundledURI > ( ) , 8usize , concat ! ( "Alignment of " , stringify ! ( ServoBundledURI ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const ServoBundledURI ) ) . mURLString as * const _ as usize } , 0usize , concat ! ( "Alignment of field: " , stringify ! ( ServoBundledURI ) , "::" , stringify ! ( mURLString ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const ServoBundledURI ) ) . mURLStringLength as * const _ as usize } , 8usize , concat ! ( "Alignment of field: " , stringify ! ( ServoBundledURI ) , "::" , stringify ! ( mURLStringLength ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const ServoBundledURI ) ) . mExtraData as * const _ as usize } , 16usize , concat ! ( "Alignment of field: " , stringify ! ( ServoBundledURI ) , "::" , stringify ! ( mExtraData ) ) ) ; } impl Clone for ServoBundledURI { fn clone ( & self ) -> Self { * self } } # [ repr ( C ) ] # [ derive ( Debug , Copy ) ] pub struct FontSizePrefs { pub mDefaultVariableSize : root :: nscoord , pub mDefaultFixedSize : root :: nscoord , pub mDefaultSerifSize : root :: nscoord , pub mDefaultSansSerifSize : root :: nscoord , pub mDefaultMonospaceSize : root :: nscoord , pub mDefaultCursiveSize : root :: nscoord , pub mDefaultFantasySize : root :: nscoord , } # [ test ] fn bindgen_test_layout_FontSizePrefs ( ) { assert_eq ! ( :: std :: mem :: size_of :: < FontSizePrefs > ( ) , 28usize , concat ! ( "Size of: " , stringify ! ( FontSizePrefs ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < FontSizePrefs > ( ) , 4usize , concat ! ( "Alignment of " , stringify ! ( FontSizePrefs ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultVariableSize as * const _ as usize } , 0usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultVariableSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultFixedSize as * const _ as usize } , 4usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultFixedSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultSerifSize as * const _ as usize } , 8usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultSerifSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultSansSerifSize as * const _ as usize } , 12usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultSansSerifSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultMonospaceSize as * const _ as usize } , 16usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultMonospaceSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultCursiveSize as * const _ as usize } , 20usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultCursiveSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const FontSizePrefs ) ) . mDefaultFantasySize as * const _ as usize } , 24usize , concat ! ( "Alignment of field: " , stringify ! ( FontSizePrefs ) , "::" , stringify ! ( mDefaultFantasySize ) ) ) ; } impl Clone for FontSizePrefs { fn clone ( & self ) -> Self { * self } } # [ repr ( C ) ] # [ derive ( Debug , Copy ) ] pub struct GeckoFontMetrics { pub mChSize : root :: nscoord , pub mXSize : root :: nscoord , } # [ test ] fn bindgen_test_layout_GeckoFontMetrics ( ) { assert_eq ! ( :: std :: mem :: size_of :: < GeckoFontMetrics > ( ) , 8usize , concat ! ( "Size of: " , stringify ! ( GeckoFontMetrics ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < GeckoFontMetrics > ( ) , 4usize , concat ! ( "Alignment of " , stringify ! ( GeckoFontMetrics ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const GeckoFontMetrics ) ) . mChSize as * const _ as usize } , 0usize , concat ! ( "Alignment of field: " , stringify ! ( GeckoFontMetrics ) , "::" , stringify ! ( mChSize ) ) ) ; assert_eq ! ( unsafe { & ( * ( 0 as * const GeckoFontMetrics ) ) . mXSize as * const _ as usize } , 4usize , concat ! ( "Alignment of field: " , stringify ! ( GeckoFontMetrics ) , "::" , stringify ! ( mXSize ) ) ) ; } impl Clone for GeckoFontMetrics { fn clone ( & self ) -> Self { * self } } pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_after : u32 = 65 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_before : u32 = 65 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_backdrop : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_cue : u32 = 36 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_firstLetter : u32 = 3 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_firstLine : u32 = 3 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozSelection : u32 = 2 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozFocusInner : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozFocusOuter : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozListBullet : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozListNumber : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozMathAnonymous : u32 = 0 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberWrapper : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberText : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberSpinBox : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberSpinUp : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozNumberSpinDown : u32 = 24 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozProgressBar : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozRangeTrack : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozRangeProgress : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozRangeThumb : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozMeterBar : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozPlaceholder : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_placeholder : u32 = 8 ; pub const SERVO_CSS_PSEUDO_ELEMENT_FLAGS_mozColorSwatch : u32 = 12 ; # [ repr ( C ) ] # [ derive ( Debug , Copy ) ] pub struct nsIDOMMediaList { pub _base : root :: nsISupports , } # [ repr ( C ) ] # [ derive ( Debug , Copy , Clone ) ] pub struct nsIDOMMediaList_COMTypeInfo { pub _address : u8 , } # [ test ] fn bindgen_test_layout_nsIDOMMediaList ( ) { assert_eq ! ( :: std :: mem :: size_of :: < nsIDOMMediaList > ( ) , 8usize , concat ! ( "Size of: " , stringify ! ( nsIDOMMediaList ) ) ) ; assert_eq ! ( :: std :: mem :: align_of :: < nsIDOMMediaList > ( ) , 8usize , concat ! ( "Alignment of " , stringify ! ( nsIDOMMediaList ) ) ) ; } impl Clone for nsIDOMMediaList { fn clone ( & self ) -> Self { * self } } pub type nsCSSAnonBoxes_NonInheritingBase = u8 ; pub const nsCSSAnonBoxes_NonInheriting_oofPlaceholder : root :: nsCSSAnonBoxes_NonInheriting = 0 ; pub const nsCSSAnonBoxes_NonInheriting_horizontalFramesetBorder : root :: nsCSSAnonBoxes_NonInheriting = 1 ; pub const nsCSSAnonBoxes_NonInheriting_verticalFramesetBorder : root :: nsCSSAnonBoxes_NonInheriting = 2 ; pub const nsCSSAnonBoxes_NonInheriting_framesetBlank : root :: nsCSSAnonBoxes_NonInheriting = 3 ; pub const nsCSSAnonBoxes_NonInheriting_tableColGroup : root :: nsCSSAnonBoxes_NonInheriting = 4 ; pub const nsCSSAnonBoxes_NonInheriting_tableCol : root :: nsCSSAnonBoxes_NonInheriting = 5 ; pub const nsCSSAnonBoxes_NonInheriting_pageBreak : root :: nsCSSAnonBoxes_NonInheriting = 6 ; pub const nsCSSAnonBoxes_NonInheriting__Count : root :: nsCSSAnonBoxes_NonInheriting = 7 ; pub type nsCSSAnonBoxes_NonInheriting = root :: nsCSSAnonBoxes_NonInheritingBase ; /// templated hashtable class maps keys to interface pointers. /// See nsBaseHashtable for complete declaration. /// @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index 827e832ebcd..0dec6ed479a 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -9,9 +9,9 @@ use element_state::{DocumentState, ElementState}; use gecko_bindings::structs::CSSPseudoClassType; use gecko_bindings::structs::RawServoSelectorList; use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI}; -use selector_parser::{Direction, SelectorParser, PseudoElementCascadeType}; +use selector_parser::{Direction, SelectorParser}; use selectors::SelectorList; -use selectors::parser::{Selector, SelectorMethods, SelectorParseErrorKind}; +use selectors::parser::{self as selector_parser, Selector, SelectorMethods, SelectorParseErrorKind}; use selectors::visitor::SelectorVisitor; use std::fmt; use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; @@ -333,9 +333,10 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { type Impl = SelectorImpl; 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) || - name.starts_with("-moz-tree-") // tree pseudo-elements + name.starts_with("-moz-tree-") } fn parse_non_ts_pseudo_class( @@ -399,16 +400,12 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { NonTSPseudoClass::Dir(Box::new(direction)) }, "-moz-any" => { - let selectors = parser.parse_comma_separated(|input| { - Selector::parse(self, input) - })?; - // Selectors inside `:-moz-any` may not include combinators. - 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()) + NonTSPseudoClass::MozAny( + selector_parser::parse_compound_selector_list( + self, + parser, + )? + ) } _ => return Err(parser.new_custom_error( SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone()) @@ -431,6 +428,8 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { ) -> Result> { PseudoElement::from_slice(&name, self.in_user_agent_stylesheet()) .or_else(|| { + // FIXME: -moz-tree check should probably be + // ascii-case-insensitive. if name.starts_with("-moz-tree-") { PseudoElement::tree_pseudo_element(&name, Box::new([])) } else { @@ -445,9 +444,10 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { name: CowRcStr<'i>, parser: &mut Parser<'i, 't>, ) -> Result> { + // FIXME: -moz-tree check should probably be ascii-case-insensitive. if name.starts_with("-moz-tree-") { - // Tree pseudo-elements can have zero or more arguments, - // separated by either comma or space. + // Tree pseudo-elements can have zero or more arguments, separated + // by either comma or space. let mut args = Vec::new(); loop { let location = parser.current_source_location(); @@ -477,12 +477,6 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { } 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 /// `fun` on it. #[inline] diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 6834bbe8fcd..d399109fee8 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -428,10 +428,7 @@ impl<'lb> GeckoXBLBinding<'lb> { if !binding.anon_content().is_null() { return Some(binding); } - binding = match binding.base_binding() { - Some(b) => b, - None => return None, - }; + binding = binding.base_binding()?; } } @@ -1006,20 +1003,14 @@ impl<'le> TElement for GeckoElement<'le> { fn closest_non_native_anonymous_ancestor(&self) -> Option { debug_assert!(self.is_native_anonymous()); - let mut parent = match self.traversal_parent() { - Some(e) => e, - None => return None, - }; + let mut parent = self.traversal_parent()?; loop { if !parent.is_native_anonymous() { return Some(parent); } - parent = match parent.traversal_parent() { - Some(p) => p, - None => return None, - }; + parent = parent.traversal_parent()?; } } @@ -1054,16 +1045,10 @@ impl<'le> TElement for GeckoElement<'le> { fn get_smil_override(&self) -> Option>> { unsafe { - let slots = match self.get_extended_slots() { - Some(s) => s, - None => return None, - }; + let slots = self.get_extended_slots()?; let base_declaration: &structs::DeclarationBlock = - match slots.mSMILOverrideStyleDeclaration.mRawPtr.as_ref() { - Some(decl) => decl, - None => return None, - }; + slots.mSMILOverrideStyleDeclaration.mRawPtr.as_ref()?; assert_eq!(base_declaration.mType, structs::StyleBackendType_Servo); let declaration: &structs::ServoDeclarationBlock = @@ -1074,11 +1059,7 @@ impl<'le> TElement for GeckoElement<'le> { base_declaration as *const structs::DeclarationBlock ); - let raw: &structs::RawServoDeclarationBlock = - match declaration.mRaw.mRawPtr.as_ref() { - Some(decl) => decl, - None => return None, - }; + let raw: &structs::RawServoDeclarationBlock = declaration.mRaw.mRawPtr.as_ref()?; Some(Locked::::as_arc( &*(&raw as *const &structs::RawServoDeclarationBlock) diff --git a/components/style/invalidation/element/element_wrapper.rs b/components/style/invalidation/element/element_wrapper.rs index e05eaa468f2..4ef5f5cad86 100644 --- a/components/style/invalidation/element/element_wrapper.rs +++ b/components/style/invalidation/element/element_wrapper.rs @@ -127,10 +127,7 @@ impl<'a, E> ElementWrapper<'a, E> if lang.is_some() { return lang; } - match current.parent_element() { - Some(parent) => current = parent, - None => return None, - } + current = current.parent_element()?; } } } diff --git a/components/style/parser.rs b/components/style/parser.rs index 1b1d4151600..df8551bff3b 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -149,8 +149,10 @@ pub trait Parse : Sized { /// Parse a value of this type. /// /// Returns an error on failure. - fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result>; + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result>; } impl Parse for Vec diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 788d39c4b48..0341edfae82 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -140,14 +140,9 @@ impl<'a> Iterator for NormalDeclarationIterator<'a> { fn next(&mut self) -> Option { loop { - let next = self.0.iter.next(); - match next { - Some((decl, importance)) => { - if !importance { - return Some(decl); - } - }, - None => return None, + let (decl, importance) = self.0.iter.next()?; + if !importance { + return Some(decl); } } } @@ -171,7 +166,7 @@ impl<'a, 'cx, 'cx_a:'cx> AnimationValueIterator<'a, 'cx, 'cx_a> { declarations: &'a PropertyDeclarationBlock, context: &'cx mut Context<'cx_a>, 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 { iter: declarations.normal_declaration_iter(), @@ -187,11 +182,7 @@ impl<'a, 'cx, 'cx_a:'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> { #[inline] fn next(&mut self) -> Option { loop { - let next = self.iter.next(); - let decl = match next { - Some(decl) => decl, - None => return None, - }; + let decl = self.iter.next()?; let animation = AnimationValue::from_declaration( decl, diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 08516ed928b..45fe22f3b6c 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -61,6 +61,7 @@ use values::{self, Auto, CustomIdent, Either, KeyframesName, None_}; use values::computed::{NonNegativeLength, ToComputedValue, Percentage}; use values::computed::font::{FontSize, SingleFontFamily}; use values::computed::effects::{BoxShadow, Filter, SimpleShadow}; +use values::computed::outline::OutlineStyle; use computed_values::border_style; pub mod style_structs { @@ -2348,10 +2349,10 @@ fn static_assert() { // cast + static_asserts let result = match v { % 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")}, % endfor - Either::First(Auto) => + OutlineStyle::Auto => structs::${border_style_keyword.gecko_constant('auto')} ${border_style_keyword.maybe_cast("u8")}, }; ${set_gecko_property("mOutlineStyle", "result")} @@ -2378,10 +2379,10 @@ fn static_assert() { match ${get_gecko_property("mOutlineStyle")} ${border_style_keyword.maybe_cast("u32")} { % for value in border_style_keyword.values_for('gecko'): 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 - 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: x => panic!("Found unexpected value in style struct for outline_style property: {:?}", x), % endif @@ -3618,11 +3619,11 @@ fn static_assert() { if self.gecko.mWillChange.len() == 0 { T::Auto } else { - T::AnimateableFeatures( - self.gecko.mWillChange.iter().map(|gecko_atom| { - CustomIdent((gecko_atom.mRawPtr as *mut nsAtom).into()) - }).collect() - ) + let custom_idents: Vec = self.gecko.mWillChange.iter().map(|gecko_atom| { + CustomIdent((gecko_atom.mRawPtr as *mut nsAtom).into()) + }).collect(); + + T::AnimateableFeatures(custom_idents.into_boxed_slice()) } } @@ -4228,8 +4229,11 @@ fn static_assert() { let ref gecko_quote_values = *self.gecko.mQuotes.mRawPtr; longhands::quotes::computed_value::T( 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::>().into_boxed_slice() ) } } diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 8a035c8c8b9..8839a58cda8 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -262,7 +262,7 @@ impl AnimatedProperty { % for prop in data.longhands: % if prop.animatable: 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": let value = if progress < 0.5 { from.clone() } else { to.clone() }; % else: @@ -2833,7 +2833,7 @@ impl ComputeSquaredDistance for AnimatedFilterList { /// /// 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")] pub fn compare_property_priority(a: &PropertyId, b: &PropertyId) -> cmp::Ordering { match (a.as_shorthand(), b.as_shorthand()) { diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 2e1c1d271d7..694566ec62f 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -881,62 +881,14 @@ ${helpers.single_keyword("-moz-orient", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-orient)", animation_value_type="discrete")} -<%helpers:longhand name="will-change" products="gecko" animation_value_type="discrete" - spec="https://drafts.csswg.org/css-will-change/#will-change"> - use std::fmt; - use style_traits::ToCss; - use values::CustomIdent; - - pub mod computed_value { - pub use super::SpecifiedValue as T; - } - - #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)] - pub enum SpecifiedValue { - Auto, - AnimateableFeatures(Vec), - } - - impl ToCss for SpecifiedValue { - fn to_css(&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 | # - pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { - 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.predefined_type( + "will-change", + "WillChange", + "computed::WillChange::auto()", + products="gecko", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-will-change/#will-change" +)} ${helpers.predefined_type( "shape-image-threshold", "Opacity", "0.0", diff --git a/components/style/properties/longhand/list.mako.rs b/components/style/properties/longhand/list.mako.rs index 4f3442da376..149bed1e07a 100644 --- a/components/style/properties/longhand/list.mako.rs +++ b/components/style/properties/longhand/list.mako.rs @@ -95,116 +95,19 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu % endif -<%helpers:longhand name="list-style-image" animation_value_type="discrete" - boxed="${product == 'gecko'}" - spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image"> - use values::specified::UrlOrNone; - pub use self::computed_value::T as SpecifiedValue; +${helpers.predefined_type("list-style-image", + "ListStyleImage", + initial_value="specified::ListStyleImage::none()", + initial_specified_value="specified::ListStyleImage::none()", + animation_value_type="discrete", + boxed=product == "gecko", + spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image")} - pub mod computed_value { - use values::specified::UrlOrNone; - - #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] - pub struct T(pub UrlOrNone); - - // 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> { - % 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 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(&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> { - 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.predefined_type("quotes", + "Quotes", + "computed::Quotes::get_initial_value()", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-content/#propdef-quotes")} ${helpers.predefined_type("-moz-image-region", "ClipRectOrAuto", diff --git a/components/style/properties/longhand/outline.mako.rs b/components/style/properties/longhand/outline.mako.rs index c35f42176f7..9446745ec3e 100644 --- a/components/style/properties/longhand/outline.mako.rs +++ b/components/style/properties/longhand/outline.mako.rs @@ -20,51 +20,14 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-ui/#propdef-outline-color", )} -<%helpers:longhand name="outline-style" animation_value_type="discrete" - spec="https://drafts.csswg.org/css-ui/#propdef-outline-style"> - use values::specified::BorderStyle; - - pub type SpecifiedValue = Either; - - impl SpecifiedValue { - #[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::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.predefined_type( + "outline-style", + "OutlineStyle", + "computed::OutlineStyle::none()", + initial_specified_value="specified::OutlineStyle::none()", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-ui/#propdef-outline-style", +)} ${helpers.predefined_type("outline-width", "BorderSideWidth", diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index 3692ddb0ac0..8d04c8eba8b 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -257,7 +257,6 @@ ${helpers.predefined_type("object-position", "computed::NonNegativeLengthOrPercentage::zero()", spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-gap" % kind, animation_value_type="NonNegativeLengthOrPercentage", - gecko_pref="layout.css.grid.enabled", products="gecko")} % for range in ["start", "end"]: @@ -267,7 +266,6 @@ ${helpers.predefined_type("object-position", animation_value_type="discrete", spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-%s" % (kind, range), products="gecko", - gecko_pref="layout.css.grid.enabled", boxed=True)} % endfor @@ -279,7 +277,6 @@ ${helpers.predefined_type("object-position", animation_value_type="discrete", spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-%ss" % kind, products="gecko", - gecko_pref="layout.css.grid.enabled", boxed=True)} ${helpers.predefined_type("grid-template-%ss" % kind, @@ -288,7 +285,6 @@ ${helpers.predefined_type("object-position", products="gecko", spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-%ss" % kind, boxed=True, - gecko_pref="layout.css.grid.enabled", animation_value_type="discrete")} % endfor @@ -298,7 +294,6 @@ ${helpers.predefined_type("grid-auto-flow", initial_value="computed::GridAutoFlow::row()", products="gecko", animation_value_type="discrete", - gecko_pref="layout.css.grid.enabled", spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-flow")} ${helpers.predefined_type("grid-template-areas", @@ -306,6 +301,5 @@ ${helpers.predefined_type("grid-template-areas", initial_value="computed::GridTemplateAreas::none()", products="gecko", animation_value_type="discrete", - gecko_pref="layout.css.grid.enabled", boxed=True, spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-areas")} diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 4c05a1541f4..bdabec78fe3 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -850,11 +850,13 @@ impl ShorthandId { /// Finds and returns an appendable value for the given declarations. /// /// Returns the optional appendable value. - pub fn get_shorthand_appendable_value<'a, I>(self, - declarations: I) - -> Option> - where I: IntoIterator, - I::IntoIter: Clone, + pub fn get_shorthand_appendable_value<'a, I>( + self, + declarations: I, + ) -> Option> + where + I: IntoIterator, + I::IntoIter: Clone, { let declarations = declarations.into_iter(); @@ -862,10 +864,7 @@ impl ShorthandId { let mut declarations2 = declarations.clone(); let mut declarations3 = declarations.clone(); - let first_declaration = match declarations2.next() { - Some(declaration) => declaration, - None => return None - }; + let first_declaration = declarations2.next()?; // https://drafts.csswg.org/css-variables/#variables-in-shorthands if let Some(css) = first_declaration.with_variables_from_shorthand(self) { diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 36f2db78236..0ee37c1a9df 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -103,7 +103,6 @@ <%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" products="gecko"> use properties::longhands::{grid_row_gap, grid_column_gap}; @@ -135,7 +134,6 @@ % for kind in ["row", "column"]: <%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}" products="gecko"> use values::specified::GridLine; @@ -175,7 +173,6 @@ % endfor <%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" spec="https://drafts.csswg.org/css-grid/#propdef-grid-area" products="gecko"> @@ -241,7 +238,6 @@ <%helpers:shorthand name="grid-template" - gecko_pref="layout.css.grid.enabled" sub_properties="grid-template-rows grid-template-columns grid-template-areas" spec="https://drafts.csswg.org/css-grid/#propdef-grid-template" products="gecko"> @@ -463,7 +459,6 @@ <%helpers:shorthand name="grid" - gecko_pref="layout.css.grid.enabled" sub_properties="grid-template-rows grid-template-columns grid-template-areas grid-auto-rows grid-auto-columns grid-auto-flow" spec="https://drafts.csswg.org/css-grid/#propdef-grid" diff --git a/components/style/rule_cache.rs b/components/style/rule_cache.rs index be0bcc43c3b..9c0ad5ea495 100644 --- a/components/style/rule_cache.rs +++ b/components/style/rule_cache.rs @@ -102,20 +102,16 @@ impl RuleCache { return None; } - let rules = match builder_with_early_props.rules { - Some(ref rules) => rules, - None => return None, - }; + let rules = builder_with_early_props.rules.as_ref()?; + let cached_values = self.map.get(rules)?; - self.map.get(rules).and_then(|cached_values| { - for &(ref conditions, ref values) in cached_values.iter() { - if conditions.matches(builder_with_early_props) { - debug!("Using cached reset style with conditions {:?}", conditions); - return Some(&**values) - } + for &(ref conditions, ref values) in cached_values.iter() { + if conditions.matches(builder_with_early_props) { + debug!("Using cached reset style with conditions {:?}", conditions); + return Some(&**values) } - None - }) + } + None } /// Inserts a node into the rules cache if possible. diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index fa76654aa4a..a06de17734e 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -547,12 +547,6 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { } 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 /// `fun` on it. #[inline] diff --git a/components/style/style_resolver.rs b/components/style/style_resolver.rs index dea014924d3..448fdca3be1 100644 --- a/components/style/style_resolver.rs +++ b/components/style/style_resolver.rs @@ -376,11 +376,7 @@ where originating_element_style.style(), pseudo, VisitedHandlingMode::AllLinksUnvisited - ); - let rules = match rules { - Some(rules) => rules, - None => return None, - }; + )?; let mut visited_rules = None; if originating_element_style.style().visited_style().is_some() { diff --git a/components/style/stylesheet_set.rs b/components/style/stylesheet_set.rs index fcecf46947a..f9e38f44152 100644 --- a/components/style/stylesheet_set.rs +++ b/components/style/stylesheet_set.rs @@ -80,10 +80,7 @@ where fn next(&mut self) -> Option { loop { if self.current.is_none() { - let next_origin = match self.origins.next() { - Some(o) => o, - None => return None, - }; + let next_origin = self.origins.next()?; self.current = Some((next_origin, self.collections.borrow_for_origin(&next_origin).iter())); @@ -238,10 +235,7 @@ where use std::mem; loop { - let potential_sheet = match self.iter.next() { - Some(s) => s, - None => return None, - }; + let potential_sheet = self.iter.next()?; let dirty = mem::replace(&mut potential_sheet.dirty, false); if dirty { diff --git a/components/style/stylesheets/origin.rs b/components/style/stylesheets/origin.rs index 5defc2a3db2..97ce0fb4b82 100644 --- a/components/style/stylesheets/origin.rs +++ b/components/style/stylesheets/origin.rs @@ -89,10 +89,7 @@ impl Iterator for OriginSetIterator { fn next(&mut self) -> Option { loop { - let origin = match Origin::from_index(self.cur) { - Some(origin) => origin, - None => return None, - }; + let origin = Origin::from_index(self.cur)?; self.cur += 1; @@ -184,10 +181,7 @@ impl<'a, T> Iterator for PerOriginIter<'a, T> where T: 'a { type Item = (&'a T, Origin); fn next(&mut self) -> Option { - let origin = match Origin::from_index(self.cur) { - Some(origin) => origin, - None => return None, - }; + let origin = Origin::from_index(self.cur)?; 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); fn next(&mut self) -> Option { - let origin = match Origin::from_index(self.cur) { - Some(origin) => origin, - None => return None, - }; + let origin = Origin::from_index(self.cur)?; self.cur += 1; diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 99f40de90c5..1cf306d123d 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -196,11 +196,7 @@ impl<'a> Iterator for DocumentCascadeDataIter<'a> { type Item = (&'a CascadeData, Origin); fn next(&mut self) -> Option { - let (_, origin) = match self.iter.next() { - Some(o) => o, - None => return None, - }; - + let (_, origin) = self.iter.next()?; Some((self.cascade_data.borrow_for_origin(origin), origin)) } } @@ -670,7 +666,7 @@ impl Stylist { parent, cascade_flags, font_metrics, - &rule_node + rule_node ) } @@ -683,37 +679,19 @@ impl Stylist { parent: Option<&ComputedValues>, cascade_flags: CascadeFlags, font_metrics: &FontMetricsProvider, - rule_node: &StrongRuleNode + rule_node: StrongRuleNode ) -> Arc { - // NOTE(emilio): We skip calculating the proper layout parent style - // here. - // - // 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 - //
. 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, + self.compute_pseudo_element_style_with_inputs( + &CascadeInputs { + rules: Some(rule_node), + visited_rules: None, + }, + pseudo, guards, parent, - parent, - parent, - None, font_metrics, cascade_flags, - self.quirks_mode, - /* rule_cache = */ None, - &mut Default::default(), - ) + ).unwrap() } /// Returns the rule node for given precomputed pseudo-element. @@ -839,8 +817,9 @@ impl Stylist { &cascade_inputs, pseudo, guards, - parent_style, + Some(parent_style), font_metrics, + CascadeFlags::empty(), ) } @@ -853,8 +832,9 @@ impl Stylist { inputs: &CascadeInputs, pseudo: &PseudoElement, guards: &StylesheetGuards, - parent_style: &ComputedValues, - font_metrics: &FontMetricsProvider + parent_style: Option<&ComputedValues>, + font_metrics: &FontMetricsProvider, + cascade_flags: CascadeFlags, ) -> Option> { // We may have only visited rules in cases when we are actually // resolving, not probing, pseudo-element style. @@ -867,6 +847,13 @@ impl Stylist { // pseudos other than before and after, so it's probably ok. // // (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 + //
. 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( inputs, Some(pseudo), @@ -875,7 +862,7 @@ impl Stylist { parent_style, parent_style, font_metrics, - CascadeFlags::empty(), + cascade_flags, )) } @@ -899,15 +886,18 @@ impl Stylist { inputs: &CascadeInputs, pseudo: Option<&PseudoElement>, guards: &StylesheetGuards, - parent_style: &ComputedValues, - parent_style_ignoring_first_line: &ComputedValues, - layout_parent_style: &ComputedValues, + parent_style: Option<&ComputedValues>, + parent_style_ignoring_first_line: Option<&ComputedValues>, + layout_parent_style: Option<&ComputedValues>, font_metrics: &FontMetricsProvider, cascade_flags: CascadeFlags ) -> Arc { // We need to compute visited values if we have visited rules or if our // 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, // or neither (e.g. if it's a text style it may have neither). So // 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 // style as our parent. 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 = - 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.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, pseudo, rule_node, guards, - Some(inherited_style), - Some(inherited_style_ignoring_first_line), - Some(layout_parent_style_for_visited), + inherited_style, + inherited_style_ignoring_first_line, + layout_parent_style_for_visited, None, font_metrics, cascade_flags | CascadeFlags::VISITED_DEPENDENT_ONLY, self.quirks_mode, /* rule_cache = */ None, &mut Default::default(), - )) - } else { - None - }; + )); + } // 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. @@ -966,9 +960,9 @@ impl Stylist { pseudo, rules, guards, - Some(parent_style), - Some(parent_style_ignoring_first_line), - Some(layout_parent_style), + parent_style, + parent_style_ignoring_first_line, + layout_parent_style, visited_values, font_metrics, cascade_flags, @@ -1232,7 +1226,10 @@ impl Stylist { debug!("Determining if style is shareable: pseudo: {}", 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. 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()) // // 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. if let Some(map) = self.cascade_data.user.borrow_for_pseudo(pseudo_element) { map.get_all_matching_rules( @@ -1315,24 +1312,20 @@ impl Stylist { } }); - if rule_hash_target.matches_user_and_author_rules() && !only_default_rules { - // Gecko skips author normal rules if cutting off inheritance. - // See nsStyleSet::FileRules(). - if !cut_off_inheritance { - // Step 3c: Author normal rules. - if let Some(map) = self.cascade_data.author.borrow_for_pseudo(pseudo_element) { - map.get_all_matching_rules( - element, - &rule_hash_target, - applicable_declarations, - context, - self.quirks_mode, - flags_setter, - CascadeLevel::AuthorNormal - ); - } - } else { - debug!("skipping author normal rules due to cut off inheritance"); + if matches_user_and_author_rules && !only_default_rules && + !cut_off_inheritance + { + // Step 3c: Author normal rules. + if let Some(map) = self.cascade_data.author.borrow_for_pseudo(pseudo_element) { + map.get_all_matching_rules( + element, + &rule_hash_target, + applicable_declarations, + context, + self.quirks_mode, + flags_setter, + CascadeLevel::AuthorNormal + ); } } else { debug!("skipping author normal rules"); diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs index 565295b2c31..f7100bf77c8 100644 --- a/components/style/values/animated/mod.rs +++ b/components/style/values/animated/mod.rs @@ -48,15 +48,15 @@ pub trait Animate: Sized { /// An animation procedure. /// -/// +/// #[allow(missing_docs)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum Procedure { - /// + /// Interpolate { progress: f64 }, - /// + /// Add, - /// + /// Accumulate { count: u64 }, } diff --git a/components/style/values/computed/box.rs b/components/style/values/computed/box.rs index e43fbd61569..989c96174f0 100644 --- a/components/style/values/computed/box.rs +++ b/components/style/values/computed/box.rs @@ -9,7 +9,8 @@ use values::computed::length::LengthOrPercentage; use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; 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. pub type VerticalAlign = GenericVerticalAlign; diff --git a/components/style/values/computed/list.rs b/components/style/values/computed/list.rs new file mode 100644 index 00000000000..0e248797055 --- /dev/null +++ b/components/style/values/computed/list.rs @@ -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()) + } +} diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index a79f9990cd8..16fe42adc15 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -41,7 +41,7 @@ pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, Font pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings}; pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang}; 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::effects::{BoxShadow, Filter, SimpleShadow}; 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::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength}; 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::position::{Position, GridAutoFlow, GridTemplateAreas}; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth}; @@ -79,6 +81,8 @@ pub mod image; #[cfg(feature = "gecko")] pub mod gecko; pub mod length; +pub mod list; +pub mod outline; pub mod percentage; pub mod position; pub mod rect; @@ -397,6 +401,7 @@ trivial_to_computed_value!(BorderStyle); trivial_to_computed_value!(Cursor); trivial_to_computed_value!(Namespace); trivial_to_computed_value!(String); +trivial_to_computed_value!(Box); /// A `` value. pub type Number = CSSFloat; diff --git a/components/style/values/computed/outline.rs b/components/style/values/computed/outline.rs new file mode 100644 index 00000000000..b3fcaee40e6 --- /dev/null +++ b/components/style/values/computed/outline.rs @@ -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; diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index bd0dc82507f..95e1f1d500e 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -59,12 +59,16 @@ where } if let Some(ref i) = self.line_num { - dest.write_str(" ")?; + if self.is_span { + dest.write_str(" ")?; + } i.to_css(dest)?; } 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)?; } diff --git a/components/style/values/specified/background.rs b/components/style/values/specified/background.rs index 52383deb460..2420825959c 100644 --- a/components/style/values/specified/background.rs +++ b/components/style/values/specified/background.rs @@ -46,11 +46,13 @@ impl BackgroundSize { } /// One of the keywords for `background-repeat`. -define_css_keyword_enum! { RepeatKeyword: - "repeat" => Repeat, - "space" => Space, - "round" => Round, - "no-repeat" => NoRepeat +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] +#[allow(missing_docs)] +pub enum RepeatKeyword { + Repeat, + Space, + Round, + NoRepeat, } /// The specified value for the `background-repeat` property. diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index 247eb7a16a9..29f699d2c60 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -9,6 +9,7 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; use std::fmt; use style_traits::{ParseError, ToCss}; +use values::CustomIdent; use values::KeyframesName; use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; use values::generics::box_::VerticalAlign as GenericVerticalAlign; @@ -130,3 +131,49 @@ define_css_keyword_enum! { OverflowClipBox: "content-box" => ContentBox, } 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 +/// +/// +pub enum WillChange { + /// Expresses no particular intent + Auto, + #[css(comma, iterable)] + /// + 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 | # + fn parse<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't> + ) -> Result> { + 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())) + } +} diff --git a/components/style/values/specified/list.rs b/components/style/values/specified/list.rs new file mode 100644 index 00000000000..7f3ae50eaad --- /dev/null +++ b/components/style/values/specified/list.rs @@ -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> { + #[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, Box)]>); + +impl ToCss for Quotes { + fn to_css(&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> { + 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)) + } + } +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index cc53fc48070..c16d12eb6c0 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -35,7 +35,7 @@ pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, Font pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings}; pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang}; 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::effects::{BoxShadow, Filter, SimpleShadow}; 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::{NoCalcLength, ViewportPercentageLength}; pub use self::length::NonNegativeLengthOrPercentage; +pub use self::list::{ListStyleImage, Quotes}; +pub use self::outline::OutlineStyle; pub use self::rect::LengthOrNumberRect; pub use self::percentage::Percentage; pub use self::position::{Position, PositionComponent, GridAutoFlow, GridTemplateAreas}; @@ -78,6 +80,8 @@ pub mod gecko; pub mod grid; pub mod image; pub mod length; +pub mod list; +pub mod outline; pub mod percentage; pub mod position; pub mod rect; diff --git a/components/style/values/specified/outline.rs b/components/style/values/specified/outline.rs new file mode 100644 index 00000000000..48385242275 --- /dev/null +++ b/components/style/values/specified/outline.rs @@ -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)] +/// +pub enum OutlineStyle { + /// auto + Auto, + /// + 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> { + 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) + } +} diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs index 15c09e05b0a..0a0a42b837f 100644 --- a/components/style/values/specified/position.rs +++ b/components/style/values/specified/position.rs @@ -42,17 +42,21 @@ pub enum PositionComponent { Side(S, Option), } -define_css_keyword_enum! { X: - "left" => Left, - "right" => Right, +/// A keyword for the X direction. +#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] +#[allow(missing_docs)] +pub enum X { + Left, + Right, } -add_impls_for_keyword_enum!(X); -define_css_keyword_enum! { Y: - "top" => Top, - "bottom" => Bottom, +/// A keyword for the Y direction. +#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] +#[allow(missing_docs)] +pub enum Y { + Top, + Bottom, } -add_impls_for_keyword_enum!(Y); impl Parse for Position { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { diff --git a/components/style_derive/cg.rs b/components/style_derive/cg.rs index 6937d5836d2..aa18fc45d10 100644 --- a/components/style_derive/cg.rs +++ b/components/style_derive/cg.rs @@ -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) +} diff --git a/components/style_derive/lib.rs b/components/style_derive/lib.rs index 6e87cc4972a..cbe33a3d199 100644 --- a/components/style_derive/lib.rs +++ b/components/style_derive/lib.rs @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#![recursion_limit = "128"] + #[macro_use] extern crate darling; extern crate proc_macro; #[macro_use] extern crate quote; @@ -13,6 +15,7 @@ use proc_macro::TokenStream; mod animate; mod cg; mod compute_squared_distance; +mod parse; mod to_animated_value; mod to_animated_zero; 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() } +#[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))] pub fn derive_to_animated_zero(stream: TokenStream) -> TokenStream { let input = syn::parse_derive_input(&stream.to_string()).unwrap(); diff --git a/components/style_derive/parse.rs b/components/style_derive/parse.rs new file mode 100644 index 00000000000..eb7d6913743 --- /dev/null +++ b/components/style_derive/parse.rs @@ -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::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> { + 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 { + match_ignore_ascii_case! { ident, + #match_body + _ => Err(()), + } + } + } + }; + + quote! { + #parse_trait_impl + #methods_impl + } +} diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs index 76f8239bcb4..12fad8f0d34 100644 --- a/components/style_derive/to_css.rs +++ b/components/style_derive/to_css.rs @@ -16,7 +16,7 @@ pub fn derive(input: DeriveInput) -> Tokens { let input_attrs = cg::parse_input_attrs::(&input); let style = synstructure::BindStyle::Ref.into(); 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::(variant); 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 = quote! {}; - if variant_attrs.function && variant_attrs.iterable { + if variant_attrs.iterable { assert_eq!(bindings.len(), 1); let binding = &bindings[0]; expr = quote! { @@ -118,41 +118,3 @@ struct CssVariantAttrs { comma: 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) -} diff --git a/etc/ci/performance/gecko_driver.py b/etc/ci/performance/gecko_driver.py index 9dec4dfda3b..99d041548ce 100644 --- a/etc/ci/performance/gecko_driver.py +++ b/etc/ci/performance/gecko_driver.py @@ -71,7 +71,7 @@ def generate_placeholder(testcase): return [timings] -def run_gecko_test(testcase, url, timeout, is_async): +def run_gecko_test(testcase, url, date, timeout, is_async): with create_gecko_session() as driver: driver.set_page_load_timeout(timeout) try: diff --git a/etc/ci/performance/runner.py b/etc/ci/performance/runner.py index 7b895f11ca0..e3ffe31b456 100644 --- a/etc/ci/performance/runner.py +++ b/etc/ci/performance/runner.py @@ -17,7 +17,7 @@ from statistics import median, StatisticsError from urllib.parse import urlsplit, urlunsplit, urljoin -DATE = datetime.now().strftime("%Y%m%d") +DATE = datetime.now().strftime("%Y-%m-%d") MACHINE = platform.machine() SYSTEM = platform.system() @@ -66,11 +66,11 @@ def execute_test(url, command, timeout): return "" -def run_servo_test(testcase, url, timeout, is_async): +def run_servo_test(testcase, url, date, timeout, is_async): if is_async: print("Servo does not support async test!") # Return a placeholder - return parse_log("", testcase, url) + return parse_log("", testcase, url, date) ua_script_path = "{}/user-agent-js".format(os.getcwd()) command = [ @@ -92,10 +92,10 @@ def run_servo_test(testcase, url, timeout, is_async): )) except subprocess.TimeoutExpired: print("Test FAILED due to timeout: {}".format(testcase)) - return parse_log(log, testcase, url) + return parse_log(log, testcase, url, date) -def parse_log(log, testcase, url): +def parse_log(log, testcase, url, date): blocks = [] block = [] copy = False @@ -149,7 +149,7 @@ def parse_log(log, testcase, url): return { "system": SYSTEM, "machine": MACHINE, - "date": DATE, + "date": date, "testcase": testcase, "title": "", "navigationStart": 0, @@ -177,15 +177,15 @@ def parse_log(log, testcase, url): # Set the testcase field to contain the original testcase name, # rather than the url. - def set_testcase(timing, testcase=None): + def set_testcase(timing, testcase=None, date=None): timing['testcase'] = testcase timing['system'] = SYSTEM timing['machine'] = MACHINE - timing['date'] = DATE + timing['date'] = date return timing valid_timing_for_case = partial(valid_timing, url=url) - set_testcase_for_case = partial(set_testcase, testcase=testcase) + set_testcase_for_case = partial(set_testcase, testcase=testcase, date=date) timings = list(map(set_testcase_for_case, filter(valid_timing_for_case, map(parse_block, blocks)))) if len(timings) == 0: @@ -329,6 +329,10 @@ def main(): default=300, # 5 min help=("kill the test if not finished in time (sec)." " Default: 5 min")) + parser.add_argument("--date", + type=str, + default=None, # 5 min + help=("the date to use in the CSV file.")) parser.add_argument("--engine", type=str, default='servo', @@ -340,6 +344,7 @@ def main(): elif args.engine == 'gecko': import gecko_driver # Load this only when we need gecko test run_test = gecko_driver.run_gecko_test + date = args.date or DATE try: # Assume the server is up and running testcases = load_manifest(args.tp5_manifest) @@ -352,7 +357,7 @@ def main(): url)) # results will be a mixure of timings dict and testcase strings # testcase string indicates a failed test - results += run_test(testcase, url, args.timeout, is_async) + results += run_test(testcase, url, date, args.timeout, is_async) print("Finished") # TODO: Record and analyze other performance.timing properties diff --git a/etc/ci/performance/test_all.sh b/etc/ci/performance/test_all.sh index 6602bc1f20e..e5e4f6dae08 100755 --- a/etc/ci/performance/test_all.sh +++ b/etc/ci/performance/test_all.sh @@ -14,6 +14,7 @@ set -o pipefail # https://groups.google.com/forum/#!topic/mozilla.dev.servo/JlAZoRgcnpA port="8123" base="http://localhost:${port}" +date="$(date +%Y-%m-%d)" while (( "${#}" )) do @@ -33,6 +34,10 @@ case "${1}" in base="${2}" shift ;; + --date) + date="${2}" + shift + ;; *) echo "Unknown option ${1}." exit @@ -56,11 +61,12 @@ trap 'kill $(jobs -pr)' SIGINT SIGTERM EXIT # MANIFEST="page_load_test/tp5n/20160509.manifest" MANIFEST="page_load_test/test.manifest" # A manifest that excludes # timeout test cases -PERF_KEY="perf-$(uname -s)-$(uname -m)-$(date +%s).csv" +PERF_KEY="perf-$(uname -s)-$(uname -m)-${date}.csv" PERF_FILE="output/${PERF_KEY}" echo "Running tests" -python3 runner.py ${engine} --runs 4 --timeout "${timeout}" --base "${base}" \ +python3 runner.py ${engine} --runs 4 --timeout "${timeout}" \ + --base "${base}" --date "${date}" \ "${MANIFEST}" "${PERF_FILE}" if [[ "${submit:-}" ]]; diff --git a/etc/ci/taskcluster-test.sh b/etc/ci/taskcluster-test.sh new file mode 100755 index 00000000000..9bad1e7aa80 --- /dev/null +++ b/etc/ci/taskcluster-test.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# 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/. + +set -o errexit +set -o nounset +set -o pipefail + +# Update this from the linux-dev builder in etc/ci/buildbot_steps.yml +./mach test-tidy --no-progress --all +./mach test-tidy --no-progress --self-test +env CC=gcc-5 CXX=g++-5 ./mach build --dev +env ./mach test-unit +env ./mach package --dev +env ./mach build-cef +env ./mach build --dev --no-default-features --features default-except-unstable +./mach build-geckolib +./mach test-stylo +bash ./etc/ci/lockfile_changed.sh +bash ./etc/ci/manifest_changed.sh +bash ./etc/ci/check_no_panic.sh diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index fdd491985f1..4f871202c9e 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -267,8 +267,19 @@ fn traverse_subtree( None }; + let is_restyle = element.get_data().is_some(); + let traversal = RecalcStyleOnly::new(shared_style_context); - driver::traverse_dom(&traversal, token, thread_pool); + let (used_parallel, stats) = driver::traverse_dom(&traversal, token, thread_pool); + + if traversal_flags.contains(TraversalFlags::ParallelTraversal) && + !traversal_flags.contains(TraversalFlags::AnimationOnly) && + is_restyle && !element.is_native_anonymous() { + // We turn off parallel traversal for background tabs; this + // shouldn't count in telemetry. We're also focusing on restyles so + // we ensure that it's a restyle. + per_doc_data.record_traversal(used_parallel, stats); + } } /// Traverses the subtree rooted at `root` for restyling. @@ -2017,7 +2028,7 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: parent_style_or_null.map(|x| &*x), cascade_flags, &metrics, - &rule_node + rule_node ).into() } @@ -2207,8 +2218,9 @@ fn get_pseudo_style( &inputs, pseudo, &guards, - inherited_styles, - &metrics + Some(inherited_styles), + &metrics, + CascadeFlags::empty(), ) }) }, @@ -3633,16 +3645,16 @@ pub extern "C" fn Servo_ReparentStyle( } } - doc_data.stylist - .compute_style_with_inputs(&inputs, - pseudo.as_ref(), - &StylesheetGuards::same(&guard), - parent_style, - parent_style_ignoring_first_line, - layout_parent_style, - &metrics, - cascade_flags) - .into() + doc_data.stylist.compute_style_with_inputs( + &inputs, + pseudo.as_ref(), + &StylesheetGuards::same(&guard), + Some(parent_style), + Some(parent_style_ignoring_first_line), + Some(layout_parent_style), + &metrics, + cascade_flags, + ).into() } #[cfg(feature = "gecko_debug")] diff --git a/python/servo/devenv_commands.py b/python/servo/devenv_commands.py index 1ddba4af445..1abf575ab5f 100644 --- a/python/servo/devenv_commands.py +++ b/python/servo/devenv_commands.py @@ -8,7 +8,7 @@ # except according to those terms. from __future__ import print_function, unicode_literals -from os import path, getcwd, listdir +from os import path, listdir from time import time import sys @@ -29,28 +29,30 @@ from servo.util import STATIC_RUST_LANG_ORG_DIST, URLOPEN_KWARGS @CommandProvider class MachCommands(CommandBase): def run_cargo(self, params, geckolib=False, check=False): - if geckolib: - self.set_use_stable_rust() - crate_dir = path.join('ports', 'geckolib') - else: - crate_dir = path.join('ports', 'servo') + if not params: + params = [] self.ensure_bootstrapped() self.ensure_clobbered() env = self.build_env(geckolib=geckolib) - if not params: - params = [] - if check: params = ['check'] + params + if geckolib: + # for c in $(cargo --list | tail -$(($(cargo --list | wc -l) - 1))); do + # (cargo help $c 2>&1 | grep "\\--package" >/dev/null 2>&1) && echo $c + # done + if params[0] and params[0] in [ + 'bench', 'build', 'check', 'clean', 'doc', 'fmt', 'pkgid', + 'run', 'rustc', 'rustdoc', 'test', 'update', + ]: + params[1:1] = ['--package', 'geckoservo'] + + self.set_use_stable_rust() + build_start = time() - if self.context.topdir == getcwd(): - with cd(crate_dir): - status = call(['cargo'] + params, env=env) - else: - status = call(['cargo'] + params, env=env) + status = call(['cargo'] + params, env=env) elapsed = time() - build_start notify_build_done(self.config, elapsed, status == 0) @@ -94,7 +96,7 @@ class MachCommands(CommandBase): 'params', default=None, nargs='...', help="Command-line arguments to be passed through to cargo check") def check_geckolib(self, params): - return self.run_cargo(["-p", "geckoservo"] + (params or []), check=True, geckolib=True) + return self.run_cargo(params, check=True, geckolib=True) @Command('cargo-update', description='Same as update-cargo', diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py index e0b9a4e7b28..de77c85c285 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -171,9 +171,11 @@ class MachCommands(CommandBase): category='testing') @CommandArgument('--base', default=None, help="the base URL for testcases") + @CommandArgument('--date', default=None, + help="the datestamp for the data") @CommandArgument('--submit', '-a', default=False, action="store_true", help="submit the data to perfherder") - def test_perf(self, base=None, submit=False): + def test_perf(self, base=None, date=None, submit=False): self.set_software_rendering_env(True) self.ensure_bootstrapped() @@ -181,6 +183,8 @@ class MachCommands(CommandBase): cmd = ["bash", "test_perf.sh"] if base: cmd += ["--base", base] + if date: + cmd += ["--date", date] if submit: cmd += ["--submit"] return call(cmd, diff --git a/servo-tidy.toml b/servo-tidy.toml index 6f96592eafa..d9bcc9def68 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -29,7 +29,9 @@ rand = [ "uuid", "ws", ] -num = [] +num = [ + "chrono", +] [ignore] # Ignored packages with duplicated versions diff --git a/tests/unit/script/textinput.rs b/tests/unit/script/textinput.rs index 977b0e686c9..5b98dc934c6 100644 --- a/tests/unit/script/textinput.rs +++ b/tests/unit/script/textinput.rs @@ -583,19 +583,19 @@ fn test_textinput_cursor_position_correct_after_clearing_selection() { #[test] fn test_textinput_set_selection_with_direction() { let mut textinput = text_input(Lines::Single, "abcdef"); - textinput.selection_direction = SelectionDirection::Forward; - textinput.set_selection_range(2, 6); + textinput.set_selection_range(2, 6, SelectionDirection::Forward); assert_eq!(textinput.edit_point.line, 0); assert_eq!(textinput.edit_point.index, 6); + assert_eq!(textinput.selection_direction, SelectionDirection::Forward); assert!(textinput.selection_begin.is_some()); assert_eq!(textinput.selection_begin.unwrap().line, 0); assert_eq!(textinput.selection_begin.unwrap().index, 2); - textinput.selection_direction = SelectionDirection::Backward; - textinput.set_selection_range(2, 6); + textinput.set_selection_range(2, 6, SelectionDirection::Backward); assert_eq!(textinput.edit_point.line, 0); assert_eq!(textinput.edit_point.index, 2); + assert_eq!(textinput.selection_direction, SelectionDirection::Backward); assert!(textinput.selection_begin.is_some()); assert_eq!(textinput.selection_begin.unwrap().line, 0); diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs index 7ec045feb81..7f8d6478c25 100644 --- a/tests/unit/style/properties/serialization.rs +++ b/tests/unit/style/properties/serialization.rs @@ -6,7 +6,7 @@ use properties::{parse, parse_input}; use style::computed_values::display::T as Display; use style::properties::{PropertyDeclaration, Importance}; use style::properties::parse_property_declaration_list; -use style::values::{CustomIdent, RGBA, Auto}; +use style::values::{CustomIdent, RGBA}; use style::values::generics::flex::FlexBasis; use style::values::specified::{BorderStyle, BorderSideWidth, Color}; use style::values::specified::{Length, LengthOrPercentage, LengthOrPercentageOrAuto}; @@ -511,7 +511,7 @@ mod shorthand_serialization { } mod outline { - use style::values::Either; + use style::values::specified::outline::OutlineStyle; use super::*; #[test] @@ -519,7 +519,7 @@ mod shorthand_serialization { let mut properties = Vec::new(); let width = BorderSideWidth::Length(Length::from_px(4f32)); - let style = Either::Second(BorderStyle::Solid); + let style = OutlineStyle::Other(BorderStyle::Solid); let color = RGBA::new(255, 0, 0, 255).into(); properties.push(PropertyDeclaration::OutlineWidth(width)); @@ -535,7 +535,7 @@ mod shorthand_serialization { let mut properties = Vec::new(); let width = BorderSideWidth::Length(Length::from_px(4f32)); - let style = Either::First(Auto); + let style = OutlineStyle::Auto; let color = RGBA::new(255, 0, 0, 255).into(); properties.push(PropertyDeclaration::OutlineWidth(width)); properties.push(PropertyDeclaration::OutlineStyle(style)); diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index e58fa12d536..30613dca959 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -112737,6 +112737,18 @@ {} ] ], + "css/css-images/gradient-border-box.html": [ + [ + "/css/css-images/gradient-border-box.html", + [ + [ + "/css/css-images/gradient-border-box-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-images/gradient-button.html": [ [ "/css/css-images/gradient-button.html", @@ -112749,6 +112761,18 @@ {} ] ], + "css/css-images/gradient-content-box.html": [ + [ + "/css/css-images/gradient-content-box.html", + [ + [ + "/css/css-images/gradient-content-box-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-images/gradient-move-stops.html": [ [ "/css/css-images/gradient-move-stops.html", @@ -112809,6 +112833,30 @@ {} ] ], + "css/css-images/tiled-gradients.html": [ + [ + "/css/css-images/tiled-gradients.html", + [ + [ + "/css/css-images/tiled-gradients-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-images/tiled-radial-gradients.html": [ + [ + "/css/css-images/tiled-radial-gradients.html", + [ + [ + "/css/css-images/tiled-radial-gradients-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-logical/cascading-001.html": [ [ "/css/css-logical/cascading-001.html", @@ -239526,11 +239574,21 @@ {} ] ], + "css/css-images/gradient-border-box-ref.html": [ + [ + {} + ] + ], "css/css-images/gradient-button-ref.html": [ [ {} ] ], + "css/css-images/gradient-content-box-ref.html": [ + [ + {} + ] + ], "css/css-images/gradient-move-stops-ref.html": [ [ {} @@ -239776,6 +239834,16 @@ {} ] ], + "css/css-images/tiled-gradients-ref.html": [ + [ + {} + ] + ], + "css/css-images/tiled-radial-gradients-ref.html": [ + [ + {} + ] + ], "css/css-lists/OWNERS": [ [ {} @@ -481622,6 +481690,14 @@ "94471f5d29319241d0d25b8391430778f668ff4f", "reftest" ], + "css/css-images/gradient-border-box-ref.html": [ + "ccf241348a131e495269e8bcc108a0253fd3fc7e", + "support" + ], + "css/css-images/gradient-border-box.html": [ + "fe78a2c52e0a89e788edf339c0d8d75c9522ad5a", + "reftest" + ], "css/css-images/gradient-button-ref.html": [ "17a42eca5cfb86e29bfb5e20a65f0585d9727e30", "support" @@ -481630,6 +481706,14 @@ "41dc276e1c60a3fbf7920f44b8032fc2b0d7114e", "reftest" ], + "css/css-images/gradient-content-box-ref.html": [ + "a030609470853d73ca1363840c4b94da6d49bb43", + "support" + ], + "css/css-images/gradient-content-box.html": [ + "5e74191a82ee45a5441d595c79b2a41b34748038", + "reftest" + ], "css/css-images/gradient-move-stops-ref.html": [ "bb2fca5aaeb7fe1abf30620695ad3fd832c0d089", "support" @@ -481858,6 +481942,22 @@ "078e1dd6dd61d36cec239ed75d02051f61fe60a5", "support" ], + "css/css-images/tiled-gradients-ref.html": [ + "47f9512fa5139fd9cdd66f0d191e8f71ad04317a", + "support" + ], + "css/css-images/tiled-gradients.html": [ + "fcc12e47fba2a938fca012e90fcfc6aa1877185e", + "reftest" + ], + "css/css-images/tiled-radial-gradients-ref.html": [ + "9033e28e4607cbcee67e37d97c2611a8ce5f19c4", + "support" + ], + "css/css-images/tiled-radial-gradients.html": [ + "4b4b4756c2f605ab4dca092775cc39b0705efda9", + "reftest" + ], "css/css-lists/OWNERS": [ "d9c8054b356c9273a054a83abeb9be0626c23921", "support" @@ -542639,7 +542739,7 @@ "support" ], "html/semantics/forms/textfieldselection/select-event.html": [ - "e4835db1c781cad4b259b782a57b452022a50d79", + "6232a1316c4221be0f2f28a91939adfbce5698f8", "testharness" ], "html/semantics/forms/textfieldselection/selection-after-content-change.html": [ @@ -542651,7 +542751,7 @@ "testharness" ], "html/semantics/forms/textfieldselection/selection-not-application.html": [ - "3763f117f8973ca9a994354ccbf22cb7114ece7a", + "db63d0d1eedec810d4c7e1b38789be457e06e985", "testharness" ], "html/semantics/forms/textfieldselection/selection-start-end.html": [ @@ -543087,7 +543187,7 @@ "testharness" ], "html/semantics/forms/the-input-element/week.html": [ - "851b1b794f820b1fb9b7ee57fe39f8f2977b7fe6", + "95fa0e8176311adcbb5a8d0d408d3c4c8bea100c", "testharness" ], "html/semantics/forms/the-label-element/.gitkeep": [ diff --git a/tests/wpt/metadata/css/css-variables/vars-background-shorthand-001.html.ini b/tests/wpt/metadata/css/css-variables/vars-background-shorthand-001.html.ini deleted file mode 100644 index 7988a468f61..00000000000 --- a/tests/wpt/metadata/css/css-variables/vars-background-shorthand-001.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[vars-background-shorthand-001.html] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/textfieldselection/select-event.html.ini b/tests/wpt/metadata/html/semantics/forms/textfieldselection/select-event.html.ini index 39e337a9fd6..1f1def1f0da 100644 --- a/tests/wpt/metadata/html/semantics/forms/textfieldselection/select-event.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/textfieldselection/select-event.html.ini @@ -1,23 +1,146 @@ [select-event.html] type: testharness - [select() on textarea queues select event] + [textarea: select()] expected: FAIL - [select() on input type text queues select event] + [textarea: select() a second time (must not fire select)] expected: FAIL - [select() on input type search queues select event] + [textarea: selectionStart a second time (must not fire select)] expected: FAIL - [select() on input type tel queues select event] + [textarea: selectionEnd a second time (must not fire select)] expected: FAIL - [select() on input type url queues select event] + [textarea: selectionDirection a second time (must not fire select)] expected: FAIL - [select() on input type password queues select event] + [textarea: setSelectionRange() a second time (must not fire select)] expected: FAIL - [text field selection: select()] + [textarea: setRangeText()] + expected: FAIL + + [textarea: setRangeText() a second time (must not fire select)] + expected: FAIL + + [input type text: select()] + expected: FAIL + + [input type text: select() a second time (must not fire select)] + expected: FAIL + + [input type text: selectionStart a second time (must not fire select)] + expected: FAIL + + [input type text: selectionEnd a second time (must not fire select)] + expected: FAIL + + [input type text: selectionDirection a second time (must not fire select)] + expected: FAIL + + [input type text: setSelectionRange() a second time (must not fire select)] + expected: FAIL + + [input type text: setRangeText()] + expected: FAIL + + [input type text: setRangeText() a second time (must not fire select)] + expected: FAIL + + [input type search: select()] + expected: FAIL + + [input type search: select() a second time (must not fire select)] + expected: FAIL + + [input type search: selectionStart a second time (must not fire select)] + expected: FAIL + + [input type search: selectionEnd a second time (must not fire select)] + expected: FAIL + + [input type search: selectionDirection a second time (must not fire select)] + expected: FAIL + + [input type search: setSelectionRange() a second time (must not fire select)] + expected: FAIL + + [input type search: setRangeText()] + expected: FAIL + + [input type search: setRangeText() a second time (must not fire select)] + expected: FAIL + + [input type tel: select()] + expected: FAIL + + [input type tel: select() a second time (must not fire select)] + expected: FAIL + + [input type tel: selectionStart a second time (must not fire select)] + expected: FAIL + + [input type tel: selectionEnd a second time (must not fire select)] + expected: FAIL + + [input type tel: selectionDirection a second time (must not fire select)] + expected: FAIL + + [input type tel: setSelectionRange() a second time (must not fire select)] + expected: FAIL + + [input type tel: setRangeText()] + expected: FAIL + + [input type tel: setRangeText() a second time (must not fire select)] + expected: FAIL + + [input type url: select()] + expected: FAIL + + [input type url: select() a second time (must not fire select)] + expected: FAIL + + [input type url: selectionStart a second time (must not fire select)] + expected: FAIL + + [input type url: selectionEnd a second time (must not fire select)] + expected: FAIL + + [input type url: selectionDirection a second time (must not fire select)] + expected: FAIL + + [input type url: setSelectionRange() a second time (must not fire select)] + expected: FAIL + + [input type url: setRangeText()] + expected: FAIL + + [input type url: setRangeText() a second time (must not fire select)] + expected: FAIL + + [input type password: select()] + expected: FAIL + + [input type password: select() a second time (must not fire select)] + expected: FAIL + + [input type password: selectionStart a second time (must not fire select)] + expected: FAIL + + [input type password: selectionEnd a second time (must not fire select)] + expected: FAIL + + [input type password: selectionDirection a second time (must not fire select)] + expected: FAIL + + [input type password: setSelectionRange() a second time (must not fire select)] + expected: FAIL + + [input type password: setRangeText()] + expected: FAIL + + [input type password: setRangeText() a second time (must not fire select)] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-not-application.html.ini b/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-not-application.html.ini index a97a4c9832b..81dc9d94fb1 100644 --- a/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-not-application.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/textfieldselection/selection-not-application.html.ini @@ -1,71 +1,74 @@ [selection-not-application.html] type: testharness - [text field selection for the input hidden] + [setRangeText on an input[type=hidden\] throws InvalidStateError] expected: FAIL - [text field selection for the input email] + [setRangeText on an input[type=email\] throws InvalidStateError] expected: FAIL - [text field selection for the input datetime] + [setRangeText on an input[type=datetime-local\] throws InvalidStateError] expected: FAIL - [text field selection for the input date] + [setRangeText on an input[type=date\] throws InvalidStateError] expected: FAIL - [text field selection for the input month] + [setRangeText on an input[type=month\] throws InvalidStateError] expected: FAIL - [text field selection for the input week] + [setRangeText on an input[type=week\] throws InvalidStateError] expected: FAIL - [text field selection for the input time] + [setRangeText on an input[type=time\] throws InvalidStateError] expected: FAIL - [text field selection for the input number] + [setRangeText on an input[type=number\] throws InvalidStateError] expected: FAIL - [text field selection for the input range] + [setRangeText on an input[type=range\] throws InvalidStateError] expected: FAIL - [text field selection for the input color] + [setRangeText on an input[type=color\] throws InvalidStateError] expected: FAIL - [text field selection for the input checkbox] + [setRangeText on an input[type=checkbox\] throws InvalidStateError] expected: FAIL - [text field selection for the input radio] + [setRangeText on an input[type=radio\] throws InvalidStateError] expected: FAIL - [text field selection for the input file] + [setRangeText on an input[type=file\] throws InvalidStateError] expected: FAIL - [text field selection for the input submit] + [setRangeText on an input[type=submit\] throws InvalidStateError] expected: FAIL - [text field selection for the input image] + [setRangeText on an input[type=image\] throws InvalidStateError] expected: FAIL - [text field selection for the input reset] + [setRangeText on an input[type=reset\] throws InvalidStateError] expected: FAIL - [text field selection for the input button] + [setRangeText on an input[type=button\] throws InvalidStateError] expected: FAIL - [text field selection for the input text] + [setRangeText on an input[type=text\] doesn't throw an exception] expected: FAIL - [text field selection for the input search] + [setRangeText on an input[type=search\] doesn't throw an exception] expected: FAIL - [text field selection for the input tel] + [setRangeText on an input[type=tel\] doesn't throw an exception] expected: FAIL - [text field selection for the input url] + [setRangeText on an input[type=url\] doesn't throw an exception] expected: FAIL - [text field selection for the input password] + [setRangeText on an input[type=password\] doesn't throw an exception] expected: FAIL - [text field selection for the input datetime-local] + [setRangeText on an input[type=null\] doesn't throw an exception] + expected: FAIL + + [setRangeText on an input[type=aninvalidtype\] doesn't throw an exception] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini index 185dd921114..4de9d689a17 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini @@ -6,9 +6,6 @@ [change state from hidden to datetime] expected: FAIL - [change state from hidden to week] - expected: FAIL - [change state from hidden to number] expected: FAIL @@ -21,9 +18,6 @@ [change state from text to datetime] expected: FAIL - [change state from text to week] - expected: FAIL - [change state from text to number] expected: FAIL @@ -36,9 +30,6 @@ [change state from search to datetime] expected: FAIL - [change state from search to week] - expected: FAIL - [change state from search to number] expected: FAIL @@ -51,9 +42,6 @@ [change state from tel to datetime] expected: FAIL - [change state from tel to week] - expected: FAIL - [change state from tel to number] expected: FAIL @@ -75,9 +63,6 @@ [change state from url to datetime] expected: FAIL - [change state from url to week] - expected: FAIL - [change state from url to number] expected: FAIL @@ -108,9 +93,6 @@ [change state from email to datetime] expected: FAIL - [change state from email to week] - expected: FAIL - [change state from email to number] expected: FAIL @@ -123,9 +105,6 @@ [change state from password to datetime] expected: FAIL - [change state from password to week] - expected: FAIL - [change state from password to number] expected: FAIL @@ -171,27 +150,9 @@ [change state from month to range] expected: FAIL - [change state from week to reset] - expected: FAIL - - [change state from week to button] - expected: FAIL - - [change state from week to email] - expected: FAIL - [change state from week to datetime] expected: FAIL - [change state from week to number] - expected: FAIL - - [change state from week to hidden] - expected: FAIL - - [change state from week to number] - expected: FAIL - [change state from week to range] expected: FAIL @@ -228,9 +189,6 @@ [change state from number to datetime] expected: FAIL - [change state from number to week] - expected: FAIL - [change state from number to range] expected: FAIL @@ -261,9 +219,6 @@ [change state from range to datetime] expected: FAIL - [change state from range to week] - expected: FAIL - [change state from range to number] expected: FAIL @@ -273,9 +228,6 @@ [change state from checkbox to datetime] expected: FAIL - [change state from checkbox to week] - expected: FAIL - [change state from checkbox to number] expected: FAIL @@ -288,9 +240,6 @@ [change state from radio to datetime] expected: FAIL - [change state from radio to week] - expected: FAIL - [change state from radio to number] expected: FAIL @@ -303,9 +252,6 @@ [change state from submit to datetime] expected: FAIL - [change state from submit to week] - expected: FAIL - [change state from submit to number] expected: FAIL @@ -318,9 +264,6 @@ [change state from image to datetime] expected: FAIL - [change state from image to week] - expected: FAIL - [change state from image to number] expected: FAIL @@ -333,9 +276,6 @@ [change state from reset to datetime] expected: FAIL - [change state from reset to week] - expected: FAIL - [change state from reset to number] expected: FAIL @@ -348,9 +288,6 @@ [change state from button to datetime] expected: FAIL - [change state from button to week] - expected: FAIL - [change state from button to number] expected: FAIL @@ -402,18 +339,12 @@ [change state from datetime-local to email] expected: FAIL - [change state from datetime-local to week] - expected: FAIL - [change state from datetime-local to number] expected: FAIL [change state from datetime-local to range] expected: FAIL - [change state from week to datetime-local] - expected: FAIL - [change state from number to datetime-local] expected: FAIL @@ -453,33 +384,6 @@ [change state from datetime-local to password] expected: FAIL - [change state from week to text] - expected: FAIL - - [change state from week to search] - expected: FAIL - - [change state from week to tel] - expected: FAIL - - [change state from week to url] - expected: FAIL - - [change state from week to password] - expected: FAIL - - [change state from week to checkbox] - expected: FAIL - - [change state from week to radio] - expected: FAIL - - [change state from week to submit] - expected: FAIL - - [change state from week to image] - expected: FAIL - [change state from number to text] expected: FAIL @@ -513,9 +417,6 @@ [change state from color to datetime-local] expected: FAIL - [change state from color to week] - expected: FAIL - [change state from color to number] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini index 4dd99f109cd..b794bb8fc75 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini @@ -6,12 +6,6 @@ [value IDL attribute of input type datetime with value attribute] expected: FAIL - [value IDL attribute of input type week without value attribute] - expected: FAIL - - [value IDL attribute of input type week with value attribute] - expected: FAIL - [value IDL attribute of input type number without value attribute] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/week.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/week.html.ini deleted file mode 100644 index 3c94a479263..00000000000 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/week.html.ini +++ /dev/null @@ -1,20 +0,0 @@ -[week.html] - type: testharness - [2014 has 52 weeks: Value should be empty] - expected: FAIL - - [Invalid value: year only] - expected: FAIL - - [Invalid value: no week number] - expected: FAIL - - [Invalid value: no '-' (U+002D)] - expected: FAIL - - [Invalid value: yearless week] - expected: FAIL - - [Invalid value: yearless week and no '-' (U+002D)] - expected: FAIL - diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 1bd5d50b9b9..5d183740117 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -40195,6 +40195,12 @@ {} ] ], + "mozilla/window_performance_topLevelDomComplete.html": [ + [ + "/_mozilla/mozilla/window_performance_topLevelDomComplete.html", + {} + ] + ], "mozilla/window_requestAnimationFrame.html": [ [ "/_mozilla/mozilla/window_requestAnimationFrame.html", @@ -72342,6 +72348,10 @@ "f03283e68b82d972ad21f674243070643ef89489", "testharness" ], + "mozilla/window_performance_topLevelDomComplete.html": [ + "4b953e63ffa6bf4ed1bc9a2baaea457d46502b9d", + "testharness" + ], "mozilla/window_requestAnimationFrame.html": [ "86310f3e4b88cce70ef92b56e4f65f034999096e", "testharness" diff --git a/tests/wpt/mozilla/meta/mozilla/window_performance_topLevelDomComplete.html.ini b/tests/wpt/mozilla/meta/mozilla/window_performance_topLevelDomComplete.html.ini new file mode 100644 index 00000000000..ac65905cb3d --- /dev/null +++ b/tests/wpt/mozilla/meta/mozilla/window_performance_topLevelDomComplete.html.ini @@ -0,0 +1,3 @@ +[window_performance_topLevelDomComplete.html] + type: testharness + prefs: [dom.testperf.enabled:true] diff --git a/tests/wpt/mozilla/tests/mozilla/window_performance_topLevelDomComplete.html b/tests/wpt/mozilla/tests/mozilla/window_performance_topLevelDomComplete.html new file mode 100644 index 00000000000..ce2431a7279 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/window_performance_topLevelDomComplete.html @@ -0,0 +1,18 @@ + + + Performance toLevelDomComplete + + + + + + + diff --git a/tests/wpt/web-platform-tests/css/css-images/gradient-border-box-ref.html b/tests/wpt/web-platform-tests/css/css-images/gradient-border-box-ref.html new file mode 100644 index 00000000000..5b219cea6c2 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-images/gradient-border-box-ref.html @@ -0,0 +1,16 @@ + + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/css/css-images/gradient-border-box.html b/tests/wpt/web-platform-tests/css/css-images/gradient-border-box.html new file mode 100644 index 00000000000..2938c5ea99e --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-images/gradient-border-box.html @@ -0,0 +1,24 @@ + + + + + Gradient Background aligned to Content Box + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/css/css-images/gradient-content-box-ref.html b/tests/wpt/web-platform-tests/css/css-images/gradient-content-box-ref.html new file mode 100644 index 00000000000..fae29540123 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-images/gradient-content-box-ref.html @@ -0,0 +1,19 @@ + + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/css/css-images/gradient-content-box.html b/tests/wpt/web-platform-tests/css/css-images/gradient-content-box.html new file mode 100644 index 00000000000..82b42ee8fbe --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-images/gradient-content-box.html @@ -0,0 +1,22 @@ + + + + + Gradient Background aligned to Content Box + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/css/css-images/tiled-gradients-ref.html b/tests/wpt/web-platform-tests/css/css-images/tiled-gradients-ref.html new file mode 100644 index 00000000000..a6fa41214ee --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-images/tiled-gradients-ref.html @@ -0,0 +1,29 @@ + + + + + + + +
+
+
+
+
+
+ + + diff --git a/tests/wpt/web-platform-tests/css/css-images/tiled-gradients.html b/tests/wpt/web-platform-tests/css/css-images/tiled-gradients.html new file mode 100644 index 00000000000..f6f5f5bd53e --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-images/tiled-gradients.html @@ -0,0 +1,22 @@ + + + + + Eight Red Triangles on White Ground (with gradients) + + + + + + +
+ + + diff --git a/tests/wpt/web-platform-tests/css/css-images/tiled-radial-gradients-ref.html b/tests/wpt/web-platform-tests/css/css-images/tiled-radial-gradients-ref.html new file mode 100644 index 00000000000..30046e4f2c0 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-images/tiled-radial-gradients-ref.html @@ -0,0 +1,40 @@ + + + + + + + +
+
+ +
+ + + diff --git a/tests/wpt/web-platform-tests/css/css-images/tiled-radial-gradients.html b/tests/wpt/web-platform-tests/css/css-images/tiled-radial-gradients.html new file mode 100644 index 00000000000..6615e8be358 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-images/tiled-radial-gradients.html @@ -0,0 +1,29 @@ + + + + + Two Ellipses with Custom Placement (with gradients) + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/select-event.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/select-event.html index 6cfe52e87fe..2fb018f82aa 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/select-event.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/select-event.html @@ -47,10 +47,10 @@ const actions = [ } ]; -for (const el of els) { +els.forEach((el) => { const elLabel = el.localName === "textarea" ? "textarea" : "input type " + el.type; - for (const action of actions) { + actions.forEach((action) => { // promise_test instead of async_test is important because these need to happen in sequence (to test that events // fire if and only if the selection changes). promise_test(t => { @@ -79,6 +79,6 @@ for (const el of els) { }, 200); }); }, `${elLabel}: ${action.label} a second time (must not fire select)`); - } -} + }); +}); diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application.html index b0db8a96fab..04b4fdd4f78 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application.html @@ -7,45 +7,90 @@
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/week.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/week.html index 77978a255a3..925acfdaf8b 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/week.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/week.html @@ -17,6 +17,9 @@ {value: "2014W", expected: "", testname: "Invalid value: no week number"}, {value: "2014W52", expected: "", testname: "Invalid value: no '-' (U+002D)"}, {value: "-W52", expected: "", testname: "Invalid value: yearless week"}, + {value: "2017-w52", expected: "", testname: "Invalid value: should be capital letter 'W'"}, + {value: "2017-W52-", expected: "", testname: "Invalid value: incorrect with '-' at the end"}, + {value: "2017-W52-12", expected: "", testname: "Invalid value: value should be two parts"}, {value: "W52", expected: "", testname: "Invalid value: yearless week and no '-' (U+002D)"}, {value: "2014-W03", attributes: { min: "2014-W02" }, expected: "2014-W03", testname: "Value >= min attribute"}, {value: "2014-W01", attributes: { min: "2014-W02" }, expected: "2014-W01", testname: "Value < min attribute"},