Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: client/dom/scripts/systemhtml.py

Issue 9537001: Generate dart:html bindings for Dartium as well as Frog. All unittests now pass (or are disabled fo… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698