author Nika Layzell <>
Tue, 25 Sep 2018 17:34:53 +0200
changeset 507828 5e6dae0c1e5a4939ccd406f14607f7fafffd45a7
parent 505764 76aa81358d762cbc618c1913061b57eccc145b1d
child 508152 c5b713000513a2cdc1fdbc70aeb8f7d78bd687b2
permissions -rw-r--r--
Bug 1448426 - Wrap windows.h to avoid problematic define statements, r=froydnj,glandium By default, windows.h exposes a large number of problematic define statements which are UpperCamelCase, such as a define from `CreateWindow` to `CreateWindow{A,W}`. As many of these names are generic (e.g. CreateFile, CreateWindow), they can mess up Gecko code that may legitimately have its own methods with the same names. The header also defines some traditional SCREAMING_SNAKE_CASE defines which can mess up our code by conflicting with local values. This patch adds a simple code generator which generates wrappers for these defines, and uses them to wrap the windows.h wrapper using the `stl_wrappers` mechanism, allowing us to use windows.h in more places. Differential Revision:

# 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

def _assign_slots(obj, args):
    for i, attr in enumerate(obj.__slots__):
        setattr(obj, attr, args[i])

class Longhand(object):
    __slots__ = ["name", "method", "id", "flags", "pref"]

    def __init__(self, *args):
        _assign_slots(self, args)

    def type():
        return "longhand"

class Shorthand(object):
    __slots__ = ["name", "method", "id", "flags", "pref", "subprops"]

    def __init__(self, *args):
        _assign_slots(self, args)

    def type():
        return "shorthand"

class Alias(object):
    __slots__ = ["name", "method", "alias_id", "prop_id", "flags", "pref"]

    def __init__(self, *args):
        _assign_slots(self, args)

    def type():
        return "alias"

# See bug 1454823 for situation of internal flag.
def is_internal(prop):
    # A property which is not controlled by pref and not enabled in
    # content by default is an internal property.
    if not prop.gecko_pref and not prop.enabled_in_content():
        return True
    # There are some special cases we may want to remove eventually.
    return in OTHER_INTERNALS

def method(prop):
    if == "float":
        return "CssFloat"
        return prop.camel_case[1:]
    return prop.camel_case

# Colors, integers and lengths are easy as well.
# TODO(emilio): This will go away once the rest of the longhands have been
# moved or perhaps using a blacklist for the ones with non-layout-dependence
# but other non-trivial dependence like scrollbar colors.

def serialized_by_servo(prop):
    # If the property requires layout information, no such luck.
    if "GETCS_NEEDS_LAYOUT_FLUSH" in prop.flags:
        return False
    if prop.type() == "shorthand":
        # FIXME: Need to serialize a value interpolated with currentcolor
        # properly to be able to use text-decoration, and figure out what to do
        # with relative mask urls.
        return != "text-decoration" and != "mask"
    # Keywords are all fine, except -moz-osx-font-smoothing, which does
    # resistfingerprinting stuff.
    if prop.keyword and != "-moz-osx-font-smoothing":
        return True
    if prop.predefined_type in SERIALIZED_PREDEFINED_TYPES:
        return True
    # TODO(emilio): Enable the rest of the longhands.
    return False

def exposed_on_getcs(prop):
    if prop.type() == "longhand":
        return not is_internal(prop)
    # TODO: bug 137688 /
    if prop.type() == "shorthand":
        return "SHORTHAND_IN_GETCS" in prop.flags

def flags(prop):
    result = []
    if prop.explicitly_enabled_in_chrome():
    elif prop.explicitly_enabled_in_ua_sheets():
    if is_internal(prop):
    if prop.enabled_in == "":
    if "GETCS_NEEDS_LAYOUT_FLUSH" in prop.flags:
    if "CAN_ANIMATE_ON_COMPOSITOR" in prop.flags:
    if exposed_on_getcs(prop):
        if serialized_by_servo(prop):
    if prop.type() == "longhand" and prop.logical:
    return ", ".join('"{}"'.format(flag) for flag in result)

def pref(prop):
    if prop.gecko_pref:
        return '"' + prop.gecko_pref + '"'
    return '""'

def sub_properties(prop):
    return ", ".join('"{}"'.format(p.ident) for p in prop.sub_properties)

data = [
    % for prop in data.longhands:
    Longhand("${}", "${method(prop)}", "${prop.ident}", [${flags(prop)}], ${pref(prop)}),
    % endfor

    % for prop in data.shorthands:
    Shorthand("${}", "${prop.camel_case}", "${prop.ident}", [${flags(prop)}], ${pref(prop)},
    % endfor

    % for prop in data.all_aliases():
    Alias("${}", "${prop.camel_case}", "${prop.ident}", "${prop.original.ident}", [], ${pref(prop)}),
    % endfor