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