OLD | NEW |
1 # Copyright (C) 2013 Google Inc. All rights reserved. | 1 # Copyright (C) 2013 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
5 # met: | 5 # met: |
6 # | 6 # |
7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
(...skipping 10 matching lines...) Expand all Loading... |
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | 28 |
29 """Functions shared by various parts of the code generator. | 29 """Functions shared by various parts of the code generator. |
30 | 30 |
31 Extends IdlTypeBase type with |enum_validation_expression| property. | |
32 | |
33 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler | 31 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler |
34 """ | 32 """ |
35 | 33 |
36 import re | 34 import re |
37 | 35 |
38 from idl_types import IdlTypeBase | 36 from idl_types import IdlTypeBase |
39 import idl_types | 37 import idl_types |
| 38 from idl_definitions import Exposure, IdlInterface |
40 from v8_globals import includes | 39 from v8_globals import includes |
41 import v8_types | |
42 | 40 |
43 ACRONYMS = [ | 41 ACRONYMS = [ |
44 'CSSOM', # must come *before* CSS to match full acronym | 42 'CSSOM', # must come *before* CSS to match full acronym |
45 'CSS', | 43 'CSS', |
46 'HTML', | 44 'HTML', |
47 'IME', | 45 'IME', |
48 'JS', | 46 'JS', |
49 'SVG', | 47 'SVG', |
50 'URL', | 48 'URL', |
51 'WOFF', | 49 'WOFF', |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 for acronym in ACRONYMS: | 109 for acronym in ACRONYMS: |
112 if name.startswith(acronym): | 110 if name.startswith(acronym): |
113 return name.replace(acronym, acronym.lower()) | 111 return name.replace(acronym, acronym.lower()) |
114 return name[0].lower() + name[1:] | 112 return name[0].lower() + name[1:] |
115 | 113 |
116 | 114 |
117 ################################################################################ | 115 ################################################################################ |
118 # C++ | 116 # C++ |
119 ################################################################################ | 117 ################################################################################ |
120 | 118 |
121 def enum_validation_expression(idl_type): | |
122 # FIXME: Add IdlEnumType, move property to derived type, and remove this che
ck | |
123 if not idl_type.is_enum: | |
124 return None | |
125 return ' || '.join(['string == "%s"' % enum_value | |
126 for enum_value in idl_type.enum_values]) | |
127 IdlTypeBase.enum_validation_expression = property(enum_validation_expression) | |
128 | |
129 | |
130 def scoped_name(interface, definition, base_name): | 119 def scoped_name(interface, definition, base_name): |
131 if 'ImplementedInPrivateScript' in definition.extended_attributes: | 120 if 'ImplementedInPrivateScript' in definition.extended_attributes: |
132 return '%s::PrivateScript::%s' % (v8_class_name(interface), base_name) | 121 return '%s::PrivateScript::%s' % (v8_class_name(interface), base_name) |
133 # partial interfaces are implemented as separate classes, with their members | 122 # partial interfaces are implemented as separate classes, with their members |
134 # implemented as static member functions | 123 # implemented as static member functions |
135 partial_interface_implemented_as = definition.extended_attributes.get('Parti
alInterfaceImplementedAs') | 124 partial_interface_implemented_as = definition.extended_attributes.get('Parti
alInterfaceImplementedAs') |
136 if partial_interface_implemented_as: | 125 if partial_interface_implemented_as: |
137 return '%s::%s' % (partial_interface_implemented_as, base_name) | 126 return '%s::%s' % (partial_interface_implemented_as, base_name) |
138 if (definition.is_static or | 127 if (definition.is_static or |
139 definition.name in ('Constructor', 'NamedConstructor')): | 128 definition.name in ('Constructor', 'NamedConstructor')): |
140 return '%s::%s' % (cpp_name(interface), base_name) | 129 return '%s::%s' % (cpp_name(interface), base_name) |
141 return 'impl->%s' % base_name | 130 return 'impl->%s' % base_name |
142 | 131 |
143 | 132 |
144 def v8_class_name(interface): | 133 def v8_class_name(interface): |
145 return v8_types.v8_type(interface.name) | 134 return 'V8' + interface.name |
| 135 |
| 136 |
| 137 def v8_class_name_or_partial(interface): |
| 138 class_name = v8_class_name(interface) |
| 139 if interface.is_partial: |
| 140 return ''.join([class_name, 'Partial']) |
| 141 return class_name |
146 | 142 |
147 | 143 |
148 ################################################################################ | 144 ################################################################################ |
149 # Specific extended attributes | 145 # Specific extended attributes |
150 ################################################################################ | 146 ################################################################################ |
151 | 147 |
152 # [ActivityLogging] | 148 # [ActivityLogging] |
153 def activity_logging_world_list(member, access_type=''): | 149 def activity_logging_world_list(member, access_type=''): |
154 """Returns a set of world suffixes for which a definition member has activit
y logging, for specified access type. | 150 """Returns a set of world suffixes for which a definition member has activit
y logging, for specified access type. |
155 | 151 |
(...skipping 30 matching lines...) Expand all Loading... |
186 | 182 |
187 | 183 |
188 # [CallWith] | 184 # [CallWith] |
189 CALL_WITH_ARGUMENTS = { | 185 CALL_WITH_ARGUMENTS = { |
190 'ScriptState': 'scriptState', | 186 'ScriptState': 'scriptState', |
191 'ExecutionContext': 'executionContext', | 187 'ExecutionContext': 'executionContext', |
192 'ScriptArguments': 'scriptArguments.release()', | 188 'ScriptArguments': 'scriptArguments.release()', |
193 'ActiveWindow': 'callingDOMWindow(info.GetIsolate())', | 189 'ActiveWindow': 'callingDOMWindow(info.GetIsolate())', |
194 'FirstWindow': 'enteredDOMWindow(info.GetIsolate())', | 190 'FirstWindow': 'enteredDOMWindow(info.GetIsolate())', |
195 'Document': 'document', | 191 'Document': 'document', |
| 192 'ThisValue': 'ScriptValue(scriptState, info.This())', |
196 } | 193 } |
197 # List because key order matters, as we want arguments in deterministic order | 194 # List because key order matters, as we want arguments in deterministic order |
198 CALL_WITH_VALUES = [ | 195 CALL_WITH_VALUES = [ |
199 'ScriptState', | 196 'ScriptState', |
200 'ExecutionContext', | 197 'ExecutionContext', |
201 'ScriptArguments', | 198 'ScriptArguments', |
202 'ActiveWindow', | 199 'ActiveWindow', |
203 'FirstWindow', | 200 'FirstWindow', |
204 'Document', | 201 'Document', |
| 202 'ThisValue', |
205 ] | 203 ] |
206 | 204 |
207 | 205 |
208 def call_with_arguments(call_with_values): | 206 def call_with_arguments(call_with_values): |
209 if not call_with_values: | 207 if not call_with_values: |
210 return [] | 208 return [] |
211 return [CALL_WITH_ARGUMENTS[value] | 209 return [CALL_WITH_ARGUMENTS[value] |
212 for value in CALL_WITH_VALUES | 210 for value in CALL_WITH_VALUES |
213 if extended_attribute_value_contains(call_with_values, value)] | 211 if extended_attribute_value_contains(call_with_values, value)] |
214 | 212 |
215 | 213 |
216 # [Conditional] | 214 # [Conditional] |
217 DELIMITER_TO_OPERATOR = { | 215 DELIMITER_TO_OPERATOR = { |
218 '|': '||', | 216 '|': '||', |
219 ',': '&&', | 217 ',': '&&', |
220 } | 218 } |
221 | 219 |
222 | 220 |
223 def conditional_string(definition_or_member): | 221 def conditional_string(definition_or_member): |
224 extended_attributes = definition_or_member.extended_attributes | 222 extended_attributes = definition_or_member.extended_attributes |
225 if 'Conditional' not in extended_attributes: | 223 if 'Conditional' not in extended_attributes: |
226 return None | 224 return None |
227 return 'ENABLE(%s)' % extended_attributes['Conditional'] | 225 return 'ENABLE(%s)' % extended_attributes['Conditional'] |
228 | 226 |
229 | 227 |
| 228 # [Constructor], [NamedConstructor] |
| 229 def is_constructor_attribute(member): |
| 230 # TODO(yukishiino): replace this with [Constructor] and [NamedConstructor] e
xtended attribute |
| 231 return member.idl_type.name.endswith('Constructor') |
| 232 |
| 233 |
230 # [DeprecateAs] | 234 # [DeprecateAs] |
231 def deprecate_as(member): | 235 def deprecate_as(member): |
232 extended_attributes = member.extended_attributes | 236 extended_attributes = member.extended_attributes |
233 if 'DeprecateAs' not in extended_attributes: | 237 if 'DeprecateAs' not in extended_attributes: |
234 return None | 238 return None |
235 includes.add('core/frame/UseCounter.h') | 239 includes.add('core/frame/UseCounter.h') |
236 return extended_attributes['DeprecateAs'] | 240 return extended_attributes['DeprecateAs'] |
237 | 241 |
238 | 242 |
239 # [Exposed] | 243 # [Exposed] |
240 EXPOSED_EXECUTION_CONTEXT_METHOD = { | 244 EXPOSED_EXECUTION_CONTEXT_METHOD = { |
| 245 'CompositorWorker': 'isCompositorWorkerGlobalScope', |
241 'DedicatedWorker': 'isDedicatedWorkerGlobalScope', | 246 'DedicatedWorker': 'isDedicatedWorkerGlobalScope', |
242 'ServiceWorker': 'isServiceWorkerGlobalScope', | 247 'ServiceWorker': 'isServiceWorkerGlobalScope', |
243 'SharedWorker': 'isSharedWorkerGlobalScope', | 248 'SharedWorker': 'isSharedWorkerGlobalScope', |
244 'Window': 'isDocument', | 249 'Window': 'isDocument', |
245 'Worker': 'isWorkerGlobalScope', | 250 'Worker': 'isWorkerGlobalScope', |
246 } | 251 } |
247 | 252 |
248 | 253 |
249 def exposed(definition_or_member, interface): | 254 EXPOSED_WORKERS = set([ |
250 exposure_set = extended_attribute_value_as_list(definition_or_member, 'Expos
ed') | 255 'CompositorWorker', |
251 if not exposure_set: | 256 'DedicatedWorker', |
252 return None | 257 'SharedWorker', |
| 258 'ServiceWorker', |
| 259 ]) |
253 | 260 |
254 interface_exposure_set = expanded_exposure_set_for_interface(interface) | 261 |
| 262 class ExposureSet: |
| 263 """An ExposureSet is a collection of Exposure instructions.""" |
| 264 def __init__(self, exposures=None): |
| 265 self.exposures = set(exposures) if exposures else set() |
| 266 |
| 267 def issubset(self, other): |
| 268 """Returns true if |self|'s exposure set is a subset of |
| 269 |other|'s exposure set. This function doesn't care about |
| 270 RuntimeEnabled.""" |
| 271 self_set = self._extended(set(e.exposed for e in self.exposures)) |
| 272 other_set = self._extended(set(e.exposed for e in other.exposures)) |
| 273 return self_set.issubset(other_set) |
| 274 |
| 275 @staticmethod |
| 276 def _extended(target): |
| 277 if EXPOSED_WORKERS.issubset(target): |
| 278 return target | set(['Worker']) |
| 279 elif 'Worker' in target: |
| 280 return target | EXPOSED_WORKERS |
| 281 return target |
| 282 |
| 283 def add(self, exposure): |
| 284 self.exposures.add(exposure) |
| 285 |
| 286 def __len__(self): |
| 287 return len(self.exposures) |
| 288 |
| 289 def __iter__(self): |
| 290 return self.exposures.__iter__() |
| 291 |
| 292 @staticmethod |
| 293 def _code(exposure): |
| 294 exposed = ('context->%s()' % |
| 295 EXPOSED_EXECUTION_CONTEXT_METHOD[exposure.exposed]) |
| 296 if exposure.runtime_enabled is not None: |
| 297 runtime_enabled = ('RuntimeEnabledFeatures::%sEnabled()' % |
| 298 uncapitalize(exposure.runtime_enabled)) |
| 299 return '({0} && {1})'.format(exposed, runtime_enabled) |
| 300 return exposed |
| 301 |
| 302 def code(self): |
| 303 if len(self.exposures) == 0: |
| 304 return None |
| 305 # We use sorted here to deflake output. |
| 306 return ' || '.join(sorted(self._code(e) for e in self.exposures)) |
| 307 |
| 308 |
| 309 def exposed(member, interface): |
| 310 """Returns a C++ code that checks if a method/attribute/etc is exposed. |
| 311 |
| 312 When the Exposed attribute contains RuntimeEnabledFeatures (i.e. |
| 313 Exposed(Arguments) form is given), the code contains check for them as |
| 314 well. |
| 315 |
| 316 EXAMPLE: [Exposed=Window, RuntimeEnabledFeature=Feature1] |
| 317 => context->isDocument() |
| 318 |
| 319 EXAMPLE: [Exposed(Window Feature1, Window Feature2)] |
| 320 => context->isDocument() && RuntimeEnabledFeatures::feature1Enabled() || |
| 321 context->isDocument() && RuntimeEnabledFeatures::feature2Enabled() |
| 322 """ |
| 323 exposure_set = ExposureSet( |
| 324 extended_attribute_value_as_list(member, 'Exposed')) |
| 325 interface_exposure_set = ExposureSet( |
| 326 extended_attribute_value_as_list(interface, 'Exposed')) |
| 327 for e in exposure_set: |
| 328 if e.exposed not in EXPOSED_EXECUTION_CONTEXT_METHOD: |
| 329 raise ValueError('Invalid execution context: %s' % e.exposed) |
255 | 330 |
256 # Methods must not be exposed to a broader scope than their interface. | 331 # Methods must not be exposed to a broader scope than their interface. |
257 if not set(exposure_set).issubset(interface_exposure_set): | 332 if not exposure_set.issubset(interface_exposure_set): |
258 raise ValueError('Interface members\' exposure sets must be a subset of
the interface\'s.') | 333 raise ValueError('Interface members\' exposure sets must be a subset of
the interface\'s.') |
259 | 334 |
260 exposure_checks = [] | 335 return exposure_set.code() |
261 for environment in exposure_set: | |
262 # Methods must be exposed on one of the scopes known to Blink. | |
263 if environment not in EXPOSED_EXECUTION_CONTEXT_METHOD: | |
264 raise ValueError('Values for the [Exposed] annotation must reflect t
o a valid exposure scope.') | |
265 | |
266 exposure_checks.append('context->%s()' % EXPOSED_EXECUTION_CONTEXT_METHO
D[environment]) | |
267 | |
268 return ' || '.join(exposure_checks) | |
269 | |
270 | |
271 def expanded_exposure_set_for_interface(interface): | |
272 exposure_set = extended_attribute_value_as_list(interface, 'Exposed') | |
273 | |
274 # "Worker" is an aggregation for the different kinds of workers. | |
275 if 'Worker' in exposure_set: | |
276 exposure_set.extend(('DedicatedWorker', 'SharedWorker', 'ServiceWorker')
) | |
277 | |
278 return sorted(set(exposure_set)) | |
279 | 336 |
280 | 337 |
281 # [GarbageCollected], [WillBeGarbageCollected] | 338 # [GarbageCollected], [WillBeGarbageCollected] |
282 def gc_type(definition): | 339 def gc_type(definition): |
283 extended_attributes = definition.extended_attributes | 340 extended_attributes = definition.extended_attributes |
284 if 'GarbageCollected' in extended_attributes: | 341 if 'GarbageCollected' in extended_attributes: |
285 return 'GarbageCollectedObject' | 342 return 'GarbageCollectedObject' |
286 elif 'WillBeGarbageCollected' in extended_attributes: | 343 elif 'WillBeGarbageCollected' in extended_attributes: |
287 return 'WillBeGarbageCollectedObject' | 344 return 'WillBeGarbageCollectedObject' |
288 return 'RefCountedObject' | 345 return 'RefCountedObject' |
289 | 346 |
290 | 347 |
291 # [ImplementedAs] | 348 # [ImplementedAs] |
292 def cpp_name(definition_or_member): | 349 def cpp_name(definition_or_member): |
293 extended_attributes = definition_or_member.extended_attributes | 350 extended_attributes = definition_or_member.extended_attributes |
294 if 'ImplementedAs' not in extended_attributes: | 351 if 'ImplementedAs' not in extended_attributes: |
295 return definition_or_member.name | 352 return definition_or_member.name |
296 return extended_attributes['ImplementedAs'] | 353 return extended_attributes['ImplementedAs'] |
297 | 354 |
298 | 355 |
299 # [MeasureAs] | 356 def cpp_name_from_interfaces_info(name, interfaces_info): |
300 def measure_as(definition_or_member): | 357 return interfaces_info.get(name, {}).get('implemented_as') or name |
301 extended_attributes = definition_or_member.extended_attributes | |
302 if 'MeasureAs' not in extended_attributes: | |
303 return None | |
304 includes.add('core/frame/UseCounter.h') | |
305 return extended_attributes['MeasureAs'] | |
306 | 358 |
307 | 359 |
308 # [PerContextEnabled] | 360 def cpp_name_or_partial(interface): |
309 def per_context_enabled_function_name(definition_or_member): | 361 cpp_class_name = cpp_name(interface) |
| 362 if interface.is_partial: |
| 363 return ''.join([cpp_class_name, 'Partial']) |
| 364 return cpp_class_name |
| 365 |
| 366 |
| 367 # [MeasureAs] |
| 368 def measure_as(definition_or_member, interface): |
310 extended_attributes = definition_or_member.extended_attributes | 369 extended_attributes = definition_or_member.extended_attributes |
311 if 'PerContextEnabled' not in extended_attributes: | 370 if 'MeasureAs' in extended_attributes: |
312 return None | 371 includes.add('core/frame/UseCounter.h') |
313 feature_name = extended_attributes['PerContextEnabled'] | 372 return lambda suffix: extended_attributes['MeasureAs'] |
314 return 'ContextFeatures::%sEnabled' % uncapitalize(feature_name) | 373 if 'Measure' in extended_attributes: |
| 374 includes.add('core/frame/UseCounter.h') |
| 375 measure_as_name = capitalize(definition_or_member.name) |
| 376 if interface is not None: |
| 377 measure_as_name = '%s_%s' % (capitalize(interface.name), measure_as_
name) |
| 378 return lambda suffix: 'V8%s_%s' % (measure_as_name, suffix) |
| 379 return None |
315 | 380 |
316 | 381 |
317 # [RuntimeEnabled] | 382 # [RuntimeEnabled] |
318 def runtime_enabled_function_name(definition_or_member): | 383 def runtime_enabled_function_name(definition_or_member): |
319 """Returns the name of the RuntimeEnabledFeatures function. | 384 """Returns the name of the RuntimeEnabledFeatures function. |
320 | 385 |
321 The returned function checks if a method/attribute is enabled. | 386 The returned function checks if a method/attribute is enabled. |
322 Given extended attribute RuntimeEnabled=FeatureName, return: | 387 Given extended attribute RuntimeEnabled=FeatureName, return: |
323 RuntimeEnabledFeatures::{featureName}Enabled | 388 RuntimeEnabledFeatures::{featureName}Enabled |
324 """ | 389 """ |
325 extended_attributes = definition_or_member.extended_attributes | 390 extended_attributes = definition_or_member.extended_attributes |
326 if 'RuntimeEnabled' not in extended_attributes: | 391 if 'RuntimeEnabled' not in extended_attributes: |
327 return None | 392 return None |
328 feature_name = extended_attributes['RuntimeEnabled'] | 393 feature_name = extended_attributes['RuntimeEnabled'] |
329 return 'RuntimeEnabledFeatures::%sEnabled' % uncapitalize(feature_name) | 394 return 'RuntimeEnabledFeatures::%sEnabled' % uncapitalize(feature_name) |
330 | 395 |
331 | 396 |
332 ################################################################################ | 397 # [Unforgeable] |
333 # Dart Specific extended attributes | 398 def is_unforgeable(interface, member): |
334 ################################################################################ | 399 return (('Unforgeable' in interface.extended_attributes or |
335 def dart_custom_method(extended_attributes): | 400 'Unforgeable' in member.extended_attributes) and |
336 return ('DartCustom' in extended_attributes and | 401 not member.is_static) |
337 extended_attribute_value_contains(extended_attributes['DartCustom'],
'New')) | 402 |
| 403 |
| 404 # [TypeChecking=Interface] / [LegacyInterfaceTypeChecking] |
| 405 def is_legacy_interface_type_checking(interface, member): |
| 406 if not ('TypeChecking' in interface.extended_attributes or |
| 407 'TypeChecking' in member.extended_attributes): |
| 408 return True |
| 409 if 'LegacyInterfaceTypeChecking' in member.extended_attributes: |
| 410 return True |
| 411 return False |
| 412 |
| 413 |
| 414 # [Unforgeable], [Global], [PrimaryGlobal] and [DoNotExposeJSAccessors] |
| 415 def on_instance(interface, member): |
| 416 """Returns True if the interface's member needs to be defined on every |
| 417 instance object. |
| 418 |
| 419 The following members must be defiend on an instance object. |
| 420 - [Unforgeable] members |
| 421 - regular members of [Global] or [PrimaryGlobal] interfaces |
| 422 - members on which [DoNotExposeJSAccessors] is specified |
| 423 """ |
| 424 # TODO(yukishiino): Implement this function following the spec. |
| 425 return not on_prototype(interface, member) |
| 426 |
| 427 |
| 428 # [ExposeJSAccessors] |
| 429 def on_prototype(interface, member): |
| 430 """Returns True if the interface's member needs to be defined on the |
| 431 prototype object. |
| 432 |
| 433 Most members are defined on the prototype object. Exceptions are as |
| 434 follows. |
| 435 - constant members |
| 436 - static members (optional) |
| 437 - [Unforgeable] members |
| 438 - members of [Global] or [PrimaryGlobal] interfaces |
| 439 - named properties of [Global] or [PrimaryGlobal] interfaces |
| 440 However, if [ExposeJSAccessors] is specified, the member is defined on the |
| 441 prototype object. |
| 442 """ |
| 443 # TODO(yukishiino): Implement this function following the spec. |
| 444 |
| 445 if ('ExposeJSAccessors' in interface.extended_attributes and |
| 446 'DoNotExposeJSAccessors' in interface.extended_attributes): |
| 447 raise Exception('Both of ExposeJSAccessors and DoNotExposeJSAccessors ar
e specified at a time in an interface: ' + interface.name) |
| 448 if ('ExposeJSAccessors' in member.extended_attributes and |
| 449 'DoNotExposeJSAccessors' in member.extended_attributes): |
| 450 raise Exception('Both of ExposeJSAccessors and DoNotExposeJSAccessors ar
e specified at a time on a member: ' + member.name + ' in an interface: ' + inte
rface.name) |
| 451 |
| 452 # Note that ExposeJSAccessors and DoNotExposeJSAccessors are more powerful |
| 453 # than 'static', [Unforgeable] and [OverrideBuiltins]. |
| 454 if 'ExposeJSAccessors' in member.extended_attributes: |
| 455 return True |
| 456 if 'DoNotExposeJSAccessors' in member.extended_attributes: |
| 457 return False |
| 458 |
| 459 # These members must not be placed on prototype chains. |
| 460 if (is_constructor_attribute(member) or |
| 461 member.is_static or |
| 462 is_unforgeable(interface, member) or |
| 463 'OverrideBuiltins' in interface.extended_attributes): |
| 464 return False |
| 465 |
| 466 # TODO(yukishiino): We should handle [Global] and [PrimaryGlobal] instead of |
| 467 # Window. |
| 468 if (interface.name == 'Window'): |
| 469 return member.idl_type.name == 'EventHandler' |
| 470 |
| 471 if 'ExposeJSAccessors' in interface.extended_attributes: |
| 472 return True |
| 473 if 'DoNotExposeJSAccessors' in interface.extended_attributes: |
| 474 return False |
| 475 |
| 476 return True |
| 477 |
| 478 |
| 479 # static, const |
| 480 def on_interface(interface, member): |
| 481 """Returns True if the interface's member needs to be defined on the |
| 482 interface object. |
| 483 |
| 484 The following members must be defiend on an interface object. |
| 485 - constant members |
| 486 - static members |
| 487 """ |
| 488 # TODO(yukishiino): Implement this function following the spec. |
| 489 return False |
| 490 |
| 491 |
| 492 ################################################################################ |
| 493 # Indexed properties |
| 494 # http://heycam.github.io/webidl/#idl-indexed-properties |
| 495 ################################################################################ |
| 496 |
| 497 def indexed_property_getter(interface): |
| 498 try: |
| 499 # Find indexed property getter, if present; has form: |
| 500 # getter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1) |
| 501 return next( |
| 502 method |
| 503 for method in interface.operations |
| 504 if ('getter' in method.specials and |
| 505 len(method.arguments) == 1 and |
| 506 str(method.arguments[0].idl_type) == 'unsigned long')) |
| 507 except StopIteration: |
| 508 return None |
| 509 |
| 510 |
| 511 def indexed_property_setter(interface): |
| 512 try: |
| 513 # Find indexed property setter, if present; has form: |
| 514 # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1, ARG_TYPE
ARG2) |
| 515 return next( |
| 516 method |
| 517 for method in interface.operations |
| 518 if ('setter' in method.specials and |
| 519 len(method.arguments) == 2 and |
| 520 str(method.arguments[0].idl_type) == 'unsigned long')) |
| 521 except StopIteration: |
| 522 return None |
| 523 |
| 524 |
| 525 def indexed_property_deleter(interface): |
| 526 try: |
| 527 # Find indexed property deleter, if present; has form: |
| 528 # deleter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG) |
| 529 return next( |
| 530 method |
| 531 for method in interface.operations |
| 532 if ('deleter' in method.specials and |
| 533 len(method.arguments) == 1 and |
| 534 str(method.arguments[0].idl_type) == 'unsigned long')) |
| 535 except StopIteration: |
| 536 return None |
| 537 |
| 538 |
| 539 ################################################################################ |
| 540 # Named properties |
| 541 # http://heycam.github.io/webidl/#idl-named-properties |
| 542 ################################################################################ |
| 543 |
| 544 def named_property_getter(interface): |
| 545 try: |
| 546 # Find named property getter, if present; has form: |
| 547 # getter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1) |
| 548 getter = next( |
| 549 method |
| 550 for method in interface.operations |
| 551 if ('getter' in method.specials and |
| 552 len(method.arguments) == 1 and |
| 553 str(method.arguments[0].idl_type) == 'DOMString')) |
| 554 getter.name = getter.name or 'anonymousNamedGetter' |
| 555 return getter |
| 556 except StopIteration: |
| 557 return None |
| 558 |
| 559 |
| 560 def named_property_setter(interface): |
| 561 try: |
| 562 # Find named property setter, if present; has form: |
| 563 # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1, ARG_TYPE ARG2
) |
| 564 return next( |
| 565 method |
| 566 for method in interface.operations |
| 567 if ('setter' in method.specials and |
| 568 len(method.arguments) == 2 and |
| 569 str(method.arguments[0].idl_type) == 'DOMString')) |
| 570 except StopIteration: |
| 571 return None |
| 572 |
| 573 |
| 574 def named_property_deleter(interface): |
| 575 try: |
| 576 # Find named property deleter, if present; has form: |
| 577 # deleter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG) |
| 578 return next( |
| 579 method |
| 580 for method in interface.operations |
| 581 if ('deleter' in method.specials and |
| 582 len(method.arguments) == 1 and |
| 583 str(method.arguments[0].idl_type) == 'DOMString')) |
| 584 except StopIteration: |
| 585 return None |
| 586 |
| 587 |
| 588 IdlInterface.indexed_property_getter = property(indexed_property_getter) |
| 589 IdlInterface.indexed_property_setter = property(indexed_property_setter) |
| 590 IdlInterface.indexed_property_deleter = property(indexed_property_deleter) |
| 591 IdlInterface.named_property_getter = property(named_property_getter) |
| 592 IdlInterface.named_property_setter = property(named_property_setter) |
| 593 IdlInterface.named_property_deleter = property(named_property_deleter) |
OLD | NEW |