New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stylo: Use atoms as the pseudo-element back-end. #12815
Changes from 1 commit
f9f347e
54b9201
12fcb7a
df44ba4
b1091df
d612d9f
010bce1
6bce4c8
babb2b7
24168f8
2b3c684
09cc240
File filter...
Jump to…
stylo: Allow regenerating atoms as part of the normal generation of b…
…indings. This configures the regeneration of atoms as part of the normal generation of bindings, so it stops being a whole different process. This also adds a generated file to components/style/generated with a convenience macro invocation for pseudo-elements, which comes handy in order to avoid duplication.
- Loading branch information
Unverified
| @@ -0,0 +1,194 @@ | ||
| #!/usr/bin/env python | ||
|
|
||
| # This Source Code Form is subject to the terms of the Mozilla Public | ||
| # License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| # file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
|
||
| import re | ||
| import os | ||
|
|
||
|
|
||
| def gnu_symbolify(source, ident): | ||
| return "_ZN" + str(len(source.CLASS)) + source.CLASS + str(len(ident)) + ident + "E" | ||
|
|
||
|
|
||
| def msvc64_symbolify(source, ident): | ||
| return "?" + ident + "@" + source.CLASS + "@@2PEAV" + source.TYPE + "@@EA" | ||
|
|
||
|
|
||
| def msvc32_symbolify(source, ident): | ||
| return "?" + ident + "@" + source.CLASS + "@@2PAV" + source.TYPE + "@@A" | ||
upsuper
Member
|
||
|
|
||
|
|
||
| class GkAtomSource: | ||
| PATTERN = re.compile('^GK_ATOM\((.+),\s*"(.*)"\)') | ||
| FILE = "dist/include/nsGkAtomList.h" | ||
| CLASS = "nsGkAtoms" | ||
| TYPE = "nsIAtom" | ||
|
|
||
|
|
||
| class CSSPseudoElementsAtomSource: | ||
| PATTERN = re.compile('^CSS_PSEUDO_ELEMENT\((.+),\s*"(.*)",') | ||
| FILE = "dist/include/nsCSSPseudoElementList.h" | ||
| CLASS = "nsCSSPseudoElements" | ||
| # NB: nsICSSPseudoElement is effectively the same as a nsIAtom, but we need | ||
| # this for MSVC name mangling. | ||
| TYPE = "nsICSSPseudoElement" | ||
|
|
||
|
|
||
| class CSSAnonBoxesAtomSource: | ||
| PATTERN = re.compile('^CSS_ANON_BOX\((.+),\s*"(.*)"\)') | ||
| FILE = "dist/include/nsCSSAnonBoxList.h" | ||
| CLASS = "nsCSSAnonBoxes" | ||
| TYPE = "nsICSSAnonBoxPseudo" | ||
|
|
||
|
|
||
| SOURCES = [ | ||
| GkAtomSource, | ||
| CSSPseudoElementsAtomSource, | ||
| CSSAnonBoxesAtomSource, | ||
| ] | ||
|
|
||
|
|
||
| def map_atom(ident): | ||
| if ident in {"box", "loop", "match", "mod", "ref", | ||
| "self", "type", "use", "where", "in"}: | ||
| return ident + "_" | ||
| return ident | ||
|
|
||
|
|
||
| class Atom: | ||
| def __init__(self, source, ident, value): | ||
| self.ident = "{}_{}".format(source.CLASS, ident) | ||
| self._original_ident = ident | ||
| self.value = value | ||
| self.source = source | ||
|
|
||
| def cpp_class(self): | ||
| return self.source.CLASS | ||
|
|
||
| def gnu_symbol(self): | ||
| return gnu_symbolify(self.source, self._original_ident) | ||
|
|
||
| def msvc32_symbol(self): | ||
| return msvc32_symbolify(self.source, self._original_ident) | ||
|
|
||
| def msvc64_symbol(self): | ||
| return msvc64_symbolify(self.source, self._original_ident) | ||
|
|
||
| def type(self): | ||
| return self.source.TYPE | ||
|
|
||
|
|
||
| def collect_atoms(objdir): | ||
| atoms = [] | ||
| for source in SOURCES: | ||
| with open(os.path.join(objdir, source.FILE)) as f: | ||
| for line in f.readlines(): | ||
| result = re.match(source.PATTERN, line) | ||
| if result: | ||
| atoms.append(Atom(source, result.group(1), result.group(2))) | ||
| return atoms | ||
|
|
||
| PRELUDE = """ | ||
| /* This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
| /* Autogenerated file, DO NOT EDIT DIRECTLY */ | ||
| """[1:] | ||
|
|
||
|
|
||
| def write_atom_macro(atoms, file_name): | ||
| ATOM_TEMPLATE = """ | ||
| #[link_name = "{link_name}"] | ||
| pub static {name}: *mut {type}; | ||
| """[1:] | ||
|
|
||
| def write_items(f, func): | ||
| f.write(" extern {\n") | ||
| for atom in atoms: | ||
| f.write(ATOM_TEMPLATE.format(name=atom.ident, | ||
| link_name=func(atom), | ||
| type=atom.type())) | ||
| f.write(" }\n") | ||
|
|
||
| with open(file_name, "wb") as f: | ||
| f.write(PRELUDE) | ||
| f.write("use gecko_bindings::structs::nsIAtom;\n\n") | ||
| f.write("use Atom;\n\n") | ||
| for source in SOURCES: | ||
| if source.TYPE != "nsIAtom": | ||
| f.write("pub enum {} {{}}\n\n".format(source.TYPE)) | ||
| f.write(""" | ||
| #[inline(always)] pub fn unsafe_atom_from_static(ptr: *mut nsIAtom) -> Atom { | ||
| unsafe { Atom::from_static(ptr) } | ||
| }\n\n | ||
| """) | ||
| f.write("cfg_if! {\n") | ||
| f.write(" if #[cfg(not(target_env = \"msvc\"))] {\n") | ||
| write_items(f, Atom.gnu_symbol) | ||
| f.write(" } else if #[cfg(target_pointer_width = \"64\")] {\n") | ||
| write_items(f, Atom.msvc64_symbol) | ||
| f.write(" } else {\n") | ||
| write_items(f, Atom.msvc32_symbol) | ||
| f.write(" }\n") | ||
| f.write("}\n\n") | ||
| f.write("#[macro_export]\n") | ||
| f.write("macro_rules! atom {\n") | ||
| f.writelines(['("%s") => { $crate::atom_macro::unsafe_atom_from_static($crate::atom_macro::%s as *mut _) };\n' | ||
| % (atom.value, atom.ident) for atom in atoms]) | ||
| f.write("}\n") | ||
|
|
||
|
|
||
| PSEUDO_ELEMENT_HEADER = """ | ||
| /* | ||
| * This file contains a helper macro invocation to aid Gecko's style system | ||
| * pseudo-element integration. | ||
| * | ||
| * This file is NOT INTENDED to be compiled as a standalone module. | ||
| * | ||
| * Also, it guarantees the property that normal pseudo-elements are processed | ||
| * before anonymous boxes. | ||
|
||
| * | ||
| * Expected usage is as follows: | ||
| * | ||
| * ``` | ||
| * fn have_to_use_pseudo_elements() { | ||
| * macro_rules pseudo_element! { | ||
| * ($pseudo_str_with_colon:expr, $pseudo_atom:expr, $is_anon_box:true) => {{ | ||
| * // Stuff stuff stuff. | ||
| * }} | ||
| * } | ||
| * include!("path/to/helper.rs") | ||
| * } | ||
| * ``` | ||
| * | ||
| */ | ||
| """ | ||
|
|
||
| PSEUDO_ELEMENT_MACRO_INVOCATION = """ | ||
| pseudo_element!(\"{}\", | ||
| atom!(\"{}\"), | ||
| {}); | ||
| """[1:] | ||
|
|
||
|
|
||
| def write_pseudo_element_helper(atoms, target_filename): | ||
| with open(target_filename, "wb") as f: | ||
| f.write(PRELUDE) | ||
| f.write(PSEUDO_ELEMENT_HEADER) | ||
| f.write("{\n") | ||
| for atom in atoms: | ||
| if atom.type() == "nsICSSPseudoElement": | ||
| f.write(PSEUDO_ELEMENT_MACRO_INVOCATION.format(atom.value, atom.value, "false")) | ||
| elif atom.type() == "nsICSSAnonBoxPseudo": | ||
| f.write(PSEUDO_ELEMENT_MACRO_INVOCATION.format(atom.value, atom.value, "true")) | ||
| f.write("}\n") | ||
|
|
||
|
|
||
| def build(objdir, verbose=False): | ||
| atoms = collect_atoms(objdir) | ||
| write_atom_macro(atoms, "../string_cache/atom_macro.rs") | ||
| write_pseudo_element_helper(atoms, "../../../components/style/generated/gecko_pseudo_element_helper.rs") | ||
| return 0 | ||
This file was deleted.
cc @upsuper, hopefully I got the msvc manglings fine.