f34eef5b91
Migrates syntax and semantics from python 2.7. Major changes include: - filters - sorting - print statements - higher-order functions - hashing and comparison and other misc changes. go.sh consistently gives the libraries in this and the previous commits with these changes. Change-Id: I66365739887158d8f321015d36e556447da1bcd3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/211542 Commit-Queue: Srujan Gaddam <srujzs@google.com> Reviewed-by: Riley Porter <rileyporter@google.com>
962 lines
34 KiB
Python
962 lines
34 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
# for details. All rights reserved. Use of this source code is governed by a
|
|
# BSD-style license that can be found in the LICENSE file.
|
|
"""This module provides shared functionality to provide Dart metadata for
|
|
DOM APIs.
|
|
"""
|
|
|
|
import copy
|
|
import json
|
|
import logging
|
|
import monitored
|
|
import os
|
|
import re
|
|
from htmlrenamer import renamed_html_members, html_interface_renames
|
|
|
|
_logger = logging.getLogger('dartmetadata')
|
|
|
|
# Annotations to be placed on native members. The table is indexed by the IDL
|
|
# interface and member name, and by IDL return or field type name. Both are
|
|
# used to assemble the annotations:
|
|
#
|
|
# INTERFACE.MEMBER: annotations for member.
|
|
# +TYPE: add annotations only if there are member annotations.
|
|
# -TYPE: add annotations only if there are no member annotations.
|
|
# TYPE: add regardless of member annotations.
|
|
|
|
_dart2js_annotations = monitored.Dict(
|
|
'dartmetadata._dart2js_annotations',
|
|
{
|
|
'AnimationEffectTiming.duration': [
|
|
"@Returns('num|String|Null')",
|
|
],
|
|
'ArrayBufferView': [
|
|
"@Creates('TypedData')",
|
|
"@Returns('TypedData|Null')",
|
|
],
|
|
'CanvasRenderingContext2D.createImageData': [
|
|
"@Creates('ImageData|=Object')",
|
|
],
|
|
'CanvasRenderingContext2D.getImageData': [
|
|
"@Creates('ImageData|=Object')",
|
|
],
|
|
'CanvasRenderingContext2D.webkitGetImageDataHD': [
|
|
"@Creates('ImageData|=Object')",
|
|
],
|
|
'CanvasRenderingContext2D.fillStyle': [
|
|
"@Creates('String|CanvasGradient|CanvasPattern')",
|
|
"@Returns('String|CanvasGradient|CanvasPattern')",
|
|
],
|
|
'CanvasRenderingContext2D.strokeStyle': [
|
|
"@Creates('String|CanvasGradient|CanvasPattern')",
|
|
"@Returns('String|CanvasGradient|CanvasPattern')",
|
|
],
|
|
'CryptoKey.algorithm': [
|
|
"@Creates('Null')",
|
|
],
|
|
'CustomEvent._detail': [
|
|
"@Creates('Null')",
|
|
],
|
|
|
|
# Normally Window is never null, but starting from a <template> element in
|
|
# JavaScript, this will be null:
|
|
# template.content.ownerDocument.defaultView
|
|
'Document.window': [
|
|
"@Creates('Window|=Object|Null')",
|
|
"@Returns('Window|=Object|Null')",
|
|
],
|
|
'Document.getElementsByClassName': [
|
|
"@Creates('NodeList|HtmlCollection')",
|
|
"@Returns('NodeList|HtmlCollection')",
|
|
],
|
|
'Document.getElementsByName': [
|
|
"@Creates('NodeList|HtmlCollection')",
|
|
"@Returns('NodeList|HtmlCollection')",
|
|
],
|
|
'Document.getElementsByTagName': [
|
|
"@Creates('NodeList|HtmlCollection')",
|
|
"@Returns('NodeList|HtmlCollection')",
|
|
],
|
|
|
|
# querysSelectorAll never returns `null`.
|
|
'Document.querySelectorAll': [
|
|
"@Creates('NodeList')",
|
|
"@Returns('NodeList')",
|
|
],
|
|
'DocumentFragment.querySelectorAll': [
|
|
"@Creates('NodeList')",
|
|
"@Returns('NodeList')",
|
|
],
|
|
'Element.querySelectorAll': [
|
|
"@Creates('NodeList')",
|
|
"@Returns('NodeList')",
|
|
],
|
|
'Element.getBoundingClientRect': [
|
|
"@Creates('_DomRect')",
|
|
"@Returns('_DomRect|Null')", # TODO(sra): Verify and remove Null.
|
|
],
|
|
'Element.getClientRects': [
|
|
"@Creates('DomRectList')",
|
|
"@Returns('DomRectList|Null')",
|
|
],
|
|
|
|
# Methods returning Window can return a local window, or a cross-frame
|
|
# window (=Object) that needs wrapping.
|
|
'Window': [
|
|
"@Creates('Window|=Object')",
|
|
"@Returns('Window|=Object')",
|
|
],
|
|
'Window.openDatabase': [
|
|
"@Creates('SqlDatabase')",
|
|
],
|
|
'Window.showModalDialog': [
|
|
"@Creates('Null')",
|
|
],
|
|
'Element.webkitGetRegionFlowRanges': [
|
|
"@Creates('JSExtendableArray')",
|
|
"@Returns('JSExtendableArray')",
|
|
],
|
|
'Element.getElementsByClassName': [
|
|
"@Creates('NodeList|HtmlCollection')",
|
|
"@Returns('NodeList|HtmlCollection')",
|
|
],
|
|
'Element.getElementsByName': [
|
|
"@Creates('NodeList|HtmlCollection')",
|
|
"@Returns('NodeList|HtmlCollection')",
|
|
],
|
|
'Element.getElementsByTagName': [
|
|
"@Creates('NodeList|HtmlCollection')",
|
|
"@Returns('NodeList|HtmlCollection')",
|
|
],
|
|
"ErrorEvent.error": [
|
|
"@Creates('Null')", # Only returns values created elsewhere.
|
|
],
|
|
|
|
# To be in callback with the browser-created Event, we had to have called
|
|
# addEventListener on the target, so we avoid
|
|
'Event.currentTarget': [
|
|
"@Creates('Null')",
|
|
"@Returns('EventTarget|=Object|Null')",
|
|
],
|
|
|
|
# Only nodes in the DOM bubble and have target !== currentTarget.
|
|
'Event.target': [
|
|
"@Creates('Node')",
|
|
"@Returns('EventTarget|=Object')",
|
|
],
|
|
|
|
# TODO(sra): Investigate how ExtendableMessageEvent.data is different from
|
|
# MessageEvent.data. It might be necessary to put in a method to translate
|
|
# the JavaScript wire type into a Dart type.
|
|
'ExtendableMessageEvent.data': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
"@annotation_Returns_SerializedScriptValue",
|
|
],
|
|
|
|
# TODO(sra): We could determine the following by parsing the compound IDL
|
|
# type.
|
|
'ExtendableMessageEvent.source': [
|
|
"@Creates('Client|ServiceWorker|MessagePort')",
|
|
"@Returns('Client|ServiceWorker|MessagePort|Null')",
|
|
],
|
|
'File.lastModifiedDate': [
|
|
"@Creates('Null')", # JS date object.
|
|
],
|
|
'FocusEvent.relatedTarget': [
|
|
"@Creates('Null')",
|
|
],
|
|
'Gamepad.buttons': [
|
|
"@Creates('JSExtendableArray|GamepadButton')",
|
|
"@Returns('JSExtendableArray')",
|
|
],
|
|
# Creates a GeolocationPosition or a GeolocationPositionError for a
|
|
# callback. See issue #45562.
|
|
'Geolocation.getCurrentPosition': [
|
|
"@Creates('Geoposition')",
|
|
"@Creates('PositionError')",
|
|
],
|
|
'Geolocation.watchPosition': [
|
|
"@Creates('Geoposition')",
|
|
"@Creates('PositionError')",
|
|
],
|
|
'HTMLCanvasElement.getContext': [
|
|
"@Creates('CanvasRenderingContext2D|RenderingContext|RenderingContext2')",
|
|
"@Returns('CanvasRenderingContext2D|RenderingContext|RenderingContext2|Null')",
|
|
],
|
|
'HTMLInputElement.valueAsDate': [
|
|
"@Creates('Null')", # JS date object.
|
|
],
|
|
|
|
# Rather than have the result of an IDBRequest as a union over all possible
|
|
# results, we mark the result as instantiating any classes, and mark
|
|
# each operation with the classes that it could cause to be asynchronously
|
|
# instantiated.
|
|
'IDBRequest.result': ["@Creates('Null')"],
|
|
|
|
# The source is usually a participant in the operation that generated the
|
|
# IDBRequest.
|
|
'IDBRequest.source': ["@Creates('Null')"],
|
|
'IDBFactory.open': ["@Creates('Database')"],
|
|
'IDBFactory.webkitGetDatabaseNames': ["@Creates('DomStringList')"],
|
|
'IDBObjectStore.put': ["@_annotation_Creates_IDBKey"],
|
|
'IDBObjectStore.add': ["@_annotation_Creates_IDBKey"],
|
|
'IDBObjectStore.get': ["@annotation_Creates_SerializedScriptValue"],
|
|
'IDBObjectStore.openCursor': ["@Creates('Cursor')"],
|
|
'IDBIndex.get': ["@annotation_Creates_SerializedScriptValue"],
|
|
'IDBIndex.getKey': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
# The source is the object store behind the index.
|
|
"@Creates('ObjectStore')",
|
|
],
|
|
'IDBIndex.openCursor': ["@Creates('Cursor')"],
|
|
'IDBIndex.openKeyCursor': ["@Creates('Cursor')"],
|
|
'IDBCursorWithValue.value': [
|
|
'@annotation_Creates_SerializedScriptValue',
|
|
'@annotation_Returns_SerializedScriptValue',
|
|
],
|
|
'IDBCursor.key': [
|
|
"@_annotation_Creates_IDBKey",
|
|
"@_annotation_Returns_IDBKey",
|
|
],
|
|
'IDBCursor.primaryKey': [
|
|
"@_annotation_Creates_IDBKey",
|
|
"@_annotation_Returns_IDBKey",
|
|
],
|
|
'IDBCursor.source': [
|
|
"@Creates('Null')",
|
|
"@Returns('ObjectStore|Index|Null')",
|
|
],
|
|
'IDBDatabase.version': [
|
|
"@Creates('int|String|Null')",
|
|
"@Returns('int|String|Null')",
|
|
],
|
|
'IDBIndex.keyPath': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
],
|
|
'IDBKeyRange.lower': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
],
|
|
'IDBKeyRange.upper': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
],
|
|
'IDBObjectStore.keyPath': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
],
|
|
'+IDBOpenDBRequest': [
|
|
"@Returns('Request')",
|
|
"@Creates('Request')",
|
|
],
|
|
'+IDBRequest': [
|
|
"@Returns('Request')",
|
|
"@Creates('Request')",
|
|
],
|
|
'IDBVersionChangeEvent.newVersion': [
|
|
"@Creates('int|String|Null')",
|
|
"@Returns('int|String|Null')",
|
|
],
|
|
'IDBVersionChangeEvent.oldVersion': [
|
|
"@Creates('int|String|Null')",
|
|
"@Returns('int|String|Null')",
|
|
],
|
|
'ImageData.data': [
|
|
"@Creates('NativeUint8ClampedList')",
|
|
"@Returns('NativeUint8ClampedList')",
|
|
],
|
|
'MediaStream.getAudioTracks': [
|
|
"@Creates('JSExtendableArray|MediaStreamTrack')",
|
|
"@Returns('JSExtendableArray')",
|
|
],
|
|
'MediaStream.getVideoTracks': [
|
|
"@Creates('JSExtendableArray|MediaStreamTrack')",
|
|
"@Returns('JSExtendableArray')",
|
|
],
|
|
'MessageEvent.data': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
"@annotation_Returns_SerializedScriptValue",
|
|
],
|
|
'MessageEvent.ports': ["@Creates('JSExtendableArray')"],
|
|
'MessageEvent.source': [
|
|
"@Creates('Null')",
|
|
"@Returns('EventTarget|=Object')",
|
|
],
|
|
'Metadata.modificationTime': [
|
|
"@Creates('Null')", # JS date object.
|
|
],
|
|
'MouseEvent.relatedTarget': [
|
|
"@Creates('Node')",
|
|
"@Returns('EventTarget|=Object|Null')",
|
|
],
|
|
'Notification.data': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
"@annotation_Returns_SerializedScriptValue",
|
|
],
|
|
'PopStateEvent.state': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
"@annotation_Returns_SerializedScriptValue",
|
|
],
|
|
'RTCStatsReport.timestamp': [
|
|
"@Creates('Null')", # JS date object.
|
|
],
|
|
'SerializedScriptValue': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
"@annotation_Returns_SerializedScriptValue",
|
|
],
|
|
'ServiceWorkerMessageEvent.data': [
|
|
"@annotation_Creates_SerializedScriptValue",
|
|
"@annotation_Returns_SerializedScriptValue",
|
|
],
|
|
'ServiceWorkerMessageEvent.source': [
|
|
"@Creates('Null')",
|
|
"@Returns('ServiceWorker|MessagePort')",
|
|
],
|
|
'ShadowRoot.getElementsByClassName': [
|
|
"@Creates('NodeList|HtmlCollection')",
|
|
"@Returns('NodeList|HtmlCollection')",
|
|
],
|
|
'ShadowRoot.getElementsByName': [
|
|
"@Creates('NodeList|HtmlCollection')",
|
|
"@Returns('NodeList|HtmlCollection')",
|
|
],
|
|
'ShadowRoot.getElementsByTagName': [
|
|
"@Creates('NodeList|HtmlCollection')",
|
|
"@Returns('NodeList|HtmlCollection')",
|
|
],
|
|
|
|
# Touch targets are Elements in a Document, or the Document.
|
|
'Touch.target': [
|
|
"@Creates('Element|Document')",
|
|
"@Returns('Element|Document')",
|
|
],
|
|
'TrackEvent.track': [
|
|
"@Creates('Null')",
|
|
],
|
|
'VTTCue.line': [
|
|
"@Creates('Null')",
|
|
"@Returns('num|String')",
|
|
],
|
|
'VTTCue.position': [
|
|
"@Creates('Null')",
|
|
"@Returns('num|String')",
|
|
],
|
|
'WebGLRenderingContext.getBufferParameter': [
|
|
"@Creates('int|Null')",
|
|
"@Returns('int|Null')",
|
|
],
|
|
'WebGLRenderingContext.getFramebufferAttachmentParameter': [
|
|
"@Creates('int|Renderbuffer|Texture|Null')",
|
|
"@Returns('int|Renderbuffer|Texture|Null')",
|
|
],
|
|
'WebGLRenderingContext.getProgramParameter': [
|
|
"@Creates('int|bool|Null')",
|
|
"@Returns('int|bool|Null')",
|
|
],
|
|
'WebGLRenderingContext.getRenderbufferParameter': [
|
|
"@Creates('int|Null')",
|
|
"@Returns('int|Null')",
|
|
],
|
|
'WebGLRenderingContext.getShaderParameter': [
|
|
"@Creates('int|bool|Null')",
|
|
"@Returns('int|bool|Null')",
|
|
],
|
|
'WebGLRenderingContext.getTexParameter': [
|
|
"@Creates('int|Null')",
|
|
"@Returns('int|Null')",
|
|
],
|
|
'WebGLRenderingContext.getUniform': [
|
|
"@Creates('Null|num|String|bool|JSExtendableArray|"
|
|
"NativeFloat32List|NativeInt32List|NativeUint32List')",
|
|
"@Returns('Null|num|String|bool|JSExtendableArray|"
|
|
"NativeFloat32List|NativeInt32List|NativeUint32List')",
|
|
],
|
|
'WebGLRenderingContext.getVertexAttrib': [
|
|
"@Creates('Null|num|bool|NativeFloat32List|Buffer')",
|
|
"@Returns('Null|num|bool|NativeFloat32List|Buffer')",
|
|
],
|
|
'WebGLRenderingContext.getParameter': [
|
|
# Taken from http://www.khronos.org/registry/webgl/specs/latest/
|
|
# Section 5.14.3 Setting and getting state
|
|
"@Creates('Null|num|String|bool|JSExtendableArray|"
|
|
"NativeFloat32List|NativeInt32List|NativeUint32List|"
|
|
"Framebuffer|Renderbuffer|Texture')",
|
|
"@Returns('Null|num|String|bool|JSExtendableArray|"
|
|
"NativeFloat32List|NativeInt32List|NativeUint32List|"
|
|
"Framebuffer|Renderbuffer|Texture')",
|
|
],
|
|
'WebGLRenderingContext.getContextAttributes': [
|
|
"@Creates('ContextAttributes|Null')",
|
|
],
|
|
'XMLHttpRequest.response': [
|
|
"@Creates('NativeByteBuffer|Blob|Document|=Object|JSExtendableArray"
|
|
"|String|num')",
|
|
],
|
|
},
|
|
dart2jsOnly=True)
|
|
|
|
_blink_experimental_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
]
|
|
|
|
_indexed_db_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX, '15')",
|
|
"@SupportedBrowser(SupportedBrowser.IE, '10')",
|
|
]
|
|
|
|
_file_system_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
]
|
|
|
|
_all_but_ie9_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
|
|
"@SupportedBrowser(SupportedBrowser.IE, '10')",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
]
|
|
|
|
_history_annotations = _all_but_ie9_annotations
|
|
|
|
_no_ie_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
]
|
|
|
|
_performance_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
|
|
"@SupportedBrowser(SupportedBrowser.IE)",
|
|
]
|
|
|
|
_rtc_annotations = [ # Note: Firefox nightly builds also support this.
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
]
|
|
|
|
_shadow_dom_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME, '26')",
|
|
]
|
|
|
|
_speech_recognition_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME, '25')",
|
|
]
|
|
|
|
_svg_annotations = _all_but_ie9_annotations
|
|
|
|
_web_sql_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
]
|
|
|
|
_webgl_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
|
|
]
|
|
|
|
_web_audio_annotations = _webgl_annotations
|
|
|
|
_webkit_experimental_annotations = [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
]
|
|
|
|
# Annotations to be placed on generated members.
|
|
# The table is indexed as:
|
|
# INTERFACE: annotations to be added to the interface declaration
|
|
# INTERFACE.MEMBER: annotation to be added to the member declaration
|
|
_annotations = monitored.Dict(
|
|
'dartmetadata._annotations',
|
|
{
|
|
'CSSHostRule':
|
|
_shadow_dom_annotations,
|
|
'WebKitCSSMatrix':
|
|
_webkit_experimental_annotations,
|
|
'Crypto':
|
|
_webkit_experimental_annotations,
|
|
'Database':
|
|
_web_sql_annotations,
|
|
'DatabaseSync':
|
|
_web_sql_annotations,
|
|
'ApplicationCache': [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
|
|
"@SupportedBrowser(SupportedBrowser.IE, '10')",
|
|
"@SupportedBrowser(SupportedBrowser.OPERA)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
],
|
|
'AudioBufferSourceNode':
|
|
_web_audio_annotations,
|
|
'AudioContext':
|
|
_web_audio_annotations,
|
|
'DOMFileSystem':
|
|
_file_system_annotations,
|
|
'DOMFileSystemSync':
|
|
_file_system_annotations,
|
|
'Window.indexedDB':
|
|
_indexed_db_annotations,
|
|
'Window.openDatabase':
|
|
_web_sql_annotations,
|
|
'Window.performance':
|
|
_performance_annotations,
|
|
'Window.webkitNotifications':
|
|
_webkit_experimental_annotations,
|
|
'Window.webkitRequestFileSystem':
|
|
_file_system_annotations,
|
|
'Window.webkitResolveLocalFileSystemURL':
|
|
_file_system_annotations,
|
|
'Element.createShadowRoot': [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME, '25')",
|
|
],
|
|
'Element.ontransitionend':
|
|
_all_but_ie9_annotations,
|
|
# Placeholder to add experimental flag, implementation for this is
|
|
# pending in a separate CL.
|
|
'Element.webkitMatchesSelector': [],
|
|
'Event.clipboardData': [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
],
|
|
'FormData':
|
|
_all_but_ie9_annotations,
|
|
'HashChangeEvent': [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
],
|
|
'History.pushState':
|
|
_history_annotations,
|
|
'History.replaceState':
|
|
_history_annotations,
|
|
'HTMLContentElement':
|
|
_shadow_dom_annotations,
|
|
'HTMLDataListElement':
|
|
_all_but_ie9_annotations,
|
|
'HTMLDetailsElement':
|
|
_webkit_experimental_annotations,
|
|
'HTMLEmbedElement': [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.IE)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
],
|
|
'HTMLKeygenElement':
|
|
_webkit_experimental_annotations,
|
|
'HTMLMeterElement':
|
|
_no_ie_annotations,
|
|
'HTMLObjectElement': [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.IE)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
],
|
|
'HTMLOutputElement':
|
|
_no_ie_annotations,
|
|
'HTMLProgressElement':
|
|
_all_but_ie9_annotations,
|
|
'HTMLShadowElement':
|
|
_shadow_dom_annotations,
|
|
'HTMLTemplateElement':
|
|
_blink_experimental_annotations,
|
|
'HTMLTrackElement': [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.IE, '10')",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
],
|
|
'IDBFactory':
|
|
_indexed_db_annotations,
|
|
'IDBDatabase':
|
|
_indexed_db_annotations,
|
|
'MediaStream':
|
|
_rtc_annotations,
|
|
'MediaStreamEvent':
|
|
_rtc_annotations,
|
|
'MediaStreamTrack':
|
|
_rtc_annotations,
|
|
'MediaStreamTrackEvent':
|
|
_rtc_annotations,
|
|
'MediaSource': [
|
|
# TODO(alanknight): This works on Firefox 33 behind a flag and in Safari
|
|
# desktop, but not mobile. On theory that static false positives are worse
|
|
# than negatives, leave those out for now. Update once they're available.
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.IE, '11')",
|
|
],
|
|
'MutationObserver': [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
],
|
|
'Performance':
|
|
_performance_annotations,
|
|
'PopStateEvent':
|
|
_history_annotations,
|
|
'RTCIceCandidate':
|
|
_rtc_annotations,
|
|
'RTCPeerConnection':
|
|
_rtc_annotations,
|
|
'RTCSessionDescription':
|
|
_rtc_annotations,
|
|
'ShadowRoot':
|
|
_shadow_dom_annotations,
|
|
'SpeechRecognition':
|
|
_speech_recognition_annotations,
|
|
'SpeechRecognitionAlternative':
|
|
_speech_recognition_annotations,
|
|
'SpeechRecognitionError':
|
|
_speech_recognition_annotations,
|
|
'SpeechRecognitionEvent':
|
|
_speech_recognition_annotations,
|
|
'SpeechRecognitionResult':
|
|
_speech_recognition_annotations,
|
|
'SVGAltGlyphElement':
|
|
_no_ie_annotations,
|
|
'SVGAnimateElement':
|
|
_no_ie_annotations,
|
|
'SVGAnimateMotionElement':
|
|
_no_ie_annotations,
|
|
'SVGAnimateTransformElement':
|
|
_no_ie_annotations,
|
|
'SVGFEBlendElement':
|
|
_svg_annotations,
|
|
'SVGFEColorMatrixElement':
|
|
_svg_annotations,
|
|
'SVGFEComponentTransferElement':
|
|
_svg_annotations,
|
|
'SVGFEConvolveMatrixElement':
|
|
_svg_annotations,
|
|
'SVGFEDiffuseLightingElement':
|
|
_svg_annotations,
|
|
'SVGFEDisplacementMapElement':
|
|
_svg_annotations,
|
|
'SVGFEDistantLightElement':
|
|
_svg_annotations,
|
|
'SVGFEFloodElement':
|
|
_svg_annotations,
|
|
'SVGFEFuncAElement':
|
|
_svg_annotations,
|
|
'SVGFEFuncBElement':
|
|
_svg_annotations,
|
|
'SVGFEFuncGElement':
|
|
_svg_annotations,
|
|
'SVGFEFuncRElement':
|
|
_svg_annotations,
|
|
'SVGFEGaussianBlurElement':
|
|
_svg_annotations,
|
|
'SVGFEImageElement':
|
|
_svg_annotations,
|
|
'SVGFEMergeElement':
|
|
_svg_annotations,
|
|
'SVGFEMergeNodeElement':
|
|
_svg_annotations,
|
|
'SVGFEMorphologyElement':
|
|
_svg_annotations,
|
|
'SVGFEOffsetElement':
|
|
_svg_annotations,
|
|
'SVGFEPointLightElement':
|
|
_svg_annotations,
|
|
'SVGFESpecularLightingElement':
|
|
_svg_annotations,
|
|
'SVGFESpotLightElement':
|
|
_svg_annotations,
|
|
'SVGFETileElement':
|
|
_svg_annotations,
|
|
'SVGFETurbulenceElement':
|
|
_svg_annotations,
|
|
'SVGFilterElement':
|
|
_svg_annotations,
|
|
'SVGForeignObjectElement':
|
|
_no_ie_annotations,
|
|
'SVGSetElement':
|
|
_no_ie_annotations,
|
|
'SQLTransaction':
|
|
_web_sql_annotations,
|
|
'SQLTransactionSync':
|
|
_web_sql_annotations,
|
|
'WebGLRenderingContext':
|
|
_webgl_annotations,
|
|
'WebSocket':
|
|
_all_but_ie9_annotations,
|
|
'Worker':
|
|
_all_but_ie9_annotations,
|
|
'XMLHttpRequest.overrideMimeType':
|
|
_no_ie_annotations,
|
|
'XMLHttpRequest.response':
|
|
_all_but_ie9_annotations,
|
|
'XMLHttpRequestEventTarget.onloadend':
|
|
_all_but_ie9_annotations,
|
|
'XMLHttpRequestEventTarget.onprogress':
|
|
_all_but_ie9_annotations,
|
|
'XSLTProcessor': [
|
|
"@SupportedBrowser(SupportedBrowser.CHROME)",
|
|
"@SupportedBrowser(SupportedBrowser.FIREFOX)",
|
|
"@SupportedBrowser(SupportedBrowser.SAFARI)",
|
|
],
|
|
})
|
|
|
|
# TODO(blois): minimize noise and enable by default.
|
|
_monitor_type_metadata = False
|
|
|
|
|
|
class DartMetadata(object):
|
|
|
|
def __init__(self,
|
|
api_status_path,
|
|
doc_comments_path,
|
|
logging_level=logging.WARNING):
|
|
_logger.setLevel(logging_level)
|
|
self._api_status_path = api_status_path
|
|
status_file = open(self._api_status_path, 'r+')
|
|
self._types = json.load(status_file)
|
|
status_file.close()
|
|
|
|
comments_file = open(doc_comments_path, 'r+')
|
|
self._doc_comments = json.load(comments_file)
|
|
comments_file.close()
|
|
|
|
if _monitor_type_metadata:
|
|
monitored_interfaces = {}
|
|
for interface_id, interface_data in list(self._types.items()):
|
|
monitored_interface = interface_data.copy()
|
|
monitored_interface['members'] = monitored.Dict(
|
|
'dartmetadata.%s' % interface_id, interface_data['members'])
|
|
|
|
monitored_interfaces[interface_id] = monitored_interface
|
|
|
|
self._monitored_types = monitored.Dict(
|
|
'dartmetadata._monitored_types', monitored_interfaces)
|
|
else:
|
|
self._monitored_types = self._types
|
|
|
|
def GetFormattedMetadata(self,
|
|
library_name,
|
|
interface,
|
|
member_id=None,
|
|
indentation=''):
|
|
""" Gets all comments and annotations for an interface or member.
|
|
"""
|
|
return self.FormatMetadata(
|
|
self.GetMetadata(library_name, interface, member_id), indentation)
|
|
|
|
def GetMetadata(self,
|
|
library_name,
|
|
interface,
|
|
member_name=None,
|
|
source_member_name=None):
|
|
""" Gets all comments and annotations for an interface or member.
|
|
|
|
Args:
|
|
source_member_name: If the member is dependent on a different member
|
|
then this is used to apply the support annotations from the other
|
|
member.
|
|
"""
|
|
annotations = self._GetComments(library_name, interface, member_name)
|
|
annotations = annotations + self._GetCommonAnnotations(
|
|
interface, member_name, source_member_name)
|
|
|
|
return annotations
|
|
|
|
def GetDart2JSMetadata(
|
|
self,
|
|
idl_type,
|
|
library_name,
|
|
interface,
|
|
member_name,
|
|
):
|
|
""" Gets all annotations for Dart2JS members- including annotations for
|
|
both dart2js and dartium.
|
|
"""
|
|
annotations = self.GetMetadata(library_name, interface, member_name)
|
|
|
|
ann2 = self._GetDart2JSSpecificAnnotations(idl_type, interface.id,
|
|
member_name)
|
|
if ann2:
|
|
if annotations:
|
|
annotations.extend(ann2)
|
|
else:
|
|
annotations = ann2
|
|
return annotations
|
|
|
|
def IsSuppressed(self, interface, member_name):
|
|
annotations = self._GetSupportLevelAnnotations(interface.id,
|
|
member_name)
|
|
return any(
|
|
annotation.startswith('@removed') for annotation in annotations)
|
|
|
|
def _GetCommonAnnotations(self,
|
|
interface,
|
|
member_name=None,
|
|
source_member_name=None):
|
|
annotations = []
|
|
if member_name:
|
|
key = '%s.%s' % (interface.id, member_name)
|
|
dom_name = '%s.%s' % (interface.javascript_binding_name,
|
|
member_name)
|
|
# DomName annotation is needed for dblclick ACX plugin analyzer.
|
|
if member_name == 'dblclickEvent' or member_name == 'ondblclick':
|
|
annotations.append("@DomName('" + dom_name + "')")
|
|
else:
|
|
key = interface.id
|
|
|
|
if key in _annotations:
|
|
annotations.extend(_annotations[key])
|
|
|
|
if (not member_name and
|
|
interface.javascript_binding_name.startswith('WebKit') and
|
|
interface.id not in html_interface_renames):
|
|
annotations.extend(_webkit_experimental_annotations)
|
|
|
|
if (member_name and member_name.startswith('webkit') and
|
|
key not in renamed_html_members):
|
|
annotations.extend(_webkit_experimental_annotations)
|
|
|
|
if source_member_name:
|
|
member_name = source_member_name
|
|
|
|
support_annotations = self._GetSupportLevelAnnotations(
|
|
interface.id, member_name)
|
|
|
|
for annotation in support_annotations:
|
|
if annotation not in annotations:
|
|
annotations.append(annotation)
|
|
|
|
return annotations
|
|
|
|
def _GetComments(self, library_name, interface, member_name=None):
|
|
""" Gets all comments for the interface or member and returns a list. """
|
|
|
|
# Add documentation from JSON.
|
|
comments = []
|
|
library_name = 'dart.dom.%s' % library_name
|
|
if library_name in self._doc_comments:
|
|
library_info = self._doc_comments[library_name]
|
|
if interface.id in library_info:
|
|
interface_info = library_info[interface.id]
|
|
if member_name:
|
|
if 'members' in interface_info and member_name in interface_info[
|
|
'members']:
|
|
comments = interface_info['members'][member_name]
|
|
elif 'comment' in interface_info:
|
|
comments = interface_info['comment']
|
|
|
|
if comments:
|
|
comments = ['\n'.join(comments)]
|
|
|
|
return comments
|
|
|
|
def AnyConversionAnnotations(self, idl_type, interface_name, member_name):
|
|
if (_annotations.get('%s.%s' % (interface_name, member_name)) or
|
|
self._GetDart2JSSpecificAnnotations(idl_type, interface_name,
|
|
member_name)):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def FormatMetadata(self, metadata, indentation):
|
|
if metadata:
|
|
newline = '\n%s' % indentation
|
|
result = newline.join(metadata) + newline
|
|
return result
|
|
return ''
|
|
|
|
def _GetDart2JSSpecificAnnotations(self, idl_type, interface_name,
|
|
member_name):
|
|
""" Finds dart2js-specific annotations. This does not include ones shared with
|
|
dartium.
|
|
"""
|
|
ann1 = _dart2js_annotations.get("%s.%s" % (interface_name, member_name))
|
|
if ann1:
|
|
ann2 = _dart2js_annotations.get('+' + idl_type)
|
|
if ann2:
|
|
return ann2 + ann1
|
|
ann2 = _dart2js_annotations.get(idl_type)
|
|
if ann2:
|
|
return ann2 + ann1
|
|
return ann1
|
|
|
|
ann2 = _dart2js_annotations.get('-' + idl_type)
|
|
if ann2:
|
|
return ann2
|
|
ann2 = _dart2js_annotations.get(idl_type)
|
|
return ann2
|
|
|
|
def _GetSupportInfo(self, interface_id, member_id=None):
|
|
""" Looks up the interface or member in the DOM status list and returns the
|
|
support level for it.
|
|
"""
|
|
if interface_id in self._monitored_types:
|
|
type_info = self._monitored_types[interface_id]
|
|
else:
|
|
type_info = {
|
|
'members': {},
|
|
'support_level': 'untriaged',
|
|
}
|
|
self._types[interface_id] = type_info
|
|
|
|
if not member_id:
|
|
return type_info
|
|
|
|
members = type_info['members']
|
|
|
|
if member_id in members:
|
|
member_info = members[member_id]
|
|
else:
|
|
if member_id == interface_id:
|
|
member_info = {}
|
|
else:
|
|
member_info = {'support_level': 'untriaged'}
|
|
members[member_id] = member_info
|
|
|
|
return member_info
|
|
|
|
def _GetSupportLevelAnnotations(self, interface_id, member_id=None):
|
|
""" Gets annotations for API support status.
|
|
"""
|
|
support_info = self._GetSupportInfo(interface_id, member_id)
|
|
|
|
dart_action = support_info.get('dart_action')
|
|
support_level = support_info.get('support_level')
|
|
comment = support_info.get('comment')
|
|
annotations = []
|
|
# TODO(blois): should add an annotation for the comment, but keeping out
|
|
# to keep the initial diff a bit more localized.
|
|
#if comment:
|
|
# annotations.append('// %s' % comment)
|
|
|
|
if dart_action:
|
|
if dart_action == 'unstable':
|
|
annotations.append('@Unstable()')
|
|
elif dart_action == 'suppress':
|
|
if comment:
|
|
annotations.append('// %s' % comment)
|
|
anAnnotation = 'deprecated'
|
|
if member_id:
|
|
anAnnotation = 'removed'
|
|
annotations.append('@%s // %s' % (anAnnotation, support_level))
|
|
pass
|
|
elif dart_action == 'stable':
|
|
pass
|
|
else:
|
|
_logger.warn(
|
|
'Unknown dart_action - %s:%s' % (interface_id, member_id))
|
|
elif support_level == 'stable':
|
|
pass
|
|
elif support_level == 'deprecated':
|
|
if comment:
|
|
annotations.append('// %s' % comment)
|
|
annotations.append('@deprecated')
|
|
elif support_level is None:
|
|
pass
|
|
else:
|
|
_logger.warn(
|
|
'Unknown support_level - %s:%s' % (interface_id, member_id))
|
|
|
|
return annotations
|
|
|
|
def Flush(self):
|
|
json_file = open(self._api_status_path, 'w+')
|
|
json.dump(
|
|
self._types,
|
|
json_file,
|
|
indent=2,
|
|
separators=(',', ': '),
|
|
sort_keys=True)
|
|
json_file.close()
|