Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
dartmetadata.py
Go to the documentation of this file.
1#!/usr/bin/env python3
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
4# BSD-style license that can be found in the LICENSE file.
5"""This module provides shared functionality to provide Dart metadata for
6DOM APIs.
7"""
8
9import copy
10import json
11import logging
12import monitored
13import os
14import re
15from htmlrenamer import renamed_html_members, html_interface_renames
16
17_logger = logging.getLogger('dartmetadata')
18
19# Annotations to be placed on native members. The table is indexed by the IDL
20# interface and member name, and by IDL return or field type name. Both are
21# used to assemble the annotations:
22#
23# INTERFACE.MEMBER: annotations for member.
24# +TYPE: add annotations only if there are member annotations.
25# -TYPE: add annotations only if there are no member annotations.
26# TYPE: add regardless of member annotations.
27
28_dart2js_annotations = monitored.Dict(
29 'dartmetadata._dart2js_annotations',
30 {
31 'AnimationEffectTiming.duration': [
32 "@Returns('num|String|Null')",
33 ],
34 'ArrayBufferView': [
35 "@Creates('TypedData')",
36 "@Returns('TypedData|Null')",
37 ],
38 'CanvasRenderingContext2D.createImageData': [
39 "@Creates('ImageData|=Object')",
40 ],
41 'CanvasRenderingContext2D.getImageData': [
42 "@Creates('ImageData|=Object')",
43 ],
44 'CanvasRenderingContext2D.webkitGetImageDataHD': [
45 "@Creates('ImageData|=Object')",
46 ],
47 'CanvasRenderingContext2D.fillStyle': [
48 "@Creates('String|CanvasGradient|CanvasPattern')",
49 "@Returns('String|CanvasGradient|CanvasPattern')",
50 ],
51 'CanvasRenderingContext2D.strokeStyle': [
52 "@Creates('String|CanvasGradient|CanvasPattern')",
53 "@Returns('String|CanvasGradient|CanvasPattern')",
54 ],
55 'CryptoKey.algorithm': [
56 "@Creates('Null')",
57 ],
58 'CustomEvent._detail': [
59 "@Creates('Null')",
60 ],
61
62 # Normally Window is never null, but starting from a <template> element in
63 # JavaScript, this will be null:
64 # template.content.ownerDocument.defaultView
65 'Document.window': [
66 "@Creates('Window|=Object|Null')",
67 "@Returns('Window|=Object|Null')",
68 ],
69 'Document.getElementsByClassName': [
70 "@Creates('NodeList|HtmlCollection')",
71 "@Returns('NodeList|HtmlCollection')",
72 ],
73 'Document.getElementsByName': [
74 "@Creates('NodeList|HtmlCollection')",
75 "@Returns('NodeList|HtmlCollection')",
76 ],
77 'Document.getElementsByTagName': [
78 "@Creates('NodeList|HtmlCollection')",
79 "@Returns('NodeList|HtmlCollection')",
80 ],
81
82 # querySelectorAll never returns `null`.
83 'Document.querySelectorAll': [
84 "@Creates('NodeList')",
85 "@Returns('NodeList')",
86 ],
87 'DocumentFragment.querySelectorAll': [
88 "@Creates('NodeList')",
89 "@Returns('NodeList')",
90 ],
91 'Element.querySelectorAll': [
92 "@Creates('NodeList')",
93 "@Returns('NodeList')",
94 ],
95 'Element.getBoundingClientRect': [
96 "@Creates('_DomRect')",
97 "@Returns('_DomRect|Null')", # TODO(sra): Verify and remove Null.
98 ],
99 'Element.getClientRects': [
100 "@Creates('DomRectList')",
101 "@Returns('DomRectList|Null')",
102 ],
103
104 # Methods returning Window can return a local window, or a cross-frame
105 # window (=Object) that needs wrapping.
106 'Window': [
107 "@Creates('Window|=Object')",
108 "@Returns('Window|=Object')",
109 ],
110 'Window.openDatabase': [
111 "@Creates('SqlDatabase')",
112 ],
113 'Window.showModalDialog': [
114 "@Creates('Null')",
115 ],
116 'Element.webkitGetRegionFlowRanges': [
117 "@Creates('JSExtendableArray')",
118 "@Returns('JSExtendableArray')",
119 ],
120 'Element.getElementsByClassName': [
121 "@Creates('NodeList|HtmlCollection')",
122 "@Returns('NodeList|HtmlCollection')",
123 ],
124 'Element.getElementsByName': [
125 "@Creates('NodeList|HtmlCollection')",
126 "@Returns('NodeList|HtmlCollection')",
127 ],
128 'Element.getElementsByTagName': [
129 "@Creates('NodeList|HtmlCollection')",
130 "@Returns('NodeList|HtmlCollection')",
131 ],
132 "ErrorEvent.error": [
133 "@Creates('Null')", # Only returns values created elsewhere.
134 ],
135
136 # To be in callback with the browser-created Event, we had to have called
137 # addEventListener on the target, so we avoid
138 'Event.currentTarget': [
139 "@Creates('Null')",
140 "@Returns('EventTarget|=Object|Null')",
141 ],
142
143 # Only nodes in the DOM bubble and have target !== currentTarget.
144 'Event.target': [
145 "@Creates('Node')",
146 "@Returns('EventTarget|=Object')",
147 ],
148
149 # TODO(sra): Investigate how ExtendableMessageEvent.data is different from
150 # MessageEvent.data. It might be necessary to put in a method to translate
151 # the JavaScript wire type into a Dart type.
152 'ExtendableMessageEvent.data': [
153 "@annotation_Creates_SerializedScriptValue",
154 "@annotation_Returns_SerializedScriptValue",
155 ],
156
157 # TODO(sra): We could determine the following by parsing the compound IDL
158 # type.
159 'ExtendableMessageEvent.source': [
160 "@Creates('Client|ServiceWorker|MessagePort')",
161 "@Returns('Client|ServiceWorker|MessagePort|Null')",
162 ],
163 'File.lastModifiedDate': [
164 "@Creates('Null')", # JS date object.
165 ],
166 'FocusEvent.relatedTarget': [
167 "@Creates('Null')",
168 ],
169 'Gamepad.buttons': [
170 "@Creates('JSExtendableArray|GamepadButton')",
171 "@Returns('JSExtendableArray')",
172 ],
173 # Creates a GeolocationPosition or a GeolocationPositionError for a
174 # callback. See issue #45562.
175 'Geolocation.getCurrentPosition': [
176 "@Creates('Geoposition')",
177 "@Creates('PositionError')",
178 ],
179 'Geolocation.watchPosition': [
180 "@Creates('Geoposition')",
181 "@Creates('PositionError')",
182 ],
183 'HTMLCanvasElement.getContext': [
184 "@Creates('CanvasRenderingContext2D|RenderingContext|RenderingContext2')",
185 "@Returns('CanvasRenderingContext2D|RenderingContext|RenderingContext2|Null')",
186 ],
187 'HTMLInputElement.valueAsDate': [
188 "@Creates('Null')", # JS date object.
189 ],
190
191 # Rather than have the result of an IDBRequest as a union over all possible
192 # results, we mark the result as instantiating any classes, and mark
193 # each operation with the classes that it could cause to be asynchronously
194 # instantiated.
195 'IDBRequest.result': ["@Creates('Null')"],
196
197 # The source is usually a participant in the operation that generated the
198 # IDBRequest.
199 'IDBRequest.source': ["@Creates('Null')"],
200 'IDBFactory.open': ["@Creates('Database')"],
201 'IDBFactory.webkitGetDatabaseNames': ["@Creates('DomStringList')"],
202 'IDBObjectStore.put': ["@_annotation_Creates_IDBKey"],
203 'IDBObjectStore.add': ["@_annotation_Creates_IDBKey"],
204 'IDBObjectStore.get': ["@annotation_Creates_SerializedScriptValue"],
205 'IDBObjectStore.openCursor': ["@Creates('Cursor')"],
206 'IDBIndex.get': ["@annotation_Creates_SerializedScriptValue"],
207 'IDBIndex.getKey': [
208 "@annotation_Creates_SerializedScriptValue",
209 # The source is the object store behind the index.
210 "@Creates('ObjectStore')",
211 ],
212 'IDBIndex.openCursor': ["@Creates('Cursor')"],
213 'IDBIndex.openKeyCursor': ["@Creates('Cursor')"],
214 'IDBCursorWithValue.value': [
215 '@annotation_Creates_SerializedScriptValue',
216 '@annotation_Returns_SerializedScriptValue',
217 ],
218 'IDBCursor.key': [
219 "@_annotation_Creates_IDBKey",
220 "@_annotation_Returns_IDBKey",
221 ],
222 'IDBCursor.primaryKey': [
223 "@_annotation_Creates_IDBKey",
224 "@_annotation_Returns_IDBKey",
225 ],
226 'IDBCursor.source': [
227 "@Creates('Null')",
228 "@Returns('ObjectStore|Index|Null')",
229 ],
230 'IDBDatabase.version': [
231 "@Creates('int|String|Null')",
232 "@Returns('int|String|Null')",
233 ],
234 'IDBIndex.keyPath': [
235 "@annotation_Creates_SerializedScriptValue",
236 ],
237 'IDBKeyRange.lower': [
238 "@annotation_Creates_SerializedScriptValue",
239 ],
240 'IDBKeyRange.upper': [
241 "@annotation_Creates_SerializedScriptValue",
242 ],
243 'IDBObjectStore.keyPath': [
244 "@annotation_Creates_SerializedScriptValue",
245 ],
246 '+IDBOpenDBRequest': [
247 "@Returns('Request')",
248 "@Creates('Request')",
249 ],
250 '+IDBRequest': [
251 "@Returns('Request')",
252 "@Creates('Request')",
253 ],
254 'IDBVersionChangeEvent.newVersion': [
255 "@Creates('int|String|Null')",
256 "@Returns('int|String|Null')",
257 ],
258 'IDBVersionChangeEvent.oldVersion': [
259 "@Creates('int|String|Null')",
260 "@Returns('int|String|Null')",
261 ],
262 'ImageData.data': [
263 "@Creates('NativeUint8ClampedList')",
264 "@Returns('NativeUint8ClampedList')",
265 ],
266 'MediaStream.getAudioTracks': [
267 "@Creates('JSExtendableArray|MediaStreamTrack')",
268 "@Returns('JSExtendableArray')",
269 ],
270 'MediaStream.getVideoTracks': [
271 "@Creates('JSExtendableArray|MediaStreamTrack')",
272 "@Returns('JSExtendableArray')",
273 ],
274 'MessageEvent.data': [
275 "@annotation_Creates_SerializedScriptValue",
276 "@annotation_Returns_SerializedScriptValue",
277 ],
278 'MessageEvent.ports': ["@Creates('JSExtendableArray')"],
279 'MessageEvent.source': [
280 "@Creates('Null')",
281 "@Returns('EventTarget|=Object')",
282 ],
283 'Metadata.modificationTime': [
284 "@Creates('Null')", # JS date object.
285 ],
286 'MouseEvent.relatedTarget': [
287 "@Creates('Node')",
288 "@Returns('EventTarget|=Object|Null')",
289 ],
290 'Notification.data': [
291 "@annotation_Creates_SerializedScriptValue",
292 "@annotation_Returns_SerializedScriptValue",
293 ],
294 'PopStateEvent.state': [
295 "@annotation_Creates_SerializedScriptValue",
296 "@annotation_Returns_SerializedScriptValue",
297 ],
298 'RTCStatsReport.timestamp': [
299 "@Creates('Null')", # JS date object.
300 ],
301 'SerializedScriptValue': [
302 "@annotation_Creates_SerializedScriptValue",
303 "@annotation_Returns_SerializedScriptValue",
304 ],
305 'ServiceWorkerMessageEvent.data': [
306 "@annotation_Creates_SerializedScriptValue",
307 "@annotation_Returns_SerializedScriptValue",
308 ],
309 'ServiceWorkerMessageEvent.source': [
310 "@Creates('Null')",
311 "@Returns('ServiceWorker|MessagePort')",
312 ],
313 'ShadowRoot.getElementsByClassName': [
314 "@Creates('NodeList|HtmlCollection')",
315 "@Returns('NodeList|HtmlCollection')",
316 ],
317 'ShadowRoot.getElementsByName': [
318 "@Creates('NodeList|HtmlCollection')",
319 "@Returns('NodeList|HtmlCollection')",
320 ],
321 'ShadowRoot.getElementsByTagName': [
322 "@Creates('NodeList|HtmlCollection')",
323 "@Returns('NodeList|HtmlCollection')",
324 ],
325
326 # Touch targets are Elements in a Document, or the Document.
327 'Touch.target': [
328 "@Creates('Element|Document')",
329 "@Returns('Element|Document')",
330 ],
331 'TrackEvent.track': [
332 "@Creates('Null')",
333 ],
334 'VTTCue.line': [
335 "@Creates('Null')",
336 "@Returns('num|String')",
337 ],
338 'VTTCue.position': [
339 "@Creates('Null')",
340 "@Returns('num|String')",
341 ],
342 'WebGLRenderingContext.getBufferParameter': [
343 "@Creates('int|Null')",
344 "@Returns('int|Null')",
345 ],
346 'WebGLRenderingContext.getFramebufferAttachmentParameter': [
347 "@Creates('int|Renderbuffer|Texture|Null')",
348 "@Returns('int|Renderbuffer|Texture|Null')",
349 ],
350 'WebGLRenderingContext.getProgramParameter': [
351 "@Creates('int|bool|Null')",
352 "@Returns('int|bool|Null')",
353 ],
354 'WebGLRenderingContext.getRenderbufferParameter': [
355 "@Creates('int|Null')",
356 "@Returns('int|Null')",
357 ],
358 'WebGLRenderingContext.getShaderParameter': [
359 "@Creates('int|bool|Null')",
360 "@Returns('int|bool|Null')",
361 ],
362 'WebGLRenderingContext.getTexParameter': [
363 "@Creates('int|Null')",
364 "@Returns('int|Null')",
365 ],
366 'WebGLRenderingContext.getUniform': [
367 "@Creates('Null|num|String|bool|JSExtendableArray|"
368 "NativeFloat32List|NativeInt32List|NativeUint32List')",
369 "@Returns('Null|num|String|bool|JSExtendableArray|"
370 "NativeFloat32List|NativeInt32List|NativeUint32List')",
371 ],
372 'WebGLRenderingContext.getVertexAttrib': [
373 "@Creates('Null|num|bool|NativeFloat32List|Buffer')",
374 "@Returns('Null|num|bool|NativeFloat32List|Buffer')",
375 ],
376 'WebGLRenderingContext.getParameter': [
377 # Taken from http://www.khronos.org/registry/webgl/specs/latest/
378 # Section 5.14.3 Setting and getting state
379 "@Creates('Null|num|String|bool|JSExtendableArray|"
380 "NativeFloat32List|NativeInt32List|NativeUint32List|"
381 "Framebuffer|Renderbuffer|Texture')",
382 "@Returns('Null|num|String|bool|JSExtendableArray|"
383 "NativeFloat32List|NativeInt32List|NativeUint32List|"
384 "Framebuffer|Renderbuffer|Texture')",
385 ],
386 'WebGLRenderingContext.getContextAttributes': [
387 "@Creates('ContextAttributes|Null')",
388 ],
389 'XMLHttpRequest.response': [
390 "@Creates('NativeByteBuffer|Blob|Document|=Object|JSExtendableArray"
391 "|String|num')",
392 ],
393 },
394 dart2jsOnly=True)
395
396_blink_experimental_annotations = [
397 "@SupportedBrowser(SupportedBrowser.CHROME)",
398]
399
400_indexed_db_annotations = [
401 "@SupportedBrowser(SupportedBrowser.CHROME)",
402 "@SupportedBrowser(SupportedBrowser.FIREFOX, '15')",
403 "@SupportedBrowser(SupportedBrowser.IE, '10')",
404]
405
406_file_system_annotations = [
407 "@SupportedBrowser(SupportedBrowser.CHROME)",
408]
409
410_all_but_ie9_annotations = [
411 "@SupportedBrowser(SupportedBrowser.CHROME)",
412 "@SupportedBrowser(SupportedBrowser.FIREFOX)",
413 "@SupportedBrowser(SupportedBrowser.IE, '10')",
414 "@SupportedBrowser(SupportedBrowser.SAFARI)",
415]
416
417_history_annotations = _all_but_ie9_annotations
418
419_no_ie_annotations = [
420 "@SupportedBrowser(SupportedBrowser.CHROME)",
421 "@SupportedBrowser(SupportedBrowser.FIREFOX)",
422 "@SupportedBrowser(SupportedBrowser.SAFARI)",
423]
424
425_performance_annotations = [
426 "@SupportedBrowser(SupportedBrowser.CHROME)",
427 "@SupportedBrowser(SupportedBrowser.FIREFOX)",
428 "@SupportedBrowser(SupportedBrowser.IE)",
429]
430
431_rtc_annotations = [ # Note: Firefox nightly builds also support this.
432 "@SupportedBrowser(SupportedBrowser.CHROME)",
433]
434
435_shadow_dom_annotations = [
436 "@SupportedBrowser(SupportedBrowser.CHROME, '26')",
437]
438
439_speech_recognition_annotations = [
440 "@SupportedBrowser(SupportedBrowser.CHROME, '25')",
441]
442
443_svg_annotations = _all_but_ie9_annotations
444
445_web_sql_annotations = [
446 "@SupportedBrowser(SupportedBrowser.CHROME)",
447 "@SupportedBrowser(SupportedBrowser.SAFARI)",
448]
449
450_webgl_annotations = [
451 "@SupportedBrowser(SupportedBrowser.CHROME)",
452 "@SupportedBrowser(SupportedBrowser.FIREFOX)",
453]
454
455_web_audio_annotations = _webgl_annotations
456
457_webkit_experimental_annotations = [
458 "@SupportedBrowser(SupportedBrowser.CHROME)",
459 "@SupportedBrowser(SupportedBrowser.SAFARI)",
460]
461
462# Annotations to be placed on generated members.
463# The table is indexed as:
464# INTERFACE: annotations to be added to the interface declaration
465# INTERFACE.MEMBER: annotation to be added to the member declaration
466_annotations = monitored.Dict(
467 'dartmetadata._annotations',
468 {
469 'CSSHostRule':
470 _shadow_dom_annotations,
471 'WebKitCSSMatrix':
472 _webkit_experimental_annotations,
473 'Crypto':
474 _webkit_experimental_annotations,
475 'Database':
476 _web_sql_annotations,
477 'DatabaseSync':
478 _web_sql_annotations,
479 'ApplicationCache': [
480 "@SupportedBrowser(SupportedBrowser.CHROME)",
481 "@SupportedBrowser(SupportedBrowser.FIREFOX)",
482 "@SupportedBrowser(SupportedBrowser.IE, '10')",
483 "@SupportedBrowser(SupportedBrowser.OPERA)",
484 "@SupportedBrowser(SupportedBrowser.SAFARI)",
485 ],
486 'AudioBufferSourceNode':
487 _web_audio_annotations,
488 'AudioContext':
489 _web_audio_annotations,
490 'DOMFileSystem':
491 _file_system_annotations,
492 'DOMFileSystemSync':
493 _file_system_annotations,
494 'Window.indexedDB':
495 _indexed_db_annotations,
496 'Window.openDatabase':
497 _web_sql_annotations,
498 'Window.performance':
499 _performance_annotations,
500 'Window.webkitNotifications':
501 _webkit_experimental_annotations,
502 'Window.webkitRequestFileSystem':
503 _file_system_annotations,
504 'Window.webkitResolveLocalFileSystemURL':
505 _file_system_annotations,
506 'Element.createShadowRoot': [
507 "@SupportedBrowser(SupportedBrowser.CHROME, '25')",
508 ],
509 'Element.ontransitionend':
510 _all_but_ie9_annotations,
511 # Placeholder to add experimental flag, implementation for this is
512 # pending in a separate CL.
513 'Element.webkitMatchesSelector': [],
514 'Event.clipboardData': [
515 "@SupportedBrowser(SupportedBrowser.CHROME)",
516 "@SupportedBrowser(SupportedBrowser.FIREFOX)",
517 "@SupportedBrowser(SupportedBrowser.SAFARI)",
518 ],
519 'FormData':
520 _all_but_ie9_annotations,
521 'HashChangeEvent': [
522 "@SupportedBrowser(SupportedBrowser.CHROME)",
523 "@SupportedBrowser(SupportedBrowser.FIREFOX)",
524 "@SupportedBrowser(SupportedBrowser.SAFARI)",
525 ],
526 'History.pushState':
527 _history_annotations,
528 'History.replaceState':
529 _history_annotations,
530 'HTMLContentElement':
531 _shadow_dom_annotations,
532 'HTMLDataListElement':
533 _all_but_ie9_annotations,
534 'HTMLDetailsElement':
535 _webkit_experimental_annotations,
536 'HTMLEmbedElement': [
537 "@SupportedBrowser(SupportedBrowser.CHROME)",
538 "@SupportedBrowser(SupportedBrowser.IE)",
539 "@SupportedBrowser(SupportedBrowser.SAFARI)",
540 ],
541 'HTMLKeygenElement':
542 _webkit_experimental_annotations,
543 'HTMLMeterElement':
544 _no_ie_annotations,
545 'HTMLObjectElement': [
546 "@SupportedBrowser(SupportedBrowser.CHROME)",
547 "@SupportedBrowser(SupportedBrowser.IE)",
548 "@SupportedBrowser(SupportedBrowser.SAFARI)",
549 ],
550 'HTMLOutputElement':
551 _no_ie_annotations,
552 'HTMLProgressElement':
553 _all_but_ie9_annotations,
554 'HTMLShadowElement':
555 _shadow_dom_annotations,
556 'HTMLTemplateElement':
557 _blink_experimental_annotations,
558 'HTMLTrackElement': [
559 "@SupportedBrowser(SupportedBrowser.CHROME)",
560 "@SupportedBrowser(SupportedBrowser.IE, '10')",
561 "@SupportedBrowser(SupportedBrowser.SAFARI)",
562 ],
563 'IDBFactory':
564 _indexed_db_annotations,
565 'IDBDatabase':
566 _indexed_db_annotations,
567 'MediaStream':
568 _rtc_annotations,
569 'MediaStreamEvent':
570 _rtc_annotations,
571 'MediaStreamTrack':
572 _rtc_annotations,
573 'MediaStreamTrackEvent':
574 _rtc_annotations,
575 'MediaSource': [
576 # TODO(alanknight): This works on Firefox 33 behind a flag and in Safari
577 # desktop, but not mobile. On theory that static false positives are worse
578 # than negatives, leave those out for now. Update once they're available.
579 "@SupportedBrowser(SupportedBrowser.CHROME)",
580 "@SupportedBrowser(SupportedBrowser.IE, '11')",
581 ],
582 'MutationObserver': [
583 "@SupportedBrowser(SupportedBrowser.CHROME)",
584 "@SupportedBrowser(SupportedBrowser.FIREFOX)",
585 "@SupportedBrowser(SupportedBrowser.SAFARI)",
586 ],
587 'Performance':
588 _performance_annotations,
589 'PopStateEvent':
590 _history_annotations,
591 'RTCIceCandidate':
592 _rtc_annotations,
593 'RTCPeerConnection':
594 _rtc_annotations,
595 'RTCSessionDescription':
596 _rtc_annotations,
597 'ShadowRoot':
598 _shadow_dom_annotations,
599 'SpeechRecognition':
600 _speech_recognition_annotations,
601 'SpeechRecognitionAlternative':
602 _speech_recognition_annotations,
603 'SpeechRecognitionError':
604 _speech_recognition_annotations,
605 'SpeechRecognitionEvent':
606 _speech_recognition_annotations,
607 'SpeechRecognitionResult':
608 _speech_recognition_annotations,
609 'SVGAltGlyphElement':
610 _no_ie_annotations,
611 'SVGAnimateElement':
612 _no_ie_annotations,
613 'SVGAnimateMotionElement':
614 _no_ie_annotations,
615 'SVGAnimateTransformElement':
616 _no_ie_annotations,
617 'SVGFEBlendElement':
618 _svg_annotations,
619 'SVGFEColorMatrixElement':
620 _svg_annotations,
621 'SVGFEComponentTransferElement':
622 _svg_annotations,
623 'SVGFEConvolveMatrixElement':
624 _svg_annotations,
625 'SVGFEDiffuseLightingElement':
626 _svg_annotations,
627 'SVGFEDisplacementMapElement':
628 _svg_annotations,
629 'SVGFEDistantLightElement':
630 _svg_annotations,
631 'SVGFEFloodElement':
632 _svg_annotations,
633 'SVGFEFuncAElement':
634 _svg_annotations,
635 'SVGFEFuncBElement':
636 _svg_annotations,
637 'SVGFEFuncGElement':
638 _svg_annotations,
639 'SVGFEFuncRElement':
640 _svg_annotations,
641 'SVGFEGaussianBlurElement':
642 _svg_annotations,
643 'SVGFEImageElement':
644 _svg_annotations,
645 'SVGFEMergeElement':
646 _svg_annotations,
647 'SVGFEMergeNodeElement':
648 _svg_annotations,
649 'SVGFEMorphologyElement':
650 _svg_annotations,
651 'SVGFEOffsetElement':
652 _svg_annotations,
653 'SVGFEPointLightElement':
654 _svg_annotations,
655 'SVGFESpecularLightingElement':
656 _svg_annotations,
657 'SVGFESpotLightElement':
658 _svg_annotations,
659 'SVGFETileElement':
660 _svg_annotations,
661 'SVGFETurbulenceElement':
662 _svg_annotations,
663 'SVGFilterElement':
664 _svg_annotations,
665 'SVGForeignObjectElement':
666 _no_ie_annotations,
667 'SVGSetElement':
668 _no_ie_annotations,
669 'SQLTransaction':
670 _web_sql_annotations,
671 'SQLTransactionSync':
672 _web_sql_annotations,
673 'WebGLRenderingContext':
674 _webgl_annotations,
675 'WebSocket':
676 _all_but_ie9_annotations,
677 'Worker':
678 _all_but_ie9_annotations,
679 'XMLHttpRequest.overrideMimeType':
680 _no_ie_annotations,
681 'XMLHttpRequest.response':
682 _all_but_ie9_annotations,
683 'XMLHttpRequestEventTarget.onloadend':
684 _all_but_ie9_annotations,
685 'XMLHttpRequestEventTarget.onprogress':
686 _all_but_ie9_annotations,
687 'XSLTProcessor': [
688 "@SupportedBrowser(SupportedBrowser.CHROME)",
689 "@SupportedBrowser(SupportedBrowser.FIREFOX)",
690 "@SupportedBrowser(SupportedBrowser.SAFARI)",
691 ],
692 })
693
694# TODO(blois): minimize noise and enable by default.
695_monitor_type_metadata = False
696
697
698class DartMetadata(object):
699
700 def __init__(self,
701 api_status_path,
702 doc_comments_path,
703 logging_level=logging.WARNING):
704 _logger.setLevel(logging_level)
705 self._api_status_path = api_status_path
706 status_file = open(self._api_status_path, 'r+')
707 self._types = json.load(status_file)
708 status_file.close()
709
710 comments_file = open(doc_comments_path, 'r+')
711 self._doc_comments = json.load(comments_file)
712 comments_file.close()
713
714 if _monitor_type_metadata:
715 monitored_interfaces = {}
716 for interface_id, interface_data in list(self._types.items()):
717 monitored_interface = interface_data.copy()
718 monitored_interface['members'] = monitored.Dict(
719 'dartmetadata.%s' % interface_id, interface_data['members'])
720
721 monitored_interfaces[interface_id] = monitored_interface
722
723 self._monitored_types = monitored.Dict(
724 'dartmetadata._monitored_types', monitored_interfaces)
725 else:
726 self._monitored_types = self._types
727
728 def GetFormattedMetadata(self,
729 library_name,
730 interface,
731 member_id=None,
732 indentation=''):
733 """ Gets all comments and annotations for an interface or member.
734 """
735 return self.FormatMetadata(
736 self.GetMetadata(library_name, interface, member_id), indentation)
737
738 def GetMetadata(self,
739 library_name,
740 interface,
741 member_name=None,
742 source_member_name=None):
743 """ Gets all comments and annotations for an interface or member.
744
745 Args:
746 source_member_name: If the member is dependent on a different member
747 then this is used to apply the support annotations from the other
748 member.
749 """
750 annotations = self._GetComments(library_name, interface, member_name)
751 annotations = annotations + self._GetCommonAnnotations(
752 interface, member_name, source_member_name)
753
754 return annotations
755
756 def GetDart2JSMetadata(
757 self,
758 idl_type,
759 library_name,
760 interface,
761 member_name,
762 ):
763 """ Gets all annotations for Dart2JS members- including annotations for
764 both dart2js and dartium.
765 """
766 annotations = self.GetMetadata(library_name, interface, member_name)
767
768 ann2 = self._GetDart2JSSpecificAnnotations(idl_type, interface.id,
769 member_name)
770 if ann2:
771 if annotations:
772 annotations.extend(ann2)
773 else:
774 annotations = ann2
775 return annotations
776
777 def IsSuppressed(self, interface, member_name):
778 annotations = self._GetSupportLevelAnnotations(interface.id,
779 member_name)
780 return any(
781 annotation.startswith('@removed') for annotation in annotations)
782
783 def _GetCommonAnnotations(self,
784 interface,
785 member_name=None,
786 source_member_name=None):
787 annotations = []
788 if member_name:
789 key = '%s.%s' % (interface.id, member_name)
790 dom_name = '%s.%s' % (interface.javascript_binding_name,
791 member_name)
792 # DomName annotation is needed for dblclick ACX plugin analyzer.
793 if member_name == 'dblclickEvent' or member_name == 'ondblclick':
794 annotations.append("@DomName('" + dom_name + "')")
795 else:
796 key = interface.id
797
798 if key in _annotations:
799 annotations.extend(_annotations[key])
800
801 if (not member_name and
802 interface.javascript_binding_name.startswith('WebKit') and
803 interface.id not in html_interface_renames):
804 annotations.extend(_webkit_experimental_annotations)
805
806 if (member_name and member_name.startswith('webkit') and
807 key not in renamed_html_members):
808 annotations.extend(_webkit_experimental_annotations)
809
810 if source_member_name:
811 member_name = source_member_name
812
813 support_annotations = self._GetSupportLevelAnnotations(
814 interface.id, member_name)
815
816 for annotation in support_annotations:
817 if annotation not in annotations:
818 annotations.append(annotation)
819
820 return annotations
821
822 def _GetComments(self, library_name, interface, member_name=None):
823 """ Gets all comments for the interface or member and returns a list. """
824
825 # Add documentation from JSON.
826 comments = []
827 library_name = 'dart.dom.%s' % library_name
828 if library_name in self._doc_comments:
829 library_info = self._doc_comments[library_name]
830 if interface.id in library_info:
831 interface_info = library_info[interface.id]
832 if member_name:
833 if 'members' in interface_info and member_name in interface_info[
834 'members']:
835 comments = interface_info['members'][member_name]
836 elif 'comment' in interface_info:
837 comments = interface_info['comment']
838
839 if comments:
840 comments = ['\n'.join(comments)]
841
842 return comments
843
844 def AnyConversionAnnotations(self, idl_type, interface_name, member_name):
845 if (_annotations.get('%s.%s' % (interface_name, member_name)) or
846 self._GetDart2JSSpecificAnnotations(idl_type, interface_name,
847 member_name)):
848 return True
849 else:
850 return False
851
852 def FormatMetadata(self, metadata, indentation):
853 if metadata:
854 newline = '\n%s' % indentation
855 result = newline.join(metadata) + newline
856 return result
857 return ''
858
859 def _GetDart2JSSpecificAnnotations(self, idl_type, interface_name,
860 member_name):
861 """ Finds dart2js-specific annotations. This does not include ones shared with
862 dartium.
863 """
864 ann1 = _dart2js_annotations.get("%s.%s" % (interface_name, member_name))
865 if ann1:
866 ann2 = _dart2js_annotations.get('+' + idl_type)
867 if ann2:
868 return ann2 + ann1
869 ann2 = _dart2js_annotations.get(idl_type)
870 if ann2:
871 return ann2 + ann1
872 return ann1
873
874 ann2 = _dart2js_annotations.get('-' + idl_type)
875 if ann2:
876 return ann2
877 ann2 = _dart2js_annotations.get(idl_type)
878 return ann2
879
880 def _GetSupportInfo(self, interface_id, member_id=None):
881 """ Looks up the interface or member in the DOM status list and returns the
882 support level for it.
883 """
884 if interface_id in self._monitored_types:
885 type_info = self._monitored_types[interface_id]
886 else:
887 type_info = {
888 'members': {},
889 'support_level': 'untriaged',
890 }
891 self._types[interface_id] = type_info
892
893 if not member_id:
894 return type_info
895
896 members = type_info['members']
897
898 if member_id in members:
899 member_info = members[member_id]
900 else:
901 if member_id == interface_id:
902 member_info = {}
903 else:
904 member_info = {'support_level': 'untriaged'}
905 members[member_id] = member_info
906
907 return member_info
908
909 def _GetSupportLevelAnnotations(self, interface_id, member_id=None):
910 """ Gets annotations for API support status.
911 """
912 support_info = self._GetSupportInfo(interface_id, member_id)
913
914 dart_action = support_info.get('dart_action')
915 support_level = support_info.get('support_level')
916 comment = support_info.get('comment')
917 annotations = []
918 # TODO(blois): should add an annotation for the comment, but keeping out
919 # to keep the initial diff a bit more localized.
920 #if comment:
921 # annotations.append('// %s' % comment)
922
923 if dart_action:
924 if dart_action == 'unstable':
925 annotations.append('@Unstable()')
926 elif dart_action == 'suppress':
927 if comment:
928 annotations.append('// %s' % comment)
929 anAnnotation = 'deprecated'
930 if member_id:
931 anAnnotation = 'removed'
932 annotations.append('@%s // %s' % (anAnnotation, support_level))
933 pass
934 elif dart_action == 'stable':
935 pass
936 else:
937 _logger.warn(
938 'Unknown dart_action - %s:%s' % (interface_id, member_id))
939 elif support_level == 'stable':
940 pass
941 elif support_level == 'deprecated':
942 if comment:
943 annotations.append('// %s' % comment)
944 annotations.append('@deprecated')
945 elif support_level is None:
946 pass
947 else:
948 _logger.warn(
949 'Unknown support_level - %s:%s' % (interface_id, member_id))
950
951 return annotations
952
953 def Flush(self):
954 json_file = open(self._api_status_path, 'w+')
955 json.dump(
956 self._types,
957 json_file,
958 indent=2,
959 separators=(',', ': '),
960 sort_keys=True)
961 json_file.close()