diff --git a/Cargo.lock b/Cargo.lock index 5e22965bdfc..bb081b3e3f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2886,6 +2886,7 @@ dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", + "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "fallible 0.0.1", diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 16d46eb6e26..cda14b1decf 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -32,6 +32,7 @@ bitflags = "1.0" byteorder = "1.0" cfg-if = "0.1.0" cssparser = "0.23.0" +debug_unreachable = "0.1.1" encoding_rs = {version = "0.7", optional = true} euclid = "0.16" fallible = { path = "../fallible" } diff --git a/components/style/lib.rs b/components/style/lib.rs index 5c5a837d5ba..429d813a754 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -33,6 +33,7 @@ extern crate bitflags; #[allow(unused_extern_crates)] extern crate byteorder; #[cfg(feature = "gecko")] #[macro_use] #[no_link] extern crate cfg_if; #[macro_use] extern crate cssparser; +#[macro_use] extern crate debug_unreachable; extern crate euclid; extern crate fallible; extern crate fnv; diff --git a/components/style/properties/data.py b/components/style/properties/data.py index ac7f9e427f7..4c9d2a066c7 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -226,6 +226,58 @@ class Longhand(object): def enabled_in_content(self): return self.enabled_in == "content" + def specified_type(self): + if self.predefined_type and not self.is_vector: + ty = "::values::specified::{}".format(self.predefined_type) + else: + ty = "longhands::{}::SpecifiedValue".format(self.ident) + if self.boxed: + ty = "Box<{}>".format(ty) + return ty + + def specified_is_copy(self): + if self.is_vector or self.boxed: + return False + if self.predefined_type: + return self.predefined_type in { + "AlignContent", + "AlignItems", + "AlignSelf", + "BackgroundRepeat", + "BorderImageRepeat", + "BorderStyle", + "Contain", + "FontStyleAdjust", + "FontSynthesis", + "FontWeight", + "GridAutoFlow", + "ImageOrientation", + "InitialLetter", + "Integer", + "IntegerOrAuto", + "JustifyContent", + "JustifyItems", + "JustifySelf", + "MozForceBrokenImageIcon", + "MozScriptLevel", + "MozScriptMinSize", + "MozScriptSizeMultiplier", + "NonNegativeNumber", + "Opacity", + "OutlineStyle", + "OverscrollBehavior", + "Percentage", + "PositiveIntegerOrAuto", + "SVGPaintOrder", + "ScrollSnapType", + "TextDecorationLine", + "TouchAction", + "TransformStyle", + "XSpan", + "XTextZoom", + } + return bool(self.keyword) + class Shorthand(object): def __init__(self, name, sub_properties, spec=None, servo_pref=None, gecko_pref=None, diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index edd82ce6236..aa78d329180 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -206,59 +206,22 @@ pub mod animated_properties { <% from itertools import groupby - copyTypes = set([ - "AlignContent", - "AlignItems", - "AlignSelf", - "BackgroundRepeat", - "BorderImageRepeat", - "BorderStyle", - "Contain", - "FontStyleAdjust", - "FontSynthesis", - "FontWeight", - "GridAutoFlow", - "ImageOrientation", - "InitialLetter", - "Integer", - "IntegerOrAuto", - "JustifyContent", - "JustifyItems", - "JustifySelf", - "MozForceBrokenImageIcon", - "MozScriptLevel", - "MozScriptMinSize", - "MozScriptSizeMultiplier", - "NonNegativeNumber", - "Opacity", - "OutlineStyle", - "OverscrollBehavior", - "Percentage", - "PositiveIntegerOrAuto", - "SVGPaintOrder", - "ScrollSnapType", - "TextDecorationLine", - "TouchAction", - "TransformStyle", - "XSpan", - "XTextZoom", - ]) + # After this code, `data.longhands` is sorted in the following order: + # - first all keyword variants and all variants known to be Copy, + # - second all the other variants, such as all variants with the same field + # have consecutive discriminants. + # The variable `variants` contain the same entries as `data.longhands` in + # the same order, but must exist separately to the data source, because + # we then need to add three additional variants `WideKeywordDeclaration`, + # `VariableDeclaration` and `CustomDeclaration`. variants = [] for property in data.longhands: - if property.predefined_type and not property.is_vector: - copy = property.predefined_type in copyTypes - ty = "::values::specified::{}".format(property.predefined_type) - else: - copy = bool(property.keyword) and not property.is_vector - ty = "longhands::{}::SpecifiedValue".format(property.ident) - if property.boxed: - ty = "Box<{}>".format(ty) variants.append({ "name": property.camel_case, - "type": ty, + "type": property.specified_type(), "doc": "`" + property.name + "`", - "copy": copy, + "copy": property.specified_is_copy(), }) groups = {} @@ -335,24 +298,31 @@ impl Clone for PropertyDeclaration { [copy, others] = [list(g) for _, g in groupby(variants, key=lambda x: not x["copy"])] %> + let self_tag = unsafe { + (*(self as *const _ as *const PropertyDeclarationVariantRepr<()>)).tag + }; + if self_tag <= LonghandId::${copy[-1]["name"]} as u16 { + #[derive(Clone, Copy)] + #[repr(u16)] + enum CopyVariants { + % for v in copy: + _${v["name"]}(${v["type"]}), + % endfor + } + + unsafe { + let mut out = mem::uninitialized(); + ptr::write( + &mut out as *mut _ as *mut CopyVariants, + *(self as *const _ as *const CopyVariants), + ); + return out; + } + } + match *self { ${" |\n".join("{}(..)".format(v["name"]) for v in copy)} => { - #[derive(Clone, Copy)] - #[repr(u16)] - enum CopyVariants { - % for v in copy: - _${v["name"]}(${v["type"]}), - % endfor - } - - unsafe { - let mut out = mem::uninitialized(); - ptr::write( - &mut out as *mut _ as *mut CopyVariants, - *(self as *const _ as *const CopyVariants), - ); - out - } + unsafe { debug_unreachable!() } } % for ty, vs in groupby(others, key=lambda x: x["type"]): <%