Added support for members of type Promise.

Fixes #31046

R=sra@google.com

Change-Id: Id1e8d415b91a842bd8e2f50c6064c24aaaed9d98
Reviewed-on: https://dart-review.googlesource.com/59460
Reviewed-by: Stephen Adams <sra@google.com>
Commit-Queue: Terry Lucas <terry@google.com>
This commit is contained in:
Terry Lucas
2018-06-13 18:20:53 +00:00
committed by commit-bot@chromium.org
parent 1e91c62d4b
commit eea2dff20d
6 changed files with 78 additions and 38 deletions
+17 -9
View File
@@ -870,7 +870,8 @@ class Animation extends EventTarget {
@DomName('Animation.finished')
@DocsEditable()
@Experimental() // untriaged
final Future finished;
Future<Animation> get finished =>
promiseToFuture<Animation>(JS("", "#.finished", this));
@DomName('Animation.id')
@DocsEditable()
@@ -890,7 +891,8 @@ class Animation extends EventTarget {
@DomName('Animation.ready')
@DocsEditable()
@Experimental() // untriaged
final Future ready;
Future<Animation> get ready =>
promiseToFuture<Animation>(JS("", "#.ready", this));
@DomName('Animation.startTime')
@DocsEditable()
@@ -2118,7 +2120,8 @@ class BeforeInstallPromptEvent extends Event {
@DomName('BeforeInstallPromptEvent.userChoice')
@DocsEditable()
@Experimental() // untriaged
final Future userChoice;
Future<Map<String, dynamic>> get userChoice =>
promiseToFutureAsMap(JS("", "#.userChoice", this));
@DomName('BeforeInstallPromptEvent.prompt')
@DocsEditable()
@@ -19387,7 +19390,8 @@ class FetchEvent extends ExtendableEvent {
@DomName('FetchEvent.preloadResponse')
@DocsEditable()
@Experimental() // untriaged
final Future preloadResponse;
Future get preloadResponse =>
promiseToFuture(JS("", "#.preloadResponse", this));
@DomName('FetchEvent.request')
@DocsEditable()
@@ -20108,7 +20112,8 @@ class FontFace extends Interceptor {
@DomName('FontFace.loaded')
@DocsEditable()
@Experimental() // untriaged
final Future loaded;
Future<FontFace> get loaded =>
promiseToFuture<FontFace>(JS("", "#.loaded", this));
@DomName('FontFace.status')
@DocsEditable()
@@ -25820,7 +25825,7 @@ class MediaKeySession extends EventTarget {
@DomName('MediaKeySession.closed')
@DocsEditable()
@Experimental() // untriaged
final Future closed;
Future<void> get closed => promiseToFuture<void>(JS("", "#.closed", this));
@DomName('MediaKeySession.expiration')
@DocsEditable()
@@ -33137,7 +33142,9 @@ class PresentationReceiver extends Interceptor {
@DomName('PresentationReceiver.connectionList')
@DocsEditable()
@Experimental() // untriaged
final Future connectionList;
Future<PresentationConnectionList> get connectionList =>
promiseToFuture<PresentationConnectionList>(
JS("", "#.connectionList", this));
}
// 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
@@ -33330,7 +33337,7 @@ class PromiseRejectionEvent extends Event {
@DomName('PromiseRejectionEvent.promise')
@DocsEditable()
@Experimental() // untriaged
final Future promise;
Future get promise => promiseToFuture(JS("", "#.promise", this));
@DomName('PromiseRejectionEvent.reason')
@DocsEditable()
@@ -36013,7 +36020,8 @@ class ServiceWorkerContainer extends EventTarget {
@DomName('ServiceWorkerContainer.ready')
@DocsEditable()
@Experimental() // untriaged
final Future ready;
Future<ServiceWorkerRegistration> get ready =>
promiseToFuture<ServiceWorkerRegistration>(JS("", "#.ready", this));
@DomName('ServiceWorkerContainer.getRegistration')
@DocsEditable()
-1
View File
@@ -401,7 +401,6 @@ websql_test: Pass # Triage, seen some double reporting on windows.
[ $compiler == dart2js && $browser ]
custom/created_callback_test: Fail # Support for created constructor. Issue 14835
fontface_loaded_test: Fail # Support for promises.
[ $compiler == dart2js && $browser && $csp ]
custom/element_upgrade_test: Fail # Issue 17298
+12 -6
View File
@@ -32,22 +32,28 @@ main() {
treeSanitizer: new NullTreeSanitizer());
document.head.append(style);
test('document fonts - temporary', () {
test('document fonts - temporary', () async {
var atLeastOneFont = false;
var loaded = <Future>[];
document.fonts.forEach((FontFace fontFace, _, __) {
var loaded = <Future<FontFace>>[];
document.fonts.forEach((FontFace fontFace, _, __) async {
atLeastOneFont = true;
Future f1 = fontFace.loaded;
Future f2 = fontFace.loaded;
var f1 = fontFace.loaded;
var f2 = fontFace.loaded;
loaded.add(fontFace.load());
loaded.add(f1);
loaded.add(f2);
});
expect(atLeastOneFont, isTrue);
return Future.wait(loaded).then(expectAsync((_) {
return Future.wait(loaded).then(expectAsync((_) async {
document.fonts.forEach((fontFace, _, __) {
expect(fontFace.status, 'loaded');
});
expect(loaded.length, 3);
for (var loadedEntry in loaded) {
var fontFace = await loadedEntry;
expect(fontFace.status, 'loaded');
expect(fontFace.family, 'Ahem');
}
}));
});
}
+1 -4
View File
@@ -186,6 +186,7 @@ html/fileapi_supported_test: RuntimeError
html/fileapi_supported_throws_test: RuntimeError
html/filereader_test: RuntimeError
html/filteredelementlist_test: RuntimeError
html/fontface_loaded_test: RuntimeError
html/fontface_test: RuntimeError
html/form_data_test: RuntimeError
html/form_element_test: RuntimeError
@@ -339,7 +340,6 @@ js/prototype_access_test: RuntimeError
collection/list_test: RuntimeError
[ $compiler == dart2js && $runtime != d8 && $runtime != jsshell ]
html/fontface_loaded_test: RuntimeError
html/html_mock_test: RuntimeError # Issue 31038
html/input_element_attributes_test: RuntimeError
html/js_dart_functions_test: RuntimeError # does not implement Dart 2 implicit `.call` tearoff
@@ -474,7 +474,6 @@ html/xhr_test: RuntimeError
[ $compiler == dart2js && $browser ]
html/custom/created_callback_test: RuntimeError
html/fontface_loaded_test: Fail # Support for promises.
html/js_typed_interop_lazy_test/01: RuntimeError
html/notification_permission_test: Timeout, Pass # Issue 32002
html/private_extension_member_test: RuntimeError
@@ -688,7 +687,6 @@ html/js_typed_interop_test: RuntimeError
[ $compiler == dart2js && $fasta && $host_checked ]
html/custom/mirrors_2_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
html/custom/mirrors_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
html/fontface_loaded_test: RuntimeError # TypeError: Cannot read property 'createFragment$3$treeSanitizer$validator' of undefined
html/indexeddb_3_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
html/indexeddb_5_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
html/js_array_test: CompileTimeError
@@ -725,7 +723,6 @@ html/element_types_keygen_test: RuntimeError # Issue 29922
html/event_customevent_test: RuntimeError
html/file_sample_test: RuntimeError
html/fileapi_entry_test: RuntimeError
html/fontface_loaded_test: RuntimeError
html/indexeddb_1_test/functional: RuntimeError
html/indexeddb_2_test: RuntimeError
html/indexeddb_3_test: RuntimeError
-1
View File
@@ -82,7 +82,6 @@ html/custom_elements_23127_test: Skip # Issue 29922
html/custom_elements_test: Skip # Issue 29922
html/deferred_multi_app_htmltest: Skip # Issue 29919
html/element_classes_test: RuntimeError # Issue 29922
html/fontface_loaded_test: RuntimeError
html/isolates_test: RuntimeError # Issue 29922
html/js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue 29922
html/js_typed_interop_side_cast_exp_test/01: RuntimeError # Requires --experimental-trust-js-interop-type-annotations flag.
+48 -17
View File
@@ -771,12 +771,14 @@ class HtmlDartInterfaceGenerator(object):
parameterized Promise type.
'''
promise_attributes = monitored.Dict('systemhtml.promise_attr_type', {
"Animation.finished": {"type": "Animation"},
"Animation.ready": {"type": "Animation"},
"FontFace.loaded": {"type": "FontFace"},
"FontFaceSet.ready": {"type": "FontFaceSet"},
"PresentationReceiver.connectionList": {"type": "PresentationConnectionList"},
"ServiceWorkerContainer.ready": {"type": "ServiceWorkerRegistration"},
"Animation.finished": {"type": "Animation"},
"Animation.ready": {"type": "Animation"},
"BeforeInstallPromptEvent.userChoice": {"type": "dictionary"},
"FontFace.loaded": {"type": "FontFace"},
"FontFaceSet.ready": {"type": "FontFaceSet"},
"MediaKeySession.closed": {"type": "void"},
"PresentationReceiver.connectionList": {"type": "PresentationConnectionList"},
"ServiceWorkerContainer.ready": {"type": "ServiceWorkerRegistration"},
})
promise_operations = monitored.Dict('systemhtml.promise_oper_type', {
@@ -1125,6 +1127,8 @@ class Dart2JSBackend(HtmlDartGenerator):
metadata = self._Metadata(attribute.type.id, attribute.id, output_type)
rename = self._RenamingAnnotation(attribute.id, html_name)
if not read_only:
if attribute.type.id == 'Promise':
_logger.warn('R/W member is a Promise: %s.%s' % (self._interface.id, html_name))
self._members_emitter.Emit(
'\n $RENAME$METADATA$TYPE $NAME;'
'\n',
@@ -1134,17 +1138,44 @@ class Dart2JSBackend(HtmlDartGenerator):
TYPE=output_type)
else:
template = '\n $RENAME$(ANNOTATIONS)final $TYPE $NAME;\n'
# Need to use a getter for list.length properties so we can add a
# setter which throws an exception, satisfying List API.
if self._interface_type_info.list_item_type() and html_name == 'length':
template = ('\n $RENAME$(ANNOTATIONS)$TYPE get $NAME => ' +
'JS("$TYPE", "#.$NAME", this);\n')
self._members_emitter.Emit(
template,
RENAME=rename,
ANNOTATIONS=metadata,
NAME=html_name,
TYPE=input_type if output_type == 'double' else output_type)
if attribute.type.id == 'Promise':
lookupOp = "%s.%s" % (self._interface.id, html_name)
promiseFound = _GetPromiseAttributeType(lookupOp)
promiseType = 'Future'
promiseCall = 'promiseToFuture'
if promiseFound is not (None):
if 'maplike' in promiseFound:
promiseCall = 'promiseToFuture<dynamic>'
promiseType = 'Future'
elif promiseFound['type'] == 'dictionary':
# It's a dictionary so return as a Map.
promiseCall = 'promiseToFutureAsMap'
promiseType = 'Future<Map<String, dynamic>>'
else:
paramType = promiseFound['type']
promiseCall = 'promiseToFuture<%s>' % paramType
promiseType = 'Future<%s>' % paramType
template = '\n $RENAME$(ANNOTATIONS)$TYPE get $NAME => $PROMISE_CALL(JS("", "#.$NAME", this));\n'
self._members_emitter.Emit(template,
RENAME=rename,
ANNOTATIONS=metadata,
TYPE=promiseType,
PROMISE_CALL=promiseCall,
NAME=html_name)
else:
# Need to use a getter for list.length properties so we can add a
# setter which throws an exception, satisfying List API.
if self._interface_type_info.list_item_type() and html_name == 'length':
template = ('\n $RENAME$(ANNOTATIONS)$TYPE get $NAME => ' +
'JS("$TYPE", "#.$NAME", this);\n')
self._members_emitter.Emit(
template,
RENAME=rename,
ANNOTATIONS=metadata,
NAME=html_name,
TYPE=input_type if output_type == 'double' else output_type)
def _AddAttributeUsingProperties(self, attribute, html_name, read_only):
self._AddRenamingGetter(attribute, html_name)