Discussion:
[dart-misc] [dart-announce] Dart 1.22 is now available
'Kevin Moore' via Dart Announcements
2017-02-14 18:03:49 UTC
Permalink
Check out the announcement
<http://news.dartlang.org/2017/02/dart-122-faster-tools-assert-messages.html> and
the changelog <https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md>.

1.22.0 <https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#language>
Language

-

Breaking change: 'Generalized tear-offs'
<https://github.com/gbracha/generalizedTearOffs/blob/master/proposal.md> are
no longer supported, and will cause errors. We updated the language spec
and added warnings in 1.21, and are now taking the last step to fully
de-support them. They were previously only supported in the VM, and there
are almost no known uses of them in the wild.
-

The assert() statement has been expanded to support an optional second
message argument (SDK issue 27342
<https://github.com/dart-lang/sdk/issues/27342>).

The message is displayed if the assert fails. It can be any object, and
it is accessible as AssertionError.message. It can be used to provide
more user friendly exception outputs. As an example, the following assert:

assert(configFile != null, "Tool config missing. Please see https://goo.gl/k8iAi for details.");

would produce the following exception output:

Unhandled exception:
'file:///Users/mit/tmp/tool/bin/main.dart': Failed assertion: line 9 pos 10:
'configFile != null': Tool config missing. Please see https://goo.gl/k8iAi for details.
#0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:33)
#1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:29)
#2 main (file:///Users/mit/tmp/tool/bin/main.dart:9:10)

-

The Null type has been moved to the bottom of the type hierarchy. As
such, it is considered a subtype of every other type. The null *literal* was
always treated as a bottom type. Now the named class Null is too:

const empty = <Null>[];
String concatenate(List<String> parts) => parts.join();int sum(List<int> numbers) => numbers.fold(0, (sum, n) => sum + n);

concatenate(empty); // OK.
sum(empty); // OK.

-

Introduce covariant modifier on parameters. It indicates that the
parameter (and the corresponding parameter in any method that overrides it)
has looser override rules. In strong mode, these require a runtime type
check to maintain soundness, but enable an architectural pattern that is
useful in some code.

It lets you specialize a family of classes together, like so:

abstract class Predator {
void chaseAndEat(covariant Prey p);
}
abstract class Prey {}
class Mouse extends Prey {}
class Seal extends Prey {}
class Cat extends Predator {
void chaseAndEat(Mouse m) => ...
}
class Orca extends Predator {
void chaseAndEat(Seal s) => ...
}

This isn't statically safe, because you could do:

Predator predator = new Cat(); // Upcast.
predator.chaseAndEat(new Seal()); // Cats can't eat seals!

To preserve soundness in strong mode, in the body of a method that uses
a covariant override (here, Cat.chaseAndEat()), the compiler
automatically inserts a check that the parameter is of the expected type.
So the compiler gives you something like:

class Cat extends Predator {
void chaseAndEat(o) {
var m = o as Mouse;
...
}
}

Spec mode allows this unsound behavior on all parameters, even though
users rarely rely on it. Strong mode disallowed it initially. Now, strong
mode lets you opt into this behavior in the places where you do want it by
using this modifier. Outside of strong mode, the modifier is ignored.
-

Change instantiate-to-bounds rules for generic type parameters when
running in strong mode. If you leave off the type parameters from a generic
type, we need to decide what to fill them in with. Dart 1.0 says just use
dynamic, but that isn't sound:

class Abser<T extends num> {
void absThis(T n) { n.abs(); }
}
var a = new Abser(); // Abser<dynamic>.
a.absThis("not a num");

We want the body of absThis() to be able to safely assume n is at least
a num -- that's why there's a constraint on T, after all. Implicitly
using dynamic as the type parameter in this example breaks that.

Instead, strong mode uses the bound. In the above example, it fills it
in with num, and then the second line where a string is passed becomes a
static error.

However, there are some cases where it is hard to figure out what that
default bound should be:

class RuhRoh<T extends Comparable<T>> {}

Strong mode's initial behavior sometimes produced surprising, unintended
results. For 1.22, we take a simpler approach and then report an error if a
good default type argument can't be found.

<https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#core-libraries>Core
libraries

-

Define FutureOr<T> for code that works with either a future or an
immediate value of some type. For example, say you do a lot of text
manipulation, and you want a handy function to chain a bunch of them:

typedef String StringSwizzler(String input);
String swizzle(String input, List<StringSwizzler> swizzlers) {
var result = input;
for (var swizzler in swizzlers) {
result = swizzler(result);
}

return result;
}

This works fine:

main() {
var result = swizzle("input", [
(s) => s.toUpperCase(),
(s) => () => s * 2)
]);
print(result); // "INPUTINPUT".
}

Later, you realize you'd also like to support swizzlers that are
asynchronous (maybe they look up synonyms for words online). You could make
your API strictly asynchronous, but then users of simple synchronous
swizzlers have to manually wrap the return value in a Future.value().
Ideally, your swizzle() function would be "polymorphic over asynchrony".
It would allow both synchronous and asynchronous swizzlers. Because awaitaccepts
immediate values, it is easy to implement this dynamically:

Future<String> swizzle(String input, List<StringSwizzler> swizzlers) async {
var result = input;
for (var swizzler in swizzlers) {
result = await swizzler(result);
}

return result;
}

main() async {
var result = swizzle("input", [
(s) => s.toUpperCase(),
(s) => new Future.delayed(new Duration(milliseconds: 40), () => s * 2)
]);
print(await result);
}

What should the declared return type on StringSwizzler be? In the past,
you had to use dynamic or Object, but that doesn't tell the user much.
Now, you can do:

typedef FutureOr<String> StringSwizzler(String input);

Like the name implies, FutureOr<String> is a union type. It can be a
String or a Future<String>, but not anything else. In this case, that's
not super useful beyond just stating a more precise type for readers of the
code. It does give you a little better error checking in code that uses the
result of that.

FutureOr<T> becomes really important in *generic* methods like
Future.then(). In those cases, having the type system understand this
magical union type helps type inference figure out the type argument of
then() based on the closure you pass it.

Previously, strong mode had hard-coded rules for handling Future.then()
specifically. FutureOr<T> exposes that functionality so third-party
APIs can take advantage of it too.

<https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#tool-changes>Tool
changes

-

Dart2Js
- Remove support for (long-time deprecated) mixin typedefs.
-

Pub
-

Avoid using a barback asset server for executables unless they
actually use transformers. This makes precompilation substantially faster,
produces better error messages when precompilation fails, and allows
globally-activated executables to consistently use the
Isolate.resolvePackageUri() API.
-

On Linux systems, always ignore packages' original file owners and
permissions when extracting those packages. This was already the default
under most circumstances.
-

Properly close the standard input stream of child processes started
using pub run.
-

Handle parse errors from the package cache more gracefully. A package
whose pubspec can't be parsed will now be ignored by pub get --offline and
deleted by pub cache repair.
-

Make pub run run executables in spawned isolates. This lets them
handle signals and use standard IO reliably.
-

Fix source-maps produced by dart2js when running in pub serve: URL
references to assets from packages match the location where pub serve serves
them (packages/package_name/ instead of../packages/package_name/).

<https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#infrastructure-changes>Infrastructure
changes

- The SDK now uses GN rather than gyp to generate its build files, which
will now be exclusively ninja flavored. Documentation can be found on our
wiki <https://github.com/dart-lang/sdk/wiki/Building-with-GN>. Also see
the help message of tools/gn.py. This change is in response to the
deprecation of gyp. Build file generation with gyp will continue to be
available in this release by setting the environment variable
DART_USE_GYP before running gclient sync or gclient runhooks, but this
will be removed in a future release.
--
For more news and information, visit https://plus.google.com/+dartlang

To join the conversation, visit https://groups.google.com/a/dartlang.org/
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Loading...