OLD | NEW |
| (Empty) |
1 # Copyright (C) 2013 Google Inc. All rights reserved. | |
2 # coding=utf-8 | |
3 # | |
4 # Redistribution and use in source and binary forms, with or without | |
5 # modification, are permitted provided that the following conditions are | |
6 # met: | |
7 # | |
8 # * Redistributions of source code must retain the above copyright | |
9 # notice, this list of conditions and the following disclaimer. | |
10 # * Redistributions in binary form must reproduce the above | |
11 # copyright notice, this list of conditions and the following disclaimer | |
12 # in the documentation and/or other materials provided with the | |
13 # distribution. | |
14 # * Neither the name of Google Inc. nor the names of its | |
15 # contributors may be used to endorse or promote products derived from | |
16 # this software without specific prior written permission. | |
17 # | |
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | |
30 """Generate template values for an interface. | |
31 | |
32 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler | |
33 """ | |
34 | |
35 from collections import defaultdict | |
36 import itertools | |
37 from operator import itemgetter | |
38 | |
39 import idl_types | |
40 from idl_types import IdlType, inherits_interface, IdlArrayOrSequenceType, IdlAr
rayType | |
41 import dart_attributes | |
42 import dart_methods | |
43 import dart_types | |
44 from dart_utilities import DartUtilities | |
45 from v8_globals import includes | |
46 import v8_attributes | |
47 import v8_interface | |
48 | |
49 | |
50 INTERFACE_H_INCLUDES = frozenset([ | |
51 'bindings/core/dart/DartDOMWrapper.h', | |
52 'platform/heap/Handle.h', | |
53 ]) | |
54 | |
55 INTERFACE_CPP_INCLUDES = frozenset([ | |
56 | |
57 'bindings/core/dart/DartUtilities.h', | |
58 'wtf/GetPtr.h', | |
59 'wtf/RefPtr.h', | |
60 ]) | |
61 | |
62 | |
63 # TODO(terry): Temporary to not generate a method, getter/setter. Format is: | |
64 # | |
65 # interface_name.method_name | |
66 # interface_name.get:attribute_name | |
67 # interface_name.set:attribute_name | |
68 # | |
69 # Ultimate solution add a special attribute flag to IDL to signal | |
70 # don't generate IDL entry in Dart (e.g., DartNoGenerate)? | |
71 IGNORE_MEMBERS = frozenset([ | |
72 'AudioBufferSourceNode.looping', # TODO(vsm): Use deprecated IDL annotation | |
73 'CSSStyleDeclaration.getPropertyCSSValue', | |
74 'CanvasRenderingContext2D.clearShadow', | |
75 'CanvasRenderingContext2D.drawImageFromRect', | |
76 'CanvasRenderingContext2D.setAlpha', | |
77 'CanvasRenderingContext2D.setCompositeOperation', | |
78 'CanvasRenderingContext2D.setFillColor', | |
79 'CanvasRenderingContext2D.setLineCap', | |
80 'CanvasRenderingContext2D.setLineJoin', | |
81 'CanvasRenderingContext2D.setLineWidth', | |
82 'CanvasRenderingContext2D.setMiterLimit', | |
83 'CanvasRenderingContext2D.setShadow', | |
84 'CanvasRenderingContext2D.setStrokeColor', | |
85 'CharacterData.remove', | |
86 'Window.call:blur', | |
87 'Window.call:focus', | |
88 'Window.clientInformation', | |
89 'Window.createImageBitmap', | |
90 'Window.get:frames', | |
91 'Window.get:length', | |
92 'Window.on:beforeUnload', | |
93 'Window.on:webkitTransitionEnd', | |
94 'Window.pagePopupController', | |
95 'Window.prompt', | |
96 'Window.webkitCancelAnimationFrame', | |
97 'Window.webkitCancelRequestAnimationFrame', | |
98 'Window.webkitIndexedDB', | |
99 'Window.webkitRequestAnimationFrame', | |
100 'Document.alinkColor', | |
101 'HTMLDocument.all', | |
102 'Document.applets', | |
103 'Document.bgColor', | |
104 'Document.clear', | |
105 'Document.createAttribute', | |
106 'Document.createAttributeNS', | |
107 'Document.createComment', | |
108 'Document.createExpression', | |
109 'Document.createNSResolver', | |
110 'Document.createProcessingInstruction', | |
111 'Document.designMode', | |
112 'Document.dir', | |
113 'Document.evaluate', | |
114 'Document.fgColor', | |
115 'Document.get:URL', | |
116 'Document.get:anchors', | |
117 'Document.get:characterSet', | |
118 'Document.get:compatMode', | |
119 'Document.get:defaultCharset', | |
120 'Document.get:doctype', | |
121 'Document.get:documentURI', | |
122 'Document.get:embeds', | |
123 'Document.get:forms', | |
124 'Document.get:inputEncoding', | |
125 'Document.get:links', | |
126 'Document.get:plugins', | |
127 'Document.get:scripts', | |
128 'Document.get:xmlEncoding', | |
129 'Document.getElementsByTagNameNS', | |
130 'Document.getOverrideStyle', | |
131 'Document.getSelection', | |
132 'Document.images', | |
133 'Document.linkColor', | |
134 'Document.location', | |
135 'Document.on:wheel', | |
136 'Document.open', | |
137 'Document.register', | |
138 'Document.set:domain', | |
139 'Document.vlinkColor', | |
140 'Document.webkitCurrentFullScreenElement', | |
141 'Document.webkitFullScreenKeyboardInputAllowed', | |
142 'Document.write', | |
143 'Document.writeln', | |
144 'Document.xmlStandalone', | |
145 'Document.xmlVersion', | |
146 'DocumentFragment.children', | |
147 'DocumentType.*', | |
148 'DOMException.code', | |
149 'DOMException.ABORT_ERR', | |
150 'DOMException.DATA_CLONE_ERR', | |
151 'DOMException.DOMSTRING_SIZE_ERR', | |
152 'DOMException.HIERARCHY_REQUEST_ERR', | |
153 'DOMException.INDEX_SIZE_ERR', | |
154 'DOMException.INUSE_ATTRIBUTE_ERR', | |
155 'DOMException.INVALID_ACCESS_ERR', | |
156 'DOMException.INVALID_CHARACTER_ERR', | |
157 'DOMException.INVALID_MODIFICATION_ERR', | |
158 'DOMException.INVALID_NODE_TYPE_ERR', | |
159 'DOMException.INVALID_STATE_ERR', | |
160 'DOMException.NAMESPACE_ERR', | |
161 'DOMException.NETWORK_ERR', | |
162 'DOMException.NOT_FOUND_ERR', | |
163 'DOMException.NOT_SUPPORTED_ERR', | |
164 'DOMException.NO_DATA_ALLOWED_ERR', | |
165 'DOMException.NO_MODIFICATION_ALLOWED_ERR', | |
166 'DOMException.QUOTA_EXCEEDED_ERR', | |
167 'DOMException.SECURITY_ERR', | |
168 'DOMException.SYNTAX_ERR', | |
169 'DOMException.TIMEOUT_ERR', | |
170 'DOMException.TYPE_MISMATCH_ERR', | |
171 'DOMException.URL_MISMATCH_ERR', | |
172 'DOMException.VALIDATION_ERR', | |
173 'DOMException.WRONG_DOCUMENT_ERR', | |
174 'Element.accessKey', | |
175 'Element.dataset', | |
176 'Element.get:classList', | |
177 'Element.getAttributeNode', | |
178 'Element.getAttributeNodeNS', | |
179 'Element.getElementsByTagNameNS', | |
180 'Element.innerText', | |
181 'Element.on:wheel', | |
182 'Element.outerText', | |
183 'Element.removeAttributeNode', | |
184 'Element.set:outerHTML', | |
185 'Element.setAttributeNode', | |
186 'Element.setAttributeNodeNS', | |
187 'Element.webkitCreateShadowRoot', | |
188 'Element.webkitMatchesSelector', | |
189 'Element.webkitPseudo', | |
190 'Element.webkitShadowRoot', | |
191 '=Event.returnValue', # Only suppress on Event, allow for BeforeUnloadEvent
. | |
192 'Event.srcElement', | |
193 'EventSource.URL', | |
194 'FontFace.ready', | |
195 'FontFaceSet.load', | |
196 'FontFaceSet.ready', | |
197 'HTMLAnchorElement.charset', | |
198 'HTMLAnchorElement.coords', | |
199 'HTMLAnchorElement.rev', | |
200 'HTMLAnchorElement.shape', | |
201 'HTMLAnchorElement.text', | |
202 'HTMLAppletElement.*', | |
203 'HTMLAreaElement.noHref', | |
204 'HTMLBRElement.clear', | |
205 'HTMLBaseFontElement.*', | |
206 'HTMLBodyElement.aLink', | |
207 'HTMLBodyElement.background', | |
208 'HTMLBodyElement.bgColor', | |
209 'HTMLBodyElement.link', | |
210 'HTMLBodyElement.on:beforeUnload', | |
211 'HTMLBodyElement.text', | |
212 'HTMLBodyElement.vLink', | |
213 'HTMLDListElement.compact', | |
214 'HTMLDirectoryElement.*', | |
215 'HTMLDivElement.align', | |
216 'HTMLFontElement.*', | |
217 'HTMLFormControlsCollection.__getter__', | |
218 'HTMLFormElement.get:elements', | |
219 'HTMLFrameElement.*', | |
220 'HTMLFrameSetElement.*', | |
221 'HTMLHRElement.align', | |
222 'HTMLHRElement.noShade', | |
223 'HTMLHRElement.size', | |
224 'HTMLHRElement.width', | |
225 'HTMLHeadElement.profile', | |
226 'HTMLHeadingElement.align', | |
227 'HTMLHtmlElement.manifest', | |
228 'HTMLHtmlElement.version', | |
229 'HTMLIFrameElement.align', | |
230 'HTMLIFrameElement.frameBorder', | |
231 'HTMLIFrameElement.longDesc', | |
232 'HTMLIFrameElement.marginHeight', | |
233 'HTMLIFrameElement.marginWidth', | |
234 'HTMLIFrameElement.scrolling', | |
235 'HTMLImageElement.align', | |
236 'HTMLImageElement.hspace', | |
237 'HTMLImageElement.longDesc', | |
238 'HTMLImageElement.name', | |
239 'HTMLImageElement.vspace', | |
240 'HTMLInputElement.align', | |
241 'HTMLLegendElement.align', | |
242 'HTMLLinkElement.charset', | |
243 'HTMLLinkElement.rev', | |
244 'HTMLLinkElement.target', | |
245 'HTMLMarqueeElement.*', | |
246 'HTMLMenuElement.compact', | |
247 'HTMLMetaElement.scheme', | |
248 'HTMLOListElement.compact', | |
249 'HTMLObjectElement.align', | |
250 'HTMLObjectElement.archive', | |
251 'HTMLObjectElement.border', | |
252 'HTMLObjectElement.codeBase', | |
253 'HTMLObjectElement.codeType', | |
254 'HTMLObjectElement.declare', | |
255 'HTMLObjectElement.hspace', | |
256 'HTMLObjectElement.standby', | |
257 'HTMLObjectElement.vspace', | |
258 'HTMLOptionElement.text', | |
259 'HTMLOptionsCollection.*', | |
260 'HTMLParagraphElement.align', | |
261 'HTMLParamElement.type', | |
262 'HTMLParamElement.valueType', | |
263 'HTMLPreElement.width', | |
264 'HTMLScriptElement.text', | |
265 'HTMLSelectElement.options', | |
266 'HTMLSelectElement.selectedOptions', | |
267 'HTMLTableCaptionElement.align', | |
268 'HTMLTableCellElement.abbr', | |
269 'HTMLTableCellElement.align', | |
270 'HTMLTableCellElement.axis', | |
271 'HTMLTableCellElement.bgColor', | |
272 'HTMLTableCellElement.ch', | |
273 'HTMLTableCellElement.chOff', | |
274 'HTMLTableCellElement.height', | |
275 'HTMLTableCellElement.noWrap', | |
276 'HTMLTableCellElement.scope', | |
277 'HTMLTableCellElement.vAlign', | |
278 'HTMLTableCellElement.width', | |
279 'HTMLTableColElement.align', | |
280 'HTMLTableColElement.ch', | |
281 'HTMLTableColElement.chOff', | |
282 'HTMLTableColElement.vAlign', | |
283 'HTMLTableColElement.width', | |
284 'HTMLTableElement.align', | |
285 'HTMLTableElement.bgColor', | |
286 'HTMLTableElement.cellPadding', | |
287 'HTMLTableElement.cellSpacing', | |
288 'HTMLTableElement.frame', | |
289 'HTMLTableElement.rules', | |
290 'HTMLTableElement.summary', | |
291 'HTMLTableElement.width', | |
292 'HTMLTableRowElement.align', | |
293 'HTMLTableRowElement.bgColor', | |
294 'HTMLTableRowElement.ch', | |
295 'HTMLTableRowElement.chOff', | |
296 'HTMLTableRowElement.vAlign', | |
297 'HTMLTableSectionElement.align', | |
298 'HTMLTableSectionElement.ch', | |
299 'HTMLTableSectionElement.chOff', | |
300 'HTMLTableSectionElement.vAlign', | |
301 'HTMLTitleElement.text', | |
302 'HTMLUListElement.compact', | |
303 'HTMLUListElement.type', | |
304 'Location.valueOf', | |
305 'MessageEvent.ports', | |
306 'MessageEvent.webkitInitMessageEvent', | |
307 'MouseEvent.x', | |
308 'MouseEvent.y', | |
309 'Navigator.registerServiceWorker', | |
310 'Navigator.unregisterServiceWorker', | |
311 'Node.compareDocumentPosition', | |
312 'Node.get:DOCUMENT_POSITION_CONTAINED_BY', | |
313 'Node.get:DOCUMENT_POSITION_CONTAINS', | |
314 'Node.get:DOCUMENT_POSITION_DISCONNECTED', | |
315 'Node.get:DOCUMENT_POSITION_FOLLOWING', | |
316 'Node.get:DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC', | |
317 'Node.get:DOCUMENT_POSITION_PRECEDING', | |
318 'Node.get:prefix', | |
319 'Node.hasAttributes', | |
320 'Node.isDefaultNamespace', | |
321 'Node.isEqualNode', | |
322 'Node.isSameNode', | |
323 'Node.isSupported', | |
324 'Node.lookupNamespaceURI', | |
325 'Node.lookupPrefix', | |
326 'Node.normalize', | |
327 'Node.set:nodeValue', | |
328 'NodeFilter.acceptNode', | |
329 'NodeIterator.expandEntityReferences', | |
330 'NodeIterator.filter', | |
331 'Performance.webkitClearMarks', | |
332 'Performance.webkitClearMeasures', | |
333 'Performance.webkitGetEntries', | |
334 'Performance.webkitGetEntriesByName', | |
335 'Performance.webkitGetEntriesByType', | |
336 'Performance.webkitMark', | |
337 'Performance.webkitMeasure', | |
338 'ShadowRoot.getElementsByTagNameNS', | |
339 'SVGElement.getPresentationAttribute', | |
340 'SVGElementInstance.on:wheel', | |
341 'WheelEvent.wheelDelta', | |
342 'Window.on:wheel', | |
343 'WindowEventHandlers.on:beforeUnload', | |
344 'WorkerGlobalScope.webkitIndexedDB', | |
345 # TODO(jacobr): should these be removed? | |
346 'Document.close', | |
347 'Document.hasFocus', | |
348 ]) | |
349 | |
350 | |
351 def _suppress_method(interface_name, name): | |
352 name_to_find = '%s.%s' % (interface_name, name) | |
353 wildcard_name_to_find = '%s.*' % interface_name | |
354 return name_to_find in IGNORE_MEMBERS or wildcard_name_to_find in IGNORE_MEM
BERS | |
355 | |
356 | |
357 # Both getter and setter are to be suppressed then the attribute is completely | |
358 # disappear. | |
359 def _suppress_attribute(interface_name, name): | |
360 return (suppress_getter(interface_name, name) and suppress_setter(interface_
name, name)) | |
361 | |
362 | |
363 def suppress_getter(interface_name, name): | |
364 name_to_find = '%s.get:%s' % (interface_name, name) | |
365 wildcard_getter_to_find = '%s.get:*' % interface_name | |
366 return (name_to_find in IGNORE_MEMBERS or | |
367 _suppress_method(interface_name, name) or | |
368 wildcard_getter_to_find in IGNORE_MEMBERS) | |
369 | |
370 | |
371 def suppress_setter(interface_name, name): | |
372 name_to_find = '%s.set:%s' % (interface_name, name) | |
373 wildcard_setter_to_find = '%s.set:*' % interface_name | |
374 return (name_to_find in IGNORE_MEMBERS or | |
375 _suppress_method(interface_name, name) or | |
376 wildcard_setter_to_find in IGNORE_MEMBERS) | |
377 | |
378 | |
379 # To suppress an IDL method or attribute with a particular Extended Attribute | |
380 # w/o a value e.g, DartStrictTypeChecking would be an empty set | |
381 # 'DartStrictTypeChecking': frozenset([]), | |
382 IGNORE_EXTENDED_ATTRIBUTES = { | |
383 # 'RuntimeEnabled': frozenset(['ExperimentalCanvasFeatures']), | |
384 } | |
385 | |
386 | |
387 # Return True if the method / attribute should be suppressed. | |
388 def _suppress_extended_attributes(extended_attributes): | |
389 if 'DartSuppress' in extended_attributes and extended_attributes.get('DartSu
ppress') == None: | |
390 return True | |
391 | |
392 # TODO(terry): Eliminate this using DartSuppress extended attribute in the | |
393 # IDL files instead of the IGNORE_EXTENDED_ATTRIBUTES list. | |
394 for extended_attribute_name in extended_attributes: | |
395 ignore_extended_values = IGNORE_EXTENDED_ATTRIBUTES.get(extended_attribu
te_name) | |
396 if ignore_extended_values != None: | |
397 extended_attribute_value = extended_attributes.get(extended_attribut
e_name) | |
398 if ((not ignore_extended_values and extended_attribute_value == None
) or | |
399 extended_attribute_value in ignore_extended_values): | |
400 return True | |
401 return False | |
402 | |
403 | |
404 # TODO(terry): Rename genenerate_interface to interface_context. | |
405 def interface_context(interface): | |
406 context = v8_interface.interface_context(interface) | |
407 | |
408 includes.clear() | |
409 | |
410 includes.update(INTERFACE_CPP_INCLUDES) | |
411 header_includes = set(INTERFACE_H_INCLUDES) | |
412 | |
413 parent_interface = interface.parent | |
414 if parent_interface: | |
415 header_includes.update(dart_types.includes_for_interface(parent_interfac
e)) | |
416 extended_attributes = interface.extended_attributes | |
417 | |
418 is_document = inherits_interface(interface.name, 'Document') | |
419 if is_document: | |
420 # FIXME(vsm): We probably need bindings/dart/DartController and | |
421 # core/frame/LocalFrame.h here. | |
422 includes.update(['DartDocument.h']) | |
423 | |
424 if inherits_interface(interface.name, 'DataTransferItemList'): | |
425 # FIXME(jacobr): this is a hack. | |
426 includes.update(['core/html/HTMLCollection.h']) | |
427 | |
428 | |
429 if inherits_interface(interface.name, 'EventTarget'): | |
430 includes.update(['bindings/core/dart/DartEventListener.h']) | |
431 | |
432 # [SetWrapperReferenceTo] | |
433 set_wrapper_reference_to_list = [{ | |
434 'name': argument.name, | |
435 # FIXME: properly should be: | |
436 # 'cpp_type': argument.idl_type.cpp_type_args(used_as_rvalue_type=True), | |
437 # (if type is non-wrapper type like NodeFilter, normally RefPtr) | |
438 # Raw pointers faster though, and NodeFilter hacky anyway. | |
439 'cpp_type': argument.idl_type.implemented_as + '*', | |
440 'idl_type': argument.idl_type, | |
441 'v8_type': dart_types.v8_type(argument.idl_type.name), | |
442 } for argument in extended_attributes.get('SetWrapperReferenceTo', [])] | |
443 for set_wrapper_reference_to in set_wrapper_reference_to_list: | |
444 set_wrapper_reference_to['idl_type'].add_includes_for_type() | |
445 | |
446 context.update({ | |
447 'conditional_string': DartUtilities.conditional_string(interface), # [C
onditional] | |
448 'cpp_class': DartUtilities.cpp_name(interface), | |
449 'header_includes': header_includes, | |
450 'is_garbage_collected': context['gc_type'] == 'GarbageCollectedObject', | |
451 'is_will_be_garbage_collected': context['gc_type'] == 'WillBeGarbageColl
ectedObject', | |
452 'measure_as': DartUtilities.measure_as(interface), # [MeasureAs] | |
453 'pass_cpp_type': dart_types.cpp_template_type( | |
454 dart_types.cpp_ptr_type('PassRefPtr', 'RawPtr', context['gc_type']), | |
455 DartUtilities.cpp_name(interface)), | |
456 'runtime_enabled_function': DartUtilities.runtime_enabled_function_name(
interface), # [RuntimeEnabled] | |
457 'set_wrapper_reference_to_list': set_wrapper_reference_to_list, | |
458 'dart_class': dart_types.dart_type(interface.name), | |
459 'v8_class': DartUtilities.v8_class_name(interface), | |
460 }) | |
461 | |
462 # Constructors | |
463 constructors = [constructor_context(interface, constructor) | |
464 for constructor in interface.constructors | |
465 # FIXME: shouldn't put named constructors with constructors | |
466 # (currently needed for Perl compatibility) | |
467 # Handle named constructors separately | |
468 if constructor.name == 'Constructor'] | |
469 if len(constructors) > 1: | |
470 context.update({'constructor_overloads': overloads_context(constructors)
}) | |
471 | |
472 # [CustomConstructor] | |
473 custom_constructors = [custom_constructor_context(interface, constructor) | |
474 for constructor in interface.custom_constructors] | |
475 | |
476 # [NamedConstructor] | |
477 named_constructor = generate_named_constructor(interface) | |
478 | |
479 generate_method_native_entries(interface, constructors, 'Constructor') | |
480 generate_method_native_entries(interface, custom_constructors, 'Constructor'
) | |
481 if named_constructor: | |
482 generate_method_native_entries(interface, [named_constructor], | |
483 'Constructor') | |
484 event_constructor = None | |
485 if context['has_event_constructor']: | |
486 event_constructor = { | |
487 'native_entries': [ | |
488 DartUtilities.generate_native_entry( | |
489 interface.name, None, 'Constructor', False, 2)], | |
490 } | |
491 | |
492 if (context['constructors'] or custom_constructors or context['has_event_con
structor'] or | |
493 named_constructor): | |
494 includes.add('core/frame/LocalDOMWindow.h') | |
495 | |
496 context.update({ | |
497 'constructors': constructors, | |
498 'custom_constructors': custom_constructors, | |
499 'event_constructor': event_constructor, | |
500 'has_custom_constructor': bool(custom_constructors), | |
501 'interface_length': | |
502 v8_interface.interface_length(interface, constructors + custom_const
ructors), | |
503 'is_constructor_call_with_document': DartUtilities.has_extended_attribut
e_value( | |
504 interface, 'ConstructorCallWith', 'Document'), # [ConstructorCallWi
th=Document] | |
505 'is_constructor_call_with_execution_context': DartUtilities.has_extended
_attribute_value( | |
506 interface, 'ConstructorCallWith', 'ExecutionContext'), # [Construct
orCallWith=ExeuctionContext] | |
507 'named_constructor': named_constructor, | |
508 }) | |
509 | |
510 # Attributes | |
511 attributes = [dart_attributes.attribute_context(interface, attribute) | |
512 for attribute in interface.attributes | |
513 # Skip attributes in the IGNORE_MEMBERS list or if an | |
514 # extended attribute is in the IGNORE_EXTENDED_ATTRIBUTES. | |
515 if (not _suppress_attribute(interface.name, attribute.name
) and | |
516 not v8_attributes.is_constructor_attribute(attribute)
and | |
517 not _suppress_extended_attributes(attribute.extended_a
ttributes) and | |
518 not ('DartSuppress' in attribute.extended_attributes a
nd | |
519 attribute.extended_attributes.get('DartSuppress') ==
None))] | |
520 context.update({ | |
521 'attributes': attributes, | |
522 'has_accessors': any(attribute['is_expose_js_accessors'] for attribute i
n attributes), | |
523 'has_attribute_configuration': any( | |
524 not (attribute['is_expose_js_accessors'] or | |
525 attribute['is_static'] or | |
526 attribute['runtime_enabled_function'] or | |
527 attribute['per_context_enabled_function']) | |
528 for attribute in attributes), | |
529 'has_constructor_attributes': any(attribute['constructor_type'] for attr
ibute in attributes), | |
530 'has_per_context_enabled_attributes': any(attribute['per_context_enabled
_function'] for attribute in attributes), | |
531 'has_replaceable_attributes': any(attribute['is_replaceable'] for attrib
ute in attributes), | |
532 }) | |
533 | |
534 # Methods | |
535 methods = [dart_methods.method_context(interface, method) | |
536 for method in interface.operations | |
537 # Skip anonymous special operations (methods name empty). | |
538 # Skip methods in our IGNORE_MEMBERS list. | |
539 # Skip methods w/ extended attributes in IGNORE_EXTENDED_ATTRIBUT
ES list. | |
540 if (method.name and | |
541 # detect unnamed getters from v8_interface. | |
542 method.name != 'anonymousNamedGetter' and | |
543 # TODO(terry): Eventual eliminate the IGNORE_MEMBERS in favor
of DartSupress. | |
544 not _suppress_method(interface.name, method.name) and | |
545 not _suppress_extended_attributes(method.extended_attributes)
and | |
546 not 'DartSuppress' in method.extended_attributes)] | |
547 compute_method_overloads_context(methods) | |
548 for method in methods: | |
549 method['do_generate_method_configuration'] = ( | |
550 method['do_not_check_signature'] and | |
551 not method['per_context_enabled_function'] and | |
552 # For overloaded methods, only generate one accessor | |
553 ('overload_index' not in method or method['overload_index'] == 1)) | |
554 | |
555 generate_method_native_entries(interface, methods, 'Method') | |
556 | |
557 context.update({ | |
558 'has_origin_safe_method_setter': any( | |
559 method['is_check_security_for_frame'] and not method['is_read_only'] | |
560 for method in methods), | |
561 'has_method_configuration': any(method['do_generate_method_configuration
'] for method in methods), | |
562 'has_per_context_enabled_methods': any(method['per_context_enabled_funct
ion'] for method in methods), | |
563 'methods': methods, | |
564 }) | |
565 | |
566 context.update({ | |
567 'indexed_property_getter': indexed_property_getter(interface), | |
568 'indexed_property_setter': indexed_property_setter(interface), | |
569 'indexed_property_deleter': v8_interface.indexed_property_deleter(interf
ace), | |
570 'is_override_builtins': 'OverrideBuiltins' in extended_attributes, | |
571 'named_property_getter': named_property_getter(interface), | |
572 'named_property_setter': named_property_setter(interface), | |
573 'named_property_deleter': v8_interface.named_property_deleter(interface)
, | |
574 }) | |
575 | |
576 generate_native_entries_for_specials(interface, context) | |
577 | |
578 native_entries = generate_interface_native_entries(context) | |
579 | |
580 context.update({ | |
581 'native_entries': native_entries, | |
582 }) | |
583 | |
584 return context | |
585 | |
586 | |
587 def generate_interface_native_entries(context): | |
588 entries = {} | |
589 | |
590 def add(ne): | |
591 entries[ne['blink_entry']] = ne | |
592 | |
593 def addAll(nes): | |
594 for ne in nes: | |
595 add(ne) | |
596 | |
597 for constructor in context['constructors']: | |
598 addAll(constructor['native_entries']) | |
599 for constructor in context['custom_constructors']: | |
600 addAll(constructor['native_entries']) | |
601 if context['named_constructor']: | |
602 addAll(context['named_constructor']['native_entries']) | |
603 if context['event_constructor']: | |
604 addAll(context['event_constructor']['native_entries']) | |
605 for method in context['methods']: | |
606 addAll(method['native_entries']) | |
607 for attribute in context['attributes']: | |
608 add(attribute['native_entry_getter']) | |
609 if not attribute['is_read_only'] or attribute['put_forwards']: | |
610 add(attribute['native_entry_setter']) | |
611 if context['indexed_property_getter']: | |
612 addAll(context['indexed_property_getter']['native_entries']) | |
613 if context['indexed_property_setter']: | |
614 addAll(context['indexed_property_setter']['native_entries']) | |
615 if context['indexed_property_deleter']: | |
616 addAll(context['indexed_property_deleter']['native_entries']) | |
617 if context['named_property_getter']: | |
618 addAll(context['named_property_getter']['native_entries']) | |
619 if context['named_property_setter']: | |
620 addAll(context['named_property_setter']['native_entries']) | |
621 if context['named_property_deleter']: | |
622 addAll(context['named_property_deleter']['native_entries']) | |
623 return list(entries.values()) | |
624 | |
625 | |
626 def generate_method_native_entry(interface, method, count, kind): | |
627 name = method.get('name') | |
628 is_static = bool(method.get('is_static')) | |
629 native_entry = \ | |
630 DartUtilities.generate_native_entry(interface.name, name, | |
631 kind, is_static, count) | |
632 return native_entry | |
633 | |
634 | |
635 def generate_method_native_entries(interface, methods, kind): | |
636 for method in methods: | |
637 native_entries = [] | |
638 arg_count = method['number_of_arguments'] | |
639 min_arg_count = method['number_of_required_arguments'] | |
640 lb = min_arg_count - 2 if min_arg_count > 2 else 0 | |
641 for x in range(lb, arg_count + 3): | |
642 native_entry = \ | |
643 generate_method_native_entry(interface, method, x, kind) | |
644 native_entries.append(native_entry) | |
645 | |
646 method.update({'native_entries': native_entries}) | |
647 | |
648 | |
649 ################################################################################ | |
650 # Overloads | |
651 ################################################################################ | |
652 | |
653 def compute_method_overloads_context(methods): | |
654 # Regular methods | |
655 compute_method_overloads_context_by_type([method for method in methods | |
656 if not method['is_static']]) | |
657 # Static methods | |
658 compute_method_overloads_context_by_type([method for method in methods | |
659 if method['is_static']]) | |
660 | |
661 | |
662 def compute_method_overloads_context_by_type(methods): | |
663 """Computes |method.overload*| template values. | |
664 | |
665 Called separately for static and non-static (regular) methods, | |
666 as these are overloaded separately. | |
667 Modifies |method| in place for |method| in |methods|. | |
668 Doesn't change the |methods| list itself (only the values, i.e. individual | |
669 methods), so ok to treat these separately. | |
670 """ | |
671 # Add overload information only to overloaded methods, so template code can | |
672 # easily verify if a function is overloaded | |
673 for name, overloads in v8_interface.method_overloads_by_name(methods): | |
674 # Resolution function is generated after last overloaded function; | |
675 # package necessary information into |method.overloads| for that method. | |
676 overloads[-1]['overloads'] = overloads_context(overloads) | |
677 overloads[-1]['overloads']['name'] = name | |
678 | |
679 | |
680 def overloads_context(overloads): | |
681 """Returns |overloads| template values for a single name. | |
682 | |
683 Sets |method.overload_index| in place for |method| in |overloads| | |
684 and returns dict of overall overload template values. | |
685 """ | |
686 assert len(overloads) > 1 # only apply to overloaded names | |
687 for index, method in enumerate(overloads, 1): | |
688 method['overload_index'] = index | |
689 | |
690 effective_overloads_by_length = v8_interface.effective_overload_set_by_lengt
h(overloads) | |
691 lengths = [length for length, _ in effective_overloads_by_length] | |
692 name = overloads[0].get('name', '<constructor>') | |
693 | |
694 # Check and fail if all overloads with the shortest acceptable arguments | |
695 # list are runtime enabled, since we would otherwise set 'length' on the | |
696 # function object to an incorrect value when none of those overloads were | |
697 # actually enabled at runtime. The exception is if all overloads are | |
698 # controlled by the same runtime enabled feature, in which case there would | |
699 # be no function object at all if it is not enabled. | |
700 shortest_overloads = effective_overloads_by_length[0][1] | |
701 if (all(method.get('runtime_enabled_function') | |
702 for method, _, _ in shortest_overloads) and | |
703 not v8_interface.common_value(overloads, 'runtime_enabled_function')): | |
704 raise ValueError('Function.length of %s depends on runtime enabled featu
res' % name) | |
705 | |
706 return { | |
707 'deprecate_all_as': v8_interface.common_value(overloads, 'deprecate_as')
, # [DeprecateAs] | |
708 'exposed_test_all': v8_interface.common_value(overloads, 'exposed_test')
, # [Exposed] | |
709 'length_tests_methods': length_tests_methods(effective_overloads_by_leng
th), | |
710 # 1. Let maxarg be the length of the longest type list of the | |
711 # entries in S. | |
712 'maxarg': lengths[-1], | |
713 'measure_all_as': v8_interface.common_value(overloads, 'measure_as'), #
[MeasureAs] | |
714 'minarg': lengths[0], | |
715 'per_context_enabled_function_all': v8_interface.common_value(overloads,
'per_context_enabled_function'), # [PerContextEnabled] | |
716 'runtime_enabled_function_all': v8_interface.common_value(overloads, 'ru
ntime_enabled_function'), # [RuntimeEnabled] | |
717 'valid_arities': lengths | |
718 # Only need to report valid arities if there is a gap in the | |
719 # sequence of possible lengths, otherwise invalid length means | |
720 # "not enough arguments". | |
721 if lengths[-1] - lengths[0] != len(lengths) - 1 else None, | |
722 } | |
723 | |
724 | |
725 def length_tests_methods(effective_overloads_by_length): | |
726 """Returns sorted list of resolution tests and associated methods, by length
. | |
727 | |
728 This builds the main data structure for the overload resolution loop. | |
729 For a given argument length, bindings test argument at distinguishing | |
730 argument index, in order given by spec: if it is compatible with | |
731 (optionality or) type required by an overloaded method, resolve to that | |
732 method. | |
733 | |
734 Returns: | |
735 [(length, [(test, method)])] | |
736 """ | |
737 return [(length, list(resolution_tests_methods(effective_overloads))) | |
738 for length, effective_overloads in effective_overloads_by_length] | |
739 | |
740 | |
741 DART_CHECK_TYPE = { | |
742 'ArrayBufferView': 'Dart_IsTypedData({cpp_value})', | |
743 'ArrayBuffer': 'Dart_IsByteBuffer({cpp_value})', | |
744 'Uint8Array': 'DartUtilities::isUint8Array({cpp_value})', | |
745 'Uint8ClampedArray': 'DartUtilities::isUint8ClampedArray({cpp_value})', | |
746 } | |
747 | |
748 | |
749 def resolution_tests_methods(effective_overloads): | |
750 """Yields resolution test and associated method, in resolution order, for ef
fective overloads of a given length. | |
751 | |
752 This is the heart of the resolution algorithm. | |
753 http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm | |
754 | |
755 Note that a given method can be listed multiple times, with different tests! | |
756 This is to handle implicit type conversion. | |
757 | |
758 Returns: | |
759 [(test, method)] | |
760 """ | |
761 methods = [effective_overload[0] | |
762 for effective_overload in effective_overloads] | |
763 if len(methods) == 1: | |
764 # If only one method with a given length, no test needed | |
765 yield 'true', methods[0] | |
766 return | |
767 | |
768 # 6. If there is more than one entry in S, then set d to be the | |
769 # distinguishing argument index for the entries of S. | |
770 index = v8_interface.distinguishing_argument_index(effective_overloads) | |
771 # (7-9 are for handling |undefined| values for optional arguments before | |
772 # the distinguishing argument (as "missing"), so you can specify only some | |
773 # optional arguments. We don't support this, so we skip these steps.) | |
774 # 10. If i = d, then: | |
775 # (d is the distinguishing argument index) | |
776 # 1. Let V be argi. | |
777 # Note: This is the argument that will be used to resolve which | |
778 # overload is selected. | |
779 cpp_value = 'Dart_GetNativeArgument(args, %s + argOffset)' % index | |
780 | |
781 # Extract argument and IDL type to simplify accessing these in each loop. | |
782 arguments = [method['arguments'][index] for method in methods] | |
783 arguments_methods = zip(arguments, methods) | |
784 idl_types = [argument['idl_type_object'] for argument in arguments] | |
785 idl_types_methods = zip(idl_types, methods) | |
786 | |
787 # We can't do a single loop through all methods or simply sort them, because | |
788 # a method may be listed in multiple steps of the resolution algorithm, and | |
789 # which test to apply differs depending on the step. | |
790 # | |
791 # Instead, we need to go through all methods at each step, either finding | |
792 # first match (if only one test is allowed) or filtering to matches (if | |
793 # multiple tests are allowed), and generating an appropriate tests. | |
794 | |
795 # 2. If V is undefined, and there is an entry in S whose list of | |
796 # optionality values has "optional" at index i, then remove from S all | |
797 # other entries. | |
798 try: | |
799 method = next(method for argument, method in arguments_methods | |
800 if argument['is_optional']) | |
801 test = 'Dart_IsNull(%s)' % cpp_value | |
802 yield test, method | |
803 except StopIteration: | |
804 pass | |
805 | |
806 # 3. Otherwise: if V is null or undefined, and there is an entry in S that | |
807 # has one of the following types at position i of its type list, | |
808 # - a nullable type | |
809 try: | |
810 method = next(method for idl_type, method in idl_types_methods | |
811 if idl_type.is_nullable) | |
812 test = 'Dart_IsNull(%s)' % cpp_value | |
813 yield test, method | |
814 except StopIteration: | |
815 pass | |
816 | |
817 # 4. Otherwise: if V is a platform object - but not a platform array | |
818 # object - and there is an entry in S that has one of the following | |
819 # types at position i of its type list, | |
820 # - an interface type that V implements | |
821 # (Unlike most of these tests, this can return multiple methods, since we | |
822 # test if it implements an interface. Thus we need a for loop, not a next.) | |
823 # (We distinguish wrapper types from built-in interface types.) | |
824 for idl_type, method in ((idl_type, method) | |
825 for idl_type, method in idl_types_methods | |
826 if idl_type.is_wrapper_type): | |
827 fmtstr = 'Dart{idl_type}::hasInstance({cpp_value})' | |
828 if idl_type.base_type in DART_CHECK_TYPE: | |
829 fmtstr = DART_CHECK_TYPE[idl_type.base_type] | |
830 test = fmtstr.format(idl_type=idl_type.base_type, cpp_value=cpp_value) | |
831 yield test, method | |
832 | |
833 # 8. Otherwise: if V is any kind of object except for a native Date object, | |
834 # a native RegExp object, and there is an entry in S that has one of the | |
835 # following types at position i of its type list, | |
836 # - an array type | |
837 # - a sequence type | |
838 # ... | |
839 # - a dictionary | |
840 try: | |
841 # FIXME: IDL dictionary not implemented, so use Blink Dictionary | |
842 # http://crbug.com/321462 | |
843 idl_type, method = next((idl_type, method) | |
844 for idl_type, method in idl_types_methods | |
845 if (idl_type.native_array_element_type or | |
846 idl_type.name == 'Dictionary')) | |
847 if idl_type.native_array_element_type: | |
848 # (We test for Array instead of generic Object to type-check.) | |
849 # FIXME: test for Object during resolution, then have type check for | |
850 # Array in overloaded method: http://crbug.com/262383 | |
851 test = 'Dart_IsList(%s)' % cpp_value | |
852 else: | |
853 # FIXME: should be '{1}->IsObject() && !{1}->IsDate() && !{1}->IsReg
Exp()'.format(cpp_value) | |
854 # FIXME: the IsDate and IsRegExp checks can be skipped if we've | |
855 # already generated tests for them. | |
856 test = 'Dart_IsInstance(%s)' % cpp_value | |
857 yield test, method | |
858 except StopIteration: | |
859 pass | |
860 | |
861 # (Check for exact type matches before performing automatic type conversion; | |
862 # only needed if distinguishing between primitive types.) | |
863 if len([idl_type.is_primitive_type for idl_type in idl_types]) > 1: | |
864 # (Only needed if match in step 11, otherwise redundant.) | |
865 if any(idl_type.is_string_type or idl_type.is_enum | |
866 for idl_type in idl_types): | |
867 # 10. Otherwise: if V is a Number value, and there is an entry in S | |
868 # that has one of the following types at position i of its type | |
869 # list, | |
870 # - a numeric type | |
871 try: | |
872 method = next(method for idl_type, method in idl_types_methods | |
873 if idl_type.is_numeric_type) | |
874 test = 'Dart_IsNumber(%s)' % cpp_value | |
875 yield test, method | |
876 except StopIteration: | |
877 pass | |
878 | |
879 # (Perform automatic type conversion, in order. If any of these match, | |
880 # that's the end, and no other tests are needed.) To keep this code simple, | |
881 # we rely on the C++ compiler's dead code elimination to deal with the | |
882 # redundancy if both cases below trigger. | |
883 | |
884 # 11. Otherwise: if there is an entry in S that has one of the following | |
885 # types at position i of its type list, | |
886 # - DOMString | |
887 # - ByteString | |
888 # - ScalarValueString [a DOMString typedef, per definition.] | |
889 # - an enumeration type | |
890 try: | |
891 method = next(method for idl_type, method in idl_types_methods | |
892 if idl_type.is_string_type or idl_type.is_enum) | |
893 yield 'true', method | |
894 except StopIteration: | |
895 pass | |
896 | |
897 # 12. Otherwise: if there is an entry in S that has one of the following | |
898 # types at position i of its type list, | |
899 # - a numeric type | |
900 try: | |
901 method = next(method for idl_type, method in idl_types_methods | |
902 if idl_type.is_numeric_type) | |
903 yield 'true', method | |
904 except StopIteration: | |
905 pass | |
906 | |
907 | |
908 ################################################################################ | |
909 # Constructors | |
910 ################################################################################ | |
911 | |
912 # [Constructor] | |
913 def custom_constructor_context(interface, constructor): | |
914 return { | |
915 'arguments': [custom_constructor_argument(argument, index) | |
916 for index, argument in enumerate(constructor.arguments)], | |
917 'auto_scope': 'true', | |
918 'is_auto_scope': True, | |
919 'is_call_with_script_arguments': False, | |
920 'is_custom': True, | |
921 'number_of_arguments': len(constructor.arguments), | |
922 'number_of_required_arguments': | |
923 v8_interface.number_of_required_arguments(constructor), | |
924 } | |
925 | |
926 | |
927 # We don't need much from this - just the idl_type_objects and preproceed_type | |
928 # to use in generating the resolver strings. | |
929 def custom_constructor_argument(argument, index): | |
930 return { | |
931 'idl_type_object': argument.idl_type, | |
932 'name': argument.name, | |
933 'preprocessed_type': str(argument.idl_type.preprocessed_type), | |
934 } | |
935 | |
936 | |
937 # [Constructor] | |
938 def constructor_context(interface, constructor): | |
939 return { | |
940 'arguments': [dart_methods.argument_context(interface, constructor, argu
ment, index) | |
941 for index, argument in enumerate(constructor.arguments)], | |
942 'auto_scope': 'true', | |
943 'cpp_value': dart_methods.cpp_value( | |
944 interface, constructor, len(constructor.arguments)), | |
945 'has_exception_state': | |
946 # [RaisesException=Constructor] | |
947 interface.extended_attributes.get('RaisesException') == 'Constructor
' or | |
948 any(argument for argument in constructor.arguments | |
949 if argument.idl_type.name == 'SerializedScriptValue' or | |
950 argument.idl_type.is_integer_type), | |
951 'is_auto_scope': True, | |
952 'is_call_with_script_arguments': False, | |
953 'is_constructor': True, | |
954 'is_custom': False, | |
955 'is_variadic': False, # Required for overload resolution | |
956 'number_of_required_arguments': | |
957 v8_interface.number_of_required_arguments(constructor), | |
958 'number_of_arguments': len(constructor.arguments), | |
959 } | |
960 | |
961 | |
962 # [NamedConstructor] | |
963 def generate_named_constructor(interface): | |
964 extended_attributes = interface.extended_attributes | |
965 if 'NamedConstructor' not in extended_attributes: | |
966 return None | |
967 # FIXME: parser should return named constructor separately; | |
968 # included in constructors (and only name stored in extended attribute) | |
969 # for Perl compatibility | |
970 idl_constructor = interface.constructors[0] | |
971 constructor = constructor_context(interface, idl_constructor) | |
972 # FIXME(vsm): We drop the name. We don't use this in Dart APIs right now. | |
973 # We probably need to encode this somehow to deal with conflicts. | |
974 # constructor['name'] = extended_attributes['NamedConstructor'] | |
975 return constructor | |
976 | |
977 | |
978 ################################################################################ | |
979 # Special operations (methods) | |
980 # http://heycam.github.io/webidl/#idl-special-operations | |
981 ################################################################################ | |
982 | |
983 def property_getter(getter, cpp_arguments): | |
984 def is_null_expression(idl_type): | |
985 if idl_type.is_union_type: | |
986 return ' && '.join('!result%sEnabled' % i | |
987 for i, _ in enumerate(idl_type.member_types)) | |
988 if idl_type.name == 'String': | |
989 # FIXME(vsm): This looks V8 specific. | |
990 return 'result.isNull()' | |
991 if idl_type.is_interface_type: | |
992 return '!result' | |
993 return '' | |
994 | |
995 context = v8_interface.property_getter(getter, []) | |
996 | |
997 idl_type = getter.idl_type | |
998 extended_attributes = getter.extended_attributes | |
999 is_raises_exception = 'RaisesException' in extended_attributes | |
1000 | |
1001 # FIXME: make more generic, so can use dart_methods.cpp_value | |
1002 cpp_method_name = 'receiver->%s' % DartUtilities.cpp_name(getter) | |
1003 | |
1004 if is_raises_exception: | |
1005 cpp_arguments.append('es') | |
1006 union_arguments = idl_type.union_arguments | |
1007 if union_arguments: | |
1008 cpp_arguments.extend([member_argument['cpp_value'] | |
1009 for member_argument in union_arguments]) | |
1010 | |
1011 cpp_value = '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments)) | |
1012 | |
1013 context.update({ | |
1014 'cpp_type': idl_type.cpp_type, | |
1015 'cpp_value': cpp_value, | |
1016 'is_null_expression': is_null_expression(idl_type), | |
1017 'is_raises_exception': is_raises_exception, | |
1018 'name': DartUtilities.cpp_name(getter), | |
1019 'union_arguments': union_arguments, | |
1020 'dart_set_return_value': idl_type.dart_set_return_value('result', | |
1021 extended_attribu
tes=extended_attributes, | |
1022 script_wrappable
='receiver', | |
1023 release=idl_type
.release)}) | |
1024 return context | |
1025 | |
1026 | |
1027 def property_setter(setter): | |
1028 context = v8_interface.property_setter(setter) | |
1029 | |
1030 idl_type = setter.arguments[1].idl_type | |
1031 extended_attributes = setter.extended_attributes | |
1032 | |
1033 context.update({ | |
1034 'dart_value_to_local_cpp_value': idl_type.dart_value_to_local_cpp_value( | |
1035 extended_attributes, 'propertyValue', False, | |
1036 context['has_type_checking_interface']), | |
1037 }) | |
1038 | |
1039 return context | |
1040 | |
1041 | |
1042 ################################################################################ | |
1043 # Indexed properties | |
1044 # http://heycam.github.io/webidl/#idl-indexed-properties | |
1045 ################################################################################ | |
1046 | |
1047 def indexed_property_getter(interface): | |
1048 try: | |
1049 # Find indexed property getter, if present; has form: | |
1050 # getter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1) | |
1051 getter = next( | |
1052 method | |
1053 for method in interface.operations | |
1054 if ('getter' in method.specials and | |
1055 len(method.arguments) == 1 and | |
1056 str(method.arguments[0].idl_type) == 'unsigned long')) | |
1057 except StopIteration: | |
1058 return None | |
1059 | |
1060 getter.name = getter.name or 'anonymousIndexedGetter' | |
1061 | |
1062 return property_getter(getter, ['index']) | |
1063 | |
1064 | |
1065 def indexed_property_setter(interface): | |
1066 try: | |
1067 # Find indexed property setter, if present; has form: | |
1068 # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1, ARG_TYPE
ARG2) | |
1069 setter = next( | |
1070 method | |
1071 for method in interface.operations | |
1072 if ('setter' in method.specials and | |
1073 len(method.arguments) == 2 and | |
1074 str(method.arguments[0].idl_type) == 'unsigned long')) | |
1075 except StopIteration: | |
1076 return None | |
1077 | |
1078 return property_setter(setter) | |
1079 | |
1080 | |
1081 ################################################################################ | |
1082 # Named properties | |
1083 # http://heycam.github.io/webidl/#idl-named-properties | |
1084 ################################################################################ | |
1085 | |
1086 def named_property_getter(interface): | |
1087 try: | |
1088 # Find named property getter, if present; has form: | |
1089 # getter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1) | |
1090 getter = next( | |
1091 method | |
1092 for method in interface.operations | |
1093 if ('getter' in method.specials and | |
1094 len(method.arguments) == 1 and | |
1095 str(method.arguments[0].idl_type) == 'DOMString')) | |
1096 except StopIteration: | |
1097 return None | |
1098 | |
1099 getter.name = getter.name or 'anonymousNamedGetter' | |
1100 | |
1101 return property_getter(getter, ['propertyName']) | |
1102 | |
1103 | |
1104 def named_property_setter(interface): | |
1105 try: | |
1106 # Find named property setter, if present; has form: | |
1107 # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1, ARG_TYPE ARG2
) | |
1108 setter = next( | |
1109 method | |
1110 for method in interface.operations | |
1111 if ('setter' in method.specials and | |
1112 len(method.arguments) == 2 and | |
1113 str(method.arguments[0].idl_type) == 'DOMString')) | |
1114 except StopIteration: | |
1115 return None | |
1116 | |
1117 return property_setter(setter) | |
1118 | |
1119 | |
1120 def generate_native_entries_for_specials(interface, context): | |
1121 def add(prop, name, arity): | |
1122 if context[prop]: | |
1123 if 'native_entries' not in context[prop]: | |
1124 context[prop].update({'native_entries': []}) | |
1125 context[prop]['native_entries'].append( | |
1126 DartUtilities.generate_native_entry( | |
1127 interface.name, name, 'Method', False, arity)) | |
1128 | |
1129 pre = ['indexed_property', 'named_property'] | |
1130 post = [('setter', '__setter__', 2), | |
1131 ('getter', '__getter__', 1), | |
1132 ('deleter', '__delete__', 1), | |
1133 ] | |
1134 props = [(p1 + "_" + p2, name, arity) | |
1135 for (p1, (p2, name, arity)) in itertools.product(pre, post)] | |
1136 for t in props: | |
1137 add(*t) | |
1138 | |
1139 for (p, name, arity) in props: | |
1140 if context[p]: | |
1141 if context[p].get('is_custom_property_query'): | |
1142 add(p, '__propertyQuery__', 1) | |
OLD | NEW |