Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: bindings/scripts/generate_global_constructors.py

Issue 540533002: Roll IDL to Dartium37 (r181268) (Closed) Base URL: https://dart.googlecode.com/svn/third_party/WebCore
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « bindings/scripts/generate_event_interfaces.py ('k') | bindings/scripts/idl_compiler.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 #
3 # Copyright 2014 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7 """Generates interface properties on global objects.
8
9 Concretely these are implemented as "constructor attributes", meaning
10 "attributes whose name ends with Constructor" (special-cased by code generator),
11 hence "global constructors" for short.
12
13 For reference on global objects, see:
14 http://heycam.github.io/webidl/#Global
15 http://heycam.github.io/webidl/#Exposed
16
17 Design document: http://www.chromium.org/developers/design-documents/idl-build
18 """
19
20 import itertools
21 import optparse
22 import os
23 import cPickle as pickle
24 import re
25 import sys
26
27 from collections import defaultdict
28 from utilities import get_file_contents, idl_filename_to_interface_name, read_fi le_to_list, write_file, get_interface_extended_attributes_from_idl, is_callback_ interface_from_idl
29
30 interface_name_to_global_names = {}
31 global_name_to_constructors = defaultdict(list)
32
33
34 HEADER_FORMAT = """// Stub header file for {{idl_basename}}
35 // Required because the IDL compiler assumes that a corresponding header file
36 // exists for each IDL file.
37 """
38
39 def parse_options():
40 parser = optparse.OptionParser()
41 parser.add_option('--idl-files-list', help='file listing IDL files')
42 parser.add_option('--global-objects-file', help='pickle file of global objec ts')
43 parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
44
45 options, args = parser.parse_args()
46
47 if options.idl_files_list is None:
48 parser.error('Must specify a file listing IDL files using --idl-files-li st.')
49 if options.global_objects_file is None:
50 parser.error('Must specify a pickle file of global objects using --globa l-objects-file.')
51 if options.write_file_only_if_changed is None:
52 parser.error('Must specify whether output files are only written if chan ged using --write-file-only-if-changed.')
53 options.write_file_only_if_changed = bool(options.write_file_only_if_changed )
54
55 return options, args
56
57
58 def flatten_list(iterable):
59 return list(itertools.chain.from_iterable(iterable))
60
61
62 def interface_name_to_constructors(interface_name):
63 """Returns constructors for an interface."""
64 global_names = interface_name_to_global_names[interface_name]
65 return flatten_list(global_name_to_constructors[global_name]
66 for global_name in global_names)
67
68
69 def record_global_constructors(idl_filename):
70 interface_name = idl_filename_to_interface_name(idl_filename)
71 full_path = os.path.realpath(idl_filename)
72 idl_file_contents = get_file_contents(full_path)
73 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co ntents)
74
75 # An interface property is produced for every non-callback interface
76 # that does not have [NoInterfaceObject].
77 # Callback interfaces with constants also have interface properties,
78 # but there are none of these in Blink.
79 # http://heycam.github.io/webidl/#es-interfaces
80 if (is_callback_interface_from_idl(idl_file_contents) or
81 'NoInterfaceObject' in extended_attributes):
82 return
83
84 # The [Exposed] extended attribute MUST take an identifier list. Each
85 # identifier in the list MUST be a global name. An interface or interface
86 # member the extended attribute applies to will be exposed only on objects
87 # associated with ECMAScript global environments whose global object
88 # implements an interface that has a matching global name.
89 # FIXME: In spec names are comma-separated, but that makes parsing very
90 # difficult (https://www.w3.org/Bugs/Public/show_bug.cgi?id=24959).
91 exposed_global_names = extended_attributes.get('Exposed', 'Window').split('& ')
92 new_constructors_list = generate_global_constructors_list(interface_name, ex tended_attributes)
93 for exposed_global_name in exposed_global_names:
94 global_name_to_constructors[exposed_global_name].extend(new_constructors _list)
95
96
97 def generate_global_constructors_list(interface_name, extended_attributes):
98 extended_attributes_list = [
99 name + '=' + extended_attributes[name]
100 for name in 'Conditional', 'PerContextEnabled', 'RuntimeEnabled'
101 if name in extended_attributes]
102 if extended_attributes_list:
103 extended_string = '[%s] ' % ', '.join(extended_attributes_list)
104 else:
105 extended_string = ''
106
107 attribute_string = 'attribute {interface_name}Constructor {interface_name}'. format(interface_name=interface_name)
108 attributes_list = [extended_string + attribute_string]
109
110 # In addition to the usual interface property, for every [NamedConstructor]
111 # extended attribute on an interface, a corresponding property MUST exist
112 # on the ECMAScript global object.
113 # http://heycam.github.io/webidl/#NamedConstructor
114 if 'NamedConstructor' in extended_attributes:
115 named_constructor = extended_attributes['NamedConstructor']
116 # Extract function name, namely everything before opening '('
117 constructor_name = re.sub(r'\(.*', '', named_constructor)
118 # Note the reduplicated 'ConstructorConstructor'
119 # FIXME: rename to NamedConstructor
120 attribute_string = 'attribute %sConstructorConstructor %s' % (interface_ name, constructor_name)
121 attributes_list.append(extended_string + attribute_string)
122
123 return attributes_list
124
125
126 def write_global_constructors_partial_interface(interface_name, idl_filename, co nstructor_attributes_list, only_if_changed):
127 # FIXME: replace this with a simple Jinja template
128 lines = (['partial interface %s {\n' % interface_name] +
129 [' %s;\n' % constructor_attribute
130 # FIXME: sort by interface name (not first by extended attributes)
131 for constructor_attribute in sorted(constructor_attributes_list)] +
132 ['};\n'])
133 write_file(''.join(lines), idl_filename, only_if_changed)
134 header_filename = os.path.splitext(idl_filename)[0] + '.h'
135 idl_basename = os.path.basename(idl_filename)
136 write_file(HEADER_FORMAT.format(idl_basename=idl_basename),
137 header_filename, only_if_changed)
138
139
140 ################################################################################
141
142 def main():
143 options, args = parse_options()
144
145 # Input IDL files are passed in a file, due to OS command line length
146 # limits. This is generated at GYP time, which is ok b/c files are static.
147 idl_files = read_file_to_list(options.idl_files_list)
148
149 # Output IDL files (to generate) are passed at the command line, since
150 # these are in the build directory, which is determined at build time, not
151 # GYP time.
152 # These are passed as pairs of GlobalObjectName, GlobalObject.idl
153 interface_name_idl_filename = [(args[i], args[i + 1])
154 for i in range(0, len(args), 2)]
155
156 with open(options.global_objects_file) as global_objects_file:
157 interface_name_to_global_names.update(pickle.load(global_objects_file))
158
159 for idl_filename in idl_files:
160 record_global_constructors(idl_filename)
161
162 # Check for [Exposed] / [Global] mismatch.
163 known_global_names = frozenset(itertools.chain.from_iterable(interface_name_ to_global_names.values()))
164 exposed_global_names = frozenset(global_name_to_constructors)
165 if not exposed_global_names.issubset(known_global_names):
166 unknown_global_names = exposed_global_names.difference(known_global_name s)
167 raise ValueError('The following global names were used in '
168 '[Exposed=xxx] but do not match any [Global] / '
169 '[PrimaryGlobal] interface: %s'
170 % list(unknown_global_names))
171
172 # Write partial interfaces containing constructor attributes for each
173 # global interface.
174 for interface_name, idl_filename in interface_name_idl_filename:
175 constructors = interface_name_to_constructors(interface_name)
176 write_global_constructors_partial_interface(
177 interface_name,
178 idl_filename,
179 constructors,
180 options.write_file_only_if_changed)
181
182
183 if __name__ == '__main__':
184 sys.exit(main())
OLDNEW
« no previous file with comments | « bindings/scripts/generate_event_interfaces.py ('k') | bindings/scripts/idl_compiler.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698