Thursday, March 28, 2013

Why dart2js produces faster JavaScript code from Dart

The dart2js compiler, which converts Dart to JavaScript, now produces smaller and faster code thanks to its global type inferencer. By analyzing the entire program, the compiler can eliminate bailouts and redundant checks, resulting in code that runs faster on modern JavaScript engines.

As evidenced by the graph below, the performance of the code generated by dart2js (the purple line) now slightly outperforms the original hand-written benchmark code (the gold line). The Dart VM, which natively runs Dart code, is the top line. High is better in this benchmark (Dart code, JavaScript code).

Taken on 2012/03/28. From

Type inferencing helps performance

Nicolas Geoffray, engineer on dart2js, has been working on the beginnings of the global type inferencer. In a recent interview (video) he showed examples of the original Dart code, the previously generated JavaScript code, and the new more optimized JavaScript code.

Code gets smaller, faster

For reference, here is a snippet of raw Dart code from the original benchmark:

 void addConstraintsConsumingTo(Variable v, List<Constraint> coll) {  
  Constraint determining = v.determinedBy;  
   for (int i = 0; i < v.constraints.length; i++) {  
    Constraint c = v.constraints[i];  
    if (c != determining && c.isSatisfied()) {  

Previously, the dart2js compiler would output this JavaScript code (for why, see Preserving Semantics below):

 addConstraintsConsumingTo$2: function(v, coll) {  
   var determining, i, t1, c;  
   determining = v.get$determinedBy();  
   i = 0;  
   while (true) {  
    t1 = $.get$length$as(v.get$constraints());  
    if (typeof t1 !== "number")  
         return bailout(1, v, coll, i, determining, t1);  
    if (!(i < t1))  
    t1 = v.get$constraints();  
    if (t1.constructor !== Array)  
     return bailout(2, v, coll, i, determining, t1);  
    if (i >= t1.length)  
     throw $.ioore(i);  
    c = t1[i];  
    if (!$.$eq(c, determining) && c.isSatisfied$0() === true)  

Since revision 20130 of dart2js, the JavaScript output now looks like this:

  addConstraintsConsumingTo$2: function(v, coll) {  
   var determining, t1, i, c;  
   determining = v.determinedBy;  
   for (t1 = v.constraints, i = 0; i < t1.length; ++i) {  
    c = t1[i];  
    if ((c == null ? determining != null : c !== determining)  
      && c.isSatisfied$0()) {  

The second version is obviously smaller, and runs faster in part because:

  • bailout code is removed
    • ex: no more return bailout(1...
  • type checks are removed
    • ex: no more typeof t1 !== "number"
  • the while loop is replaced by a for loop
  • function calls are replaced by field access
    • ex: v.get$determinedBy() is now v.determinedBy

Preserving null semantics

Remember that Dart is not just a different syntax for JavaScript, but is itself a new language and libraries with their own semantics. These semantics need to be preserved when compiled to JavaScript, which helps to explain why the original JavaScript code was so verbose. However, the global type inferencing can now help to reduce the verbosity, without changing the semantics of the operations.

Treatment of nulls is a good example of differing behavior between Dart and JavaScript. Consider this code snippet:

 var x = null;  
 var y = 1;  
 var results = x + y;  
  // Dart throws NoSuchMethodError because the null object  
  // doesn't define the + operator.  
  // However, JavaScript sets results to 1.

Many developers appreciate being told when they try to use a null variable, and thus like the NoSuchMethodError. The dart2js compiler needs to ensure this behavior is retained. However, if dart2js can determine during program compilation that x is never null, then dart2js can eliminate the extra checks and just emit the straightforward JavaScript code.

[Disclaimer! What follows is a snapshot of dart2js's behavior on 2013/03/28.]

Here is an example. Consider the following code:

 var x = null;  
 var y = 1;  
 var results = x + y;

Notice how x is null, which forces dart2js to emit this code:

 $.main = function() {  
  $.Primitives_printString($.toString$0($.JSNull_methods.$add(null, 1)));  

However, if x is not null, dart2js can generate intelligent code that eliminates the null handling:

 $.main = function() {  

Notice how dart2js inlines the addition into the literal value 3.

Here is a more complex example. Pay close attention to the complete lack of type annotations. This shows that dart2js performs its type inferencing based on how objects are used, not on how variables are annotated.  (Remember that Dart is an optionally typed language, so the type annotations are ignored at runtime. However, as you can see, the runtimes still make intelligent decisions.)

 add(x , y) {  
  var z = x * 2;  
  return z + y;  
 main() {  
  var x = null;  
  var y = 1;  
  var result = add(x, y);  

Because x is null, dart2js outputs the following JavaScript code:

 $.main = function() {  
  $.Primitives_printString($.toString$0($.$add$ns($.JSNull_methods.$mul(null, 2), 1)));  
 $.$add$ns = function(receiver, a0) {  
  if (typeof receiver == "number" && typeof a0 == "number")  
   return receiver + a0;  
  return $.getInterceptor$ns(receiver).$add(receiver, a0);  

Now consider this code, where x is not null:

 add(x , y) {  
  var z = x * 2;  
  return z + y;  
 main() {  
  var x = 2;  
  var y = 1;  
  var result = add(x, y);  

The dart2js compiler knows that both x and y are not null, and generates this code:

 $.main = function() {  

Pretty impressive, if I do say so! Notice how dart2js inlines the call to add, and all the math, down to the literal number 5.

One more example of how dart2js can look at nulls. Consider this code, which explicitly checks for null parameters and throws an exception:

 add(x , y) {  
  if (x == null || y == null) throw new ArgumentError('must not be null');  
  var z = x * 2;  
  return z + y;  
 main() {  
  var x = null;  
  var y = 1;  
  var result = add(x, y);  

In a sense, you're putting in your own message to dart2js: "assume that if variables get past this check, that they are not null." Therefore, dart2js can generate the following code:

 $.add = function(x, y) {  
  if (x == null || false)  
   throw $.$$throw($.ArgumentError$("must not be null"));  
  return $.$add$ns($.JSNull_methods.$mul(x, 2), y);  
 $.main = function() {  
  $.Primitives_printString($.toString$0($.add(null, 1)));  

Not as good as when both x and y are not null, but better than the the code generated without the null guards.

The main point here is that dart2js maintains Dart semantics whenever it compiles to JavaScript. With type inferencing, it's now generating smarter, smaller, and ultimately faster code without sacrificing semantics.

Preserving index out of bounds semantics

Another example of different behavior between Dart and JavaScript is what happens when you access an index that is out of bounds of an array or list. Consider this code:

 var fruits = ['apples', 'oranges'];  
 var fruit = fruits[99];  
  // Dart will throw a RangeError because fruits only has two elements.  
  // JavaScript will set fruit to undefined.  

Again, many developers appreciate being explicitly told when they try to access an index that is out of bounds. To bring this behavior to JavaScript, dart2js needs to insert code and logic. For example:

 $.main = function() {  
  var fruits = ["apples", "oranges"];  
  if (99 >= fruits.length)  
   throw $.ioore(99);  

However, if dart2js can determine that an index access is never out of bounds of the list, it can optimize the generated code. There are two ways to make a list whose length is known at compile time: constant lists and fixed-length lists.

Here is an example of using a constant list:

 main() {  
  var fruits = const ['apples', 'oranges'];  
  var fruit = fruits[99];  

The dart2js compiler will output the following code, because it knows the length of the list at compile time:

$.main = function() {  
  throw $.ioore(99);  
 // ...  
 $.List_apples_oranges = Isolate.makeConstantList(["apples", "oranges"]);  

Notice how the exception is immediately thrown, because the compiler knows at compile time that 99 is out of the range of the list.


The dart2js compiler, which converts Dart code to JavaScript, must maintain Dart semantics in the generated output. Due to recent updates, dart2js can perform whole program analysis and in some cases eliminate bailouts, typechecks, range checks, and other code while keeping consistent with the semantics of the Dart language and libraries. This means smaller, and often faster, code.

The team isn't done yet, there's lots more work to be done. We caution developers from writing code specifically tuned for dart2js's behavior today, as there will be plenty of changes to the code generation algorithms. If you have some code that you believe should be generated more efficiently, please open a bug at so we can fix it for you.

Tuesday, March 26, 2013

An Important New Article on Working with Streams in Dart

Read Getting Your Feet Wet with Streamsthe latest article at and learn about Streams in Dart.

How do you model values that vary over continuous time? Or deal with events which occur at finite points in time? In the Javascript world, the answer often involves using Functional Reactive Programming (FRP), with frameworks like RxJs, bacon.js and Flapjax providing elegant approaches to traditional event-driven programming. 

In Dart, Streams provide a consistent interface for working with repeating events. Streams are everywhere in Dart! 

In an important new article, Chris Buckett details ways in which you can subscribe to (and unsubscribe from) a Stream. He shows how to transform, validate and consume Stream data, and handle errors using a StreamSubscription.  This article demystifies the subject of Streams: read it if you want to know more about this important topic.

Your feedback really counts. Please join the conversation at the Dart mailing list, and ask questions at Stack Overflow.

Photo credit:

Monday, March 25, 2013

Notes from the March 18 Dart Language Design Meeting

Once again, the always-helpful Bob Nystrom fills us in on the language design discussions taking place amongst Dart engineers. Here are his notes from the March 18 language meeting:


Lars: I like the "implements dynamic" thing.
Gilad: Me too, it's like a get out of jail free card.
Kasper: That means the type behaves like dynamic in all contexts? Even for is checks and checked mode checks?
Gilad: If you assign something to it, it goes through normal rules. But if you assign it to something, works like dynamic. It could go both ways.
Lars: The real solution would be to do it dynamically. Like you have noSuchMethod, you could have isSubtype on ClassMirror that returns a boolean. You could implement that to do what you want.
Gilad: That's complicated to implement.
Lars: Let's talk about the first solution with Ivan and Kasper.
Kasper: That means it will be a subtype of all types. If a class claims it implements dynamic and List, should you get warnings if you implement list methods incorrectly? Are we going to say it's illegal to implement list too?
Gilad: It's legal, but stupid. It won't change anything at all.
Lars: My perspective is, given that this is a corner case, I'm fine with it not having any effect if you also say you implement List.
Gilad: We could say implementing dynamic just affects subtyping, but you still get the same warnings internally in class.
Lars: I'm fine with that too.
Gilad: OK, i'll send around a proposal.

optional arguments and forwarding

Lars: No one is screaming for [the forwarding operator], so we'll just ignore it.
Gilad: Do we use "?" on its own?
Lars: It's being used a lot, so we keep it. As long as you aren't forwarding it's fine. Maybe we need to look at the reflective interface for calling methods. If we implement this proposed solution, it probably won't be used other than in a few places.
Kasper: Where are the uses of "?"? In the DOM mostly?
Lars: There's a lot in the DOM but in other places to.
Kasper: It's not a question of forwarding, but of being forwarded to.
Lars: I'm fine either way. I find it harder to read using null. It's hard to remove things because people are already screaming about breaking lib changes.

lazy loading

Lars: Gilad, are you up on what's going on there?
Gilad: I've seen the patches, but it's not in spec. I haven't had time to talk to Peter yet, but I'm tracking it.
Kasper: We haven't figured out if we want same solution on VM.
Gilad: I assumed that. What does that mean?
Lars: As a minimum, we need the same code to run there.
Kasper: Yes, load() should do something minimal.
Gilad: It would be nice if it actually could defer it.
Lars: I'm fine with the VM preloading it.
Gilad: In that case, it doesn't belong in spec because it has no particular behavior. It's a dart2js deployment detail.
Lars: Yes, easiest solution is to keep out of spec.


As always, view the changelog for the full list of changes, and to get started with the Editor, see our tutorial.

Wednesday, March 20, 2013

Significant Dart Editor Release Brings Back String Plus Operator

Dart Editor has a new build. This is a significant release with a long list of breaking changes. You are urged to update your Dart code accordingly. 

Due to popular demand, the Dart team brought back the plus operator for string concatenation. That change has now landed in the Editor. Before this release, using + to concatenate strings produced this

Now, you can use + for concatenation. The concat() method has been deprecated:

There are numerous other changes in the core libraries, the dart:html library, and the dart:io library. 
Eric Clayberg fills us in on the details of this release:

A new Dart Editor build is available at include:
  • New analyzer available via experimental preference.
    (work in progress, all features not enabled yet).
  • Package root preferences removed in favor of --package-root cmd line option.
  • Reduced heap usage by ~25%.
  • Fixed a memory leak which could eventually consume 10% of the heap.
Breaking Change List:
  • Wide-ranging changes:
    • All HTML callback APIs have been converted to Futures (with a few exceptions: RtcPeerConnection.getStats, Window.setImmediate, Window.requestAnimationFrame, Window.openDatabase, WorkerContext.openDatabase, and MutationObserver).
  • Name/functionality changes in corelib:
    • IOSink interface has changed. It now implements StringSink with the methods write,writeln, writeAll and writeCharCode for writing strings to an IOSink. As writing strings to an IOSink requires an encoding theIOSink now has en encoding property. Depending on what the IOSink is connected to this encoding property might be mutable. For the IOSink on HttpClientRequest and HttpResponse the encoding is determined from the "charset" parameter of the "Content-Type" header. The default in this case is ISO_8859_1.
      To match the write prefix of the methods on StringSink the add (for writing bytes) have been renamed to writeBytes and addStream has been renamed to writeStream.
    • StreamSink becomes EventSink, signalError becomes addError
    • num.floor(), .ceil(), .truncate(), .round() return integers now (even on doubles).
    • xMatching -> xWhere:
      Iterable.firstMatching -> Iterable.firstWhere
      Iterable.lastMatching -> Iterable.lastWhere
      Iterable.singleMatching -> Iterable.singleWhere
      Stream.firstMatching -> Stream.firstWhere
      Stream.lastMatching -> Stream.lastWhere
      Stream.singleMatching -> Stream.singleWhere
      Collection.removeMatching -> Collection.removeWhere
      Collection.retainMatching -> Collection.retainWhere
    • Timer.repeating -> Timer.periodic
    • Set.containsAll(Collection) -> Set.containsAll(Iterable)
    • Set.intersection(Collection) -> Set.intersection(Set)
    • Duration has a private variable now and its implicit interface cannot be implemented anymore without warnings.
  • Deprecations in corelib:
    • Set.isSubsetOf deprecated, to be removed.
    • List.getRange(start, length) deprecated, to be removed.
    • Iterable.min, Iterable.max, Stream.min, Stream.max deprecated, to be removed.
  • dart:html:
    • Rect has been renamed to CssRect, RgbColor has been renamed to CssRgbColor.
    • General-purpose Rect and Point classes have been added
    • APIs exposing ClientRect now expose Rect
    • Element.client* and Element.offset* properties have now become rects as well.The old syntax is currently deprecated.
      var top = Element.clientTop;
      var top =;
    • Input events are having their position properties change from clientX & clientY to a single Point field. The old syntax is currently deprecated.
      var x = mouseEvent.offsetX;
      var x = mouseEvent.offset.x;
    • CanvasRenderingContext.drawImage(canvas_OR_image_OR_video, num sx_OR_x, num sy_OR_y, [numsw_OR_width, num height_OR_sh, num dx, num dy, num dw, num dh]) has changed to two functions with more reasonable parameters:
      void drawImage(CanvasImageSource source, num destinationX, num destinationY) and
      void drawImageAtScale(CanvasImageSource source, Rect destinationRect, {Rect sourceRect})
      CanvasImageSource is one of ImageElement, VideoElement, or CanvasElement.
      The primary reason for this change is to make the method signature more understandable, while not reducing any functionality.
    • DirectoryEntry.getFile and DirectoryEntry.getDirectory have changed function signatures and added DirectoryEntry.createFile and DirectoryEntry.createDirectory methods.
    • The EventSource constructor, Notification constructor, and have different signatures -- in all of these cases the Map argument now uses optional named parameters instead.
    • Window.requestFileSystem and WorkerContext.requestFileSystem have a slightly different signature. By default the user only needs to specify the desired file system size, and we will request temporary storage. The user can specify that they want permanent storage by setting a named optional parameter to true.
  • dart:io
    • The event stream from a WebSocket is now a stream of the messages (of type List<int> or type String). The close event is now the onDone on the stream with the close code and close reason available as properties on the WebSocket object.
    • The IOSink interface now implements StringSink. This renames addString to write, add to writeBytes and addStream to writeStream.
  • pub
    • Support for SDK packages (depending on a package directly from the locally-installed SDK) has been removed. All SDK packages are and have been available from for months and almost all users should have moved over at this point so it shouldn’t affect many.

And as always,view the changelog for the full list of changes, and to get started with the Editor see our tutorial.

Thursday, March 14, 2013

Irrduino: A Sprinkler System Built Using Arduino, Android, Google App Engine, Python, and Dart

Developers frequently ask me if Dart is ready for the real world. Well, of course, that depends on the application. Check out this short video in which Joe Fernandez and I not only show that Dart can be used in the real world, we also show that it can be used to take the tedium out of watering your lawn!

The Dart code for Lawnville was originally written in January of 2012, a mere three months after Dart was launched as a "technology preview". That was six months before Dart's M1 release, so it's been updated a few times along the way. However, the code really hasn't fundamentally changed that much since the beginning.

Perhaps the most interesting piece of code is the use of a Queue (from the dart:collection library) to schedule watering tasks. You can click on different parts of the lawn, and the droid will fly over and water each section for a short amount of time:
  _actionQueue = new Queue();
  _actionQueue.add({'action': 'water', 'zone':});
  void _executeActionQueue() {
    if (_actionQueue.isEmpty) {
      _waitingForTimer = false;
    } else {
      var action = _actionQueue.removeFirst();
      _waitingForTimer = true;
      new Timer(new Duration(milliseconds: TIMER_INTERVAL),
A Timer and window.requestAnimationFrame are used to control animations:
  void _repositionDroid(int x, int y, [Callback callback = null]) {
    x -= (HALF * DROID_WIDTH).toInt();
    y -= DROID_HEIGHT;
    _droid.src = "/static/images/droid-jetpack-on-front.png"; = "${x}px"; = "${y}px";
    new Timer(new Duration(milliseconds: REPOSITION_DURATION), () {
      if (callback != null) {
      } else {
        _droid.src = "/static/images/droid-waiting-front.png";

  void _startAnimationLoop() {
    _animationStartTime = new;

  void _animationLoop(int timestamp) {
    _animationProgress = timestamp - _animationStartTime;
    for (Callback callback in _animationCallbacks.values) {
An HttpRequest is used to send commands to IrrduinoServer which in turn sends commands to IrrduinoController in order to control the sprinkler system:
  void _waterRpc(int zone) {
    var req = new HttpRequest();
    int secs = (TIMER_INTERVAL * SECS_PER_MS).toInt();"POST", "/?water-zone=true&zone=${zone}&secs=${secs}", true);
    req.onReadyStateChange.listen((Event e) {
      if (req.readyState == 4) {
        if (req.status == 200) {
          window.console.log("Watering was successful");
        } else {
          window.console.log("Watering was unsuccessful");
In total, the complete Dart code is about 110 lines long, not counting comments and closing braces.

You might wonder why I chose to use Dart so soon after its release, especially since I wasn't even on the Dart team at the time. I've always gotten a kick out of coding in new languages. At the time, I figured that as long as I could talk to the DOM and make XMLHttpRequests, I could do almost anything. These days, Dart is a lot more useful thanks to the growing selection of pub packages available, but even before these things existed, Dart had enough functionality to help water a lawn ;)

If you want to download the complete source code for Irrduino, you can get it from

Dart VM Uses More CPU Features for Faster Performance

The Dart VM, a new virtual machine that runs Dart code, can now take advantage of SIMD instruction sets found in common CPUs. This means that Dart apps, when running in the Dart VM, can perform significantly faster for some algorithms. Code written with the new SIMD APIs still compiles to JavaScript, but won't see the same speed boost.

Are you using all of the CPU?

SIMD stands for Single Instruction Multiple Data, and is a set of CPU instructions for computing multiple results in parallel. The Dart SIMD APIs allow you to add, subtract, multiply, and divide four numbers at the same time. SIMD is widely used in games, 3D graphics applications, and more.

John McCutchan, Developer Programs Engineer on Dart, recently landed the changes with help from the Dart VM team. Watch John's talk from SFHTML5, and learn about his background optimizing console games, his journey to the web, and his quest to help web apps use all the CPU. The slides are also available.

Tuesday, March 12, 2013

New Article on Futures and Error Handling in Dart

Read the latest article at and learn about handing errors and exceptions when working with Futures.

Have you wondered how to implement the asynchronous equivalent of a try-catch? Or how errors actually get propagated when working with Futures? Or how you can prevent synchronous errors from leaking out of asynchronous code?  Then this article is for you.  

The article focuses entirely on error handling when working with Futures, explains how to handle errors that are emitted asynchronously, and points out a few gotchas that you should watch out for.  

Your feedback really counts. Please join the conversation at the Dart mailing list, and ask questions at Stack Overflow.

Photo credit:

Tuesday, March 5, 2013

New Dart Editor Release WIth Substantial Performance Improvement

Dart Editor has a new build. Daniel Rubel fills us in on the details:

new Dart Editor build is available at include:
  • Fixed a notable Editor performance issue related to Pub and symlinks.
Breaking Change List:
  • Deprecated List.addLast. Use List.add instead.
  • dart:indexed_db - Remainder of APIs have been converted over to Futures (this was a continuation of work from the conversions done in M3).
*** Note that as a result this version does not include support for developing Chrome Applications. If you're using that feature, you should stick with the M3 release for now. ***

And as always, view the changelog for the full list of changes, and to get started with the Editor, see ourtutorial.

(Photo credit:

Monday, March 4, 2013

Notes from Feb 25th Language Meeting: Function Type Annotations, Optional Parameters and Exported Types

The invaluable Bob Nystrom fills us in on the language design discussions taking place amongst Dart engineers. Here are his notes from the February 25 language meeting:

Here's my notes from last week's meeting. I'll have this week's meeting notes out later this week:

function type annotations

Kasper noticed (or maybe someone noticed and brought it to his attention) that there is a place in Dart where seemingly innocuous type annotations do have a runtime effect. Given implicit closurization and is-checks with function types, you can:

1. Store a reference to a method in a variable.
2. Do an is check on that variable against some function type.

For that is check to perform correctly, it means we have to keep track of the methods type annotations at runtime.

The team discussed a bit about whether or not they want to make any changes around this, but didn't come to any conclusions.

optional parameters

We're entering a mode where changing the language gets increasingly hard. We should be careful.

Dan Grove said then if we're going to pull stuff out, we should do it soon. One thing people worry about is parameter syntax with optional parameters and forwarding.

Lars has some ideas for forwarding and will write up a proposal so we have something to discuss.

exported types

I asked if a library B exports Foo from library A and some library C imports both, are those Foos the same type?

I wasn't clear in my question, but after later verifying it myself, it seems Dart does do what I want here:

    // main.dart
    import 'foo.dart' as foo;
    import 'bar.dart' as bar;

    methodTakesFoo(foo.Baz baz) => print("ok");
    methodTakesBar(bar.Baz baz) => print("ok");

    main() {
      var fromFoo = new foo.Baz();
      var fromBar = new bar.Baz();
      print('foo.Baz is foo.Baz = ${fromFoo is foo.Baz}');
      print('foo.Baz is bar.Baz = ${fromFoo is bar.Baz}');
      print('bar.Baz is foo.Baz = ${fromBar is foo.Baz}');
      print('bar.Baz is bar.Baz = ${fromBar is bar.Baz}');
    // foo.dart
    library foo;
    class Baz {}

    // bar.dart
    library bar;
    export 'foo.dart'; 
 On both the VM (in checked mode) and dart2js, this prints four "true"s and four "ok"s.

And as always, view the changelog for the full list of changes, and to get started with the Editor, see our tutorial.

Bootstrap Widgets Ported to Web Components with Dart Web UI

The wildly successful Bootstrap project, which helps web developers build responsive designs for web apps, has been ported to Dart's Web UI library. This means the dynamic widgets like accordion, carousel, tabs, and more, are reborn as actual web components. The Dart Widgets library has all the code, and you can easily install it from pub.

With real encapsulation, you can now use custom components that contain the structure, style, and behavior of the widget. For example, instead of using div elements with special classes and requiring another script to make it all work, you can simply use <x-accordion> which contains everything you need.

Here is an example:

    <div class="accordion-heading">
      <a class="accordion-toggle" data-toggle="collapse">Item 1</a>
    <p>Item 1 content - Lorem ipsum</p>
    <div class="accordion-heading">
      <a class="accordion-toggle" data-toggle="collapse">Item 2</a>
    <p>Item 2 content - Ut enim ad minim </p>

Thanks to Kevin Moore for open sourcing this project. Get started building declarative modern apps with Widgets and Web UI today!

Friday, March 1, 2013

New Dart Editor Build With More Libraries Moving To Using Streams and Futures

Dart Editor has a new build. Eric Clayberg 
fills us in on the details:

A new Dart Editor build is available at include:
  • Cleanup for => onClick.listen changes.
  • New application wizards updated for library changes.
  • Bug fix for debugging Dartium launches on Windows machines using IPv6.
Breaking Change List:
  • dart2js: temporarily remove --disable-unsafe-eval ***
  • dart:html
    • Web SQL APIs have moved into dart:web_sql, Database was renamed to SqlDatabase
    • Geolocation API has been cleaned up w/ futures & streams.
  • dart:io
    • Version 2 of the dart:io library moving to using streams and futures extensively for all async operations instead for registration of callbacks.
  • libraries:
    • BiDirectionalIterator -> BidirectionalIterator
*** Note that as a result this version does not support for developing Chrome Applications. If you're using that feature, you should stick with the M3 release for now. ***

And as always,view the changelog for the full list of changes, and to get started with the Editor see our tutorial.