| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright (C) 2013 Google Inc. All rights reserved. | 3 # Copyright (C) 2013 Google Inc. All rights reserved. |
| 4 # | 4 # |
| 5 # Redistribution and use in source and binary forms, with or without | 5 # Redistribution and use in source and binary forms, with or without |
| 6 # modification, are permitted provided that the following conditions are | 6 # modification, are permitted provided that the following conditions are |
| 7 # met: | 7 # met: |
| 8 # | 8 # |
| 9 # * Redistributions of source code must retain the above copyright | 9 # * Redistributions of source code must retain the above copyright |
| 10 # notice, this list of conditions and the following disclaimer. | 10 # notice, this list of conditions and the following disclaimer. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | 30 |
| 31 import optparse | 31 import optparse |
| 32 import os | 32 import os |
| 33 import cPickle as pickle | |
| 34 import posixpath | 33 import posixpath |
| 35 import re | 34 |
| 36 import string | 35 from utilities import get_file_contents, write_file, write_pickle_file, get_inte
rface_extended_attributes_from_idl, is_callback_interface_from_idl, get_partial_
interface_name_from_idl, get_implemented_interfaces_from_idl, get_parent_interfa
ce, get_put_forward_interfaces_from_idl |
| 37 | 36 |
| 38 module_path = os.path.dirname(__file__) | 37 module_path = os.path.dirname(__file__) |
| 39 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) | 38 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) |
| 40 | 39 |
| 41 INHERITED_EXTENDED_ATTRIBUTES = set([ | 40 INHERITED_EXTENDED_ATTRIBUTES = set([ |
| 42 'ActiveDOMObject', | 41 'ActiveDOMObject', |
| 43 'DependentLifetime', | 42 'DependentLifetime', |
| 44 'WillBeGarbageCollected', | 43 'WillBeGarbageCollected', |
| 45 ]) | 44 ]) |
| 46 | 45 |
| 47 | 46 |
| 48 # interfaces_info is *exported* (in a pickle), and should only contain data | 47 # interfaces_info is *exported* (in a pickle), and should only contain data |
| 49 # about an interface that contains paths or is needed by *other* interfaces, | 48 # about an interface that contains paths or is needed by *other* interfaces, |
| 50 # i.e., file layout data (to abstract the compiler from file paths) or | 49 # i.e., file layout data (to abstract the compiler from file paths) or |
| 51 # public data (to avoid having to read other interfaces unnecessarily). | 50 # public data (to avoid having to read other interfaces unnecessarily). |
| 52 # It should *not* contain full information about an interface (e.g., all | 51 # It should *not* contain full information about an interface (e.g., all |
| 53 # extended attributes), as this would cause unnecessary rebuilds. | 52 # extended attributes), as this would cause unnecessary rebuilds. |
| 54 interfaces_info = {} | 53 interfaces_info = {} |
| 55 | 54 |
| 56 # Auxiliary variables (not visible to future build steps) | 55 # Auxiliary variables (not visible to future build steps) |
| 57 partial_interface_files = {} | 56 partial_interface_files = {} |
| 58 parent_interfaces = {} | 57 parent_interfaces = {} |
| 59 extended_attributes_by_interface = {} # interface name -> extended attributes | 58 extended_attributes_by_interface = {} # interface name -> extended attributes |
| 60 | 59 |
| 61 | 60 |
| 62 class IdlBadFilenameError(Exception): | |
| 63 """Raised if an IDL filename disagrees with the interface name in the file."
"" | |
| 64 pass | |
| 65 | |
| 66 | |
| 67 class IdlInterfaceFileNotFoundError(Exception): | 61 class IdlInterfaceFileNotFoundError(Exception): |
| 68 """Raised if the IDL file implementing an interface cannot be found.""" | 62 """Raised if the IDL file implementing an interface cannot be found.""" |
| 69 pass | 63 pass |
| 70 | 64 |
| 71 | 65 |
| 72 def parse_options(): | 66 def parse_options(): |
| 73 usage = 'Usage: %prog [options] [generated1.idl]...' | 67 usage = 'Usage: %prog [options] [generated1.idl]...' |
| 74 parser = optparse.OptionParser(usage=usage) | 68 parser = optparse.OptionParser(usage=usage) |
| 75 parser.add_option('--event-names-file', help='output file') | 69 parser.add_option('--event-names-file', help='output file') |
| 76 parser.add_option('--idl-files-list', help='file listing IDL files') | 70 parser.add_option('--idl-files-list', help='file listing IDL files') |
| 77 parser.add_option('--interface-dependencies-file', help='output file') | 71 parser.add_option('--interface-dependencies-file', help='output file') |
| 78 parser.add_option('--interfaces-info-file', help='output pickle file') | 72 parser.add_option('--interfaces-info-file', help='output pickle file') |
| 79 parser.add_option('--window-constructors-file', help='output file') | |
| 80 parser.add_option('--workerglobalscope-constructors-file', help='output file
') | |
| 81 parser.add_option('--sharedworkerglobalscope-constructors-file', help='outpu
t file') | |
| 82 parser.add_option('--dedicatedworkerglobalscope-constructors-file', help='ou
tput file') | |
| 83 parser.add_option('--serviceworkerglobalscope-constructors-file', help='outp
ut file') | |
| 84 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') | 73 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') |
| 85 options, args = parser.parse_args() | 74 options, args = parser.parse_args() |
| 86 if options.event_names_file is None: | 75 if options.event_names_file is None: |
| 87 parser.error('Must specify an output file using --event-names-file.') | 76 parser.error('Must specify an output file using --event-names-file.') |
| 88 if options.interface_dependencies_file is None: | 77 if options.interface_dependencies_file is None: |
| 89 parser.error('Must specify an output file using --interface-dependencies
-file.') | 78 parser.error('Must specify an output file using --interface-dependencies
-file.') |
| 90 if options.interfaces_info_file is None: | 79 if options.interfaces_info_file is None: |
| 91 parser.error('Must specify an output file using --interfaces-info-file.'
) | 80 parser.error('Must specify an output file using --interfaces-info-file.'
) |
| 92 if options.window_constructors_file is None: | |
| 93 parser.error('Must specify an output file using --window-constructors-fi
le.') | |
| 94 if options.workerglobalscope_constructors_file is None: | |
| 95 parser.error('Must specify an output file using --workerglobalscope-cons
tructors-file.') | |
| 96 if options.sharedworkerglobalscope_constructors_file is None: | |
| 97 parser.error('Must specify an output file using --sharedworkerglobalscop
e-constructors-file.') | |
| 98 if options.dedicatedworkerglobalscope_constructors_file is None: | |
| 99 parser.error('Must specify an output file using --dedicatedworkerglobals
cope-constructors-file.') | |
| 100 if options.serviceworkerglobalscope_constructors_file is None: | |
| 101 parser.error('Must specify an output file using --serviceworkerglobalsco
pe-constructors-file.') | |
| 102 if options.idl_files_list is None: | 81 if options.idl_files_list is None: |
| 103 parser.error('Must specify a file listing IDL files using --idl-files-li
st.') | 82 parser.error('Must specify a file listing IDL files using --idl-files-li
st.') |
| 104 if options.write_file_only_if_changed is None: | 83 if options.write_file_only_if_changed is None: |
| 105 parser.error('Must specify whether file is only written if changed using
--write-file-only-if-changed.') | 84 parser.error('Must specify whether file is only written if changed using
--write-file-only-if-changed.') |
| 106 options.write_file_only_if_changed = bool(options.write_file_only_if_changed
) | 85 options.write_file_only_if_changed = bool(options.write_file_only_if_changed
) |
| 107 return options, args | 86 return options, args |
| 108 | 87 |
| 109 | 88 |
| 110 ################################################################################ | 89 ################################################################################ |
| 111 # Basic file reading/writing | |
| 112 ################################################################################ | |
| 113 | |
| 114 def get_file_contents(idl_filename): | |
| 115 with open(idl_filename) as idl_file: | |
| 116 lines = idl_file.readlines() | |
| 117 return ''.join(lines) | |
| 118 | |
| 119 | |
| 120 def write_file(new_lines, destination_filename, only_if_changed): | |
| 121 if only_if_changed and os.path.isfile(destination_filename): | |
| 122 with open(destination_filename) as destination_file: | |
| 123 if destination_file.readlines() == new_lines: | |
| 124 return | |
| 125 with open(destination_filename, 'w') as destination_file: | |
| 126 destination_file.write(''.join(new_lines)) | |
| 127 | |
| 128 | |
| 129 def write_pickle_file(pickle_filename, data, only_if_changed): | |
| 130 if only_if_changed and os.path.isfile(pickle_filename): | |
| 131 with open(pickle_filename) as pickle_file: | |
| 132 if pickle.load(pickle_file) == data: | |
| 133 return | |
| 134 with open(pickle_filename, 'w') as pickle_file: | |
| 135 pickle.dump(data, pickle_file) | |
| 136 | |
| 137 | |
| 138 ################################################################################ | |
| 139 # IDL parsing | |
| 140 # | |
| 141 # We use regular expressions for parsing; this is incorrect (Web IDL is not a | |
| 142 # regular language), but simple and sufficient in practice. | |
| 143 # Leading and trailing context (e.g. following '{') used to avoid false matches. | |
| 144 ################################################################################ | |
| 145 | |
| 146 def get_partial_interface_name_from_idl(file_contents): | |
| 147 match = re.search(r'partial\s+interface\s+(\w+)\s*{', file_contents) | |
| 148 return match and match.group(1) | |
| 149 | |
| 150 | |
| 151 # identifier-A implements identifier-B; | |
| 152 # http://www.w3.org/TR/WebIDL/#idl-implements-statements | |
| 153 def get_implemented_interfaces_from_idl(file_contents, interface_name): | |
| 154 def get_implemented(left_identifier, right_identifier): | |
| 155 # identifier-A must be the current interface | |
| 156 if left_identifier != interface_name: | |
| 157 raise IdlBadFilenameError("Identifier on the left of the 'implements
' statement should be %s in %s.idl, but found %s" % (interface_name, interface_n
ame, left_identifier)) | |
| 158 return right_identifier | |
| 159 | |
| 160 implements_re = (r'^\s*' | |
| 161 r'(\w+)\s+' | |
| 162 r'implements\s+' | |
| 163 r'(\w+)\s*' | |
| 164 r';') | |
| 165 implements_matches = re.finditer(implements_re, file_contents, re.MULTILINE) | |
| 166 implements_pairs = [(match.group(1), match.group(2)) | |
| 167 for match in implements_matches] | |
| 168 return [get_implemented(left, right) for left, right in implements_pairs] | |
| 169 | |
| 170 | |
| 171 def is_callback_interface_from_idl(file_contents): | |
| 172 match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents) | |
| 173 return bool(match) | |
| 174 | |
| 175 | |
| 176 def get_parent_interface(file_contents): | |
| 177 match = re.search(r'interface\s+' | |
| 178 r'\w+\s*' | |
| 179 r':\s*(\w+)\s*' | |
| 180 r'{', | |
| 181 file_contents) | |
| 182 return match and match.group(1) | |
| 183 | |
| 184 | |
| 185 def get_interface_extended_attributes_from_idl(file_contents): | |
| 186 match = re.search(r'\[(.*)\]\s*' | |
| 187 r'((callback|partial)\s+)?' | |
| 188 r'(interface|exception)\s+' | |
| 189 r'\w+\s*' | |
| 190 r'(:\s*\w+\s*)?' | |
| 191 r'{', | |
| 192 file_contents, flags=re.DOTALL) | |
| 193 if not match: | |
| 194 return {} | |
| 195 # Strip comments | |
| 196 # re.compile needed b/c Python 2.6 doesn't support flags in re.sub | |
| 197 single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE) | |
| 198 block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL) | |
| 199 extended_attributes_string = re.sub(single_line_comment_re, '', match.group(
1)) | |
| 200 extended_attributes_string = re.sub(block_comment_re, '', extended_attribute
s_string) | |
| 201 extended_attributes = {} | |
| 202 # FIXME: this splitting is WRONG: it fails on ExtendedAttributeArgList like | |
| 203 # 'NamedConstructor=Foo(a, b)' | |
| 204 parts = [extended_attribute.strip() | |
| 205 for extended_attribute in extended_attributes_string.split(',') | |
| 206 # Discard empty parts, which may exist due to trailing comma | |
| 207 if extended_attribute.strip()] | |
| 208 for part in parts: | |
| 209 name, _, value = map(string.strip, part.partition('=')) | |
| 210 extended_attributes[name] = value | |
| 211 return extended_attributes | |
| 212 | |
| 213 | |
| 214 def get_put_forward_interfaces_from_idl(file_contents): | |
| 215 put_forwards_pattern = (r'\[[^\]]*PutForwards=[^\]]*\]\s+' | |
| 216 r'readonly\s+' | |
| 217 r'attribute\s+' | |
| 218 r'(\w+)') | |
| 219 return sorted(set(match.group(1) | |
| 220 for match in re.finditer(put_forwards_pattern, | |
| 221 file_contents, | |
| 222 flags=re.DOTALL))) | |
| 223 | |
| 224 | |
| 225 ################################################################################ | |
| 226 # Write files | 90 # Write files |
| 227 ################################################################################ | 91 ################################################################################ |
| 228 | 92 |
| 229 def write_dependencies_file(dependencies_filename, only_if_changed): | 93 def write_dependencies_file(dependencies_filename, only_if_changed): |
| 230 """Write the interface dependencies file. | 94 """Write the interface dependencies file. |
| 231 | 95 |
| 232 The format is as follows: | 96 The format is as follows: |
| 233 | 97 |
| 234 Document.idl P.idl | 98 Document.idl P.idl |
| 235 Event.idl | 99 Event.idl |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 refined_filename, _ = os.path.splitext(os.path.relpath(filename, source_
dir)) | 145 refined_filename, _ = os.path.splitext(os.path.relpath(filename, source_
dir)) |
| 282 refined_filename = refined_filename.replace(os.sep, posixpath.sep) | 146 refined_filename = refined_filename.replace(os.sep, posixpath.sep) |
| 283 extended_attributes_list = [ | 147 extended_attributes_list = [ |
| 284 extended_attribute_string(name) | 148 extended_attribute_string(name) |
| 285 for name in 'Conditional', 'ImplementedAs', 'RuntimeEnabled' | 149 for name in 'Conditional', 'ImplementedAs', 'RuntimeEnabled' |
| 286 if name in extended_attributes] | 150 if name in extended_attributes] |
| 287 lines.append('%s %s\n' % (refined_filename, ', '.join(extended_attribute
s_list))) | 151 lines.append('%s %s\n' % (refined_filename, ', '.join(extended_attribute
s_list))) |
| 288 write_file(lines, destination_filename, only_if_changed) | 152 write_file(lines, destination_filename, only_if_changed) |
| 289 | 153 |
| 290 | 154 |
| 291 def write_global_constructors_partial_interface(interface_name, destination_file
name, constructor_attributes_list, only_if_changed): | |
| 292 lines = (['partial interface %s {\n' % interface_name] + | |
| 293 [' %s;\n' % constructor_attribute | |
| 294 for constructor_attribute in sorted(constructor_attributes_list)]
+ | |
| 295 ['};\n']) | |
| 296 write_file(lines, destination_filename, only_if_changed) | |
| 297 | |
| 298 | |
| 299 ################################################################################ | 155 ################################################################################ |
| 300 # Dependency resolution | 156 # Dependency resolution |
| 301 ################################################################################ | 157 ################################################################################ |
| 302 | 158 |
| 303 def include_path(idl_filename, implemented_as=None): | 159 def include_path(idl_filename, implemented_as=None): |
| 304 """Returns relative path to header file in POSIX format; used in includes. | 160 """Returns relative path to header file in POSIX format; used in includes. |
| 305 | 161 |
| 306 POSIX format is used for consistency of output, so reference tests are | 162 POSIX format is used for consistency of output, so reference tests are |
| 307 platform-independent. | 163 platform-independent. |
| 308 """ | 164 """ |
| (...skipping 24 matching lines...) Expand all Loading... |
| 333 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) | 189 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) |
| 334 implemented_as = extended_attributes.get('ImplementedAs') | 190 implemented_as = extended_attributes.get('ImplementedAs') |
| 335 # FIXME: remove [NoHeader] once switch to Python | 191 # FIXME: remove [NoHeader] once switch to Python |
| 336 this_include_path = (include_path(idl_filename, implemented_as) | 192 this_include_path = (include_path(idl_filename, implemented_as) |
| 337 if 'NoHeader' not in extended_attributes else None) | 193 if 'NoHeader' not in extended_attributes else None) |
| 338 | 194 |
| 339 # Handle partial interfaces | 195 # Handle partial interfaces |
| 340 partial_interface_name = get_partial_interface_name_from_idl(idl_file_conten
ts) | 196 partial_interface_name = get_partial_interface_name_from_idl(idl_file_conten
ts) |
| 341 if partial_interface_name: | 197 if partial_interface_name: |
| 342 add_paths_to_partials_dict(partial_interface_name, full_path, this_inclu
de_path) | 198 add_paths_to_partials_dict(partial_interface_name, full_path, this_inclu
de_path) |
| 343 return False | 199 return |
| 344 | 200 |
| 345 # If not a partial interface, the basename is the interface name | 201 # If not a partial interface, the basename is the interface name |
| 346 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) | 202 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) |
| 347 | 203 |
| 348 interfaces_info[interface_name] = { | 204 interfaces_info[interface_name] = { |
| 349 'full_path': full_path, | 205 'full_path': full_path, |
| 350 'implements_interfaces': get_implemented_interfaces_from_idl(idl_file_co
ntents, interface_name), | 206 'implements_interfaces': get_implemented_interfaces_from_idl(idl_file_co
ntents, interface_name), |
| 351 'is_callback_interface': is_callback_interface_from_idl(idl_file_content
s), | 207 'is_callback_interface': is_callback_interface_from_idl(idl_file_content
s), |
| 352 # Interfaces that are referenced (used as types) and that we introspect | 208 # Interfaces that are referenced (used as types) and that we introspect |
| 353 # during code generation (beyond interface-level data ([ImplementedAs], | 209 # during code generation (beyond interface-level data ([ImplementedAs], |
| 354 # is_callback_interface, ancestors, and inherited extended attributes): | 210 # is_callback_interface, ancestors, and inherited extended attributes): |
| 355 # deep dependencies. | 211 # deep dependencies. |
| 356 # These cause rebuilds of referrers, due to the dependency, so these | 212 # These cause rebuilds of referrers, due to the dependency, so these |
| 357 # should be minimized; currently only targets of [PutForwards]. | 213 # should be minimized; currently only targets of [PutForwards]. |
| 358 'referenced_interfaces': get_put_forward_interfaces_from_idl(idl_file_co
ntents), | 214 'referenced_interfaces': get_put_forward_interfaces_from_idl(idl_file_co
ntents), |
| 359 } | 215 } |
| 360 if this_include_path: | 216 if this_include_path: |
| 361 interfaces_info[interface_name]['include_path'] = this_include_path | 217 interfaces_info[interface_name]['include_path'] = this_include_path |
| 362 if implemented_as: | 218 if implemented_as: |
| 363 interfaces_info[interface_name]['implemented_as'] = implemented_as | 219 interfaces_info[interface_name]['implemented_as'] = implemented_as |
| 364 | 220 |
| 365 return True | |
| 366 | |
| 367 | |
| 368 def generate_constructor_attribute_list(interface_name, extended_attributes): | |
| 369 extended_attributes_list = [ | |
| 370 name + '=' + extended_attributes[name] | |
| 371 for name in 'Conditional', 'PerContextEnabled', 'RuntimeEnabled' | |
| 372 if name in extended_attributes] | |
| 373 if extended_attributes_list: | |
| 374 extended_string = '[%s] ' % ', '.join(extended_attributes_list) | |
| 375 else: | |
| 376 extended_string = '' | |
| 377 | |
| 378 attribute_string = 'attribute {interface_name}Constructor {interface_name}'.
format(interface_name=interface_name) | |
| 379 attributes_list = [extended_string + attribute_string] | |
| 380 | |
| 381 # In addition to the regular property, for every [NamedConstructor] | |
| 382 # extended attribute on an interface, a corresponding property MUST exist | |
| 383 # on the ECMAScript global object. | |
| 384 if 'NamedConstructor' in extended_attributes: | |
| 385 named_constructor = extended_attributes['NamedConstructor'] | |
| 386 # Extract function name, namely everything before opening '(' | |
| 387 constructor_name = re.sub(r'\(.*', '', named_constructor) | |
| 388 # Note the reduplicated 'ConstructorConstructor' | |
| 389 attribute_string = 'attribute %sConstructorConstructor %s' % (interface_
name, constructor_name) | |
| 390 attributes_list.append(extended_string + attribute_string) | |
| 391 | |
| 392 return attributes_list | |
| 393 | |
| 394 | |
| 395 def record_global_constructors_and_extended_attributes(idl_filename, global_cons
tructors): | |
| 396 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) | |
| 397 full_path = os.path.realpath(idl_filename) | |
| 398 idl_file_contents = get_file_contents(full_path) | |
| 399 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) | |
| 400 | |
| 401 # Record extended attributes | 221 # Record extended attributes |
| 402 extended_attributes_by_interface[interface_name] = extended_attributes | 222 extended_attributes_by_interface[interface_name] = extended_attributes |
| 403 | 223 |
| 404 # Record global constructors | |
| 405 if (not is_callback_interface_from_idl(idl_file_contents) and | |
| 406 'NoInterfaceObject' not in extended_attributes): | |
| 407 global_contexts = extended_attributes.get('GlobalContext', 'Window').spl
it('&') | |
| 408 new_constructor_list = generate_constructor_attribute_list(interface_nam
e, extended_attributes) | |
| 409 for global_object in global_contexts: | |
| 410 global_constructors[global_object].extend(new_constructor_list) | |
| 411 | |
| 412 # Record parents | 224 # Record parents |
| 413 parent = get_parent_interface(idl_file_contents) | 225 parent = get_parent_interface(idl_file_contents) |
| 414 if parent: | 226 if parent: |
| 415 parent_interfaces[interface_name] = parent | 227 parent_interfaces[interface_name] = parent |
| 416 | 228 |
| 417 | 229 |
| 418 def record_extended_attributes(idl_filename): | |
| 419 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) | |
| 420 full_path = os.path.realpath(idl_filename) | |
| 421 idl_file_contents = get_file_contents(full_path) | |
| 422 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) | |
| 423 extended_attributes_by_interface[interface_name] = extended_attributes | |
| 424 | |
| 425 | |
| 426 def generate_ancestors_and_inherited_extended_attributes(interface_name): | 230 def generate_ancestors_and_inherited_extended_attributes(interface_name): |
| 427 interface_info = interfaces_info[interface_name] | 231 interface_info = interfaces_info[interface_name] |
| 428 interface_extended_attributes = extended_attributes_by_interface[interface_n
ame] | 232 interface_extended_attributes = extended_attributes_by_interface[interface_n
ame] |
| 429 inherited_extended_attributes = dict( | 233 inherited_extended_attributes = dict( |
| 430 (key, value) | 234 (key, value) |
| 431 for key, value in interface_extended_attributes.iteritems() | 235 for key, value in interface_extended_attributes.iteritems() |
| 432 if key in INHERITED_EXTENDED_ATTRIBUTES) | 236 if key in INHERITED_EXTENDED_ATTRIBUTES) |
| 433 | 237 |
| 434 def generate_ancestors(interface_name): | 238 def generate_ancestors(interface_name): |
| 435 while interface_name in parent_interfaces: | 239 while interface_name in parent_interfaces: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 449 # IDL files, or generated support files. | 253 # IDL files, or generated support files. |
| 450 ancestor_extended_attributes = extended_attributes_by_interface.get(ance
stor, {}) | 254 ancestor_extended_attributes = extended_attributes_by_interface.get(ance
stor, {}) |
| 451 inherited_extended_attributes.update(dict( | 255 inherited_extended_attributes.update(dict( |
| 452 (key, value) | 256 (key, value) |
| 453 for key, value in ancestor_extended_attributes.iteritems() | 257 for key, value in ancestor_extended_attributes.iteritems() |
| 454 if key in INHERITED_EXTENDED_ATTRIBUTES)) | 258 if key in INHERITED_EXTENDED_ATTRIBUTES)) |
| 455 if inherited_extended_attributes: | 259 if inherited_extended_attributes: |
| 456 interface_info['inherited_extended_attributes'] = inherited_extended_att
ributes | 260 interface_info['inherited_extended_attributes'] = inherited_extended_att
ributes |
| 457 | 261 |
| 458 | 262 |
| 459 def parse_idl_files(idl_files, global_constructors_filenames): | 263 def parse_idl_files(idl_files): |
| 460 """Compute dependencies between IDL files, and return constructors on global
objects. | 264 """Compute information about IDL files. |
| 461 | 265 |
| 462 Primary effect is computing info about main interfaces, stored in global | 266 Primary effect is computing info about main interfaces, stored in global |
| 463 interfaces_info. | 267 interfaces_info. |
| 464 The keys are the interfaces for which bindings are generated; | |
| 465 this does not include interfaces implemented by another interface. | |
| 466 | |
| 467 Returns: | |
| 468 global_constructors: | |
| 469 dict of global objects -> list of constructors on that object | |
| 470 """ | 268 """ |
| 471 global_constructors = dict([ | 269 # Generate dependencies. |
| 472 (global_object, []) | |
| 473 for global_object in global_constructors_filenames]) | |
| 474 | |
| 475 # Generate dependencies, and (for main IDL files), record | |
| 476 # global_constructors and extended_attributes_by_interface. | |
| 477 for idl_filename in idl_files: | 270 for idl_filename in idl_files: |
| 478 # Test skips partial interfaces | 271 generate_dependencies(idl_filename) |
| 479 if generate_dependencies(idl_filename): | |
| 480 record_global_constructors_and_extended_attributes(idl_filename, glo
bal_constructors) | |
| 481 | 272 |
| 482 for interface_name in interfaces_info: | 273 for interface_name in interfaces_info: |
| 483 generate_ancestors_and_inherited_extended_attributes(interface_name) | 274 generate_ancestors_and_inherited_extended_attributes(interface_name) |
| 484 | 275 |
| 485 # Add constructors on global objects to partial interfaces | |
| 486 # These are all partial interfaces, but the files are dynamically generated, | |
| 487 # so they need to be handled separately from static partial interfaces. | |
| 488 for global_object, constructor_filename in global_constructors_filenames.ite
ritems(): | |
| 489 if global_object in interfaces_info: | |
| 490 # No include path needed, as already included in the header file | |
| 491 add_paths_to_partials_dict(global_object, constructor_filename) | |
| 492 | |
| 493 # An IDL file's dependencies are partial interface files that extend it, | 276 # An IDL file's dependencies are partial interface files that extend it, |
| 494 # and files for other interfaces that this interfaces implements. | 277 # and files for other interfaces that this interfaces implements. |
| 495 for interface_name, interface_info in interfaces_info.iteritems(): | 278 for interface_name, interface_info in interfaces_info.iteritems(): |
| 496 partial_interfaces_full_paths, partial_interfaces_include_paths = ( | 279 partial_interfaces_full_paths, partial_interfaces_include_paths = ( |
| 497 (partial_interface_files[interface_name]['full_paths'], | 280 (partial_interface_files[interface_name]['full_paths'], |
| 498 partial_interface_files[interface_name]['include_paths']) | 281 partial_interface_files[interface_name]['include_paths']) |
| 499 if interface_name in partial_interface_files else ([], [])) | 282 if interface_name in partial_interface_files else ([], [])) |
| 500 | 283 |
| 501 implemented_interfaces = interface_info['implements_interfaces'] | 284 implemented_interfaces = interface_info['implements_interfaces'] |
| 502 try: | 285 try: |
| 503 implemented_interfaces_full_paths = [ | 286 implemented_interfaces_full_paths = [ |
| 504 interfaces_info[interface]['full_path'] | 287 interfaces_info[interface]['full_path'] |
| 505 for interface in implemented_interfaces] | 288 for interface in implemented_interfaces] |
| 506 implemented_interfaces_include_paths = [ | 289 implemented_interfaces_include_paths = [ |
| 507 interfaces_info[interface]['include_path'] | 290 interfaces_info[interface]['include_path'] |
| 508 for interface in implemented_interfaces | 291 for interface in implemented_interfaces |
| 509 if 'include_path' in interfaces_info[interface]] | 292 if 'include_path' in interfaces_info[interface]] |
| 510 except KeyError as key_name: | 293 except KeyError as key_name: |
| 511 raise IdlInterfaceFileNotFoundError('Could not find the IDL file whe
re the following implemented interface is defined: %s' % key_name) | 294 raise IdlInterfaceFileNotFoundError('Could not find the IDL file whe
re the following implemented interface is defined: %s' % key_name) |
| 512 | 295 |
| 513 interface_info['dependencies_full_paths'] = ( | 296 interface_info['dependencies_full_paths'] = ( |
| 514 partial_interfaces_full_paths + | 297 partial_interfaces_full_paths + |
| 515 implemented_interfaces_full_paths) | 298 implemented_interfaces_full_paths) |
| 516 interface_info['dependencies_include_paths'] = ( | 299 interface_info['dependencies_include_paths'] = ( |
| 517 partial_interfaces_include_paths + | 300 partial_interfaces_include_paths + |
| 518 implemented_interfaces_include_paths) | 301 implemented_interfaces_include_paths) |
| 519 | 302 |
| 520 return global_constructors | |
| 521 | |
| 522 | 303 |
| 523 ################################################################################ | 304 ################################################################################ |
| 524 | 305 |
| 525 def main(): | 306 def main(): |
| 526 options, args = parse_options() | 307 options, args = parse_options() |
| 527 | 308 |
| 528 # Static IDL files are passed in a file (generated at GYP time), due to OS | 309 # Static IDL files are passed in a file (generated at GYP time), due to OS |
| 529 # command line length limits | 310 # command line length limits |
| 530 with open(options.idl_files_list) as idl_files_list: | 311 with open(options.idl_files_list) as idl_files_list: |
| 531 idl_files = [line.rstrip('\n') for line in idl_files_list] | 312 idl_files = [line.rstrip('\n') for line in idl_files_list] |
| 532 # Generated IDL files are passed at the command line, since these are in the | 313 # Generated IDL files are passed at the command line, since these are in the |
| 533 # build directory, which is determined at build time, not GYP time, so these | 314 # build directory, which is determined at build time, not GYP time, so these |
| 534 # cannot be included in the file listing static files | 315 # cannot be included in the file listing static files |
| 535 idl_files.extend(args) | 316 idl_files.extend(args) |
| 536 | 317 |
| 537 only_if_changed = options.write_file_only_if_changed | 318 only_if_changed = options.write_file_only_if_changed |
| 538 global_constructors_filenames = { | |
| 539 'Window': options.window_constructors_file, | |
| 540 'WorkerGlobalScope': options.workerglobalscope_constructors_file, | |
| 541 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_
file, | |
| 542 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru
ctors_file, | |
| 543 'ServiceWorkerGlobalScope': options.serviceworkerglobalscope_constructor
s_file, | |
| 544 } | |
| 545 | 319 |
| 546 global_constructors = parse_idl_files(idl_files, global_constructors_filenam
es) | 320 parse_idl_files(idl_files) |
| 547 | 321 write_pickle_file(options.interfaces_info_file, interfaces_info, only_if_cha
nged) |
| 548 write_dependencies_file(options.interface_dependencies_file, only_if_changed
) | 322 write_dependencies_file(options.interface_dependencies_file, only_if_changed
) |
| 549 write_pickle_file(options.interfaces_info_file, interfaces_info, only_if_cha
nged) | |
| 550 for interface_name, filename in global_constructors_filenames.iteritems(): | |
| 551 if interface_name in interfaces_info: | |
| 552 write_global_constructors_partial_interface(interface_name, filename
, global_constructors[interface_name], only_if_changed) | |
| 553 write_event_names_file(options.event_names_file, only_if_changed) | 323 write_event_names_file(options.event_names_file, only_if_changed) |
| 554 | 324 |
| 555 | 325 |
| 556 if __name__ == '__main__': | 326 if __name__ == '__main__': |
| 557 main() | 327 main() |
| OLD | NEW |