tag:blogger.com,1999:blog-86015792660124556342024-03-13T21:04:23.692-07:00Seth Ladd's BlogProduct Manager @ Google, web engineer, author, conference organizer.Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comBlogger912125tag:blogger.com,1999:blog-8601579266012455634.post-67461775320622977212015-12-22T12:31:00.000-08:002015-12-22T12:40:44.829-08:00Add SSL to your personal websiteGive yourself a gift this holiday season, and add SSL to your personal site. The web is going secure, and it's time to be part of the solution. This article details how I turned on SSL + custom domains, plus automated deploys, for my <a href="https://sethladd.com/">personal site</a> for the cost of a domain (which I already had) and $5/year. Read on!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="186" src="http://2.bp.blogspot.com/-aMjWAuUbh9o/VnjJh5u7nlI/AAAAAAAB1_4/CcSO4GSNUL0/s400/Screen%2BShot%2B2015-12-21%2Bat%2B7.54.20%2BPM.png" width="400" /></div>
<br />
Turns out, it's easier (and more affordable!) than you think to add SSL to your website. But first, why bother? There are lots of reasons why you should care about adding SSL:<br />
<br />
<ul>
<li>Search engines are preferring SSL</li>
<li>New web APIs (like service worker) mandate SSL</li>
<li>Users trust SSL</li>
<li>Bonus: SSL can help enable HTTP/2 on some servers</li>
</ul>
<div>
Your setup will vary, so look for the easiest/shortest path to SSL for your particular site. Everyone has factors they want to optimize for. Here's what I was trying to optimize, as I looked for a solution.</div>
<div>
<br /></div>
<div>
I needed a solution that was:</div>
<div>
<ul>
<li>Affordable</li>
<ul>
<li>The solution should be very, very affordable. Affordable, in this context, means "as close to free as possible". My personal website is <i>extremely</i> low traffic. It doesn't make sense for me to pay a lot of money for something so small.</li>
</ul>
<li>Easy</li>
<ul>
<li>I don't have time to manage my personal site. The solution has to be simple and quick.</li>
</ul>
<li>Sustainable</li>
<ul>
<li>Because I don't have time to manage my site, I need a solution that is "set and forget" for as long as possible.</li>
</ul>
<li>GitHub friendly</li>
<ul>
<li>My site's source is on GitHub, and I needed a hosting+SSL solution that integrated with a "push to deploy" model.</li>
</ul>
<li>Static file friendly</li>
<ul>
<li>My personal site is extremely simple. I don't need anything other than a few static files.</li>
</ul>
<li>Works with Custom Domains</li>
<ul>
<li>I want to use my own domain.</li>
</ul>
</ul>
<div>
I looked at a lot of options. Here's what <i>didn't</i> work for me, for a variety of reasons. They may work for you.</div>
</div>
<div>
<br /></div>
<div>
<ul>
<li>Managing my own VPS (e.g. on Digital Ocean or EC2).</li>
<ul>
<li>This option completely rules out easy and sustainable. Manual configuration of servers, or keeping linux distros up to date, are two things I absolutely do not want to be doing.</li>
</ul>
<li>Google Cloud Storage</li>
<ul>
<li>GCS does serve static files, and even supports custom domains. However, they don't support custom domains <i>and</i> SSL. Bummer. It also doesn't support basic static file hosting feature like redirects, so it's probably not an option anyway.</li>
</ul>
<li>GitHub Pages</li>
<ul>
<li>Great integration with GitHub (of course :), but don't they don't support custom domains <i>and</i> SSL. They support custom domains, and SSL via the github.io domain, just not custom domains and SSL together at the same time.</li>
</ul>
<li>Amazon Web Services</li>
<ul>
<li>I'm not aware of an AWS product that meets my needs. Maybe they have some awesome static file server with custom domains and SSL and git integration? I didn't see one.</li>
</ul>
<li>Firebase Static Hosting</li>
<ul>
<li>This open is actually really good, and it was almost my solution. Their setup is very simple, they support custom domains and SSL, and they have decent GitHub integration (it requires just a little bit of scripting to deploy after a push). The only downside is that it costs $5/month for custom domains (but, the certificate is free and provided by Firebase). $60/year is a small price, especially considering the Firebase gives you an SSL certificate for free! Also, their static hosting is very good: they give you configuration options for redirects, custom 404 pages, and more. It's a very good option for most people. But, if $60/year is an issue (and it was hard for me to justify $60/year for a site that maybe serves 60 pages a year :), keep reading.</li>
<li>I should also note that it doesn't appear that Firebase supports IPv6 hosting. At least, their instructions didn't tell me to add IPv6 addresses to my DNS. This is probably a minor thing.</li>
</ul>
</ul>
<div>
The hosting option that <i>did</i> work for me, after a lot of searching and reading, was: Google App Engine.</div>
</div>
<div>
<br /></div>
<div>
Google App Engine has a few things that made it a winner for me:</div>
<div>
<ul>
<li>A completely free tier.</li>
<ul>
<li>My personal site is way, way, way under the free tier limits.</li>
</ul>
<li>Runs itself</li>
<ul>
<li>App Engine just keeps on trucking, especially for a simple static site.</li>
</ul>
<li>Custom domains</li>
<ul>
<li>No need to upgrade to a paid tier to get this feature.</li>
</ul>
<li>Custom certificates</li>
<ul>
<li>You need to upload your own certification, but you don't need to upgrade to a paid tier to get this feature.</li>
</ul>
<li>Fine for simple static sites</li>
<ul>
<li>For just a few pages, App Engine's configuration is decent. It's not as simple as Firebase's, but I don't anticipate needing redirects.</li>
</ul>
<li>Can be deployed from a push to GitHub</li>
<ul>
<li><a href="https://travis-ci.org/">Travis</a> to the rescue! The free Travis CI system can trigger a deploy to App Engine, when you push to GitHub.</li>
</ul>
<li>Support for "naked domains"</li>
<ul>
<li>App Engine can now serve http://example.com. For the longest time, they request a subdomain, but naked domains now work.</li>
</ul>
<li>Supports IPv6</li>
<ul>
<li>Because future.</li>
</ul>
</ul>
<div>
Google App Engine isn't perfect. If you want to do any redirects, you need to start writing Python. And it's not obvious how to setup App Engine for pure static hosting, nor is App Engine the simplest way to serve a static site (e.g. it's not good at recognizing optional trailing slashes in URL paths), but it can be done.</div>
<div>
<br /></div>
<div>
The next question was: where do I get an inexpensive SSL certificate? I looked around, and there are a lot of options and resellers. I purchased a three-year personal cert from https://ssls.com for a total of $15. That's 1/4 the price of one year of hosting with Firebase. The fact that I found a very affordable SSL cert is what really made App Engine a winner for me.</div>
</div>
<div>
<br /></div>
<div>
I assume you know about GitHub, how to get an App Engine account, and how to connect Travis to automate the builds. I know this looks like a lot of steps, but, remember, I'm doing three things here: custom domains, SSL, and automated deploys.</div>
<div>
<br /></div>
<div>
Here's a list of docs and some manual steps that helped me get my personal website setup for custom domain, SSL, and automated deploys from GitHub:</div>
<div>
<ul>
<li><a href="https://cloud.google.com/appengine/docs/python/console/using-custom-domains-and-ssl">Custom domains and SSL for App Engine</a></li>
<ul>
<li>Helps you link your domain to App Engine and walks you through generating the necessary files for the certificate.</li>
</ul>
<li><a href="https://www.ssls.com/">Affordable personal SSL certs from ssls.com</a></li>
<ul>
<li>I purchased a "PositiveSSL" cert with a three-year expiration.</li>
<li>Generate a CSR by running <i>openssl req -nodes -newkey rsa:2048 -keyout myserver.key -out server.csr</i> in a temp directory</li>
<ul>
<li>Tips for answering the questions: <a href="https://www.ssls.com/user/certificates/activate/4123421">https://www.ssls.com/user/certificates/activate/4123421</a></li>
</ul>
<li>Upload the CSR to your certificate vendor</li>
<li>You may need to perform additional verification steps. For example, I had to verify that I owned by domain by uploading a file to a special location on my server that serves my domain name.</li>
</ul>
<li>Generating a service account from the Google Cloud Console</li>
<ul>
<li>You can create a Service Account by going to the Google Cloud Console, go to “APIs & auth” -> “Credentials”, then click “Add Credential” and “Service Account”, finally clicking “JSON” to download the JSON key.</li>
</ul>
<li>Encrypting the JSON key</li>
<ul>
<li>Install the travis command-line utils: <i>sudo gem install travis -v 1.8.0 --no-rdoc --no-ri</i></li>
<li>run: <i>cd your_website_dir</i></li>
<li>run: <i>cp </i><i>path/to/downloaded/cloud/service_account.json .</i></li>
<li>run: <i>travis login --auto</i></li>
<li>run: <i>travis encrypt-file service_account.json --add</i></li>
<li>run: <i>rm service_account.json</i></li>
<ul>
<li>DO NOT check this file in! Only check in the encrypted version.</li>
</ul>
</ul>
<li><a href="https://github.com/sethladd/sethladd-site/blob/master/.travis.yml">My .travis.yml file</a> which kicks off the deploy script</li>
<ul>
<li>Grab this, and add it to your project (or, diff it with your existing .travis.yml file and add the relevant lines).</li>
</ul>
<li><a href="https://github.com/sethladd/sethladd-site/blob/master/travis.sh">My travis.sh script</a> which is the actual deploy script</li>
<ul>
<li>This has the logic to download the Google Cloud SDK, configuration authentication, and perform the actual deploy.</li>
</ul>
<li><a href="https://github.com/sethladd/sethladd-site/blob/master/app.yaml">My app.yaml</a> which configures my app for App Engine</li>
<ul>
<li>I had to remove some values, in order to work with the new gcloud command. For example, I had to remove the <i>application</i> and <i>version</i> keys from this file (they are set in travis.sh now, via gcloud).</li>
</ul>
<li>Turning on App Engine Admin API and Google Cloud Storage JSON API in the "API Manager" of the Google Cloud Console.</li>
<ul>
<li>None of the docs I found told me to do this. Took me a while to figure this part out!</li>
</ul>
</ul>
<div>
<br /></div>
</div>
<div>
If you don't mind spending $60/year for hosting with a custom domain and SSL, consider Firebase. It's significantly less steps.</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-51002987747005810812015-08-18T16:37:00.001-07:002015-08-18T18:04:49.250-07:00Dynamically load package contents with Dart's new Resource class<b>tldr:</b> In Dart 1.12, you can now dynamically load the contents of files/assets from package dependencies. The new Resource class is currently implemented in the VM, with dart2js support coming in a future release.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="480" src="http://2.bp.blogspot.com/-V4BCahYatsU/VdPBIvrnazI/AAAAAAABxCg/PZFJc5pglDk/s640/Untitled-1.png" width="640" /></div>
<br />
<br />
<span style="font-size: large;">Motivation</span><br />
<br />
Dart applications are rarely just a collection of .dart files from a single developer. Real-world Dart apps often include numerous package dependencies, which contain additional Dart libraries as well as assets such as images, configuration files, template files, and more. It's always been possible to import third-party libraries with Dart's package: URI scheme, however prior to Dart 1.12 it was not possible to access non-Dart files via package: URIs.<br />
<br />
For example, consider a tool such as <a href="http://stagehand.pub/">stagehand</a>, which generates new Dart projects such as web apps, server apps, pub packages, and more. The source of the new projects are stored as files and templates inside the stagehand package. Somehow, the stagehand tool needs to reference and load files from its packages. The contents of packages are addressable with package: URI scheme, but the Dart platform didn't provide a way to load those resources.<br />
<br />
<span style="font-size: large;">Hello, Resource!</span><br />
<br />
Enter the new <a href="https://api.dartlang.org/apidocs/channels/dev/dartdoc-viewer/dart:core.Resource">Resource class</a>, which first appeared in Dart 1.12. The Resource class performs a very special role: allow Dart code to, at runtime, identify and load a resource identified by a package: URI.<br />
<br />
Consider this simple package layout:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">resourcetest/</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pubspec.yaml</span><br />
<span style="font-family: Courier New, Courier, monospace;"> .packages</span><br />
<span style="font-family: Courier New, Courier, monospace;"> bin/</span><br />
<span style="font-family: Courier New, Courier, monospace;"> main.dart</span><br />
<span style="font-family: Courier New, Courier, monospace;"> lib/</span><br />
<span style="font-family: Courier New, Courier, monospace;"> myresource.txt</span><br />
<br />
Here are the contents of main.dart:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">main() async {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> var myResource = new Resource('package:resourcetest/myresource.txt');</span><br />
<span style="font-family: Courier New, Courier, monospace;"> var resourceContents = await myResource.readAsString();</span><br />
<span style="font-family: Courier New, Courier, monospace;"> print(resourceContents);</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<br />
First, construct a new Resource with a package: URI. Of course, the Resource will only be able to load package: URIs from your application/script and dependencies declared in your pubspec.yaml file.<br />
<br />
Then, call readAsString(), which returns a Future containing the contents of the resource.<br />
<br />
That's it!<br />
<br />
<span style="font-size: large;">The Resource API</span><br />
<br />
There are a few ways to load the contents of a Resource instance.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">openRead() → Stream<List<int>></span><br />
<br />
Read the resource content as a stream of bytes.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">readAsBytes() → Future<List<int>></span><br />
<br />
Read the resource content.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">readAsString({Encoding encoding}) → Future<String></span><br />
<br />
Read the resource content as a string.<br />
<br />
Technically, the Resource class can load any URI that it already knows how to load. For example, the Dart VM can load file: , http: , and package: URIs.<br />
<br />
<span style="font-size: large;">Things to consider</span><br />
<br />
As of Dart 1.12, only the Dart VM has implemented the Resource class. Support is planned for dart2js in a near-future release.<br />
<br />
The Resource class only works if your application is started with a valid way to resolve package: URIs. The Dart platform supports multiple ways to tell the runtimes and compilers where and how to resolve package: URIs, and under most circumstances, you don't need to do anything special.<br />
<br />
One of the following must be true, in order for the Dart runtime to be able to resolve the package: URIs:<br />
<br />
<br />
<ul>
<li>run your Dart app after it was installed with pub global activate</li>
<li>run your Dart app with a --package=path/to/.packages</li>
<li>run your Dart app with a --package-root=path/to/packages/dir</li>
<li>run your Dart app's entry point next to the .packages file</li>
<li>run your Dart app's entry point next to the packages/ directory</li>
</ul>
<br />
<br />
Normally, everything is set up for you, because pub does a great job of ensuring your app has a .packages file. This is true even with apps installed with pub global activate!<br />
<br />
<span style="font-size: large;">Summary</span><br />
<br />
The new Resource class allows you to dynamically load the contents of package: URIs. You can use the new Resource class to load text or binary assets from within your app and your third-party dependencies.<br />
<br />
<a href="https://www.dartlang.org/downloads/archive/">Download a Dart 1.12-dev SDK</a> and enjoy the new Resource class. We look forward to your <a href="http://dartbug.com/">feedback</a>, and we can't wait to see what you build.<br />
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-56744997191300679052015-08-11T09:47:00.000-07:002015-08-24T09:41:40.107-07:00New Dart SDK helps eliminates symlinks<i>In which we retell the story of Dart and symlinks, investigate the new .packages file, and create a simpler world for Dart developers everywhere.</i><br />
<div>
<br /></div>
tldr: The Dart team is working towards a world where symlinks are no longer required because of the new .packages file.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="424" src="http://2.bp.blogspot.com/-9IJVyBlXuDE/Vcoqoz2TmlI/AAAAAAABwyU/nfbEvx9MdgQ/s640/Untitled-1.png" width="640" /></div>
<br />
<h2>
Why a new solution for locating packages?</h2>
In the long long ago, during the before times (aka 2011), <a href="https://www.dartlang.org/">Dart</a> could only run monolithic scripts and apps. In those early days, Dart didn't have support for packages/shared libraries. Then came <i>package:</i> URIs, which opened the door for sharing code. However, the platform only had one way to resolve that package: URI: look inside a packages/ directory next to the file importing the library. (Later, a --package-root option was added for more flexibility.) Thus began Dart's reliance on <i>symlinks</i> as a way of creating the packages/ directories next to all locations containing Dart scripts or libraries. Those symlinks and the package: scheme helped ushered in a boom of third-party libraries, the pub package manager, <a href="http://pub.dartlang.org/">pub.dartlang.org</a>, and more.<br />
<br />
However, turns out that a reliance on symlinks leads to numerous issues, especially for our Windows developers. Putting symlinks into each subdirectory makes for a cluttered project. A directory full of symlinks only works on your local machine. The Windows operating system doesn't support symlinks (though, through some research, the pub authors did come up with a solution for modern Windows installs with something calls <i>junction points</i>). It became clear that the Dart platform needed a more robust and formal way to connect your script to your dependencies and third-party libraries.<br />
<br />
The search began for a solution, and <a href="https://github.com/dart-lang/dart_enhancement_proposals/issues/5">DEP5</a> (formally known as package spec) was born. The proposal specifies a new <i>.packages</i> file and a discovery workflow, and eliminates the need for symlinks everywhere. I am very happy to report that Dart SDK 1.12 will be the first version of Dart that doesn't require symlinks.<br />
<h2>
What is .packages?</h2>
The new .packages file is a simple map between a package name and a URI to the package's lib directory. Here is an example:<br />
<br />
<pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6000003814697px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;"># This file has been generated by the Dart tool pub on Apr 14 09:14:14 2015.
# It contains a map from Dart package names to Dart package locations.
# Dart tools, including Dart VM and and Dart analyzer, rely on the content.
# AUTO GENERATED - DO NOT EDIT
unittest:/home/somebody/.pub/cache/unittest-0.9.9/lib/
async:/home/somebody/.pub/cache/async-1.1.0/lib/
quiver:/home/somebody/.pub/cache/quiver-1.2.1/lib/</code></pre>
<br />
The .packages file is auto-generated by pub, version 1.12-dev or greater.<br />
<h2>
Where does .packages live?</h2>
The .packages usually lives at the root of your package/app. For example:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">my_app/</span><br />
<span style="font-family: Courier New, Courier, monospace;"> README.md</span><br />
<span style="font-family: Courier New, Courier, monospace;"> CHANGELOG.md</span><br />
<span style="font-family: Courier New, Courier, monospace;"> .packages</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pubspec.yaml</span><br />
<span style="font-family: Courier New, Courier, monospace;"> lib/</span><br />
<span style="font-family: Courier New, Courier, monospace;"> my_lib.dart</span><br />
<span style="font-family: Courier New, Courier, monospace;"> bin/</span><br />
<span style="font-family: Courier New, Courier, monospace;"> my_app.dart</span><br />
<br />
The Dart runtimes, such as the VM, dartjs, and analyzer, will traverse up directories, from the entry point script, to find a .packages. Thus, you do not need a .packages next to each script that you need to run or compile.<br />
<h2>
Do I check in .packages?</h2>
Do not check in .packages, because it contains paths that are local to your system. You can safely tell your source control system to ignore this file.<br />
<h2>
How do I use the file?</h2>
Under normal circumstances, you do not need to do anything special to use the file. pub creates the .packages file automatically.<br />
<br />
The Analysis Server also uses .packages, so IDE/editor users (e.g. Atom, WebStorm, etc) should be able to work in a project without symlinks.<br />
<br />
You can optionally specify a .packages as a command-line argument. For example:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">dart --packages=path/to/a/.packages main.dart</span><br />
<h2>
Do I still need a packages/ directory in my project?</h2>
No. With .packages, there is no longer a need for symlinks or a packages/ directory in your project. Check out the next question for how to get to this beautiful new world.<br />
<h2>
Great! So, how can I eliminate symlinks?</h2>
You can use a hidden <span style="font-family: Courier New, Courier, monospace;">--no-package-symlinks</span> command-line argument to instruct pub <i>not</i> to generate symlinks. For example:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">pub get --no-package-symlinks</span><br />
<br />
The above command will generate a .packages file in the root of your project, and will not generate any symlinks or packages/ directories.<br />
<h2>
Caveats</h2>
If you use WebStorm or IntelliJ, you may need to upgrade to WebStorm 11 EAP or the latest IntelliJ EAP to correctly work with .packages and no symlinks. The <a href="https://youtrack.jetbrains.com/issue/WEB-16466">Dart plugin for JetBrains did add support for .packages</a>, but it might not work with WebStorm 10. If you can't upgrade, do not run pub with --no-package-symlinks.<br />
<h2>
Next steps</h2>
Please <a href="https://www.dartlang.org/downloads/archive/">install a 1.12-dev or later of the Dart SDK</a> and test your code with the new .packages file. We eagerly await your <a href="http://dartbug.com/">feedback</a>, especially from developers using Windows. You can also follow the <a href="https://github.com/dart-lang/sdk/issues/23372">meta-issue</a> as we complete our implementation. Thanks!Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-49564218200300350142015-07-08T17:15:00.000-07:002015-08-13T12:04:00.797-07:00Null-aware operators in DartThree new language features just landed in the latest dev channel build of the <a href="https://www.dartlang.org/">Dart</a>! Collectively known as <i>null-aware operators</i>, these new features will help you reduce the code required to work with potentially null objects.<br />
<br />
I'm excited for these new abilities, because typing less is always a good thing. Read on to learn more, and be sure to try these new features on <a href="https://dartpad.dartlang.org/">Dart Pad</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-aJDSY_Ph4Go/VZ2-iOy8eHI/AAAAAAABvn4/__J0db_cync/s1600/Screen%2BShot%2B2015-07-08%2Bat%2B5.21.15%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-aJDSY_Ph4Go/VZ2-iOy8eHI/AAAAAAABvn4/__J0db_cync/s1600/Screen%2BShot%2B2015-07-08%2Bat%2B5.21.15%2BPM.png" /></a></div>
<h2>
??</h2>
Use ?? when you want to evaluate and return an expression IFF another expression resolves to null.<br />
<code></code><br />
<pre><code> exp ?? otherExp
</code></pre>
<br />
is similar to<br />
<code></code><br />
<pre><code> ((x) => x == null ? otherExp : x)(exp)
</code></pre>
<br />
<h2>
??=</h2>
Use ??= when you want to assign a value to an object IFF that object is null. Otherwise, return the object.<br />
<code></code><br />
<pre><code> obj ??= value
</code></pre>
<br />
is similar to
<br />
<code></code><br />
<pre><code> ((x) => x == null ? obj = value : x)(obj)
</code></pre>
<br />
<h2>
?.</h2>
Use ?. when you want to call a method/getter on an object IFF that object is <i>not</i> null (otherwise, return null).
<br />
<code></code><br />
<pre><code> obj?.method()
</code></pre>
<br />
is similar to
<br />
<code></code><br />
<pre><code> ((x) => x == null ? null : x.method())(obj)
</code></pre>
<br />
You can chain ?. calls, for example:
<br />
<code></code><br />
<pre><code> obj?.child?.child?.getter
</code></pre>
<br />
If obj, or child1, or child2 are null, the entire expression returns null. Otherwise, getter is called and returned.
<br />
<h2>
Try them today!</h2>
The easiest way to try null-aware operators is to use <a href="https://dartpad.dartlang.org/">Dart Pad</a>, our browser-based playground for Dart.<br />
<br />
Or, <a href="https://www.dartlang.org/downloads/archive/">download</a> a 1.12-dev (or later) build of the Dart SDK to try these new features in the Dart VM, dart2js, and the Dart analyzer.
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-90700742317740679602015-04-11T20:42:00.001-07:002015-04-11T20:42:20.275-07:00Formatting Dart code before every git commit<a href="https://www.dartlang.org/">Dart</a>'s dartfmt tool is a really neat utility to automatically format your code. Use the <a href="https://www.dartlang.org/tools/dartfmt/">dartfmt</a> tool in your workflow to ensure your code complies with the <a href="https://www.dartlang.org/articles/style-guide/">Dart style guide</a>.<br />
<br />
Of course, you don't want to manually run dartfmt. Instead, you want to automate it. Use git's pre-commit hook to ensure your code is formatted, before it is committed.<br />
<br />
Add the following code to your .<span style="font-family: Courier New, Courier, monospace;">git/hooks/pre-commit</span> script for your local repo, and make sure the script is executable.<br />
<br />
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">#!/bin/bash</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">DARTFMT_OUTPUT=`dartfmt -w . | grep Formatted`</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">if [ -n "$DARTFMT_OUTPUT" ]; then</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> echo $DARTFMT_OUTPUT</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> echo "Re-attempt commit."</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> exit 1</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">else</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> echo "All Dart files formatted correctly. Yay!"</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> exit 0</span></div>
<br />
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">fi</span></div>
<div class="p1">
<br /></div>
<div class="p1">
If your code needs formatting, it will be formatted and written to disk. The commit will fail, so you have a chance to inspect the changes.</div>
<div class="p1">
<br /></div>
<div class="p1">
You can enforce formatting with your Continuous Integration system. Try these <a href="http://work.j832.com/2015/04/enforce-formatting-for-your-dart.html">instructions to use dartfmt with Travis CI</a>, and fail a build if a file isn't formatted.</div>
<div class="p1">
<br /></div>
<div class="p1">
Have you integrated dartfmt into your workflow? Let us know in the comments below!</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-20414726690860405692014-05-09T07:27:00.003-07:002014-05-13T12:35:15.204-07:00I ported a JavaScript app to Dart. Here's what I learned.<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In which I port a snazzy little JavaScript audio web app to <a href="https://www.dartlang.org/">Dart</a>, discover a bug, and high-five type annotations. Here's what I learned.</span><br />
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span>
<span style="background-color: transparent; color: black; font-size: 15px; font-variant: normal; font-weight: normal; text-decoration-line: none; vertical-align: baseline; white-space: pre-wrap;"><i>[As it says in the header of this blog, I'm a seasoned Dart developer. However, I certainly don't write Dart every day (I wish!). Don't interpret this post as "Hi, I'm new to Dart". Instead, interpret this post as "I'm applying what I've been documenting."]</i></span></span><br />
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span>
<span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">This post analyzes two versions of the same app, both the original (JavaScript) version and the Dart version. The original version is a proxy for any small JavaScript app, there's nothing particularly special about the original version, which is why it made for a good example.</span></span><br />
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span>
<span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">This post discusses the differences between the two implementations: file organization, dependencies and modules, shims, classes, type annotations, event handling, calling multiple methods, asynchronous programming, animation, and interop with JavaScript libraries. Finally, I detail the lessons learned.</span></span></div>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Background</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Mr. Paul Lewis wrote a snazzy little web app for audio processing. His </span><a href="https://github.com/paullewis/music-dna" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Music DNA</span></a><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> app uses JavaScript to load up an audio file, play it, and visualize the sounds in a browser. It’s a cool little demo of what’s possible on the web platform.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><img alt="Screen Shot 2014-04-25 at 4.10.53 PM.png" height="268px;" src="https://lh6.googleusercontent.com/6MnP2DLt3dyFck972viNURWBzT8q2oJhcScJff2Dj5c2Vc5qeKLBuoZWDdTp0i7nJDda-cbGzXj0es5XJfYA2HR9VskdKX3FwWhqBwUpzw5UIrKWSKqVoLfjVgQXKm6_tw" style="-webkit-transform: rotate(0rad); border: none;" width="300px;" /></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">I’m always impressed with Paul’s designs and code, so I asked myself: Could I easily port this app to Dart? Was Dart up to the challenge of a web audio app? Is there benefit to using Dart for little apps like this?</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Spoiler: yes, yes (mostly), and yes. Read on!</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Fine print</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">I ported the original JavaScript version of Music DNA app as of </span><a href="https://github.com/paullewis/music-dna/tree/5747c31c264032c8be21cfb5173f6945740554fc" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">this revision</span></a><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. The code for the </span><a href="https://github.com/sethladd/music_dna_dart" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></a><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> is also available. It’s possible that by the time you read this, the original JavaScript version will have changed. I also attempted to minimize the differences between the two code bases. I tried to keep the names the same (when appropriate), and the number of files the same (again, when appropriate).</span></span></div>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Organization</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In which I examine file layout and navigation of both the original project and my Dart version.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The original version collected all files into a single directory.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-25 at 9.48.35 PM.png" height="420px;" src="https://lh3.googleusercontent.com/Y5dsC50DqzjNI290qGBtHqCaxfGeeHyisJci6-k-n_4Iqma4qaeWOcxATO__31RCj_e3EPKgwEZjAOO9jdhoDlW_3luZGU8RwbytpcpS3M8DZLuaYrw97HK2FJ0dvL6NSQ" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="224px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">To discover the “main” JavaScript file, I opened index.html and I found six script files:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-25 at 9.49.50 PM.png" height="239px;" src="https://lh6.googleusercontent.com/rAPS_T4kdYs6mPdL8wjgdBkQsG_WFhwW-ucvgeBZW3WgVUbYT2HwwQxcNgNlfVSuqa-68frtzYvcVMEmm_imnXA5L4InOc4N_qeGi9UhOl0AGqBmX-pGQQah6OuROijuCg" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Hm, where does the application start? I wasn’t sure. I opened each file, in order. It appeared that bootstrap.js contained the “entry point” of the application.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The entry point was a “immediately invoked function expression” (IIFE):</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="music-dna_bootstrap_js_at_master_·_paullewis_music-dna.png" height="477px;" src="https://lh3.googleusercontent.com/8ncuE86d-xiXqzP4aun1jLCKtxllVeGjrS8F0AxfYBuPkHFKXqNa2Rit2FTRKsulCQxkKTfiUVwDj95YxrSBUDrc0D4n7Cb2FCM-bwt1VyRIyg7hLdThLpUj_CruJvxrhw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart’s package manager, </span><a href="https://pub.dartlang.org/" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">pub</span></a><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">, defines a </span><a href="https://www.dartlang.org/tools/pub/package-layout.html" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">layout convention for packages</span></a><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> and apps. The Dart version has the HTML, and Dart files for the app, inside a </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">web</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> directory. The library files (files that contain libraries that might be useful for any app) are inside a </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">lib</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> directory. (More on this soon.)</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-25 at 10.34.11 PM.png" height="580px;" src="https://lh6.googleusercontent.com/2djzBljTncCrNw7T3zwK7Xl3Pxs3wQf2vg7Nrx3eq9YMO9aPJi6PnOiis5FkxzmjedlBNofJq5GfBISSep_Pt3xruhd4kjbm58_nbX0ZAqVtV0Y-0ICxSAPy8u4mT3s4ow" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="414px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">To find the “entry point”, I opened the main HTML file (music_dna.html). I found a single Dart file and two supporting JavaScript files.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-25 at 9.59.01 PM.png" height="113px;" src="https://lh5.googleusercontent.com/mr8lMTiKWU4AoEMvJJnP17ZozdYsZnCsIGn5LIrLXTjsFSHoP6J363_qyhxCj6cOsks6VLemmFpBYydGR1cefKdKsI3NhBY2uIlwgXXPTfYjMom-150GZEbu-2m6x3UQ3A" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">I did not port the id3.js file to Dart for two reasons: it was minified, and I wanted to test Dart-JavaScript interop. The dart.js file is boilerplate: it helps the app run in both JavaScript engines and Dart VM.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Dart_Editor.png" height="290px;" src="https://lh3.googleusercontent.com/NJ0JkPFstLP2sWVhzJ3I-jPRv84TEE_JjIy7daRYNwzAkdllRYE8RMOF4WcWbBftJIg87CXhCpxLZb2IprtfYiedIZWwZH0Hc_SALoY6Rru3kMZNaTJqPsSy8LK6MfwDqw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="550px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The application starts from the main() function in bootstrap.dart. All Dart programs start at the main() function.</span></div>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dependencies and modules</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In which I examine how both versions handle linking to libraries or modules.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">JavaScript doesn’t have a native library or module system. The original version listed each “module” as a separate script tag from the main HTML file (screenshot above). The order of the scripts is important, as scripts that load later depend on scripts that were loaded earlier. The code does not explicitly declare its dependencies.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">For example, the bootstrap script creates a new instance of MusicDNA. The bootstrap.js file does not include a reference to the location of the definition of the MusicDNA function.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="music-dna_bootstrap_js_at_master_·_paullewis_music-dna.png" height="220px;" src="https://lh5.googleusercontent.com/XkhGqrQJhHuJ84wmfoLyHf5kJbl3WattEY0pd77L6c9oBkEDzrsR192SuTqVRmUXp7V2HTQ1QGwAdmYPELJqYV-3WxzATsEjhz_qv4Sq0GcJKkHXrv95Q6KsT2ysKzEfgw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The MusicDNA function comes from the music-dna.js file, which is loaded before the bootstrap.js file via script tags.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The Dart language natively supports </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">libraries</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. A library can </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">import</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> other libraries. For example, the bootstrap.dart file imports its dependencies:</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-25 at 10.31.14 PM.png" height="115px;" src="https://lh3.googleusercontent.com/9D7np9MialJdfjfrA2UHDSoaNLqvrmVhd6BySsalL0bgx30DNxHXU11YPvw0za7_onasQEDrj7pfyv5ixnasnV6i_Ma_6xcFkKtNl0UF2oNmEVeieW-sZ2C42uW5JxyxFg" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The Dart SDK has some standard libraries like </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">dart:html</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> for DOM access, </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">dart:js</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> for interop with JavaScript (more on this below), and more. The code also imports </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">music_dna.dart</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> which explicitly provides the </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">MusicDNA</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> class. Using the </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">show</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> keyword with </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">import</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> makes it easy to glance at what names are provided by what library.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The music_dna.dart file is its own library, which also declares its own dependencies:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-25 at 11.10.20 PM.png" height="230" src="https://lh6.googleusercontent.com/dA7DKi_hn1-bc51oRY2NsBrXEdC0ttHhTwszhaN78zsB8H1zT395Sae1CuIHI16fDXnrv3zmfC5KQJkN9mbDHwI36YYihNDzleGR0q524LaPGFYedGg9SD5U2j4YMw87AQ" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="640" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Notice the two types of URIs used in imports: </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">dart:____</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> and </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">package:_____</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. Imports from </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">dart:</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> come from the Dart SDK, and imports from </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">package:</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> refer to libraries that live in </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">packages</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. A package is a bundle of Dart code, conforming to some layout conventions, and declared by a </span><a href="https://www.dartlang.org/tools/pub/pubspec.html" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">pubspec.yaml</span><span style="background-color: transparent; color: #1155cc; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;"> file</span></a><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Both libraries and applications can live inside of a package. The music_dna application is itself a package. The music_dna library imports the audio library from its own package. This is a handy way to avoid using relative (and brittle) paths that would have to reach up and out of the file’s directory.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Back to libraries: A library can be split into multiple </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">parts</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. The audio.dart file declares the library, its imports, and the two other files that contain the library’s classes: audio_parser.dart and audio_renderer.dart.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Dart_Editor.png" height="221px;" src="https://lh5.googleusercontent.com/Yncets4H41DTyTwcDi9rwvDor_lR-MTi-qTt0HsADuePeKUrI_b8AdCAzvLxbXXV5YCc-nyitaOD-MJ8nOGQwNj1uY46c-F-oD5lp-tuXVtsxGYp8l-ejBGoq4X7Lpc_Xg" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">An abbreviated way to look at the libraries and dependencies of the Dart version:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="296px;" src="https://docs.google.com/drawings/d/s2HsePbNpyMV-Q9LYyu1f5g/image?w=624&h=296&rev=161&ac=1" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Shims</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In which I explore how both versions deal will shimming browser APIs, such as Web Audio and requestAnimationFrame. A shim is a thin layer of code that compensates for browser differences in function names or APIs.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The original version shimmed the APIs using a common JavaScript language pattern. For example, here is the shim for AudioContext (from Web Audio) in audio_parser.js:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="music-dna_audio-parser_js_at_master_·_paullewis_music-dna.png" height="323px;" src="https://lh4.googleusercontent.com/fkZbNdZatfNO4oz5l8wG-4yErAwSzvTwLhHiOu5v6wUQACai2fsy-UUBpTvfh-5kwt6x9eTeGvqDVKhWrsk8SWJTGpF8PMEl8ChSuQFQXMGeeSCApn4PSeoQXKvE2qLadA" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The original code also shimmed requestAnimationFrame in bootstrap.js:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-25 at 10.44.26 PM.png" height="225px;" src="https://lh6.googleusercontent.com/lMAonOdbEaVt8BB5vm9S_BMlBo10LxOgupB1eU33vjMYbW7Bm_ygcB3gc4pzA9KoT6Iq3hZLNE2Q80ReeLRm1vYJE9rT_HESN3kpI_DMKhlQH-nsAEQuMVlcxG7hUUgENQ" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">dart:html</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> library hides the shims, so I don’t need to worry about it. For example, I just needed to import the </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">dart:web_audio</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> library and then use the </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">AudioContext</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> name.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Dart_Editor.png" height="103px;" src="https://lh6.googleusercontent.com/G1T0jk1e4ZvGCaNGq_KdchETrGmE-wDcMRJeDeEWZ3j1wXX14M3V_ZQdkfJi_CvmikGG76XR4S1dVrbmmPyLRf6qFqWkTfcTpWRXz_od2ZFTebOeSQMWCovW__z7tSytMw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Dart_Editor.png" height="59px;" src="https://lh5.googleusercontent.com/pvdkSVcR9h-65gsClGyDcHnK4jC1KqSBJ-5v_kQD1xktxDSdBKn2XhQLtMMzST2eplcqj94oGPU5vjmjGngtQPGjMWoRpOn3dsTuBzREsf2OqDOUZjbAWxcXSiccS_Z-mw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When I compile the Dart app to JavaScript, the shims are included in the generated JavaScript. This ensures the generated code works in all modern browsers.</span></div>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Classes</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In which I examine how both versions model and construct concepts.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">JavaScript is not a class-based object oriented language. The original version used standard JavaScript patterns for “classes”.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="music-dna_audio-parser_js_at_master_·_paullewis_music-dna.png" height="401px;" src="https://lh4.googleusercontent.com/ys8KQsADL90K08GTK-VxYrWP9547ZQZgYEk2h7QQ4qgX4y1_NF6aSXM5C8uocoL4KS7dgcAJU284SDQzH33NKXykLTpoA9MK52cJ3mp4baYtYr41S_-XTIE-fqBVnc-8Ug" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The JavaScript version initializes fields by constructing new objects as well calling methods. The object isn’t initialized until the entire body of the AudioParser function is run.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart is a class-based object oriented language. I created a formal class for AudioParser.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="403px;" src="https://lh5.googleusercontent.com/nGb3sxDx5ec-rbe0j51aijvDwN5jJL_xxwGL8TSi5o3t_5loK2tWWTagyi_KMDqRulOL6ZaihA8HEQJ2YBKGOr2q3xKFT3TkaIA-4GjHOHHgYQR4bWKPIl8ouvNUabDAew" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The Dart version initializes most fields inside of the constructor body. By the time the constructor body is run, the object is initialized.</span></div>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Type annotations (aka discovering a bug)</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In which I use </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">type annotations</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> and discover a </span><a href="https://github.com/paullewis/music-dna/issues/7" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">bug</span></a><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> in the original code.</span></span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">JavaScript doesn’t have a way to explicitly state that a variable can hold a specific type of object. Fields are simply marked as </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">var</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">, as in this example:</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-26 at 12.26.34 AM.png" height="379px;" src="https://lh3.googleusercontent.com/OGa0DkJapvDcdaS9Bkt9W1csGqPWAPXaPCD-Ph3jbG5JtZGkOK54u3HtpPAGEKYoIEjxBmGztVlTTBUIbpfwpBQrZ08QNc3sMIoOpzSrky8xIZOFRQOwh7ZofDL2QRYhIQ" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">It’s unclear what kind of function can be assigned to </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">audioDecodedCallback</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. I can assume what </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">sourceNode</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> or </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">audioRenderer</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> can be, because I know this is a Web Audio app and there’s another file called audio-renderer.js.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Method parameters also do not have a type annotation. Here is one example:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="337px;" src="https://lh4.googleusercontent.com/LEx1cVrEkg9PFi7384Cf_icTYM9SuBCY104gEzGrL9Z_2bHJ5RIjve2saKpMCFlnE1Mk1ri2X3iKN8Okijma9V6_-D9FF8vSg-iJZPIAWEoGu_SKOi9vD4kXYFgQ4EnWBw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Can you spot the bug in the above example?</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> I didn’t, until I converted the code to Dart.</span></span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Type annotations are optional in Dart, but I love ‘em. I use type annotations as inline and explicit docs for my fellow programmers and my productive tools.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">We’ve seen it before, but here’s the recap of how I use type annotations for fields in AudioParser:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-26 at 12.36.44 AM.png" height="278px;" src="https://lh4.googleusercontent.com/O1TeSY_qAqwUIb05xPHk8B75l-qBY8lA6GqF3CqSeO_8g_1WZAWsNWIDun7N5ypJaN2WZC3pxZg9XJqjvmPjGNoaJ9Rj6Fu_0mbdrK3lDSIWf9E2Nnr1npszHQ7o1kJZmw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="512px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">So, </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">gainNode</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> is of type </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">GainNode</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. I could probably have guessed that, if I knew there was a Web Audio type called GainNode. Without the type annotation, editors and analyzers can’t infer that </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">gainNode</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> is a </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">GainNode</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. And that’s important, because…</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="249px;" src="https://lh6.googleusercontent.com/puQTLRsQ-uAjkUur6bHipRsG-Fz_p5mJEkOYPeqKzD4g-q2WgEWC4GAAiFjLco_RfrwzyIussqtRMVBwldzqU2mLAvh5J_OTwwD6LEiE02qWTIRHsi9VMSUBynYHsVFiHA" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart Editor and the Dart analyzer knows that </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">disconnect()</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> takes an </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">int</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> and not a </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">GainNode</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. A warning is displayed, and bug identified!</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Turns out, the code didn’t need the call to disconnect() anyway. But, I feel more confident knowing that tools can identify potential errors.</span></div>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Event handlers, and calling multiple methods on the same object</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In which I encounter a Dart-y DOM, use a Dart language feature, and reduce the amount of code I have to type.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The traditional way to listen for DOM events (like </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">drop</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> or </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">dragover</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">) is to use </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">addEventListener()</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. This method takes a string as the first parameter. If you misspell the name of the event, you will not get a warning, and the program will keep on trucking. There is no code completion for the values of the strings, because the language can’t express all the valid values for the first argument.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Here is an example, from the original code, of listening to multiple events on a single </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">fileDropArea</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> object.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-26 at 12.47.25 AM.png" height="245px;" src="https://lh3.googleusercontent.com/s__jBi-oxNPniX1tWsgDx0gdXCKd7o1w4YY02vyjBlU-zxmJDhDp83WW9Npy8ExIOXslMD3rf7WliOQQTSudvaP718B_yF0lR91UhP1UzagciAugsrRWs3kfTlEWmxBa-g" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">dart:html</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> library offers DOM APIs that are more toolable. There are specific methods for specific events, for example </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">onDrop</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. If you misspell the method name, the tools can warn you about an unknown method. Also, you can use code completion to help discover other events to listen for.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart supports </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">method cascades</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">, which help reduce repetitive code. If you need to call multiple methods on a single object, cascade the calls and avoid repeating the variable.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Here is the Dart code for setting up the drag and drop area:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img alt="Screen Shot 2014-04-26 at 1.12.45 AM.png" height="178px;" src="https://lh3.googleusercontent.com/S046oG51e2MldfcQuoj3XnPBrI6sAUVTZOMrekaw_UqPa_xCsARSwgb3iXhRo_AyZ6llVQkRAJJSMnhi33Qz3O2FtTjwiI4I5eIMvUzUGbcLLIz4TozAmeUawbjULvX_8w" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="468px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Notice how </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">fileDropArea</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> is stated only once. The double dot (..) syntax is the cascade. Compare this version to the original JavaScript version above.</span></span></div>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Asynchronous callbacks</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In which I explore how both versions handle asynchronicity.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When something needs to run “later”, JavaScript calls a </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">callback function</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">. The MusicDNA app uses asynchronous callbacks when decoding audio data.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<ol style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">MusicDNA has a </span><span style="background-color: #cfe2f3; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">onAudioDataParsed</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> function.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">MusicDNA creates a new AudioParser, and passes </span><span style="background-color: #cfe2f3; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">onAudioDataParsed</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> to it.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">MusicDNA calls </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">audioParser.parseArrayBuffer()</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">, which calls an </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap;">asynchronous</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">decodeAudioData</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> method.</span></span></div>
</li>
</ol>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Control is returned to the browser, and events are processed as normal. The audio is decoded in the background. Sometime later...</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<ol start="4" style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">decodeAudioData</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> is finished and is successful, it calls </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">audioParser.onDecodeData</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">onDecodeData</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> is finished, it calls </span><span style="background-color: #cfe2f3; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">onAudioDataParsed</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Now we’re back in MusicDNA!</span></div>
</li>
</ol>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">As you can see, a function can get passed around, with no clear line of execution.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Here’s the code, see if you can follow the callback:</span></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="143px;" src="https://lh6.googleusercontent.com/KKvJnIpg1UycR_iiW5EmGNhxz7JyExyi94oypymHJ1hS-4RMmPqcaHnHnGGRcWOOcaC8x4IyAcwsXLZKYbwuKcPvr9gvehlA86x0zXdF8L-eCNgiY-nzAMY-LwmPCE-u_Q" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In AudioParser:</span></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="371px;" src="https://lh6.googleusercontent.com/t4_q0NlR7igF5YersQdHzCP_JlZJHK5Kv63_jNDjKOqvx0Q_EOYkw74-7Fp0IEsGJYop9L6QguK1PEYXN8Ro1xTfkv0IHFQoLD9iaHjVZgW-b65_6OJN7JXeQAhq4tPBQw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">parseArrayBuffer() calls decodeAudioData() which asynchronously calls onDecodeData.</span></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="101px;" src="https://lh6.googleusercontent.com/_cuo5I0m5qSJyKAzpVsyWV1R5pFSx2h9y5bGmWDpbCgyHuD4JG_JrhvD2CwckV8sWLi1eV0M5sM85httARIFv-z58dLQjh02RR8vPANNvWit74KYlZFvryJdjX5wYIXuxQ" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The onDecodeData function calls the callback given to AudioParser from the constructor:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="649px;" src="https://lh6.googleusercontent.com/672EqZyaCUb8OdV_y6xTt9t0kX9hy4_h1snQcf2g01nHMwHnjznaUjxoMCp7pDmiSDrMEKCFENc_pZSjhW8j1IWPVOv6n9wgh-rGpbjVLpoB76C-ejXKwZnWT3zFOK3ciw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart’s core SDK has a </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Future</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> class, which represents values available sometime in the future. An asynchronous function or method returns a Future instead of accepting a callback as a parameter. The Future </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">completes</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> when the asynchronous function is finished, and a value is available.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">In the Dart version, </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">parseArrayBuffer</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> returns a Future, as seen below:</span></span></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="156px;" src="https://lh4.googleusercontent.com/uUHTfzJ4t2IGBeG9z5GIPywyAkOjRuzkvmmTOjHDQ2jIu0G67QGCTVSJP4JPALB3gbQbjJ5FgrxkG2yj8kEdqYmWQWvdqm1R9m0F04RxHQH4b8DKTzq5m0c3IUrsAWvZbQ" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Now that the async methods can return futures, the code can get simplified. For example, Futures are chainable, so music_dna.dart looks like this:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="219px;" src="https://lh5.googleusercontent.com/_5XoH3PvL2EbVGrGlWgo7x1BoZIlf_294o3Gs43uizQ5MZZM7bThuClLDf0fIcr8kQk8bXwjbUOEKVjw2VpnL8G3VjfS51JMt0fREBcjlkz-4oqgUainh_1YT7rmpkQIVA" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="589px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The above code reads:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<ol style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Read the file into an array buffer.</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When the </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">loadEnd</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> event is done, </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">then</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> parse the array buffer.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">When the array buffer is done, </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">then</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> read the duration.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: decimal; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Return a future to caller of </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">parse</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> knows when parsing is finished.</span></span></div>
</li>
</ol>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Animation</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Modern web apps animate with </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">requestAnimationFrame</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">, which is an API that lets your app get notified when the browser is ready for your app to draw a frame.</span></span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Again, because JavaScript uses callbacks for async notifications, the requestAnimFrame (a shimmed version of requestAnimationFrame) uses callbacks.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="572px;" src="https://lh5.googleusercontent.com/XINijaB6YWDgUyprEQSiVvPdHQxbzlcvU9pmf2xdhSbm16kEa9LRI68KsJLxi1u5YekYuMiDVBJKHTVHdKRDXAORQ1UeiuOA7sfd1T6gKVUNXI-MpZCBv6QKXfa0v1zgzQ" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart uses Futures in many places, including in the HTML libraries. Specifically, requestAnimationFrame has been rewritten to return a Future that completes when the frame is ready.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="287px;" src="https://lh3.googleusercontent.com/XSd4FGtKRp5qKtA75VohqV135rkSYzDEDb4GMLo6bOSYNAtrXt8xhXyuZ_2UBUwmjNJscv-Yv_m39ZLQgVMZ9kXQEzbNXS0EdWMsG9TgUEaeQ4a1cSlJyTma8-akGfMbaQ" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="595px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<h1 dir="ltr" style="margin-bottom: 0pt; margin-top: 10pt;">
<span style="font-family: inherit; font-size: 21px; font-weight: normal; line-height: 24.149999618530273px; white-space: pre-wrap;">Code size</span></h1>
<div>
<span style="font-family: inherit; font-weight: normal; line-height: 24.149999618530273px; white-space: pre-wrap;"><br /></span></div>
<div>
<span style="font-family: inherit; font-weight: normal; line-height: 24.149999618530273px; white-space: pre-wrap;">There are two ways to look at code size: the original code that the developer works with, and the compiled, minified, gzipped code size. It's important to stress that neither the original version or the Dart version made any attempts to create the most terse code possible. Line counts include blank lines and comments. I believe this app is too small to make any reasonable claim about lines of code correlation to language.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="color: black; font-family: inherit; font-size: 17px; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<div>
<span style="font-family: inherit; font-weight: normal; line-height: 24.149999618530273px; white-space: pre-wrap;"><br /></span></div>
<div>
<span style="font-family: inherit; font-weight: normal; line-height: 24.149999618530273px; white-space: pre-wrap;">The important JavaScript files, their sizes, and number of lines:</span></div>
<div>
<ul>
<li><span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">audio-parser.js: 1823 bytes, 78 lines</span></li>
<li><span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">audio-renderer.js: 2751 bytes, 120 lines</span></li>
<li><span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">bootstrap.js: 1803 bytes, 69 lines</span></li>
<li><span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">music-dna.js: 3608 bytes, 130 lines</span></li>
</ul>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">Total bytes for the scripts (not counting id3.js): 9985 bytes.</span></div>
</div>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;"><br /></span></div>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">Total lines for the scripts: 397 lines.</span></div>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;"><br /></span></div>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">The original app did not concat the JS files or minify them, however most developers should perform those steps with "real" apps. Most web servers will gzip on the fly, so it's worth noting that the total number of gzipped bytes from scripts (gzipping each file individually) results in 3825 bytes.</span></div>
<div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="color: black; font-family: inherit; font-size: 17px; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
</div>
<div>
<span style="font-family: inherit; font-weight: normal; line-height: 24.149999618530273px; white-space: pre-wrap;"><br /></span></div>
<div>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">The important Dart files, their sizes, and number of lines:</span></div>
<div>
<ul>
<li><span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">lib/audio.dart: 427 bytes, 12 lines</span></li>
<li><span style="font-family: inherit;"><span style="line-height: 24.149999618530273px; white-space: pre-wrap;">lib/src/audio_parser.dart: 1786 bytes, </span><span style="line-height: 24.149999618530273px; white-space: pre-wrap;">68 lines</span></span></li>
<li><span style="font-family: inherit;"><span style="line-height: 24.149999618530273px; white-space: pre-wrap;">lib/src/audio_renderer.dart: 2273 bytes, </span><span style="line-height: 24.149999618530273px; white-space: pre-wrap;">99 lines</span></span></li>
<li><span style="font-family: inherit;"><span style="line-height: 24.149999618530273px; white-space: pre-wrap;">web/bootstrap.dart: 1763 bytes, </span><span style="line-height: 24.149999618530273px; white-space: pre-wrap;">71 lines</span></span></li>
<li><span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">web/music_dna.dart: 1623 bytes, 59 lines</span></li>
</ul>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">Total bytes for the scripts (not counting id3.js): 7872 bytes.</span></div>
</div>
</div>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;"><br /></span></div>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">Total lines for the scripts: 309 lines.</span></div>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;"><br /></span></div>
<div>
<span style="font-family: inherit; line-height: 24.149999618530273px; white-space: pre-wrap;">Compiling and minifying the Dart scripts to JavaScript generates 143kb bytes. Gzipping the generated JavaScript (as most web servers and browsers compress/decompress on the fly) results in 41kb bytes. (For comparison, jQuery itself is 32kb minified and gzipped. However, the original Music DNA app does not use jQuery.)</span></div>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Interop with JavaScript libraries</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The Music DNA app uses a JavaScript file called id3.js to read the ID3 tags and extract metadata like song title and artist.</span></div>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Original version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">The id3.js file is included as a script tag, just like any other JavaScript file.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="118px;" src="https://lh3.googleusercontent.com/PhNiNPz5SphfTm3uA2CrywbTCQVI3gtFGxf9i_CKmvulMMwAGMO20WSHR2NE70h9PgBo9eYz2mNrM9eiYvg3wVmGtzRzVepscjYMg-O0ZRDHsqD0LzbXDtZbBdm-s1Dxng" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="450px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt; text-align: center;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Using the ID3 functionality is easy, as it’s just JavaScript in JavaScript. Here is how the ID3 library is used inside of bootstrap.js:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="237px;" src="https://lh5.googleusercontent.com/8iK3p7zI85B7-CsfLH2imyoZsLVyd0fDBzFEth7v1tSzdtQzLnt01fh3Pw8cx-zhXvFdd8R4Ps1Xqn_TrSdt6xS_fvHZiu1xNhLgdrQZoCsvWLw-hlpRA_RPMgwwKg6gLg" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="460px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Original version</span></td></tr>
</tbody></table>
<h2 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 17px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart version</span></h2>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Using JavaScript files in Dart requires the </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">dart:js</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> library, which provides Dart-JavaScript interop. I had to import the dart:js library, explicitly get a reference to the ID3 object (which originally came from the id3.js file), and use the </span><span style="background-color: transparent; color: black; font-size: 15px; font-style: italic; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">callMethod</span><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> method to call JavaScript methods.</span></span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">I was able to use id3.js in the Dart app, but the integration isn’t as trivial as it is with JavaScript-JavaScript interop.</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Here is the Dart code:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: inherit;"><img height="535px;" src="https://lh6.googleusercontent.com/lkWffP1MHo3shlI84v1yLC7BpA6sb4tY5Sqj1oYZ-NnJ1namA0sDPi_PqEAxR8ipuWkq6d-TGxp1eK6JoHQ_NTaXg7nW_JbAbPwGCNogjwpg7smRUF0ZDZpph7YfwUWDTw" style="-webkit-transform: rotate(0rad); border: none; margin-left: auto; margin-right: auto;" width="624px;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: inherit;">Dart version</span></td></tr>
</tbody></table>
<h1 dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 10pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 21px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Lessons learned</span></h1>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Porting the Music DNA app from JavaScript to Dart was a lot of fun. Here’s what I learned:</span></div>
<span style="font-family: inherit;"><b style="font-weight: normal;"><br /></b>
</span><br />
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Futures are great! They really simplify API design.</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Type annotations save the day. I found a bug in the original code after I ported it to Dart, thanks to type annotations and code analysis.</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">You can interoperate with JavaScript from Dart, it’s just not a “cut and paste” job.</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">It’s easy to tell where Dart programs start.</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration-line: none; vertical-align: baseline;"><span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Compiled, minified, and gzipped apps about this size end up a little bigger than jQuery.</span></li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart’s library mechanism makes it easy to determine where names come from.</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Dart’s HTML library shims APIs like requestAnimationFrame for you.</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Method cascades are sweet.</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration-line: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Code completion. Love it. Especially helpful when exploring new APIs.</span></div>
</li>
</ul>
<div>
<span style="font-family: inherit; font-size: 15px; white-space: pre-wrap;"><br /></span></div>
<div>
<span style="font-family: inherit; font-size: 15px; white-space: pre-wrap;">There are other language and library features of Dart that I didn't get a chance to use. If you're interested, there is a <a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html">Dart language tour</a> that might be interesting to you.</span></div>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Of course, most of the techniques used by Dart in this article aren't impossible with JavaScript. In fact, future versions of JavaScript should get features like modules and promises. They just aren't built-in, obvious, or easy "out of the box" with JavaScript as we know it today. And this is where I begin to see some of the real power with Dart: the out of the box experience is really good. Shims? yup. Futures? yup. Layout convention? yup. Classes? yup. Type annotations (instead of comment)? yup. Dart seems to have a broader and more functional base on which we can build. I like it.</span><br />
<span style="font-family: inherit;"><br /></span>
<br />
<div dir="ltr" style="line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: inherit; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Many thanks to Paul Lewis for the inspiration and sharing his code.</span></div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-81952429177982195592014-04-28T21:42:00.000-07:002014-04-30T11:16:22.388-07:00Speed Up Your Dart App's Initial Load With This Transformer<div style="text-align: center;">
I just saved potentially <i>hundreds of blocking milliseconds</i> from my Dart app's initial loads.</div>
<div style="text-align: center;">
By moving script tags, and using my new pub transformer, you can help your users, too.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="http://3.bp.blogspot.com/-y4YjZIr0wQI/U2CeImoj3cI/AAAAAAABbsM/IMdMQSlE5eU/s1600/pm_web.jpg" height="229" width="640" /></div>
<br /></div>
<h2>
Where does the time go?</h2>
First, some background:<br />
<br />
Typical Dart applications are designed to work in Dart VM and modern JavaScript. A small file, named <i>dart.js</i>, is loaded by the HTML file and checks to see what runtime is available. If the Dart VM is available, the Dart code is run. Otherwise, the dart.js file swaps out the Dart script for its equivalent JavaScript file compiled from the original Dart code.<br />
<br />
Dart Editor can generate skeleton applications, complete with starter HTML, CSS, and Dart files. It's really handy for getting started quickly. As of today, the default starter HTML code looks something like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><!DOCTYPE html></span><br />
<span style="font-family: Courier New, Courier, monospace;"><html></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <head></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <meta charset="utf-8"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <meta name="viewport" content="width=device-width, initial-scale=1.0"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <title>Hugs all around</title></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <link rel="stylesheet" href="styles.css"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> </head></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <body></span><br />
<span style="font-family: Courier New, Courier, monospace;"> .......</span><br />
<span style="font-family: Courier New, Courier, monospace;"> <!-- not a good practice, do not copy --></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <script type="application/dart" src="hugs.dart"></script></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <script data-pub-inline="packages/browser/dart.js"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> </body></span><br />
<span style="font-family: Courier New, Courier, monospace;"></html></span><br />
<br />
Some browsers delay script execution until CSS resources are downloaded (unless the script tags are before the CSS file). This means that the <i>dart.js</i> file isn't executed until the CSS file in the <head> is downloaded. This is an unnecessary delay in app startup.<br />
<br />
<h3 style="text-align: center;">
<i>Location and order matters for scripts and CSS resources. Default projects from Dart Editor can be optimized.</i></h3>
<br />
For the above HTML file, the browser's workflow looks something like this:<br />
<ol>
<li>The main HTML loads, with links to CSS, dart.js, and the Dart application.</li>
<li>The browser downloads the dart.js file and the CSS file, more or less concurrently.</li>
<li><b>The CSS file must finish downloading until the dart.js script is executed.</b></li>
<li>dart.js checks to see if Dart VM is available. It's probably not.</li>
<li>dart.js looks for the Dart application script tag.</li>
<li>dart.js replaces the script tag with another script tag that points to the Dart app compiled to JavaScript.</li>
<li>The browser then, finally, downloads the actual application.</li>
</ol>
<div>
See this output from DevTools for an illustration:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-gHWEa6vaROQ/U2CaOmGLQyI/AAAAAAABbsA/_fj940s29UA/s1600/Pub_transformer_test.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-gHWEa6vaROQ/U2CaOmGLQyI/AAAAAAABbsA/_fj940s29UA/s1600/Pub_transformer_test.png" height="226" width="640" /></a></div>
<br />
<br /></div>
<div>
For my simple app, hosted on the public internet, the app loaded in approximately 1.29 seconds. There are two root causes: the unnecessary download of dart.js, and the blocked execution of dart.js.<br />
<br />
<h3 style="text-align: center;">
<i>The app was <b>blocked for 300ms</b>. </i></h3>
</div>
<h2>
Saving time</h2>
<div>
I wanted the functionality of dart.js without the extra delay in startup. The solution was to move the script tags, and inline dart.js.<br />
<br />
Step one, move the script tags into the <head> tag, before the CSS resource.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> <head></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <meta charset="utf-8"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <meta name="viewport" content="width=device-width, initial-scale=1.0"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <title>Hugs</title></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <script async type="application/dart" src="hugs.dart"></script></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <script async data-pub-inline src="packages/browser/dart.js"></script></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <link rel="stylesheet" href="styles.css"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> </head></span><br />
<br />
Dart apps don't begin until after DOMContentLoaded, so it's safe to start downloading the app as soon as possible (as long as the script tag is marked as <i>async</i>).<br />
<br />
Step two, add an <i>async</i> attribute to the script tags. This attribute tells the browser <i>not</i> to block page parsing while the script is downloading and executing.<br />
<br />
Step three: <a href="https://www.dartlang.org/tools/pub/transformers/index.html">write a <i>pub transformer</i></a> to rewrite the HTML, and inline the contents of dart.js. Therefor, <a href="http://pub.dartlang.org/packages/script_inliner">script_inliner</a>, my new pub package and transformer, was born!</div>
<div>
<br /></div>
<div>
To install the transformer, add it to your pubspec.yaml dependencies:</div>
<br />
<div>
<span style="font-family: Courier New, Courier, monospace;">dependencies:</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> script_inliner: ">=0.0.1 <0.1.0"</span></div>
<div>
<br /></div>
<div>
Then, add script_inliner to the list of transformers in your pubspec.yaml:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">transformers:</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">- script_inliner</span></div>
</div>
<div>
<br /></div>
<div>
Then, add a <i>data-pub-inline</i> attribute to script tags that should be inlined. For example:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><script data-pub-inline src="packages/browser/dart.js"></script></span></div>
<div>
<br /></div>
<div>
When you run <i>pub build</i> or <i>pub serve</i>, the transformer kicks in and inlines the script.</div>
<h2>
The results</h2>
<div>
Here's the same app, with the contents of dart.js inlined:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-J6XOasYFb_g/U18sKQHn7GI/AAAAAAABblk/3Hw9wojf4ig/s1600/Pub_transformer_test+3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-J6XOasYFb_g/U18sKQHn7GI/AAAAAAABblk/3Hw9wojf4ig/s1600/Pub_transformer_test+3.png" height="142" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br /></div>
<div>
Notice how the browser no longer requests dart.js (because the contents were inlined), and the browser downloads the app's script file as soon as any other external resource. After numerous reloads (and clearing the cache), the approximate average time was 916ms.<br />
<br />
<h3 style="text-align: center;">
<i>Inlining dart.js, and moving the script tags, resulted in over 25% faster load times.</i></h3>
<br />
Please move your script tags and try the <a href="http://pub.dartlang.org/packages/script_inliner">script_inliner transformer</a> and let me know if it works for you.<br />
<br />
For the curious, here's what the HTML now looks like:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><!DOCTYPE html></span><br />
<span style="font-family: Courier New, Courier, monospace;"><html></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <head></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <meta charset="utf-8"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <meta name="viewport" content="width=device-width, initial-scale=1.0"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <title>Hugs</title></span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> <script async type="application/dart" src="pub_transformer_test.dart"></script></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <script data-pub-inline="packages/browser/dart.js"></span><br />
<span style="font-family: Courier New, Courier, monospace;">(function() {</span><br />
<span style="font-family: Courier New, Courier, monospace;">if (navigator.userAgent.indexOf('(Dart)') === -1) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> var scripts = document.getElementsByTagName("script");</span><br />
<span style="font-family: Courier New, Courier, monospace;"> var length = scripts.length;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> for (var i = 0; i < length; ++i) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if (scripts[i].type == "application/dart") {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if (scripts[i].src && scripts[i].src != '') {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> var script = document.createElement('script');</span><br />
<span style="font-family: Courier New, Courier, monospace;"> script.async = true;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> script.src = scripts[i].src.replace(/\.dart(?=\?|$)/, '.dart.js');</span><br />
<span style="font-family: Courier New, Courier, monospace;"> var parent = scripts[i].parentNode;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> document.currentScript = script;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> parent.replaceChild(script, scripts[i]);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;">})();</span><br />
<span style="font-family: Courier New, Courier, monospace;"></script></span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> <link rel="stylesheet" href="style.css"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> </head></span><br />
<span style="font-family: Courier New, Courier, monospace;"> ......</span><br />
<br />
(Fine print: tests from my home machine, over wifi, hitting static files served by Dropbox. Also note: I've barely tested this transformer, and I haven't tried it with too many different scripts. YMMV.)<br />
<br />
<h2>
Measure and optimize</h2>
<br />
Use the performance rules that you've learned as a guide, but always use the tools to measure and verify. Performance is a feature, and has direct correlation to customer satisfaction and conversions. Time spent on faster app loads is time well spent.<br />
<br />
<br />
<span style="font-size: x-small;">(Banner from http://www.ayoungertheatre.com/wp-content/uploads/2011/11/pm_web.jpg)</span></div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-36531142564465279882014-02-05T08:58:00.000-08:002014-02-05T09:19:48.079-08:00Angular and Polymer Data Binding, Together!<br />
<img height="454" src="https://lh6.googleusercontent.com/pJ6hVT4TF5zkTg5JojxpYf_C-6BMQ7mscM_-b2x3qoRDdNv0JeOxI5xjly_TwYVvJm4nX_JMjVNCbhx08agffmq76GdsCB1oCSO1RjsSlfH-vW8MBNOHuL9n2A" width="640" /><br />
<br />
<br />
<div style="text-align: center;">
<i>Angular and Polymer, sitting in a DOM tree,</i></div>
<div style="text-align: center;">
<i>B-i-n-d-i-n-g.</i></div>
<div style="text-align: center;">
<i>First comes components,</i></div>
<div style="text-align: center;">
<i>Then comes elements,</i></div>
<div style="text-align: center;">
<i>Then comes the interop with the node dot bind.</i></div>
<br />
<a href="http://angulardart.org/">Angular</a>, a super heroic MVC framework, and <a href="http://polymer-project.org/">Polymer</a>, polyfills and enhancements for custom elements built on top of Web Components, can live harmoniously in the same app. This post shows you how to connect Angular-controlled components to Polymer-controlled elements via data binding. And we do it all in <a href="https://www.dartlang.org/">Dart</a>.<br />
<br />
<h2>
Angular <i>and</i> Polymer</h2>
<br />
I get asked "Should I use Angular or Polymer?" a lot. My answer is, "Yes". That is, both libraries have distinct strengths, and you can use both in the same app.<br />
<br />
Polymer excels at creating encapsulated custom elements. You can use those custom elements in any web app or web page, regardless if that app is built with Angular, Ember, etc. Angular excels at application engineering, with dependency injection, end-to-end testability, routing, and services.<br />
<br />
<br />
<img height="381" src="https://lh4.googleusercontent.com/lJJ3-2tzMUItRlkQ98R_3v9XZbpPJipi3ObioEMMMyjAegEEDn5hZ0X4K6UvaYn2REoHYTz4-GcoM_WfS1Pj3J-IchFnDNjVMjn4SAAah2XO1ep3umk1_QrkTQ" width="640" /><br />
<br />
Here are some features that Angular offers:<br />
<ul>
<li>directives - kind of like mixins or traits for DOM nodes</li>
<li>dependency injection</li>
<li>testing support</li>
<li>routing</li>
<li>services</li>
<li>server communication</li>
</ul>
<div>
Here are some features that Polymer offers:<br />
<ul>
<li><polymer-element> - convenient way to declare custom elements</li>
<li>widgets</li>
<li>polyfills for new web platform features</li>
<li>encapsulation for the DOM</li>
<li>built on emerging web standards</li>
</ul>
There are some similar features between the two libraries. Both libraries implement a data binding solution (which we cover below). Angular is beginning to build on top of emerging web standards (like Shadow DOM). I expect that, over time, more and more of Angular will take advantage of the Web Components family of specifications.<br />
<h2>
Interop</h2>
We can interop Angular and Polymer via the DOM, as well as via data binding.<br />
<br />
<h3>
DOM interop</h3>
<br />
We've always been able to use the DOM for basic interop between custom elements and Angular. For example, setting an attribute on a custom element is a type of API interop. Simply creating the custom element and inserting it into the document is another type of interop. Polymer and Angular already interop at the DOM layer.<br />
<br />
For example, here's an example of an Angular managed page that includes a Polymer element.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="http://4.bp.blogspot.com/-zXQRFYGykJY/UvJJfYL2crI/AAAAAAABYHM/phUKn4pQDNI/s1600/Dart_Editor.png" height="377" width="640" /></div>
<br />
<br />
In the above code, Angular manages the binding of the <span style="font-family: Courier New, Courier, monospace;">cool</span> variable in the HTML. When cool changes, everywhere you see <span style="font-family: Courier New, Courier, monospace;">{{cool}}</span> also changes. Yes, even when bound into an attribute of a custom element!<br />
<br />
The <my-element> is just a custom Polymer element encapsulates an input field and displays a value. Here's the code:<br />
<br />
<pre class="prettyprint lang-dart"><code>
<polymer-element name="my-element">
<template>
<p>
<input type="text" value="{{message}}"> Polymer binding: {{message}}
</p>
</template>
<script type="application/dart" src="my_element.dart"></script>
</polymer-element>
</code></pre>
<br />
The Angular code can set attributes on <my-element>, listen for DOM events from <my-element>, and of course even insert children elements inside of <my-element>. So in a sense, Angular can interop with Polymer elements just like any other DOM element.<br />
<br />
However, there is an issue. Can you spot it in the animated GIF below?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="http://4.bp.blogspot.com/-OtHB3jRMT6o/UvJf8nmc-SI/AAAAAAABYHw/4xCVAN1ltLM/s1600/before.gif" height="297" width="400" /></div>
<br />
Any changes to <span style="font-family: Courier New, Courier, monospace;">cool</span> initiated from inside the Polymer element <b>are not propagated</b> back out into the outside DOM or Angular. We need real bi-directional data binding: Angular down into Polymer, and Polymer back out to Angular.<br />
<br />
<h3>
Data binding interop</h3>
<br />
Polymer manages data binding through a feature called <a href="http://www.polymer-project.org/platform/node_bind.html">Node.bind()</a>. Node.bind() is a "new method added to all DOM nodes which instructs them to bind the named property to the data provided". Angular does not use Node.bind() out of the box, so Angular is unable to listen for changes that are initiated from Polymer.<br />
<br />
Until now.<br />
<br />
<a href="https://plus.google.com/+JustinFagnani">Justin Fagnani</a>, an engineer on the Dart team, released <a href="http://pub.dartlang.org/packages/angular_node_bind">angular_node_bind</a>, a Dart package that bridges the Angular and Polymer worlds. It is an Angular module that can listen for Node.bind() changes and propagate the changes into Angular.<br />
<br />
Justin explains why this package can help:<br />
<br />
<ul>
<li>Node.bind() takes care of setting up the binding, including two-way bindings, eliminating the need for directives for every property for two-way bindings.</li>
<li>Custom elements that expose properties will be properly bound, again including two-way bindings. You can use the growing collection of custom element libraries in your Angular app.</li>
</ul>
<br />
To use angular_node_bind, add the following to your app's pubspec.yaml file:<br />
<br />
<pre class="prettyprint lang-yaml"><code>
name: angularpolymer
description: A demo of Angular and Polymer data binding.
dependencies:
angular: any
angular_node_bind: any
browser: any
polymer: any
transformers:
- polymer:
entry_points: web/angularpolymer.html
</code></pre>
<br />
Register the NodeBindModule with Angular:<br />
<br />
<pre class="prettyprint lang-dart"><code>
import 'package:polymer/polymer.dart' show initPolymer;
import 'package:angular/angular.dart' show ngBootstrap;
import 'package:angular_node_bind/angular_node_bind.dart' show NodeBindModule;
void main() {
initPolymer().run(() {
ngBootstrap(module: new NodeBindModule());
});
}
</code></pre>
<br />
Finally, change the syntax used for binding into Polymer elements, from {{...}} to [[...]]:<br />
<br />
<pre class="prettyprint"><code>
<my-element message="[[cool]]"></my-element>
</code></pre>
<br />
Notice the binding expression is now <span style="font-family: Courier New, Courier, monospace;">[[cool]]</span> instead of <span style="font-family: Courier New, Courier, monospace;">{{cool}}</span>. The angular_node_bind module looks for [[ ... ]] and wires up Node.bind().<br />
<br />
Here is a little movie of how the app works with true bi-directional data binding between Polymer and Angular:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="http://3.bp.blogspot.com/-UXUbXHlaAXA/UvJgI6uztsI/AAAAAAABYH4/2VEPxyDB3LY/s1600/after.gif" height="275" width="400" /></div>
<br />
<br />
Notice how changes from Angular are reflected in the Polymer element, and how changes from within the Polymer element are reflected in the Angular code. Awesome!<br />
<h2>
Summary</h2>
You can use Polymer custom elements inside of an Angular app in at least two ways. Polymer elements are just like regular DOM elements, so they have attributes, emit events, and can contain children elements. Use Dart's angular_node_bind package to connect Polymer's data binding to Angular's data binding for true bi-directional data sharing.<br />
<br />
Lovely, Angular and Polymer holding hands.<br />
<h2>
Get the source code</h2>
You can check out the <a href="https://github.com/sethladd/dart-angular-polymer-data-binding">source code</a> mentioned in this post.<br />
<span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"></span></div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-50996926814328498472014-01-08T23:07:00.000-08:002014-01-08T23:07:16.687-08:00How to shrink the size of your Dart app when compiled to JavaScriptSo you caught the Dart bug and you're enjoying using the structured language, comprehensive libraries, and productive tools. Great! Except, when you compiled your Dart app to JavaScript, the output was bigger than expected. Read this post to learn how to reduce the size of your JavaScript output. Small apps are fast apps!<br />
<br />
<h2>
Make sure you are minifying</h2>
<br />
The dart2js compiler can minify your JavaScript. However, minification is not the default. Make sure you opt-into minification before you deploy to production.<br />
<br />
How can you tell if you minified? Take a look at the generated JavaScript and you'll know. Minified JavaScript replaces variables names, function names, and more with shorter names. It also moves code around to use less lines.<br />
<br />
If you compile your app from the command line, use --minify:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">dart2js --minify -o=app.dart.js app.dart</span><br />
<br />
If you use <a href="http://pub.dartlang.org/doc/pub-build.html">pub build</a> (a streamlined build process for pub package and apps), it defaults to minifying. Yay!<br />
<br />
If you use Dart Editor, it's a bit more tricky. Follow the <a href="http://stackoverflow.com/questions/19017116/how-do-i-minify-javascript-code-compiled-from-dart-editor">instructions</a> I posted on StackOverflow for screenshots and a walk through. You need to add --minify to the Run config in Manage Launches.<br />
<br />
You will see a significant reduction in size after you minify.<br />
<br />
<h2>
Make sure all dart:mirrors imports use @MirrorsUsed</h2>
<br />
Dart's reflection capabilities come from the <a href="https://api.dartlang.org/docs/channels/stable/latest/dart_mirrors.html">mirrors library</a>. Mirrors are really powerful, but they introduce challenges to dart2js's tree shaking abilities. Normally, dart2js can look at the entire app and deduce what code is required to run the app. However, as of the time of this writing, mirrors (due to their API design and highly dynamic nature) more-or-less disable dart2js's tree shaking.<br />
<br />
Enter <a href="https://api.dartlang.org/docs/channels/stable/latest/dart_mirrors/MirrorsUsed.html">@MirrorsUsed</a>, a <a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html#ch02-metadata">metadata annotation</a>, which explicitly states what parts of the program are reflected. Tools like dart2js can use @MirrorsUsed to re-enable tree shaking.<br />
<br />
<i>Note: by the time you read this article, @MirrorsUsed might be deprecated or removed. The engineers are working on better ways to deduce how mirrors are used in the code. As of the time of this writing, @MirrorsUsed is the tool we have to gain control over the output size when mirrors are used.</i><br />
<br />
If your app imports dart:mirrors and you compile it with dart2js, you might see a warning like this:<br />
<br />
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">sethladd</span>:~/dart/test/web$ dart2js test.dart </span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2">test.dart:1:1: </span>Hint: 6379 methods retained for use by dart:mirrors out of 7873 total methods (81%).</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">import 'dart:html';</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2">mylibrary.dart:3:1: </span>Info: This import is not annotated with @MirrorsUsed, which may lead to unnecessarily large generated code.</span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;">Try adding '@MirrorsUsed(...)' as described at https://goo.gl/Akrrog.</span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;">import 'dart:mirrors';</span></div>
<br />
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;">^^^^^^^^^^^^^^^^^^^^^^</span></div>
<div class="p4">
<br /></div>
<div class="p4">
If you see "This import is not annotated with @MirrorsUsed", then the generated JavaScript is probably too big. My sample app, which uses UUID, HTML, and mirrors, compiles out to > 4MB. Yikes. But we can fix it!</div>
<div class="p4">
<br /></div>
<div class="p4">
At the import of dart:mirrors, add a @MirrorsUsed and specify what the app reflects on. You can specify:</div>
<div class="p4">
</div>
<ul>
<li>targets: one or more names of libraries or classes</li>
<li>metaTargets: one or more classes used as metadata to indicate reflectability</li>
</ul>
<div>
For example:</div>
<div>
<br /></div>
<br />
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">library</span> mylib;</span></div>
<div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;">@MirrorsUsed(targets: 'mylib')</span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'dart:mirrors'<span class="s2">;</span></span></div>
<div class="p4">
<span class="s2"><br /></span></div>
<div class="p4">
All names and things (classes, functions, etc) inside of mylib will be retained for reflection.</div>
<div class="p4">
<br /></div>
<div class="p4">
From what I can tell, once dart2js sees a @MirrorsUsed, it then tree shakes and drops all targets that are not specified. So be sure to include a complete list of targets (libraries, classes, etc) that will be reflected.</div>
<div class="p4">
<br /></div>
<div class="p4">
In my test app (uuid, html, mirrors), the generated JavaScript size dropped to 400k unminified (from 4MB unminified) once I added @MirrorsUsed.</div>
<div class="p4">
<br /></div>
<div class="p4">
If the import of dart:mirrors is not under your control (e.g. you use a package that imports a package that uses dart:mirrors), you can introduce your own @MirrorsUsed annotation to override. Just introduce your own import of dart:mirrors in code that you control (e.g. in your entry point file), add @MirrorsUsed, specify targets and metaTargets, and set override: '*'.</div>
<div class="p4">
<br /></div>
<div class="p4">
As mentioned above, Dart engineers are working on making mirrors + reflection + dart2js much friendlier. We know @MirrorsUsed is hard to get right, but it's the only tool we have right now at the time of this writing.</div>
<div class="p4">
<br /></div>
<h2>
Make sure you are gzipping</h2>
<div class="p4">
<br /></div>
<div class="p4">
Of course, your web server should perform real-time compression. Be sure to account for gzip when calculating how many bits are traveling across the wire.</div>
<div class="p4">
<br /></div>
<h2>
Summary</h2>
<div class="p4">
<br /></div>
<div class="p4">
To calculate the real size over the wire, minify your app, add @MirrorsUsed if you use mirrors, and enable HTTP compression like Gzip. If you have any questions, please ask on <a href="http://stackoverflow.com/tags/dart">StackOverflow</a> or file a bug at <a href="http://dartbug.com/new">dartbug.com/new</a>. </div>
</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-91549166895780163372013-12-11T00:10:00.002-08:002013-12-11T00:10:47.796-08:00Compile-time dead code elimination with dart2jsRight before the release of Dart 1.0, the Dart team snuck in a cool new feature that helps you optimize the generated JavaScript from your Dart apps. Configuration values from the environment can be evaluated at compile time and potentially result in dead code elimination. Smaller code is faster code!<br />
<br />
As an example, let's consider the common case of logging. Debug logging is a useful tool during development and testing, but often there's no need to ship production code with debug log statements. Wouldn't it be cool if you could remove all the debug log statements before you ship to production, without having to manually delete any lines of code? Now with Dart and <i>fromEnvironment</i>, you can!<br />
<br />
Here is a small example of a log function that is useful during development, but unnecessary during production. If a DEBUG is set, the log message is printed. The code gets the compile-time constant value from the <i>String.fromEnvironment() constructor</i>. Notice the <i>const</i> qualifier, instead of <i>new</i>, as the important signal that the environment value is a <i>compile-time constant</i>. Without <i>const</i> here, the compiler doesn't know what the value is during compilation.<br />
<br />
<pre class="prettyprint">log(String msg) {
if (const String.fromEnvironment('DEBUG') != null) {
print('debug: $msg');
}
}
main() {
log('In production, I do not exist');
}
</pre>
<br />
For dart2js, you can pass values from the environment (not to be confused with "environment variables" that you might set in your shell) via the <span style="font-family: Courier New, Courier, monospace;">-D</span> command line arguments.<br />
<br />
When compiled with <span style="font-family: Courier New, Courier, monospace;">dart2js -DDEBUG=true app.dart</span>, the output includes the logging behavior:<br />
<br />
<pre class="prettyprint"> main: function() {
H.printString("debug: In the production release, I do not exist");
}
</pre>
<br />
Notice how dart2js inlined the log function into main, which is cool. Because the DEBUG value was set, dart2js knew that the <span style="font-family: Courier New, Courier, monospace;">if</span> statement inside of <span style="font-family: Courier New, Courier, monospace;">log()</span> returns true.<br />
<br />
However, if -DDEBUG is not set, the logging behavior is not included in the generated JavaScript code:<br />
<br />
<pre class="prettyprint"> main: function() {
}
</pre>
<br />
Tools like dart2js can understand how expressions that use compile-time constants resolve. Dead code is eliminated from the generated output.<br />
<br />
Strings, ints, and booleans can produce values from the environment: <a href="https://api.dartlang.org/docs/channels/stable/latest/dart_core/int.html#fromEnvironment">int.fromEnvironment</a>, <a href="https://api.dartlang.org/docs/channels/stable/latest/dart_core/String.html#fromEnvironment">String.fromEnvironment</a>, and <a href="https://api.dartlang.org/docs/channels/stable/latest/dart_core/bool.html#fromEnvironment">bool.fromEnvironment</a>. Use <i>fromEnvironment</i> with <i>const</i> to help control which code blocks make it into the generated JavaScript code.Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-75424104344783007222013-09-28T17:38:00.000-07:002014-01-20T10:52:03.669-08:00Forms, HTTP servers, and Polymer with Dart(Update of this old <a href="http://blog.sethladd.com/2013/06/forms-http-servers-and-web-components.html">Web UI post</a>. Updated as of Jan 17, 2014 and Dart 1.1.)<br />
<br />
Dart can be used on the client and the server. This post shows how to:<br />
<br />
<ul>
<li>build a form as a custom element</li>
<li>bind input fields to a Dart object</li>
<li>build a Dart HTTP server</li>
<li>handle and parse a form submit</li>
</ul>
<div>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="http://4.bp.blogspot.com/-cYtkxMP-rYw/Ukd5EYqI_II/AAAAAAAAbkQ/e_pFosam_mg/s640/Sample_app_and_Server_Rack_1_w_Horizon_Server___Flickr_-_Photo_Sharing_.png" height="313" width="640" /></div>
<br /></div>
<br />
<div>
For lots more Polymer.dart examples, be sure to check out the <a href="https://github.com/sethladd/dart-polymer-dart-examples">Dart Polymer Samples</a>. You can find the <a href="https://github.com/sethladd/dart-example-form-submit">code for this post</a> at my Github account.</div>
<div>
<h2>
Step 1: Install the packages</h2>
<div>
Open up pubspec.yaml (used by the pub package manager) and add the dependencies for Polymer.dart and http_server.</div>
<div>
<br /></div>
<pre class="prettyprint"><code>name: parse_form_submit
description: A sample Polymer application
dependencies:
polymer: any
http_server: any
</code></pre>
<br />
<div>
<a href="https://github.com/sethladd/dart-example-form-submit/blob/master/pubspec.yaml">Source for pubspec.yaml</a>.</div>
<div>
<h2>
Step 2: Create the model class</h2>
<div>
This class is for the "business object". It is bound to the form, so we make its fields observable.</div>
<div>
<br /></div>
<pre class="prettyprint"><code>library models;
import 'package:polymer/polymer.dart';
class Person extends Object with Observable {
@observable String firstName;
@observable String lastName;
@observable int age = 0;
}
</code></pre>
<div>
<br /></div>
<div>
<a href="https://github.com/sethladd/dart-example-form-submit/blob/master/web/models.dart">Source for models.dart</a>.</div>
<div>
<h2>
Step 3: Create the custom element HTML</h2>
<div>
<br /></div>
<div>
This custom element, brought to you by Polymer.dart, wraps the form and makes it easy to reuse. The <template> tag contains the structure of this custom element. The submit event runs the doSubmit() method of this custom component (see in the next step).</div>
<div>
<br /></div>
<div>
A Dart class, linked by the <script> tag, backs this custom element.</div>
<div>
<br /></div>
<pre class="prettyprint"><code><!DOCTYPE html>
<polymer-element name="person-form" attributes="action">
<template>
<div id="message"></div>
<form method="post" on-submit="{{doSubmit}}">
<div>
First name: <input type="text" value="{{person.firstName}}" name="firstName">
</div>
<div>
Last name: <input type="text" value="{{person.lastName}}" name="lastName">
</div>
<div>
Age: <input type="number" value="{{person.age | asInteger}}" name="age">
</div>
<div>
<input type="submit">
</div>
</form>
</template>
<script type="application/dart" src="person_form.dart"></script>
</polymer-element>
</code></pre>
<div>
<br /></div>
<div>
<a href="https://github.com/sethladd/dart-example-form-submit/blob/master/web/person_form.html">Source for person_form.html</a>.</div>
<div>
<h2>
Step 4: Create the custom element Dart code</h2>
<div>
If a custom element needs custom behavior, you can implement it with Dart. Each custom element tag you use on the page has an instance of its corresponding class. Here, the PersonForm class goes with the <person-form> tag.</div>
<div>
<br /></div>
<div>
The doSubmit() method is called when the form is submitted (see the on-submit binding from Step 3).</div>
<div>
<br /></div>
<div>
In this case, we disable the default behavior of form submission so we don't incur a page reload. We use HttpRequest to submit the form data, and update a div inside our custom element with the response text.</div>
<div>
<br /></div>
<pre class="prettyprint"><code>import 'package:polymer/polymer.dart';
import 'models.dart';
import 'dart:html';
import 'ui_filters.dart' show StringToInt;
import 'package:polymer_expressions/filter.dart' show Transformer;
@CustomTag('person-form')
class PersonForm extends PolymerElement {
final Person person = new Person();
PersonForm.created() : super.created();
@published String action;
doSubmit(Event e, var detail, Node target) {
e.preventDefault();
FormElement form = target as FormElement;
form.action = action;
HttpRequest.request(action,
method: form.method,
sendData: new FormData(form))
.then((HttpRequest req) {
shadowRoot.querySelector('#message').text = req.responseText;
})
.catchError((e) => print(e));
}
// Filters and transformers can be referenced as fields.
final Transformer asInteger = new StringToInt();
}
</code></pre>
<div>
<br /></div>
<div>
<a href="https://github.com/sethladd/dart-example-form-submit/blob/master/web/person_form.dart">Source for person_form.dart</a>.</div>
<div>
<h2>
Step 5: Import and use the custom element</h2>
<div>
Use a <link> tag to import the custom element. You must also export polymer/init.dart, which helps to initialize the app.</div>
<div>
<div>
<br /></div>
<pre class="prettyprint"><code><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample app</title>
<link rel="stylesheet" href="parse_form_submit.css">
<link rel="import" href="person_form.html">
<script type="application/dart">export 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js"></script>
</head>
<body>
<h1>Forms</h1>
<person-form action="http://localhost:8888/submit"></person-form>
</body>
</html>
</code></pre>
<div>
<br /></div>
<div>
<a href="https://github.com/sethladd/dart-example-form-submit/blob/master/web/index.html">Source for index.html</a>.</div>
<div>
<h2>
Step 6: Write the server</h2>
<div>
Dart's dart:io library help you write command-line and server-side application. We use the http_server package for additional HTTP server functionality. The server listens for POST requests, parses the form data into a Map, enable CORS headers (so pages from any origin can submit to this server), and sends back a string version of the original form data.</div>
<div>
<br /></div>
<pre class="prettyprint"><code>import 'dart:io';
import 'package:http_server/http_server.dart';
echo(HttpRequest req) {
print('received submit');
HttpBodyHandler.processRequest(req).then((HttpBody body) {
print(body.body.runtimeType); // Map
req.response
..headers.add('Access-Control-Allow-Origin', '*')
..headers.add('Content-Type', 'text/plain')
..statusCode = 201
..write(body.body.toString())
..close();
});
}
main() {
HttpServer.bind('0.0.0.0', 8888).then((HttpServer server) {
print('Server is running');
server.listen((HttpRequest req) {
if (req.uri.path == '/submit' && req.method == 'POST') {
echo(req);
}
});
});
}
</code></pre>
<div>
<br /></div>
<div>
<a href="https://github.com/sethladd/dart-example-form-submit/blob/master/bin/server.dart">Source for server.dart</a>.</div>
<div>
<br /></div>
<div>
<h2>
Summary</h2>
<div>
Ta da! You've just used Dart to create a live, data-bound form and wrapped it up in a web component. Then, you wrote a Dart server to parse the form data and return a simple response. Be sure to checkout the <a href="https://github.com/sethladd/dart-example-form-submit">Github repo for this post</a> for all the code. Is this the best we can do? Probably not, you probably want a more full-featured server-side framework. There are a few in pub.dartlang.org for you to explore.</div>
<div>
<br /></div>
<h2>
Learning more</h2>
<div>
To learn more about Dart, try these resources:</div>
<div>
<ul>
<li><a href="https://www.dartlang.org/docs/tutorials/">Dart tutorials</a></li>
<li><a href="http://g.co/dartisans">Dartisans community on G+</a></li>
<li><a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html">Dart language tour</a></li>
<li><a href="https://www.dartlang.org/articles/">Dart articles</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-68150482532853540042013-09-15T14:37:00.003-07:002013-09-16T02:08:48.651-07:00JavaZone Report. Spoiler: Awesome.I had the pleasure of presenting <a href="http://www.dartlang.org/">Dart</a> and Web Components at <a href="http://jz13.java.no/">JavaZone 2013</a> in Oslo, Norway, and I'm so very happy I had the chance. The audience was clearly interested in Dart, the organizers are truly professional and welcoming, the crowd was friendly, the A/V setup was top-notch, and the logistics were easy.<br />
<br />
JavaZone is produced by <a href="http://java.no/">JavaBin</a>, a large network of Java user groups across Norway. I believe this was the 12th or 13th year for JavaZone. The conference has the feel of a big happy meetup. It's chill, mostly local attendees, mostly local vendors (though I did see JetBrains and Atlassian), and approximately 2000 attendees. Don't let "meetup" fool you, this is a full conference: two days, seven concurrent tracks, professional A/V, swag, food, etc. I liked how this was a conference built by the fans, for the fans.<br />
<br />
There is continuous food during the conference. You will never go hungry during JavaZone. There was also a coffee bar serving individual drop coffees, sponsored by a local consultancy.<br />
<br />
There are seven concurrent tracks, and it's sometimes hard to decide which session to attend. Fear not, because JavaZone thought about that, too. In their overflow room, there is a giant screen showing all seven presentations at once! Pick up a headset and select the right channel for audio.<br />
<br />
<div class="g-post" data-href="https://plus.google.com/118397406534237711570/posts/UGBLu2ChAiH">
</div>
<br />
<br />
JavaZone is known for Triple-A promo videos, a great party, and a once-in-a-lifetime speaker adventure (more on that later). The organizers have a "full spectrum" (my term, not theirs) approach to creating the event.<br />
<br />
You may have seen this promo video for JavaZone 2013. It has the same quality as a Hollywood trailer. If you're a programmer of any sort, you'll probably find this funny.<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="360" src="//www.youtube.com/embed/E3418SeWZfQ" width="640"></iframe>
<br />
<br />
The JavaZone party, appropriately named AweZone, is held in a music hall. Multiple levels, multiple bands, and free for attendees. Cool fact: many band members are developers from local tech companies. They know how to rock.<br />
<br />
Traveling to JavaZone was easy: fly into OSL Oslo airport, get the airport express train straight to downtown Oslo. It takes about 20 minutes. I stayed at the Radisson Blu Park Plaza, which is across the street from the train station and next door to the event venue: Oslo Spectrum.<br />
<br />
I was lucky enough to present in the biggest room, with approximately 300 developers there to watch the talk. It's an updated presentation that Justin Fagnani and I did at Google I/O 2013, with more emphasis on the latest web components and <a href="https://www.dartlang.org/polymer-dart/">polymer.dart</a> work.<br />
<br />
If you missed it, here's the video from my talk:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="281" mozallowfullscreen="" src="//player.vimeo.com/video/74391396" webkitallowfullscreen="" width="500"></iframe> <br />
<a href="http://vimeo.com/74391396">Dart and Web Components - Scalable, Structured Web Apps</a> from <a href="http://vimeo.com/javazone">JavaZone</a> on <a href="https://vimeo.com/">Vimeo</a>.<br />
<br />
The audience was shy asking questions in front of everyone, but I had a solid crowd of developers come up to me after the talk. Many were interested in what the Angular + Dart story is. Luckily, there's an <a href="https://github.com/angular/angular.dart">Angular port for Dart</a> in the works, and the Polymer work is putting many of the concepts from Angular directly into the browser.<br />
<br />
With JavaZone such a good conference, is there anything I would changed? I was asked by one of the organizers, and I did suggest considering shorter talk times. The presentations were 60 minutes this year, but I've seen successful conferences with shorter talks (45 min, even down to 30 min).<br />
<br />
To help thank the speakers, and to help celebrate the conference, the JavaBin folks arrange an excursion called JourneyZone. About 16 total travelers left the conference after it was done and headed up north.<br />
<br />
For many of us, it was our first time in Norway, and we were no disappointed. We traveled up to the <a href="http://www.fablab.no/">MIT Fablab in Lyngen, Norway</a>.<br />
<br />
<iframe frameborder="0" height="350" marginheight="0" marginwidth="0" scrolling="no" src="https://www.google.com/maps?sll=37.06250000000001,-95.67706800000003&sspn=56.57546792736244,72.86498330404729&t=h&q=mit+fablab+lyngen&dg=opt&ie=UTF8&hq=mit+fablab+lyngen&hnear=&radius=15000&cid=4367983835179383350&ll=69.472969,20.214844&spn=22.337324,74.707031&z=3&iwloc=A&output=embed" width="425"></iframe><br />
<small><a href="https://www.google.com/maps?sll=37.06250000000001,-95.67706800000003&sspn=56.57546792736244,72.86498330404729&t=h&q=mit+fablab+lyngen&dg=opt&ie=UTF8&hq=mit+fablab+lyngen&hnear=&radius=15000&cid=4367983835179383350&ll=69.472969,20.214844&spn=22.337324,74.707031&z=3&iwloc=A&source=embed" style="color: blue; text-align: left;">View Larger Map</a></small>
<br />
<br />
We saw the northern lights, hiked a glacier, zoomed down a zip line, rappelled down a cliff, relaxed in a sauna, hung out with super cool people, and more. Here's the glacier we hiked across:<br />
<br />
<div class="g-post" data-href="https://plus.google.com/118397406534237711570/posts/N9bfpc1iVf5">
</div>
<br />
<!-- Place this tag where you want the widget to render. -->
<br />
<div class="g-post" data-href="https://plus.google.com/118397406534237711570/posts/AKbGADp7Xck">
</div>
<br />
In summary, Dart was seemingly well received by the JavaZone audience, the JavaZone conference is first rate, and JourneyZone was spectacular. Thanks to all the organizers, and thanks to all those who attended my talk. Hope to see you again next year!Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-16466013614485123982013-09-05T18:04:00.003-07:002013-09-05T18:18:20.236-07:00You complete me, unless you already have a Dart futureDart Protip: if you already have an instance of Future, you probably don't need a Completer. Simply return the last Future.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="http://4.bp.blogspot.com/-96p-Dv4Mtpw/UikrkngSzeI/AAAAAAAAbR8/Qwbn1AhxLBg/s1600/jerry_maguire.png" /></div>
<br />
<br />
If you find yourself using Completers inside of Futures, like this:<br />
<br />
<pre class="prettyprint"><code>
// NOT recommended.
Future doStuff() {
Future future = someAsyncProcess();
Completer<bool> completer = new Completer();
future.then((msg) {
bool result = msg.result as bool;
completer.complete(result);
});
return completer.future;
}
</bool></code></pre>
<br />
<br />
then I'm happy to report there's a better way. Dart's Futures chain, so you can do this instead:<br />
<br />
<pre class="prettyprint"><code>
// Recommend.
Future doStuff() {
return someAsyncProcess().then((msg) => msg.result);
}
</code></pre>
<br />
<br />
The last Future in a chain can return another Future, or simply a value. It's always a good idea to return a Future from a function that uses a Future. This way, the caller knows when the method finished its async work, and can properly handle potential errors.<br />
<br />
Completers are great for bridging a callback-based API with a Future-based API. For example, suppose your database driver doesn't use Futures, but you need to return a Future. Try this code:
<br />
<pre class="prettyprint"><code>
// A good use of a Completer.
Future doStuff() {
Completer completer = new Completer();
runDatabaseQuery(sql, (results) {
completer.complete(results);
});
return completer.future;
}
</code></pre>
<br />
To learn more about Futures, read <a href="https://www.dartlang.org/articles/using-future-based-apis/">Using Future Based APIs</a>. To step up your game, read <a href="https://www.dartlang.org/articles/futures-and-error-handling/">Futures and Error Handling</a>.<br />
<br />
Enjoy!Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-3364073134905972712013-07-23T01:00:00.002-07:002013-07-31T07:45:16.271-07:00Polymer and Dart: A First LookIn which I try the new polymer.dart, a build.dart file is deleted, and a template springs to life.<br />
<br />
(This post heavily inspired by Nik Graf's great "<a href="http://www.nikgraf.com/post/55711411091/getting-started-with-polymer-dart">Getting started with Polymer.dart</a>" post.)<br />
<br />
<h2>
The web is evolving</h2>
<br />
Developers take notice! Coming soon: actual encapsulation, real live data binding, even re-usable components! The Web Components family of specifications is on their way to a browser near you, but the standardizations process is lengthy. Fear not, web engineers are working hard to bring these new capabilities to you today.<br />
<br />
The <a href="http://www.polymer-project.org/">Polymer project</a>, a new type of library for the web, is built on top of Web Components, and designed to leverage the evolving web platform on modern browsers. Most importantly, the Polymer project has code that you can use <i>today</i> (to be fair, it's pre-alpha, but much of it works if you are brave).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img border="0" src="http://3.bp.blogspot.com/-BDddgOqtNBc/Ue4llRV0BiI/AAAAAAAAYqw/tQJAls-PToY/s1600/Screen+Shot+2013-07-22+at+11.42.57+PM.png" style="margin-left: auto; margin-right: auto;" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The Polymer project is more than just polyfills.</td></tr>
</tbody></table>
<br />
<h2>
Web UI is evolving</h2>
<br />
The Dart project, to more closely align with emerging web specifications, is building polymer.dart, the next evolution of Web UI. In the <a href="http://news.dartlang.org/2013/07/introducing-polymer-dart.html">announcement</a>, it was mentioned that Web UI will be sunset in favor of polymer.dart. While Web UI will be around for some time, new work focuses on polymer.dart.<br />
<br />
From the <a href="http://www.polymer-project.org/faq.html#dart">Polymer project FAQ</a>:<br />
<br />
<blockquote class="tr_bq">
<b>How is polymer.dart related to Polymer?</b><br />
polymer.dart is a Dart port of Polymer created and maintained by the Dart team. The Dart team is collaborating with the Polymer team to ensure that polymer.dart elements and polyfills are fully compatible with Polymer.</blockquote>
<br />
Luckily for developers, polymer.dart and Web UI are fairly similar. It shouldn't be too much work to port a Web UI app to polymer.dart. We anticipate docs and examples to help developers with the transition.<br />
<br />
There are many good reasons for this evolution:<br />
<br />
<ul>
<li>closer alignment to another team building out support for Web Components</li>
<li>eventual elimination of the build/compile step required by Web UI</li>
<li>better interop between JavaScript components and Dart components</li>
<li>Dart developers get faster access to critical polyfills like Web Animations and Pointer Events</li>
</ul>
<br />
There's no rush for you to upgrade. Polymer.dart is very new, and it will be some time before it is feature compatible with Web UI. So, stick with Web UI if you're building production apps and wait for the transition guides to appear.<br />
<br />
<h2>
Aside: What about Angular?</h2>
<br />
Many developers want to know what's up with Angular, and how it all relates. I can't speak for the Angular project, but this <a href="https://groups.google.com/forum/#!msg/polymer-dev/4RSYaKmbtEk/uYnY3900wpIJ">post</a> to the Polymer mailing list from Miško Hevery should shed some light:<br />
<br />
<blockquote class="tr_bq">
We're in early stages of designing Angular 2.0, but some of our goals are: </blockquote>
<blockquote class="tr_bq">
- Angular will use the underlying web platform features available to it (e.g. Node.bind, template integration, Custom Elements, etc...) </blockquote>
<blockquote class="tr_bq">
- Web Components (Polymer, Ember, or any other framework/library) will work seamlessly within Angular apps and directives. </blockquote>
<blockquote class="tr_bq">
- Components written in Angular will export to Web Components (to be used by Polymer, Ember, or any other framework/library) . </blockquote>
<blockquote class="tr_bq">
We're working actively with the MDV, Web Components, and Polymer teams to make sure that our approaches remain compatible as all these projects evolve (and they will still evolve). </blockquote>
<blockquote class="tr_bq">
-- Misko & the Angular team</blockquote>
I look forward to frameworks like Angular using the foundation of Web Components.<br />
<br />
<h2>
Hello, Polymer.dart</h2>
<br />
Let's give polymer.dart a try! For this first look, we'll build a very simple "Hello, World" example that shows off how to install polymer.dart, use the <template> tag, and bind a model.<br />
<br />
<h3>
Installing the polymer package</h3>
<br />
Add the <a href="http://pub.dartlang.org/packages/pub">polymer pub package</a> to your pubspec.yaml. For this simple example, this is the only package that you'll need to explicitly declare:<br />
<code></code><br />
<pre class="prettyprint"><code>name: polymer_first_look
dependencies:
<b>polymer: any</b>
</code></pre>
<br />
<br />
<h3>
Creating the template</h3>
<br />
Add a <template> element to the web/index.html file. A <template> is an inert DOM fragment. It's valid HTML, but not activated by the page. You can manually clone the element and insert the clone into the page. Or, even better, you can use Model-Driven Views (MDV) to bind data to the template. The binding of data to the template activates the template, thus inserting it into the page.<br />
<br />
The <i>bind</i> attribute on the <template> element states that the template activates (is cloned and inserted into the DOM) when data is bound to the template. The bind attribute comes from MDV.<br />
<br />
The {{ and }} mark data binding between a field and some text. The field comes from the model data objects bound to the template. The {{ and }} are removed and replaced with the value of the field.<br />
<br />
<pre class="prettyprint"><code><!DOCTYPE html>
<html>
<head>
<title>index</title>
</head>
<body>
<b><template id="tmpl" bind>
<p>Hello {{msg}}</p>
</template></b>
<script type="application/dart" src="index.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
</code></pre>
<br />
<br />
<h3>
Binding the data</h3>
<br />
The application, in web/index.dart, creates a single model object (a plain Dart object) and then attaches it to the <template> element from the page.<br />
<br />
We must import the MDV package and initialize it before binding can have any effect.<br />
<br />
<br />
<pre class="prettyprint"><code>import 'dart:html';
import 'package:mdv/mdv.dart' as mdv;
class Message {
String msg;
}
main() {
<b> mdv.initialize();
var message = new Message()..msg = 'world';
query('#tmpl').model = message;</b>
}
</code></pre>
<br />
<br />
One big difference between Web UI and Polymer.dart: you must explicitly bind your model to the template. Web UI worked with code generation and lexical scope. Polymer.dart, because it comes from a JavaScript-influenced Polymer project, does not have code generation or lexical scope.<br />
<br />
And that's it! There's no need for a build.dart with this simple test app. This works in Dartium and via dart2js. (Note: dart2js + polymer.dart output size is quite large, but follow <a href="http://dartbug.com/11524">dartbug.com/11524</a> for a fix.)<br />
<br />
<h2>
Next steps</h2>
<br />
<ul>
<li>Join the <a href="https://groups.google.com/a/dartlang.org/forum/#!forum/web-ui">web-ui@</a> and <a href="https://groups.google.com/forum/?fromgroups=#!forum/polymer-dev">polymer-dev@</a> mailing lists.</li>
<li>File bugs on polymer.dart at <a href="http://dartbug.com/new">dartbug.com/new</a>.</li>
<li>Read all about <a href="http://www.polymer-project.org/">Polymer</a>.</li>
<li>Have fun! :)</li>
</ul>
<div>
This is just the beginning, there's a lot to explore with polymer.dart. I'm looking forward to more experiments as I learn about this brave new world.</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-19398394178790957452013-07-19T14:23:00.000-07:002013-07-19T14:23:06.051-07:00Two-way data binding with Web UI custom elements and models<span style="font-size: large;">Preface</span><br />
<br />
This could very well be my last Web UI post! The <a href="http://news.dartlang.org/2013/07/introducing-polymer-dart.html">Dart team announced they started on polymer.dart</a>, a port of the <a href="http://www.polymer-project.org/">Polymer project</a> to Dart. Polymer.dart is the next evolution of Web UI. Luckily, the concepts are mostly the same and the syntax is mostly the same, because Web UI is also an implementation of the Web Components.<br />
<br />
So why am I still writing about Web UI? Lots of people have asked about two-way data binding between a component and a model, so I wanted to have a record of this functionality. Also, what's described below isn't too different than how polymer.dart works (and we'll cover it in a future post).<br />
<br />
I look forward to the glorious new world of coordinated polyfills and new custom elements. Go go polymer.dart and the Polymer project!<br />
<br />
<span style="font-size: large;">Intro</span><br />
<br />
The Dart class that backs a custom element can itself also take part in two-way data binding. This post explores how to bind a model object to a web component property. If a model's field changes, the custom element's property changes. If the custom element's property changes, the model's field changes.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="212" src="http://3.bp.blogspot.com/-pQ1Yw5JtBrE/UembRqdbNwI/AAAAAAAAYqI/t6Y36kOfOE0/s640/Web+UI+two-way+data+binding.png" width="640" /></div>
<br />
(Note: the same technique, with different syntax, should work in polymer.dart as well.)<br />
<br />
The demo app contains:<br />
<ul>
<li>A model for a Switch</li>
<li>A custom element for a Toggle</li>
</ul>
<div>
<span style="font-size: large;">The goal</span><br />
<br />
When the switch is flipped, we want to flip the toggle. When the toggle is flipped, we want to flip the switch. Both Switch and Toggle don't know about each other. Let's connect them!</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Defining the Switch model</span></div>
<div>
<br /></div>
<div>
The Switch class is a standard business model, and it's marked as @observable.</div>
<div>
<br /></div>
<div>
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> library toggle;
import 'package:web_ui/web_ui.dart';
<u><b>@observable</b></u>
class Switch {
String flipped = 'off';
}
</code></pre>
<br />
<span style="font-size: large;">Defining the ToggleComponent</span><br />
<br /></div>
<div>
The Toggle custom element has two files: the <element> definition and the Dart class.<br />
<br />
The Dart class for ToggleComponent is also @observable, and has a single field: state.<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> library turn_off;
import 'package:web_ui/web_ui.dart';
<u><b>@observable</b></u>
class ToggleComponent extends WebComponent {
String state = 'On';
void toggle() {
if (state == 'On') {
state = 'Off';
} else {
state = 'On';
}
}
}
</code></pre>
<br />
The custom component renders a button, and displays the state field. The button changes the state field by calling the toggle() method.<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <!DOCTYPE html>
<html>
<body>
<element name="toggle" constructor="ToggleComponent" extends="div">
<template>
<button on-click="toggle()">Toggle</button>
<p>Inside the component: The toggle is {{state}}</p>
</template>
<script type="application/dart" src="toggle_component.dart"></script>
</element>
</body>
</html>
</code></pre>
<br />
<span style="font-size: large;">Initializing and controlling the switch</span><br />
<br />
Inside the main app, create a single Switch instance and two methods that turn the switch on or off.<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> library app;
import 'dart:html';
import 'package:web_ui/web_ui.dart';
import 'switch.dart';
Switch lightSwitch = new Switch();
turnSwitchOn() {
lightSwitch.flipped = 'On';
}
turnSwitchOff() {
lightSwitch.flipped = 'Off';
}
void main() {
}
</code></pre>
<br />
<span style="font-size: large;">Connecting the Switch to the Toggle</span><br />
<br />
Web UI supports two-way binding on custom elements with its <i>bind-foo</i> attribute, where foo is the name of a property on the custom element's backing class.<br />
<br />
In this example, we bind toggle's state to switch's flipped field. This code comes from <a href="https://github.com/sethladd/dart-web-components-tests/blob/master/web/bind_component_field_to_model_field/app.html">app.html</a>:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <u><b><div is="toggle" bind-state="lightSwitch.flipped"></div></b></u>
<p>The switch is set to {{lightSwitch.flipped}}</p>
<p>
<button on-click="turnSwitchOn()">Turn Switch On</button>
<button on-click="turnSwitchOff()">Turn Switch Off</button>
</p>
</code></pre>
<br />
<span style="font-size: large;">Live demo</span><br />
<br />
<iframe height="200" src="http://sethladd.github.io/dart-web-components-tests/deploy/bind_component_field_to_model_field/out/bind_component_field_to_model_field/app.html" width="680"></iframe>
</div>
<br />
Press the Toggle button (the custom component) and it runs toggle() which flips the ToggleComponent's internal state field. Because state is bound to lightSwitch.flipped, the switch is also flipped. Pretty cool!<br />
<br />
<span style="font-size: large;">Summary</span><br />
<br />
You can bind a component's property to a model's field. This works today with Web UI's <i>bind-foo</i> attribute, and should work with polymer.dart's <i>foo="{{model.field}}"</i> attribute.<br />
<br />
Meanwhile, Web UI is being phased out in favor of polymer.dart. Both libraries have the same goal: provide excellent implementations of modern and emerging web specifications and to help developers build amazing modular and beautiful web apps!Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-61559898682233713822013-07-19T06:00:00.000-07:002013-07-19T06:00:14.513-07:00Dart and Sencha Touch for Mobile Web Apps<div>
You can use <a href="http://www.dartlang.org/articles/js-dart-interop/">Dart's JS-Interop</a> to integrate Dart code into your existing <a href="http://www.sencha.com/products/touch">Sencha Touch</a> application. This allows you to take advantage of Sencha Touch's mobile-first framework and Dart's productivity, language, and libraries.</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Preface</span></div>
<div>
<br /></div>
<b>Sencha Touch is a full-featured JavaScript framework for mobile web apps</b>. It supports layouts for multiple devices, touch, lots of widgets, models, a resource framework, and more. I've used Ext JS (a cousin of Sencha Touch) in a previous job, and was quite happy.<br />
<div>
<br /></div>
<div>
I'm also quite happy with Dart, the new scalable web programming platform from Google. <b>Dart compiles to JavaScript, and even interoperates with JavaScript.</b> It's a new language, libraries, package manager, VM (for client AND server apps), and rich tools. I feel really productive in Dart.</div>
<div>
<br /></div>
<div>
I've never used Sencha Touch, so my first question was: <b>how do I insert Dart into an existing Sencha Touch application?</b></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="640" src="http://2.bp.blogspot.com/-KQRShKnUedg/UeikodmI3FI/AAAAAAAAYow/kJGrFbGMK0c/s640/download-2.png" width="380" /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Getting Sencha Touch</span></div>
<div>
<br /></div>
<div>
Sencha already has great docs, so I won't repeat them here. This post assumes you have a Sencha Touch app already, but if not, check out <a href="http://www.sencha.com/products/touch">http://www.sencha.com/products/touch</a>. Make sure to download both the SDK and the sencha command line utility. I needed both to get started.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="409" src="http://3.bp.blogspot.com/-WG_-WeZFbiI/Ueinzg7vPEI/AAAAAAAAYpI/KwElvB-DsDE/s640/Screen+Shot+2013-07-18+at+10.40.31+PM.png" width="640" /></div>
<br /></div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Getting Dart</span></div>
<div>
<br /></div>
<div>
Installing Dart is super easy. The best way is to <a href="http://www.dartlang.org/tools/editor/">install Dart Editor</a>, which includes the editor, Dart SDK, and Dartium (Chromium + an embedded Dart VM). Even if you don't intent to use the editor, you almost certainly want Dartium for easy development testing (think: edit, reload, there is no step three).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="173" src="http://www.dartlang.org/logos/dart-logo-wordmark.png" width="400" /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
If you are new to Dart, might I recommend the <a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html">Language Tour</a> and the <a href="http://www.dartlang.org/docs/tutorials/">Tutorials</a>.</div>
<br />
<br />
<span style="font-size: large;">The Setup</span><br />
<br />
There are effectively two apps in play:<br />
<br />
<ol>
<li>The Sencha Touch app</li>
<li>The Dart app</li>
</ol>
<div>
Both apps need to fully initialize and load (possibly loading multiple scripts) and there's no guarantee that one app will load before the other.</div>
<div>
<br /></div>
<div>
The Dart app needs a way get a handle on the Sencha App, but only <i>after</i> the Sencha app is loaded and initialized. This scheme needs to work in both Dartium (JS and Dart VM) and across the web (via dart2js, which compiles Dart into JavaScript).</div>
</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Modify your Sencha Touch app</span></div>
<div>
<br /></div>
<div>
<i>(Note: I'm a Sencha Touch n00b, so maybe there's a better way. Please let me know in the comments.)</i></div>
<div>
<br /></div>
<div>
This isn't pretty, but here's what I did:</div>
<div>
<br /></div>
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var senchaLaunchComplete = false;
Ext.application({
// ....
launch: function() {
// ...
senchaLaunchComplete = true;
},
});
</code></pre>
<br />
Notice I added a global "senchaLaunchComplete" variable that flips to <i>true</i> when the launch is complete. Again, not proud of this, and I'd like to learn more about how Sencha initializes. I can't fire a postMessage event from the Sencha App because it might get lost before the Dart app has a chance to load and initialize.<br />
<br />
Ideas welcome, but let's move on, shall we? :)<br />
<br />
<span style="font-size: large;">Waiting for the Sencha app to load</span><br />
<br />
The Dart app starts by repeatedly polling the <i>senchaLaunchComplete</i> variable from JavaScript. Dart uses JS-Interop to reach into the JavaScript world. JS-Interop works in both Dartium and when compiled with dart2js.<br />
<br />
All Dart programs start with a <i>main()</i> function. This makes it very easy to understand where your program actually starts running. Inside main() I setup a <i>Timer</i> to check the variable. (Again, sorry for the ugly code.)<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">
import 'dart:html';
import 'dart:async';
import 'package:js/js.dart' as js;
main() {
// TODO: make this better
new Timer.periodic(const Duration(milliseconds: 100), (Timer t) {
if (js.context.senchaLaunchComplete) {
initDart();
t.cancel();
}
});
}
</code></pre>
<br />
<br />
When <i>senchaLaunchComplete</i> is true, <i>initDart()</i> runs and the timer stops. The <i>js.context</i> is a handle into the JavaScript side of the world.<br />
<br />
<span style="font-size: large;">Adding a button and panel with Dart</span><br />
<br />
Now that both apps are loaded, and initialized, Dart code can add new objects to the Sencha Touch app. Let's add a new panel, which contains some text and a button.<br />
<br />
Sencha Touch apps can be declared with JSON, or imperatively constructed. I show both methods below. Remember, everything that follows is Dart code:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> initDart() {
// Grab the app's main panel
var mainPanel = js.context.Ext.Viewport.items.getAt(0);
// You can create a new object imperatively using a Proxy
var button = new js.Proxy(js.context.Ext.Button)
..setText('Click Me')
..setHandler(new js.Callback.many((b, e, _, __) {
// Respond to clicks with callbacks
js.context.Ext.Msg.alert('Success!', 'This is a Dart function, run from JavaScript.');
}));
// You can also create objects declaratively using ExtJS style.
var dartPanel = js.map({
'title': 'From Dart',
'iconCls': 'star',
'html': 'Hello from Dart! This panel was created from Dart code.',
'items': [button]
});
// Add the panel from Dart land into JS land
mainPanel.add(dartPanel);
}
</code></pre>
<br />
The main panel was constructed by the main Sencha Touch app over in JavaScript land. We get a handle to the main panel via JS-Interop and the js.context.<br />
<br />
Use <i>js.Proxy</i> to construct a new JavaScript object and get its reference. In the code above, a new <i>Ext.Button</i> is created from Dart, and configured. The double-dot syntax (..) is <i>method cascades</i>: <a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html#classes">https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html#classes</a><br />
<br />
Notice a click handler is installed on the button, as a <i>js.Callback</i>. The callback can be fired multiple times. When the button is clicked, a new <i>Ext.Msg.alert</i> is displayed.<br />
<br />
The new panel is created as an example of Sencha's declarative configuration. The <i>js.map</i> is an efficient way to convert a Dart map into a JavaScript object. Notice how the Dart map contains a direct reference to the button (a Proxy object).<br />
<br />
The new panel, which contains the button, is then added to the main panel. This combines the two worlds.<br />
<br />
<span style="font-size: large;">Screenshots</span><br />
<br />
The star button comes from Dart. The home button comes for JavaScript. They basically are hugging! :)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-hp3G4qK_8B8/UeiwXd2y8WI/AAAAAAAAYpY/cjipQDwVpn0/s1600/framed_Screenshot_2013-07-18-22-03-06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="http://1.bp.blogspot.com/-hp3G4qK_8B8/UeiwXd2y8WI/AAAAAAAAYpY/cjipQDwVpn0/s640/framed_Screenshot_2013-07-18-22-03-06.png" width="382" /></a></div>
<br />
When the button is clicked, it calls a Dart function. How cool!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-bCth_onM75I/UeiwkvkuMHI/AAAAAAAAYpg/dP45fUkaei8/s1600/framed_Screenshot_2013-07-18-22-03-10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="http://3.bp.blogspot.com/-bCth_onM75I/UeiwkvkuMHI/AAAAAAAAYpg/dP45fUkaei8/s640/framed_Screenshot_2013-07-18-22-03-10.png" width="382" /></a></div>
<br />
<br />
<span style="font-size: large;">All the code (and details)</span><br />
<br />
The code for a sample Sencha Touch + Dart app is available here: <a href="https://github.com/sethladd/dart-sencha-touch-demo">https://github.com/sethladd/dart-sencha-touch-demo</a>. You'll need the sample code to see how a Dart application is arranged, and how to include both the Sencha JavaScript files and the Dart files. Specifically, check out <a href="https://github.com/sethladd/dart-sencha-touch-demo/blob/master/web/index.html">https://github.com/sethladd/dart-sencha-touch-demo/blob/master/web/index.html</a><br />
<br />
<span style="font-size: large;">What's next?</span><br />
<br />
This small demo simply shows how to insert some Dart logic into an existing Sencha Touch app. However, Sencha Touch is quite full featured, and there are more areas to explore. For example, how to interact with a Sencha model from Dart? How to create a Dart class and use it as a Sencha model? Good topics for future posts!<br />
<br />
<span style="font-size: large;">Summary</span><br />
<br />
You can extend an existing Sencha Touch app with Dart with Dart's JS-Interop. If you use Sencha Touch for your mobile HTML5 web apps, try using Dart's language, libraries, and tools as you add new features to your app. Go forth and build awesome mobile-first web apps!Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-67109245834826416512013-06-12T15:16:00.002-07:002013-06-12T15:16:42.881-07:00Create unified interfaces across dart:io and dart:htmlDart runs on the client, thanks to dart:html, and on the command line, thanks to dart:io. However, like oil and water, those two libraries just don't mix. Your web apps can't use dart:io, and your server apps can't use dart:html. Normally, this isn't a problem, because the two different targets are oh so very different. However, some concepts are common, such as Web sockets or HTTP requests. Wouldn't it be nice to have a unified interface to Web sockets that works with either dart:io or dart:html? I'll spare you the suspense: Yes!<div>
<br /></div>
<div>
This post shows you one strategy to design a high-level interface for functionality that exists in both dart:io and dart:html. While the Dart team has the concept of configurability on their radar, not much concrete action has happened. In the meantime, try this strategy and you too can experiment with unifying interfaces and APIs. Code reuse FTW!</div>
<div>
<br /></div>
<div>
(This post was inspired by Mark Bennett's <a href="https://plus.google.com/104431949275766772757/posts/2zqWy1RcKi6">original question</a> who is trying to build a more unified Web Socket interface.)</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Step 1: Create a library and an interface</span></div>
<div>
<br /></div>
<div>
Design the interface that unifies something from dart:html and dart:io.</div>
<div>
<br /></div>
<div>
<pre style="border: 0px; padding: 0px;"><div class="line" id="LC1" style="border: 0px; margin: 0px; padding: 0px 0px 0px 10px;">
<span style="color: #333333; font-family: Consolas, Liberation Mono, Courier, monospace;"><span style="font-size: 12px; line-height: 18px;"><b>library shared;
abstract class BaseFoo {
common();
}</b></span></span></div>
</pre>
</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Step 2: Implement the interface for dart:html</span></div>
<div>
<br /></div>
<div>
In another library, implement the interface with dart:html:</div>
<div>
<br /></div>
<div>
<pre style="border: 0px; padding: 0px;"><div class="line" id="LC1" style="border: 0px; margin: 0px; padding: 0px 0px 0px 10px;">
<span style="color: #333333; font-family: Consolas, Liberation Mono, Courier, monospace;"><span style="font-size: 12px; line-height: 18px;"><b>library html_thing;
import 'dart:html';
import 'shared_interface.dart';
class Foo extends BaseFoo {
common() {
print('from html');
}
}</b></span></span></div>
</pre>
</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Step 3: Implement the interface for dart:io</span></div>
<div>
<br /></div>
<div>
In another library, implement the interface with dart:io.</div>
<div>
<br /></div>
<div>
<pre style="border: 0px; padding: 0px;"><div class="line" id="LC1" style="border: 0px; margin: 0px; padding: 0px 0px 0px 10px;">
<span style="color: #333333; font-family: Consolas, Liberation Mono, Courier, monospace;"><span style="font-size: 12px; line-height: 18px;"><b>library io_thing;
import 'dart:io';
import 'shared_interface.dart';
class Foo extends BaseFoo {
common() {
print('from io');
}
}</b></span></span></div>
</pre>
</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Step 4: Package it up</span></div>
<div>
<br /></div>
<div>
All of the previous code can go into the same pub package.</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Pick a library to use</span></div>
<div>
<br /></div>
<div>
The consumer of your pub package must decide which library to import. For example, a dart:io app might look like this:</div>
<div>
<br /></div>
<div>
<pre style="border: 0px; padding: 0px;"><div class="line" id="LC1" style="border: 0px; margin: 0px; padding: 0px 0px 0px 10px;">
<span style="color: #333333; font-family: Consolas, Liberation Mono, Courier, monospace;"><span style="font-size: 12px; line-height: 18px;"><b>import 'dart:io';
import 'package:sharedinterfacetest/io_version.dart';
main() {
var foo = new Foo();
foo.common();
}</b></span></span></div>
</pre>
</div>
<div>
<br /></div>
<div>
Hope that helps! All the <a href="https://github.com/sethladd/dart-shared-interface-example">code for this example</a> is found at Github.</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-13935797916938101832013-06-11T13:40:00.001-07:002014-06-06T16:15:54.809-07:00Call JavaScript from Dart - First Look<span style="color: red; font-size: x-large;">UPDATE</span>: This article is deprecated. Dart has an improved Dart-JavaScript interop library, now included in the Dart SDK. Please <a href="https://www.dartlang.org/articles/js-dart-interop/">read about dart:js</a> and how to use it.<br />
<br />
If possible, do not use the js package that this blog post talks about. The js package will bloat your code.<br />
<br />
<br />
---<br />
<br />
<br />
<br />
You can use <a href="http://www.dartlang.org/">Dart</a> to access existing JavaScript code, thanks to the <a href="http://www.dartlang.org/articles/js-dart-interop/">Dart-JS Interop</a> package. Call JavaScript functions from Dart, send Dart callbacks to JavaScript, and more!<br />
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="http://4.bp.blogspot.com/-nyg0xW8FKp4/UbeJQncDAdI/AAAAAAAAXps/LNa77SHI1kw/s400/4594527045_c38b45d85d.jpg" height="383" width="400" /></div>
<br />
<div>
<br /></div>
<div>
The <a href="http://api.dartlang.org/">Dart core libraries</a> have a lot of functionality provided out of the box (collections, querying the DOM, dates and times, math, and more), so you can get quite far with just the Dart SDK and the many <a href="http://pub.dartlang.org/">pub packages</a>. However, there are plenty of useful JavaScript libraries that can really help enhance Dart web apps. Luckily, Dart can synchronously talk to JavaScript!</div>
<div>
<br /></div>
<div>
<span style="font-family: inherit; font-size: large;">Step 1: Install the js package</span></div>
<div>
<br /></div>
<div>
Add the following to your pubspec.yaml file:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">dependencies:</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> js: any</span></div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Step 2: Get a JavaScript library</span></div>
<div>
<br /></div>
<div>
Hugs make you feel better, let's use the hugs.js library:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">function Hug(strength) {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> this.strength = strength;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">Hug.prototype.embrace = function(length) {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> return 'Thanks, that was a good hug for ' + length + ' minutes!';</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">Hug.prototype.patBack = function(onDone) {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> onDone('All done.');</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
</div>
<div>
<br /></div>
<div>
Be sure to include the JavaScript files in your main HTML file:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><script src="hugs.js"></script></span><br />
<span style="font-family: Courier New, Courier, monospace;"><script src="packages/browser/dart.js"></script></span><br />
<span style="font-family: Courier New, Courier, monospace;"><script src="packages/browser/interop.js"></script></span></div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Step 3: Write Dart code</span></div>
<div>
<br /></div>
<div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'dart:html'<span class="s2">;</span></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'package:js/js.dart'<span class="s2"> </span><span class="s1">as</span><span class="s2"> js;</span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">void</span> <span class="s3">main</span>() {</span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> </span>// Grab the context from JS land.</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s1">var</span> context = js.<span class="s4">context</span>;</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> </span>// Use the [] notation to let --minify work.</span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> </span>// See https://github.com/dart-lang/js-interop/issues/86</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> </span>// Get a proxy to the JS object.</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s1">var</span> hug = <span class="s1">new</span> js.Proxy(<span class="s5">context</span>[<span class="s6">'Hug'</span>]);</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> </span>// Call the embrace method and pass in 10.</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s1">var</span> result = <span class="s5">hug</span>[<span class="s6">'embrace'</span>](<span class="s7">10</span>);</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> query(<span class="s6">'#output'</span>).<span class="s4">text</span> = result;</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> </span>// Call the patBack method and pass in a callback.</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s5">hug</span>[<span class="s6">'patBack'</span>](<span class="s1">new</span> js.Callback.once((msg) {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> query(<span class="s6">'#output'</span>).appendText(<span class="s6">' This just in: </span>$msg<span class="s6">'</span>);</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> }));</span></div>
<br />
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div class="p3">
<br /></div>
<div class="p3">
The hug instance is accessed via a js.Proxy object. You can even pass a Dart function as a callback to a JavaScript function!</div>
<div class="p3">
<br /></div>
<div class="p3">
<span style="font-size: large;">Summary</span></div>
<div class="p3">
<br /></div>
<div class="p3">
Use the Dart-JS interop library to access the billions of existing JavaScript libraries from Dart. Read the <a href="http://draft.blogger.com/"><span id="goog_1062396048"></span>article<span id="goog_1062396049"></span></a> for more details and see examples that use the Twitter API, Google Maps API, and the Google Charts API from Dart. The pub package is <a href="https://github.com/dart-lang/js-interop">open source on Github</a>, and is maintained by Googlers and engineers from the community.</div>
<br />
<br /></div>
</div>
Photo Credit: <a href="http://www.flickr.com/photos/41768119@N04/4594527045/">Gloson</a> <a href="http://creativecommons.org/licenses/by-nc/2.0/">cc</a>Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-61981659425285035962013-06-05T19:27:00.000-07:002013-09-28T17:38:51.918-07:00Forms, HTTP servers, and Web Components with Dart<span style="font-size: x-large;">(<a href="http://blog.sethladd.com/2013/09/forms-http-servers-and-polymer-with-dart.html">UPDATED VERSION HERE</a>. This post is out of date, you probably want the <a href="http://blog.sethladd.com/2013/09/forms-http-servers-and-polymer-with-dart.html">new version</a>.)</span><br />
<br />
Dart can be used on the client and the server. This post shows how to:<br />
<div>
<ul>
<li>build a form as a custom element</li>
<li>bind input fields to a Dart object</li>
<li>build a Dart HTTP server</li>
<li>handle and parse a form submit</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="252" src="http://2.bp.blogspot.com/-i53oGFflxKM/Ua_yhctuZNI/AAAAAAAAXiU/JZsstHI7JUc/s400/4436325865_d627768fa6_b.jpg" width="400" /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
For lots more examples, and more context and details, be sure to check out the <a href="http://www.dartlang.org/docs/tutorials/">Dart Tutorials</a>. You can find the <a href="https://github.com/sethladd/dart-form-submit-demo">code</a> for this post at my Github account.</div>
</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Step 1: Install the Web UI package</span></div>
<div>
<br /></div>
<div>
Open up pubspec.yaml (used by the <a href="http://pub.dartlang.org/">pub package manager</a>) and add the dependencies for Web UI.</div>
<div>
<br /></div>
<div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">dependencies<span class="s1">:</span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> browser<span class="s1">:</span> any</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> web_ui<span class="s1">:</span> any</span></div>
<div class="p2">
<br /></div>
<div class="p2">
<span style="font-size: large;">Step 2: Create the model class</span></div>
<div class="p2">
<br /></div>
<div class="p2">
This class is for our "business object". It is bound to the form, so we make it <a href="http://www.dartlang.org/web-ui/observable">observable</a>.</div>
<div class="p2">
<br /></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">library</span> person;</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'package:web_ui/web_ui.dart'<span class="s2">;</span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2">@</span>observable</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">class</span> Person {</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> String <span class="s3">firstName</span>;</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> String <span class="s3">lastName</span>;</span></div>
<div class="p5">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> double </span><span class="s3">age</span><span class="s2"> = </span><span class="s4">0.0</span><span class="s2">; </span>// not an int because web ui loves doubles</span></div>
<div class="p2">
</div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div class="p1">
<br /></div>
<div class="p1">
<span style="font-size: large;">Step 3: Create the custom element HTML</span></div>
<div class="p1">
<br /></div>
<div class="p1">
This custom element, polyfilled by <a href="http://www.dartlang.org/articles/web-ui/spec.html">Web UI</a>, wraps the form and makes it easy to reuse. The custom element is bound to an instance of Person, our model class. The <template> tag contains the structure of this custom element. Notice the submit event runs the submit() method of this custom component (see in the next step). The $event object, representing the submit event, is passed to submit().</div>
<div class="p1">
<br /></div>
<div class="p1">
<br /></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s1">element</span> name=<span class="s2">"person-form"</span> constructor=<span class="s2">"PersonForm"</span> extends=<span class="s2">"div"</span>></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s1">template</span>></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s1">div</span> id=<span class="s2">"message"</span>></<span class="s1">div</span>></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s1">form</span> method=<span class="s2">"post" </span>on-submit="submit($event)"</span><span style="font-family: 'Courier New', Courier, monospace;">></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s1">input</span> type=<span class="s2">"text"</span> bind-value=<span class="s2">"person.firstName"</span> name=<span class="s2">"firstName"</span>></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s1">input</span> type=<span class="s2">"text"</span> bind-value=<span class="s2">"person.lastName"</span> name=<span class="s2">"lastName"</span>></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s1">input</span> type=<span class="s2">"number"</span> bind-value-as-number=<span class="s2">"person.age"</span> name=<span class="s2">"age"</span>></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s1">input</span> type=<span class="s2">"submit"</span>></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> </<span class="s1">form</span>></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> </<span class="s1">template</span>></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><span class="s3"> <</span><span class="s1">script</span><span class="s3"> type=</span>"application/dart"<span class="s3"> src=</span>"personform.dart"<span class="s3">></</span><span class="s1">script</span><span class="s3">></span></span></div>
<div class="p2">
</div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s3"> </</span>element<span class="s3">></span></span></div>
<div class="p3">
<span class="s3"><br /></span></div>
<div class="p3">
<span class="s3"><span style="font-size: large;">Step 4: Create the custom element Dart code</span></span></div>
<div class="p3">
<span class="s3"><br /></span></div>
<div class="p3">
<span class="s3">If a custom element needs custom behavior, you can implement it with Dart. Each custom element tag you use on the page as an instance of its corresponding class. The submit() method is called when the form is submitted (see the on-submit binding from Step 3). The person and action fields of the PersonForm class get initialized by attribute and data bindings from the usage of the custom element tag.</span></div>
<div class="p3">
<span class="s3"><br /></span></div>
<div class="p3">
<span class="s3">In this case, we disable the default behavior of form submission so we don't incur a page reload. We use HttpRequest to submit the form data, and update a div inside our custom element with the response text.</span></div>
<div class="p3">
<span class="s3"><br /></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'package:web_ui/web_ui.dart'<span class="s2">;</span></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'person.dart'<span class="s2">;</span></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'dart:html'<span class="s2">;</span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">class</span> PersonForm <span class="s1">extends</span> WebComponent {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> Person <span class="s3">person</span>;</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> String <span class="s3">action</span>;</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"> submit(Event e) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> e.preventDefault();</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> FormElement form = e.target as FormElement;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> form.action = action;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> HttpRequest.request(form.action,</span><br />
<span style="font-family: Courier New, Courier, monospace;"> method:form.method,</span><br />
<span style="font-family: Courier New, Courier, monospace;"> sendData:new FormData(form))</span><br />
<span style="font-family: Courier New, Courier, monospace;"> .then((HttpRequest req) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> host.query('#message').text = req.responseText;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> })</span><br />
<span style="font-family: Courier New, Courier, monospace;"> .catchError((e) => print(e));</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div class="p3">
<span class="s3"><span style="font-family: Courier New, Courier, monospace;">
</span></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div class="p3">
<br /></div>
<div class="p3">
<span style="font-size: large;">Step 5: Import and use the custom element</span></div>
<div class="p3">
<br /></div>
<div class="p3">
Use a <link> tag to import the custom element. Use the custom element with is="person-form" attribute on a <div>. An instance of person (created in the next step) is bound to the custom element. The action attribute on div is used to set the action via static data binding.</div>
<div class="p3">
<br /></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1"><</span>html<span class="s1">></span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s2">head</span>></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s2">meta</span> charset=<span class="s3">"utf-8"</span>></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1"> <</span><span class="s2">link</span><span class="s1"> rel=</span>"stylesheet"<span class="s1"> href=</span>"parse_form_submit.css"<span class="s1">></span></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1"> <</span><span class="s2">link</span><span class="s1"> rel=</span>"import"<span class="s1"> href=</span>"personform.html"<span class="s1">></span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> </<span class="s2">head</span>></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s2">body</span>></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> <<span class="s2">h1</span>>Forms</<span class="s2">h1</span>></span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1"> <</span><span class="s2">div</span><span class="s1"> action=</span>"http://localhost:8888/submit"<span class="s1"> is=</span>"person-form"<span class="s1"> person=</span>"{{person}}"<span class="s1">></</span><span class="s2">div</span><span class="s1">></span></span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1"> <</span><span class="s2">script</span><span class="s1"> type=</span>"application/dart"<span class="s1"> src=</span>"parse_form_submit.dart"<span class="s1">></</span><span class="s2">script</span><span class="s1">></span></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1"> <</span><span class="s2">script</span><span class="s1"> src=</span>"packages/browser/dart.js"<span class="s1">></script></span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> </body></span></div>
<div class="p3">
</div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"></html></span></div>
<div class="p2">
<br /></div>
<div class="p2">
<span style="font-size: large;">Step 6: Create the app's main code</span></div>
<div class="p2">
<br /></div>
<div class="p2">
All this app needs is one instance of Person. The instance defined here is visible to the page, and is the same as used in the custom element from Step 5 (person="{{person}}"). The main() method is empty, because Web UI handles all the binding, initialization, etc.</div>
<div class="p2">
<br /></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'person.dart'<span class="s2">;</span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;">Person <span class="s3">person</span> = <span class="s1">new</span> Person();</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p2">
</div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s4">main</span>() { }</span></div>
<div class="p3">
<br /></div>
<div class="p3">
<span style="font-size: large;">Step 7: Write the server</span></div>
<div class="p3">
<br /></div>
<div class="p3">
Dart's <a href="http://www.dartlang.org/articles/io/">dart:io library</a> help you write command-line and server-side application. We use the builtin HTTP server functionality to listen for POST requests, parse the form data into a Map, enable <a href="http://enable-cors.org/index.html">CORS headers</a> (so pages from any origin can submit to this server), and send back a string version of the original form data.</div>
<div class="p3">
<br /></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'dart:io'<span class="s2">;</span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s3">main</span>() {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> HttpServer.bind(<span class="s4">'0.0.0.0'</span>, <span class="s5">8888</span>).then((HttpServer server) {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> server.listen((HttpRequest req) {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s1">if</span> (req.<span class="s6">uri</span>.<span class="s6">path</span> == <span class="s4">'/submit'</span> && req.<span class="s6">method</span> == <span class="s4">'POST'</span>) {</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> print(</span>'received submit'<span class="s2">);</span></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> HttpBodyHandler.processRequest(req).then((HttpBody body) {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> print(body.<span class="s6">body</span>.<span class="s7">runtimeType</span>); <span class="s8">// Map</span></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> req.</span><span class="s6">response</span><span class="s2">.</span><span class="s6">headers</span><span class="s2">.add(</span>'Access-Control-Allow-Origin'<span class="s2">, </span>'*'<span class="s2">);</span></span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2"> req.</span><span class="s6">response</span><span class="s2">.</span><span class="s6">headers</span><span class="s2">.add(</span>'Content-Type'<span class="s2">, </span>'text/plain'<span class="s2">);</span></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> req.<span class="s6">response</span>.<span class="s6">statusCode</span> = <span class="s5">HttpStatus.CREATED</span>;</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> req.<span class="s6">response</span>.write(body.<span class="s6">body</span>.toString());</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> req.<span class="s6">response</span>.close();</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> });</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> });</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> });</span></div>
<div class="p3">
</div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div class="p3">
<br /></div>
<div class="p3">
<span style="font-size: large;">Summary</span></div>
<div class="p3">
<br /></div>
<div class="p3">
Ta da! You've just used Dart to create a live, data-bound form and wrapped it up in a web component. Then, you wrote a Dart server to parse the form data and return a simple response. Be sure to checkout the <a href="https://github.com/sethladd/dart-form-submit-demo">Github repo</a> for this post for all the code (as I left out a few things). Is this the best we can do? Probably not, you probably want a more full-featured server-side framework. There are a few in <a href="http://pub.dartlang.org/">pub.dartlang.org</a> for you to explore.</div>
<div class="p3">
<br /></div>
<div class="p3">
<span style="font-size: large;">Learning more</span></div>
<div class="p3">
<br /></div>
<div class="p3">
To learn more about Dart, try these resources:</div>
<div class="p3">
</div>
<ul>
<li><a href="http://www.dartlang.org/docs/tutorials/">Dart tutorials</a></li>
<li><a href="http://g.co/dartisans">Dartisans community on G+</a></li>
<li><a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html">Dart language tour</a></li>
<li><a href="http://www.dartlang.org/articles/">Dart articles</a></li>
</ul>
<br />
<div class="p3">
Photo Credit: <a href="http://www.flickr.com/photos/25384802@N08/4436325865/">jasleen_kaur</a></div>
</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-83339122167585217002013-05-21T20:41:00.003-07:002013-05-21T20:41:47.837-07:00Watch the video from What's New in Dart from Google I/O 2013Google I/O was a blast, and <a href="http://news.dartlang.org/2013/05/strong-dart-presence-at-2013-google-io.html">Dart had a great time</a>. For posterity, check out the video of my talk with co-presenter Justin Fagnani. We covered what's new across the Dartosphere, including language features, libraries, tools, and ecosystem.<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="360" src="https://www.youtube.com/embed/kvZTOCAG_-0" width="640"></iframe><br />
<br />
Like what you see? Head on over to <a href="http://dartlang.org/">dartlang.org</a> to download the SDK and check out our docs and tutorials. You can always find us in our <a href="http://g.co/dartisans">Dartisans G+ community</a>. Stop by and say hi!Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-59863054172368040472013-04-23T22:47:00.001-07:002014-09-05T09:59:39.305-07:00Lazy Load Libraries in Dart<span style="font-size: x-large;">UPDATE: This article is now DEPRECATED, but the feature lives on! Dart now formally supports lazy loading (deferred) libraries. Learn more in the <a href="https://www.dartlang.org/docs/spec/deferred-loading.html">Deferred Loading in Dart article</a>.</span><br />
<br />
<span style="color: #999999;">Dart is a statically analyzable language, and its tree-shaking compiler does a good job of eliminating dead code and producing a single, optimized application file. However, sometimes developers need to control when certain libraries are loaded and thus need to control which libraries are included in the main application file. To help, the dart2js compiler, which converts Dart code into JavaScript code, now supports lazy-loaded libraries.</span><br />
<span style="color: #999999;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-mt92rQOSk_Q/UXdx0aKXAfI/AAAAAAAAV1Y/zCqHR0Le-hc/s1600/87885327_b0db9347cf.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="color: #999999;"><img border="0" src="http://1.bp.blogspot.com/-mt92rQOSk_Q/UXdx0aKXAfI/AAAAAAAAV1Y/zCqHR0Le-hc/s1600/87885327_b0db9347cf.jpg" /></span></a></div>
<span style="color: #999999;"><br /></span>
<div>
<span style="color: #999999;"><br /></span></div>
<div>
<span style="color: #999999; font-size: large;">Lazy Load</span><br />
<div>
<span style="color: #999999;"><br /></span></div>
<div>
<span style="color: #999999;">As an example, consider an application that has many different screens. Some screens are more obscure than others, and aren't required for the application to start. A developer should be able to say "I don't need these screens now, but pull them in when I do need them." This lazy-loading is a common deployment strategy for web apps, because small initial loads means faster application startup.</span></div>
<div>
<span style="color: #999999;"><br /></span></div>
<div>
<span style="color: #999999;">You can mark a library as "lazy", and the dart2js compiler will output a separate JavaScript file for that library. Note that dart2js still performs tree shaking (aka dead code elimination) across the entire app (technically, across the entire isolate). This means that only the functionality required from the lazy-loaded library will actually be compiled into the separate file.</span></div>
<div>
<span style="color: #999999;"><br /></span></div>
<div>
<span style="color: #999999;">The lazy-loaded library is still part of the application structure, and must exist and be available to dart2js when the program is compiled. This is not "dynamic loading", per se, because the application must statically import all libraries (lazy or not).</span></div>
<div>
<span style="color: #999999;"><br /></span></div>
<div>
<span style="color: #999999;">(Note: as of the time of this writing, dart2js emits at most one other JavaScript file. This restriction will be removed and you will be able to emit multiple files for a single application. Please track <a href="https://code.google.com/p/dart/issues/detail?id=3940">Dartbug 3940</a> to learn more.)</span></div>
<div>
<span style="color: #999999;"><br /></span></div>
<div>
<span style="color: #999999; font-size: large;">DeferredLibrary Example</span></div>
</div>
<div>
<span style="color: #999999;"><br /></span></div>
<div>
<span style="color: #999999;">The main application can mark a library with an @lazy metadata. Then, it declares an instance of <a href="http://api.dartlang.org/docs/bleeding_edge/dart_async/DeferredLibrary.html">DeferredLibrary</a> that points to the outputted JavaScript file.</span></div>
<div>
<span style="color: #999999;"><br /></span></div>
<div>
<div class="p1">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><span class="s1">import </span>'dart:html'<span class="s1">;</span></span></div>
<div class="p1">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><span class="s1">import </span>'dart:async'<span class="s1">;</span></span></div>
<div class="p2">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;">@lazy</span></div>
<div class="p1">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><span class="s1">import </span>'reverser.dart'<span class="s1">;</span></span></div>
<div class="p2">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><span class="s2">const</span> lazy = <span class="s2">const</span> DeferredLibrary(<span class="s3">'reverser'</span>, uri: <span class="s3">'./part.js'</span>);</span></div>
<div class="p2">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><span class="s2">void</span> main() {</span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"> lazy.load().then((_) {</span></div>
<div class="p1">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><span class="s1"> print(</span>'library loaded'<span class="s1">);</span></span></div>
<div class="p1">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><span class="s1"> query(</span>"#sample_text_id"<span class="s1">)</span></span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"> ..text = <span class="s3">"Click me!"</span></span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"> ..onClick.listen(reverseText);</span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"> });</span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;">}</span></div>
<div class="p2">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"><span class="s2">void</span> reverseText(MouseEvent event) {</span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"> query(<span class="s3">"#sample_text_id"</span>).text =</span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;"> reverse(query(<span class="s3">"#sample_text_id"</span>).text);</span></div>
<div class="p3">
<span style="color: #999999; font-family: Courier New, Courier, monospace;">}</span></div>
<div class="p3">
<span style="color: #999999;"><br /></span></div>
<div class="p3">
<span style="color: #999999;">Notice how the library doesn't come into existence until after the Future from <span style="font-family: Courier New, Courier, monospace;">lazy.load()</span> completes. Only then can you call into the library.</span></div>
<div class="p3">
<span style="color: #999999;"><br /></span></div>
<div class="p3">
<span style="color: #999999;">The runtime throws NoSuchMethodError if you try to access functionality from a library that it not yet loaded.</span></div>
<div class="p3">
<span style="color: #999999;"><br /></span></div>
<div class="p3">
<span style="color: #999999; font-size: large;">More to come</span></div>
<div class="p3">
<span style="color: #999999;"><br /></span></div>
<div class="p3">
<span style="color: #999999;">The lazy-load functionality of dart2js is just the beginning. In the future, you will be able to mark multiple libraries as "lazy", and really control how you deploy and load your web application.</span><br />
<span style="color: #999999;"><br /></span>
<span style="color: #999999;">Also, this functionality only currently works with dart2js. Please star <a href="https://code.google.com/p/dart/issues/detail?id=10171">Dartbug 10171</a> if you are interested in seeing the same lazy-loading for the VM and Dartium.</span></div>
<div class="p3">
<span style="color: #999999;"><br /></span></div>
<div class="p3">
<span style="color: #999999;">Please try this out, we look forward to your feedback!</span></div>
<div class="p3">
<span style="color: #999999;"><br /></span></div>
<div class="p3">
<span style="color: #999999;"><br /></span></div>
</div>
<span style="color: #999999;">(Photo Credit: <a href="http://www.flickr.com/photos/87603889@N00/87885327/">Marcus Hansson</a> licensed under <a href="http://creativecommons.org/licenses/by/2.0/">cc</a>)</span>Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-14211435915730658742013-04-23T21:17:00.000-07:002013-04-23T21:26:47.173-07:00Dynamically Load Code with DartRejoice! Dartium, a build of Chromium with the Dart VM, can now spawn a new isolate from a URI. This means your Dart apps have a new option for more modular code.<br />
<br />
<span style="font-size: large;">Isolates</span><br />
<br />
In Dart, an <i>isolate</i> is an abstraction for an "isolated memory heap". Isolates do not share memory (variables, statics, etc), they are essentially self-contained applications. Isolates communicate by sending and receiving messages over <i>ports</i>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-lKoB2jUTX6U/UXdS8wuphdI/AAAAAAAAV1I/Jf78_URD_Fc/s1600/Dart+isolates+diagram+(1).png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-lKoB2jUTX6U/UXdS8wuphdI/AAAAAAAAV1I/Jf78_URD_Fc/s1600/Dart+isolates+diagram+(1).png" /></a></div>
<br />
<span style="font-size: large;">Why Isolates Matter</span><br />
<br />
Dart programs are static, in that their shape and structure do not change after they are compiled. A static program is great for optimizations like tree shaking (aka dead code elimination), type-inferencing compilers, and more.<br />
<br />
However, modular apps often require a way to dynamically load code. Configurable and modular apps need a way to, at run time, pull in new functionality. If Dart apps have a static structure, how can they dynamically alter their behavior?<br />
<br />
Isolates to the rescue! The structure inside of an isolate is static, but a Dart program is free to dynamically load other isolates. This means that libraries can be loaded into isolates at run time.<br />
<br />
<span style="font-size: large;">Your First Isolate</span><br />
<br />
This simple <i>reverser</i> isolate listens on its port, receives messages, reverses them, and send the reversed text back to the sender.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">// reverser.dart</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<br />
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">import</span><span class="s2"> </span>'dart:isolate'<span class="s2">;</span></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s3">main</span>() {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s4">port</span>.receive((msg, SendPort replyTo) {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s1">var</span> reverse = msg <span class="s1">as</span> String;</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s1">var</span> buffer = <span class="s1">new</span> StringBuffer();</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s1">for</span> (<span class="s1">var</span> i = reverse.<span class="s4">length</span> - <span class="s5">1</span>; i >= <span class="s5">0</span>; i--) {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> buffer.write(reverse[i]);</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> replyTo.send(buffer.toString());</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"> });</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div class="p3">
<br /></div>
<div class="p3">
The main application (which itself is an isolate), is responsible for instantiating the reverser isolate. Use the <span style="font-family: Courier New, Courier, monospace;">spawnUri()</span> function from <span style="font-family: Courier New, Courier, monospace;">dart:isolate</span> to spawn a new isolate from some file.</div>
<div class="p3">
</div>
<div class="p1">
<br /></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;">// main.dart</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">SendPort <span class="s1">reverser</span>;</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"><span class="s2">void</span> <span class="s3">main</span>() {</span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s4"> query(</span>"#sample_text_id"<span class="s4">)</span></span></div>
<div class="p3">
<span style="font-family: Courier New, Courier, monospace;"><span class="s4"> ..</span><span class="s1">text</span><span class="s4"> = </span>"Click me!"</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> ..<span class="s1">onClick</span>.listen(reverseText);</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s2">var</span> serviceFile = <span class="s5">'reverser.dart'</span>;</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p4">
<span style="font-family: Courier New, Courier, monospace;"><span class="s4"> </span><span class="s2">if</span><span class="s4"> (identical(</span><span class="s6">1</span><span class="s4">, </span><span class="s6">1.0</span><span class="s4">)) { </span>// <span class="s7">XXX</span>: horrible hack to detect if we're in JS</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> serviceFile = <span class="s5">'reverser.dart.js'</span>;</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> </span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s1">reverser</span> = spawnUri(serviceFile);</span></div>
<div class="p2">
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div class="p2">
<br /></div>
<div class="p2">
Notice the horrible hack to detect if this code is running in the Dart VM or JavaScript. I don't know a better way to do it, but I don't recommend this.</div>
<div class="p2">
<br /></div>
<div class="p2">
When the text from #sample_text_id is clicked, the reverseText function is run:<br />
<br />
<br />
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"><span class="s1">void</span> <span class="s2">reverseText</span>(MouseEvent event) {</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s1">var</span> text = query(<span class="s3">"#sample_text_id"</span>).<span class="s4">text</span>;</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> <span class="s4">reverser</span>.call(text).then((reversed) {</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> query(<span class="s3">"#sample_text_id"</span>).<span class="s4">text</span> = reversed;</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;"> });</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace;">}</span></div>
<div class="p1">
<br /></div>
<div class="p1">
Notice how the reverser isolate is sent a message via call(), which returns a Future. When the Future completes, the callback registered with then() is run.</div>
<div class="p1">
<br /></div>
<div class="p1">
<span style="font-size: large;">Support</span></div>
<div class="p1">
<br /></div>
<div class="p1">
Dartium supports spawnUri since at least version 28.0.1478.0 (194114). Dart2js compiles spawnUri() into a Web worker.</div>
<div class="p1">
<br /></div>
<div class="p1">
Note that each isolate is its own app, so dart2js must compile the same bootstrap code into each isolate file.</div>
</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-44282295199823797242013-04-18T13:09:00.001-07:002013-04-18T13:09:46.189-07:006 Dart FAQs - Answered!<a href="https://plus.google.com/105922896126183852742">Calvin Prewitt</a> wrote some good <a href="https://plus.google.com/u/0/+SethLadd/posts/25HSRX13wUh">questions about Dart</a> via G+. It might be hard to find his questions and my answers, so I hoisted them here. Enjoy!<br /><br /><i>Q) Could you also detail compatibility and which JavaScript APIs are fully or partially supported for Dart2JS production code?</i><br /><br />A) All JavaScript APIs supported by Chrome should be available to Dart. See <a href="http://www.dartlang.org/articles/improving-the-dom/">http://www.dartlang.org/articles/improving-the-dom/</a><br /><br /><br /><br /><i>Q) It appears Dart is aiming to eventually replace it? The FAQ says it only targets modern browser versions.</i><br /><br />A) Dart's aim is to give developers like you a very productive experience, and give your users a very fast experience. Dart targets IE9+, plus the modern versions of Firefox, Chrome, Safari, mobile safari, and Chrome for Android. Basically, modern browsers.<br /><br /><br /><br /><i>Q) Is there a way to have fine grained control over the JS code like in Closure?</i><br /><br />A) Dart2js can emit a single file, plus up to one other lazily loaded library. In the future, we want to give you more control. Here's the bug: <a href="https://code.google.com/p/dart/issues/detail?id=10023">https://code.google.com/p/dart/issues/detail?id=10023</a> Please note, dart2js's output is already smaller thanks to tree-shaking.<br /><br /><br /><br /><i>Q) I've noticed a lot of similarities to Closure Library. Has some or all of the Closure Library code been ported?</i><br /><br />A) I'm unaware of an "official" port from the closure libraries. In general, though, you shouldn't need it. Dart's core libraries are pretty comprehensive. Check out <a href="http://api.dartlang.org/">http://api.dartlang.org</a><br /><br /><br /><br /><i>Q) Is Dart ready for production use? Specifically for generating JS code. If not, what's missing or where are the sore spots?</i><br /><br />A) Dart's M4 release just came out, promising no more breaking changes to the core libs. Hurray! There's still work to do, but the platform just got much more stable. If you see something missing, let us know: <a href="http://dartbug.com/new">http://dartbug.com/new</a><div>
<br /></div>
<div>
<br /><br /><i>Q) Finally, where can I help? Closure is nowhere near a productive environment. If Dart is aiming to make building complex web apps easier than working with Closure, I'd like to contribute to that goal.</i><br /><br />A) Yes, we're "aiming to hit a productivity and performance bullseye" (groan :) We'd love help. Dart is open source, so check out <a href="http://dartbug.com/">http://dartbug.com/</a> and out Github presence at<a href="http://github.com/dart-lang">http://github.com/dart-lang</a> Join our Dartisans community in G+, too</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-67176801433526295402013-03-25T21:34:00.001-07:002013-03-25T22:17:08.579-07:00First Look at Dart MixinsYou can use <i>mixins</i> to help inject behavior into your classes without using inheritance. Use a mixin when you have shared functionality that doesn't fit well in a <i>is-a</i> relationship.<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" src="http://1.bp.blogspot.com/-k_PxdBf6fR4/UVEkgVmt_II/AAAAAAAAVbE/wEurF9mx0xc/s1600/5406671277_5d6d9329bb.jpg" /></div>
<div>
<br />
<div>
<br /></div>
<div>
Dart supports a basic form of <a href="http://www.dartlang.org/articles/mixins/">mixins</a> as of the M3 release in early 2013. The language designers expect to expand on mixins' abilities in future versions of the language.</div>
<div>
<br /></div>
<div>
Surprisingly, you've been using the concept of a mixin all along. Dart considers a mixin as the <i>delta between a subclass and its superclass</i>. That is, every time you define an <i>is-a</i> relationship with the <i>extends</i> keyword, you are really defining a delta between the new class and its parent class. In other words, a subclass definition is like a mixin definition.</div>
<div>
<br /></div>
<div>
Given that short description, it should come as no surprise that an abstract class (with a few restrictions) is itself a mixin. Here is an example of a Persistance mixin:</div>
<div>
<br /></div>
<div>
<pre style="background-color: #f0f0f0; border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 450.828125px;"><code style="word-wrap: normal;"> abstract class Persistence {
void save(String filename) {
print('saving the object as ${toJson()}');
}
void load(String filename) {
print('loading from $filename');
}
Object toJson();
} </code></pre>
</div>
<div>
<br /></div>
<div>
Restrictions on mixin definitions include:</div>
<div>
<ol>
<li>Must not declare a constructor</li>
<li>Superclass is Object</li>
<li>Contains no calls to super</li>
</ol>
<div>
You can use the mixin with the <i>with</i> keyword. Here is an example:</div>
</div>
<div>
<br /></div>
<div>
<pre style="background-color: #f0f0f0; border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 450.828125px;"><code style="word-wrap: normal;"> abstract class Warrior extends Object <b>with Persistence</b> {
fight(Warrior other) {
// ...
}
}
class Ninja extends Warrior {
Map toJson() {
return {'throwing_stars': true};
}
}
class Zombie extends Warrior {
Map toJson() {
return {'eats_brains': true};
}
} </code></pre>
</div>
<div>
<br /></div>
<div>
In the above example, both Ninja and Zombie extend from Warrior. This makes sense, they are both warriors, so the <i>is-a</i> relationship applies. All warriors can be persisted and loaded from a database, but this is purely behavior and the statement <i>Warrior is-a Persistence</i> simply doesn't make sense. Inheritance does not apply here, but we can use a mixin to inject the functionality.</div>
<div>
<br /></div>
<div>
<pre style="background-color: #f0f0f0; border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 450.828125px;"><code style="word-wrap: normal;"> main() {
var ninja = new Ninja();
ninja.save('warriors.txt');
var zombie = new Zombie();
zombie.save('warriors.txt');
} </code></pre>
</div>
<div>
<br />
A class that uses a mixin is also a member of the mixin's type:<br />
<br />
<br />
<pre style="background-color: #f0f0f0; border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; width: 450.828125px;"><code style="word-wrap: normal;"> print(ninja is Persistence); // true! </code></pre>
<br />
<br /></div>
<div>
Mixins are fairly new to Dart, so they aren't widely deployed. We're curious to see how you use mixins. Let us know on the <a href="mailto:misc@dartlang.org">Dart mailing list</a>, and please <a href="http://dartbug.com/">file any bugs</a> you may encounter. Thanks!</div>
<div>
<br /></div>
<div>
<span style="font-size: x-small;">(Photo courtesy of <a href="http://www.flickr.com/photos/58871905@N03/5406671277/">http://www.flickr.com/photos/58871905@N03/5406671277/</a>)</span></div>
</div>
Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.comtag:blogger.com,1999:blog-8601579266012455634.post-58551161992477166562013-03-20T17:10:00.001-07:002013-03-20T17:12:19.763-07:00Dart on FLOSS Weekly from TWiT NetworkToday I had the pleasure of chatting about <a href="http://www.dartlang.org/" target="_blank">Dart</a> with Randal Schwartz and Aaron Newcomb on <a href="http://twit.tv/show/floss-weekly" target="_blank">FLOSS Weekly</a> (part of the <a href="http://twit.tv/" target="_blank">TWiT network</a>). We talked about the Dart language, its developer ecosystem, and the future of the project.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://twit.tv/show/floss-weekly/245" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="223" src="http://4.bp.blogspot.com/-YuqltAZe5qk/UUpQTGYwTSI/AAAAAAAAVXI/2g3QIYdChsQ/s400/Screen+Shot+2013-03-20+at+5.11.34+PM.png" width="400" /></a></div>
<br />
<br />
You can <a href="http://twit.tv/show/floss-weekly/245" target="_blank">watch the entire video</a> of the interview, embedded below for easy viewing:<br />
<br />
<iframe align="middle" frameborder="0" height="320" hspace="0" marginheight="0" marginwidth="0" scrolling="no" src="http://twit.tv/embed/12691" width="640"></iframe>
<br />
Thanks to Randal and Aaron for a lively discussion. They are awesome hosts and I highly recommend you tune in.<br />
<br />
Have Dart questions? Join us on the <a href="http://www.dartlang.org/mailing-list" target="_blank">mailing list</a> or the <a href="https://plus.google.com/communities/114566943291919232850" target="_blank">Dartisans G+ Community</a>. We love feedback!Anonymoushttp://www.blogger.com/profile/13906800552603557213noreply@blogger.com