diff --git a/CHANGELOG.md b/CHANGELOG.md index 58074e9a8f1..bd76c512b90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ ### Libraries +#### `dart:async` + +- Added `Future.pause` as alternative to `Future.delayed` with no callback. +- Added `List.unmodifiableOf` with better typing than `List.unmodifiable`. +- Added `Map.unmodifiableOf` with better typing than `Map.unmodifiable`. + #### `dart:io` - The cookie-date parser now uses the correct algorithm again. diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.expect index 3e00f36be5d..889dd2a6cbb 100644 --- a/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.expect +++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.expect @@ -39,6 +39,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#MyList#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#MyList#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); constants { #C1 = constructor-tearoff core::List::filled diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.modular.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.modular.expect index 3e00f36be5d..889dd2a6cbb 100644 --- a/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.modular.expect +++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.modular.expect @@ -39,6 +39,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#MyList#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#MyList#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); constants { #C1 = constructor-tearoff core::List::filled diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.outline.expect index 082fb013eb4..cd85b0ac20c 100644 --- a/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.outline.expect +++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.outline.expect @@ -19,3 +19,5 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#MyList#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#MyList#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.transformed.expect index ffc9bb81945..6f2b132187f 100644 --- a/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/issue47462.dart.strong.transformed.expect @@ -39,6 +39,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#MyList#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#MyList#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); constants { #C1 = constructor-tearoff core::List::filled @@ -52,4 +54,4 @@ constants { Extra constant evaluation status: Evaluated: StaticInvocation @ org-dartlang-testcase:///issue47462.dart:18:16 -> BoolConstant(true) Evaluated: StaticInvocation @ org-dartlang-testcase:///issue47462.dart:19:17 -> BoolConstant(false) -Extra constant evaluation: evaluated: 50, effectively constant: 2 +Extra constant evaluation: evaluated: 52, effectively constant: 2 diff --git a/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.expect b/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.expect index 48710e44ff7..d94f898c872 100644 --- a/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.expect +++ b/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.expect @@ -555,6 +555,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16a#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias16a#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#empty#tearOff({core::bool growable = #C2}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#filled#tearOff(core::int length, self::E16a% /* erasure=invalid-type, declared=! */ fill, {core::bool growable = #C2}) → core::List @@ -567,6 +569,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias16b#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#empty#tearOff({core::bool growable = #C2}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#filled#tearOff(core::int length, self::_#Alias23#filled#tearOff::T% fill, {core::bool growable = #C2}) → core::List @@ -579,6 +583,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias23#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#empty#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>({core::bool growable = #C2}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#filled#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::int length, self::_#Alias24#filled#tearOff::T% fill, {core::bool growable = #C2}) → core::List @@ -591,6 +597,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#unmodifiable#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias24#unmodifiableOf#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); constants { #C1 = 0 diff --git a/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.modular.expect b/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.modular.expect index 48710e44ff7..d94f898c872 100644 --- a/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.modular.expect +++ b/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.modular.expect @@ -555,6 +555,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16a#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias16a#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#empty#tearOff({core::bool growable = #C2}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#filled#tearOff(core::int length, self::E16a% /* erasure=invalid-type, declared=! */ fill, {core::bool growable = #C2}) → core::List @@ -567,6 +569,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias16b#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#empty#tearOff({core::bool growable = #C2}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#filled#tearOff(core::int length, self::_#Alias23#filled#tearOff::T% fill, {core::bool growable = #C2}) → core::List @@ -579,6 +583,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias23#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#empty#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>({core::bool growable = #C2}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#filled#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::int length, self::_#Alias24#filled#tearOff::T% fill, {core::bool growable = #C2}) → core::List @@ -591,6 +597,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#unmodifiable#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias24#unmodifiableOf#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); constants { #C1 = 0 diff --git a/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.outline.expect b/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.outline.expect index 78b01499c34..0bfba13c806 100644 --- a/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.outline.expect +++ b/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.outline.expect @@ -495,6 +495,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16a#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias16a#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#empty#tearOff({has-declared-initializer core::bool growable}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#filled#tearOff(core::int length, self::E16a% /* erasure=invalid-type, declared=! */ fill, {has-declared-initializer core::bool growable}) → core::List @@ -507,6 +509,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias16b#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#empty#tearOff({has-declared-initializer core::bool growable}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#filled#tearOff(core::int length, self::_#Alias23#filled#tearOff::T% fill, {has-declared-initializer core::bool growable}) → core::List @@ -519,6 +523,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias23#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#empty#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>({has-declared-initializer core::bool growable}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#filled#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::int length, self::_#Alias24#filled#tearOff::T% fill, {has-declared-initializer core::bool growable}) → core::List @@ -531,3 +537,5 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#unmodifiable#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias24#unmodifiableOf#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); diff --git a/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.transformed.expect b/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.transformed.expect index 48710e44ff7..d94f898c872 100644 --- a/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/extension_types/cyclic_representation_type.dart.strong.transformed.expect @@ -555,6 +555,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16a#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias16a#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#empty#tearOff({core::bool growable = #C2}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#filled#tearOff(core::int length, self::E16a% /* erasure=invalid-type, declared=! */ fill, {core::bool growable = #C2}) → core::List @@ -567,6 +569,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias16b#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias16b#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#empty#tearOff({core::bool growable = #C2}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#filled#tearOff(core::int length, self::_#Alias23#filled#tearOff::T% fill, {core::bool growable = #C2}) → core::List @@ -579,6 +583,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias23#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias23#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#empty#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>({core::bool growable = #C2}) → core::List return core::List::empty(growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#filled#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::int length, self::_#Alias24#filled#tearOff::T% fill, {core::bool growable = #C2}) → core::List @@ -591,6 +597,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#Alias24#unmodifiable#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#Alias24#unmodifiableOf#tearOff% /* erasure=invalid-type, declared=! */ = self::E24% /* erasure=invalid-type, declared=! */>(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); constants { #C1 = 0 diff --git a/pkg/front_end/testcases/general/issue47462.dart.strong.expect b/pkg/front_end/testcases/general/issue47462.dart.strong.expect index 3e00f36be5d..889dd2a6cbb 100644 --- a/pkg/front_end/testcases/general/issue47462.dart.strong.expect +++ b/pkg/front_end/testcases/general/issue47462.dart.strong.expect @@ -39,6 +39,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#MyList#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#MyList#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); constants { #C1 = constructor-tearoff core::List::filled diff --git a/pkg/front_end/testcases/general/issue47462.dart.strong.modular.expect b/pkg/front_end/testcases/general/issue47462.dart.strong.modular.expect index 3e00f36be5d..889dd2a6cbb 100644 --- a/pkg/front_end/testcases/general/issue47462.dart.strong.modular.expect +++ b/pkg/front_end/testcases/general/issue47462.dart.strong.modular.expect @@ -39,6 +39,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#MyList#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#MyList#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); constants { #C1 = constructor-tearoff core::List::filled diff --git a/pkg/front_end/testcases/general/issue47462.dart.strong.outline.expect b/pkg/front_end/testcases/general/issue47462.dart.strong.outline.expect index 082fb013eb4..cd85b0ac20c 100644 --- a/pkg/front_end/testcases/general/issue47462.dart.strong.outline.expect +++ b/pkg/front_end/testcases/general/issue47462.dart.strong.outline.expect @@ -19,3 +19,5 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#MyList#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#MyList#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); diff --git a/pkg/front_end/testcases/general/issue47462.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue47462.dart.strong.transformed.expect index ffc9bb81945..6f2b132187f 100644 --- a/pkg/front_end/testcases/general/issue47462.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/general/issue47462.dart.strong.transformed.expect @@ -39,6 +39,8 @@ static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/arr return core::List::generate(length, generator, growable: growable); static synthetic method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/array_patch.dart */ _#MyList#unmodifiable#tearOff(core::Iterable elements) → core::List return core::List::unmodifiable(elements); +static synthetic method /* from org-dartlang-sdk:///sdk/lib/core/list.dart */ _#MyList#unmodifiableOf#tearOff(core::Iterable elements) → core::List + return core::List::unmodifiableOf(elements); constants { #C1 = constructor-tearoff core::List::filled @@ -52,4 +54,4 @@ constants { Extra constant evaluation status: Evaluated: StaticInvocation @ org-dartlang-testcase:///issue47462.dart:18:16 -> BoolConstant(true) Evaluated: StaticInvocation @ org-dartlang-testcase:///issue47462.dart:19:17 -> BoolConstant(false) -Extra constant evaluation: evaluated: 50, effectively constant: 2 +Extra constant evaluation: evaluated: 52, effectively constant: 2 diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart index 98f8447caf7..490b12d0064 100644 --- a/sdk/lib/async/future.dart +++ b/sdk/lib/async/future.dart @@ -399,16 +399,19 @@ abstract interface class Future { /// /// If [computation] returns a future, /// the future returned by this constructor will complete with the value or - /// error of that future. + /// error of that future, which may not be available until even later. /// /// If the duration is 0 or less, /// it completes no sooner than in the next event-loop iteration, /// after all microtasks have run. + /// (The waiting for the delay uses a [Timer] created in the current zone.) /// - /// If [computation] is omitted, - /// it will be treated as if [computation] was `() => null`, + /// The computation must not be omitted, and must not be null. + /// Use [Future.pause] instead if you just want to wait for duration. + /// Until that is reflected in the signature, if [computation] is omitted, + /// then [T] must be nullable. + /// Then the computation will be treated as if it was `() => null`, /// and the future will eventually complete with the `null` value. - /// In that case, [T] must be nullable. /// /// If calling [computation] throws, the created future will complete with the /// error. @@ -418,11 +421,16 @@ abstract interface class Future { /// /// Example: /// ```dart - /// Future.delayed(const Duration(seconds: 1), () { - /// print('One second has passed.'); // Prints after 1 second. + /// var now = DateTime.now(); + /// var later = await Future.delayed(const Duration(seconds: 1), () { + /// return DateTime.timestamp(); /// }); + /// print(now.difference(later)); // At least a second. /// ``` - factory Future.delayed(Duration duration, [FutureOr computation()?]) { + factory Future.delayed( + Duration duration, [ + FutureOr Function()? computation, + ]) { if (computation == null && !typeAcceptsNull()) { throw ArgumentError.value( null, @@ -448,6 +456,19 @@ abstract interface class Future { return result; } + /// Creates a [Future] that completes with no result after [duration]. + /// + /// Like [Future.delayed], but does not perform any action, + /// and cannot complete with an error. + @Since("3.13") + static Future pause([Duration duration = Duration.zero]) { + var result = _Future(); + Zone._current.createTimer(duration, () { + result._completeWithValue(null); + }); + return result; + } + /// Waits for multiple futures to complete and collects their results. /// /// Returns a future which will complete once all the provided futures diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart index 429209e9daa..c898dfeb125 100644 --- a/sdk/lib/core/list.dart +++ b/sdk/lib/core/list.dart @@ -191,7 +191,10 @@ abstract interface class List implements Iterable, _ListIterable { /// /// This constructor creates a growable list when [growable] is true; /// otherwise, it returns a fixed-length list. - external factory List.from(Iterable elements, {bool growable = true}); + external factory List.from( + Iterable elements, { + bool growable = true, + }); /// Creates a list from [elements]. /// @@ -241,8 +244,24 @@ abstract interface class List implements Iterable, _ListIterable { /// final unmodifiableList = List.unmodifiable(numbers); // [1, 2, 3] /// unmodifiableList[1] = 87; // Throws. /// ``` + // @Deprecated("Use List.unmodifiableOf instead") external factory List.unmodifiable(Iterable elements); + /// Creates an unmodifiable list containing all [elements]. + /// + /// The [Iterator] of [elements] provides the order of the elements. + /// + /// An unmodifiable list cannot have its length or elements changed. + /// If the elements are themselves immutable, then the resulting list + /// is also immutable. + /// ```dart + /// final numbers = [1, 2, 3]; + /// final unmodifiableList = List.unmodifiable(numbers); // [1, 2, 3] + /// unmodifiableList[1] = 87; // Throws. + /// ``` + @Since("3.13") + factory List.unmodifiableOf(Iterable elements) = List.unmodifiable; + /// Adapts [source] to be a `List`. /// /// Any time the list would produce an element that is not a [T], diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart index 12c0cca11a3..42bc4f5529b 100644 --- a/sdk/lib/core/map.dart +++ b/sdk/lib/core/map.dart @@ -92,8 +92,26 @@ abstract interface class Map { /// final unmodifiableMap = Map.unmodifiable(planets); /// unmodifiableMap[4] = 'Mars'; // Throws /// ``` + // @Deprecated("Use Map.unmodifiableOf instead") external factory Map.unmodifiable(Map other); + /// Creates an unmodifiable hash-based map containing the entries of [other]. + /// + /// The map requires the keys to implement compatible + /// `operator==` and `hashCode`. + /// The created map iterates keys in a fixed order, + /// preserving the order provided by [other]. + /// + /// The resulting map behaves like the result of [Map.of], + /// except that the map returned by this constructor is not modifiable. + /// ```dart + /// final planets = {1: 'Mercury', 2: 'Venus', 3: 'Earth'}; + /// final unmodifiableMap = Map.unmodifiableOf(planets); + /// unmodifiableMap[4] = 'Mars'; // Throws + /// ``` + @Since("3.13") + factory Map.unmodifiableOf(Map other) = Map.unmodifiable; + /// Creates an identity map with the default implementation, [LinkedHashMap]. /// /// An identity map uses [identical] for equality and [identityHashCode] diff --git a/tests/corelib/list_unmodifiable_test.dart b/tests/corelib/list_unmodifiable_test.dart index deb16effccc..a1a15e31c42 100644 --- a/tests/corelib/list_unmodifiable_test.dart +++ b/tests/corelib/list_unmodifiable_test.dart @@ -36,13 +36,13 @@ class Test { Test(this.element); - run(name, Iterable create(int size)) { + void run(String name, Iterable create(int size)) { test(name, create(0)); test(name, create(1)); test(name, create(3)); } - test(name, iterable) { + void test(String name, Iterable iterable) { testSingle(name, iterable); testSingle("$name-where", iterable.where((x) => true)); testSingle("$name-map", iterable.map((x) => x)); @@ -53,180 +53,188 @@ class Test { testSingle("$name-takeWhile", iterable.takeWhile((x) => true)); } - testSingle(name, iterable) { + void testSingle(String name, Iterable iterable) { var elements = iterable.toList(); int length = elements.length; - var list = new List.unmodifiable(iterable); + for (var list in [ + new List.unmodifiable(iterable), + // Not the case for "subclass" test. + if (iterable is Iterable) new List.unmodifiableOf(iterable), + ]) { + Expect.isTrue(list is List, "$name-type-$E"); + Expect.isTrue(list is! List, "$name-!type-!$E"); - Expect.isTrue(list is List, "$name-type-$E"); - Expect.isTrue(list is! List, "$name-!type-!$E"); - - checkElements() { - Expect.equals(length, list.length); - for (int i = 0; i < length; i++) { - Expect.identical(elements[i], list[i], "$name-identical-$i"); + checkElements() { + Expect.equals(length, list.length); + for (int i = 0; i < length; i++) { + Expect.identical(elements[i], list[i], "$name-identical-$i"); + } } - } - checkElements(); - - throws(funcName, func) { - try { - func(); - } catch (e, s) { - Expect.isTrue(e is UnsupportedError, "$name: $funcName threw $e"); - return; - } checkElements(); - Expect.fail("$name: $funcName didn't throw"); - } - throws("[]=", () { - list[0] = element; - }); - throws("length=", () { - list.length = length + 1; - }); - throws("length=", () { - list.length = length - 1; - }); - throws("setAll", () { - list.setAll(0, []); - }); - throws("add", () { - list.add(element); - }); - throws("insert", () { - list.insert(0, element); - }); - throws("insertAll", () { - list.insertAll(0, []); - }); - throws("addAll", () { - list.addAll([]); - }); - throws("remove", () { - list.remove(element); - }); - throws("removeWhere", () { - list.removeWhere((x) => true); - }); - throws("retainWhere", () { - list.retainWhere((x) => false); - }); - throws("sort", () { - list.sort(); - }); - throws("shuffle", () { - list.shuffle(); - }); - throws("clear", () { - list.clear(); - }); - throws("removeAt", () { - list.removeAt(0); - }); - throws("removeLast", () { - list.removeLast(); - }); - throws("setRange", () { - list.setRange(0, 1, []); - }); - throws("removeRange", () { - list.removeRange(0, 1); - }); - throws("replaceRange", () { - list.replaceRange(0, 1, []); - }); - throws("fillRange", () { - list.fillRange(0, 1, element); - }); + throws(funcName, func) { + try { + func(); + } catch (e, s) { + Expect.isTrue(e is UnsupportedError, "$name: $funcName threw $e"); + return; + } + checkElements(); + Expect.fail("$name: $funcName didn't throw"); + } - success(opName, op(List list), [bool throws = false]) { - if (throws) { - var e1, e2; - Expect.throws(() => op(elements), (e) { - e1 = e; - return true; - }, '$name :: $opName should throw for $elements'); - Expect.throws(() => op(list), (e) { - e2 = e; - return true; - }, '$name :: $opName should throw for $list'); - Expect.equals( - e1.runtimeType, - e2.runtimeType, - "$name :: $opName threw different errors for $elements and $list: " - "${e1.runtimeType} vs ${e2.runtimeType}", + throws("[]=", () { + list[0] = element; + }); + throws("length=", () { + list.length = length + 1; + }); + throws("length=", () { + list.length = length - 1; + }); + throws("setAll", () { + list.setAll(0, []); + }); + throws("add", () { + list.add(element); + }); + throws("insert", () { + list.insert(0, element); + }); + throws("insertAll", () { + list.insertAll(0, []); + }); + throws("addAll", () { + list.addAll([]); + }); + throws("remove", () { + list.remove(element); + }); + throws("removeWhere", () { + list.removeWhere((x) => true); + }); + throws("retainWhere", () { + list.retainWhere((x) => false); + }); + throws("sort", () { + list.sort(); + }); + throws("shuffle", () { + list.shuffle(); + }); + throws("clear", () { + list.clear(); + }); + throws("removeAt", () { + list.removeAt(0); + }); + throws("removeLast", () { + list.removeLast(); + }); + throws("setRange", () { + list.setRange(0, 1, []); + }); + throws("removeRange", () { + list.removeRange(0, 1); + }); + throws("replaceRange", () { + list.replaceRange(0, 1, []); + }); + throws("fillRange", () { + list.fillRange(0, 1, element); + }); + + success(opName, op(List list), [bool throws = false]) { + if (throws) { + var e1, e2; + Expect.throws(() => op(elements), (e) { + e1 = e; + return true; + }, '$name :: $opName should throw for $elements'); + Expect.throws(() => op(list), (e) { + e2 = e; + return true; + }, '$name :: $opName should throw for $list'); + Expect.equals( + e1.runtimeType, + e2.runtimeType, + "$name :: $opName threw different errors for $elements and $list: " + "${e1.runtimeType} vs ${e2.runtimeType}", + ); + return; + } + var expect = op(elements); + var actual = op(list); + checkElements(); + if (expect is List) { + Expect.listEquals(expect, actual, "$name-$opName"); + } else if (expect is Iterable) { + Expect.isTrue(actual is Iterable); + Expect.listEquals(expect.toList(), actual.toList(), "$name-$opName"); + } else { + Expect.equals(expect, actual, "$name-$opName"); + } + } + + success("indexOf", (l) => l.indexOf(element)); + success("lastIndexOf", (l) => l.lastIndexOf(element)); + success("contains", (l) => l.contains(2)); + success("elementAt", (l) => l.elementAt(1), list.length < 2); + success("reversed", (l) => l.reversed); + success("sublist0-1", (l) => l.sublist(0, 1), list.isEmpty); + success("getRange0-1", (l) => l.getRange(0, 1), list.isEmpty); + success("asMap-keys", (l) => l.asMap().keys); + success("asMap-values", (l) => l.asMap().values); + success("where", (l) => l.where((x) => true)); + success("map", (l) => l.map((x) => x)); + success("expand", (l) => l.expand((x) => [x, x])); + success("skip", (l) => l.skip(1)); + success("take", (l) => l.take(1)); + success("skipWhile", (l) => l.skipWhile((x) => false)); + success("takeWhile", (l) => l.takeWhile((x) => true)); + success("first", (l) => l.first, list.isEmpty); + success("last", (l) => l.last, list.isEmpty); + success("single", (l) => l.single, list.length != 1); + success("firstWhere", (l) => l.firstWhere((x) => true), list.isEmpty); + success("lastWhere", (l) => l.lastWhere((x) => true), list.isEmpty); + success( + "singleWhere", + (l) => l.singleWhere((x) => true), + list.length != 1, + ); + success("isEmpty", (l) => l.isEmpty); + success("isNotEmpty", (l) => l.isNotEmpty); + success("join", (l) => l.join("/")); + success("fold", (l) => l.fold("--", (a, b) => "$a/$b")); + if (elements is List && list is List) { + success( + "reduce", + (l) => (l as List).reduce((a, b) => (a + b).floor()), + list.isEmpty, ); - return; } - var expect = op(elements); - var actual = op(list); - checkElements(); - if (expect is List) { - Expect.listEquals(expect, actual, "$name-$opName"); - } else if (expect is Iterable) { - Expect.isTrue(actual is Iterable); - Expect.listEquals(expect.toList(), actual.toList(), "$name-$opName"); - } else { - Expect.equals(expect, actual, "$name-$opName"); + success("every", (l) => l.every((x) => x == 0)); + success("any", (l) => l.any((x) => x == 2)); + success("toList", (l) => l.toList()); + success("toSet", (l) => l.toSet()); + success("toString", (l) => l.toString()); + + var it = elements.iterator; + list.forEach((v) { + Expect.isTrue(it.moveNext()); + Expect.equals(it.current, v); + }); + Expect.isFalse(it.moveNext()); + + if (elements is List && list is List) { + success( + "String.fromCharCodes", + (l) => new String.fromCharCodes(l as List), + ); } } - - success("indexOf", (l) => l.indexOf(element)); - success("lastIndexOf", (l) => l.lastIndexOf(element)); - success("contains", (l) => l.contains(2)); - success("elementAt", (l) => l.elementAt(1), list.length < 2); - success("reversed", (l) => l.reversed); - success("sublist0-1", (l) => l.sublist(0, 1), list.isEmpty); - success("getRange0-1", (l) => l.getRange(0, 1), list.isEmpty); - success("asMap-keys", (l) => l.asMap().keys); - success("asMap-values", (l) => l.asMap().values); - success("where", (l) => l.where((x) => true)); - success("map", (l) => l.map((x) => x)); - success("expand", (l) => l.expand((x) => [x, x])); - success("skip", (l) => l.skip(1)); - success("take", (l) => l.take(1)); - success("skipWhile", (l) => l.skipWhile((x) => false)); - success("takeWhile", (l) => l.takeWhile((x) => true)); - success("first", (l) => l.first, list.isEmpty); - success("last", (l) => l.last, list.isEmpty); - success("single", (l) => l.single, list.length != 1); - success("firstWhere", (l) => l.firstWhere((x) => true), list.isEmpty); - success("lastWhere", (l) => l.lastWhere((x) => true), list.isEmpty); - success("singleWhere", (l) => l.singleWhere((x) => true), list.length != 1); - success("isEmpty", (l) => l.isEmpty); - success("isNotEmpty", (l) => l.isNotEmpty); - success("join", (l) => l.join("/")); - success("fold", (l) => l.fold("--", (a, b) => "$a/$b")); - if (elements is List && list is List) { - success( - "reduce", - (l) => (l as List).reduce((a, b) => (a + b).floor()), - list.isEmpty, - ); - } - success("every", (l) => l.every((x) => x == 0)); - success("any", (l) => l.any((x) => x == 2)); - success("toList", (l) => l.toList()); - success("toSet", (l) => l.toSet()); - success("toString", (l) => l.toString()); - - var it = elements.iterator; - list.forEach((v) { - Expect.isTrue(it.moveNext()); - Expect.equals(it.current, v); - }); - Expect.isFalse(it.moveNext()); - - if (elements is List && list is List) { - success( - "String.fromCharCodes", - (l) => new String.fromCharCodes(l as List), - ); - } } } @@ -243,36 +251,36 @@ List createGrowableList(int n) { return new List.filled(n, n, growable: true); } -Iterable createIterable(int n) => new Iterable.generate(n); -Iterable createConstMapKeys(int n) { +Iterable createIterable(int n) => new Iterable.generate(n); +Iterable createConstMapKeys(int n) { if (n == 0) return const {}.keys; return const {0: 0, 1: 1, 2: 2}.keys; } -Iterable createConstMapValues(int n) { +Iterable createConstMapValues(int n) { if (n == 0) return const {}.values; return const {0: 0, 1: 1, 2: 2}.values; } -Iterable createMapKeys(int n) { +Iterable createMapKeys(int n) { var map = {}; for (int i = 0; i < n; i++) map[i] = i; return map.keys; } -Iterable createMapValues(int n) { +Iterable createMapValues(int n) { var map = {}; for (int i = 0; i < n; i++) map[i] = i; return map.values; } -Iterable createSplayMapKeys(int n) { +Iterable createSplayMapKeys(int n) { var map = new SplayTreeMap(); for (int i = 0; i < n; i++) map[i] = i; return map.keys; } -Iterable createSplayMapValues(int n) { +Iterable createSplayMapValues(int n) { var map = new SplayTreeMap(); for (int i = 0; i < n; i++) map[i] = i; return map.values; @@ -296,11 +304,11 @@ Queue createQueue(int n) { return queue; } -Iterable createListMapKeys(int n) { +Iterable createListMapKeys(int n) { return createGrowableList(n).asMap().keys; } -Iterable createListMapValues(int n) { +Iterable createListMapValues(int n) { return createGrowableList(n).asMap().values; } diff --git a/tests/corelib/map_test.dart b/tests/corelib/map_test.dart index 17940797396..4bba7e80758 100644 --- a/tests/corelib/map_test.dart +++ b/tests/corelib/map_test.dart @@ -1115,6 +1115,7 @@ void testUnmodifiableMaps() { checkUnmodifiable(const {1: 1}); checkUnmodifiable(Map.unmodifiable({1: 1})); + checkUnmodifiable(Map.unmodifiableOf({1: 1})); checkUnmodifiable(UnmodifiableMapView({1: 1})); checkUnmodifiable(const MapView({1: 1})); } diff --git a/tests/corelib/map_unmodifiable_cast_test.dart b/tests/corelib/map_unmodifiable_cast_test.dart index d2fb897403d..115200077ff 100644 --- a/tests/corelib/map_unmodifiable_cast_test.dart +++ b/tests/corelib/map_unmodifiable_cast_test.dart @@ -30,9 +30,13 @@ void main() { "unmodView(int).cast", ); - var m2 = new Map.unmodifiable({1: 37}); - testNum(m2, "Map.unmod"); - testNum(m2.cast(), "Map.unmod.cast"); + for (var map in [ + new Map.unmodifiable({1: 37}), + new Map.unmodifiableOf({1: 37}), + ]) { + testNum(map, "Map.unmod"); + testNum(map.cast(), "Map.unmod.cast"); + } Map nsm = new NsmMap().foo(a: 0); test(nsm, #a, 0, "nsm", noSuchMethodMap: true); diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart index 9805ed29f80..f1ee7936b50 100644 --- a/tests/lib/async/future_test.dart +++ b/tests/lib/async/future_test.dart @@ -1319,6 +1319,109 @@ void testIgnoreWhenCompleteError() { Future.delayed(Duration.zero, asyncEnd); } +void testFuturePause() { + const Duration low = Duration(milliseconds: 10); + const Duration mid = Duration(milliseconds: 20); + const Duration hi = Duration(milliseconds: 30); + // No argument means Duration.zero. + + asyncStart(); + var timers = 0; + void expectTimer(int n) { + timers++; + Expect.equals(n, timers); + } + + Timer(hi, () { + expectTimer(10); + }); + Timer(mid, () { + expectTimer(7); + }); + Timer(low, () { + expectTimer(4); + }); + Timer(Duration.zero, () { + expectTimer(1); + }); + Future.pause(hi).then((_) { + expectTimer(11); + }); + Future.pause(mid).then((_) { + expectTimer(8); + }); + Future.pause(low).then((_) { + expectTimer(5); + }); + Future.pause().then((_) { + expectTimer(2); + }); + Timer(hi, () { + expectTimer(12); + asyncEnd(); + }); + Timer(mid, () { + expectTimer(9); + }); + Timer(low, () { + expectTimer(6); + }); + Timer(Duration.zero, () { + expectTimer(3); + }); +} + +void testFuturePauseNoArg() { + asyncStart(); + // No argument means Duration.zero. + var microtasks = 0; + var timers = 0; + void expectMicrotask(int expectedMicrotasks, int expectedTimers) { + microtasks++; + Expect.equals(expectedMicrotasks, microtasks); + Expect.equals(expectedTimers, timers); + } + + void expectTimer(int expectedTimers) { + timers++; + microtasks = 0; + Expect.equals(expectedTimers, timers); + } + + scheduleMicrotask(() { + expectMicrotask(1, 0); + }); + Future.microtask(() { + expectMicrotask(2, 0); + }); + Timer(Duration.zero, () { + expectTimer(1); + scheduleMicrotask(() { + expectMicrotask(1, 1); + }); + }); + Timer(const Duration(milliseconds: 10), () { + expectTimer(4); + asyncEnd(); + }); + // Behaves as timer.zero. + Future.pause().then((_) { + expectTimer(2); + scheduleMicrotask(() { + expectMicrotask(1, 2); + }); + }); + scheduleMicrotask(() { + expectMicrotask(3, 0); + }); + Future.microtask(() { + expectMicrotask(4, 0); + }); + Timer(Duration.zero, () { + expectTimer(3); + }); +} + void main() { asyncStart(); @@ -1373,6 +1476,9 @@ void main() { testChainedFutureValueDelay(); testChainedFutureError(); + testFuturePause(); + testFuturePauseNoArg(); + testSyncFuture_i13368(); testWaitCleanUp();