diff options
28 files changed, 574 insertions, 266 deletions
diff --git a/.travis.yml b/.travis.yml index 534ecf3f1af..49fef44f73c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ matrix: - $HOME/.ccache before_cache: - ./mach clean-nightlies --keep 2 --force + - ./mach clean-cargo-cache --keep 2 --force env: CCACHE=/usr/bin/ccache addons: apt: diff --git a/Cargo.lock b/Cargo.lock index 907fce8e64b..daa5cef0da3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,10 +77,10 @@ dependencies = [ [[package]] name = "aster" -version = "0.38.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -164,22 +164,21 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.22.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aster 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clang-sys 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -358,14 +357,13 @@ dependencies = [ [[package]] name = "clang-sys" -version = "0.14.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1489,6 +1487,16 @@ dependencies = [ ] [[package]] +name = "libloading" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "libservo" version = "0.0.1" dependencies = [ @@ -2126,22 +2134,22 @@ dependencies = [ [[package]] name = "quasi" -version = "0.29.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quasi_codegen" -version = "0.29.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aster 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2760,7 +2768,7 @@ version = "0.0.1" dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bindgen 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bindgen 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)", "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2878,29 +2886,28 @@ dependencies = [ [[package]] name = "syntex" -version = "0.54.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_errors" -version = "0.54.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_pos" -version = "0.54.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2908,16 +2915,14 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.54.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3199,7 +3204,7 @@ dependencies = [ [[package]] name = "webrender" version = "0.36.0" -source = "git+https://github.com/servo/webrender#c661afa3193b4d00c15509537a8d8fc33aa0c274" +source = "git+https://github.com/servo/webrender#005eb39d79afca7ea0dc140d5cf7b809be06589b" dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0-alpha6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3228,7 +3233,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.36.0" -source = "git+https://github.com/servo/webrender#c661afa3193b4d00c15509537a8d8fc33aa0c274" +source = "git+https://github.com/servo/webrender#005eb39d79afca7ea0dc140d5cf7b809be06589b" dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0-alpha6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3353,7 +3358,7 @@ dependencies = [ "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a0c3b5be4ed53affe3e1a162b2e7ef9979bcaac80daa9026e9d7988c41e0e83" "checksum arrayvec 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d89f1b0e242270b5b797778af0c8d182a1a2ccac5d8d6fadf414223cc0fab096" -"checksum aster 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c9b49e42a449c0b79d8acb91db37621de0978064dca7d3288ddcf030123e5b3" +"checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0" "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21" "checksum audio-video-metadata 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3b6ef29ee98ad95a37f34547fd7fb40724772294110ed6ca0445fc2e964c29d1" "checksum azure 0.15.0 (git+https://github.com/servo/rust-azure)" = "<none>" @@ -3362,7 +3367,7 @@ dependencies = [ "checksum base64 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "979d348dc50dfcd050a87df408ec61f01a0a27ee9b4ebdc6085baba8275b2c7f" "checksum binary-space-partition 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "df65281d9b2b5c332f5bfbd9bb5e5f2e62f627c259cf9dc9cd10fecb758be33d" "checksum bincode 1.0.0-alpha6 (registry+https://github.com/rust-lang/crates.io-index)" = "fb0cdeac1c5d567fdb487ae5853c024e4acf1ea85ba6a6552fe084e0805fea5d" -"checksum bindgen 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88f9d9abd7964621201c558021ff4f39b7b4d571a9a56a88844da9971e2344ce" +"checksum bindgen 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21a1de90068c1e58dd31b71daab70e1a1e54212b43cc6c4714e7c8acefb28992" "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" @@ -3381,7 +3386,7 @@ dependencies = [ "checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d" "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" "checksum cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86765cb42c2a2c497e142af72517c1b4d7ae5bb2f25dfa77a5c69642f2342d89" -"checksum clang-sys 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f98f0715ff67f27ca6a2f8f0ffc2a56f8edbc7acd57489c29eadc3a15c4eafe" +"checksum clang-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f4f6aa0c4cfa318cd4d2940afae57e48b94d44d3aced603501df24f3c2a414f" "checksum clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758" "checksum cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "d18d68987ed4c516dcc3e7913659bfa4076f5182eea4a7e0038bb060953e76ac" "checksum cocoa 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a5d0bcb4d345adf9b4ada6c5bb3e2b87c8150b79c46f3f26446de5f4d48de4b" @@ -3467,6 +3472,7 @@ dependencies = [ "checksum leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc" "checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" "checksum libloading 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fd1835a714c1f67ba073a493493c23686a480e2614e208c921834808b1f19d8f" +"checksum libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "be99f814beb3e9503a786a592c909692bb6d4fc5a695f6ed7987223acfbd5194" "checksum libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e5ee912a45d686d393d5ac87fac15ba0ba18daae14e8e7543c63ebf7fb7e970c" "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" @@ -3518,8 +3524,8 @@ dependencies = [ "checksum png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cb773e9a557edb568ce9935cf783e3cdcabe06a9449d41b3e5506d88e582c82" "checksum precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf1fc3616b3ef726a847f2cd2388c646ef6a1f1ba4835c2629004da48184150" "checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260" -"checksum quasi 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dcbf815446dc6a0afbc72d88f9a8aa71b608d10b168e09437c80c0fd6fd410c9" -"checksum quasi_codegen 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b06172e92ab0099427609854ffb1512c377be5fc4beaf572ae5d5a01b8359596" +"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3" +"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "checksum rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50c575b58c2b109e2fbc181820cbe177474f35610ff9e357dc75f6bac854ffbf" @@ -3562,10 +3568,10 @@ dependencies = [ "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ccc9780bf1aa601943988c2876ab22413c01ad1739689aa6af18d0aa0b3f38b" -"checksum syntex 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb3f52553a966675982404dc34028291b347e0c9a9c0b0b34f2da6be8a0443f8" -"checksum syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dee2f6e49c075f71332bb775219d5982bee6732d26227fa1ae1b53cdb12f5cc5" -"checksum syntex_pos 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df3921c7945dfb9ffc53aa35adb2cf4313b5ab5f079c3619b3d4eb82a0efc2b" -"checksum syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc960085bae44591e22d01f6c0e82a8aec832f8659aca556cdf8ecbdac2bb47b" +"checksum syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8f5e3aaa79319573d19938ea38d068056b826db9883a5d47f86c1cecc688f0e" +"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" +"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047" +"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791" "checksum target_build_utils 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f42dc058080c19c6a58bdd1bf962904ee4f5ef1fe2a81b529f31dacc750c679f" "checksum tendril 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4ce04c250d202db8004921e3d3bc95eaa4f2126c6937a428ae39d12d0e38df62" "checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" diff --git a/Cargo.toml b/Cargo.toml index 496e61e7f86..25a76e5d167 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,9 @@ opt-level = 3 # Uncomment to profile on Linux: # debug = true # lto = false + +[replace] +# If you need to temporarily test Servo with a local fork of some upstream +# crate, add that here. Use the form: +# +# "<crate>:<version>" = { path = "/path/to/local/checkout" } diff --git a/components/config/opts.rs b/components/config/opts.rs index 836e2330341..95917edb062 100644 --- a/components/config/opts.rs +++ b/components/config/opts.rs @@ -32,11 +32,6 @@ pub struct Opts { /// The initial URL to load. pub url: Option<ServoUrl>, - /// How many threads to use for CPU painting (`-t`). - /// - /// Note that painting is sequentialized when using GPU painting. - pub paint_threads: usize, - /// The maximum size of each tile in pixels (`-s`). pub tile_size: usize, @@ -105,7 +100,7 @@ pub struct Opts { /// font for layout tests. pub enable_text_antialiasing: bool, - /// If set with --enable-subpixel, use subpixel antialiasing for glyphs. In the future + /// If set with --disable-subpixel, use subpixel antialiasing for glyphs. In the future /// this will likely become the default, but for now it's opt-in while we work /// out any bugs and improve the implementation. pub enable_subpixel_text_antialiasing: bool, @@ -251,8 +246,8 @@ pub struct DebugOptions { /// Disable antialiasing of rendered text. pub disable_text_aa: bool, - /// Enable subpixel antialiasing of rendered text. - pub enable_subpixel_aa: bool, + /// Disable subpixel antialiasing of rendered text. + pub disable_subpixel_aa: bool, /// Disable antialiasing of rendered text on the HTML canvas element. pub disable_canvas_aa: bool, @@ -354,7 +349,7 @@ impl DebugOptions { "help" => self.help = true, "bubble-widths" => self.bubble_widths = true, "disable-text-aa" => self.disable_text_aa = true, - "enable-subpixel-aa" => self.enable_subpixel_aa = true, + "disable-subpixel-aa" => self.disable_subpixel_aa = true, "disable-canvas-aa" => self.disable_text_aa = true, "dump-style-tree" => self.dump_style_tree = true, "dump-rule-tree" => self.dump_rule_tree = true, @@ -504,7 +499,6 @@ pub fn default_opts() -> Opts { Opts { is_running_problem_test: false, url: Some(ServoUrl::parse("about:blank").unwrap()), - paint_threads: 1, tile_size: 512, device_pixels_per_px: None, time_profiling: None, @@ -693,12 +687,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { .unwrap_or_else(|err| args_fail(&format!("Error parsing option: --device-pixel-ratio ({})", err))) ); - let mut paint_threads: usize = match opt_match.opt_str("t") { - Some(paint_threads_str) => paint_threads_str.parse() - .unwrap_or_else(|err| args_fail(&format!("Error parsing option: -t ({})", err))), - None => cmp::max(num_cpus::get() * 3 / 4, 1), - }; - // If only the flag is present, default to a 5 second period for both profilers let time_profiling = if opt_match.opt_present("p") { match opt_match.opt_str("p") { @@ -748,7 +736,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { let mut bubble_inline_sizes_separately = debug_options.bubble_widths; if debug_options.trace_layout { - paint_threads = 1; layout_threads = Some(1); bubble_inline_sizes_separately = true; } @@ -809,7 +796,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { let opts = Opts { is_running_problem_test: is_running_problem_test, url: Some(url), - paint_threads: paint_threads, tile_size: tile_size, device_pixels_per_px: device_pixels_per_px, time_profiling: time_profiling, @@ -842,7 +828,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { show_debug_parallel_layout: debug_options.show_parallel_layout, paint_flashing: debug_options.paint_flashing, enable_text_antialiasing: !debug_options.disable_text_aa, - enable_subpixel_text_antialiasing: debug_options.enable_subpixel_aa, + enable_subpixel_text_antialiasing: !debug_options.disable_subpixel_aa, enable_canvas_antialiasing: !debug_options.disable_canvas_aa, dump_style_tree: debug_options.dump_style_tree, dump_rule_tree: debug_options.dump_rule_tree, diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index f2aea7a97df..af5590bdad0 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -975,12 +975,23 @@ pub struct GradientBorder { pub outset: SideOffsets2D<f32>, } +/// A border that is made of radial gradient +#[derive(Clone, HeapSizeOf, Deserialize, Serialize)] +pub struct RadialGradientBorder { + /// The gradient info that this border uses, border-image-source. + pub gradient: RadialGradient, + + /// Outsets for the border, as per border-image-outset. + pub outset: SideOffsets2D<f32>, +} + /// Specifies the type of border #[derive(Clone, HeapSizeOf, Deserialize, Serialize)] pub enum BorderDetails { Normal(NormalBorder), Image(ImageBorder), Gradient(GradientBorder), + RadialGradient(RadialGradientBorder), } /// Paints a border. diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index d91050176a9..b48bb607ac7 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -564,20 +564,20 @@ fn build_border_radius(abs_bounds: &Rect<Au>, handle_overlapping_radii(&abs_bounds.size, &BorderRadii { top_left: model::specified_border_radius(border_style.border_top_left_radius, - abs_bounds.size.width), + abs_bounds.size), top_right: model::specified_border_radius(border_style.border_top_right_radius, - abs_bounds.size.width), + abs_bounds.size), bottom_right: model::specified_border_radius(border_style.border_bottom_right_radius, - abs_bounds.size.width), + abs_bounds.size), bottom_left: model::specified_border_radius(border_style.border_bottom_left_radius, - abs_bounds.size.width), + abs_bounds.size), }) } /// Get the border radius for the rectangle inside of a rounded border. This is useful /// for building the clip for the content inside the border. fn build_border_radius_for_inner_rect(outer_rect: &Rect<Au>, - style: ::StyleArc<ServoComputedValues>) + style: &ServoComputedValues) -> BorderRadii<Au> { let mut radii = build_border_radius(&outer_rect, style.get_border()); if radii.is_square() { @@ -603,66 +603,90 @@ fn build_border_radius_for_inner_rect(outer_rect: &Rect<Au>, } fn convert_gradient_stops(gradient_items: &[GradientItem], - length: Au, + total_length: Au, style: &ServoComputedValues) -> Vec<GradientStop> { // Determine the position of each stop per CSS-IMAGES § 3.4. - // - // FIXME(#3908, pcwalton): Make sure later stops can't be behind earlier stops. - let stop_items = gradient_items.iter().filter_map(|item| { + + // Only keep the color stops, discard the color interpolation hints. + let mut stop_items = gradient_items.iter().filter_map(|item| { match *item { - GradientItem::ColorStop(ref stop) => Some(stop), + GradientItem::ColorStop(ref stop) => Some(*stop), _ => None, } }).collect::<Vec<_>>(); - let mut stops = Vec::with_capacity(stop_items.len()); + + assert!(stop_items.len() >= 2); + + // Run the algorithm from + // https://drafts.csswg.org/css-images-3/#color-stop-syntax + + // Step 1: + // If the first color stop does not have a position, set its position to 0%. + { + let first = stop_items.first_mut().unwrap(); + if first.position.is_none() { + first.position = Some(LengthOrPercentage::Percentage(0.0)); + } + } + // If the last color stop does not have a position, set its position to 100%. + { + let last = stop_items.last_mut().unwrap(); + if last.position.is_none() { + last.position = Some(LengthOrPercentage::Percentage(1.0)); + } + } + + // Step 2: Move any stops placed before earlier stops to the + // same position as the preceding stop. + let mut last_stop_position = stop_items.first().unwrap().position.unwrap(); + for stop in stop_items.iter_mut().skip(1) { + if let Some(pos) = stop.position { + if position_to_offset(last_stop_position, total_length) + > position_to_offset(pos, total_length) { + stop.position = Some(last_stop_position); + } + last_stop_position = stop.position.unwrap(); + } + } + + // Step 3: Evenly space stops without position. + // Note: Remove the + 2 if fix_gradient_stops is changed. + let mut stops = Vec::with_capacity(stop_items.len() + 2); let mut stop_run = None; for (i, stop) in stop_items.iter().enumerate() { let offset = match stop.position { None => { if stop_run.is_none() { // Initialize a new stop run. - let start_offset = if i == 0 { - 0.0 - } else { - // `unwrap()` here should never fail because this is the beginning of - // a stop run, which is always bounded by a length or percentage. - position_to_offset(stop_items[i - 1].position.unwrap(), length) - }; - let (end_index, end_offset) = - match stop_items[i..] - .iter() - .enumerate() - .find(|&(_, ref stop)| stop.position.is_some()) { - None => (stop_items.len() - 1, 1.0), - Some((end_index, end_stop)) => { - // `unwrap()` here should never fail because this is the end of - // a stop run, which is always bounded by a length or - // percentage. - (end_index, - position_to_offset(end_stop.position.unwrap(), length)) - } - }; + // `unwrap()` here should never fail because this is the beginning of + // a stop run, which is always bounded by a length or percentage. + let start_offset = + position_to_offset(stop_items[i - 1].position.unwrap(), total_length); + // `unwrap()` here should never fail because this is the end of + // a stop run, which is always bounded by a length or percentage. + let (end_index, end_stop) = stop_items[(i + 1)..] + .iter() + .enumerate() + .find(|&(_, ref stop)| stop.position.is_some()) + .unwrap(); + let end_offset = position_to_offset(end_stop.position.unwrap(), total_length); stop_run = Some(StopRun { start_offset: start_offset, end_offset: end_offset, - start_index: i, - stop_count: end_index - i, + start_index: i - 1, + stop_count: end_index, }) } let stop_run = stop_run.unwrap(); let stop_run_length = stop_run.end_offset - stop_run.start_offset; - if stop_run.stop_count == 0 { - stop_run.end_offset - } else { - stop_run.start_offset + - stop_run_length * (i - stop_run.start_index) as f32 / - (stop_run.stop_count as f32) - } + stop_run.start_offset + + stop_run_length * (i - stop_run.start_index) as f32 / + ((2 + stop_run.stop_count) as f32) } Some(position) => { stop_run = None; - position_to_offset(position, length) + position_to_offset(position, total_length) } }; stops.push(GradientStop { @@ -673,6 +697,35 @@ fn convert_gradient_stops(gradient_items: &[GradientItem], stops } +#[inline] +/// Duplicate the first and last stops if necessary. +/// +/// Explanation by pyfisch: +/// If the last stop is at the same position as the previous stop the +/// last color is ignored by webrender. This differs from the spec +/// (I think so). The implementations of Chrome and Firefox seem +/// to have the same problem but work fine if the position of the last +/// stop is smaller than 100%. (Otherwise they ignore the last stop.) +/// +/// Similarly the first stop is duplicated if it is not placed +/// at the start of the virtual gradient ray. +fn fix_gradient_stops(stops: &mut Vec<GradientStop>) { + if stops.first().unwrap().offset > 0.0 { + let color = stops.first().unwrap().color; + stops.insert(0, GradientStop { + offset: 0.0, + color: color, + }) + } + if stops.last().unwrap().offset < 1.0 { + let color = stops.last().unwrap().color; + stops.push(GradientStop { + offset: 1.0, + color: color, + }) + } +} + /// Returns the the distance to the nearest or farthest corner depending on the comperator. fn get_distance_to_corner<F>(size: &Size2D<Au>, center: &Point2D<Au>, cmp: F) -> Au where F: Fn(Au, Au) -> Au @@ -710,7 +763,7 @@ fn convert_circle_size_keyword(keyword: SizeKeyword, center: &Point2D<Au>) -> Size2D<Au> { use style::values::computed::image::SizeKeyword::*; let radius = match keyword { - ClosestSide => { + ClosestSide | Contain => { let dist = get_distance_to_sides(size, center, ::std::cmp::min); ::std::cmp::min(dist.width, dist.height) } @@ -719,12 +772,7 @@ fn convert_circle_size_keyword(keyword: SizeKeyword, ::std::cmp::max(dist.width, dist.height) } ClosestCorner => get_distance_to_corner(size, center, ::std::cmp::min), - FarthestCorner => get_distance_to_corner(size, center, ::std::cmp::max), - _ => { - // TODO(#16542) - println!("TODO: implement size keyword {:?} for circles", keyword); - Au::new(0) - } + FarthestCorner | Cover => get_distance_to_corner(size, center, ::std::cmp::max), }; Size2D::new(radius, radius) } @@ -736,15 +784,10 @@ fn convert_ellipse_size_keyword(keyword: SizeKeyword, center: &Point2D<Au>) -> Size2D<Au> { use style::values::computed::image::SizeKeyword::*; match keyword { - ClosestSide => get_distance_to_sides(size, center, ::std::cmp::min), + ClosestSide | Contain => get_distance_to_sides(size, center, ::std::cmp::min), FarthestSide => get_distance_to_sides(size, center, ::std::cmp::max), ClosestCorner => get_ellipse_radius(size, center, ::std::cmp::min), - FarthestCorner => get_ellipse_radius(size, center, ::std::cmp::max), - _ => { - // TODO(#16542) - println!("TODO: implement size keyword {:?} for ellipses", keyword); - Size2D::new(Au::new(0), Au::new(0)) - } + FarthestCorner | Cover => get_ellipse_radius(size, center, ::std::cmp::max), } } @@ -1097,7 +1140,14 @@ impl FragmentDisplayListBuilding for Fragment { let length = Au::from_f32_px( (delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0)); - let stops = convert_gradient_stops(stops, length, style); + let mut stops = convert_gradient_stops(stops, length, style); + + // 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); @@ -1131,8 +1181,14 @@ impl FragmentDisplayListBuilding for Fragment { EndingShape::Ellipse(LengthOrPercentageOrKeyword::Keyword(word)) => convert_ellipse_size_keyword(word, &bounds.size, ¢er), }; - let length = Au::from_f32_px(radius.width.to_f32_px().hypot(radius.height.to_f32_px())); - let stops = convert_gradient_stops(stops, length, style); + + let mut stops = convert_gradient_stops(stops, radius.width, style); + // 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, @@ -1222,7 +1278,7 @@ impl FragmentDisplayListBuilding for Fragment { spread_radius: box_shadow.spread_radius, border_radius: model::specified_border_radius(style.get_border() .border_top_left_radius, - absolute_bounds.size.width).width, + absolute_bounds.size).width, clip_mode: if box_shadow.inset { BoxShadowClipMode::Inset } else { @@ -1321,8 +1377,24 @@ impl FragmentDisplayListBuilding for Fragment { }), })); } - GradientKind::Radial(_, _) => { - // TODO(#16638): Handle border-image with radial gradient. + GradientKind::Radial(ref shape, ref center) => { + let grad = self.convert_radial_gradient(&bounds, + &gradient.items[..], + shape, + center, + gradient.repeating, + style); + state.add_display_item(DisplayItem::Border(box BorderDisplayItem { + base: base, + border_widths: border.to_physical(style.writing_mode), + details: BorderDetails::RadialGradient( + display_list::RadialGradientBorder { + gradient: grad, + + // TODO(gw): Support border-image-outset + outset: SideOffsets2D::zero(), + }), + })); } } } @@ -2304,7 +2376,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { let mut clip = ClippingRegion::from_rect(&clip_rect); let border_radii = build_border_radius_for_inner_rect(&border_box, - self.fragment.style.clone()); + &self.fragment.style); if !border_radii.is_square() { clip.intersect_with_rounded_rect(&clip_rect, &border_radii) } @@ -2326,7 +2398,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { let clip_rect = Rect::new(Point2D::zero(), content_box.size); let mut clip = ClippingRegion::from_rect(&clip_rect); - let radii = build_border_radius_for_inner_rect(&border_box, self.fragment.style.clone()); + let radii = build_border_radius_for_inner_rect(&border_box, &self.fragment.style); if !radii.is_square() { clip.intersect_with_rounded_rect(&clip_rect, &radii) } @@ -2702,12 +2774,10 @@ struct StopRun { fn position_to_offset(position: LengthOrPercentage, Au(total_length): Au) -> f32 { match position { - LengthOrPercentage::Length(Au(length)) => { - (1.0f32).min(length as f32 / total_length as f32) - } + LengthOrPercentage::Length(Au(length)) => length as f32 / total_length as f32, LengthOrPercentage::Percentage(percentage) => percentage as f32, LengthOrPercentage::Calc(calc) => - (1.0f32).min(calc.percentage() + (calc.length().0 as f32) / (total_length as f32)), + calc.percentage() + (calc.length().0 as f32) / (total_length as f32), } } diff --git a/components/layout/model.rs b/components/layout/model.rs index 27f0b2ce7a7..531d37038d7 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -478,10 +478,22 @@ pub fn specified(length: LengthOrPercentage, containing_length: Au) -> Au { } } -pub fn specified_border_radius(radius: BorderRadiusSize, containing_length: Au) -> Size2D<Au> { +/// Computes a border radius size against the containing size. +/// +/// Note that percentages in `border-radius` are resolved against the relevant +/// box dimension instead of only against the width per [1]: +/// +/// > Percentages: Refer to corresponding dimension of the border box. +/// +/// [1]: https://drafts.csswg.org/css-backgrounds-3/#border-radius +pub fn specified_border_radius( + radius: BorderRadiusSize, + containing_size: Size2D<Au>) + -> Size2D<Au> +{ let generics::BorderRadiusSize(size) = radius; - let w = specified(size.width, containing_length); - let h = specified(size.height, containing_length); + let w = specified(size.width, containing_size.width); + let h = specified(size.height, containing_size.height); Size2D::new(w, h) } diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index eca0837d6a8..cd450bd273e 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -353,15 +353,35 @@ impl WebRenderDisplayItemConverter for DisplayItem { } } BorderDetails::Gradient(ref gradient) => { + let extend_mode = if gradient.gradient.repeating { + ExtendMode::Repeat + } else { + ExtendMode::Clamp + }; webrender_traits::BorderDetails::Gradient(webrender_traits::GradientBorder { gradient: builder.create_gradient( gradient.gradient.start_point.to_pointf(), gradient.gradient.end_point.to_pointf(), gradient.gradient.stops.clone(), - ExtendMode::Clamp), + extend_mode), outset: gradient.outset, }) } + BorderDetails::RadialGradient(ref gradient) => { + let extend_mode = if gradient.gradient.repeating { + ExtendMode::Repeat + } else { + ExtendMode::Clamp + }; + webrender_traits::BorderDetails::RadialGradient(webrender_traits::RadialGradientBorder { + gradient: builder.create_radial_gradient( + gradient.gradient.center.to_pointf(), + gradient.gradient.radius.to_sizef(), + gradient.gradient.stops.clone(), + extend_mode), + outset: gradient.outset, + }) + } }; builder.push_border(rect, clip, widths, details); diff --git a/components/net/subresource_integrity.rs b/components/net/subresource_integrity.rs index 68cc6b7c930..ae6cfe9c14a 100644 --- a/components/net/subresource_integrity.rs +++ b/components/net/subresource_integrity.rs @@ -4,7 +4,7 @@ use base64; use net_traits::response::{Response, ResponseBody, ResponseType}; -use openssl::hash::{MessageDigest, hash}; +use openssl::hash::{MessageDigest, hash2}; use std::iter::Filter; use std::str::Split; use std::sync::MutexGuard; @@ -119,7 +119,7 @@ fn apply_algorithm_to_response(body: MutexGuard<ResponseBody>, message_digest: MessageDigest) -> String { if let ResponseBody::Done(ref vec) = *body { - let response_digest = hash(message_digest, vec).unwrap(); + let response_digest = hash2(message_digest, vec).unwrap(); //Now hash2 base64::encode(&response_digest) } else { unreachable!("Tried to calculate digest of incomplete response body") diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 207c521d63b..63f1a567124 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -65,6 +65,6 @@ kernel32-sys = "0.2" [build-dependencies] lazy_static = "0.2" log = "0.3" -bindgen = { version = "0.22", optional = true } +bindgen = { version = "0.24", optional = true } regex = {version = "0.2", optional = true} walkdir = "1.0" diff --git a/components/style/binding_tools/regen_atoms.py b/components/style/binding_tools/regen_atoms.py index 0950c0d7212..05acee47a7d 100755 --- a/components/style/binding_tools/regen_atoms.py +++ b/components/style/binding_tools/regen_atoms.py @@ -97,7 +97,9 @@ class Atom: def collect_atoms(objdir): atoms = [] for source in SOURCES: - with open(os.path.join(objdir, source.FILE)) as f: + path = os.path.abspath(os.path.join(objdir, source.FILE)) + print("cargo:rerun-if-changed={}".format(path)) + with open(path) as f: for line in f.readlines(): result = re.match(source.PATTERN, line) if result: @@ -255,15 +257,14 @@ def write_pseudo_element_helper(atoms, target_filename): f.write("}\n") -def generate_atoms(dist): - style_path = os.path.dirname(os.path.dirname(__file__)) +def generate_atoms(dist, out): atoms = collect_atoms(dist) - write_atom_macro(atoms, os.path.join(style_path, "gecko_string_cache/atom_macro.rs")) - write_pseudo_element_helper(atoms, os.path.join(style_path, "gecko/generated/gecko_pseudo_element_helper.rs")) + write_atom_macro(atoms, os.path.join(out, "atom_macro.rs")) + write_pseudo_element_helper(atoms, os.path.join(out, "pseudo_element_helper.rs")) if __name__ == "__main__": - if len(sys.argv) != 2: - print("Usage: {} objdir".format(sys.argv[0])) + if len(sys.argv) != 3: + print("Usage: {} dist out".format(sys.argv[0])) exit(2) - generate_atoms(os.path.join(sys.argv[1], "dist")) + generate_atoms(sys.argv[1], sys.argv[2]) diff --git a/components/style/build.rs b/components/style/build.rs index 5ecaf902c2b..8d40ccb9969 100644 --- a/components/style/build.rs +++ b/components/style/build.rs @@ -2,7 +2,6 @@ * 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/. */ -#[cfg(feature = "gecko")] #[macro_use] extern crate lazy_static; #[cfg(feature = "bindgen")] @@ -53,6 +52,10 @@ fn find_python() -> String { }.to_owned() } +lazy_static! { + pub static ref PYTHON: String = env::var("PYTHON").ok().unwrap_or_else(find_python); +} + fn generate_properties() { for entry in WalkDir::new("properties") { let entry = entry.unwrap(); @@ -64,10 +67,9 @@ fn generate_properties() { } } - let python = env::var("PYTHON").ok().unwrap_or_else(find_python); let script = Path::new(file!()).parent().unwrap().join("properties").join("build.py"); let product = if cfg!(feature = "gecko") { "gecko" } else { "servo" }; - let status = Command::new(python) + let status = Command::new(&*PYTHON) .arg(&script) .arg(product) .arg("style-crate") diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs index 85d80fae1d4..af8d1c72252 100644 --- a/components/style/build_gecko.rs +++ b/components/style/build_gecko.rs @@ -3,35 +3,32 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ mod common { - use std::env; - use std::path::PathBuf; + use std::{env, fs, io}; + use std::path::{Path, PathBuf}; lazy_static! { pub static ref OUTDIR_PATH: PathBuf = PathBuf::from(env::var("OUT_DIR").unwrap()).join("gecko"); } - pub const STRUCTS_DEBUG_FILE: &'static str = "structs_debug.rs"; - pub const STRUCTS_RELEASE_FILE: &'static str = "structs_release.rs"; - pub const BINDINGS_FILE: &'static str = "bindings.rs"; - - #[derive(Clone, Copy, PartialEq)] - pub enum BuildType { - Debug, - Release, - } - - pub fn structs_file(build_type: BuildType) -> &'static str { - match build_type { - BuildType::Debug => STRUCTS_DEBUG_FILE, - BuildType::Release => STRUCTS_RELEASE_FILE + /// Copy contents of one directory into another. + /// It currently only does a shallow copy. + pub fn copy_dir<P, Q, F>(from: P, to: Q, callback: F) -> io::Result<()> + where P: AsRef<Path>, Q: AsRef<Path>, F: Fn(&Path) { + let to = to.as_ref(); + for entry in from.as_ref().read_dir()? { + let entry = entry?; + let path = entry.path(); + callback(&path); + fs::copy(&path, to.join(entry.file_name()))?; } + Ok(()) } } #[cfg(feature = "bindgen")] mod bindings { use bindgen::{Builder, CodegenConfig}; - use bindgen::chooser::{EnumVariantCustomBehavior, EnumVariantValue, TypeChooser}; + use bindgen::callbacks::{EnumVariantCustomBehavior, EnumVariantValue, ParseCallbacks}; use regex::Regex; use std::cmp; use std::collections::HashSet; @@ -39,9 +36,28 @@ mod bindings { use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::{Path, PathBuf}; + use std::process::{Command, exit}; use std::sync::Mutex; use std::time::SystemTime; use super::common::*; + use super::super::PYTHON; + + const STRUCTS_DEBUG_FILE: &'static str = "structs_debug.rs"; + const STRUCTS_RELEASE_FILE: &'static str = "structs_release.rs"; + const BINDINGS_FILE: &'static str = "bindings.rs"; + + #[derive(Clone, Copy, PartialEq)] + enum BuildType { + Debug, + Release, + } + + fn structs_file(build_type: BuildType) -> &'static str { + match build_type { + BuildType::Debug => STRUCTS_DEBUG_FILE, + BuildType::Release => STRUCTS_RELEASE_FILE + } + } lazy_static! { static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap(); @@ -60,11 +76,6 @@ mod bindings { pub static ref LAST_MODIFIED: Mutex<SystemTime> = Mutex::new(get_modified_time(&env::current_exe().unwrap()) .expect("Failed to get modified time of executable")); - static ref BINDING_DISTDIR_PATH: PathBuf = { - let path = DISTDIR_PATH.join("rust_bindings/style"); - fs::create_dir_all(&path).expect("Fail to create bindings dir in dist"); - path - }; } fn get_modified_time(file: &Path) -> Option<SystemTime> { @@ -237,8 +248,6 @@ mod bindings { } let bytes = result.into_bytes(); File::create(&out_file).unwrap().write_all(&bytes).expect("Unable to write output"); - File::create(&BINDING_DISTDIR_PATH.join(file)).unwrap() - .write_all(&bytes).expect("Unable to write output to binding dist"); } fn get_arc_types() -> Vec<String> { @@ -261,7 +270,7 @@ mod bindings { #[derive(Debug)] struct Callbacks; - impl TypeChooser for Callbacks { + impl ParseCallbacks for Callbacks { fn enum_variant_behavior(&self, enum_name: Option<&str>, variant_name: &str, @@ -276,7 +285,7 @@ mod bindings { } } - pub fn generate_structs(build_type: BuildType) { + fn generate_structs(build_type: BuildType) { let mut builder = Builder::get_initial_builder(build_type) .enable_cxx_namespaces() .with_codegen_config(CodegenConfig { @@ -284,10 +293,10 @@ mod bindings { vars: true, ..CodegenConfig::nothing() }) - .include(add_include("nsCSSPseudoClasses.h")) // servo/rust-bindgen#599 - .header(add_include("nsStyleStruct.h")) + .header(add_include("nsCSSPseudoClasses.h")) // servo/rust-bindgen#599 + .include(add_include("nsStyleStruct.h")) .include(add_include("mozilla/ServoPropPrefList.h")) - .header(add_include("mozilla/StyleAnimationValue.h")) + .include(add_include("mozilla/StyleAnimationValue.h")) .include(add_include("gfxFontConstants.h")) .include(add_include("nsThemeConstants.h")) .include(add_include("mozilla/dom/AnimationEffectReadOnlyBinding.h")) @@ -315,7 +324,7 @@ mod bindings { .bitfield_enum("nsChangeHint") .bitfield_enum("nsRestyleHint") .constified_enum("UpdateAnimationsTasks") - .type_chooser(Box::new(Callbacks)); + .parse_callbacks(Box::new(Callbacks)); let whitelist_vars = [ "NS_THEME_.*", "NODE_.*", @@ -508,8 +517,8 @@ mod bindings { "StyleAnimationValue", // pulls in a whole bunch of stuff we don't need in the bindings ]; let blacklist = [ - ".*_char_traits", - ".*_incompatible_char_type", + ".*char_traits", + ".*incompatible_char_type", ]; struct MappedGenericType { @@ -565,7 +574,7 @@ mod bindings { write_binding_file(builder, structs_file(build_type), &fixups); } - pub fn setup_logging() { + fn setup_logging() -> bool { use log; struct BuildLogger { @@ -594,20 +603,23 @@ mod bindings { } } - log::set_logger(|log_level| { - log_level.set(log::LogLevelFilter::Debug); - Box::new(BuildLogger { - file: env::var("STYLO_BUILD_LOG").ok().and_then(|path| { - fs::File::create(path).ok().map(Mutex::new) - }), - filter: env::var("STYLO_BUILD_FILTER").ok() - .unwrap_or_else(|| "bindgen".to_owned()), + if let Ok(path) = env::var("STYLO_BUILD_LOG") { + log::set_logger(|log_level| { + log_level.set(log::LogLevelFilter::Debug); + Box::new(BuildLogger { + file: fs::File::create(path).ok().map(Mutex::new), + filter: env::var("STYLO_BUILD_FILTER").ok() + .unwrap_or_else(|| "bindgen".to_owned()), + }) }) - }) - .expect("Failed to set logger."); + .expect("Failed to set logger."); + true + } else { + false + } } - pub fn generate_bindings() { + fn generate_bindings() { let mut builder = Builder::get_initial_builder(BuildType::Release) .disable_name_namespacing() .with_codegen_config(CodegenConfig { @@ -624,6 +636,7 @@ mod bindings { .whitelisted_function("Gecko_.*"); let structs_types = [ "mozilla::css::GridTemplateAreasValue", + "mozilla::css::ImageValue", "mozilla::css::URLValue", "mozilla::Side", "RawGeckoAnimationPropertySegment", @@ -764,6 +777,11 @@ mod bindings { "RawGeckoServoStyleRuleList", ]; for &ty in structs_types.iter() { + // XXX cku: will be removed in Part 2. + if ty.starts_with("mozilla::css::ImageValue") { + builder = builder + .raw_line("#[allow(unused_imports)]"); + } builder = builder.hide_type(ty) .raw_line(format!("use gecko_bindings::structs::{};", ty)); // TODO this is hacky, figure out a better way to do it without @@ -810,52 +828,70 @@ mod bindings { } write_binding_file(builder, BINDINGS_FILE, &Vec::new()); } -} -#[cfg(not(feature = "bindgen"))] -mod bindings { - use std::fs; - use std::path::{Path, PathBuf}; - use super::common::*; - - lazy_static! { - static ref BINDINGS_PATH: PathBuf = Path::new(file!()).parent().unwrap().join("gecko_bindings"); + fn generate_atoms() { + let script = Path::new(file!()).parent().unwrap().join("binding_tools").join("regen_atoms.py"); + println!("cargo:rerun-if-changed={}", script.display()); + let status = Command::new(&*PYTHON) + .arg(&script) + .arg(DISTDIR_PATH.as_os_str()) + .arg(OUTDIR_PATH.as_os_str()) + .status() + .unwrap(); + if !status.success() { + exit(1); + } } - pub fn setup_logging() {} + pub fn generate() { + use std::thread; + macro_rules! run_tasks { + ($($task:expr,)+) => { + if setup_logging() { + $($task;)+ + } else { + let threads = vec![$( thread::spawn(|| $task) ),+]; + for thread in threads.into_iter() { + thread.join().unwrap(); + } + } + } + } + run_tasks! { + generate_structs(BuildType::Debug), + generate_structs(BuildType::Release), + generate_bindings(), + generate_atoms(), + } - pub fn generate_structs(build_type: BuildType) { - let file = structs_file(build_type); - let source = BINDINGS_PATH.join(file); - println!("cargo:rerun-if-changed={}", source.display()); - fs::copy(source, OUTDIR_PATH.join(file)).unwrap(); + // Copy all generated files to dist for the binding package + let path = DISTDIR_PATH.join("rust_bindings/style"); + if path.exists() { + fs::remove_dir_all(&path).expect("Fail to remove binding dir in dist"); + } + fs::create_dir_all(&path).expect("Fail to create bindings dir in dist"); + copy_dir(&*OUTDIR_PATH, &path, |_| {}).expect("Fail to copy generated files to dist dir"); } +} - pub fn generate_bindings() { - let source = BINDINGS_PATH.join(BINDINGS_FILE); - println!("cargo:rerun-if-changed={}", source.display()); - fs::copy(source, OUTDIR_PATH.join(BINDINGS_FILE)).unwrap(); +#[cfg(not(feature = "bindgen"))] +mod bindings { + use std::path::Path; + use super::common::*; + + pub fn generate() { + let dir = Path::new(file!()).parent().unwrap().join("gecko/generated"); + println!("cargo:rerun-if-changed={}", dir.display()); + copy_dir(&dir, &*OUTDIR_PATH, |path| { + println!("cargo:rerun-if-changed={}", path.display()); + }).expect("Fail to copy generated files to out dir"); } } pub fn generate() { use self::common::*; - use std::{env, fs, thread}; + use std::fs; println!("cargo:rerun-if-changed=build_gecko.rs"); fs::create_dir_all(&*OUTDIR_PATH).unwrap(); - bindings::setup_logging(); - if env::var("STYLO_BUILD_LOG").is_ok() { - bindings::generate_structs(BuildType::Debug); - bindings::generate_structs(BuildType::Release); - bindings::generate_bindings(); - } else { - let threads = vec![ - thread::spawn(|| bindings::generate_structs(BuildType::Debug)), - thread::spawn(|| bindings::generate_structs(BuildType::Release)), - thread::spawn(|| bindings::generate_bindings()), - ]; - for t in threads.into_iter() { - t.join().unwrap(); - } - } + bindings::generate(); } diff --git a/components/style/gecko_string_cache/atom_macro.rs b/components/style/gecko/generated/atom_macro.rs index 6d99ed66fb1..6d99ed66fb1 100644 --- a/components/style/gecko_string_cache/atom_macro.rs +++ b/components/style/gecko/generated/atom_macro.rs diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko/generated/bindings.rs index 6aab0a41d7d..6aab0a41d7d 100644 --- a/components/style/gecko_bindings/bindings.rs +++ b/components/style/gecko/generated/bindings.rs diff --git a/components/style/gecko/generated/gecko_pseudo_element_helper.rs b/components/style/gecko/generated/pseudo_element_helper.rs index e9d61b03bd8..e9d61b03bd8 100644 --- a/components/style/gecko/generated/gecko_pseudo_element_helper.rs +++ b/components/style/gecko/generated/pseudo_element_helper.rs diff --git a/components/style/gecko_bindings/structs_debug.rs b/components/style/gecko/generated/structs_debug.rs index 3c8c4afa4e1..3c8c4afa4e1 100644 --- a/components/style/gecko_bindings/structs_debug.rs +++ b/components/style/gecko/generated/structs_debug.rs diff --git a/components/style/gecko_bindings/structs_release.rs b/components/style/gecko/generated/structs_release.rs index d69c258bc05..d69c258bc05 100644 --- a/components/style/gecko_bindings/structs_release.rs +++ b/components/style/gecko/generated/structs_release.rs diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index 4add99e36e8..af7dd323faf 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -165,7 +165,7 @@ impl PseudoElement { }} } - include!("generated/gecko_pseudo_element_helper.rs"); + include!(concat!(env!("OUT_DIR"), "/gecko/pseudo_element_helper.rs")); None } @@ -190,7 +190,7 @@ impl PseudoElement { }} } - include!("generated/gecko_pseudo_element_helper.rs"); + include!(concat!(env!("OUT_DIR"), "/gecko/pseudo_element_helper.rs")); None } @@ -492,7 +492,7 @@ impl SelectorImpl { }} } - include!("generated/gecko_pseudo_element_helper.rs") + include!(concat!(env!("OUT_DIR"), "/gecko/pseudo_element_helper.rs")); } #[inline] diff --git a/components/style/gecko_string_cache/mod.rs b/components/style/gecko_string_cache/mod.rs index 741a4a3e534..428d522be11 100644 --- a/components/style/gecko_string_cache/mod.rs +++ b/components/style/gecko_string_cache/mod.rs @@ -25,7 +25,10 @@ use std::slice; #[macro_use] #[allow(improper_ctypes, non_camel_case_types, missing_docs)] -pub mod atom_macro; +pub mod atom_macro { + include!(concat!(env!("OUT_DIR"), "/gecko/atom_macro.rs")); +} + #[macro_use] pub mod namespace; diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 6f34a264cdb..159f5de5884 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -2081,7 +2081,7 @@ ${helpers.single_keyword_system("font-variant-position", #[inline] pub fn get_initial_value() -> computed_value::T { - ::gecko_bindings::structs::NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER + ::gecko_bindings::structs::NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER as f32 } pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> { diff --git a/ports/cef/core.rs b/ports/cef/core.rs index 7db9246355c..7fcac74d848 100644 --- a/ports/cef/core.rs +++ b/ports/cef/core.rs @@ -68,7 +68,6 @@ pub extern "C" fn cef_initialize(args: *const cef_main_args_t, }; let mut temp_opts = opts::default_opts(); - temp_opts.paint_threads = rendering_threads; temp_opts.headless = false; temp_opts.hard_fail = false; temp_opts.enable_text_antialiasing = true; diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index a3016014792..da182198ac4 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -18,6 +18,7 @@ import shutil import subprocess import sys import urllib2 +import glob from mach.decorators import ( CommandArgument, @@ -26,7 +27,7 @@ from mach.decorators import ( ) import servo.bootstrap as bootstrap -from servo.command_base import CommandBase, BIN_SUFFIX +from servo.command_base import CommandBase, BIN_SUFFIX, cd from servo.util import delete, download_bytes, download_file, extract, host_triple @@ -346,3 +347,175 @@ class MachCommands(CommandBase): elif not force: print("Nothing done. " "Run `./mach clean-nightlies -f` to actually remove.") + + @Command('clean-cargo-cache', + description='Clean unused Cargo packages', + category='bootstrap') + @CommandArgument('--force', '-f', + action='store_true', + help='Actually remove stuff') + @CommandArgument('--show-size', '-s', + action='store_true', + help='Show packages size') + @CommandArgument('--keep', + default='1', + help='Keep up to this many most recent dependencies') + @CommandArgument('--custom-path', '-c', + action='store_true', + help='Get Cargo path from CARGO_HOME environment variable') + def clean_cargo_cache(self, force=False, show_size=False, keep=None, custom_path=False): + def get_size(path): + if os.path.isfile(path): + return os.path.getsize(path) / (1024 * 1024.0) + total_size = 0 + for dirpath, dirnames, filenames in os.walk(path): + for f in filenames: + fp = os.path.join(dirpath, f) + total_size += os.path.getsize(fp) + return total_size / (1024 * 1024.0) + + removing_anything = False + packages = { + 'crates': {}, + 'git': {}, + } + import toml + if os.environ.get("CARGO_HOME", "") and custom_path: + cargo_dir = os.environ.get("CARGO_HOME") + else: + cargo_dir = path.join(self.context.topdir, ".cargo") + cargo_file = open(path.join(self.context.topdir, "Cargo.lock")) + content = toml.load(cargo_file) + + for package in content.get("package", []): + source = package.get("source", "") + version = package["version"] + if source == u"registry+https://github.com/rust-lang/crates.io-index": + crate_name = "{}-{}".format(package["name"], version) + if not packages["crates"].get(crate_name, False): + packages["crates"][package["name"]] = { + "current": [], + "exist": [], + } + packages["crates"][package["name"]]["current"].append(crate_name) + elif source.startswith("git+"): + name = source.split("#")[0].split("/")[-1].replace(".git", "") + branch = "" + crate_name = "{}-{}".format(package["name"], source.split("#")[1]) + crate_branch = name.split("?") + if len(crate_branch) > 1: + branch = crate_branch[1].replace("branch=", "") + name = crate_branch[0] + + if not packages["git"].get(name, False): + packages["git"][name] = { + "current": [], + "exist": [], + } + packages["git"][name]["current"].append(source.split("#")[1][:7]) + if branch: + packages["git"][name]["current"].append(branch) + + crates_dir = path.join(cargo_dir, "registry") + crates_cache_dir = "" + crates_src_dir = "" + if os.path.isdir(path.join(crates_dir, "cache")): + for p in os.listdir(path.join(crates_dir, "cache")): + crates_cache_dir = path.join(crates_dir, "cache", p) + crates_src_dir = path.join(crates_dir, "src", p) + + git_dir = path.join(cargo_dir, "git") + git_db_dir = path.join(git_dir, "db") + git_checkout_dir = path.join(git_dir, "checkouts") + git_db_list = filter(lambda f: not f.startswith('.'), os.listdir(git_db_dir)) + git_checkout_list = os.listdir(git_checkout_dir) + + for d in list(set(git_db_list + git_checkout_list)): + crate_name = d.replace("-{}".format(d.split("-")[-1]), "") + if not packages["git"].get(crate_name, False): + packages["git"][crate_name] = { + "current": [], + "exist": [], + } + if os.path.isdir(path.join(git_checkout_dir, d)): + for d2 in os.listdir(path.join(git_checkout_dir, d)): + dep_path = path.join(git_checkout_dir, d, d2) + if os.path.isdir(dep_path): + packages["git"][crate_name]["exist"].append((path.getmtime(dep_path), d, d2)) + elif os.path.isdir(path.join(git_db_dir, d)): + packages["git"][crate_name]["exist"].append(("db", d, "")) + + for d in os.listdir(crates_src_dir): + crate_name = re.sub(r"\-\d+(\.\d+){1,3}.+", "", d) + if not packages["crates"].get(crate_name, False): + packages["crates"][crate_name] = { + "current": [], + "exist": [], + } + packages["crates"][crate_name]["exist"].append(d) + + total_size = 0 + for packages_type in ["git", "crates"]: + sorted_packages = sorted(packages[packages_type]) + for crate_name in sorted_packages: + crate_count = 0 + existed_crates = packages[packages_type][crate_name]["exist"] + for exist in sorted(existed_crates, reverse=True): + current_crate = packages[packages_type][crate_name]["current"] + size = 0 + exist_name = exist + exist_item = exist[2] if packages_type == "git" else exist + if exist_item not in current_crate: + crate_count += 1 + removing_anything = True + if int(crate_count) >= int(keep) or not current_crate: + crate_paths = [] + if packages_type == "git": + exist_checkout_path = path.join(git_checkout_dir, exist[1]) + exist_db_path = path.join(git_db_dir, exist[1]) + exist_name = path.join(exist[1], exist[2]) + exist_path = path.join(git_checkout_dir, exist_name) + + if exist[0] == "db": + crate_paths.append(exist_db_path) + crate_count += -1 + else: + crate_paths.append(exist_path) + + # remove crate from checkout if doesn't exist in db directory + if not os.path.isdir(exist_db_path): + crate_count += -1 + + with cd(path.join(exist_path, ".git", "objects", "pack")): + for pack in glob.glob("*"): + pack_path = path.join(exist_db_path, "objects", "pack", pack) + if os.path.exists(pack_path): + crate_paths.append(pack_path) + + if len(os.listdir(exist_checkout_path)) <= 1: + crate_paths.append(exist_checkout_path) + if os.path.isdir(exist_db_path): + crate_paths.append(exist_db_path) + else: + crate_paths.append(path.join(crates_cache_dir, "{}.crate".format(exist))) + crate_paths.append(path.join(crates_src_dir, exist)) + + size = sum(get_size(p) for p in crate_paths) if show_size else 0 + total_size += size + print_msg = (exist_name, " ({}MB)".format(round(size, 2)) if show_size else "", cargo_dir) + if force: + print("Removing `{}`{} package from {}".format(*print_msg)) + for crate_path in crate_paths: + if os.path.exists(crate_path): + delete(crate_path) + else: + print("Would remove `{}`{} package from {}".format(*print_msg)) + + if removing_anything and show_size: + print("\nTotal size of {} MB".format(round(total_size, 2))) + + if not removing_anything: + print("Nothing to remove.") + elif not force: + print("\nNothing done. " + "Run `./mach clean-cargo-cache -f` to actually remove.") diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py index 792b6071145..3a33f5f3b0d 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -24,7 +24,7 @@ from mach.decorators import ( Command, ) -from servo.command_base import CommandBase, cd, call, BIN_SUFFIX, find_dep_path_newest +from servo.command_base import CommandBase, cd, call, BIN_SUFFIX from servo.util import host_triple @@ -413,7 +413,6 @@ class MachCommands(CommandBase): self.ensure_bootstrapped() env = self.build_env(is_build=True, geckolib=True) - geckolib_build_path = path.join(self.context.topdir, "target", "geckolib").encode("UTF-8") ret = None opts = [] @@ -433,14 +432,6 @@ class MachCommands(CommandBase): if features: opts += ["--features", ' '.join(features)] - if with_gecko is not None: - print("Generating atoms data...") - run_file = path.join(self.context.topdir, "components", - "style", "binding_tools", "regen_atoms.py") - run_globals = {"__file__": run_file} - execfile(run_file, run_globals) - run_globals["generate_atoms"](env["MOZ_DIST"]) - build_start = time() with cd(path.join("ports", "geckolib")): ret = call(["cargo", "build"] + opts, env=env, verbose=verbose) @@ -451,15 +442,6 @@ class MachCommands(CommandBase): print("GeckoLib build completed in %s" % format_duration(elapsed)) - if with_gecko is not None: - print("Copying binding files to style/gecko_bindings...") - build_path = path.join(geckolib_build_path, "release" if release else "debug", "") - target_style_path = find_dep_path_newest("style", build_path) - out_gecko_path = path.join(target_style_path, "out", "gecko") - bindings_path = path.join(self.context.topdir, "components", "style", "gecko_bindings") - for f in ["bindings.rs", "structs_debug.rs", "structs_release.rs"]: - shutil.copy(path.join(out_gecko_path, f), bindings_path) - return ret @Command('clean', diff --git a/servo-tidy.toml b/servo-tidy.toml index 6bc386c85f0..4be11ad234a 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -31,16 +31,19 @@ num = [] [ignore] # Ignored packages with duplicated versions -packages = ["bitflags"] +packages = [ + "bitflags", + "libloading", # Conflicting version is only used at build-time by geckolib. +] # Files that are ignored for all tidy and lint checks. files = [ # Helper macro where actually a pseudo-element per line makes sense. "./components/style/gecko/non_ts_pseudo_class_list.rs", # Generated and upstream code combined with our own. Could use cleanup - "./components/style/gecko_bindings/bindings.rs", - "./components/style/gecko_bindings/structs_debug.rs", - "./components/style/gecko_bindings/structs_release.rs", - "./components/style/gecko_string_cache/atom_macro.rs", + "./components/style/gecko/generated/bindings.rs", + "./components/style/gecko/generated/structs_debug.rs", + "./components/style/gecko/generated/structs_release.rs", + "./components/style/gecko/generated/atom_macro.rs", "./resources/hsts_preload.json", "./tests/wpt/metadata/MANIFEST.json", "./tests/wpt/metadata-css/MANIFEST.json", diff --git a/tests/unit/stylo/check_bindings.py b/tests/unit/stylo/check_bindings.py index db5a11cc3a7..f4cdc5b6655 100755 --- a/tests/unit/stylo/check_bindings.py +++ b/tests/unit/stylo/check_bindings.py @@ -8,7 +8,7 @@ import os import re ROOT_PATH = os.path.join("..", "..", "..") -INPUT_FILE = os.path.join(ROOT_PATH, "components", "style", "gecko_bindings", "bindings.rs") +INPUT_FILE = os.path.join(ROOT_PATH, "components", "style", "gecko", "generated", "bindings.rs") OUTPUT_FILE = os.path.join(os.environ["OUT_DIR"], "check_bindings.rs") GLUE_FILE = os.path.join(ROOT_PATH, "ports", "geckolib", "glue.rs") GLUE_OUTPUT_FILE = os.path.join(os.environ["OUT_DIR"], "glue.rs") diff --git a/tests/unit/stylo/sanity_checks.rs b/tests/unit/stylo/sanity_checks.rs index 008779721be..ce0576fe6cf 100644 --- a/tests/unit/stylo/sanity_checks.rs +++ b/tests/unit/stylo/sanity_checks.rs @@ -46,7 +46,7 @@ fn assert_basic_pseudo_elements() { }; } - include!("../../../components/style/gecko/generated/gecko_pseudo_element_helper.rs"); + include!("../../../components/style/gecko/generated/pseudo_element_helper.rs"); assert!(saw_before); assert!(saw_after); diff --git a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-origin-013.htm.ini b/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-origin-013.htm.ini deleted file mode 100644 index 901fffe5fea..00000000000 --- a/tests/wpt/metadata-css/css-transforms-1_dev/html/transform-origin-013.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[transform-origin-013.htm] - type: reftest - expected: FAIL |