no bug - Correct some typos in the comments. a=typo-fix
[gecko.git] / js / src / GeneratePrefs.py
blobb28114c25994c06f248a7ec85b40ade0ceaa104a
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 # This script generates js/public/PrefsGenerated.h from StaticPrefList.yaml
7 import buildconfig
8 import six
9 import yaml
10 from mozbuild.preprocessor import Preprocessor
12 HEADER_TEMPLATE = """\
13 /* This Source Code Form is subject to the terms of the Mozilla Public
14 * License, v. 2.0. If a copy of the MPL was not distributed with this
15 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
17 #ifndef js_PrefsGenerated_h
18 #define js_PrefsGenerated_h
20 /* This file is generated by js/src/GeneratePrefs.py. Do not edit! */
22 #include "mozilla/Atomics.h"
24 #include <stdint.h>
26 %(contents)s
28 #endif // js_PrefsGenerated_h
29 """
32 def load_yaml(yaml_path):
33 # First invoke the preprocessor to handle #ifdefs in the YAML file.
34 pp = Preprocessor()
35 pp.context.update(buildconfig.defines["ALLDEFINES"])
37 # To make #ifdef DEBUG work, use a similar hack as in emit_code in
38 # generate_static_pref_list.py.
39 if buildconfig.substs.get("MOZ_DEBUG"):
40 pp.context["DEBUG"] = "1"
42 pp.out = six.StringIO()
43 pp.do_filter("substitution")
44 pp.do_include(yaml_path)
45 contents = pp.out.getvalue()
46 return yaml.safe_load(contents)
49 # Returns the C++ type to use for the pref type from the YAML file. Always use
50 # the non-atomic type for return values and arguments. The field type is
51 # determined elsewhere.
52 def get_cpp_type(type):
53 if type in ("bool", "RelaxedAtomicBool"):
54 return "bool"
55 if type in ("uint32_t", "RelaxedAtomicUint32"):
56 return "uint32_t"
57 if type in ("int32_t", "RelaxedAtomicInt32"):
58 return "int32_t"
59 raise Exception("Unexpected type: {}".format(type))
62 # Returns a C++ expression for the default pref value. Booleans in the YAML file
63 # are converted to Pythonic True or False, so those need special handling.
64 def get_cpp_init_value(val):
65 if val is True:
66 return "true"
67 if val is False:
68 return "false"
69 return str(val)
72 def generate_prefs_header(c_out, yaml_path):
73 prefs = load_yaml(yaml_path)
75 js_options_prefix = "javascript.options."
77 def is_js_pref(pref):
78 set_spidermonkey_pref = pref.get("set_spidermonkey_pref", False)
79 if set_spidermonkey_pref not in (False, "startup", "always"):
80 raise Exception("Invalid value for set_spidermonkey_pref")
82 # Ignore prefs that don't have the |set_spidermonkey_pref| attribute.
83 if set_spidermonkey_pref is False:
84 return False
86 # Only support prefs with javascript.options prefix.
87 if not pref["name"].startswith(js_options_prefix):
88 raise Exception("set_spidermonkey_pref only works for JS prefs")
90 return True
92 # Remove all non-JS prefs and sort prefs by name.
93 prefs = list(filter(is_js_pref, prefs))
94 prefs.sort(key=lambda pref: pref["name"])
96 class_fields = []
97 class_fields_inits = []
99 macro_entries = []
100 browser_set_statements = []
101 browser_set_non_startup_statements = []
103 for pref in prefs:
104 name = pref["name"]
105 name = name[len(js_options_prefix) :]
107 is_startup_pref = pref["set_spidermonkey_pref"] == "startup"
109 cpp_name = name.replace(".", "_").replace("-", "_")
110 type = get_cpp_type(pref["type"])
111 init_value = get_cpp_init_value(pref["value"])
113 setter_name = ("setAtStartup_" if is_startup_pref else "set_") + cpp_name
115 # Use a relaxed atomic for non-startup prefs because those might be changed
116 # after startup.
117 field_type = type
118 if not is_startup_pref:
119 field_type = "mozilla::Atomic<{}, mozilla::Relaxed>".format(field_type)
120 class_fields.append("static {} {}_;".format(field_type, cpp_name))
121 class_fields_inits.append(
122 "{} JS::Prefs::{}_{{{}}};".format(field_type, cpp_name, init_value)
125 is_startup_pref_bool = "true" if is_startup_pref else "false"
127 # Generate a MACRO invocation like this:
128 # MACRO("arraybuffer_transfer", arraybuffer_transfer, bool, setAtStartup_arraybuffer_transfer, true)
129 macro_entries.append(
130 'MACRO("{}", {}, {}, {}, {})'.format(
131 name, cpp_name, type, setter_name, is_startup_pref_bool
135 # Generate a C++ statement to set the JS pref based on Gecko's StaticPrefs:
136 # JS::Prefs::setAtStartup_foo(StaticPrefs::javascript_options_foo());
137 browser_pref_cpp_name = pref["name"].replace(".", "_").replace("-", "_")
138 if pref.get("do_not_use_directly", False):
139 browser_pref_cpp_name += "_DoNotUseDirectly"
141 statement = "JS::Prefs::{}(mozilla::StaticPrefs::{}());".format(
142 setter_name, browser_pref_cpp_name
144 browser_set_statements.append(statement)
146 # For non-startup prefs, also generate code to update the pref after startup.
147 if not is_startup_pref:
148 browser_set_non_startup_statements.append(statement)
150 contents = ""
152 contents += "#define JS_PREF_CLASS_FIELDS \\\n"
153 contents += "".join(map(lambda s: " {}\\\n".format(s), class_fields))
154 contents += "\n\n"
156 contents += "#define JS_PREF_CLASS_FIELDS_INIT \\\n"
157 contents += "".join(map(lambda s: " {}\\\n".format(s), class_fields_inits))
158 contents += "\n\n"
160 contents += "#define FOR_EACH_JS_PREF(MACRO) \\\n"
161 contents += "".join(map(lambda s: " {}\\\n".format(s), macro_entries))
162 contents += "\n\n"
164 contents += "#define SET_JS_PREFS_FROM_BROWSER_PREFS \\\n"
165 contents += "".join(map(lambda s: " {}\\\n".format(s), browser_set_statements))
166 contents += "\n\n"
168 contents += "#define SET_NON_STARTUP_JS_PREFS_FROM_BROWSER_PREFS \\\n"
169 contents += "".join(
170 map(lambda s: " {}\\\n".format(s), browser_set_non_startup_statements)
172 contents += "\n\n"
174 c_out.write(
175 HEADER_TEMPLATE
177 "contents": contents,