Sunday, March 25, 2012

4 new changes to the Dart language spec

The Dart team published version 0.08 of the Dart language spec, including 15 changes. I've detailed four of the most exciting changes below, some of which you might have seen as early proposals. Not all of these changes are implemented yet, but they show what direction the language and team is moving.

Lazily Initialization for static variables

This change was proposed in February 2012.

Previously, static class variables and top level variables had to be compile time constants. This kept initialization costs at startup low, but otherwise was constraining to the developer. With this change, static class variables and top level variables will be initialized at first access (lazily) and no longer need to constant. This is a developer friendly change that keeps initialization costs low.

Version 0.08 of the spec now reads "Static variable declarations are initialized lazily. The first time a static variable v is read, it is set to the result of evaluating its initializer."

For example, this will soon be possible:

class Awesome {
  static PonyPower ponyPower = new PonyPower();
}


class PonyPower {
  // NOT a const constructor
  PonyPower() {
    // feed and groom pony
  }


  activate() {
    // summon rainbow
  }
}


main() {
  var power = Awesome.ponyPower; // initializes ponyPower now
  power.activate();
}

This feature is not yet implemented (as of 2012-03-25).

New equality semantics

This change was proposed in January 2012, and with version 0.08 of the spec, it finally gets added to the language.

In my opinion, equality in Dart just got a lot more simple. With the new changes, equality of the form a == b works like this:
  1. If a === b (is same instance), return true. Otherwise,
  2. If either a or b is null, return false. Otherwise,
  3. return the result of a.equals(b)
You are free to implement .equals() in your class to further define equality semantics. The rules imply you no longer need to check for === or null in your .equals() method.

This feature is not yet implemented (as of 2012-03-25).

Cascaded method invocations

This change was proposed in February 2012. Also, this particular feature should be considered less stable than the others.

Cascades allow you to chain numerous method calls to the same object, even if the API wasn't originally designed for that.

For example, consider the case of using the HTML5 Canvas API. Before the cascade feature, you would have to write the following code:

ctx.beginPath();
ctx.fillStyle = penColor;
ctx.arc(tx, ty, penWidth/2+2, 0, PI2, true);
ctx.fill();
ctx.moveTo(wx, wy);
ctx.strokeStyle = "black";
ctx.lineTo(tx, ty);
ctx.closePath();
ctx.stroke();

With cascades, this gets simplified and less redundant with:

ctx
..beginPath()
..fillStyle = penColor
..arc(tx, ty, penWidth/2+2, 0, PI2, true)
..fill()
..moveTo(wx, wy)
..strokeStyle = "black"
..lineTo(tx, ty)
..closePath()
..stroke();

The treatment for a cascade, which is object..method, is essentially like writing:

(x){x.method; return x;}(object)

In other words, "create a function, pass in some object x,  call the method on x, and return x".

Note that array and map calls also work with cascades, as a cascade can work with any method, operator, setter, or getter.

This feature is not yet implemented (as of 2012-03-25).

Removal of String + concatenation

This change we've been warning about for a while.

Having + to concatenate Strings leads to puzzlers, and we're taking advantage of building a new language by taking this opportunity to remove some of the subtle "features" that have lead to known puzzlers in the past.

Before you cry out in angst, allow me to show you how to deal with Strings, including a new feature that came in to compensate for removing +.

Remember that Dart has String interpolation, which can lead to code like this:

var name = 'Bob';
var msg = 'Hello, $name.';

Also, Dart has multi-line Strings thanks to triple quotes:

var html = """
<tr>
  <td>Snake Eyes</td>
  <td>Storm Shadow</td>
  <td>Firefly</td>
</tr>""";

For the hat trick, Dart now also has adjacent String literals:

var reallyLongLine = 'Sometimes you just need to work with really long lines '
                     'and a triple quotes multi-line string will not work. Luckily '
                     'Dart will automatically concatenate adjacent string literals '
                     'just like thing!';

Both the Dart VM and the Dart to JavaScript compiler already support adjacent string literals, so we encourage you to remove all uses of + for string concatenation, as + on String will be removed soon.

Summary

There are other changes to the Dart language spec with version 0.08, so I encourage you to browse the change log in the spec itself.

In this post, I covered lazy initialization for statics, new equality semantics, cascaded method invocations, and removal of the + operator for string concatenation.

As always, the Dart team wants you to join the discussion. Please join the mailing list or enter feature requests and bug reports to dartbug.com. A good way to get early notification of some language changes is to follow the Dart News and Updates feed.

Tuesday, March 20, 2012

Dart templates now allow nesting

UPDATE: Work on this library has stopped. You probably want to see Web UI, the fully supported modern client-side library for dynamic, data-driven web apps.

Just a few days after we see the first hints at a Dart template library, new features and fixes have landed to make Dart templates even more useful. This is Part 2 of our exploration of Dart templates, read Part One for an introduction to Dart templates.

Included in this new commit are:
  • fixed bug with whitespace being removed from text nodes
  • added local names for #with and #each
  • added ability to call another template from within a template
Let's take these new features for a spin.

Local names

Using local names, we can loop through a simple List of Strings.  For example, given the following simple script:

#import('dart:html');
#source('hello.dart');

main() {
  List fruits = ['apples', 'oranges', 'bananas'];
  Hello hello = new Hello("Bob", fruits);
  hello.p.on.click.add((e) => print('clicked on paragraph!'));
  document.body.elements.add(hello.root);
}

Here's the template the goes along with the above code:

template Hello(String to, List fruits) {
  <div var=hello>
    <p var=p>${to}</p>
    <p>My favorite fruits are:</p>
    <ul>
      ${#each fruits fruit}
      <li>${fruit}</li>
      ${/each}
    </ul>
  </div>
}

The new syntax for #each is now #each collection [item] where item is an optional name for the current item. This allows, among other things, iteration over simple Dart collections.

Calling other templates

Another new feature allows for calling a template from another template. Here's an example of a single .tmpl file containing two templates, with the first calling the second.

template Hello(String to, List fruits) {
  <div var=hello>
    <p var=p>${to}</p>
    <p>My favorite fruits are:</p>
    ${#Fruit(fruits)}
  </div>
}

template Fruit(List fruits) {
  <ul>
    ${#each fruits fruit}
    <li>I do love eating a fresh, ripe ${fruit}</li>
    ${/each}
  </ul>
}

I think there are still a few kinks to work out here, but nice to see some composability with templates.

Next up

More CSS features to support name mangling is on the TODO list. What else do you want to see from Dart's template library?

Summary

Dart's template library is optimized for rich client web apps. Given a file containing HTML snippets, the Dart template library will generate Dart classes that programmatically generate the HTML elements.

Friday, March 16, 2012

JSONP with Dart

A few people have asked how to handle JSONP in Dart. Turns out, this is basically possible, and I'd appreciate feedback on this technique.

JSONP is a trick to get around the lack of CORS headers in your favorite API. CORS is the modern way to get around the single origin policy, however even Google still doesn't support CORS on many of their APIs. The web developer community has come up with JSONP as a hack until all browsers and all APIs support CORS.

Option 1: If you always deploy to JavaScript

This method only works if you are always deploying to JavaScript and are not deploying or testing on Dartium (Chromium with an embedded Dart VM). Also, this feels hacky.

Add the JSONP callback to your main page as a small JavaScript method.

<script type="text/javascript">
function callbackForJsonpApi(data) {
  dartCallback(JSON.stringify(data));
}
</script>

This simple method converts the data from the server into a big JSON string. It passes this string to dartCallback, which happens to come from the JavaScript generated by your Dart program.

Your Dart code should look like this:

#import('dart:html');
#import('dart:json');

dartCallback(String data) {
  var obj = JSON.parse(data);
  print(obj['responseData']);
}

void main() {
  // this pulls in the function to ensure
  // it's compiled into the resulting JavaScript
  var f = dartCallback;
  
  Element script = new Element.tag("script");
  script.src = "https://ajax.googleapis.com/ajax/services/search/news?v=1.0&q=barack%20obama&callback=callbackForJsonpApi";
  document.body.elements.add(script);
}

This tricky hack takes advantage of the fact that the Dart top level functions are translated to JavaScript functions with the same names.

Pros: Simple to understand.
Cons: Doesn't work in Dartium, may not work in the future (if the JavaScript compiler starts to munge names).

Option 2: If you deploy to Dartium and JavaScript

Dartium is Chromium with an embedded Dart VM. Dartium is able to run native Dart code, without any compilation to JavaScript. If you are developing and testing on Dartium (as many of us do), you will need another option for emulating JSONP.

First, add this small snippet of JavaScript to your main page.

<script type="text/javascript">
function callbackForJsonpApi(s) {
  window.postMessage(JSON.stringify(s), '*');
}
</script>

Notice the use of postMessage() to communicate the JSON string data. Using postMessage is how you can send data between the JavaScript world and the Dart world in Dartium.

#import('dart:html');
#import('dart:json');

dataReceived(MessageEvent e) {
  var data = JSON.parse(e.data);
  print(data['responseData']);
}

void main() {
  // listen for the postMessage from the main page
  window.on.message.add(dataReceived);
  
  Element script = new Element.tag("script");
  script.src = "https://ajax.googleapis.com/ajax/services/search/news?v=1.0&q=barack%20obama&callback=callbackForJsonpApi";
  document.body.elements.add(script);
}

The Dart app listens for messages and delegates to dataReceived. Once parsed from the JSON string into an object of Maps and Lists, the Dart program can now operate on the data sent from the JSONP service.

Pros: This option works in both Dartium and when compiled to JavaScript.
Cons: More complicated, possibly slower due to sending large strings over postMessage.

Summary

Accessing a web service that uses JSONP with Dart is possible. For maximum compatibility, use postMessage to communicate between the JavaScript callback and the Dart application.

Please add your comments about this technique, and let us know which JSONP services are you mashing up with Dart.

Thanks for trying Dart!


First look at Dart's HTML template library

UPDATE: Work on this library has stopped. You probably want to see Web UI, the fully supported modern client-side library for dynamic, data-driven web apps.

Note: this is very very early access stuff. Feedback most welcome!

Dart is built to help developers build modern web apps. With today's commit of an HTML template library, that job just got a little bit easier. I take a first look at this new (and still evolving) template library to see what it does and how it works.

This week has been full of great stuff in the Dart community. Just a sample: Lars Bak and Kasper Lund join the JavaScript Jabber podcast, support for adjacent string literals lands in the Dart Editor, and the article I co-authored titled What is Dart? was published by O'Reilly. With this new template library, it looks like there is no slowing down.

Intro

Modern web apps process data and generate display content on the client. The days of full page refreshes and expensive server round trips are gone. Modern web app frameworks usually ship with some sort of template option, to ease the burden of constructing lengthy DOM. Whether you use a template system or construct the DOM programmatically with Views, it's much better to not have to ask the server for HTML.

The Dart engineers have just checked in a preview of their template system, specifically targeting HTML applications. It converts blocks of HTML text, sprinkled with interpreted directives, into Dart classes ready to generate DOM nodes for insertion into your app.

Getting started

This project is not yet part of the SDK, so you'll need to sync to the bleeding_edge branch from the Dart source repository, as of 2012-03-15. Look inside util/tests/template and util/template for the examples, tests, libraries and binaries.

Hello, templates

Here's what a simple template file looks like:

template Hello(String to) {
  <div>${to}</div>
}

Note this is not "Dart code" and does not live in a .dart file. Instead this is a Dart template, and lives in a .tmpl file.

The template is compiled into a Dart class, to be used by your program. The name of the template, in this case Hello, becomes the name of the class. The arguments to the template, in this case String to, become the constructor arguments.

Compile the template into a Dart class with the following command. It assumes you have the Dart VM on your PATH.

$DART_REPO/dart/util/template hello.tmpl

This will generate a hello.dart file containing a Hello class. We'll look inside the hello.dart file in a moment, for now let's keep going.

Next, you'll build your sample Dart script. We'll keep this very simple:

#import('dart:html');
#source('hello.dart'); // generated by the template engine

main() {
  Hello hello = new Hello("Bob"); // created from the template
  document.body.elements.add(hello.root);
}

Our sample script sources the hello.dart file, making it available to this script. We then construct a new instance of Hello and attach its root element to the document's body.

Next, compile your simple Dart script (assuming frogc, the Dart to JavaScript compiler, is on your PATH);

frogc test-hello.dart

Next, create a simple HTML file to host the script:

<!DOCTYPE html>
<html>
<head>
  <title>Template Test</title>
</head>
<body>
<script type="text/javascript" src="test-hello.dart.js"></script>
</body>
</html>

Loading the page and executing the script will use the template to populate the document's body:

<!DOCTYPE html>
<html>
<head>
  <title>Template Test</title>
<style></style></head>
<body>
<script type="text/javascript" src="test-hello.dart.js"></script>
<div id="hello">Bob</div>
</body>
</html>

Notice the new <div> in the page!  Cool!

The Hello class walkthrough

The template itself is compiled into a class. Let's look at that class by breaking it down.

First we see a handy utility method to strip strings of XSS vulnerabilities. Or, at least we find the placeholder to do that. :) Glad to see the templates taking XSS seriously. I also like to see Dart code that uses top level functions,  for not everything in Dart needs to be a class.

String safeHTML(String html) {
  // TODO(terry): Escaping for XSS vulnerabilities TBD.
  return html;
}

Next up is the actual Hello class. Instead of breaking up the class, I added comments for inline commentary.

class Hello {
  // SETH: this is what your template hangs off of.
  // SETH: This never touches the DOM.
  Element _fragment;

  String to;

  // SETH: this name comes from the template
  Hello(this.to) {
    // SETH: templates can inject stylesheets. Example to follow.
    // Insure stylesheet for template exist in the document.
    add_hello_templatesStyles();

    _fragment = new Element.tag('div');

    // SETH: here's the template! Notice the string interpolation
    var e0 = new Element.html('<div>${inject_0()}</div>');
    _fragment.elements.add(e0);
  }

  // SETH: how to access the nodes from the template.
  // SETH: Still not attached to DOM.
  Element get root() => _fragment.nodes.first;

  // Injection functions:
  String inject_0() {
    return safeHTML('${to}');
  }

  // Each functions:

  // With functions:

  // SETH: our template didn't define any CSS, so this is empty
  // CSS for this template.
  static final String stylesheet = "";
}

Accessing specific HTML elements

The template system is more expressive than our simple example shows.

You can bind individual elements to variables for easy access by your Dart code. Any HTML tag with a var attribute will be directly accessible by a variable on the template class.

For example:

template Hello(String to) {
  <div var=hello>
    <p var=p>${to}</p>
  </div>
}

Compiling the above template will generate the following output:

class Hello {
  Element _fragment;

  String to;

  // Elements bound to a variable:
  var hello;
  var p;

  Hello(this.to) {
    // Insure stylesheet for template exist in the document.
    add_hello_templatesStyles();

    _fragment = new Element.tag('div');
    hello = new Element.html('<div></div>');
    _fragment.elements.add(hello);
    p = new Element.html('<p>${inject_0()}</p>');
    hello.elements.add(p);
  }

Which means you can now access these elements directly in your script:

main() {
  Hello hello = new Hello("Bob");
  hello.p.on.click.add((e) => print('clicked on paragraph!'));
  document.body.elements.add(hello.root);
}

Loops

You can loop over a collection, but there doesn't seem to be a way to print the value from a simple list of Strings or numbers (this is a known bug, it's on the short short list). For now, you can loop over objects with fields and print the fields, though:

template Applications(var products) {
  <div>
    ${#each products}
      <div>
        <span>${name}</span> <!-- similar to product.name -->
        <span>-</span>
        <span>${users}</span>
      </div>
    ${/each}
  </div>
}

Summary

The Dart templates library is brand new, and should be considered technology preview just like anything else in the Dart project.

The template library is specialized for constructing HTML sub trees for inclusion in your client side web app. Your template files, which include HTML tags and text, are compiled into Dart classes which construct DOM elements.

Please give it a shot and let us know what you think by joining the mailing list or file a bug or feature request.

Tuesday, March 13, 2012

Concatenating string literals without the + operator in Dart

As you might recall, Dart is removing support for concatenating strings with the + operator. In its place, the team has added support for "adjacent string literals". This new functionality is now available in Dart VM, Frog, and the Editor.

It turns out that puzzles arise from the using + to concatenate strings, so the Dart team felt compelled to take a fresh approach. Dart already had string interpolation, which allows you to embed a string within a string:

// String interpolation in Dart
String to = 'Bob';
String msg = "Hello $to";  // Hello Bob

Dart also has multi-line Strings, using triple quotes:

String htmlTemplate = """
<div>
  <p>
    Hello $to.
  </p>
</div>""";

Sometimes, however, you need to deal with very long strings. You used to use the + operator to concat long strings, but the new way is to use adjacent string literals.

// Old 'n busted way to concat long strings in Dart
String longMessage = 'This is what you used to do in Dart. ' +
                     'You would use the + operator ' +
                     'to concat strings. Just like we are ' +
                     'doing here, in fact.';


// The new hotness
String longMessage = 'This is what you used to do in Dart. '
                     'You would use the + operator '
                     'to concat strings. Just like we are '
                     'doing here, in fact.';

Summary

The recommendation is to stop using + to concatenate strings and begin to refactor the old code to use adjacent string literals and string interpolation.

As always, the Dart team is very interested in your comments, please join the mailing list to share your experiences.

Friday, March 9, 2012

Using Futures in Dart for Better Async Code

Dart bundles lots of functionality into its standard libraries, helping developers avoid reinventing the wheel from project to project. One of those wheels is a better way to handle asynchronous callback driven programs. Thanks to the Future interface, potentially hard to follow callback code can be replaced with a more structured design.

(This is part 13 of an ongoing series about Dart.)

Intro

Let's pretend I have a set of potentially expensive methods that should be executed in order. Ideally, I should be able to write code like:

// Yikes! This will lock the page by running too
// many long processes in the main UI thread.
button.on.click.add((e) {
  costlyQuery();
  expensiveWork();
  lengthyComputation();
  print("done!");
});

Unfortunately, code like the above locks the main thread, freezing the application. Bummer.

Using callbacks is a typical way to make my UI responsive and keep expensive processes off the main thread. So I refactor the code into:

 button.on.click.add((e) {
   costlyQuery(() {
     expensiveWork(() {
       lengthyComputation(() {
         print("done!");
       });
     });
   });
 });

The method signatures now look like:

void costlyQuery(onComplete());
void expensiveWork(onComplete());
void lengthyComputation(onComplete());

With all the nesting, though, things get a little confusing, and doesn't scale with a big algorithm. Imagine nesting these callbacks to 5 or 6 levels. Yikes.

Future is the future

The Future interface is designed to help design code that is more linear in appearance, without sacrificing the benefits of asynchronous behavior.

A Future represents a value that will be provided sometime in the future. The Future is a token that your method can return immediately, before the method performs its expensive calculations. Once the expensive work is done, the value can be given to the Future, thus notifying the consumer that the work is done.

Generally, the workflow when using a Future looks like:

  1. Enter the method.
  2. Construct a Future.
  3. Start the expensive work in some callback or isolate.
  4. Return the Future (before the expensive work is finished).
  5. ... expensive work continues ...
  6. Expensive work is finished, gives resulting value to Future.
  7. The consumer of the Future is notified the value is present.
Refactoring to use a Future, the method signature becomes:

// return a Future immediately, then get to work
Future expensiveWork();

When using Futures, it's often very helpful to also use a Completer. The Completer makes it easy to create and signal when a Future is complete. The implementation of expensiveWork() would look like:

Future<Results> costlyQuery() {
  var completer = new Completer();

  database.query("SELECT * FROM giant_table", (results) {
    // when complete
    completer.complete(results);
  });

  // this returns essentially immediately,
  // before query is finished
  return completer.future; 
}

A client who calls costlyQuery() will immediately receive a Future in response. The client is notified when a value exists when the then() method is called on futureResults.

Future<Results> futureResults = costlyQuery();
futureResults.then((results) => renderTable(results));

Or, if you want to streamline the code:

costlyQuery().then((results) => renderTable(results));

I really like how the code reads. "Run a costly query, then, render the table."

Chaining futures

The real power of Futures comes in when you need to run multiple async methods in order, as our initial example illustrates.

Luckily, the Future interface provides a chain() method to make this easy. Assuming each of our expensive methods returns a Future, behold the glory:


 button.on.click.add((e) {
   costlyQuery()
   .chain((value) => expensiveWork())
   .chain((value) => lengthyComputation())
   .then((value) => print("done!"));
 });

Error handling

Futures pass along both values and exceptions. Here's the code for handling an exception and giving it to a Future.

  database.query("SELECT * FROM giant_table", (results) {
    // when complete
    completer.complete(results);
  }, (error) {
    completer.completeException(error);
  });

You can use any object to represent an exception, which is why we are simply passing the error to the Future as an exception.

Here's how to handle any exception from any of the chain() methods:

 button.on.click.add((e) {
   Future result = costlyQuery();
   result.handleException((exception) => print("DOH!"));

   result.chain((value) => expensiveWork())
         .chain((value) => lengthyComputation())
         .then((value) => print("done!"));
   
 });

(Note that an upcoming addition to the language, method chaining, will make this code a bit nicer.)

Parallel futures

The Futures interface helps with handling multiple Future objects, if the order in which they are run doesn't matter. For example, you can kick off many Future instances and wait for all of them to finish with this code:

costlyQuery() {
  return new Future.immediate("costly");
}

expensiveWork() {
  return new Future.immediate("expensive");
}

lengthyComputation() {
  return new Future.immediate("lengthy");
}

void main() {
  Futures.wait([
    costlyQuery(),
    expensiveWork(),
    lengthyComputation()
  ]).then((values) => print(values));
  
  // prints [costly, expensive, length]
}

Summary

Dart's Future interface represents a value that is provided sometime in the future. It can be returned immediately from a long running method, and it will signal the receiver when a value is ready.

Using a Completer to help manage a Future is a good idea. If you can run multiple Future objects in any order, consider using the Futures interface.

Next Steps

Read the previous Part 12 on Classes in DartRead more of my Dart poststry Dart in your browserbrowse the API docs, or file an issue request. Dart is getting ready, please send us your feedback!

Friday, March 2, 2012

Dart's warnings, errors, and checked and production modes


The Dart team talks about "checked" and "production" mode. Dart's systems can generate warnings and exceptions. I wanted to wrap my head about the two different modes and the two different kinds of feedback, so I wrote this post to gather my thoughts.

Dart uses both warnings and errors to signal detected problems. Dart detects problems both during static compilation (or analysis) and during dynamic execution.

Warnings and Errors

A warning does not halt execution. It seems obvious, but look for the word "warning". That tells you a potential problem has been detected. The program will still be compiled, and, if you're running the Dart VM, will be executed.

An error, on the other hand, throws an execution. If you do not catch the exception, it will halt your program.

Dart detects some type assignment problems during compilation time, if given enough information. For example, the following code uses static types:

num add(num x, num y) => x + y;
add("hello", "world"); // warning: strings aren't numbers

Compiling the above program will issue a warning, because the literal strings "hello" and "world" are not numbers, and the system had enough information to detect this for you.

If you don't give enough type information, the static analysis won't be able to issue type warnings. For example:

add(x, y) => x + y;
add("hello", "world");

The compiler doesn't know that x and y are numbers, so it can't issue a warning.

Remember, static analysis and compilation are different than execution. So far, we've been talking about steps that happen before execution. Give the system enough type information, and the static analysis and compilation steps will warn if you if something might go wrong.

Check and production modes

During execution, Dart programs run in two modes: "checked" mode and "production" mode. In checked mode, dynamic type assertions are turned ON. Given our code sample from above, which generates warnings yet still compiles:

num add(num x, num y) => x + y;
add("hello", "world");

In checked mode, (which you can turn on in the VM and Frog with --enable_type_checks), the type assertions will throw an exception because, dynamically, the types are checked and BOOM you can't pass a String where it expects a number.

In production mode, though, the program runs as if static types were omitted and dynamic type assertions are disabled. In production mode, the above sample will execute to completion, because at the moment you can concatenate two strings with + (WARNING: soon, string + concat will be removed, used only for illustrative purposes).

Why even have a production mode that ignores static types? A core tenet of Dart is that it compiles to JavaScript, which does not have static types. To keep performance high, the Dart program must have the same runtime semantics with or without static types.

Production mode is also useful because the VM needs to compile Dart code quickly. Performing static analysis in the VM at compile time is therefore not always an option and often not sufficient to replace runtime type checking. Runtime type-checking is expensive, especially in presence of type arguments (generics).

Summary

Dart programs EXECUTE in two modes: checked (with dynamic type assertions turned ON) and production (with dynamic type assertions turned OFF).  Dart programs COMPILE with some static analysis capabilities, and will issue WARNINGs if enough type information is given for it to detect potential problems. These warnings do not halt the process, the program will still begin executing.

Next Steps

Read more about optional typing and its implications in an article by Gilad Bracha, spec lead for Dart. Learn more about turning on checked mode in Dart VM and Frog.

Disclaimer

I'm probably required to say that the views expressed in this blog are my own, and do not necessarily reflect those of my employer. Also, except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License, and code samples are licensed under the BSD License.