Auto merge of #23827 - emilio:gecko-sync, r=emilio,manishearth

style: Sync changes from mozilla-central, and update euclid

See individual commits for details.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23827)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-07-23 18:42:00 -04:00 committed by GitHub
commit 8f7440f368
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
175 changed files with 1481 additions and 1441 deletions

View file

@ -16,8 +16,7 @@ path = "lib.rs"
doctest = false
[features]
gecko = ["style_traits/gecko", "fallible/known_system_malloc"]
use_bindgen = ["bindgen", "regex", "toml"]
gecko = ["style_traits/gecko", "fallible/known_system_malloc", "bindgen", "regex", "toml"]
servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5ever",
"cssparser/serde", "encoding_rs", "malloc_size_of/servo", "arrayvec/use_union",
"servo_url", "string_cache", "crossbeam-channel", "to_shmem/servo", "servo_arc/servo"]
@ -37,7 +36,7 @@ crossbeam-channel = { version = "0.3", optional = true }
derive_more = "0.13"
new_debug_unreachable = "1.0"
encoding_rs = {version = "0.8", optional = true}
euclid = "0.19"
euclid = "0.20"
fallible = { path = "../fallible" }
fxhash = "0.2"
hashglobe = { path = "../hashglobe" }

View file

@ -4,13 +4,13 @@
#[macro_use]
extern crate lazy_static;
#[cfg(feature = "bindgen")]
#[cfg(feature = "gecko")]
extern crate bindgen;
#[cfg(feature = "bindgen")]
#[cfg(feature = "gecko")]
extern crate log;
#[cfg(feature = "bindgen")]
#[cfg(feature = "gecko")]
extern crate regex;
#[cfg(feature = "bindgen")]
#[cfg(feature = "gecko")]
extern crate toml;
extern crate walkdir;

View file

@ -2,458 +2,406 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
mod common {
use std::env;
use std::path::PathBuf;
use super::PYTHON;
use bindgen::{Builder, CodegenConfig};
use regex::Regex;
use std::cmp;
use std::collections::HashSet;
use std::env;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::process::{exit, Command};
use std::slice;
use std::sync::Mutex;
use std::time::SystemTime;
use toml;
use toml::value::Table;
lazy_static! {
pub static ref OUTDIR_PATH: PathBuf =
PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("gecko");
lazy_static! {
static ref OUTDIR_PATH: PathBuf = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("gecko");
}
const STRUCTS_FILE: &'static str = "structs.rs";
fn read_config(path: &PathBuf) -> Table {
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
update_last_modified(&path);
let mut contents = String::new();
File::open(path)
.expect("Failed to open config file")
.read_to_string(&mut contents)
.expect("Failed to read config file");
match toml::from_str::<Table>(&contents) {
Ok(result) => result,
Err(e) => panic!("Failed to parse config file: {}", e),
}
}
#[cfg(feature = "bindgen")]
mod bindings {
use super::super::PYTHON;
use super::common::*;
use bindgen::{Builder, CodegenConfig};
use regex::Regex;
use std::cmp;
use std::collections::HashSet;
use std::env;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::process::{exit, Command};
use std::slice;
use std::sync::Mutex;
use std::time::SystemTime;
use toml;
use toml::value::Table;
lazy_static! {
static ref CONFIG: Table = {
// Load Gecko's binding generator config from the source tree.
let path = PathBuf::from(env::var_os("MOZ_SRC").unwrap())
.join("layout/style/ServoBindings.toml");
read_config(&path)
};
static ref BUILD_CONFIG: Table = {
// Load build-specific config overrides.
let path = PathBuf::from(env::var_os("MOZ_TOPOBJDIR").unwrap())
.join("layout/style/bindgen.toml");
read_config(&path)
};
static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
static ref DISTDIR_PATH: PathBuf = {
let path = PathBuf::from(env::var_os("MOZ_DIST").unwrap());
if !path.is_absolute() || !path.is_dir() {
panic!("MOZ_DIST must be an absolute directory, was: {}", path.display());
}
path
};
static ref SEARCH_PATHS: Vec<PathBuf> = vec![
DISTDIR_PATH.join("include"),
DISTDIR_PATH.join("include/nspr"),
];
static ref ADDED_PATHS: Mutex<HashSet<PathBuf>> = Mutex::new(HashSet::new());
static ref LAST_MODIFIED: Mutex<SystemTime> =
Mutex::new(get_modified_time(&env::current_exe().unwrap())
.expect("Failed to get modified time of executable"));
}
const STRUCTS_FILE: &'static str = "structs.rs";
fn get_modified_time(file: &Path) -> Option<SystemTime> {
file.metadata().and_then(|m| m.modified()).ok()
}
fn read_config(path: &PathBuf) -> Table {
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
update_last_modified(&path);
fn update_last_modified(file: &Path) {
let modified = get_modified_time(file).expect("Couldn't get file modification time");
let mut last_modified = LAST_MODIFIED.lock().unwrap();
*last_modified = cmp::max(modified, *last_modified);
}
let mut contents = String::new();
File::open(path)
.expect("Failed to open config file")
.read_to_string(&mut contents)
.expect("Failed to read config file");
match toml::from_str::<Table>(&contents) {
Ok(result) => result,
Err(e) => panic!("Failed to parse config file: {}", e),
fn search_include(name: &str) -> Option<PathBuf> {
for path in SEARCH_PATHS.iter() {
let file = path.join(name);
if file.is_file() {
update_last_modified(&file);
return Some(file);
}
}
None
}
lazy_static! {
static ref CONFIG: Table = {
// Load Gecko's binding generator config from the source tree.
let path = PathBuf::from(env::var_os("MOZ_SRC").unwrap())
.join("layout/style/ServoBindings.toml");
read_config(&path)
};
static ref BUILD_CONFIG: Table = {
// Load build-specific config overrides.
let path = PathBuf::from(env::var_os("MOZ_TOPOBJDIR").unwrap())
.join("layout/style/bindgen.toml");
read_config(&path)
};
static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
static ref DISTDIR_PATH: PathBuf = {
let path = PathBuf::from(env::var_os("MOZ_DIST").unwrap());
if !path.is_absolute() || !path.is_dir() {
panic!("MOZ_DIST must be an absolute directory, was: {}", path.display());
}
path
};
static ref SEARCH_PATHS: Vec<PathBuf> = vec![
DISTDIR_PATH.join("include"),
DISTDIR_PATH.join("include/nspr"),
];
static ref ADDED_PATHS: Mutex<HashSet<PathBuf>> = Mutex::new(HashSet::new());
static ref LAST_MODIFIED: Mutex<SystemTime> =
Mutex::new(get_modified_time(&env::current_exe().unwrap())
.expect("Failed to get modified time of executable"));
fn add_headers_recursively(path: PathBuf, added_paths: &mut HashSet<PathBuf>) {
if added_paths.contains(&path) {
return;
}
fn get_modified_time(file: &Path) -> Option<SystemTime> {
file.metadata().and_then(|m| m.modified()).ok()
}
fn update_last_modified(file: &Path) {
let modified = get_modified_time(file).expect("Couldn't get file modification time");
let mut last_modified = LAST_MODIFIED.lock().unwrap();
*last_modified = cmp::max(modified, *last_modified);
}
fn search_include(name: &str) -> Option<PathBuf> {
for path in SEARCH_PATHS.iter() {
let file = path.join(name);
if file.is_file() {
update_last_modified(&file);
return Some(file);
}
let mut file = File::open(&path).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
added_paths.insert(path);
// Find all includes and add them recursively
for cap in INCLUDE_RE.captures_iter(&content) {
if let Some(path) = search_include(cap.get(1).unwrap().as_str()) {
add_headers_recursively(path, added_paths);
}
None
}
}
fn add_headers_recursively(path: PathBuf, added_paths: &mut HashSet<PathBuf>) {
if added_paths.contains(&path) {
fn add_include(name: &str) -> String {
let mut added_paths = ADDED_PATHS.lock().unwrap();
let file = search_include(name).expect("Include not found!");
let result = String::from(file.to_str().unwrap());
add_headers_recursively(file, &mut *added_paths);
result
}
trait BuilderExt {
fn get_initial_builder() -> Builder;
fn include<T: Into<String>>(self, file: T) -> Builder;
}
impl BuilderExt for Builder {
fn get_initial_builder() -> Builder {
use bindgen::RustTarget;
// Disable rust unions, because we replace some types inside of
// them.
let mut builder = Builder::default()
.rust_target(RustTarget::Stable_1_25)
.disable_untagged_union();
let rustfmt_path = env::var_os("RUSTFMT")
// This can be replaced with
// > .filter(|p| !p.is_empty()).map(PathBuf::from)
// once we can use 1.27+.
.and_then(|p| {
if p.is_empty() {
None
} else {
Some(PathBuf::from(p))
}
});
if let Some(path) = rustfmt_path {
builder = builder.with_rustfmt(path);
}
for dir in SEARCH_PATHS.iter() {
builder = builder.clang_arg("-I").clang_arg(dir.to_str().unwrap());
}
builder = builder.include(add_include("mozilla-config.h"));
if env::var("CARGO_FEATURE_GECKO_DEBUG").is_ok() {
builder = builder.clang_arg("-DDEBUG=1").clang_arg("-DJS_DEBUG=1");
}
let build_config = BUILD_CONFIG["build"]
.as_table()
.expect("Malformed config file");
let extra_bindgen_flags = build_config["args"].as_array().unwrap().as_slice();
for item in extra_bindgen_flags.iter() {
builder = builder.clang_arg(item.as_str().expect("Expect string in list"));
}
builder
}
fn include<T: Into<String>>(self, file: T) -> Builder {
self.clang_arg("-include").clang_arg(file)
}
}
struct Fixup {
pat: String,
rep: String,
}
fn write_binding_file(builder: Builder, file: &str, fixups: &[Fixup]) {
let out_file = OUTDIR_PATH.join(file);
if let Some(modified) = get_modified_time(&out_file) {
// Don't generate the file if nothing it depends on was modified.
let last_modified = LAST_MODIFIED.lock().unwrap();
if *last_modified <= modified {
return;
}
let mut file = File::open(&path).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
added_paths.insert(path);
// Find all includes and add them recursively
for cap in INCLUDE_RE.captures_iter(&content) {
if let Some(path) = search_include(cap.get(1).unwrap().as_str()) {
add_headers_recursively(path, added_paths);
}
}
}
fn add_include(name: &str) -> String {
let mut added_paths = ADDED_PATHS.lock().unwrap();
let file = search_include(name).expect("Include not found!");
let result = String::from(file.to_str().unwrap());
add_headers_recursively(file, &mut *added_paths);
result
}
trait BuilderExt {
fn get_initial_builder() -> Builder;
fn include<T: Into<String>>(self, file: T) -> Builder;
}
impl BuilderExt for Builder {
fn get_initial_builder() -> Builder {
use bindgen::RustTarget;
// Disable rust unions, because we replace some types inside of
// them.
let mut builder = Builder::default()
.rust_target(RustTarget::Stable_1_25)
.disable_untagged_union();
let rustfmt_path = env::var_os("RUSTFMT")
// This can be replaced with
// > .filter(|p| !p.is_empty()).map(PathBuf::from)
// once we can use 1.27+.
.and_then(|p| {
if p.is_empty() {
None
} else {
Some(PathBuf::from(p))
}
});
if let Some(path) = rustfmt_path {
builder = builder.with_rustfmt(path);
}
for dir in SEARCH_PATHS.iter() {
builder = builder.clang_arg("-I").clang_arg(dir.to_str().unwrap());
}
builder = builder.include(add_include("mozilla-config.h"));
if env::var("CARGO_FEATURE_GECKO_DEBUG").is_ok() {
builder = builder.clang_arg("-DDEBUG=1").clang_arg("-DJS_DEBUG=1");
}
let build_config = BUILD_CONFIG["build"]
.as_table()
.expect("Malformed config file");
let extra_bindgen_flags = build_config["args"].as_array().unwrap().as_slice();
for item in extra_bindgen_flags.iter() {
builder = builder.clang_arg(item.as_str().expect("Expect string in list"));
}
builder
}
fn include<T: Into<String>>(self, file: T) -> Builder {
self.clang_arg("-include").clang_arg(file)
}
}
struct Fixup {
pat: String,
rep: String,
}
fn write_binding_file(builder: Builder, file: &str, fixups: &[Fixup]) {
let out_file = OUTDIR_PATH.join(file);
if let Some(modified) = get_modified_time(&out_file) {
// Don't generate the file if nothing it depends on was modified.
let last_modified = LAST_MODIFIED.lock().unwrap();
if *last_modified <= modified {
return;
}
}
let command_line_opts = builder.command_line_flags();
let result = builder.generate();
let mut result = match result {
Ok(bindings) => bindings.to_string(),
Err(_) => {
panic!(
"Failed to generate bindings, flags: {:?}",
command_line_opts
);
},
};
for fixup in fixups.iter() {
result = Regex::new(&fixup.pat)
.unwrap()
.replace_all(&result, &*fixup.rep)
.into_owned()
.into();
}
let bytes = result.into_bytes();
File::create(&out_file)
.unwrap()
.write_all(&bytes)
.expect("Unable to write output");
}
struct BuilderWithConfig<'a> {
builder: Builder,
config: &'a Table,
used_keys: HashSet<&'static str>,
}
impl<'a> BuilderWithConfig<'a> {
fn new(builder: Builder, config: &'a Table) -> Self {
BuilderWithConfig {
builder,
config,
used_keys: HashSet::new(),
}
}
fn handle_list<F>(self, key: &'static str, func: F) -> BuilderWithConfig<'a>
where
F: FnOnce(Builder, slice::Iter<'a, toml::Value>) -> Builder,
{
let mut builder = self.builder;
let config = self.config;
let mut used_keys = self.used_keys;
if let Some(list) = config.get(key) {
used_keys.insert(key);
builder = func(builder, list.as_array().unwrap().as_slice().iter());
}
BuilderWithConfig {
builder,
config,
used_keys,
}
}
fn handle_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
where
F: FnMut(Builder, &'a toml::Value) -> Builder,
{
self.handle_list(key, |b, iter| iter.fold(b, |b, item| func(b, item)))
}
fn handle_str_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
where
F: FnMut(Builder, &'a str) -> Builder,
{
self.handle_items(key, |b, item| func(b, item.as_str().unwrap()))
}
fn handle_table_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
where
F: FnMut(Builder, &'a Table) -> Builder,
{
self.handle_items(key, |b, item| func(b, item.as_table().unwrap()))
}
fn handle_common(self, fixups: &mut Vec<Fixup>) -> BuilderWithConfig<'a> {
self.handle_str_items("headers", |b, item| b.header(add_include(item)))
.handle_str_items("raw-lines", |b, item| b.raw_line(item))
.handle_str_items("hide-types", |b, item| b.blacklist_type(item))
.handle_table_items("fixups", |builder, item| {
fixups.push(Fixup {
pat: item["pat"].as_str().unwrap().into(),
rep: item["rep"].as_str().unwrap().into(),
});
builder
})
}
fn get_builder(self) -> Builder {
for key in self.config.keys() {
if !self.used_keys.contains(key.as_str()) {
panic!(format!("Unknown key: {}", key));
}
}
self.builder
}
}
fn generate_structs() {
let builder = Builder::get_initial_builder()
.enable_cxx_namespaces()
.with_codegen_config(
CodegenConfig::TYPES | CodegenConfig::VARS | CodegenConfig::FUNCTIONS,
let command_line_opts = builder.command_line_flags();
let result = builder.generate();
let mut result = match result {
Ok(bindings) => bindings.to_string(),
Err(_) => {
panic!(
"Failed to generate bindings, flags: {:?}",
command_line_opts
);
let mut fixups = vec![];
let builder = BuilderWithConfig::new(builder, CONFIG["structs"].as_table().unwrap())
.handle_common(&mut fixups)
.handle_str_items("whitelist-functions", |b, item| b.whitelist_function(item))
.handle_str_items("bitfield-enums", |b, item| b.bitfield_enum(item))
.handle_str_items("rusty-enums", |b, item| b.rustified_enum(item))
.handle_str_items("whitelist-vars", |b, item| b.whitelist_var(item))
.handle_str_items("whitelist-types", |b, item| b.whitelist_type(item))
.handle_str_items("opaque-types", |b, item| b.opaque_type(item))
.handle_table_items("cbindgen-types", |b, item| {
let gecko = item["gecko"].as_str().unwrap();
let servo = item["servo"].as_str().unwrap();
b.blacklist_type(format!("mozilla::{}", gecko))
.module_raw_line("root::mozilla", format!("pub use {} as {};", servo, gecko))
})
.handle_table_items("mapped-generic-types", |builder, item| {
let generic = item["generic"].as_bool().unwrap();
let gecko = item["gecko"].as_str().unwrap();
let servo = item["servo"].as_str().unwrap();
let gecko_name = gecko.rsplit("::").next().unwrap();
let gecko = gecko
.split("::")
.map(|s| format!("\\s*{}\\s*", s))
.collect::<Vec<_>>()
.join("::");
},
};
for fixup in fixups.iter() {
result = Regex::new(&fixup.pat)
.unwrap()
.replace_all(&result, &*fixup.rep)
.into_owned()
.into();
}
let bytes = result.into_bytes();
File::create(&out_file)
.unwrap()
.write_all(&bytes)
.expect("Unable to write output");
}
struct BuilderWithConfig<'a> {
builder: Builder,
config: &'a Table,
used_keys: HashSet<&'static str>,
}
impl<'a> BuilderWithConfig<'a> {
fn new(builder: Builder, config: &'a Table) -> Self {
BuilderWithConfig {
builder,
config,
used_keys: HashSet::new(),
}
}
fn handle_list<F>(self, key: &'static str, func: F) -> BuilderWithConfig<'a>
where
F: FnOnce(Builder, slice::Iter<'a, toml::Value>) -> Builder,
{
let mut builder = self.builder;
let config = self.config;
let mut used_keys = self.used_keys;
if let Some(list) = config.get(key) {
used_keys.insert(key);
builder = func(builder, list.as_array().unwrap().as_slice().iter());
}
BuilderWithConfig {
builder,
config,
used_keys,
}
}
fn handle_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
where
F: FnMut(Builder, &'a toml::Value) -> Builder,
{
self.handle_list(key, |b, iter| iter.fold(b, |b, item| func(b, item)))
}
fn handle_str_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
where
F: FnMut(Builder, &'a str) -> Builder,
{
self.handle_items(key, |b, item| func(b, item.as_str().unwrap()))
}
fn handle_table_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
where
F: FnMut(Builder, &'a Table) -> Builder,
{
self.handle_items(key, |b, item| func(b, item.as_table().unwrap()))
}
fn handle_common(self, fixups: &mut Vec<Fixup>) -> BuilderWithConfig<'a> {
self.handle_str_items("headers", |b, item| b.header(add_include(item)))
.handle_str_items("raw-lines", |b, item| b.raw_line(item))
.handle_str_items("hide-types", |b, item| b.blacklist_type(item))
.handle_table_items("fixups", |builder, item| {
fixups.push(Fixup {
pat: format!("\\broot\\s*::\\s*{}\\b", gecko),
rep: format!("::gecko_bindings::structs::{}", gecko_name),
pat: item["pat"].as_str().unwrap().into(),
rep: item["rep"].as_str().unwrap().into(),
});
builder.blacklist_type(gecko).raw_line(format!(
"pub type {0}{2} = {1}{2};",
gecko_name,
servo,
if generic { "<T>" } else { "" }
))
builder
})
.get_builder();
write_binding_file(builder, STRUCTS_FILE, &fixups);
}
fn setup_logging() -> bool {
struct BuildLogger {
file: Option<Mutex<fs::File>>,
filter: String,
}
impl log::Log for BuildLogger {
fn enabled(&self, meta: &log::Metadata) -> bool {
self.file.is_some() && meta.target().contains(&self.filter)
}
fn log(&self, record: &log::Record) {
if !self.enabled(record.metadata()) {
return;
}
let mut file = self.file.as_ref().unwrap().lock().unwrap();
let _ = writeln!(
file,
"{} - {} - {} @ {}:{}",
record.level(),
record.target(),
record.args(),
record.file().unwrap_or("<unknown>"),
record.line().unwrap_or(0)
);
}
fn flush(&self) {
if let Some(ref file) = self.file {
file.lock().unwrap().flush().unwrap();
}
fn get_builder(self) -> Builder {
for key in self.config.keys() {
if !self.used_keys.contains(key.as_str()) {
panic!(format!("Unknown key: {}", key));
}
}
if let Some(path) = env::var_os("STYLO_BUILD_LOG") {
log::set_max_level(log::LevelFilter::Debug);
log::set_boxed_logger(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.");
true
} else {
false
}
}
fn generate_atoms() {
let script = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap())
.join("gecko")
.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 generate() {
setup_logging();
generate_structs();
generate_atoms();
for path in ADDED_PATHS.lock().unwrap().iter() {
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
}
self.builder
}
}
#[cfg(not(feature = "bindgen"))]
mod bindings {
use super::common::*;
use std::path::{Path, PathBuf};
use std::{env, fs, io};
fn generate_structs() {
let builder = Builder::get_initial_builder()
.enable_cxx_namespaces()
.with_codegen_config(CodegenConfig::TYPES | CodegenConfig::VARS | CodegenConfig::FUNCTIONS);
let mut fixups = vec![];
let builder = BuilderWithConfig::new(builder, CONFIG["structs"].as_table().unwrap())
.handle_common(&mut fixups)
.handle_str_items("whitelist-functions", |b, item| b.whitelist_function(item))
.handle_str_items("bitfield-enums", |b, item| b.bitfield_enum(item))
.handle_str_items("rusty-enums", |b, item| b.rustified_enum(item))
.handle_str_items("whitelist-vars", |b, item| b.whitelist_var(item))
.handle_str_items("whitelist-types", |b, item| b.whitelist_type(item))
.handle_str_items("opaque-types", |b, item| b.opaque_type(item))
.handle_table_items("cbindgen-types", |b, item| {
let gecko = item["gecko"].as_str().unwrap();
let servo = item["servo"].as_str().unwrap();
b.blacklist_type(format!("mozilla::{}", gecko))
.module_raw_line("root::mozilla", format!("pub use {} as {};", servo, gecko))
})
.handle_table_items("mapped-generic-types", |builder, item| {
let generic = item["generic"].as_bool().unwrap();
let gecko = item["gecko"].as_str().unwrap();
let servo = item["servo"].as_str().unwrap();
let gecko_name = gecko.rsplit("::").next().unwrap();
let gecko = gecko
.split("::")
.map(|s| format!("\\s*{}\\s*", s))
.collect::<Vec<_>>()
.join("::");
/// Copy contents of one directory into another.
/// It currently only does a shallow copy.
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(())
fixups.push(Fixup {
pat: format!("\\broot\\s*::\\s*{}\\b", gecko),
rep: format!("::gecko_bindings::structs::{}", gecko_name),
});
builder.blacklist_type(gecko).raw_line(format!(
"pub type {0}{2} = {1}{2};",
gecko_name,
servo,
if generic { "<T>" } else { "" }
))
})
.get_builder();
write_binding_file(builder, STRUCTS_FILE, &fixups);
}
fn setup_logging() -> bool {
struct BuildLogger {
file: Option<Mutex<fs::File>>,
filter: String,
}
pub fn generate() {
let dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").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");
impl log::Log for BuildLogger {
fn enabled(&self, meta: &log::Metadata) -> bool {
self.file.is_some() && meta.target().contains(&self.filter)
}
fn log(&self, record: &log::Record) {
if !self.enabled(record.metadata()) {
return;
}
let mut file = self.file.as_ref().unwrap().lock().unwrap();
let _ = writeln!(
file,
"{} - {} - {} @ {}:{}",
record.level(),
record.target(),
record.args(),
record.file().unwrap_or("<unknown>"),
record.line().unwrap_or(0)
);
}
fn flush(&self) {
if let Some(ref file) = self.file {
file.lock().unwrap().flush().unwrap();
}
}
}
if let Some(path) = env::var_os("STYLO_BUILD_LOG") {
log::set_max_level(log::LevelFilter::Debug);
log::set_boxed_logger(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.");
true
} else {
false
}
}
fn generate_atoms() {
let script = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap())
.join("gecko")
.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 generate() {
use self::common::*;
use std::fs;
println!("cargo:rerun-if-changed=build_gecko.rs");
fs::create_dir_all(&*OUTDIR_PATH).unwrap();
bindings::generate();
setup_logging();
generate_structs();
generate_atoms();
for path in ADDED_PATHS.lock().unwrap().iter() {
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
}
}

View file

@ -31,8 +31,8 @@ use crate::traversal_flags::TraversalFlags;
use app_units::Au;
#[cfg(feature = "servo")]
use crossbeam_channel::Sender;
use euclid::Size2D;
use euclid::TypedScale;
use euclid::default::Size2D;
use euclid::Scale;
use fxhash::FxHashMap;
#[cfg(feature = "servo")]
use parking_lot::RwLock;
@ -195,7 +195,7 @@ impl<'a> SharedStyleContext<'a> {
}
/// The device pixel ratio
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
self.stylist.device().device_pixel_ratio()
}

View file

@ -14,7 +14,7 @@ use crate::values::computed::CSSPixelLength;
use crate::values::computed::Resolution;
use crate::Atom;
use app_units::Au;
use euclid::Size2D;
use euclid::default::Size2D;
fn viewport_size(device: &Device) -> Size2D<Au> {
if let Some(pc) = device.pres_context() {

View file

@ -16,8 +16,8 @@ use crate::values::{CustomIdent, KeyframesName};
use app_units::Au;
use app_units::AU_PER_PX;
use cssparser::RGBA;
use euclid::Size2D;
use euclid::TypedScale;
use euclid::default::Size2D;
use euclid::Scale;
use servo_arc::Arc;
use std::fmt;
use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
@ -247,20 +247,20 @@ impl Device {
}
/// Returns the device pixel ratio.
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
let pc = match self.pres_context() {
Some(pc) => pc,
None => return TypedScale::new(1.),
None => return Scale::new(1.),
};
let override_dppx = pc.mOverrideDPPX;
if override_dppx > 0.0 {
return TypedScale::new(override_dppx);
return Scale::new(override_dppx);
}
let au_per_dpx = pc.mCurAppUnitsPerDevPixel as f32;
let au_per_px = AU_PER_PX as f32;
TypedScale::new(au_per_px / au_per_dpx)
Scale::new(au_per_px / au_per_dpx)
}
/// Returns whether document colors are enabled.

View file

@ -303,6 +303,11 @@ impl_threadsafe_refcount!(
bindings::Gecko_AddRefURLExtraDataArbitraryThread,
bindings::Gecko_ReleaseURLExtraDataArbitraryThread
);
impl_threadsafe_refcount!(
structs::nsIReferrerInfo,
bindings::Gecko_AddRefnsIReferrerInfoArbitraryThread,
bindings::Gecko_ReleasensIReferrerInfoArbitraryThread
);
impl_threadsafe_refcount!(
structs::nsIURI,
bindings::Gecko_AddRefnsIURIArbitraryThread,

View file

@ -5,8 +5,8 @@
//! Geometry in flow-relative space.
use crate::properties::style_structs;
use euclid::default::{Point2D, Rect, SideOffsets2D, Size2D};
use euclid::num::Zero;
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
use std::cmp::{max, min};
use std::fmt::{self, Debug, Error, Formatter};
use std::ops::{Add, Sub};

View file

@ -240,16 +240,31 @@ trait PrivateMatchMethods: TElement {
let new_box_style = new_style.get_box();
let new_style_specifies_animations = new_box_style.specifies_animations();
let old_style = match old_style {
Some(old) => old,
None => return new_style_specifies_animations,
};
let has_animations = self.has_css_animations();
if !new_style_specifies_animations && !has_animations {
return false;
}
let old_style = match old_style {
Some(old) => old,
// If we have no old style but have animations, we may be a
// pseudo-element which was re-created without style changes.
//
// This can happen when we reframe the pseudo-element without
// restyling it (due to content insertion on a flex container or
// such, for example). See bug 1564366.
//
// FIXME(emilio): The really right fix for this is keeping the
// pseudo-element itself around on reframes, but that's a bit
// harder. If we do that we can probably remove quite a lot of the
// EffectSet complexity though, since right now it's stored on the
// parent element for pseudo-elements given we need to keep it
// around...
None => {
return new_style_specifies_animations || new_style.is_pseudo_style();
},
};
let old_box_style = old_style.get_box();
let keyframes_could_have_changed = context

View file

@ -153,7 +153,7 @@ where
// longhands are only allowed if they have our
// restriction flag set.
if let PropertyDeclarationId::Longhand(id) = declaration.id() {
if !id.flags().contains(restriction) {
if !id.flags().contains(restriction) && cascade_level.origin() != Origin::UserAgent {
return None;
}
}

View file

@ -175,6 +175,7 @@ class Longhand(object):
predefined_type=None, servo_pref=None, gecko_pref=None,
enabled_in="content", need_index=False,
gecko_ffi_name=None,
has_effect_on_gecko_scrollbars=None,
allowed_in_keyframe_block=True, cast_type='u8',
logical=False, logical_group=None, alias=None, extra_prefixes=None, boxed=False,
flags=None, allowed_in_page_rule=False, allow_quirks="No",
@ -192,6 +193,14 @@ class Longhand(object):
self.style_struct = style_struct
self.servo_pref = servo_pref
self.gecko_pref = gecko_pref
self.has_effect_on_gecko_scrollbars = has_effect_on_gecko_scrollbars
assert (
has_effect_on_gecko_scrollbars in [None, False, True] and
not style_struct.inherited or
(gecko_pref is None) == (has_effect_on_gecko_scrollbars is None)), (
"Property " + name + ": has_effect_on_gecko_scrollbars must be " +
"specified, and must have a value of True or False, iff a " +
"property is inherited and is behind a Gecko pref")
# For enabled_in, the setup is as follows:
# It needs to be one of the four values: ["", "ua", "chrome", "content"]
# * "chrome" implies "ua", and implies that they're explicitly
@ -208,6 +217,7 @@ class Longhand(object):
self.logical_group = logical_group
if self.logical:
assert logical_group, "Property " + name + " must have a logical group"
self.alias = parse_property_aliases(alias)
self.extra_prefixes = parse_property_aliases(extra_prefixes)
self.boxed = arg_to_bool(boxed)
@ -532,8 +542,10 @@ class PropertiesData(object):
self.current_style_struct = None
self.longhands = []
self.longhands_by_name = {}
self.longhands_by_logical_group = {}
self.longhand_aliases = []
self.shorthands = []
self.shorthands_by_name = {}
self.shorthand_aliases = []
def new_style_struct(self, *args, **kwargs):
@ -563,6 +575,8 @@ class PropertiesData(object):
self.current_style_struct.longhands.append(longhand)
self.longhands.append(longhand)
self.longhands_by_name[name] = longhand
if longhand.logical_group:
self.longhands_by_logical_group.setdefault(longhand.logical_group, []).append(longhand)
return longhand
@ -577,6 +591,7 @@ class PropertiesData(object):
shorthand.alias = list(map(lambda xp: Alias(xp[0], shorthand, xp[1]), shorthand.alias))
self.shorthand_aliases += shorthand.alias
self.shorthands.append(shorthand)
self.shorthands_by_name[name] = shorthand
return shorthand
def shorthands_except_all(self):
@ -584,3 +599,172 @@ class PropertiesData(object):
def all_aliases(self):
return self.longhand_aliases + self.shorthand_aliases
def _add_logical_props(data, props):
groups = set()
for prop in props:
if prop not in data.longhands_by_name:
assert data.product == "servo"
continue
prop = data.longhands_by_name[prop]
if prop.logical_group:
groups.add(prop.logical_group)
for group in groups:
for prop in data.longhands_by_logical_group[group]:
props.add(prop.name)
# These are probably Gecko bugs and should be supported per spec.
def _remove_common_first_line_and_first_letter_properties(props, product):
if product == "gecko":
props.remove("-moz-tab-size")
props.remove("hyphens")
props.remove("line-break")
props.remove("text-align-last")
props.remove("text-emphasis-position")
props.remove("text-emphasis-style")
props.remove("text-emphasis-color")
props.remove("text-decoration-skip-ink")
props.remove("text-decoration-thickness")
props.remove("text-underline-offset")
props.remove("overflow-wrap")
props.remove("text-align")
props.remove("text-justify")
props.remove("white-space")
props.remove("word-break")
props.remove("text-indent")
class PropertyRestrictions:
@staticmethod
def logical_group(data, group):
return map(lambda p: p.name, data.longhands_by_logical_group[group])
@staticmethod
def shorthand(data, shorthand):
return map(lambda p: p.name, data.shorthands_by_name[shorthand].sub_properties)
@staticmethod
def spec(data, spec_path):
return map(lambda p: p.name, filter(lambda p: spec_path in p.spec, data.longhands))
# https://drafts.csswg.org/css-pseudo/#first-letter-styling
@staticmethod
def first_letter(data):
props = set([
"color",
"float",
"initial-letter",
# Kinda like css-fonts?
"-moz-osx-font-smoothing",
# Kinda like css-text?
"-webkit-text-stroke-width",
"-webkit-text-fill-color",
"-webkit-text-stroke-color",
"vertical-align",
"line-height",
# Kinda like css-backgrounds?
"background-blend-mode",
] + PropertyRestrictions.shorthand(data, "padding")
+ PropertyRestrictions.shorthand(data, "margin")
+ PropertyRestrictions.spec(data, "css-fonts")
+ PropertyRestrictions.spec(data, "css-backgrounds")
+ PropertyRestrictions.spec(data, "css-text")
+ PropertyRestrictions.spec(data, "css-shapes")
+ PropertyRestrictions.spec(data, "css-text-decor"))
_add_logical_props(data, props)
_remove_common_first_line_and_first_letter_properties(props, data.product)
return props
# https://drafts.csswg.org/css-pseudo/#first-line-styling
@staticmethod
def first_line(data):
props = set([
# Per spec.
"color",
# Kinda like css-fonts?
"-moz-osx-font-smoothing",
# Kinda like css-text?
"-webkit-text-stroke-width",
"-webkit-text-fill-color",
"-webkit-text-stroke-color",
"vertical-align",
"line-height",
# Kinda like css-backgrounds?
"background-blend-mode",
] + PropertyRestrictions.spec(data, "css-fonts")
+ PropertyRestrictions.spec(data, "css-backgrounds")
+ PropertyRestrictions.spec(data, "css-text")
+ PropertyRestrictions.spec(data, "css-text-decor"))
# These are probably Gecko bugs and should be supported per spec.
for prop in PropertyRestrictions.shorthand(data, "border"):
props.remove(prop)
for prop in PropertyRestrictions.shorthand(data, "border-radius"):
props.remove(prop)
props.remove("box-shadow")
_remove_common_first_line_and_first_letter_properties(props, data.product)
return props
# https://drafts.csswg.org/css-pseudo/#placeholder
#
# The spec says that placeholder and first-line have the same restrictions,
# but that's not true in Gecko and we also allow a handful other properties
# for ::placeholder.
@staticmethod
def placeholder(data):
props = PropertyRestrictions.first_line(data)
props.add("opacity")
props.add("white-space")
props.add("text-overflow")
props.add("text-align")
props.add("text-justify")
return props
# https://drafts.csswg.org/css-pseudo/#marker-pseudo
@staticmethod
def marker(data):
return set([
"color",
"text-combine-upright",
"unicode-bidi",
"direction",
"content",
"-moz-osx-font-smoothing",
] + PropertyRestrictions.spec(data, "css-fonts"))
# https://www.w3.org/TR/webvtt1/#the-cue-pseudo-element
@staticmethod
def cue(data):
return set([
"color",
"opacity",
"visibility",
"text-shadow",
"white-space",
"text-combine-upright",
"ruby-position",
# XXX Should these really apply to cue?
"font-synthesis",
"-moz-osx-font-smoothing",
# FIXME(emilio): background-blend-mode should be part of the
# background shorthand, and get reset, per
# https://drafts.fxtf.org/compositing/#background-blend-mode
"background-blend-mode",
] + PropertyRestrictions.shorthand(data, "text-decoration")
+ PropertyRestrictions.shorthand(data, "background")
+ PropertyRestrictions.shorthand(data, "outline")
+ PropertyRestrictions.shorthand(data, "font"))

View file

@ -117,9 +117,14 @@ impl ComputedValues {
).to_outer(None)
}
#[inline]
pub fn is_pseudo_style(&self) -> bool {
self.0.mPseudoType != PseudoStyleType::NotPseudo
}
#[inline]
pub fn pseudo(&self) -> Option<PseudoElement> {
if self.0.mPseudoType == PseudoStyleType::NotPseudo {
if !self.is_pseudo_style() {
return None;
}
PseudoElement::from_pseudo_type(self.0.mPseudoType)

View file

@ -15,8 +15,7 @@ ${helpers.predefined_type(
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
allow_quirks="Yes",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
CAN_ANIMATE_ON_COMPOSITOR",
flags="CAN_ANIMATE_ON_COMPOSITOR",
)}
${helpers.predefined_type(
@ -28,7 +27,6 @@ ${helpers.predefined_type(
vector="True",
animation_value_type="discrete",
ignored_when_colors_disabled="True",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
% for (axis, direction, initial) in [("x", "Horizontal", "left"), ("y", "Vertical", "top")]:
@ -41,7 +39,6 @@ ${helpers.predefined_type(
animation_value_type="ComputedValue",
vector=True,
vector_animation_type="repeatable_list",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
% endfor
@ -53,7 +50,6 @@ ${helpers.predefined_type(
animation_value_type="discrete",
vector=True,
spec="https://drafts.csswg.org/css-backgrounds/#the-background-repeat",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
${helpers.single_keyword(
@ -63,7 +59,6 @@ ${helpers.single_keyword(
gecko_enum_prefix="StyleImageLayerAttachment",
spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
${helpers.single_keyword(
@ -75,7 +70,6 @@ ${helpers.single_keyword(
gecko_inexhaustive=True,
spec="https://drafts.csswg.org/css-backgrounds/#the-background-clip",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}
${helpers.single_keyword(
@ -86,7 +80,6 @@ ${helpers.single_keyword(
gecko_inexhaustive=True,
spec="https://drafts.csswg.org/css-backgrounds/#the-background-origin",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
)}
${helpers.predefined_type(
@ -98,7 +91,6 @@ ${helpers.predefined_type(
vector=True,
vector_animation_type="repeatable_list",
animation_value_type="BackgroundSizeList",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
extra_prefixes="webkit")}
// https://drafts.fxtf.org/compositing/#background-blend-mode
@ -110,5 +102,4 @@ ${helpers.single_keyword(
gecko_constant_prefix="NS_STYLE_BLEND",
vector=True, products="gecko", animation_value_type="discrete",
spec="https://drafts.fxtf.org/compositing/#background-blend-mode",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
)}

View file

@ -29,7 +29,6 @@
logical=is_logical,
logical_group="border-color",
allow_quirks="No" if is_logical else "Yes",
flags="APPLIES_TO_FIRST_LETTER",
ignored_when_colors_disabled=True,
)}
@ -38,7 +37,6 @@
"specified::BorderStyle::None",
alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"),
spec=maybe_logical_spec(side, "style"),
flags="APPLIES_TO_FIRST_LETTER",
animation_value_type="discrete" if not is_logical else "none",
logical=is_logical,
logical_group="border-style",
@ -55,7 +53,7 @@
animation_value_type="NonNegativeLength",
logical=is_logical,
logical_group="border-width",
flags="APPLIES_TO_FIRST_LETTER GETCS_NEEDS_LAYOUT_FLUSH",
flags="GETCS_NEEDS_LAYOUT_FLUSH",
allow_quirks="No" if is_logical else "Yes",
servo_restyle_damage="reflow rebuild_and_reflow_inline"
)}
@ -78,7 +76,6 @@
extra_prefixes=prefixes,
spec=maybe_logical_spec(corner, "radius"),
boxed=True,
flags="APPLIES_TO_FIRST_LETTER",
animation_value_type="BorderCornerRadius",
logical_group="border-radius",
logical=is_logical,
@ -112,7 +109,6 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
vector=False,
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER",
boxed=product == "servo",
ignored_when_colors_disabled=True
)}
@ -124,7 +120,6 @@ ${helpers.predefined_type(
initial_specified_value="generics::rect::Rect::all(specified::NonNegativeLengthOrNumber::zero())",
spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER",
boxed=True,
)}
@ -135,7 +130,6 @@ ${helpers.predefined_type(
initial_specified_value="specified::BorderImageRepeat::stretch()",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-backgrounds/#the-border-image-repeat",
flags="APPLIES_TO_FIRST_LETTER",
)}
${helpers.predefined_type(
@ -145,7 +139,6 @@ ${helpers.predefined_type(
initial_specified_value="specified::BorderImageWidth::all(specified::BorderImageSideWidth::one())",
spec="https://drafts.csswg.org/css-backgrounds/#border-image-width",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER",
boxed=True,
)}
@ -156,6 +149,5 @@ ${helpers.predefined_type(
initial_specified_value="specified::BorderImageSlice::hundred_percent()",
spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER",
boxed=True,
)}

View file

@ -9,15 +9,12 @@
inherited=False,
gecko_name="Display") %>
// We allow "display" to apply to placeholders because we need to make the
// placeholder pseudo-element an inline-block in the UA stylesheet in Gecko.
${helpers.predefined_type(
"display",
"Display",
"computed::Display::inline()",
initial_specified_value="specified::Display::inline()",
animation_value_type="discrete",
flags="APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-display/#propdef-display",
servo_restyle_damage="rebuild_and_reflow",
needs_context=product == "gecko"
@ -62,7 +59,6 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-box/#propdef-float",
animation_value_type="discrete",
needs_context=False,
flags="APPLIES_TO_FIRST_LETTER",
servo_restyle_damage="rebuild_and_reflow",
gecko_ffi_name="mFloat",
)}
@ -83,7 +79,6 @@ ${helpers.predefined_type(
"VerticalAlign",
"computed::VerticalAlign::baseline()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align",
servo_restyle_damage = "reflow",
)}
@ -103,7 +98,6 @@ ${helpers.single_keyword("-servo-overflow-clip-box", "padding-box content-box",
products="gecko",
enabled_in="ua",
needs_context=False,
flags="APPLIES_TO_PLACEHOLDER",
gecko_pref="layout.css.overflow-clip-box.enabled",
animation_value_type="discrete",
spec="Internal, may be standardized in the future: \
@ -111,9 +105,6 @@ ${helpers.single_keyword("-servo-overflow-clip-box", "padding-box content-box",
)}
% endfor
// FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`.
//
// We allow it to apply to placeholders for UA sheets, which set it !important.
% for (axis, logical) in ALL_AXES:
<% full_name = "overflow-{}".format(axis) %>
${helpers.predefined_type(
@ -123,7 +114,6 @@ ${helpers.single_keyword("-servo-overflow-clip-box", "padding-box content-box",
logical_group="overflow",
logical=logical,
animation_value_type="discrete",
flags="APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-overflow-3/#propdef-{}".format(full_name),
needs_context=False,
servo_restyle_damage = "reflow",
@ -477,10 +467,6 @@ ${helpers.predefined_type(
// CSS Basic User Interface Module Level 3
// http://dev.w3.org/csswg/css-ui
//
// This is APPLIES_TO_PLACEHOLDER so we can override, in the UA sheet, the
// 'resize' property we'd inherit from textarea otherwise. Basically, just
// makes the UA rules easier to write.
${helpers.predefined_type(
"resize",
"Resize",
@ -489,7 +475,6 @@ ${helpers.predefined_type(
animation_value_type="discrete",
needs_context=False,
gecko_ffi_name="mResize",
flags="APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-ui/#propdef-resize",
)}
@ -616,11 +601,12 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-will-change/#will-change",
)}
// The spec issue for the parse_method: https://github.com/w3c/csswg-drafts/issues/4102.
${helpers.predefined_type(
"shape-image-threshold", "Opacity", "0.0",
parse_method="parse_number",
products="gecko",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER",
spec="https://drafts.csswg.org/css-shapes/#shape-image-threshold-property",
)}
@ -630,7 +616,6 @@ ${helpers.predefined_type(
"computed::NonNegativeLengthPercentage::zero()",
products="gecko",
animation_value_type="NonNegativeLengthPercentage",
flags="APPLIES_TO_FIRST_LETTER",
spec="https://drafts.csswg.org/css-shapes/#shape-margin-property",
)}
@ -640,7 +625,6 @@ ${helpers.predefined_type(
"generics::basic_shape::ShapeSource::None",
products="gecko",
animation_value_type="basic_shape::FloatAreaShape",
flags="APPLIES_TO_FIRST_LETTER",
spec="https://drafts.csswg.org/css-shapes/#shape-outside-property",
)}

View file

@ -13,7 +13,6 @@ ${helpers.predefined_type(
initial_specified_value="specified::Content::normal()",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-content/#propdef-content",
flags="APPLIES_TO_MARKER",
servo_restyle_damage="rebuild_and_reflow",
)}

View file

@ -12,9 +12,8 @@ ${helpers.predefined_type(
"Opacity",
"1.0",
animation_value_type="ComputedValue",
flags="APPLIES_TO_CUE CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \
CAN_ANIMATE_ON_COMPOSITOR",
spec="https://drafts.csswg.org/css-color/#opacity",
flags="CREATES_STACKING_CONTEXT CAN_ANIMATE_ON_COMPOSITOR",
spec="https://drafts.csswg.org/css-color/#transparency",
servo_restyle_damage = "reflow_out_of_flow",
)}
@ -28,7 +27,6 @@ ${helpers.predefined_type(
vector_animation_type="with_zero",
extra_prefixes="webkit",
ignored_when_colors_disabled=True,
flags="APPLIES_TO_FIRST_LETTER",
spec="https://drafts.csswg.org/css-backgrounds/#box-shadow",
)}

View file

@ -12,7 +12,6 @@ ${helpers.predefined_type(
"FontFamily",
initial_value="computed::FontFamily::serif()",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-family",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -23,7 +22,6 @@ ${helpers.predefined_type(
initial_value="computed::FontStyle::normal()",
initial_specified_value="specified::FontStyle::normal()",
animation_value_type="FontStyle",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-style",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -42,7 +40,6 @@ ${helpers.single_keyword_system(
gecko_ffi_name="mFont.variantCaps",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
custom_consts=font_variant_caps_custom_consts,
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
animation_value_type="discrete",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -53,7 +50,6 @@ ${helpers.predefined_type(
initial_value="computed::FontWeight::normal()",
initial_specified_value="specified::FontWeight::normal()",
animation_value_type="Number",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -65,7 +61,6 @@ ${helpers.predefined_type(
initial_specified_value="specified::FontSize::medium()",
animation_value_type="NonNegativeLength",
allow_quirks="Yes",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -77,7 +72,6 @@ ${helpers.predefined_type(
initial_value="computed::FontSizeAdjust::none()",
initial_specified_value="specified::FontSizeAdjust::none()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust",
)}
@ -87,7 +81,6 @@ ${helpers.predefined_type(
products="gecko",
initial_value="specified::FontSynthesis::get_initial_value()",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-synthesis",
)}
@ -97,7 +90,6 @@ ${helpers.predefined_type(
initial_value="computed::FontStretch::hundred()",
initial_specified_value="specified::FontStretch::normal()",
animation_value_type="Percentage",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -109,7 +101,6 @@ ${helpers.single_keyword_system(
gecko_ffi_name="mFont.kerning",
gecko_constant_prefix="NS_FONT_KERNING",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-kerning",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
animation_value_type="discrete",
)}
@ -120,7 +111,6 @@ ${helpers.predefined_type(
initial_value="computed::FontVariantAlternates::get_initial_value()",
initial_specified_value="specified::FontVariantAlternates::get_initial_specified_value()",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates",
)}
@ -131,7 +121,6 @@ ${helpers.predefined_type(
initial_value="computed::FontVariantEastAsian::empty()",
initial_specified_value="specified::FontVariantEastAsian::empty()",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian",
)}
@ -142,7 +131,6 @@ ${helpers.predefined_type(
initial_value="computed::FontVariantLigatures::empty()",
initial_specified_value="specified::FontVariantLigatures::empty()",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-ligatures",
)}
@ -153,7 +141,6 @@ ${helpers.predefined_type(
initial_value="computed::FontVariantNumeric::empty()",
initial_specified_value="specified::FontVariantNumeric::empty()",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric",
)}
@ -164,7 +151,6 @@ ${helpers.single_keyword_system(
gecko_ffi_name="mFont.variantPosition",
gecko_constant_prefix="NS_FONT_VARIANT_POSITION",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
animation_value_type="discrete",
)}
@ -176,27 +162,19 @@ ${helpers.predefined_type(
initial_specified_value="specified::FontFeatureSettings::normal()",
extra_prefixes="moz:layout.css.prefixes.font-features",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings",
)}
<%
# This spec link is too long to fit elsewhere
variation_spec = """\
https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-the-font-variation-settings-property\
"""
%>
${helpers.predefined_type(
"font-variation-settings",
"FontVariationSettings",
products="gecko",
gecko_pref="layout.css.font-variations.enabled",
has_effect_on_gecko_scrollbars=False,
initial_value="computed::FontVariationSettings::normal()",
initial_specified_value="specified::FontVariationSettings::normal()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="${variation_spec}",
spec="https://drafts.csswg.org/css-fonts-4/#propdef-font-variation-settings"
)}
${helpers.predefined_type(
@ -207,7 +185,6 @@ ${helpers.predefined_type(
initial_specified_value="specified::FontLanguageOverride::normal()",
animation_value_type="discrete",
extra_prefixes="moz:layout.css.prefixes.font-features",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override",
)}
@ -216,10 +193,10 @@ ${helpers.single_keyword_system(
"auto none",
products="gecko",
gecko_pref="layout.css.font-variations.enabled",
has_effect_on_gecko_scrollbars=False,
gecko_ffi_name="mFont.opticalSizing",
gecko_constant_prefix="NS_FONT_OPTICAL_SIZING",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
spec="https://www.w3.org/TR/css-fonts-4/#font-optical-sizing-def",
)}
@ -513,9 +490,9 @@ ${helpers.single_keyword(
gecko_constant_prefix="NS_FONT_SMOOTHING",
gecko_ffi_name="mFont.smoothing",
gecko_pref="layout.css.osx-font-smoothing.enabled",
has_effect_on_gecko_scrollbars=False,
products="gecko",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth)",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
animation_value_type="discrete",
)}

View file

@ -14,7 +14,6 @@ ${helpers.single_keyword(
gecko_ffi_name="mVisible",
animation_value_type="ComputedValue",
spec="https://drafts.csswg.org/css-box/#propdef-visibility",
flags="APPLIES_TO_CUE",
)}
// CSS Writing Modes Level 3
@ -38,7 +37,6 @@ ${helpers.single_keyword(
animation_value_type="none",
spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
needs_conversion=True,
flags="APPLIES_TO_MARKER",
servo_restyle_damage="rebuild_and_reflow",
)}

View file

@ -10,6 +10,15 @@
// Section 10 - Text
${helpers.single_keyword(
"dominant-baseline",
"""auto ideographic alphabetic hanging mathematical central middle
text-after-edge text-before-edge""",
products="gecko",
animation_value_type="discrete",
spec="https://www.w3.org/TR/css-inline-3/#propdef-dominant-baseline",
)}
${helpers.single_keyword(
"text-anchor",
"start middle end",
@ -52,7 +61,7 @@ ${helpers.predefined_type(
"Default::default()",
products="gecko",
animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty",
spec="https://svgwg.org/svg2-draft/painting.html#FillOpacity",
)}
${helpers.predefined_type(
@ -123,7 +132,7 @@ ${helpers.predefined_type(
"Default::default()",
products="gecko",
animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty",
spec="https://svgwg.org/svg2-draft/painting.html#StrokeOpacity",
)}
${helpers.predefined_type(

View file

@ -11,7 +11,6 @@ ${helpers.predefined_type(
"ColorPropertyValue",
"::cssparser::RGBA::new(0, 0, 0, 255)",
animation_value_type="AnimatedRGBA",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
ignored_when_colors_disabled="True",
spec="https://drafts.csswg.org/css-color/#color",
)}
@ -21,8 +20,7 @@ ${helpers.predefined_type(
"LineHeight",
"computed::LineHeight::normal()",
animation_value_type="LineHeight",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE \
APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH",
flags="GETCS_NEEDS_LAYOUT_FLUSH",
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height",
servo_restyle_damage="reflow"
)}
@ -34,7 +32,6 @@ ${helpers.predefined_type(
"TextTransform",
"computed::TextTransform::none()",
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text/#propdef-text-transform",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -102,7 +99,7 @@ ${helpers.predefined_type(
gecko_enum_prefix="StyleTextJustify"
animation_value_type="discrete"
gecko_pref="layout.css.text-justify.enabled"
flags="APPLIES_TO_PLACEHOLDER",
has_effect_on_gecko_scrollbars="False"
spec="https://drafts.csswg.org/css-text/#propdef-text-justify"
servo_restyle_damage="rebuild_and_reflow"
>
@ -148,7 +145,6 @@ ${helpers.predefined_type(
"TextAlign",
"computed::TextAlign::Start",
animation_value_type="discrete",
flags="APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text/#propdef-text-align",
servo_restyle_damage = "reflow",
)}
@ -158,7 +154,6 @@ ${helpers.predefined_type(
"LetterSpacing",
"computed::LetterSpacing::normal()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -168,7 +163,6 @@ ${helpers.predefined_type(
"WordSpacing",
"computed::WordSpacing::zero()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -180,8 +174,6 @@ ${helpers.predefined_type(
gecko_enum_prefix="StyleWhiteSpace"
needs_conversion="True"
animation_value_type="discrete"
// Only allowed for UA sheets, which set it !important.
flags="APPLIES_TO_CUE APPLIES_TO_PLACEHOLDER"
spec="https://drafts.csswg.org/css-text/#propdef-white-space"
servo_restyle_damage="rebuild_and_reflow"
>
@ -229,7 +221,6 @@ ${helpers.predefined_type(
animation_value_type="AnimatedTextShadowList",
ignored_when_colors_disabled=True,
simple_vector_bindings=True,
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text-decor-3/#text-shadow-property",
)}
@ -293,7 +284,6 @@ ${helpers.predefined_type(
products="gecko",
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color",
)}
@ -305,7 +295,6 @@ ${helpers.predefined_type(
products="gecko",
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color",
)}
@ -316,7 +305,6 @@ ${helpers.predefined_type(
initial_specified_value="specified::BorderSideWidth::zero()",
computed_type="crate::values::computed::NonNegativeLength",
products="gecko",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-width",
animation_value_type="discrete",
)}
@ -337,7 +325,6 @@ ${helpers.single_keyword(
products="gecko",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-ruby/#ruby-position-property",
flags="APPLIES_TO_CUE",
)}
// CSS Writing Modes Module Level 3
@ -349,7 +336,6 @@ ${helpers.single_keyword(
products="gecko",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-writing-modes-3/#text-combine-upright",
flags="APPLIES_TO_CUE APPLIES_TO_MARKER",
)}
// SVG 1.1: Section 11 - Painting: Filling, Stroking and Marker Symbols
@ -382,6 +368,7 @@ ${helpers.predefined_type(
products="gecko",
animation_value_type="ComputedValue",
gecko_pref="layout.css.text-underline-offset.enabled",
has_effect_on_gecko_scrollbars=False,
spec="https://drafts.csswg.org/css-text-decor-4/#underline-offset",
)}
@ -394,5 +381,6 @@ ${helpers.predefined_type(
needs_context=False,
animation_value_type="discrete",
gecko_pref="layout.css.text-decoration-skip-ink.enabled",
has_effect_on_gecko_scrollbars=False,
spec="https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-ink-property",
)}

View file

@ -23,7 +23,6 @@ ${helpers.single_keyword(
"auto none",
animation_value_type="discrete",
extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all",
flags="APPLIES_TO_PLACEHOLDER",
spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty",
)}
@ -74,6 +73,10 @@ ${helpers.predefined_type(
"Default::default()",
spec="https://drafts.csswg.org/css-scrollbars-1/#scrollbar-color",
gecko_pref="layout.css.scrollbar-color.enabled",
# Surprisingly, yes the computed value of scrollbar-color has no effect on
# Gecko scrollbar elements, since the value only matters on the scrollable
# element itself.
has_effect_on_gecko_scrollbars=False,
animation_value_type="ScrollbarColor",
boxed=True,
ignored_when_colors_disabled=True,

View file

@ -22,7 +22,7 @@
logical=side[1],
logical_group="margin",
spec=spec,
flags="APPLIES_TO_FIRST_LETTER GETCS_NEEDS_LAYOUT_FLUSH",
flags="GETCS_NEEDS_LAYOUT_FLUSH",
allowed_in_page_rule=True,
servo_restyle_damage="reflow"
)}
@ -38,7 +38,6 @@
logical=side[1],
logical_group="scroll-margin",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-margin-%s" % side[0],
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE",
animation_value_type="ComputedValue",
)}
% endfor

View file

@ -18,7 +18,6 @@ ${helpers.predefined_type(
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
spec="https://drafts.csswg.org/css-ui/#propdef-outline-color",
flags="APPLIES_TO_CUE",
)}
${helpers.predefined_type(
@ -28,7 +27,6 @@ ${helpers.predefined_type(
initial_specified_value="specified::OutlineStyle::none()",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-ui/#propdef-outline-style",
flags="APPLIES_TO_CUE",
)}
${helpers.predefined_type(
@ -39,7 +37,6 @@ ${helpers.predefined_type(
computed_type="crate::values::computed::NonNegativeLength",
animation_value_type="NonNegativeLength",
spec="https://drafts.csswg.org/css-ui/#propdef-outline-width",
flags="APPLIES_TO_CUE",
)}
// The -moz-outline-radius-* properties are non-standard and not on a standards track.

View file

@ -6,8 +6,6 @@
<% from data import ALL_SIDES, maybe_moz_logical_alias %>
<% data.new_style_struct("Padding", inherited=False) %>
// APPLIES_TO_PLACEHOLDER so we can set it in UA stylesheets. But we use a
// !important value there, so pages can't set it.
% for side in ALL_SIDES:
<%
spec = "https://drafts.csswg.org/css-box/#propdef-padding-%s" % side[0]
@ -23,7 +21,7 @@
logical=side[1],
logical_group="padding",
spec=spec,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH",
flags="GETCS_NEEDS_LAYOUT_FLUSH",
allow_quirks="No" if side[1] else "Yes",
servo_restyle_damage="reflow rebuild_and_reflow_inline"
)}

View file

@ -6,15 +6,6 @@
<% data.new_style_struct("SVG", inherited=False, gecko_name="SVGReset") %>
${helpers.single_keyword(
"dominant-baseline",
"""auto use-script no-change reset-size ideographic alphabetic hanging
mathematical central middle text-after-edge text-before-edge""",
products="gecko",
animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/text.html#DominantBaselineProperty",
)}
${helpers.single_keyword(
"vector-effect",
"none non-scaling-stroke",
@ -40,7 +31,7 @@ ${helpers.predefined_type(
"1.0",
products="gecko",
animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVGTiny12/painting.html#propdef-stop-opacity",
spec="https://svgwg.org/svg2-draft/pservers.html#StopOpacityProperty",
)}
// Section 15 - Filter Effects
@ -60,7 +51,7 @@ ${helpers.predefined_type(
"1.0",
products="gecko",
animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty",
spec="https://drafts.fxtf.org/filter-effects/#FloodOpacityProperty",
)}
${helpers.predefined_type(

View file

@ -13,7 +13,6 @@ ${helpers.predefined_type(
"computed::TextOverflow::get_initial_value()",
animation_value_type="discrete",
boxed=True,
flags="APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -23,7 +22,6 @@ ${helpers.single_keyword(
"normal embed isolate bidi-override isolate-override plaintext",
animation_value_type="none",
spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi",
flags="APPLIES_TO_MARKER",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -33,7 +31,6 @@ ${helpers.predefined_type(
"specified::TextDecorationLine::none()",
initial_specified_value="specified::TextDecorationLine::none()",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line",
servo_restyle_damage="rebuild_and_reflow",
)}
@ -43,7 +40,6 @@ ${helpers.single_keyword(
"solid double dotted dashed wavy -moz-none",
products="gecko",
animation_value_type="discrete",
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style",
)}
@ -55,7 +51,6 @@ ${helpers.predefined_type(
products="gecko",
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color",
)}
@ -66,17 +61,16 @@ ${helpers.predefined_type(
initial_specified_value="specified::InitialLetter::normal()",
animation_value_type="discrete",
products="gecko",
flags="APPLIES_TO_FIRST_LETTER",
gecko_pref="layout.css.initial-letter.enabled",
spec="https://drafts.csswg.org/css-inline/#sizing-drop-initials",
)}
${helpers.predefined_type(
"text-decoration-width",
"text-decoration-thickness",
"LengthOrAuto",
"computed::LengthOrAuto::auto()",
products="gecko",
animation_value_type="ComputedValue",
gecko_pref="layout.css.text-decoration-width.enabled",
gecko_pref="layout.css.text-decoration-thickness.enabled",
spec="https://drafts.csswg.org/css-text-decor-4/#text-decoration-width-property"
)}

View file

@ -53,7 +53,7 @@ pub use self::cascade::*;
<%!
from collections import defaultdict
from data import Method, Keyword, to_rust_ident, to_camel_case, SYSTEM_FONT_LONGHANDS
from data import Method, PropertyRestrictions, Keyword, to_rust_ident, to_camel_case, SYSTEM_FONT_LONGHANDS
import os.path
%>
@ -812,6 +812,22 @@ impl LonghandIdSet {
&IGNORED_WHEN_COLORS_DISABLED
}
/// Returns the set of properties that are declared as having no effect on
/// Gecko <scrollbar> elements or their descendant scrollbar parts.
#[cfg(debug_assertions)]
#[cfg(feature = "gecko")]
#[inline]
pub fn has_no_effect_on_gecko_scrollbars() -> &'static Self {
// data.py asserts that has_no_effect_on_gecko_scrollbars is True or
// False for properties that are inherited and Gecko pref controlled,
// and is None for all other properties.
${static_longhand_id_set(
"HAS_NO_EFFECT_ON_SCROLLBARS",
lambda p: p.has_effect_on_gecko_scrollbars is False
)}
&HAS_NO_EFFECT_ON_SCROLLBARS
}
/// Iterate over the current longhand id set.
pub fn iter(&self) -> LonghandIdSetIterator {
LonghandIdSetIterator { longhands: self, cur: 0, }
@ -987,6 +1003,28 @@ bitflags! {
if logical_count * 2 != len(props):
raise RuntimeError("Logical group {} has ".format(group) +
"unbalanced logical / physical properties")
FIRST_LINE_RESTRICTIONS = PropertyRestrictions.first_line(data)
FIRST_LETTER_RESTRICTIONS = PropertyRestrictions.first_letter(data)
MARKER_RESTRICTIONS = PropertyRestrictions.marker(data)
PLACEHOLDER_RESTRICTIONS = PropertyRestrictions.placeholder(data)
CUE_RESTRICTIONS = PropertyRestrictions.cue(data)
def restriction_flags(property):
name = property.name
flags = []
if name in FIRST_LINE_RESTRICTIONS:
flags.append("APPLIES_TO_FIRST_LINE")
if name in FIRST_LETTER_RESTRICTIONS:
flags.append("APPLIES_TO_FIRST_LETTER")
if name in PLACEHOLDER_RESTRICTIONS:
flags.append("APPLIES_TO_PLACEHOLDER")
if name in MARKER_RESTRICTIONS:
flags.append("APPLIES_TO_MARKER")
if name in CUE_RESTRICTIONS:
flags.append("APPLIES_TO_CUE")
return flags
%>
/// A group for properties which may override each other
@ -1190,7 +1228,7 @@ impl LonghandId {
// constant expression support.
const FLAGS: [u16; ${len(data.longhands)}] = [
% for property in data.longhands:
% for flag in property.flags:
% for flag in property.flags + restriction_flags(property):
PropertyFlags::${flag}.bits |
% endfor
0,

View file

@ -15,7 +15,7 @@
use crate::properties::longhands::background_clip;
use crate::properties::longhands::background_clip::single_value::computed_value::T as Clip;
use crate::properties::longhands::background_origin::single_value::computed_value::T as Origin;
use crate::values::specified::{Color, Position, PositionComponent};
use crate::values::specified::{AllowQuirks, Color, Position, PositionComponent};
use crate::parser::Parse;
// FIXME(emilio): Should be the same type!
@ -64,7 +64,9 @@
}
}
if position.is_none() {
if let Ok(value) = input.try(|input| Position::parse(context, input)) {
if let Ok(value) = input.try(|input| {
Position::parse_three_value_quirky(context, input, AllowQuirks::No)
}) {
position = Some(value);
// Parse background size, if applicable.
@ -211,7 +213,7 @@
let mut any = false;
input.parse_comma_separated(|input| {
let value = Position::parse_quirky(context, input, AllowQuirks::Yes)?;
let value = Position::parse_three_value_quirky(context, input, AllowQuirks::Yes)?;
position_x.push(value.horizontal);
position_y.push(value.vertical);
any = true;

View file

@ -15,7 +15,8 @@ use crate::values::computed::CSSPixelLength;
use crate::values::KeyframesName;
use app_units::Au;
use cssparser::RGBA;
use euclid::{Size2D, TypedScale, TypedSize2D};
use euclid::default::Size2D as UntypedSize2D;
use euclid::{Scale, Size2D};
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
use style_traits::viewport::ViewportConstraints;
use style_traits::{CSSPixel, DevicePixel};
@ -29,9 +30,9 @@ pub struct Device {
/// The current media type used by de device.
media_type: MediaType,
/// The current viewport size, in CSS pixels.
viewport_size: TypedSize2D<f32, CSSPixel>,
viewport_size: Size2D<f32, CSSPixel>,
/// The current device pixel ratio, from CSS pixels to device pixels.
device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
/// The font size of the root element
/// This is set when computing the style of the root
@ -59,8 +60,8 @@ impl Device {
/// Trivially construct a new `Device`.
pub fn new(
media_type: MediaType,
viewport_size: TypedSize2D<f32, CSSPixel>,
device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
viewport_size: Size2D<f32, CSSPixel>,
device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
) -> Device {
Device {
media_type,
@ -121,7 +122,7 @@ impl Device {
/// Returns the viewport size of the current device in app units, needed,
/// among other things, to resolve viewport units.
#[inline]
pub fn au_viewport_size(&self) -> Size2D<Au> {
pub fn au_viewport_size(&self) -> UntypedSize2D<Au> {
Size2D::new(
Au::from_f32_px(self.viewport_size.width),
Au::from_f32_px(self.viewport_size.height),
@ -129,7 +130,7 @@ impl Device {
}
/// Like the above, but records that we've used viewport units.
pub fn au_viewport_size_for_viewport_unit_resolution(&self) -> Size2D<Au> {
pub fn au_viewport_size_for_viewport_unit_resolution(&self) -> UntypedSize2D<Au> {
self.used_viewport_units.store(true, Ordering::Relaxed);
self.au_viewport_size()
}
@ -140,7 +141,7 @@ impl Device {
}
/// Returns the device pixel ratio.
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
self.device_pixel_ratio
}

View file

@ -181,18 +181,29 @@ impl UrlExtraData {
#[cfg(feature = "gecko")]
impl fmt::Debug for UrlExtraData {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
struct DebugURI(*mut structs::nsIURI);
impl fmt::Debug for DebugURI {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use nsstring::nsCString;
let mut spec = nsCString::new();
unsafe {
bindings::Gecko_nsIURI_Debug(self.0, &mut spec);
macro_rules! define_debug_struct {
($struct_name:ident, $gecko_class:ident, $debug_fn:ident) => {
struct $struct_name(*mut structs::$gecko_class);
impl fmt::Debug for $struct_name {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use nsstring::nsCString;
let mut spec = nsCString::new();
unsafe {
bindings::$debug_fn(self.0, &mut spec);
}
spec.fmt(formatter)
}
}
spec.fmt(formatter)
}
};
}
define_debug_struct!(DebugURI, nsIURI, Gecko_nsIURI_Debug);
define_debug_struct!(
DebugReferrerInfo,
nsIReferrerInfo,
Gecko_nsIReferrerInfo_Debug
);
formatter
.debug_struct("URLExtraData")
.field("is_chrome", &self.is_chrome())
@ -202,7 +213,11 @@ impl fmt::Debug for UrlExtraData {
)
.field(
"referrer",
&DebugURI(self.as_ref().mReferrer.raw::<structs::nsIURI>()),
&DebugReferrerInfo(
self.as_ref()
.mReferrerInfo
.raw::<structs::nsIReferrerInfo>(),
),
)
.finish()
}

View file

@ -25,7 +25,7 @@ use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercen
use app_units::Au;
use cssparser::CowRcStr;
use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
use euclid::TypedSize2D;
use euclid::Size2D;
use selectors::parser::SelectorParseErrorKind;
use std::borrow::Cow;
use std::cell::RefCell;
@ -832,7 +832,7 @@ impl MaybeNew for ViewportConstraints {
});
Some(ViewportConstraints {
size: TypedSize2D::new(width.to_f32_px(), height.to_f32_px()),
size: Size2D::new(width.to_f32_px(), height.to_f32_px()),
// TODO: compute a zoom factor for 'auto' as suggested by DEVICE-ADAPT § 10.
initial_zoom: PinchZoomFactor::new(initial_zoom.unwrap_or(1.)),

View file

@ -7,28 +7,12 @@
#[cfg(feature = "gecko")]
pub use crate::values::specified::list::ListStyleType;
pub use crate::values::specified::list::MozListReversed;
pub use crate::values::specified::list::{QuotePair, Quotes};
lazy_static! {
static ref INITIAL_QUOTES: crate::ArcSlice<QuotePair> = crate::ArcSlice::from_iter_leaked(
vec![
QuotePair {
opening: "\u{201c}".to_owned().into(),
closing: "\u{201d}".to_owned().into(),
},
QuotePair {
opening: "\u{2018}".to_owned().into(),
closing: "\u{2019}".to_owned().into(),
},
]
.into_iter()
);
}
pub use crate::values::specified::list::Quotes;
impl Quotes {
/// Initial value for `quotes`.
#[inline]
pub fn get_initial_value() -> Quotes {
Quotes(INITIAL_QUOTES.clone())
Quotes::Auto
}
}

View file

@ -23,7 +23,7 @@ use crate::rule_cache::RuleCacheConditions;
use crate::Atom;
#[cfg(feature = "servo")]
use crate::Prefix;
use euclid::Size2D;
use euclid::default::Size2D;
use std::cell::RefCell;
use std::cmp;
use std::f32;
@ -64,7 +64,7 @@ pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageO
#[cfg(feature = "gecko")]
pub use self::list::ListStyleType;
pub use self::list::MozListReversed;
pub use self::list::{QuotePair, Quotes};
pub use self::list::Quotes;
pub use self::motion::{OffsetPath, OffsetRotate};
pub use self::outline::OutlineStyle;
pub use self::percentage::{NonNegativePercentage, Percentage};

View file

@ -10,7 +10,7 @@ use crate::values::animated::ToAnimatedZero;
use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
use crate::values::generics::transform as generic;
use crate::Zero;
use euclid::{Transform3D, Vector3D};
use euclid::default::{Transform3D, Vector3D};
pub use crate::values::generics::transform::TransformStyle;

View file

@ -5,7 +5,7 @@
//! Machinery to compute distances between animatable values.
use app_units::Au;
use euclid::Size2D;
use euclid::default::Size2D;
use std::iter::Sum;
use std::ops::Add;

View file

@ -12,7 +12,8 @@ use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercent
use crate::values::{computed, CSSFloat};
use crate::Zero;
use app_units::Au;
use euclid::{self, Rect, Transform3D};
use euclid;
use euclid::default::{Rect, Transform3D};
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
@ -562,7 +563,7 @@ impl<T: ToMatrix> Transform<T> {
for operation in &*self.0 {
let matrix = operation.to_3d_matrix(reference_box)?;
contain_3d |= operation.is_3d();
transform = transform.pre_mul(&matrix);
transform = transform.pre_transform(&matrix);
}
Ok((transform, contain_3d))

View file

@ -22,7 +22,7 @@ use crate::values::CSSFloat;
use crate::Zero;
use app_units::Au;
use cssparser::{Parser, Token};
use euclid::Size2D;
use euclid::default::Size2D;
use std::cmp;
use std::ops::{Add, Mul};
use style_traits::values::specified::AllowedNumericType;

View file

@ -104,7 +104,7 @@ pub struct QuotePair {
pub closing: crate::OwnedStr,
}
/// Specified and computed `quotes` property.
/// List of quote pairs for the specified/computed value of `quotes` property.
#[derive(
Clone,
Debug,
@ -117,23 +117,53 @@ pub struct QuotePair {
ToResolvedValue,
ToShmem,
)]
#[repr(C)]
pub struct Quotes(
#[repr(transparent)]
pub struct QuoteList(
#[css(iterable, if_empty = "none")]
#[ignore_malloc_size_of = "Arc"]
pub crate::ArcSlice<QuotePair>,
);
/// Specified and computed `quotes` property: `auto`, `none`, or a list
/// of characters.
///
/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(
Clone,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[repr(C)]
pub enum Quotes {
/// list of quote pairs
QuoteList(QuoteList),
/// auto (use lang-dependent quote marks)
Auto,
}
impl Parse for Quotes {
fn parse<'i, 't>(
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Quotes, ParseError<'i>> {
if input
.try(|input| input.expect_ident_matching("auto"))
.is_ok()
{
return Ok(Quotes::Auto);
}
if input
.try(|input| input.expect_ident_matching("none"))
.is_ok()
{
return Ok(Self::default());
return Ok(Quotes::QuoteList(QuoteList::default()));
}
let mut quotes = Vec::new();
@ -150,7 +180,9 @@ impl Parse for Quotes {
}
if !quotes.is_empty() {
Ok(Quotes(crate::ArcSlice::from_iter(quotes.into_iter())))
Ok(Quotes::QuoteList(QuoteList(crate::ArcSlice::from_iter(
quotes.into_iter(),
))))
} else {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}

View file

@ -65,7 +65,7 @@ pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageO
#[cfg(feature = "gecko")]
pub use self::list::ListStyleType;
pub use self::list::MozListReversed;
pub use self::list::{QuotePair, Quotes};
pub use self::list::Quotes;
pub use self::motion::{OffsetPath, OffsetRotate};
pub use self::outline::OutlineStyle;
pub use self::percentage::Percentage;
@ -402,14 +402,18 @@ impl Parse for NonNegativeNumberOrPercentage {
}
}
#[allow(missing_docs)]
/// The value of Opacity is <alpha-value>, which is "<number> | <percentage>".
/// However, we serialize the specified value as number, so it's ok to store
/// the Opacity as Number.
#[derive(
Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo, ToCss, ToShmem,
)]
pub struct Opacity(Number);
impl Parse for Opacity {
fn parse<'i, 't>(
impl Opacity {
/// Parse number value only.
#[inline]
pub fn parse_number<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
@ -417,6 +421,29 @@ impl Parse for Opacity {
}
}
impl Parse for Opacity {
/// Opacity accepts <number> | <percentage>, so we parse it as NumberOrPercentage,
/// and then convert into an Number if it's a Percentage.
/// https://drafts.csswg.org/cssom/#serializing-css-values
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let number = match NumberOrPercentage::parse(context, input)? {
NumberOrPercentage::Percentage(p) => Number {
value: p.get(),
calc_clamping_mode: if p.is_calc() {
Some(AllowedNumericType::All)
} else {
None
},
},
NumberOrPercentage::Number(n) => n,
};
Ok(Opacity(number))
}
}
impl ToComputedValue for Opacity {
type ComputedValue = CSSFloat;

View file

@ -94,13 +94,17 @@ impl Parse for Position {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
let position = Self::parse_three_value_quirky(context, input, AllowQuirks::No)?;
if position.is_three_value_syntax() {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok(position)
}
}
impl Position {
/// Parses a `<position>`, with quirks.
pub fn parse_quirky<'i, 't>(
/// Parses a `<bg-position>`, with quirks.
pub fn parse_three_value_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
@ -183,6 +187,12 @@ impl Position {
pub fn center() -> Self {
Self::new(PositionComponent::Center, PositionComponent::Center)
}
/// Returns true if this uses a 3 value syntax.
#[inline]
fn is_three_value_syntax(&self) -> bool {
self.horizontal.component_count() != self.vertical.component_count()
}
}
impl ToCss for Position {
@ -252,6 +262,20 @@ impl<S> PositionComponent<S> {
pub fn zero() -> Self {
PositionComponent::Length(LengthPercentage::Percentage(Percentage::zero()))
}
/// Returns the count of this component.
fn component_count(&self) -> usize {
match *self {
PositionComponent::Length(..) | PositionComponent::Center => 1,
PositionComponent::Side(_, ref lp) => {
if lp.is_some() {
2
} else {
1
}
},
}
}
}
impl<S: Side> ToComputedValue for PositionComponent<S> {