diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart index 843e633ed35..ee8e65362ee 100644 --- a/sdk/lib/html/dart2js/html_dart2js.dart +++ b/sdk/lib/html/dart2js/html_dart2js.dart @@ -870,7 +870,8 @@ class Animation extends EventTarget { @DomName('Animation.finished') @DocsEditable() @Experimental() // untriaged - final Future finished; + Future get finished => + promiseToFuture(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 get ready => + promiseToFuture(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> 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 get loaded => + promiseToFuture(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 get closed => promiseToFuture(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 get connectionList => + promiseToFuture( + 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 get ready => + promiseToFuture(JS("", "#.ready", this)); @DomName('ServiceWorkerContainer.getRegistration') @DocsEditable() diff --git a/tests/html/html.status b/tests/html/html.status index 9fe79e42d2e..f83e0c755a3 100644 --- a/tests/html/html.status +++ b/tests/html/html.status @@ -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 diff --git a/tests/lib_2/html/fontface_loaded_test.dart b/tests/lib_2/html/fontface_loaded_test.dart index a9334b6699f..a4670e7e8ca 100644 --- a/tests/lib_2/html/fontface_loaded_test.dart +++ b/tests/lib_2/html/fontface_loaded_test.dart @@ -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 = []; - document.fonts.forEach((FontFace fontFace, _, __) { + var loaded = >[]; + 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'); + } })); }); } diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status index e3b55be8981..695151b80b3 100644 --- a/tests/lib_2/lib_2_dart2js.status +++ b/tests/lib_2/lib_2_dart2js.status @@ -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 diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status index bbfa3a406e0..db43afec828 100644 --- a/tests/lib_2/lib_2_dartdevc.status +++ b/tests/lib_2/lib_2_dartdevc.status @@ -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. diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py index 324900ca1ff..458d8102156 100644 --- a/tools/dom/scripts/systemhtml.py +++ b/tools/dom/scripts/systemhtml.py @@ -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' + promiseType = 'Future' + elif promiseFound['type'] == 'dictionary': + # It's a dictionary so return as a Map. + promiseCall = 'promiseToFutureAsMap' + promiseType = 'Future>' + 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)