OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
3 # for details. All rights reserved. Use of this source code is governed by a | 3 # for details. All rights reserved. Use of this source code is governed by a |
4 # BSD-style license that can be found in the LICENSE file. | 4 # BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 """This module provides shared functionality for the system to generate | 6 """This module provides shared functionality for the system to generate |
7 Dart:html APIs from the IDL database.""" | 7 Dart:html APIs from the IDL database.""" |
8 | 8 |
9 import os | 9 import os |
10 from generator import * | 10 from generator import * |
11 from systembase import * | 11 from systembase import * |
12 from systemfrog import * | 12 from systemfrog import * |
13 from systeminterface import * | 13 from systeminterface import * |
sra1
2012/02/29 23:11:55
Are you using this import?
You could comment it o
Jacob
2012/03/01 00:40:44
Done.
| |
14 from systemwrapping import * | |
sra1
2012/02/29 23:11:55
Are you using this import?
Jacob
2012/03/01 00:40:44
Done.
| |
14 | 15 |
15 # Members from the standard dom that should not be exposed publicly in dart:html | 16 # Members from the standard dom that should not be exposed publicly in dart:html |
16 # but need to be exposed internally to implement dart:html on top of a standard | 17 # but need to be exposed internally to implement dart:html on top of a standard |
17 # browser. | 18 # browser. |
18 _private_html_members = { | 19 _private_html_members = set([ |
19 'Element': set(['clientLeft', 'clientTop', 'clientWidth', 'clientHeight', | 20 'Element.clientLeft', |
20 'offsetLeft', 'offsetTop', 'offsetWidth', 'offsetHeight', | 21 'Element.clientTop', |
21 'scrollLeft', 'scrollTop', 'scrollWidth', 'scrollHeight', | 22 'Element.clientWidth', |
22 'childElementCount', 'firstElementChild', 'hasAttribute', | 23 'Element.clientHeight', |
23 'getAttribute', 'removeAttribute', 'setAttribute', 'className', | 24 'Element.offsetLeft', |
24 'children']), | 25 'Element.offsetTop', |
25 'Node' : set(['appendChild', 'removeChild', 'replaceChild', 'attributes', | 26 'Element.offsetWidth', |
26 'childNodes']), | 27 'Element.offsetHeight', |
27 # TODO(jacobr): other direct translate methods on node such as | 28 'Element.scrollLeft', |
28 # textContext->text | 29 'Element.scrollTop', |
29 'Document': set(['createElement', 'createEvent']), | 30 'Element.scrollWidth', |
30 'Window': set(['getComputedStyle']), | 31 'Element.scrollHeight', |
31 'EventTarget': set(['removeEventListener', 'addEventListener', | 32 'Element.childElementCount', |
32 'dispatchEvent']), | 33 'Element.firstElementChild', |
33 'Event': set(['initEvent', 'target', 'srcElement', 'currentTarget']) | 34 'Element.hasAttribute', |
34 } | 35 'Element.getAttribute', |
36 'Element.removeAttribute', | |
37 'Element.setAttribute', | |
38 'Element.className', | |
39 'Element.children', | |
40 'Element.querySelectorAll', | |
41 'Document.querySelectorAll', | |
42 'Element.getBoundingClientRect', | |
43 'Element.getClientRects', | |
44 'Node.appendChild', | |
45 'Node.removeChild', | |
46 'Node.replaceChild', | |
47 'Node.attributes', | |
48 'Node.childNodes', | |
49 'Document.createElement', | |
50 'Document.createEvent', | |
51 'Document.createTextNode', | |
52 'Document.createTouchList', | |
53 'Window.getComputedStyle', | |
54 'EventTarget.removeEventListener', | |
55 'EventTarget.addEventListener', | |
56 'EventTarget.dispatchEvent', | |
57 'Event.initEvent', | |
58 'MouseEvent.initMouseEvent', | |
59 ]) | |
35 | 60 |
36 # Members from the standard dom that exist in the dart:html library with | 61 # Members from the standard dom that exist in the dart:html library with |
37 # identical functionality but with cleaner names. | 62 # identical functionality but with cleaner names. |
38 html_library_renames = { | 63 _html_library_renames = { |
39 'Document.createTextNode': 'Text.Text', | 64 'Document.defaultView': 'window', |
40 'Document.get:defaultView': 'Document.get:window', | 65 'DocumentFragment.querySelector': 'query', |
41 'DocumentFragment.querySelector': 'Element.query', | 66 'Element.querySelector': 'query', |
42 'Element.querySelector': 'Element.query', | 67 'Element.webkitMatchesSelector' : 'matchesSelector', |
43 'Document.querySelector': 'Element.query', | 68 'Element.scrollIntoViewIfNeeded': 'scrollIntoView', |
44 'DocumentFragment.querySelectorAll': 'Element.queryAll', | 69 'Document.querySelector': 'query', |
45 'DocumentFragment.querySelectorAll': 'Element.queryAll', | 70 'DocumentFragment.querySelectorAll': 'queryAll', |
46 'Element.querySelectorAll': 'Element.queryAll', | 71 'DocumentFragment.querySelectorAll': 'queryAll', |
47 'Element.scrollIntoViewIfNeeded': 'Element.scrollIntoView', | 72 'Node.cloneNode': 'clone', |
48 'Node.cloneNode': 'Node.clone', | 73 'Node.nextSibling': 'nextNode', |
49 'Node.get:nextSibling': 'Node.get:nextNode', | 74 'Node.ownerDocument': 'document', |
50 'Node.get:ownerDocument': 'Node.get:document', | 75 'Node.parentNode': 'parent', |
51 'Node.get:parentNode': 'Node.get:parent', | 76 'Node.previousSibling': 'previousNode', |
52 'Node.get:previousSibling': 'Node.get:previousNode', | 77 'Node.textContent': 'text', |
53 } | 78 } |
54 | 79 |
80 #TODO(jacobr): inject annotations into the interfaces based on this table and | |
81 # on _html_library_renames. | |
82 _injected_doc_fragments = { | |
83 'Element.query': ' /** @domName querySelector, Document.getElementById */', | |
84 } | |
55 # Members and classes from the dom that should be removed completelly from | 85 # Members and classes from the dom that should be removed completelly from |
56 # dart:html. These could be expressed in the IDL instead but expressing this | 86 # dart:html. These could be expressed in the IDL instead but expressing this |
57 # as a simple table instead is more concise. | 87 # as a simple table instead is more concise. |
58 # TODO(jacobr): cleanup and augment this list. | 88 # TODO(jacobr): cleanup and augment this list. |
59 _html_library_remove = set([ | 89 _html_library_remove = set([ |
60 'Window.get:document', # Removed as we have a custom implementation. | 90 'Window.get:document', # Removed as we have a custom implementation. |
61 'NodeList.item', | 91 'NodeList.item', |
62 "Attr.*", | 92 "Attr.*", |
63 # "BarProp.*", | 93 # "BarProp.*", |
64 # "BarInfo.*", | 94 # "BarInfo.*", |
(...skipping 12 matching lines...) Expand all Loading... | |
77 "Document.get:forms", | 107 "Document.get:forms", |
78 # "Document.get:selectedStylesheetSet", | 108 # "Document.get:selectedStylesheetSet", |
79 # "Document.set:selectedStylesheetSet", | 109 # "Document.set:selectedStylesheetSet", |
80 # "Document.get:preferredStylesheetSet", | 110 # "Document.get:preferredStylesheetSet", |
81 "Document.get:links", | 111 "Document.get:links", |
82 "Document.getElementsByTagName", | 112 "Document.getElementsByTagName", |
83 "Document.set:domain", | 113 "Document.set:domain", |
84 "Document.get:implementation", | 114 "Document.get:implementation", |
85 "Document.createAttributeNS", | 115 "Document.createAttributeNS", |
86 "Document.get:inputEncoding", | 116 "Document.get:inputEncoding", |
117 "Document.getElementById", | |
87 "Document.getElementsByClassName", | 118 "Document.getElementsByClassName", |
119 "Element.getElementsByClassName", | |
120 "Element.getElementsByTagNameNS", | |
121 "Element.getElementsByTagName", | |
88 "Document.get:compatMode", | 122 "Document.get:compatMode", |
89 "Document.importNode", | 123 "Document.importNode", |
90 "Document.evaluate", | 124 "Document.evaluate", |
91 "Document.get:images", | 125 "Document.get:images", |
92 "Document.querySelector", | 126 "Document.querySelector", |
93 "Document.createExpression", | 127 "Document.createExpression", |
94 "Document.getOverrideStyle", | 128 "Document.getOverrideStyle", |
95 "Document.get:xmlStandalone", | 129 "Document.get:xmlStandalone", |
96 "Document.set:xmlStandalone", | 130 "Document.set:xmlStandalone", |
97 "Document.createComment", | 131 "Document.createComment", |
(...skipping 25 matching lines...) Expand all Loading... | |
123 "DocumentType.*", | 157 "DocumentType.*", |
124 "Element.hasAttributeNS", | 158 "Element.hasAttributeNS", |
125 "Element.getAttributeNS", | 159 "Element.getAttributeNS", |
126 "Element.setAttributeNode", | 160 "Element.setAttributeNode", |
127 "Element.getAttributeNode", | 161 "Element.getAttributeNode", |
128 "Element.removeAttributeNode", | 162 "Element.removeAttributeNode", |
129 "Element.removeAttributeNS", | 163 "Element.removeAttributeNS", |
130 "Element.setAttributeNodeNS", | 164 "Element.setAttributeNodeNS", |
131 "Element.getAttributeNodeNS", | 165 "Element.getAttributeNodeNS", |
132 "Element.setAttributeNS", | 166 "Element.setAttributeNS", |
167 "BodyElement.text", | |
168 "AnchorElement.text", | |
169 "OptionElement.text", | |
170 "ScriptElement.text", | |
171 "TitleElement.text", | |
133 # "EventSource.get:url", | 172 # "EventSource.get:url", |
134 # TODO(jacobr): should these be removed? | 173 # TODO(jacobr): should these be removed? |
135 "Document.close", | 174 "Document.close", |
136 "Document.hasFocus", | 175 "Document.hasFocus", |
137 | 176 |
138 "Document.get:vlinkColor", | 177 "Document.get:vlinkColor", |
139 "Document.set:vlinkColor", | 178 "Document.set:vlinkColor", |
140 "Document.captureEvents", | 179 "Document.captureEvents", |
141 "Document.releaseEvents", | 180 "Document.releaseEvents", |
142 "Document.get:compatMode", | 181 "Document.get:compatMode", |
(...skipping 12 matching lines...) Expand all Loading... | |
155 "Document.get:alinkColor", | 194 "Document.get:alinkColor", |
156 "Document.set:alinkColor", | 195 "Document.set:alinkColor", |
157 "Document.get:embeds", | 196 "Document.get:embeds", |
158 "Document.open", | 197 "Document.open", |
159 "Document.clear", | 198 "Document.clear", |
160 "Document.get:scripts", | 199 "Document.get:scripts", |
161 "Document.writeln", | 200 "Document.writeln", |
162 "Document.get:linkColor", | 201 "Document.get:linkColor", |
163 "Document.set:linkColor", | 202 "Document.set:linkColor", |
164 "Element.get:itemRef", | 203 "Element.get:itemRef", |
165 "Element.set:className", | |
166 "Element.get:outerText", | 204 "Element.get:outerText", |
167 "Element.set:outerText", | 205 "Element.set:outerText", |
168 "Element.get:accessKey", | 206 "Element.get:accessKey", |
169 "Element.set:accessKey", | 207 "Element.set:accessKey", |
170 "Element.get:itemType", | 208 "Element.get:itemType", |
171 "Element.get:innerText", | 209 "Element.get:innerText", |
172 "Element.set:innerText", | 210 "Element.set:innerText", |
173 "Element.set:outerHTML", | 211 "Element.set:outerHTML", |
174 "Element.get:itemScope", | 212 "Element.get:itemScope", |
175 "Element.set:itemScope", | 213 "Element.set:itemScope", |
176 "Element.get:itemValue", | 214 "Element.get:itemValue", |
177 "Element.set:itemValue", | 215 "Element.set:itemValue", |
178 "Element.get:itemId", | 216 "Element.get:itemId", |
179 "Element.set:itemId", | 217 "Element.set:itemId", |
180 "Element.get:itemProp", | 218 "Element.get:itemProp", |
219 'Element.scrollIntoView', | |
181 "EmbedElement.getSVGDocument", | 220 "EmbedElement.getSVGDocument", |
182 "FormElement.get:elements", | 221 "FormElement.get:elements", |
183 "HTMLFrameElement.*", | 222 "HTMLFrameElement.*", |
184 "HTMLFrameSetElement.*", | 223 "HTMLFrameSetElement.*", |
185 "HTMLHtmlElement.get:version", | 224 "HTMLHtmlElement.get:version", |
186 "HTMLHtmlElement.set:version", | 225 "HTMLHtmlElement.set:version", |
187 # "IFrameElement.getSVGDocument", #TODO(jacobr): should this be removed | 226 # "IFrameElement.getSVGDocument", #TODO(jacobr): should this be removed |
188 "InputElement.get:dirName", | 227 "InputElement.get:dirName", |
189 "InputElement.set:dirName", | 228 "InputElement.set:dirName", |
190 "HTMLIsIndexElement.*", | 229 "HTMLIsIndexElement.*", |
191 "ObjectElement.getSVGDocument", | 230 "ObjectElement.getSVGDocument", |
192 "HTMLOptionsCollection.*", | 231 "HTMLOptionsCollection.*", |
193 "HTMLPropertiesCollection.*", | 232 "HTMLPropertiesCollection.*", |
194 "SelectElement.remove", | 233 "SelectElement.remove", |
195 "TextAreaElement.get:dirName", | 234 "TextAreaElement.get:dirName", |
196 "TextAreaElement.set:dirName", | 235 "TextAreaElement.set:dirName", |
197 "NamedNodeMap.*", | 236 "NamedNodeMap.*", |
198 "Node.isEqualNode", | 237 "Node.isEqualNode", |
199 "Node.get:TEXT_NODE", | 238 "Node.get:TEXT_NODE", |
200 "Node.hasAttributes", | 239 "Node.hasAttributes", |
201 "Node.get:DOCUMENT_TYPE_NODE", | 240 "Node.get:DOCUMENT_TYPE_NODE", |
202 "Node.get:DOCUMENT_POSITION_FOLLOWING", | 241 "Node.get:DOCUMENT_POSITION_FOLLOWING", |
203 "Node.get:childNodes", | |
204 "Node.lookupNamespaceURI", | 242 "Node.lookupNamespaceURI", |
205 "Node.get:ELEMENT_NODE", | 243 "Node.get:ELEMENT_NODE", |
206 "Node.get:namespaceURI", | 244 "Node.get:namespaceURI", |
207 "Node.get:DOCUMENT_FRAGMENT_NODE", | 245 "Node.get:DOCUMENT_FRAGMENT_NODE", |
208 "Node.get:localName", | 246 "Node.get:localName", |
209 "Node.dispatchEvent", | 247 "Node.dispatchEvent", |
210 "Node.isDefaultNamespace", | 248 "Node.isDefaultNamespace", |
211 "Node.compareDocumentPosition", | 249 "Node.compareDocumentPosition", |
212 "Node.get:baseURI", | 250 "Node.get:baseURI", |
213 "Node.isSameNode", | 251 "Node.isSameNode", |
214 "Node.get:DOCUMENT_POSITION_DISCONNECTED", | 252 "Node.get:DOCUMENT_POSITION_DISCONNECTED", |
215 "Node.get:DOCUMENT_NODE", | 253 "Node.get:DOCUMENT_NODE", |
216 "Node.get:DOCUMENT_POSITION_CONTAINS", | 254 "Node.get:DOCUMENT_POSITION_CONTAINS", |
217 "Node.get:COMMENT_NODE", | 255 "Node.get:COMMENT_NODE", |
218 "Node.get:ENTITY_REFERENCE_NODE", | 256 "Node.get:ENTITY_REFERENCE_NODE", |
219 "Node.isSupported", | 257 "Node.isSupported", |
220 "Node.get:firstChild", | 258 "Node.get:firstChild", |
221 "Node.get:DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", | 259 "Node.get:DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", |
222 "Node.get:lastChild", | 260 "Node.get:lastChild", |
223 "Node.get:attributes", | |
224 "Node.get:NOTATION_NODE", | 261 "Node.get:NOTATION_NODE", |
225 "Node.normalize", | 262 "Node.normalize", |
226 "Node.get:parentElement", | 263 "Node.get:parentElement", |
227 "Node.get:ATTRIBUTE_NODE", | 264 "Node.get:ATTRIBUTE_NODE", |
228 "Node.get:ENTITY_NODE", | 265 "Node.get:ENTITY_NODE", |
229 "Node.get:DOCUMENT_POSITION_CONTAINED_BY", | 266 "Node.get:DOCUMENT_POSITION_CONTAINED_BY", |
230 "Node.get:prefix", | 267 "Node.get:prefix", |
231 "Node.set:prefix", | 268 "Node.set:prefix", |
232 "Node.get:DOCUMENT_POSITION_PRECEDING", | 269 "Node.get:DOCUMENT_POSITION_PRECEDING", |
233 "Node.get:nodeType", | 270 "Node.get:nodeType", |
(...skipping 18 matching lines...) Expand all Loading... | |
252 'Window': ['DOMContentLoaded'] | 289 'Window': ['DOMContentLoaded'] |
253 } | 290 } |
254 | 291 |
255 # These event names must be camel case when attaching event listeners | 292 # These event names must be camel case when attaching event listeners |
256 # using addEventListener even though the onEventName properties in the DOM for | 293 # using addEventListener even though the onEventName properties in the DOM for |
257 # them are not camel case. | 294 # them are not camel case. |
258 _on_attribute_to_event_name_mapping = { | 295 _on_attribute_to_event_name_mapping = { |
259 'webkitanimationend': 'webkitAnimationEnd', | 296 'webkitanimationend': 'webkitAnimationEnd', |
260 'webkitanimationiteration': 'webkitAnimationIteration', | 297 'webkitanimationiteration': 'webkitAnimationIteration', |
261 'webkitanimationstart': 'webkitAnimationStart', | 298 'webkitanimationstart': 'webkitAnimationStart', |
262 'webkitfullscreenchange': 'webkitFullScreenChange', | |
263 'webkitfullscreenerror': 'webkitFullScreenError', | |
264 'webkitspeechchange': 'webkitSpeechChange', | 299 'webkitspeechchange': 'webkitSpeechChange', |
265 'webkittransitionend': 'webkitTransitionEnd', | 300 'webkittransitionend': 'webkitTransitionEnd', |
266 } | 301 } |
267 | 302 |
268 # Mapping from raw event names to the pretty camelCase event names exposed as | 303 # Mapping from raw event names to the pretty camelCase event names exposed as |
269 # properties in dart:html. If the DOM exposes a new event name, you will need | 304 # properties in dart:html. If the DOM exposes a new event name, you will need |
270 # to add the lower case to camel case conversion for that event name here. | 305 # to add the lower case to camel case conversion for that event name here. |
271 _html_event_names = { | 306 _html_event_names = { |
272 'DOMContentLoaded': 'contentLoaded', | 307 'DOMContentLoaded': 'contentLoaded', |
273 'touchleave': 'touchLeave', | 308 'touchleave': 'touchLeave', |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 'touchend': 'touchEnd', | 391 'touchend': 'touchEnd', |
357 'touchmove': 'touchMove', | 392 'touchmove': 'touchMove', |
358 'touchstart': 'touchStart', | 393 'touchstart': 'touchStart', |
359 'unload': 'unload', | 394 'unload': 'unload', |
360 'updateready': 'updateReady', | 395 'updateready': 'updateReady', |
361 'volumechange': 'volumeChange', | 396 'volumechange': 'volumeChange', |
362 'waiting': 'waiting', | 397 'waiting': 'waiting', |
363 'webkitAnimationEnd': 'animationEnd', | 398 'webkitAnimationEnd': 'animationEnd', |
364 'webkitAnimationIteration': 'animationIteration', | 399 'webkitAnimationIteration': 'animationIteration', |
365 'webkitAnimationStart': 'animationStart', | 400 'webkitAnimationStart': 'animationStart', |
366 'webkitFullScreenChange': 'fullScreenChange', | 401 'webkitfullscreenchange': 'fullscreenChange', |
367 'webkitFullScreenError': 'fullScreenError', | 402 'webkitfullscreenerror': 'fullscreenError', |
368 'webkitSpeechChange': 'speechChange', | 403 'webkitSpeechChange': 'speechChange', |
369 'webkitTransitionEnd': 'transitionEnd' | 404 'webkitTransitionEnd': 'transitionEnd' |
370 } | 405 } |
371 | 406 |
372 def _OnAttributeToEventName(on_method): | 407 def _OnAttributeToEventName(on_method): |
373 event_name = on_method.id[2:] | 408 event_name = on_method.id[2:] |
374 if event_name in _on_attribute_to_event_name_mapping: | 409 if event_name in _on_attribute_to_event_name_mapping: |
375 return _on_attribute_to_event_name_mapping[event_name] | 410 return _on_attribute_to_event_name_mapping[event_name] |
376 else: | 411 else: |
377 return event_name | 412 return event_name |
378 | 413 |
379 def _DomToHtmlEvents(interface_id, events): | 414 def _DomToHtmlEvents(interface_id, events): |
380 event_names = set(map(_OnAttributeToEventName, events)) | 415 event_names = set(map(_OnAttributeToEventName, events)) |
381 if interface_id in _html_manual_events: | 416 if interface_id in _html_manual_events: |
382 for manual_event_name in _html_manual_events[interface_id]: | 417 for manual_event_name in _html_manual_events[interface_id]: |
383 event_names.add(manual_event_name) | 418 event_names.add(manual_event_name) |
384 | 419 |
385 return sorted(event_names, key=lambda name: _html_event_names[name]) | 420 return sorted(event_names, key=lambda name: _html_event_names[name]) |
386 | 421 |
387 # ------------------------------------------------------------------------------ | 422 # ------------------------------------------------------------------------------ |
423 class HtmlSystemShared(object): | |
388 | 424 |
389 class HtmlSystem(System): | 425 def __init__(self, database, generator): |
390 | |
391 def __init__(self, templates, database, emitters, output_dir, generator): | |
392 super(HtmlSystem, self).__init__( | |
393 templates, database, emitters, output_dir) | |
394 self._event_classes = set() | 426 self._event_classes = set() |
395 self._seen_event_names = {} | 427 self._seen_event_names = {} |
428 self._database = database | |
396 self._generator = generator | 429 self._generator = generator |
397 | 430 |
398 def _AllowInHtmlLibrary(self, interface, member): | 431 def _AllowInHtmlLibrary(self, interface, member, member_prefix): |
399 if self._PrivateInHtmlLibrary(interface, member): | 432 return not self._Matches(interface, member, member_prefix, |
400 return False | 433 _html_library_remove) |
434 | |
435 def _Matches(self, interface, member, member_prefix, candidates): | |
401 for interface_name in ([interface.id] + | 436 for interface_name in ([interface.id] + |
402 self._generator._AllImplementedInterfaces(interface)): | 437 self._generator._AllImplementedInterfaces(interface)): |
403 if interface.id + '.' + member in _html_library_remove: | 438 if (DartType(interface_name) + '.' + member in candidates or |
404 return False | 439 DartType(interface_name) + '.' + member_prefix + member in candidates) : |
sra1
2012/02/29 23:11:55
These two tests do the same when member_prefix='',
Jacob
2012/03/01 00:40:44
Clarified offline. The design is the table of matc
| |
405 return True | 440 return True |
441 return False | |
406 | 442 |
407 def _PrivateInHtmlLibrary(self, interface, member): | 443 def MaybeReturnDocument(self, return_type): |
444 """ | |
445 To make it appear that there are not a distinct Document and | |
446 HTMLHtmlElement (document.documentElement) objects we always use | |
447 documentElement instead of the regular document object so must not | |
448 allow a regular document to leak out. | |
449 """ | |
450 # TODO(jacobr): any method that returns a Node could also theoretically | |
451 # really return a Document but there are alot of methods that return nodes | |
452 # and they all appear to be same. Consider the alternate strategy of | |
sra1
2012/02/29 23:11:55
same = sane?
Jacob
2012/03/01 00:40:44
same ==> safe :)
done
| |
453 # whitelisting just the known safe methods that return Nodes. | |
454 return (DartType(return_type) == 'EventTarget' or | |
455 DartType(return_type) == 'Document') | |
456 | |
457 def RenameInHtmlLibrary(self, interface, member, member_prefix=''): | |
458 """ | |
459 Returns the name of the member in the HTML library or None if the member is | |
460 suppressed in the HTML library | |
461 """ | |
462 if not self._AllowInHtmlLibrary(interface, member, member_prefix): | |
463 return None | |
464 | |
408 for interface_name in ([interface.id] + | 465 for interface_name in ([interface.id] + |
409 self._generator._AllImplementedInterfaces(interface)): | 466 self._generator._AllImplementedInterfaces(interface)): |
410 if (interface_name in _private_html_members and | 467 name = interface.id + '.' + member |
411 member in _private_html_members[interface_name]): | 468 if name in _html_library_renames: |
412 return True | 469 return _html_library_renames[name] |
413 return False | 470 name = interface.id + '.' + member_prefix + member |
471 if name in _html_library_renames: | |
472 return _html_library_renames[name] | |
473 | |
474 if self._PrivateInHtmlLibrary(interface, member, member_prefix): | |
475 return '_' + member | |
476 | |
477 # No rename required | |
478 return member | |
479 | |
480 def _PrivateInHtmlLibrary(self, interface, member, member_prefix): | |
481 return self._Matches(interface, member, member_prefix, | |
482 _private_html_members) | |
414 | 483 |
415 # TODO(jacobr): this already exists | 484 # TODO(jacobr): this already exists |
416 def _TraverseParents(self, interface, callback): | 485 def _TraverseParents(self, interface, callback): |
417 for parent in interface.parents: | 486 for parent in interface.parents: |
418 parent_id = parent.type.id | 487 parent_id = parent.type.id |
419 if self._database.HasInterface(parent_id): | 488 if self._database.HasInterface(parent_id): |
420 parent_interface = self._database.GetInterface(parent_id) | 489 parent_interface = self._database.GetInterface(parent_id) |
421 callback(parent_interface) | 490 callback(parent_interface) |
422 self._TraverseParents(parent_interface, callback) | 491 self._TraverseParents(parent_interface, callback) |
423 | 492 |
424 # TODO(jacobr): this isn't quite right.... | 493 # TODO(jacobr): this isn't quite right.... |
425 def _GetParentsEventsClasses(self, interface): | 494 def GetParentsEventsClasses(self, interface): |
426 # Ugly hack as we don't specify that Document inherits from Element | 495 # Ugly hack as we don't specify that Document inherits from Element |
427 # in our IDL. | 496 # in our IDL. |
428 if interface.id == 'Document': | 497 if interface.id == 'Document': |
429 return ['ElementEvents'] | 498 return ['ElementEvents'] |
430 | 499 |
431 interfaces_with_events = set() | 500 interfaces_with_events = set() |
432 def visit(parent): | 501 def visit(parent): |
433 if parent.id in self._event_classes: | 502 if parent.id in self._event_classes: |
434 interfaces_with_events.add(parent) | 503 interfaces_with_events.add(parent) |
435 | 504 |
436 self._TraverseParents(interface, visit) | 505 self._TraverseParents(interface, visit) |
437 if len(interfaces_with_events) == 0: | 506 if len(interfaces_with_events) == 0: |
438 return ['Events'] | 507 return ['Events'] |
439 else: | 508 else: |
440 names = [] | 509 names = [] |
441 for interface in interfaces_with_events: | 510 for interface in interfaces_with_events: |
442 names.append(interface.id + 'Events') | 511 names.append(interface.id + 'Events') |
443 return names | 512 return names |
444 | 513 |
514 def _ImplClassName(self, type_name): | |
515 return '_' + type_name + 'Impl' | |
516 | |
517 class HtmlSystem(System): | |
518 | |
519 def __init__(self, templates, database, emitters, output_dir, generator): | |
520 super(HtmlSystem, self).__init__( | |
521 templates, database, emitters, output_dir) | |
522 self._shared = HtmlSystemShared(database, generator) | |
523 | |
445 class HtmlInterfacesSystem(HtmlSystem): | 524 class HtmlInterfacesSystem(HtmlSystem): |
446 | 525 |
447 def __init__(self, templates, database, emitters, output_dir, generator): | 526 def __init__(self, templates, database, emitters, output_dir, generator): |
448 super(HtmlInterfacesSystem, self).__init__( | 527 super(HtmlInterfacesSystem, self).__init__( |
449 templates, database, emitters, output_dir, generator) | 528 templates, database, emitters, output_dir, generator) |
450 self._dart_interface_file_paths = [] | 529 self._dart_interface_file_paths = [] |
451 | 530 |
452 def InterfaceGenerator(self, | 531 def InterfaceGenerator(self, |
453 interface, | 532 interface, |
454 common_prefix, | 533 common_prefix, |
455 super_interface_name, | 534 super_interface_name, |
456 source_filter): | 535 source_filter): |
457 """.""" | 536 """.""" |
458 interface_name = interface.id | 537 interface_name = interface.id |
459 dart_interface_file_path = self._FilePathForDartInterface(interface_name) | 538 dart_interface_file_path = self._FilePathForDartInterface(interface_name) |
460 | 539 |
461 self._dart_interface_file_paths.append(dart_interface_file_path) | 540 self._dart_interface_file_paths.append(dart_interface_file_path) |
462 | 541 |
463 dart_interface_code = self._emitters.FileEmitter(dart_interface_file_path) | 542 dart_interface_code = self._emitters.FileEmitter(dart_interface_file_path) |
464 | 543 |
465 template_file = 'interface_%s.darttemplate' % interface_name | 544 template_file = 'interface_%s.darttemplate' % interface_name |
466 template = self._templates.TryLoad(template_file) | 545 template = self._templates.TryLoad(template_file) |
467 if not template: | 546 if not template: |
468 template = self._templates.Load('interface.darttemplate') | 547 template = self._templates.Load('interface.darttemplate') |
469 | 548 |
470 return HtmlDartInterfaceGenerator( | 549 return HtmlDartInterfaceGenerator( |
471 interface, dart_interface_code, | 550 interface, dart_interface_code, |
472 template, | 551 template, |
473 common_prefix, super_interface_name, | 552 common_prefix, super_interface_name, |
474 source_filter, self) | 553 source_filter, self, self._shared) |
475 | 554 |
476 def ProcessCallback(self, interface, info): | 555 def ProcessCallback(self, interface, info): |
477 """Generates a typedef for the callback interface.""" | 556 """Generates a typedef for the callback interface.""" |
478 interface_name = interface.id | 557 interface_name = interface.id |
479 file_path = self._FilePathForDartInterface(interface_name) | 558 file_path = self._FilePathForDartInterface(interface_name) |
480 self._ProcessCallback(interface, info, file_path) | 559 self._ProcessCallback(interface, info, file_path) |
481 | 560 |
482 def GenerateLibraries(self, lib_dir): | 561 def GenerateLibraries(self, lib_dir): |
483 pass | 562 pass |
484 | 563 |
485 | 564 |
486 def _FilePathForDartInterface(self, interface_name): | 565 def _FilePathForDartInterface(self, interface_name): |
487 """Returns the file path of the Dart interface definition.""" | 566 """Returns the file path of the Dart interface definition.""" |
488 # TODO(jmesserly): is this the right path | 567 # TODO(jmesserly): is this the right path |
489 return os.path.join(self._output_dir, 'html', 'interface', | 568 return os.path.join(self._output_dir, 'html', 'interface', |
490 '%s.dart' % interface_name) | 569 '%s.dart' % interface_name) |
491 | 570 |
492 # ------------------------------------------------------------------------------ | 571 # ------------------------------------------------------------------------------ |
493 | 572 |
494 # TODO(jmesserly): inheritance is probably not the right way to factor this long | 573 # TODO(jmesserly): inheritance is probably not the right way to factor this long |
495 # term, but it makes merging better for now. | 574 # term, but it makes merging better for now. |
496 class HtmlDartInterfaceGenerator(DartInterfaceGenerator): | 575 class HtmlDartInterfaceGenerator(DartInterfaceGenerator): |
497 """Generates Dart Interface definition for one DOM IDL interface.""" | 576 """Generates Dart Interface definition for one DOM IDL interface.""" |
498 | 577 |
499 def __init__(self, interface, emitter, template, | 578 def __init__(self, interface, emitter, template, |
500 common_prefix, super_interface, source_filter, system): | 579 common_prefix, super_interface, source_filter, system, shared): |
501 super(HtmlDartInterfaceGenerator, self).__init__(interface, | 580 super(HtmlDartInterfaceGenerator, self).__init__(interface, |
502 emitter, template, common_prefix, super_interface, source_filter) | 581 emitter, template, common_prefix, super_interface, source_filter) |
503 self._system = system | 582 self._system = system |
583 self._shared = shared | |
504 | 584 |
505 def StartInterface(self): | 585 def StartInterface(self): |
506 typename = self._interface.id | 586 typename = self._interface.id |
507 | 587 |
508 extends = [] | 588 extends = [] |
509 suppressed_extends = [] | 589 suppressed_extends = [] |
510 | 590 |
511 for parent in self._interface.parents: | 591 for parent in self._interface.parents: |
512 # TODO(vsm): Remove source_filter. | 592 # TODO(vsm): Remove source_filter. |
513 if MatchSourceFilter(self._source_filter, parent): | 593 if MatchSourceFilter(self._source_filter, parent): |
514 # Parent is a DOM type. | 594 # Parent is a DOM type. |
515 extends.append(DartType(parent.type.id)) | 595 extends.append(DartType(parent.type.id)) |
516 elif '<' in parent.type.id: | 596 elif '<' in parent.type.id: |
517 # Parent is a Dart collection type. | 597 # Parent is a Dart collection type. |
518 # TODO(vsm): Make this check more robust. | 598 # TODO(vsm): Make this check more robust. |
519 extends.append(parent.type.id) | 599 extends.append(DartType(parent.type.id)) |
520 else: | 600 else: |
521 suppressed_extends.append('%s.%s' % | 601 suppressed_extends.append('%s.%s' % |
522 (self._common_prefix, parent.type.id)) | 602 (self._common_prefix, DartType(parent.type.id))) |
523 | 603 |
524 comment = ' extends' | 604 comment = ' extends' |
525 extends_str = '' | 605 extends_str = '' |
526 if extends: | 606 if extends: |
527 extends_str += ' extends ' + ', '.join(extends) | 607 extends_str += ' extends ' + ', '.join(extends) |
528 comment = ',' | 608 comment = ',' |
529 if suppressed_extends: | 609 if suppressed_extends: |
530 extends_str += ' /*%s %s */' % (comment, ', '.join(suppressed_extends)) | 610 extends_str += ' /*%s %s */' % (comment, ', '.join(suppressed_extends)) |
531 | 611 |
532 if typename in interface_factories: | 612 if typename in interface_factories: |
(...skipping 12 matching lines...) Expand all Loading... | |
545 '\n' | 625 '\n' |
546 ' $CTOR(int length);\n' | 626 ' $CTOR(int length);\n' |
547 '\n' | 627 '\n' |
548 ' $CTOR.fromList(List<$TYPE> list);\n' | 628 ' $CTOR.fromList(List<$TYPE> list);\n' |
549 '\n' | 629 '\n' |
550 ' $CTOR.fromBuffer(ArrayBuffer buffer);\n', | 630 ' $CTOR.fromBuffer(ArrayBuffer buffer);\n', |
551 CTOR=self._interface.id, | 631 CTOR=self._interface.id, |
552 TYPE=DartType(element_type)) | 632 TYPE=DartType(element_type)) |
553 | 633 |
554 def AddAttribute(self, getter, setter): | 634 def AddAttribute(self, getter, setter): |
555 if getter and not self._system._AllowInHtmlLibrary(self._interface, | 635 html_getter_name = self._shared.RenameInHtmlLibrary( |
556 'get:' + getter.id): | 636 self._interface, getter.id, 'get:') |
637 html_setter_name = self._shared.RenameInHtmlLibrary( | |
638 self._interface, getter.id, 'set:') | |
639 | |
640 if not html_getter_name: | |
557 getter = None | 641 getter = None |
558 if setter and not self._system._AllowInHtmlLibrary(self._interface, | 642 if not html_setter_name: |
559 'set:' + setter.id): | |
560 setter = None | 643 setter = None |
561 if not getter and not setter: | 644 if not getter and not setter: |
562 return | 645 return |
563 if getter and setter and DartType(getter.type.id) == DartType(setter.type.id ): | 646 |
647 # We don't yet handle inconsistent renames of the getter and setter yet. | |
648 if html_getter_name and html_setter_name: | |
649 assert html_getter_name == html_setter_name | |
650 if (getter and setter and | |
651 DartType(getter.type.id) == DartType(setter.type.id)): | |
564 self._members_emitter.Emit('\n $TYPE $NAME;\n', | 652 self._members_emitter.Emit('\n $TYPE $NAME;\n', |
565 NAME=getter.id, TYPE=DartType(getter.type.id)); | 653 NAME=html_getter_name, |
654 TYPE=DartType(getter.type.id)); | |
566 return | 655 return |
567 if getter and not setter: | 656 if getter and not setter: |
568 self._members_emitter.Emit('\n final $TYPE $NAME;\n', | 657 self._members_emitter.Emit('\n final $TYPE $NAME;\n', |
569 NAME=getter.id, TYPE=DartType(getter.type.id)); | 658 NAME=html_getter_name, |
659 TYPE=DartType(getter.type.id)); | |
570 return | 660 return |
571 raise Exception('Unexpected getter/setter combination %s %s' % | 661 raise Exception('Unexpected getter/setter combination %s %s' % |
572 (getter, setter)) | 662 (getter, setter)) |
573 | 663 |
574 def AddOperation(self, info): | 664 def AddOperation(self, info): |
575 """ | 665 """ |
576 Arguments: | 666 Arguments: |
577 operations - contains the overloads, one or more operations with the same | 667 operations - contains the overloads, one or more operations with the same |
578 name. | 668 name. |
579 """ | 669 """ |
580 if self._system._AllowInHtmlLibrary(self._interface, info.name): | 670 html_name = self._shared.RenameInHtmlLibrary(self._interface, info.name) |
671 if html_name: | |
581 self._members_emitter.Emit('\n' | 672 self._members_emitter.Emit('\n' |
582 ' $TYPE $NAME($PARAMS);\n', | 673 ' $TYPE $NAME($PARAMS);\n', |
583 TYPE=info.type_name, | 674 TYPE=info.type_name, |
584 NAME=info.name, | 675 NAME=html_name, |
585 PARAMS=info.ParametersInterfaceDeclaration()) | 676 PARAMS=info.ParametersInterfaceDeclaration()) |
586 | 677 |
587 def FinishInterface(self): | 678 def FinishInterface(self): |
588 pass | 679 pass |
589 | 680 |
590 def AddConstant(self, constant): | 681 def AddConstant(self, constant): |
591 self._EmitConstant(self._members_emitter, constant) | 682 self._EmitConstant(self._members_emitter, constant) |
592 | 683 |
593 def AddEventAttributes(self, event_attrs): | 684 def AddEventAttributes(self, event_attrs): |
594 event_attrs = _DomToHtmlEvents(self._interface.id, event_attrs) | 685 event_attrs = _DomToHtmlEvents(self._interface.id, event_attrs) |
595 self._system._event_classes.add(self._interface.id) | 686 self._shared._event_classes.add(self._interface.id) |
596 events_interface = self._interface.id + 'Events' | 687 events_interface = self._interface.id + 'Events' |
597 self._members_emitter.Emit('\n $TYPE get on();\n', | 688 self._members_emitter.Emit('\n $TYPE get on();\n', |
598 TYPE=events_interface) | 689 TYPE=events_interface) |
599 events_members = self._emitter.Emit( | 690 events_members = self._emitter.Emit( |
600 '\ninterface $INTERFACE extends $PARENTS {\n$!MEMBERS}\n', | 691 '\ninterface $INTERFACE extends $PARENTS {\n$!MEMBERS}\n', |
601 INTERFACE=events_interface, | 692 INTERFACE=events_interface, |
602 PARENTS=', '.join( | 693 PARENTS=', '.join( |
603 self._system._GetParentsEventsClasses(self._interface))) | 694 self._shared.GetParentsEventsClasses(self._interface))) |
604 | 695 |
605 for event_name in event_attrs: | 696 for event_name in event_attrs: |
606 if event_name in _html_event_names: | 697 if event_name in _html_event_names: |
607 events_members.Emit('\n EventListenerList get $NAME();\n', | 698 events_members.Emit('\n EventListenerList get $NAME();\n', |
608 NAME=_html_event_names[event_name]) | 699 NAME=_html_event_names[event_name]) |
609 else: | 700 else: |
610 raise Exception('No known html even name for event: ' + event_name) | 701 raise Exception('No known html even name for event: ' + event_name) |
611 | 702 |
612 # ------------------------------------------------------------------------------ | 703 # ------------------------------------------------------------------------------ |
613 | 704 |
614 # TODO(jmesserly): inheritance is probably not the right way to factor this long | 705 # TODO(jmesserly): inheritance is probably not the right way to factor this long |
615 # term, but it makes merging better for now. | 706 # term, but it makes merging better for now. |
616 class HtmlFrogClassGenerator(FrogInterfaceGenerator): | 707 class HtmlFrogClassGenerator(FrogInterfaceGenerator): |
617 """Generates a Frog class for the dart:html library from a DOM IDL | 708 """Generates a Frog class for the dart:html library from a DOM IDL |
618 interface. | 709 interface. |
619 """ | 710 """ |
620 | 711 |
621 def __init__(self, system, interface, template, super_interface, dart_code): | 712 def __init__(self, system, interface, template, super_interface, dart_code, |
713 shared): | |
622 super(HtmlFrogClassGenerator, self).__init__( | 714 super(HtmlFrogClassGenerator, self).__init__( |
623 system, interface, template, super_interface, dart_code) | 715 system, interface, template, super_interface, dart_code) |
716 self._shared = shared | |
624 | 717 |
718 def _ImplClassName(self, type_name): | |
719 return self._shared._ImplClassName(type_name) | |
625 | 720 |
626 def StartInterface(self): | 721 def StartInterface(self): |
627 interface = self._interface | 722 interface = self._interface |
628 interface_name = interface.id | 723 interface_name = interface.id |
629 | 724 |
630 self._class_name = self._ImplClassName(interface_name) | 725 self._class_name = self._ImplClassName(interface_name) |
631 | 726 |
632 base = None | 727 base = None |
633 if interface.parents: | 728 if interface.parents: |
634 supertype = interface.parents[0].type.id | 729 supertype = interface.parents[0].type.id |
635 # FIXME: We're currently injecting List<..> and EventTarget as | |
636 # supertypes in dart.idl. We should annotate/preserve as | |
637 # attributes instead. For now, this hack lets the interfaces | |
638 # inherit, but not the classes. | |
639 if (not IsDartListType(supertype) and | |
640 not supertype == 'EventTarget'): | |
641 base = self._ImplClassName(supertype) | |
642 if IsDartCollectionType(supertype): | 730 if IsDartCollectionType(supertype): |
643 # List methods are injected in AddIndexer. | 731 # List methods are injected in AddIndexer. |
644 pass | 732 pass |
645 elif supertype == 'EventTarget': | |
646 # Most implementors of EventTarget specify the EventListener operations | |
647 # again. If the operations are not specified, try to inherit from the | |
648 # EventTarget implementation. | |
649 # | |
650 # Applies to MessagePort. | |
651 if not [op for op in interface.operations if op.id == 'addEventListener' ]: | |
652 base = self._ImplClassName(supertype) | |
653 else: | 733 else: |
654 base = self._ImplClassName(supertype) | 734 base = self._ImplClassName(supertype) |
655 | 735 |
656 native_spec = MakeNativeSpec(interface.javascript_binding_name) | 736 native_spec = MakeNativeSpec(interface.javascript_binding_name) |
657 | 737 |
658 extends = ' extends ' + base if base else '' | 738 extends = ' extends ' + base if base else '' |
659 | 739 |
660 # TODO: Include all implemented interfaces, including other Lists. | 740 # TODO: Include all implemented interfaces, including other Lists. |
661 implements = [interface_name] | 741 implements = [interface_name] |
662 element_type = MaybeTypedArrayElementType(self._interface) | 742 element_type = MaybeTypedArrayElementType(self._interface) |
663 if element_type: | 743 if element_type: |
664 implements.append('List<%s>' % DartType(element_type)) | 744 implements.append('List<%s>' % DartType(element_type)) |
665 | 745 |
666 self._members_emitter = self._dart_code.Emit( | 746 self._members_emitter = self._dart_code.Emit( |
667 self._template, | 747 self._template, |
668 #class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { | 748 #class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { |
669 #$!MEMBERS | 749 #$!MEMBERS |
670 #} | 750 #} |
671 CLASSNAME=self._class_name, | 751 CLASSNAME=self._class_name, |
672 EXTENDS=extends, | 752 EXTENDS=extends, |
673 IMPLEMENTS=' implements ' + ', '.join(implements), | 753 IMPLEMENTS=' implements ' + ', '.join(implements), |
674 NATIVESPEC=' native "' + native_spec + '"') | 754 NATIVESPEC=' native "' + native_spec + '"') |
675 | 755 |
676 element_type = MaybeTypedArrayElementType(interface) | |
677 if element_type: | 756 if element_type: |
678 self.AddTypedArrayConstructors(element_type) | 757 self.AddTypedArrayConstructors(element_type) |
679 | 758 |
759 def AddIndexer(self, element_type): | |
760 """Adds all the methods required to complete implementation of List.""" | |
761 # We would like to simply inherit the implementation of everything except | |
762 # get length(), [], and maybe []=. It is possible to extend from a base | |
763 # array implementation class only when there is no other implementation | |
764 # inheritance. There might be no implementation inheritance other than | |
765 # DOMBaseWrapper for many classes, but there might be some where the | |
766 # array-ness is introduced by a non-root interface: | |
767 # | |
768 # interface Y extends X, List<T> ... | |
769 # | |
770 # In the non-root case we have to choose between: | |
771 # | |
772 # class YImpl extends XImpl { add List<T> methods; } | |
773 # | |
774 # and | |
775 # | |
776 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | |
777 # | |
778 self._members_emitter.Emit( | |
779 '\n' | |
780 ' $TYPE operator[](int index) native "return this[index];";\n', | |
781 TYPE=self._NarrowOutputType(element_type)) | |
782 | |
783 if 'CustomIndexedSetter' in self._interface.ext_attrs: | |
784 self._members_emitter.Emit( | |
785 '\n' | |
786 ' void operator[]=(int index, $TYPE value) native "this[index] = valu e";\n', | |
787 TYPE=self._NarrowInputType(element_type)) | |
788 else: | |
789 # The HTML library implementation of NodeList has a custom indexed setter | |
790 # implementation that uses the parent node the NodeList is associated | |
791 # with if one is available. | |
792 if self._interface.id != 'NodeList': | |
793 self._members_emitter.Emit( | |
794 '\n' | |
795 ' void operator[]=(int index, $TYPE value) {\n' | |
796 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' | |
797 ' }\n', | |
798 TYPE=self._NarrowInputType(element_type)) | |
799 | |
800 # TODO(sra): Use separate mixins for mutable implementations of List<T>. | |
801 # TODO(sra): Use separate mixins for typed array implementations of List<T>. | |
802 if self._interface.id != 'NodeList': | |
803 template_file = 'immutable_list_mixin.darttemplate' | |
804 template = self._system._templates.Load(template_file) | |
805 self._members_emitter.Emit(template, E=DartType(element_type)) | |
806 | |
680 def AddAttribute(self, getter, setter): | 807 def AddAttribute(self, getter, setter): |
681 | 808 |
682 if self._system._PrivateInHtmlLibrary(self._interface, getter.id): | 809 html_getter_name = self._shared.RenameInHtmlLibrary( |
683 if getter: | 810 self._interface, getter.id, 'get:') |
684 self._AddGetter(getter, True) | 811 html_setter_name = self._shared.RenameInHtmlLibrary( |
685 if setter: | 812 self._interface, getter.id, 'set:') |
686 self._AddSetter(setter, True) | 813 |
687 return | 814 if not html_getter_name: |
688 if getter and not self._system._AllowInHtmlLibrary(self._interface, | |
689 'get:' + getter.id): | |
690 getter = None | 815 getter = None |
691 if setter and not self._system._AllowInHtmlLibrary(self._interface, | 816 if not html_setter_name: |
692 'set:' + setter.id): | |
693 setter = None | 817 setter = None |
818 | |
694 if not getter and not setter: | 819 if not getter and not setter: |
695 return | 820 return |
821 | |
822 if ((getter and (html_getter_name != getter.id or | |
823 self._shared.MaybeReturnDocument(getter.type.id))) or | |
824 (setter and (html_setter_name != setter.id or | |
825 self._shared.MaybeReturnDocument(setter.type.id))) or | |
826 self._interface.id == 'Document'): | |
827 if getter: | |
828 self._AddRenamingGetter(getter, html_getter_name) | |
829 if setter: | |
830 self._AddRenamingSetter(setter, html_setter_name) | |
831 return | |
832 | |
696 # If the (getter, setter) pair is shadowing, we can't generate a shadowing | 833 # If the (getter, setter) pair is shadowing, we can't generate a shadowing |
697 # field (Issue 1633). | 834 # field (Issue 1633). |
698 (super_getter, super_getter_interface) = self._FindShadowedAttribute(getter) | 835 (super_getter, super_getter_interface) = self._FindShadowedAttribute(getter) |
699 (super_setter, super_setter_interface) = self._FindShadowedAttribute(setter) | 836 (super_setter, super_setter_interface) = self._FindShadowedAttribute(setter) |
700 if super_getter or super_setter: | 837 if super_getter or super_setter: |
701 if getter and not setter and super_getter and not super_setter: | 838 if getter and not setter and super_getter and not super_setter: |
702 if getter.type.id == super_getter.type.id: | 839 if DartType(getter.type.id) == DartType(super_getter.type.id): |
703 # Compatible getter, use the superclass property. This works because | 840 # Compatible getter, use the superclass property. This works because |
704 # JavaScript will do its own dynamic dispatch. | 841 # JavaScript will do its own dynamic dispatch. |
705 output_type = getter and self._NarrowOutputType(getter.type.id) | 842 output_type = getter and self._NarrowOutputType(getter.type.id) |
706 self._members_emitter.Emit( | 843 self._members_emitter.Emit( |
707 '\n' | 844 '\n' |
708 ' // Use implementation from $SUPER.\n' | 845 ' // Use implementation from $SUPER.\n' |
709 ' // final $TYPE $NAME;\n', | 846 ' // final $TYPE $NAME;\n', |
710 SUPER=super_getter_interface.id, | 847 SUPER=super_getter_interface.id, |
711 NAME=getter.id, TYPE=output_type) | 848 NAME=getter.id, TYPE=output_type) |
712 return | 849 return |
713 | 850 |
714 self._members_emitter.Emit('\n // Shadowing definition.') | 851 self._members_emitter.Emit('\n // Shadowing definition.') |
715 if getter: | 852 if getter: |
sra1
2012/02/29 23:11:55
_AddAttributeUsingProperties?
Otherwise you might
Jacob
2012/03/01 00:40:44
Done.
| |
716 self._AddGetter(getter, False) | 853 self._AddGetter(getter) |
717 if setter: | 854 if setter: |
718 self._AddSetter(setter, False) | 855 self._AddSetter(setter) |
719 return | 856 return |
720 | 857 |
721 if self._interface.id != 'Document': | 858 output_type = getter and self._NarrowOutputType(getter.type.id) |
722 output_type = getter and self._NarrowOutputType(getter.type.id) | 859 input_type = setter and self._NarrowInputType(setter.type.id) |
723 input_type = setter and self._NarrowInputType(setter.type.id) | 860 if getter and setter and input_type == output_type: |
724 if getter and setter and input_type == output_type: | 861 self._members_emitter.Emit( |
725 self._members_emitter.Emit( | 862 '\n $TYPE $NAME;\n', |
726 '\n $TYPE $NAME;\n', | 863 NAME=getter.id, TYPE=output_type) |
727 NAME=getter.id, TYPE=output_type) | 864 return |
728 return | 865 if getter and not setter: |
729 if getter and not setter: | 866 self._members_emitter.Emit( |
730 self._members_emitter.Emit( | 867 '\n final $TYPE $NAME;\n', |
731 '\n final $TYPE $NAME;\n', | 868 NAME=getter.id, TYPE=output_type) |
732 NAME=getter.id, TYPE=output_type) | 869 return |
733 return | 870 self._AddAttributeUsingProperties(getter, setter) |
734 self._AddAttributeUsingProperties(getter, setter, False) | |
735 | 871 |
736 def _AddAttributeUsingProperties(self, getter, setter, private): | 872 def _AddAttributeUsingProperties(self, getter, setter): |
737 if getter: | 873 if getter: |
738 self._AddGetter(getter, private) | 874 self._AddGetter(getter) |
739 if setter: | 875 if setter: |
740 self._AddSetter(setter, private) | 876 self._AddSetter(setter) |
741 | 877 |
742 def _AddGetter(self, attr, private): | 878 def _AddGetter(self, attr): |
743 # TODO(sra): Remove native body when Issue 829 fixed. | 879 self._AddRenamingGetter(attr, attr.id) |
880 | |
881 def _AddSetter(self, attr): | |
882 self._AddRenamingSetter(attr, attr.id) | |
883 | |
884 def _AddRenamingGetter(self, attr, html_name): | |
885 return_type = self._NarrowOutputType(attr.type.id) | |
886 if self._shared.MaybeReturnDocument(attr.type.id): | |
887 self._members_emitter.Emit( | |
888 '\n $TYPE get $(HTML_NAME)() => ' | |
889 '_FixHtmlDocumentReference(_$(HTML_NAME));\n', | |
890 HTML_NAME=html_name, | |
891 NAME=attr.id, TYPE=return_type, | |
sra1
2012/02/29 23:11:55
I think it is easier to find TYPE if it is on its
Jacob
2012/03/01 00:40:44
Done.
| |
892 THIS='this.parentNode' if self._interface.id == 'Document' else 'this' | |
sra1
2012/02/29 23:11:55
THIS is not used
Jacob
2012/03/01 00:40:44
Done.
| |
893 ) | |
894 html_name = '_' + html_name | |
895 # For correctness this needs to be the return type of the native helper | |
896 # method due to the fact that the real HTMLDocument object is not typed | |
897 # as a document. TODO(jacobr): we could simplify this. | |
898 return_type = '_EventTargetImpl' | |
899 | |
744 self._members_emitter.Emit( | 900 self._members_emitter.Emit( |
745 '\n $TYPE get $PRIVATE$NAME() native "return $THIS.$NAME;";\n', | 901 '\n $TYPE get $(HTML_NAME)() native "return $(THIS).$NAME;";\n', |
746 NAME=attr.id, TYPE=self._NarrowOutputType(attr.type.id), | 902 HTML_NAME=html_name, |
747 PRIVATE='_' if private else '', | 903 NAME=attr.id, TYPE=return_type, |
748 THIS='this.parentNode' if self._interface.id == 'Document' else 'this' | 904 THIS='this.parentNode' if self._interface.id == 'Document' else 'this' |
749 ) | 905 ) |
750 | 906 |
751 def _AddSetter(self, attr, private): | 907 def _AddRenamingSetter(self, attr, html_name): |
752 # TODO(sra): Remove native body when Issue 829 fixed. | |
753 self._members_emitter.Emit( | 908 self._members_emitter.Emit( |
754 '\n void set $PRIVATE$NAME($TYPE value)' | 909 '\n void set $HTML_NAME($TYPE value)' |
755 ' native "$THIS.$NAME = value;";\n', | 910 ' native "$(THIS).$NAME = value;";\n', |
911 HTML_NAME=html_name, | |
756 NAME=attr.id, TYPE=self._NarrowInputType(attr.type.id), | 912 NAME=attr.id, TYPE=self._NarrowInputType(attr.type.id), |
757 PRIVATE='_' if private else '', | |
758 THIS='this.parentNode' if self._interface.id == 'Document' else 'this') | 913 THIS='this.parentNode' if self._interface.id == 'Document' else 'this') |
759 | 914 |
760 def AddOperation(self, info): | 915 def AddOperation(self, info): |
761 """ | 916 """ |
762 Arguments: | 917 Arguments: |
763 info: An OperationInfo object. | 918 info: An OperationInfo object. |
764 """ | 919 """ |
765 private_in_html = self._system._PrivateInHtmlLibrary(self._interface, | 920 html_name = self._shared.RenameInHtmlLibrary(self._interface, info.name) |
766 info.name) | 921 if not html_name: |
767 if private_in_html or self._interface.id == 'Document': | 922 return |
768 # TODO(vsm): Handle overloads. | 923 |
769 # TODO(jacobr): handle document more efficiently for cases where any | 924 maybe_return_document = self._shared.MaybeReturnDocument(info.type_name) |
770 # document is fine. For example: use window.document instead of | 925 |
771 # this.parentNode. | 926 if (self._interface.id == 'Document' or html_name != info.name or |
sra1
2012/02/29 23:11:55
Why self._interface.id == 'Document' ok I see - 't
Jacob
2012/03/01 00:40:44
Good comments. Done.
On 2012/02/29 23:11:55, sra1
| |
927 info.type_name == 'Document') or maybe_return_document: | |
sra1
2012/02/29 23:11:55
Is info.typename == 'Doc' redundant with maybe_ret
Jacob
2012/03/01 00:40:44
fixed. That was legacy.
| |
928 | |
929 # For example: use window.document instead of his.parentNode. | |
772 return_type = self._NarrowOutputType(info.type_name) | 930 return_type = self._NarrowOutputType(info.type_name) |
931 if maybe_return_document: | |
932 assert len(info.overloads) == 1 | |
933 self._members_emitter.Emit( | |
934 '\n' | |
935 ' $TYPE $(HTML_NAME)($PARAMS) => ' | |
936 '_FixHtmlDocumentReference(_$(HTML_NAME)($PARAMNAMES));\n', | |
937 TYPE=return_type, | |
938 HTML_NAME=html_name, | |
939 PARAMNAMES=info.ParametersAsArgumentList(), | |
940 PARAMS=info.ParametersImplementationDeclaration( | |
941 lambda type_name: self._NarrowInputType(type_name))) | |
942 html_name = '_' + html_name | |
943 # For correctness this needs to be the return type of the native helper | |
944 # method due to the fact that the real HTMLDocument object is not typed | |
945 # as a document. TODO(jacobr): we could simplify this. | |
946 return_type = '_EventTargetImpl' | |
sra1
2012/02/29 23:11:55
This muck-with-the-names-and-fall-through logic is
Jacob
2012/03/01 00:40:44
Nice. That makes the code better.
| |
947 | |
948 | |
773 self._members_emitter.Emit( | 949 self._members_emitter.Emit( |
774 '\n' | 950 '\n' |
775 ' $TYPE $PRIVATE$NAME($PARAMS)' | 951 ' $TYPE $(HTML_NAME)($PARAMS)' |
776 ' native "$(RETURN)$(THIS).$NAME($PARAMNAMES);";\n', | 952 ' native "$(RETURN)$(THIS).$NAME($PARAMNAMES);";\n', |
777 TYPE=return_type, | 953 TYPE=return_type, |
778 RETURN='' if return_type == 'void' else 'return ', | 954 RETURN='' if return_type == 'void' else 'return ', |
955 HTML_NAME=html_name, | |
779 NAME=info.name, | 956 NAME=info.name, |
780 PRIVATE='_' if private_in_html else '', | |
781 THIS='this.parentNode' if self._interface.id == 'Document' | 957 THIS='this.parentNode' if self._interface.id == 'Document' |
782 else 'this', | 958 else 'this', |
783 PARAMNAMES=info.ParametersAsArgumentList(), | 959 PARAMNAMES=info.ParametersAsArgumentList(), |
784 PARAMS=info.ParametersImplementationDeclaration( | 960 PARAMS=info.ParametersImplementationDeclaration( |
785 lambda type_name: self._NarrowInputType(type_name))) | 961 lambda type_name: self._NarrowInputType(type_name))) |
786 elif self._system._AllowInHtmlLibrary(self._interface, info.name): | 962 else: |
787 # TODO(jacobr): this is duplicated from the parent class. | |
788 self._members_emitter.Emit( | 963 self._members_emitter.Emit( |
789 '\n' | 964 '\n' |
790 ' $TYPE $NAME($PARAMS) native;\n', | 965 ' $TYPE $NAME($PARAMS) native;\n', |
791 TYPE=self._NarrowOutputType(info.type_name), | 966 TYPE=self._NarrowOutputType(info.type_name), |
792 NAME=info.name, | 967 NAME=info.name, |
793 PARAMS=info.ParametersImplementationDeclaration( | 968 PARAMS=info.ParametersImplementationDeclaration( |
794 lambda type_name: self._NarrowInputType(type_name))) | 969 lambda type_name: self._NarrowInputType(type_name))) |
795 | 970 |
796 def AddEventAttributes(self, event_attrs): | 971 def AddEventAttributes(self, event_attrs): |
797 event_attrs = _DomToHtmlEvents(self._interface.id, event_attrs) | 972 event_attrs = _DomToHtmlEvents(self._interface.id, event_attrs) |
798 events_class = '_' + self._interface.id + 'EventsImpl' | 973 events_class = '_' + self._interface.id + 'EventsImpl' |
799 events_interface = self._interface.id + 'Events' | 974 events_interface = self._interface.id + 'Events' |
800 self._members_emitter.Emit( | 975 self._members_emitter.Emit( |
801 '\n $TYPE get on() =>\n new $TYPE($EVENTTARGET);\n', | 976 '\n $TYPE get on() =>\n new $TYPE($EVENTTARGET);\n', |
802 TYPE=events_class, | 977 TYPE=events_class, |
803 EVENTTARGET='_jsDocument' if self._interface.id == 'Document' | 978 EVENTTARGET='_jsDocument' if self._interface.id == 'Document' |
804 else 'this') | 979 else 'this') |
805 | 980 |
806 self._system._event_classes.add(self._interface.id) | 981 self._shared._event_classes.add(self._interface.id) |
807 | 982 |
808 parent_event_classes = self._system._GetParentsEventsClasses( | 983 parent_event_classes = self._shared.GetParentsEventsClasses( |
809 self._interface) | 984 self._interface) |
810 if len(parent_event_classes) != 1: | 985 if len(parent_event_classes) != 1: |
811 raise Exception('Only one parent event class allowed ' | 986 raise Exception('Only one parent event class allowed ' |
812 + self._interface.id) | 987 + self._interface.id) |
813 | 988 |
814 # TODO(jacobr): specify the type of _ptr as EventTarget | 989 # TODO(jacobr): specify the type of _ptr as EventTarget |
815 events_members = self._dart_code.Emit( | 990 events_members = self._dart_code.Emit( |
816 '\n' | 991 '\n' |
817 'class $CLASSNAME extends $SUPER implements $INTERFACE {\n' | 992 'class $CLASSNAME extends $SUPER implements $INTERFACE {\n' |
818 ' $CLASSNAME(_ptr) : super(_ptr);\n' | 993 ' $CLASSNAME(_ptr) : super(_ptr);\n' |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
851 dart_frog_file_path = self._FilePathForFrogImpl(interface.id) | 1026 dart_frog_file_path = self._FilePathForFrogImpl(interface.id) |
852 self._dart_frog_file_paths.append(dart_frog_file_path) | 1027 self._dart_frog_file_paths.append(dart_frog_file_path) |
853 | 1028 |
854 template_file = 'impl_%s.darttemplate' % interface.id | 1029 template_file = 'impl_%s.darttemplate' % interface.id |
855 template = self._templates.TryLoad(template_file) | 1030 template = self._templates.TryLoad(template_file) |
856 if not template: | 1031 if not template: |
857 template = self._templates.Load('frog_impl.darttemplate') | 1032 template = self._templates.Load('frog_impl.darttemplate') |
858 | 1033 |
859 dart_code = self._emitters.FileEmitter(dart_frog_file_path) | 1034 dart_code = self._emitters.FileEmitter(dart_frog_file_path) |
860 return HtmlFrogClassGenerator(self, interface, template, | 1035 return HtmlFrogClassGenerator(self, interface, template, |
861 super_interface_name, dart_code) | 1036 super_interface_name, dart_code, self._shared) |
862 | 1037 |
863 def GenerateLibraries(self, lib_dir): | 1038 def GenerateLibraries(self, lib_dir): |
864 self._GenerateLibFile( | 1039 self._GenerateLibFile( |
865 'html_frog.darttemplate', | 1040 'html_frog.darttemplate', |
866 os.path.join(lib_dir, 'html_frog.dart'), | 1041 os.path.join(lib_dir, 'html_frog.dart'), |
867 (self._interface_system._dart_interface_file_paths + | 1042 (self._interface_system._dart_interface_file_paths + |
868 self._interface_system._dart_callback_file_paths + | 1043 self._interface_system._dart_callback_file_paths + |
869 self._dart_frog_file_paths)) | 1044 self._dart_frog_file_paths)) |
870 | 1045 |
871 def Finish(self): | 1046 def Finish(self): |
872 pass | 1047 pass |
873 | 1048 |
874 def _FilePathForFrogImpl(self, interface_name): | 1049 def _FilePathForFrogImpl(self, interface_name): |
875 """Returns the file path of the Frog implementation.""" | 1050 """Returns the file path of the Frog implementation.""" |
876 # TODO(jmesserly): is this the right path | 1051 # TODO(jmesserly): is this the right path |
877 return os.path.join(self._output_dir, 'html', 'frog', | 1052 return os.path.join(self._output_dir, 'html', 'frog', |
878 '%s.dart' % interface_name) | 1053 '%s.dart' % interface_name) |
879 | 1054 |
1055 # ----------------------------------------------------------------------------- | |
1056 | |
1057 class HtmlDartiumSystem(HtmlSystem): | |
1058 | |
1059 def __init__(self, templates, database, emitters, output_dir, generator): | |
1060 """Prepared for generating wrapping implementation. | |
1061 | |
1062 - Creates emitter for Dart code. | |
1063 """ | |
1064 super(HtmlDartiumSystem, self).__init__( | |
1065 templates, database, emitters, output_dir, generator) | |
1066 self._shared = HtmlSystemShared(database, generator) | |
1067 self._dart_dartium_file_paths = [] | |
1068 self._wrap_cases = [] | |
1069 | |
1070 def InterfaceGenerator(self, | |
1071 interface, | |
1072 common_prefix, | |
1073 super_interface_name, | |
1074 source_filter): | |
1075 """.""" | |
1076 dart_dartium_file_path = self._FilePathForImpl(interface.id) | |
1077 self._dart_dartium_file_paths.append(dart_dartium_file_path) | |
1078 | |
1079 template_file = 'impl_%s.darttemplate' % interface.id | |
1080 template = self._templates.TryLoad(template_file) | |
1081 # TODO(jacobr): change this name as it is confusing. | |
1082 if not template: | |
1083 template = self._templates.Load('frog_impl.darttemplate') | |
1084 | |
1085 dart_code = self._emitters.FileEmitter(dart_dartium_file_path) | |
1086 return HtmlDartiumInterfaceGenerator(self, interface, template, | |
1087 super_interface_name, dart_code, self._BaseDefines(interface), | |
1088 self._shared) | |
1089 | |
1090 def _FilePathForImpl(self, interface_name): | |
1091 """Returns the file path of the Frog implementation.""" | |
1092 # TODO(jmesserly): is this the right path | |
1093 return os.path.join(self._output_dir, 'html', 'dartium', | |
1094 '%s.dart' % interface_name) | |
1095 | |
1096 def ProcessCallback(self, interface, info): | |
1097 pass | |
1098 | |
1099 def GenerateLibraries(self, lib_dir): | |
1100 # Library generated for implementation. | |
1101 self._GenerateLibFile( | |
1102 'html_dartium.darttemplate', | |
1103 os.path.join(lib_dir, 'html_dartium.dart'), | |
1104 (self._interface_system._dart_interface_file_paths + | |
1105 self._interface_system._dart_callback_file_paths + | |
1106 # FIXME: Move the implementation to a separate library. | |
1107 self._dart_dartium_file_paths | |
1108 ), | |
1109 WRAPCASES='\n'.join(self._wrap_cases)) | |
1110 | |
1111 def Finish(self): | |
1112 pass | |
1113 | |
1114 def _FilePathForDartWrappingImpl(self, interface_name): | |
sra1
2012/02/29 23:11:55
Unused?
Jacob
2012/03/01 00:40:44
Done.
| |
1115 """Returns the file path of the html dartium wrapping implementation.""" | |
1116 return os.path.join(self._output_dir, 'html', 'wrapping', | |
1117 '_%s.dart' % interface_name) | |
1118 | |
880 # ------------------------------------------------------------------------------ | 1119 # ------------------------------------------------------------------------------ |
881 | 1120 |
882 class WrappingInterfaceGenerator(object): | 1121 # TODO(jacobr): there is far too much duplicated code between these bindings |
883 """Generates Dart and JS implementation for one DOM IDL interface.""" | 1122 # and the Frog bindings. A larger scale refactoring needs to be performed to |
1123 # reduce the duplicated logic. | |
1124 class HtmlDartiumInterfaceGenerator(object): | |
1125 """Generates a wrapper based implementation fo the HTML library that works | |
1126 on Dartium. This is not intended to be the final solution for implementing | |
1127 dart:html on Dartium. Eventually we should generate direct wrapperless | |
1128 dart:html bindings that work on dartium.""" | |
884 | 1129 |
885 def __init__(self, interface, super_interface, dart_code, base_members): | 1130 def __init__(self, system, interface, template, super_interface, dart_code, |
886 """Generates Dart and JS code for the given interface. | 1131 base_members, shared): |
1132 """Generates Dart wrapper code for the given interface. | |
887 | 1133 |
888 Args: | 1134 Args: |
889 | 1135 |
890 interface: an IDLInterface instance. It is assumed that all types have | 1136 interface: an IDLInterface instance. It is assumed that all types have |
891 been converted to Dart types (e.g. int, String), unless they are in | 1137 been converted to Dart types (e.g. int, String), unless they are in |
892 the same package as the interface. | 1138 the same package as the interface. |
893 super_interface: A string or None, the name of the common interface that | 1139 super_interface: A string or None, the name of the common interface that |
894 this interface implements, if any. | 1140 this interface implements, if any. |
895 dart_code: an Emitter for the file containing the Dart implementation | 1141 dart_code: an Emitter for the file containing the Dart implementation |
896 class. | 1142 class. |
897 base_members: a set of names of members defined in a base class. This is | 1143 base_members: a set of names of members defined in a base class. This is |
898 used to avoid static member 'overriding' in the generated Dart code. | 1144 used to avoid static member 'overriding' in the generated Dart code. |
1145 shared: functionaly shared across all Html generators. | |
sra1
2012/02/29 23:11:55
Document 'template'.
Jacob
2012/03/01 00:40:44
Done.
| |
899 """ | 1146 """ |
1147 self._system = system | |
900 self._interface = interface | 1148 self._interface = interface |
901 self._super_interface = super_interface | 1149 self._super_interface = super_interface |
902 self._dart_code = dart_code | 1150 self._dart_code = dart_code |
903 self._base_members = base_members | 1151 self._base_members = base_members |
904 self._current_secondary_parent = None | 1152 self._current_secondary_parent = None |
1153 self._shared = shared | |
1154 self._template = template | |
905 | 1155 |
1156 def DomObjectName(self): | |
1157 return '_documentPtr' if self._interface.id == 'Document' else '_ptr' | |
1158 | |
1159 # TODO(jacobr): these 3 methods are duplicated. | |
1160 def _NarrowToImplementationType(self, type_name): | |
1161 # TODO(sra): Move into the 'system' and cache the result. | |
1162 if type_name == 'EventListener': | |
1163 # Callbacks are typedef functions so don't have a class. | |
1164 return type_name | |
1165 if self._system._database.HasInterface(type_name): | |
1166 interface = self._system._database.GetInterface(type_name) | |
1167 if RecognizeCallback(interface): | |
1168 # Callbacks are typedef functions so don't have a class. | |
1169 return type_name | |
1170 else: | |
1171 return self._ImplClassName(type_name) | |
1172 return type_name | |
1173 | |
1174 def _NarrowInputType(self, type_name): | |
1175 return self._NarrowToImplementationType(type_name) | |
1176 | |
1177 def _NarrowOutputType(self, type_name): | |
1178 return self._NarrowToImplementationType(type_name) | |
906 | 1179 |
907 def StartInterface(self): | 1180 def StartInterface(self): |
1181 | |
908 interface = self._interface | 1182 interface = self._interface |
909 interface_name = interface.id | 1183 interface_name = interface.id |
910 | |
911 self._class_name = self._ImplClassName(interface_name) | 1184 self._class_name = self._ImplClassName(interface_name) |
912 | 1185 |
913 base = self._BaseClassName(interface) | 1186 base = None |
1187 if interface.parents: | |
1188 supertype = interface.parents[0].type.id | |
1189 if not IsDartListType(supertype): | |
1190 base = self._ImplClassName(supertype) | |
1191 if IsDartCollectionType(supertype): | |
1192 # List methods are injected in AddIndexer. | |
1193 pass | |
1194 else: | |
1195 base = self._ImplClassName(supertype) | |
1196 | |
1197 # TODO(jacobr): this is fragile. There isn't a guarantee that dart:dom | |
1198 # will continue to exactly match the IDL names. | |
1199 dom_name = interface.javascript_binding_name | |
1200 # We hard code the cases for these classes | |
1201 if dom_name != 'HTMLHtmlElement' and dom_name != 'Document': | |
1202 self._system._wrap_cases.append( | |
1203 ' case "%s": return new %s._wrap(domObject);' % | |
1204 (dom_name, self._class_name)) | |
1205 | |
1206 extends = ' extends ' + base if base else ' extends _DOMTypeBase' | |
1207 | |
1208 # TODO: Include all implemented interfaces, including other Lists. | |
1209 implements = [interface_name] | |
1210 element_type = MaybeTypedArrayElementType(self._interface) | |
1211 if element_type: | |
1212 implements.append('List<' + DartType(element_type) + '>') | |
1213 implements_str = ', '.join(implements) | |
914 | 1214 |
915 (self._members_emitter, | 1215 (self._members_emitter, |
916 self._top_level_emitter) = self._dart_code.Emit( | 1216 self._top_level_emitter) = self._dart_code.Emit( |
917 '\n' | 1217 self._template + '$!TOP_LEVEL', |
918 'class $CLASS extends $BASE implements $INTERFACE {\n' | 1218 #class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { |
919 ' $CLASS() : super() {}\n' | 1219 #$!MEMBERS |
920 '\n' | 1220 #} |
921 ' static create_$CLASS() native {\n' | 1221 NATIVESPEC='', # hack to make reusing the same templates work. |
922 ' return new $CLASS();\n' | 1222 CLASSNAME=self._class_name, |
923 ' }\n' | 1223 EXTENDS=extends, |
924 '$!MEMBERS' | 1224 IMPLEMENTS=' implements ' + implements_str) |
925 '\n' | |
926 ' String get typeName() { return "$INTERFACE"; }\n' | |
927 '}\n' | |
928 '$!TOP_LEVEL', | |
929 CLASS=self._class_name, BASE=base, INTERFACE=interface_name) | |
930 | 1225 |
931 def _ImplClassName(self, type_name): | 1226 # Document requires a custom wrapper. |
932 return '_' + type_name + 'WrappingImplementation' | 1227 if dom_name != 'Document': |
1228 self._members_emitter.Emit( | |
1229 ' $(CLASSNAME)._wrap(ptr) : super._wrap(ptr);\n', | |
1230 CLASSNAME=self._class_name) | |
933 | 1231 |
934 def _BaseClassName(self, interface): | 1232 def _BaseClassName(self, interface): |
935 if not interface.parents: | 1233 if not interface.parents: |
936 return 'DOMWrapperBase' | 1234 return '_DOMTypeBase' |
937 | 1235 |
938 supertype = interface.parents[0].type.id | 1236 supertype = DartType(interface.parents[0].type.id) |
939 | 1237 |
940 # FIXME: We're currently injecting List<..> and EventTarget as | |
941 # supertypes in dart.idl. We should annotate/preserve as | |
942 # attributes instead. For now, this hack lets the interfaces | |
943 # inherit, but not the classes. | |
944 # List methods are injected in AddIndexer. | |
945 if IsDartListType(supertype) or IsDartCollectionType(supertype): | 1238 if IsDartListType(supertype) or IsDartCollectionType(supertype): |
946 return 'DOMWrapperBase' | 1239 return 'DOMWrapperBase' |
947 | 1240 |
948 if supertype == 'EventTarget': | 1241 if supertype == 'EventTarget': |
949 # Most implementors of EventTarget specify the EventListener operations | 1242 # Most implementors of EventTarget specify the EventListener operations |
950 # again. If the operations are not specified, try to inherit from the | 1243 # again. If the operations are not specified, try to inherit from the |
951 # EventTarget implementation. | 1244 # EventTarget implementation. |
952 # | 1245 # |
953 # Applies to MessagePort. | 1246 # Applies to MessagePort. |
954 if not [op for op in interface.operations if op.id == 'addEventListener']: | 1247 if not [op for op in interface.operations if op.id == 'addEventListener']: |
955 return self._ImplClassName(supertype) | 1248 return self._ImplClassName(supertype) |
956 return 'DOMWrapperBase' | 1249 return 'DOMWrapperBase' |
957 | 1250 |
958 return self._ImplClassName(supertype) | 1251 return self._ImplClassName(supertype) |
959 | 1252 |
1253 def _ImplClassName(self, type_name): | |
1254 return self._shared._ImplClassName(type_name) | |
1255 | |
960 def FinishInterface(self): | 1256 def FinishInterface(self): |
961 """.""" | 1257 """.""" |
962 pass | 1258 pass |
963 | 1259 |
964 def AddConstant(self, constant): | 1260 def AddConstant(self, constant): |
965 # Constants are already defined on the interface. | 1261 # Constants are already defined on the interface. |
966 pass | 1262 pass |
967 | 1263 |
968 def _MethodName(self, prefix, name): | 1264 def _MethodName(self, prefix, name): |
969 method_name = prefix + name | 1265 method_name = prefix + name |
970 if name in self._base_members: # Avoid illegal Dart 'static override'. | 1266 if name in self._base_members: # Avoid illegal Dart 'static override'. |
971 method_name = method_name + '_' + self._interface.id | 1267 method_name = method_name + '_' + self._interface.id |
972 return method_name | 1268 return method_name |
973 | 1269 |
974 def AddAttribute(self, getter, setter): | 1270 def AddAttribute(self, getter, setter): |
975 if getter: | 1271 html_getter_name = self._shared.RenameInHtmlLibrary( |
976 self._AddGetter(getter) | 1272 self._interface, getter.id, 'get:') |
977 if setter: | 1273 html_setter_name = self._shared.RenameInHtmlLibrary( |
978 self._AddSetter(setter) | 1274 self._interface, getter.id, 'set:') |
979 | 1275 |
980 def _AddGetter(self, attr): | 1276 if getter and html_getter_name: |
981 # FIXME: Instead of injecting the interface name into the method when it is | 1277 self._AddGetter(getter, html_getter_name) |
982 # also implemented in the base class, suppress the method altogether if it | 1278 if setter and html_setter_name: |
983 # has the same signature. I.e., let the JS do the virtual dispatch instead. | 1279 self._AddSetter(setter, html_setter_name) |
984 method_name = self._MethodName('_get_', attr.id) | 1280 |
1281 def _AddGetter(self, attr, html_name): | |
1282 if self._shared.MaybeReturnDocument(attr.type.id): | |
1283 self._members_emitter.Emit( | |
1284 '\n' | |
1285 ' $TYPE get $(HTML_NAME)() => ' | |
1286 '_FixHtmlDocumentReference(_wrap($(THIS).$NAME));\n', | |
1287 NAME=attr.id, HTML_NAME=html_name, TYPE=DartType(attr.type.id), | |
1288 THIS=self.DomObjectName()) | |
1289 else: | |
1290 self._members_emitter.Emit( | |
1291 '\n' | |
1292 ' $TYPE get $(HTML_NAME)() => _wrap($(THIS).$NAME);\n', | |
1293 NAME=attr.id, HTML_NAME=html_name, TYPE=DartType(attr.type.id), | |
1294 THIS=self.DomObjectName()) | |
1295 | |
1296 def _AddSetter(self, attr, html_name): | |
985 self._members_emitter.Emit( | 1297 self._members_emitter.Emit( |
986 '\n' | 1298 '\n' |
987 ' $TYPE get $NAME() { return $METHOD(this); }\n' | 1299 ' void set $(HTML_NAME)($TYPE value) { $(THIS).$NAME = _unwrap(value); }\n', |
988 ' static $TYPE $METHOD(var _this) native;\n', | 1300 NAME=attr.id, HTML_NAME=html_name, TYPE=DartType(attr.type.id), |
989 NAME=attr.id, TYPE=attr.type.id, METHOD=method_name) | 1301 THIS=self.DomObjectName()) |
990 | |
991 def _AddSetter(self, attr): | |
992 # FIXME: See comment on getter. | |
993 method_name = self._MethodName('_set_', attr.id) | |
994 self._members_emitter.Emit( | |
995 '\n' | |
996 ' void set $NAME($TYPE value) { $METHOD(this, value); }\n' | |
997 ' static void $METHOD(var _this, $TYPE value) native;\n', | |
998 NAME=attr.id, TYPE=attr.type.id, METHOD=method_name) | |
999 | 1302 |
1000 def AddSecondaryAttribute(self, interface, getter, setter): | 1303 def AddSecondaryAttribute(self, interface, getter, setter): |
1001 self._SecondaryContext(interface) | 1304 self._SecondaryContext(interface) |
1002 self.AddAttribute(getter, setter) | 1305 self.AddAttribute(getter, setter) |
1003 | 1306 |
1004 def AddSecondaryOperation(self, interface, info): | 1307 def AddSecondaryOperation(self, interface, info): |
1005 self._SecondaryContext(interface) | 1308 self._SecondaryContext(interface) |
1006 self.AddOperation(info) | 1309 self.AddOperation(info) |
1007 | 1310 |
1008 def AddEventAttributes(self, event_attrs): | 1311 def AddEventAttributes(self, event_attrs): |
1009 pass | 1312 event_attrs = _DomToHtmlEvents(self._interface.id, event_attrs) |
1313 events_class = '_' + self._interface.id + 'EventsImpl' | |
1314 events_interface = self._interface.id + 'Events' | |
1315 self._members_emitter.Emit( | |
1316 '\n' | |
1317 ' $TYPE get on() {\n' | |
1318 ' if (_on == null) _on = new $TYPE($EVENTTARGET);\n' | |
1319 ' return _on;\n' | |
1320 ' }\n', | |
1321 TYPE=events_class, | |
1322 EVENTTARGET='_wrappedDocumentPtr' if self._interface.id == 'Document' | |
1323 else 'this') | |
1324 | |
1325 self._shared._event_classes.add(self._interface.id) | |
1326 | |
1327 parent_event_classes = self._shared.GetParentsEventsClasses( | |
1328 self._interface) | |
1329 if len(parent_event_classes) != 1: | |
1330 raise Exception('Only one parent event class allowed ' | |
1331 + self._interface.id) | |
1332 | |
1333 # TODO(jacobr): specify the type of _ptr as EventTarget | |
1334 events_members = self._dart_code.Emit( | |
1335 '\n' | |
1336 'class $CLASSNAME extends $SUPER implements $INTERFACE {\n' | |
1337 ' $CLASSNAME(_ptr) : super(_ptr);\n' | |
1338 '$!MEMBERS}\n', | |
1339 TARGETCLASS=self._NarrowOutputType(self._interface.id), | |
sra1
2012/02/29 23:11:55
TARGETCLASS appears to be unused.
Jacob
2012/03/01 00:40:44
Done.
| |
1340 CLASSNAME=events_class, | |
1341 INTERFACE=events_interface, | |
1342 SUPER='_' + parent_event_classes[0] + 'Impl') | |
1343 | |
1344 for event_name in event_attrs: | |
1345 if event_name in _html_event_names: | |
1346 events_members.Emit( | |
1347 "\n" | |
1348 " EventListenerList get $NAME() => _get('$RAWNAME');\n", | |
1349 RAWNAME=event_name, | |
1350 NAME=_html_event_names[event_name]) | |
1351 else: | |
1352 raise Exception('No known html even name for event: ' + event_name) | |
1010 | 1353 |
1011 def _SecondaryContext(self, interface): | 1354 def _SecondaryContext(self, interface): |
1012 if interface is not self._current_secondary_parent: | 1355 if interface is not self._current_secondary_parent: |
1013 self._current_secondary_parent = interface | 1356 self._current_secondary_parent = interface |
1014 self._members_emitter.Emit('\n // From $WHERE\n', WHERE=interface.id) | 1357 self._members_emitter.Emit('\n // From $WHERE\n', WHERE=interface.id) |
1015 | 1358 |
1359 # TODO(jacobr): change this to more directly match the frog version. | |
1016 def AddIndexer(self, element_type): | 1360 def AddIndexer(self, element_type): |
1017 """Adds all the methods required to complete implementation of List.""" | 1361 """Adds all the methods required to complete implementation of List.""" |
1018 # We would like to simply inherit the implementation of everything except | 1362 # We would like to simply inherit the implementation of everything except |
1019 # get length(), [], and maybe []=. It is possible to extend from a base | 1363 # get length(), [], and maybe []=. It is possible to extend from a base |
1020 # array implementation class only when there is no other implementation | 1364 # array implementation class only when there is no other implementation |
1021 # inheritance. There might be no implementation inheritance other than | 1365 # inheritance. There might be no implementation inheritance other than |
1022 # DOMBaseWrapper for many classes, but there might be some where the | 1366 # DOMBaseWrapper for many classes, but there might be some where the |
1023 # array-ness is introduced by a non-root interface: | 1367 # array-ness is introduced by a non-root interface: |
1024 # | 1368 # |
1025 # interface Y extends X, List<T> ... | 1369 # interface Y extends X, List<T> ... |
1026 # | 1370 # |
1027 # In the non-root case we have to choose between: | 1371 # In the non-root case we have to choose between: |
1028 # | 1372 # |
1029 # class YImpl extends XImpl { add List<T> methods; } | 1373 # class YImpl extends XImpl { add List<T> methods; } |
1030 # | 1374 # |
1031 # and | 1375 # and |
1032 # | 1376 # |
1033 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | 1377 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } |
1034 # | 1378 # |
1035 if self._HasNativeIndexGetter(self._interface): | 1379 if self._HasNativeIndexGetter(self._interface): |
1036 self._EmitNativeIndexGetter(self._interface, element_type) | 1380 self._EmitNativeIndexGetter(self._interface, element_type) |
1037 else: | 1381 else: |
1038 self._members_emitter.Emit( | 1382 self._members_emitter.Emit( |
1039 '\n' | 1383 '\n' |
1040 ' $TYPE operator[](int index) {\n' | 1384 ' $TYPE operator[](int index) => _wrap($(THIS)[index]);\n' |
1041 ' return item(index);\n' | 1385 '\n', |
1042 ' }\n', | 1386 THIS=self.DomObjectName(), |
1043 TYPE=DartType(element_type)) | 1387 TYPE=DartType(element_type)) |
1044 | 1388 |
1045 if self._HasNativeIndexSetter(self._interface): | 1389 if self._HasNativeIndexSetter(self._interface): |
1046 self._EmitNativeIndexSetter(self._interface, element_type) | 1390 self._EmitNativeIndexSetter(self._interface, element_type) |
1047 else: | 1391 else: |
1048 self._members_emitter.Emit( | 1392 # The HTML library implementation of NodeList has a custom indexed setter |
1049 '\n' | 1393 # implementation that uses the parent node the NodeList is associated |
1050 ' void operator[]=(int index, $TYPE value) {\n' | 1394 # with if one is available. |
1051 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' | 1395 if self._interface.id != 'NodeList': |
1052 ' }\n', | 1396 self._members_emitter.Emit( |
1053 TYPE=element_type) | 1397 '\n' |
1398 ' void operator[]=(int index, $TYPE value) {\n' | |
1399 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' | |
1400 ' }\n', | |
1401 TYPE=DartType(element_type)) | |
1402 | |
1403 # The list interface for this class is manually generated. | |
1404 if self._interface.id == 'NodeList': | |
1405 return | |
1054 | 1406 |
1055 self._members_emitter.Emit( | 1407 self._members_emitter.Emit( |
1056 '\n' | 1408 '\n' |
1057 ' void add($TYPE value) {\n' | 1409 ' void add($TYPE value) {\n' |
1058 ' throw new UnsupportedOperationException("Cannot add to immutable Li st.");\n' | 1410 ' throw new UnsupportedOperationException("Cannot add to immutable Li st.");\n' |
1059 ' }\n' | 1411 ' }\n' |
1060 '\n' | 1412 '\n' |
1061 ' void addLast($TYPE value) {\n' | 1413 ' void addLast($TYPE value) {\n' |
1062 ' throw new UnsupportedOperationException("Cannot add to immutable Li st.");\n' | 1414 ' throw new UnsupportedOperationException("Cannot add to immutable Li st.");\n' |
1063 ' }\n' | 1415 ' }\n' |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1132 ' throw new NotImplementedException();\n' | 1484 ' throw new NotImplementedException();\n' |
1133 ' }\n' | 1485 ' }\n' |
1134 '\n' | 1486 '\n' |
1135 ' bool isEmpty() {\n' | 1487 ' bool isEmpty() {\n' |
1136 ' return length == 0;\n' | 1488 ' return length == 0;\n' |
1137 ' }\n' | 1489 ' }\n' |
1138 '\n' | 1490 '\n' |
1139 ' Iterator<$TYPE> iterator() {\n' | 1491 ' Iterator<$TYPE> iterator() {\n' |
1140 ' return new _FixedSizeListIterator<$TYPE>(this);\n' | 1492 ' return new _FixedSizeListIterator<$TYPE>(this);\n' |
1141 ' }\n', | 1493 ' }\n', |
1142 TYPE=element_type) | 1494 TYPE=DartType(element_type)) |
1143 | 1495 |
1144 def _HasNativeIndexGetter(self, interface): | 1496 def _HasNativeIndexGetter(self, interface): |
1145 return ('HasIndexGetter' in interface.ext_attrs or | 1497 return ('HasIndexGetter' in interface.ext_attrs or |
1146 'HasNumericIndexGetter' in interface.ext_attrs) | 1498 'HasNumericIndexGetter' in interface.ext_attrs) |
1147 | 1499 |
1148 def _EmitNativeIndexGetter(self, interface, element_type): | 1500 def _EmitNativeIndexGetter(self, interface, element_type): |
1149 method_name = '_index' | 1501 method_name = '_index' |
1150 self._members_emitter.Emit( | 1502 self._members_emitter.Emit( |
1151 '\n' | 1503 '\n $TYPE operator[](int index) => _wrap($(THIS)[index]);\n', |
1152 ' $TYPE operator[](int index) { return $METHOD(this, index); }\n' | 1504 TYPE=DartType(element_type), THIS=self.DomObjectName(), METHOD=method_na me) |
1153 ' static $TYPE $METHOD(var _this, int index) native;\n', | |
1154 TYPE=element_type, METHOD=method_name) | |
1155 | 1505 |
1156 def _HasNativeIndexSetter(self, interface): | 1506 def _HasNativeIndexSetter(self, interface): |
1157 return 'HasCustomIndexSetter' in interface.ext_attrs | 1507 return 'HasCustomIndexSetter' in interface.ext_attrs |
1158 | 1508 |
1159 def _EmitNativeIndexSetter(self, interface, element_type): | 1509 def _EmitNativeIndexSetter(self, interface, element_type): |
1160 method_name = '_set_index' | 1510 method_name = '_set_index' |
1161 self._members_emitter.Emit( | 1511 self._members_emitter.Emit( |
1162 '\n' | 1512 '\n' |
1163 ' void operator[]=(int index, $TYPE value) {\n' | 1513 ' void operator[]=(int index, $TYPE value) {\n' |
1164 ' return $METHOD(this, index, value);\n' | 1514 ' return $(THIS)[index] = _unwrap(value);\n' |
1165 ' }\n' | 1515 ' }\n', |
1166 ' static $METHOD(_this, index, value) native;\n', | 1516 THIS=self.DomObjectName(), TYPE=DartType(element_type), METHOD=method_na me) |
1167 TYPE=element_type, METHOD=method_name) | |
1168 | 1517 |
1169 def AddOperation(self, info): | 1518 def AddOperation(self, info): |
1170 """ | 1519 """ |
1171 Arguments: | 1520 Arguments: |
1172 info: An OperationInfo object. | 1521 info: An OperationInfo object. |
1173 """ | 1522 """ |
1523 html_name = self._shared.RenameInHtmlLibrary(self._interface, info.name) | |
1524 | |
1525 if not html_name: | |
1526 return | |
1527 | |
1174 body = self._members_emitter.Emit( | 1528 body = self._members_emitter.Emit( |
1175 '\n' | 1529 '\n' |
1176 ' $TYPE $NAME($PARAMS) {\n' | 1530 ' $TYPE $HTML_NAME($PARAMS) {\n' |
1177 '$!BODY' | 1531 '$!BODY' |
1178 ' }\n', | 1532 ' }\n', |
1179 TYPE=info.type_name, | 1533 TYPE=info.type_name, |
1180 NAME=info.name, | 1534 HTML_NAME=html_name, |
1181 PARAMS=info.ParametersImplementationDeclaration()) | 1535 PARAMS=info.ParametersImplementationDeclaration()) |
1182 | 1536 |
1183 # Process in order of ascending number of arguments to ensure missing | 1537 # Process in order of ascending number of arguments to ensure missing |
1184 # optional arguments are processed early. | 1538 # optional arguments are processed early. |
1185 overloads = sorted(info.overloads, | 1539 overloads = sorted(info.overloads, |
1186 key=lambda overload: len(overload.arguments)) | 1540 key=lambda overload: len(overload.arguments)) |
1187 self._native_version = 0 | 1541 self._native_version = 0 |
1188 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) | 1542 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) |
1189 if fallthrough: | 1543 if fallthrough: |
1190 body.Emit(' throw "Incorrect number or type of arguments";\n'); | 1544 body.Emit(' throw "Incorrect number or type of arguments";\n'); |
1191 | 1545 |
1192 def GenerateSingleOperation(self, emitter, info, indent, operation): | 1546 def GenerateSingleOperation(self, emitter, info, indent, operation): |
1193 """Generates a call to a single operation. | 1547 """Generates a call to a single operation. |
1194 | 1548 |
1195 Arguments: | 1549 Arguments: |
1196 emitter: an Emitter for the body of a block of code. | 1550 emitter: an Emitter for the body of a block of code. |
1197 info: the compound information about the operation and its overloads. | 1551 info: the compound information about the operation and its overloads. |
1198 indent: an indentation string for generated code. | 1552 indent: an indentation string for generated code. |
1199 operation: the IDLOperation to call. | 1553 operation: the IDLOperation to call. |
1200 """ | 1554 """ |
1201 # TODO(sra): Do we need to distinguish calling with missing optional | 1555 # TODO(sra): Do we need to distinguish calling with missing optional |
1202 # arguments from passing 'null' which is represented as 'undefined'? | 1556 # arguments from passing 'null' which is represented as 'undefined'? |
1203 def UnwrapArgExpression(name, type): | 1557 def UnwrapArgExpression(name, type): |
1204 # TODO: Type specific unwrapping. | 1558 # TODO: Type specific unwrapping. |
1205 return '__dom_unwrap(%s)' % (name) | 1559 return '_unwrap(%s)' % (name) |
1206 | 1560 |
1207 def ArgNameAndUnwrapper(arg_info, overload_arg): | 1561 def ArgNameAndUnwrapper(arg_info, overload_arg): |
1208 (name, type, value) = arg_info | 1562 (name, type, value) = arg_info |
1209 return (name, UnwrapArgExpression(name, type)) | 1563 return (name, UnwrapArgExpression(name, type)) |
1210 | 1564 |
1211 names_and_unwrappers = [ArgNameAndUnwrapper(info.arg_infos[i], arg) | 1565 names_and_unwrappers = [ArgNameAndUnwrapper(info.arg_infos[i], arg) |
1212 for (i, arg) in enumerate(operation.arguments)] | 1566 for (i, arg) in enumerate(operation.arguments)] |
1213 unwrap_args = [unwrap_arg for (_, unwrap_arg) in names_and_unwrappers] | 1567 unwrap_args = [unwrap_arg for (_, unwrap_arg) in names_and_unwrappers] |
1214 arg_names = [name for (name, _) in names_and_unwrappers] | 1568 arg_names = ['_unwrap(%s)' % name for (name, _) in names_and_unwrappers] |
1215 | 1569 |
1216 self._native_version += 1 | 1570 argument_expressions = ', '.join(arg_names) |
1217 native_name = self._MethodName('_', info.name) | |
1218 if self._native_version > 1: | |
1219 native_name = '%s_%s' % (native_name, self._native_version) | |
1220 | |
1221 argument_expressions = ', '.join(['this'] + arg_names) | |
1222 if info.type_name != 'void': | 1571 if info.type_name != 'void': |
1223 emitter.Emit('$(INDENT)return $NATIVENAME($ARGS);\n', | 1572 # We could place the logic for handling Document directly in _wrap |
1224 INDENT=indent, | 1573 # but we chose to place it here so that bugs in the wrapper and |
1225 NATIVENAME=native_name, | 1574 # wrapperless implementations are more consistent. |
1226 ARGS=argument_expressions) | 1575 if self._shared.MaybeReturnDocument(info.type_name): |
1576 emitter.Emit('$(INDENT)return _FixHtmlDocumentReference(' | |
1577 '_wrap($(THIS).$NAME($ARGS)));\n', | |
1578 INDENT=indent, | |
1579 THIS=self.DomObjectName(), | |
1580 NAME=info.name, | |
1581 ARGS=argument_expressions) | |
1582 else: | |
1583 emitter.Emit('$(INDENT)return _wrap($(THIS).$NAME($ARGS));\n', | |
1584 INDENT=indent, | |
1585 THIS=self.DomObjectName(), | |
1586 NAME=info.name, | |
1587 ARGS=argument_expressions) | |
1227 else: | 1588 else: |
1228 emitter.Emit('$(INDENT)$NATIVENAME($ARGS);\n' | 1589 emitter.Emit('$(INDENT)$(THIS).$NAME($ARGS);\n' |
1229 '$(INDENT)return;\n', | 1590 '$(INDENT)return;\n', |
1230 INDENT=indent, | 1591 INDENT=indent, |
1231 NATIVENAME=native_name, | 1592 THIS=self.DomObjectName(), |
1593 NAME=info.name, | |
1232 ARGS=argument_expressions) | 1594 ARGS=argument_expressions) |
1233 | 1595 |
1234 self._members_emitter.Emit(' static $TYPE $NAME($PARAMS) native;\n', | |
1235 NAME=native_name, | |
1236 TYPE=info.type_name, | |
1237 PARAMS=', '.join(['receiver'] + arg_names) ) | |
1238 | |
1239 | |
1240 def GenerateDispatch(self, emitter, info, indent, position, overloads): | 1596 def GenerateDispatch(self, emitter, info, indent, position, overloads): |
1241 """Generates a dispatch to one of the overloads. | 1597 """Generates a dispatch to one of the overloads. |
1242 | 1598 |
1243 Arguments: | 1599 Arguments: |
1244 emitter: an Emitter for the body of a block of code. | 1600 emitter: an Emitter for the body of a block of code. |
1245 info: the compound information about the operation and its overloads. | 1601 info: the compound information about the operation and its overloads. |
1246 indent: an indentation string for generated code. | 1602 indent: an indentation string for generated code. |
1247 position: the index of the parameter to dispatch on. | 1603 position: the index of the parameter to dispatch on. |
1248 overloads: a list of the remaining IDLOperations to dispatch. | 1604 overloads: a list of the remaining IDLOperations to dispatch. |
1249 | 1605 |
(...skipping 22 matching lines...) Expand all Loading... | |
1272 positive = [] | 1628 positive = [] |
1273 negative = [] | 1629 negative = [] |
1274 first_overload = overloads[0] | 1630 first_overload = overloads[0] |
1275 (param_name, param_type, param_default) = info.arg_infos[position] | 1631 (param_name, param_type, param_default) = info.arg_infos[position] |
1276 | 1632 |
1277 if position < len(first_overload.arguments): | 1633 if position < len(first_overload.arguments): |
1278 # FIXME: This will not work if the second overload has a more | 1634 # FIXME: This will not work if the second overload has a more |
1279 # precise type than the first. E.g., | 1635 # precise type than the first. E.g., |
1280 # void foo(Node x); | 1636 # void foo(Node x); |
1281 # void foo(Element x); | 1637 # void foo(Element x); |
1282 type = first_overload.arguments[position].type.id | 1638 type = DartType(first_overload.arguments[position].type.id) |
1283 test = TypeCheck(param_name, type) | 1639 test = TypeCheck(param_name, type) |
1284 pred = lambda op: len(op.arguments) > position and op.arguments[position]. type.id == type | 1640 pred = lambda op: (len(op.arguments) > position and |
1641 DartType(op.arguments[position].type.id) == type) | |
1285 else: | 1642 else: |
1286 type = None | 1643 type = None |
1287 test = NullCheck(param_name) | 1644 test = NullCheck(param_name) |
1288 pred = lambda op: position >= len(op.arguments) | 1645 pred = lambda op: position >= len(op.arguments) |
1289 | 1646 |
1290 for overload in overloads: | 1647 for overload in overloads: |
1291 if pred(overload): | 1648 if pred(overload): |
1292 positive.append(overload) | 1649 positive.append(overload) |
1293 else: | 1650 else: |
1294 negative.append(overload) | 1651 negative.append(overload) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1326 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee | 1683 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee |
1327 # that Y = Z-X, so we need to check for Y. | 1684 # that Y = Z-X, so we need to check for Y. |
1328 true_code = emitter.Emit( | 1685 true_code = emitter.Emit( |
1329 '$(INDENT)if ($COND) {\n' | 1686 '$(INDENT)if ($COND) {\n' |
1330 '$!TRUE' | 1687 '$!TRUE' |
1331 '$(INDENT)}\n', | 1688 '$(INDENT)}\n', |
1332 COND=test, INDENT=indent) | 1689 COND=test, INDENT=indent) |
1333 self.GenerateDispatch( | 1690 self.GenerateDispatch( |
1334 true_code, info, indent + ' ', position + 1, positive) | 1691 true_code, info, indent + ' ', position + 1, positive) |
1335 return True | 1692 return True |
OLD | NEW |