Mozilla

Articles

Sort by:

View:

  1. Updating and Tweaking your Firefox OS Developer Preview phone/Geeksphone

    Developer Preview editions of the Firefox OS phone are now becoming widely available to the community, mainly through Geeksphone. Since these are for developers, naturally we want to encourage you to tinker and play with them as much as possible!
    In this post we will cover some basic tips on how to keep your phone up to date and how to tweak the system Gaia applications.

    Updating your Geeksphone to the latest images

    Firefox OS updates can be be downloaded from within the the Settings app, listed under Device information. The phone can be set to check for updates daily, weekly or monthly. In addition a “check now” button is provided. When an update is available you will be prompted to download and install the current version.

    The team at Geeksphone is also now providing the latest stable and nightly builds as self contained downloads for flashing your phone. Before proceeding make you have setup your phone as described in “Setting Up the Geeksphone Device” section of the Pushing Firefox OS Apps to the Geeksphone post. This will insure that you can push data to the phone.

    The builds are located at the Geeksphone download site. On this site you will be presented with options for selecting your device and what type of build you want to use.

    Download your particular build and extract the archive to your filesystem. The archive contains the images and commands required to flash the phone using Windows, Mac OS X or Linux. Before attempting to flash the phone make sure that you have enabled Remote debugging on the phone. This option can be set by launching the Settings app and navigating to Device information -> More information -> Developer tab. Also do not attempt to flash the phone if the power level is below 50%.

    Windows

    Open a Command Prompt (start -> type cmd in search -> enter on windows 7, Windows key + X -> select Command Prompt on Windows 8) and cd to the directory containing the extracted files. Run:

    flash.bat.

    Mac OS X

    Open a Terminal (Cmd + space -> type terminal -> enter) window and cd to the directory containing the extracted files. Run:

    ./flash_mac.sh

    Linux

    Open a Terminal (control-alt-t on Ubuntu) window and cd to the directory containing the extracted files. Run:

    ./flash.sh

    This should flash the new image to the phone. The phone will need to be setup again as all data will be cleared.

    Tweaking Gaia

    If you are of the industrious sort, you may want to tweak the default applications in Gaia – the UI in Firefox OS. In this section we will cover some of the basics for cloning Gaia and making changes to the default system apps. Bear in mind these tips are “at your own risk” and may involve you reading the later section “Ok, I bricked my phone”. Before proceeding make sure that you have adb and fastboot installed on your system. To verify if these are installed open a terminal and type adb devices with your phone connected. You should see something similar to the following.

    You should also be able to run fastboot from the terminal. If you run fastboot, a set of parameter options should be displayed. If you do not have adb or fastboot installed, a quick Google search with your operating system will return several quick starts on how to install them. In addition to adb and fastboot you will need Git. If you do not currently have Git installed have a look at this setup guide. Finally make sure your phone is setup for remote debugging as described in the previous section.

    Once you have the prerequisites you can open a terminal and cd to the directory you would like to clone the Gaia source code to and type the following commands.

    git clone git://github.com/mozilla-b2g/gaia.git gaia
    cd gaia

    This will clone the current Gaia code to your system. Currently the Geeksphone Keon uses the v1.0.1 branch of Gaia code, so set the proper branch using the following command.

    git checkout -b v1.0.1 origin/v1.0.1

    Most of the system apps are located in the apps subdirectory of gaia. You can now make any changes to these Firefox OS apps you wish. Once you have made changes run the following command to push the modified apps to your phone. This will by default push all the system apps to the phone:

    B2G_SYSTEM_APPS=1 make install-gaia

    If you only changed one of the apps you can specify the particular app using similar syntax. In this example only the calendar app will be pushed to the phone:

    APP=calendar B2G_SYSTEM_APPS=1 make install-gaia

    If you have issues while making the changes, you can reset the phone to default values using either of the following commands.

    make production
    make reset-gaia

    Note: Bear in mind that either of the above commands will clear any data or apps that you have pushed to the phone.

    “Ok, I bricked my phone”

    If you are in the process of modifying your phone and it becomes “unresponsive” you should be able to recover it using fastboot with a simple procedure. The following illustrates reseting the Keon but other phones should have a similar process. You will also need to verify that you have fastboot installed.

    First remove the USB cable and then remove the battery from the phone for thirty seconds. Then reinsert the battery and press the volume down button while holding the power button for a few seconds. Next re-connect the usb cable and run the following commands from a terminal window in the directory that contains the latest img files described in the first section of this post.

    fastboot flash recovery recovery.img
    fastboot flash boot boot.img
    fastboot flash userdata userdata.img
    fastboot flash system system.img
    fastboot reboot

    This process should recover your phone.

    Go play!

    We hope these instructions are useful to you, and naturally we want you to be as happy about Firefox OS and the possibilities as we are! Feel free to play around with updating your devices, making changes/updates to Gaia apps and also to be inspired to take these learnings into building your own Open Web Apps.

  2. Compete in the “Amp Your Firefox” Add-ons Contest

    People love their add-ons—85% of Firefox users have them installed, and there have been over 3 billion downloads since they revolutionized browsing in 2004. There are add-ons for almost everything under the sun: fun, productivity, personalization, even for making tea. Between June 13 – July 18, 2013, we challenge you to delight these fans by creating or updating add-ons that amp up their Firefox.

    We’re also challenging you on the mobile front—with more than 10 million people using Firefox for Android, this is your chance to take the fun and personalization of add-ons to a fast-growing and passionate fan base.

    A panel of judges will pick the best add-on from each prize category, and the community will choose which category winner is the best overall add-on. Category winners will receive Android tablets, and the Best Overall winner will receive an 11-inch Macbook Air. All participants whose entry is approved (fully reviewed) for AMO will receive “Amp Your Firefox” t-shirts! The winning add-ons will also get tons of exposure on AMO and other Mozilla properties.

    The Categories

    Best Mobile Add-on

    Create add-ons that take Firefox for Android to the next level for over 10 million users by improving readability, enhancing the web experience across devices, and rounding out browsing features—get creative!

    Best Mobile Add-on Port

    If you’ve created an add-on for desktop and think it would be great for a mobile audience, port it over to Firefox for Android!

    Best Game Add-on

    It takes creativity and imagination to make a great game add-on like Cheevos or Destroy the Web—are you up for taking the challenge?

    Best Complete Theme

    Complete themes can dramatically change the look of your Firefox—everything from buttons, window frames, tabs, and menus can be customized—the sky’s the limit. Create complete themes that are both aesthetically pleasing and transform the appearance of Firefox.

    Best Updated Add-on

    If you’ve created an add-on and want to freshen it up by adding new features, making it restartless, or porting it to the SDK, this is the category for you.

    Mobile Next!

    One of the key categories we’re excited about for this competition is Mobile. Firefox for Android has done incredibly well in terms of user uptake and reviews in the Play marketplace, and the Android and Jetpack teams have both been working hard to make developing Add-ons for Mobile Firefox as easy as possible. Having said that, developing mobile add-ons is different enough that we thought we’d call out some of the highlights.

    NativeWindow & BrowserApp

    NativeWindow and BrowserApp are privileged JavaScript APIs that allow developers to add their own custom functionality to the Native Java UI that is used on Firefox for Android instead of XUL. BrowserApp provides add-on developers the ability to interact with mobile browser tabs. NativeWindow allows developers to add menu items to the main and context menus, and to trigger native notifications.

    Mark Finkle has created a handy github repo that includes all of the boilerplate code you’ll need to get started. Using this restartless add-on skeleton as the basis for your work, NativeWindow and BrowserApp are easy to access as properties off of the window object:

    // show a toast immediately
    aWindow.NativeWindow.toast.show("Showing you a toast", "short");
     
    // add a menu item that shows a toast when clicked
    let menuId = aWindow.NativeWindow.menu.add(“Hello!, icon, function() {
        aWindow.NativeWindow.toast.show("I ran the callback!", "short");
    });

    Jetpack – mobile ready

    If you’re more comfortable with the Add-on SDK, I’m happy to report that the Jetpack team has done a lot of work to support mobile development. Most ( but not all ) Jetpack APIs work on Mobile, and the cfx command-line tool has been enhanced to be able to easily push your add-on onto the device for testing.

    It is relatively simple to use NativeWindow from a Jetpack-based add-on:

    // get the most recent window
    const utils = require('api-utils/window/utils');
    const recent = utils.getMostRecentBrowserWindow();
     
    // show a toast notification
    recent.NativeWindow.toast.show(opts.message, duration);
     
    // listen for tabs events
    let tabs = require('tabs');
    tabs.on('ready', function(tab) {
        console.log(recent.BrowserApp.selectedTab.id, tabs.activeTab.id);
    });

    Caveats

    Mobile phones present unique challenges for web browsers like Firefox mobile, so there are some very real limitations on what you can do with extensions as compared to desktop Firefox:

    • Add-on Builder does not support packaging or running extensions on a phone
    • Firefox for Android does not support XUL overlays
    • not all of the Add-on SDK’s modules are compatible with Firefox for Android, please consult this compatibility guide for more information.

    For even more detail on using the NativeWindow api and Jetpack for hacking on mobile extensions, see the Jetpack, Fennec and NativeWindow blog post in the Mozilla Add-ons blog.

    Get going!

    Have fun, and good luck!

  3. May MDN sprint wrap-up

    Here are some of the high points from the MDN sprint that took place last weekend, May 31st and June 1st.

    New content

    Mixed security content blocking is now turned on by default in Firefox Aurora. David Bruant and Xavier Borderie improved the Mixed content page and David created How to fix a website with blocked mixed content.

    Jérémie Patonnier hosted the meet-up in the Paris office, and finished documenting the WebFM API. Jérémie has been documenting lots of the hardware device APIs. Check out this Device orientation example, if your browser and device support it.

    New contributor Scott Turner improved the Using IndexedDB article.

    Translations

    A sprint meet-up in Mozilla’s Paris office meant that lots of French translation work got done, with lots of fixes to the corresponding English content along the way. Several people continued working after the end of the sprint, so by now:

    Reviews

    William Reynolds completed editorial reviews on a large number of articles, from Rhino Runtime to Object defineProperty.

    Editorial reviews (checking grammar, spelling, etc.) are a quick and easy way to contribute to MDN, even if you’re new to development. Lots of newcomers to MDN start out by doing editorial reviews — you can too! Just click Sign in on any MDN page, and create an account via Mozilla Persona.

  4. Building a simple paint game with HTML5 Canvas and Vanilla JavaScript

    When the talk is about HTML5 Canvas you mostly hear about libraries to make it work for legacy browsers, performance tricks like off-screen Canvas and ways to draw and animate sprites and tiles. This is only one part of Canvas, though. On the lowest level, Canvas is a way to manipulate pixels of a portion of the screen. Either via a painting API or by directly manipulating the pixel array (which by the way is a typed array and thus performs admirably).

    Using this knowledge, I thought it’d be fun to create a small game I saw in an ad for a tablet: a simple game for kids to paint letters. The result is a demo for FirefoxOS called Letterpaint which will show up soon on the Marketplace. The code is on GitHub.

    letterpaint

    The fun thing about building Letterpaint was that I took a lot of shortcuts. Painting on a canvas is easy (and gets much easier using Jacob Seidelin’s Canvas cheatsheet), but on the first glance making sure that users stay in a certain shape is tricky. So is finding out how much of the letter has been filled in. However, by going back to seeing a Canvas as a collection of pixels, I found a simple way to make this work:

    • When I paint the letter, I read out the amount of pixels that have the colour of the letter
    • When you click the mouse button or touch the screen I test the colour of the pixel at the current mouse/finger position
    • When the pixel is not transparent, you are inside the letter as the main Canvas by default is transparent
    • When you release the mouse or stop touching the screen I compare the amount of pixels of the paint colour with the ones of the letter.

    Simple, isn’t it? And it is all possible with two re-usable functions:

    /*
      getpixelcolour(x, y)
      returns the rgba value of the pixel at position x and y
    */
    function getpixelcolour(x, y) {
      var pixels = cx.getImageData(0, 0, c.width, c.height);
      var index = ((y * (pixels.width * 4)) + (x * 4));
      return {
        r: pixels.data[index],
        g: pixels.data[index + 1],
        b: pixels.data[index + 2],
        a: pixels.data[index + 3]
      };
    }
     
    /*
      getpixelamount(r, g, b)
      returns the amount of pixels in the canvas of the colour 
      provided
    */
    function getpixelamount(r, g, b) {
      var pixels = cx.getImageData(0, 0, c.width, c.height);
      var all = pixels.data.length;
      var amount = 0;
      for (i = 0; i < all; i += 4) {
        if (pixels.data[i] === r &&
            pixels.data[i + 1] === g &&
            pixels.data[i + 2] === b) {
          amount++;
        }
      }
      return amount;
    }

    Add some painting functions to that and you have the game done. You can see a step by step guide of this online (and pull the code from GitHub) and there is a screencast describing the tricks and decisions on YouTube.

    The main thing to remember here is that it is very tempting to reach for libraries and tools to get things done quickly, but that it could mean that you think too complex. Browsers have very powerful tools built in for us, and in many cases it means you just need to be up-to-date and fearless in trying something “new” that comes out-of-the-box.

  5. The Proximity API

    Something that’s very nice with bringing the web to the mobile platform with Firefox OS and WebAPIs is the ability to connect more into the physical world. One part there is the Proximity API, which is also a W3C Working Draft – Proximity Events.

    What it is

    The API is about detecting how close the device is to any other physical object, by accessing the proximity sensor. There are two ways of working with proximity

    • Device proximity
    • User proximity

    From the spec:

    The DeviceProximityEvent interface provides web developers information about the distance between the hosting device and a nearby object.

    The UserProximityEvent interface provides web developers a user-agent- and platform-specific approximation that the hosting device has sensed a nearby object.

    Using it

    Working with proximity is as easy as adding a couple of event handlers, depending on what you want to do. The deviceproximity event works with the metric system, and you will get back the distance in centimeters (these examples take for granted that you have an existing proximityDisplay element to present the values in). You are also able to check the minimum and maximum distance the sensor in your device supports.

    window.ondeviceproximity = function (event) {
        // Check proximity, in centimeters
        var prox = "<strong>Proximity: </strong>" + event.value + " cm<br>";
            prox += "<strong>Min value supported: </strong>" + event.min + " cm<br>";
            prox += "<strong>Max value supported: </strong>" + event.max + " cm";
        proximityDisplay.innerHTML = prox;
    };

    It should be noted that the values sensors currently can return a quite small value, ranging from 0 up to 5 or 10 centimeters. In general, I believe the use case has been to detect if the user is holding the device up to the ear or not, but my personal opinion is that this could provide to be even more exciting if it supported, say, up to a meter!

    With userproximity, the value you get back is a near property on the event object, which is a boolean returning whether the user is near to the sensor or not.

    window.onuserproximity = function (event) {
        // Check user proximity
        var userProx = "<strong>User proximity - near: </strong>" + event.near + "<br>";
        userProximityDisplay.innerHTML = userProx;
    };

    I’ve also added device and proximity code and testing to the Firefox OS Boilerplate App so feel free to get the latest code there and play around with it.

    Web browser support

    The Proximity API is currently supported in:

    Conclusion

    Working with proximity is yet another example of crossing the gap between software and real physical context, and showing just how powerful the web can be. We hope to see you creating many interesting things based on it!

  6. Building a Todo app for Firefox OS, part 1

    This is the first part out of two in a tutorial series where we will build a Todo app for Firefox OS from scratch. I assume you have some understanding of HTML5, CSS3, JavaScript, jQuery/Zepto, and Backbone.js. In this part we will handcraft a properly structured and semantic UI of a Todo app using best practices for designing UIs for mobile.

    The source for the Todo app is available on GitHub.

    Setting Up the Environment

    We will use volo as our package manager and build tool.

    Step 1

    First you need to install Node.js because volo depends on it. Windows and Mac users can download it from here. But for Linux users, I recommend you use the package manager: instructions for installation using package manager on different distros.

    Step 2

    Install volo using the following command.

    npm install -g volo

    Make sure you use `sudo` before above command in *nix environment.

    Step 3

    Create a blank project fos-todo-app using `volo create` command.

    volo create fos-todo-app

    This will create a folder fos-todo-app and copy required volo project files from GitHub.

    Remember we will work only with the files in fos-todo-app/www directory. If you have never worked with volo before, [Streamline your Process with Volo](http://net.tutsplus.com/tutorials/javascript-ajax/streamline-your-process-with-volo/) is a recommended read.

    Step 4

    Make sure you have the latest stable version of Firefox installed. Then [install the Firefox OS simulator add-on](https://addons.mozilla.org/en-US/firefox/addon/firefox-os-simulator/). At the end of this article we will test UI of our app in this simulator.

    Step 5

    Get the [MozTT font](https://github.com/mozilla-b2g/moztt/tree/master/MozTT) and install it. MozTT is the font used in Firefox OS. It’s an optional step but it’s better to install this font on your system so you can get consistent look and feel in the Firefox OS Simulator and the real phone.

    Todo View

    The first UI that we will build will show a title in the header, Add/Delete buttons in the footer and a todo list. This view will be used for viewing, editing, mark as complete, and deleting tasks.

    Todo View - Firefox OS

    Add role="application" attribute to the `body` element and write following HTML for the Todo View.

    <section id="view-todos" role="region">
      <header>
        <h1>Todos</h1>
      </header>
     
      <article class="view-content">
        <ul id="todo-list" class="todo-list reset-list" role="list">
          <li role="listitem">
            <label>
              <input type="checkbox">
              <span>My task 1</span>
            </label>
     
            <input type="text" aria-hidden="true">
            <button class="btn edit"><span>Edit</span></button>
          </li>
     
          <li role="listitem">
            <label>
              <input type="checkbox" checked>
              <span>My task 2</span>
            </label>
     
            <input type="text" aria-hidden="true">
            <button class="btn edit"><span>Edit</span></button>
          </li>
        </ul>
      </article>
     
      <footer>
        <menu role="toolbar">
          <button role="menuitem" class="btn add"><span>Add</span></button>
          <button role="menuitem" class="btn del" disabled><span>Delete</span></button>
        </menu>
      </footer>
    </section><!--end view-todos-->

    Each view is assigned a role="region". Within the view, you can have header, footer and any container element having the view-content class which will contain the contents of the view.

    In the above view’s content, we have ul[role=list] which contains tasks entered by user. For testing purposes, I added two dummy tasks so you can understand each list item’s (`li[role=listitem]`) structure. Within each list item we have a label element containing a <input type="checkbox"> and a span element containing the text of task. The second element in the list item contains a <input type="text"> element which is initially hidden using attribute aria-hidden="true". Finally the third element is .btn.edit (edit button).

    Note: Of course it’s not magic. We will write CSS for all these attributes. Check out ARIA and Progressive Enhancement if you are new to WAI-ARIA.

    The purpose of placing the label in the list item is to display each task’s text and input[type=text] (which is initially hidden) will be used to edit that text. Any task can enter edit mode when user tap on .btn.edit (edit button). Similarly, tasks are “marked as completed” when user tap on label.

    In the footer we have menu[role=toolbar] containing Add/Delete buttons. Later using CSS for these buttons, we will display a svg icon in background and hide an inner span in it.

    Add View

    The second and final view in our app will be used to add tasks to the todo list.

    Add View

    In this view we have a textbox for entering a task’s text, and a insert contact link will be used to add the contact number using Web Activities. Here’s the HTML for Add View.

    <section id="view-add" role="region">
      <header>
        <h1>[+] Todo</h1>
      </header>
     
      <section class="view-content">
        <div class="wrapper">
          <menu class="options">
            <ul id="activities" class="reset-list" role="list">
              <li role="listitem"><a href="#"><label for="task">[Insert Contact]</label></a></li>
            </ul>
          </menu>
     
          <form aria-owns="btn-add-done">
            <input type="text" name="task" id="task" required>
          </form>
        </div>
      </section>
     
      <footer>
        <menu role="toolbar">
          <button id="btn-add-done" role="menuitem" class="btn done" disabled><span>Done</span></button>
          <button role="menuitem" class="btn del"><span>Cancel</span></button>
        </menu>
      </footer>
    </section><!--end view-add-->

    Note that the contents in section.view-content is wrapped using div.wrapper so we can limit its max-width and right align menu.options.

    Second thing to note here is the aria-owns attribute on form element. This attribute relates to the form with btn-add-done.

    Element Styles

    Let’s write the CSS for the HTML elements. An explanation is given in comments above each selector.

    /* Stretch vertically */
    html, body { height: 100%; }
     
    body {
      background: radial-gradient(ellipse at center, rgba(231,76,60,1) 0%,rgba(192,57,43,1) 100%);
      color: #fff;
      font-family: MozTT, sans-serif;
     
      /* Reset base size */
      font-size: 16px;
     
      /* Set font size relative to base size */
      /* Check <a href="http://snook.ca/archives/html_and_css/font-size-with-rem">this</a> article on rem usage */
      font-size: 1.4rem;
     
      font-weight: 300;
     
      /* Remove spacing */
      margin: 0;
    }
     
    h1, h2, h3, h4, h5, h6 { font-weight: 300; }
     
    h1 { font-size: 3rem; }
     
    a {
      color: #FFA49E;
      text-decoration: none;
      text-shadow: 0px 1px 1px rgba(0,0,0,.3);
    }
    a:hover { color: #fff; }
     
    input, button, select, textarea {
      border-radius: 0;
      box-shadow: none;
    }
    input[type=text], textarea, select {
      border: none;
      font-family: MozTT, sans-serif;
      font-size: 1.3rem;
      font-weight: 300;
      padding: .7rem .8rem;
    }

    View Specific Styles

    #view-todos > .view-content {
      margin-left: 0;
      margin-right: 0;
    }
     
    #view-add > .view-content {
      margin-top: 2rem;
    }
    #view-add > .view-content > .wrapper {
      overflow: hidden;
      margin: 0 auto;
      max-width: 800px;
      width: 100%;
    }
    #view-add input[name=task] {
      width: 100%;
    }
    #view-add .options {
      margin: 0 0 .5rem 0;
      text-align: right;
    }
    #view-add .options [role=listitem] {
      margin: .5rem 0;
    }
    #view-add .options a {
      padding: .4rem;
    }

    Module Styles

    View Module

    /* All views have region role so selecting them with attribute selector  */
    [role=region] {
      background: radial-gradient(ellipse at center, rgba(231,76,60,1) 0%,rgba(192,57,43,1) 100%);
     
      /* Stretch both vertically/horizontally */
      top: 0; right: 0; bottom: 0; left: 0;
     
      position: fixed;
      overflow-x: hidden;
    }
    [role=region] > header {
      margin: .5rem 0 1rem 0;
      text-align: center;
    }
    [role=region] > header > h1 {
      margin: 0;
      text-shadow: 0px 1px 1px rgba(0,0,0,.4);
    }
    [role=region] > .view-content {
      margin: 0 1rem 4rem 1rem;
    }
    [role=region] > footer {
      background: rgba(0,0,0,.2);
      right: 0; bottom: 0; left: 0;
      position: fixed;
      text-align: center;
    }
    [role=region] > footer > menu[role=toolbar] {
      margin: 0;
      padding: 0;
    }

    Button Module

    .btn {
      border: none;
      width: 3.5rem;
      height: 3.5rem;
    }
    .btn > span {
      display: none;
    }
    .btn:disabled {
      opacity: .2;
    }
    .btn.done {
      background: url(../img/check.svg) no-repeat center center;
    }
    .btn.add {
      background: url(../img/add.svg) no-repeat center center;
    }
    .btn.del {
      background: url(../img/del.svg) no-repeat center center;
    }
    .btn.edit {
      background: url(../img/edit.svg) no-repeat center center;
    }
    .btn:hover {
      background-color: rgba(255,255,255,.1);
    }

    Todo List Module

    .todo-list > li {
      border-bottom: 1px solid rgba(255,255,255,.1);
      position: relative;
    }
    .todo-list > li > .btn {
      top: 0; right: 0;
      position: absolute;
      height: 3.9rem;
    }
    .todo-list label {
      border-bottom: 1px solid rgba(0, 0, 0, 0.1);
      display: block;
      padding: 1rem 2.8rem 1rem 1rem;
    }
    .todo-list > li:last-child,
    .todo-list > li:last-child > label {
      border-bottom: none;
    }
    .todo-list label > span {
      transition: all .5s;
    }
     
    /***
      This selector is interesting. It creates a line-through and
      decrease opacity of text in span when checkbox is checked
    ***/
    .todo-list input[type=checkbox]:checked + span {
      text-decoration: line-through;
      opacity: .4;
    }
     
    .todo-list > li > input[type=text] {
      margin: .4rem;
      /* removing input padding and margin from 100% */
      width: calc(100% - 2.3rem);
    }

    Utility Styles

    .reset-list {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    [aria-hidden=true] {
      display: none !important;
    }

    Animations

    Following are a few animation effects that we will use to animate our views. Although we will use Zepto.js which on run-time generates CSS3 animations using JavaScript, I prefer to write my own animations using CSS3 and make use of it by applying/removing CSS classes on DOM elements.

    Zepto is a minimalist JavaScript library for modern browsers with a largely jQuery-compatible API. If you use jQuery, you already know how to use Zepto. ‐ zeptojs.com

    Check out the How to use CSS Animations tutorial for understanding CSS3 Animations better.

    .slide-up-in {
      animation-name: slide-up-in;
      animation-duration: .6s;
      transform: translateY(0%);
      opacity: 1;
    }
    @keyframes slide-up-in {
      0% { transform: translateY(30%); opacity: 0; }
      100% { transform: translateY(0%); opacity: 1; }
    }
     
    .slide-down-out {
      animation-name: slide-down-out;
      animation-duration: .6s;
      transform: translateY(30%);
      opacity: 0;
    }
    @keyframes slide-down-out {
      0% { transform: translateY(0%); opacity: 1; }
      100% { transform: translateY(30%); opacity: 0; }
    }
     
    .slide-right-in {
      animation-name: slide-right-in;
      animation-duration: .6s;
      transform: translateX(0%);
    }
    @keyframes slide-right-in {
      0% { transform: translateX(-100%); }
      100% { transform: translateX(0%); }
    }
     
    .slide-left-out {
      animation-name: slide-left-out;
      animation-duration: .6s;
      transform: translateX(-100%);
    }
    @keyframes slide-left-out {
      0% { transform: translateX(0%); }
      100% { transform: translateX(-100%); }
    }

    Testing in Firefox OS Simulator

    Firefox OS Simulator

    You can pretty easily test the UI we have developed using the Firefox OS Simulator. All you need is a manifest.webapp file in root directory (fos-todo-app/www). Add the following json in it.

    {
      "version": "0.1",
      "name": "Todos",
      "description": "Awesome todo app by iFadey",
      "launch_path": "/index.html",
      "icons": {
        "16": "/img/icons/icon-16.png",
        "48": "/img/icons/icon-48.png",
        "128": "/img/icons/icon-128.png"
      },
      "developer": {
        "name": "Fawad Hassan",
        "url": "http://ifadey.com"
      },
      "installs_allowed_from": ["*"],
      "appcache_path": "/cache.manifest",
      "default_locale": "en"
    }

    Currently I haven’t added an app icon but don’t worry about it. Firefox OS adds a default app icon if it doesn’t find one mentioned in the manifest file. Now open the simulator tab from Tools > Web Developer > Firefox OS Simulator. Then click Add Directory button and select the manifest file from our app directory. This will add our app in the simulator.

    End of part 1

    Now you have gotten started with the Todo app and have gotten going with a few easy steps. In next part we will add life in our app using JavaScript (Backbone/Zepto). We will create Todo model, collection, and views and for the sake of simplicity, we will only store our todo collection in IndexedDB. We will also make use of Web Activities to inject contact number in text of todo task.

  7. MDN sprint for better web tech resources — join in!

    MDN is one of our most important resources, and the core of knowledge and sharing for developers around the world. Additionally, it’s one of the vital cornerstones for all information we share at Mozilla Hacks, so in whatever way you can take part, it is highly appreciated. – Editor’s note

    Over on the Mozilla Developer Network site, this Friday and Saturday (May 31 and June 1), we’re having the latest in our series of “MDN sprints”. This is a chance for you to learn about a web development topic, and help improve the resources about it on MDN by sharing what you learn or what you already know. Please join us!

    About what?

    The major topical focus for this sprint is Web device APIs, which give JavaScript code access to device hardware. How about trying them out, and then writing some helpful code examples?

    Another timely topic is mixed content blocking, which just arrived in the Firefox Aurora channel. Help us explain to Web developers how to fix sites so users won’t be tripped up by mixed-security content.

    But those are just suggestions; any topic for Web developers or Mozilla developers is fair game. You can also find more info and ideas on the MDN sprint wiki page.

    Where?

    You can join in from anywhere in the world. Of course you could just dive into MDN, but part of the point of a sprint is to do it with other people. Join the #devmo channel on irc.mozilla.org to talk with other sprinters, about what you’re doing, they’re doing, or whatever. (Here’s info about IRC if you’re not familiar with it.) We might also do a Google Hangout, so ask about that when you drop in.

    If you happen to be in San Francisco or Paris, we’re holding in-person meetups for this sprint on June 1st, at the Mozilla spaces in those cities. Come on by and sprint in person!

    When?

    The sprint officially runs from 8:00 a.m. PDT on May 31st (Starting time in your timezone) to 5:00 p.m. PDT on June 1st (Ending time in your timezone). Of course, you can start earlier or continue later, and stay for as long or as short a time as fits your schedule.

    Sound interesting? Give it a try!

  8. Optimizing your JavaScript game for Firefox OS

    When developing on a quad core processor with 16 gigabytes of RAM you can easily forget to consider how it will perform on a mobile device. This article will detail some best practices and things to consider for moving a game to Firefox OS or any similar hardware target.

    Making the best of 256 Mb RAM/800 Mhz CPU

    There are many areas of focus to keep in mind while developing a game. When your goal is to draw 60 times a second, garbage collection and inefficient drawing calls start to get in your way. Let’s start with the basics…

    Don’t over-optimize

    This might sound counter-intuitive in an article about game optimization but optimization is the last step; performed on complete, working code. While it’s never a bad idea to keep these tips and tricks in mind, you don’t know whether you’ll need them until you’ve finished the game and played it on a device.

    Optimize Drawing

    Drawing on HTML5 2D canvas is the biggest bottleneck in most JavaScript games, as all other updates are usually just algebra without touching the DOM. Canvas operations are hardware accelerated, which can give you some extra room to breath.

    Use whole-pixel rendering

    Sub-pixel rendering occurs when you render objects on a canvas without whole values.

    ctx.drawImage(myImage, 0.3, 0.5)

    This causes the browser to do extra calculations to create the anti-aliasing effect. To avoid this, make sure to round all co-ordinates used in calls to drawImage using Math.floor or as you’ll reader further in the article, bitwse operators.

    jsPerf – drawImage whole pixels.

    Cache drawing in an offscreen canvas

    If you find yourself with complex drawing operations on each frame, consider creating an offscreen canvas, draw to it once (or whenever it changes) on the offscreen canvas, then on each frame draw the offscreen canvas.

    myEntity.offscreenCanvas = document.createElement(“canvas”);
    myEntity.offscreenCanvas.width = myEntity.width;
    myEntity.offscreenCanvas.height = myEntity.height;
    myEntity.offscreenContext = myEntity.offscreenCanvas.getContext(“2d”);
     
    myEntity.render(myEntity.offscreenContext);

    Use moz-opaque on the canvas tag (Firefox Only)

    If your game uses canvas and doesn’t need to be transparent, set the moz-opaque attribute on the canvas tag. This information can be used internally to optimize rendering.

    <canvas id="mycanvas" moz-opaque></canvas>

    Described more in Bug 430906 – Add moz-opaque attribute on canvas.

    Scaling canvas using CSS3 transform

    CSS3 transforms are faster by using the GPU. Best case is to not scale the canvas or have a smaller canvas and scale up rather than a bigger canvas and scale down. For Firefox OS, target 480 x 320 px.

    var scaleX = canvas.width / window.innerWidth;
    var scaleY = canvas.height / window.innerHeight;
     
    var scaleToFit = Math.min(scaleX, scaleY);
    var scaleToCover = Math.max(scaleX, scaleY);
     
    stage.style.transformOrigin = "0 0"; //scale from top left
    stage.style.transform = "scale(" + scaleToFit + ")";

    See it working in this jsFiddle.

    Nearest-neighbour rendering for scaling pixel-art

    Leading on from the last point, if your game is themed with pixel-art, you should use one of the following techniques when scaling the canvas. The default resizing algorithm creates a blurry effect and ruins the beautiful pixels.

    canvas {
      image-rendering: crisp-edges;
      image-rendering: -moz-crisp-edges;
      image-rendering: -webkit-optimize-contrast;
      -ms-interpolation-mode: nearest-neighbor;
    }

    or

    var context = canvas.getContext(‘2d’);
    context.webkitImageSmoothingEnabled = false;
    context.mozImageSmoothingEnabled = false;
    context.imageSmoothingEnabled = false;

    More documentation is available on MDN for image-rendering.

    CSS for large background images

    If like most games you have a static background image, use a plain DIV element with a CSS background property and position it under the canvas. This will avoid drawing a large image to the canvas on every tick.

    Multiple canvases for layers

    Similar to the last point, you may find you have some elements that are frequently changing and moving around whereas other things (like UI) never change. An optimization in this situation is to create layers using multiple canvas elements.

    For example you could create a UI layer that sits on top of everything and is only drawn during user input. You could create game layer where the frequently updating entities exist and a background layer for entities that rarely update.

    Don’t scale images in drawImage

    Cache various sizes of your images on an offscreen canvas when loading as opposed to constantly scaling them in drawImage.

    jsPerf – Canvas drawImage Scaling Performance.

    Be careful with heavy physics libraries

    If possible, roll your own physics as libraries like Box2D don’t perform well on low-end Firefox OS devices.

    When asm.js support lands in Firefox OS, Emscripten-compiled libraries can take advantage of near-native performance. More reading in Box2d Revisited.

    Use WebGL instead of Context 2D

    Easier said than done but giving all the heavy graphics lifting to the GPU will free up the CPU for greater good. Even though WebGL is 3D, you can use it to draw 2D surfaces. There are some libraries out there that aim to abstract the drawing contexts.

    Minimize Garbage Collection

    JavaScript can spoil us when it comes to memory management. We generally don’t need to worry about memory leaks or conservatively allocating memory. But if we’ve allocated too much and garbage collection occurs in the middle of a frame, that can take up valuable time and result in a visible drop in FPS.

    Pool common objects and classes

    To minimise the amount of objects being cleaned during garbage collection, use a pre-initialised pool of objects and reuse them rather than creating new objects all the time.

    Code example of generic object pool:

    Avoid internal methods creating garbage

    There are various JavaScript methods that create new objects rather than modifying the existing one. This includes: Array.slice, Array.splice, Function.bind.

    Read more about JavaScript garbage collection

    Avoid frequent calls to localStorage

    LocalStorage uses file IO and blocks the main thread to retrieve and save data. Use an in-memory object to cache the values of localStorage and even save writes for when the player is not mid-game.

    Code example of an abstract storage object:

    Async localStorage API with IndexedDB

    IndexedDB is a non-blocking API for storing data on the client but may be overkill for small and simple data. Gaia’s library to make localStorage API asynchronous, using IndexedDB is available on Github: async_storage.js.

    Miscellaneous micro-optimization

    Sometimes when you’ve exhausted all your options and it just won’t go any faster, you can try some micro-optimizations below. However do note that these only start to make a difference in heavy usage when every millisecond counts. Look for them in your hot game loops.

    Use x | 0 instead of Math.floor
    Clear arrays with .length = 0 to avoid creating a new Array
    Sacrifice some CPU time to avoid creating garbage.
    Use if .. else over switch
    jsPerf – switch vs if-else
    Date.now() over (+ new Date)
    jsPerf – Date.now vs new Date().getTime() vs +new Date
    Or performance.now() for a sub-millisecond solution
    Use TypedArrays for floats or integers (e.g. vectors and matrices)
    gl-matrix – Javascript Matrix and Vector library for High Performance WebGL apps

    Conclusion

    Building for mobile devices and not-so-strong hardware is a good and creative exercise, and we hope you will want to make sure your games work well on all platforms!

  9. Content Security Policy 1.0 lands in Firefox Aurora

    The information in this article is based on work together with Ian Melven, Kailas Patil and Tanvi Vyas.

    We have just landed support for the Content Security Policy (CSP) 1.0
    specification
    in Firefox Aurora (Firefox 23), available as of tomorrow (May 30th). CSP is a security mechanism that aims to protect a website against content injection attacks by providing a whitelist of known-good domain names to accept JavaScript (and other content) from. CSP does this by sending a Content-Security-Policy header with the document it protects (yes, we lost the X prefix with the 1.0 version of the spec).

    To effectively protect against XSS, a few JavaScript features have to be
    disabled:

    • All inline JavaScript is disallowed. This means, that all the JavaScript code must be placed in a separate file that is linked via <script src=... >
    • All calls to functions which allow JavaScript code being executed from strings (e.g., eval) are disabled

    CSP now more intuitive and consistent

    While Firefox has had support for CSP since its invention here at Mozilla, things have been changing a lot. The streamlined development of a specification within the W3C has made the concept more intuitive and consistent. Most directives in a CSP header are now of a unified form which explicitly specifies the type of content you want to restrict:

    • img-src
    • object-src
    • script-src
    • style-src and so on.

    Oh and if you feel like you must allow less secure JavaScript coding styles, you can add the values unsafe-inline or unsafe-eval to your list of script sources. (This used to be inline-script and eval-script before).

    Start protecting your website by implementing CSP now!

    But wait – isn’t that a bit tedious… Writing a complex policy and making sure that you remembered all the resources that your website requires? Don’t fret! Here comes UserCSP again!

    Generate your Content Security Policies with UserCSP!

    During the last few months, Kailas Patil, a student in our Security Mentorship Program has continued his GSoC work from last year to update UserCSP.

    UserCSP is a Firefox add-on that helps web developers and security-minded users use CSP. Web developers can create a Content Security Policy (CSP) for their site by using UserCSP’s infer CSP feature. This feature can list required resource URLs and turn them into a policy ready to plug into a CSP header.

    In addition, UserCSP is the first step to expose a policy enforcement mechanism directly to web users. Furthermore, users can enforce a stricter policy than a page supplies through the add-on or apply a policy to certain websites that don’t currently support CSP.

    While earlier versions of UserCSP were more aligned to content security policies as originally invented at Mozilla, this version is updated to be in compliance with the CSP 1.0 specification. This means that policies derived with this add-on may work in all browsers as soon as they support the specification. Hooray!

    As this evolves and ships, our MDN documentation on Content Security Policy (CSP) will keep on evolving, and we also plan to write more about this in the Mozilla Security Blog in the next few weeks, so stay tuned!

  10. Compiling to JavaScript, and Debugging with Source Maps

    Update 2013/05/29: I have updated the article to reflect recent changes in the source map specification where the //@ syntax for linking a source map to a script has been deprecated in favor of //# due to problems with Internet Explorer.

    This is a tutorial on how to write a compiler which generates JavaScript as its target language, and maintains line and column meta-data in source maps for debugging. Storing line and column coordinates in a source map allows the end-user of the compiler to debug the source code that they wrote, rather than the ugly, generated JavaScript they are not familiar with.

    In this tutorial, we will be compiling a small Reverse Polish Notation, or RPN, language to JavaScript. The language is super simple, and is nothing more than simple arithmetic with variable storage and output capabilities. We are keeping the language simple so that we can focus on integrating source maps with the compiler, rather than language implementation details.

    Availability

    Initial support for source maps in the debugger is available in Firefox 23 (Aurora at time of writing) with more improvements coming in Firefox 24 (Nightly at time of writing). Chrome DevTools also have support for source maps.

    Overview of the Source Language

    RPN uses postfix notation, meaning that the operator follows its two operands. One of the benefits of RPN is that as long as we limit ourselves to binary operators, we do not need any parentheses, and do not need to worry about operator precedence.

    Here is an example program in our source language:

    a 5 =;
    b 3 =;
    c a b + 4 * =;

    This is an equivalent program written in a language which uses infix notation for its arithmetic operators:

    a = 5;
    b = 3;
    c = (a + b) * 4;

    Our language will support addition, subtraction, multiplication, division, assignment, and printing. The print operator’s first operand is the value to print, the second operand is how many times to print the value and must be greater than or equal to one:

    5 1 print;
    # Output:
    # 5
     
    3 4 print;
    # Output:
    # 3
    # 3
    # 3
    # 3
     
    4 print;
    # Syntax error
     
    n -1 =;
    4 n print;
    # Runtime error

    Lastly, division by zero should throw an error:

    5 0 /;
    # Runtime error

    Getting Setup

    We will be writing our compiler on Node.js, using Jison to generate the parser for our language from a grammar, and using the source-map library to help generate source maps.

    The first step is to download and install Node.js if you don’t already have it on your system.

    After you have installed Node.js, use its package manager npm to create a new project for the compiler:

    $ mkdir rpn
    $ cd rpn/
    $ npm init .

    After the last command, npm will prompt you with a bunch of questions. Enter your name and email, answer ./lib/rpn.js for the main module/entry point, and just let npm use the defaults that it supplies for the rest of the questions.

    Once you have finished answering the prompts, create the directory layout for the project:

    $ mkdir lib
    $ touch lib/rpn.js
    $ mkdir -p lib/rpn

    The public API for the compiler will reside within lib/rpn.js, while the submodules we use to implement various things such as the lexer and abstract syntax tree will live in lib/rpn/*.js.

    Next, open up the package.json file and add jison and source-map to the project’s dependencies:

    ...
    "dependencies": {
      "jison": ">=0.4.4",
      "source-map": ">=0.1.22"
    },
    ...

    Now we will install a link to our package in Node.js’s globally installed packages directory. This allows us to import our package from the Node.js shell:

    $ npm link .

    Make sure that everything works by opening the Node.js shell and importing our package:

    $ node
    > require("rpn")
    {}

    Writing the Lexer

    A lexer (also known as a scanner or tokenizer) breaks the inputted raw source code into a stream of semantic tokens. For example in our case, we would want to break the raw input string "5 3 +;" into something like ["5", "3", "+", ";"].

    Because we are using Jison, rather than writing the lexer and parser by hand, our job is much easier. All that is required is to supply a list of rules that describe the types of tokens we are expecting. The left hand side of the rules are regular expressions to match individual tokens, the right hand side are the snippets of code to execute when an instance of the corresponding token type is found. These tokens will be passed on to the parser in the next phase of the compiler.

    Create the rules for lexical analysis in lib/rpn/lex.js:

    exports.lex = {
      rules: [
        ["\\s+",                   "/* Skip whitespace! */"],
        ["#.*\\n",                 "/* Skip comments! */"],
        [";",                      "return 'SEMICOLON'"],
        ["\\-?[0-9]+(\\.[0-9]+)?", "return 'NUMBER';"],
        ["print",                  "return 'PRINT';"],
        ["[a-zA-Z][a-zA-Z0-9_]*",  "return 'VARIABLE';"],
        ["=",                      "return '=';"],
        ["\\+",                    "return '+';"],
        ["\\-",                    "return '-';"],
        ["\\*",                    "return '*';"],
        ["\\/",                    "return '/';"],
        ["$",                      "return 'EOF';"]
      ]
    };

    Writing the Parser

    The parser takes the tokens from the lexer one at a time and confirms that the input is a valid program in our source language.

    Once again, the task of writing the parser is much easier than it would otherwise be thanks to Jison. Rather than writing the parser ourselves, Jison will programmatically create one for us if we provide a grammar for the language.

    If all we cared about was whether the input was a valid program, we would stop here. However, we are also going to compile the input to JavaScript, and to do that we need to create an abstract syntax tree. We build the AST in the code snippets next to each rule.

    A typical grammar contains productions with the form:

    LeftHandSide → RightHandSide1
                 | RightHandSide2
                 ...

    However, in Jison we are a) writing in JavaScript, and b) also providing code to execute for each rule so that we can create the AST. Therefore, we use the following format:

    LeftHandSide: [
      [RightHandSide1, CodeToExecute1],
      [RightHandSide2, CodeToExecute2],
      ...
    ]

    Inside the code snippets, there are a handful of magic variables we have access to:

    • $$: The value of the left hand side of the production.
    • $1/$2/$3/etc: The value of the the nth form in the right hand side of the production.
    • @1/@2/@3/etc: An object containing the line and column coordinates where the nth form in the right hand side of the production was parsed.
    • yytext: The full text of currently matched rule.

    Using this information, we can create the grammar in lib/rpn/bnf.js:

    exports.bnf = {
      start: [
        ["input EOF", "return $$;"]
      ],
      input: [
        ["",           "$$ = [];"],
        ["line input", "$$ = [$1].concat($2);"]
      ],
      line: [
        ["exp SEMICOLON", "$$ = $1;"]
      ],
      exp: [
        ["NUMBER",           "$$ = new yy.Number(@1.first_line, @1.first_column, yytext);"],
        ["VARIABLE",         "$$ = new yy.Variable(@1.first_line, @1.first_column, yytext);"],
        ["exp exp operator", "$$ = new yy.Expression(@3.first_line, @3.first_column, $1, $2, $3);"]
      ],
      operator: [
        ["PRINT", "$$ = new yy.Operator(@1.first_line, @1.first_column, yytext);"],
        ["=",     "$$ = new yy.Operator(@1.first_line, @1.first_column, yytext);"],
        ["+",     "$$ = new yy.Operator(@1.first_line, @1.first_column, yytext);"],
        ["-",     "$$ = new yy.Operator(@1.first_line, @1.first_column, yytext);"],
        ["*",     "$$ = new yy.Operator(@1.first_line, @1.first_column, yytext);"],
        ["/",     "$$ = new yy.Operator(@1.first_line, @1.first_column, yytext);"]
      ]
    };

    Implementing the Abstract Syntax Tree

    Create the definitions for the abstract syntax tree nodes in lib/rpn/ast.js.

    Since we will be maintaining line and column information in all of the AST nodes, we can reuse some code by making a base prototype:

    var AstNode = function (line, column) {
      this._line = line;
      this._column = column;
    };

    The definitions for the rest of the AST nodes are pretty straight forward. Link up the prototype chain, assign relevant attributes, and don’t forget to call AstNode‘s constructor:

    exports.Number = function (line, column, numberText) {
      AstNode.call(this, line, column);
      this._value = Number(numberText);
    };
    exports.Number.prototype = Object.create(AstNode.prototype);
     
    exports.Variable = function (line, column, variableText) {
      AstNode.call(this, line, column);
      this._name = variableText;
    };
    exports.Variable.prototype = Object.create(AstNode.prototype);
     
    exports.Expression = function (line, column, operand1, operand2, operator) {
      AstNode.call(this, line, column);
      this._left = operand1;
      this._right = operand2;
      this._operator = operator;
    };
    exports.Expression.prototype = Object.create(AstNode.prototype);
     
    exports.Operator = function (line, column, operatorText) {
      AstNode.call(this, line, column);
      this.symbol = operatorText;
    };
    exports.Operator.prototype = Object.create(AstNode.prototype);

    Compilation

    Generated JavaScript

    Before we generate JavaScript, we need a plan. There are a couple ways we can structure the outputted JavaScript.

    One strategy is to translate the RPN expressions to the equivalent human readable JavaScript expression we would create if we had been writing JavaScript all along. For example, if we were to port this RPN example:

    a 8 =;
    b 2 =;
    c a b 1 - / =;

    We might write the following JavaScript:

    var a = 8;
    var b = 3;
    var c = a / (b - 1);

    However, this means that we are completely adopting the nuances of JavaScript’s arithmetic. In an earlier example, we saw that a helpful runtime error was thrown when any number was divided by zero. Most languages throw an error when this occurs, however JavaScript does not; instead, the result is Infinity. Therefore, we can’t completely embrace JavaScript’s arithmetic system, and we must generate some code to check for divide-by-zero errors ourselves. Adding this code gets a little tricky if we want to maintain the strategy of generating human readable code.

    Another option is treating the JavaScript interpreter as a stack machine of sorts and generating code that pushes and pops values to and from a stack. Furthermore, stack machines are a natural fit for evaluating RPN. In fact, it is such a good fit that RPN “was independently reinvented by F. L. Bauer and E. W. Dijkstra in the early 1960s to reduce computer memory access and utilize the stack to evaluate expressions.”

    Generating JavaScript code for the same example above, but utilizing the JavaScript interpreter as a stack machine, might look something like this:

    push(8);
    push('a');
    env[pop()] = pop();
    push(2);
    push('b');
    env[pop()] = pop();
    push('a');
    push('b');
    push(1);
    temp = pop();
    push(pop() - temp);
    temp = pop();
    if (temp === 0) throw new Error("Divide by zero");
    push(pop() / temp);
    push('c');
    env[pop()] = pop();

    This is the strategy we will follow. The generated code is a bit larger, and we will require a preamble to define push, pop, etc, but compilation becomes much easier. Furthermore, the fact that the generated code isn’t as human readable only highlights the benefits of using source maps!

    Creating Source Maps

    If we weren’t generating source maps along with our generated JavaScript, we could build the generated code via concatenating strings of code:

    code += "push(" + operand1.compile() + " "
      + operator.compile() + " "
      + operand2.compile() + ");\n";

    However, this doesn’t work when we are creating source maps because we need to maintain line and column information. When we concatenate strings of code, we lose that information.

    The source-map library contains SourceNode for exactly this reason. If we add a new method on our base AstNode prototype, we can rewrite our example like this:

    var SourceNode = require("source-map").SourceNode;
    AstNode.prototype._sn = function (originalFilename, chunk) {
      return new SourceNode(this._line, this._column, originalFilename, chunk);
    };
     
    ...
     
    code = this._sn("foo.rpn", [code,
                                "push(",
                                operand1.compile(), " ",
                                operator.compile(), " ",
                                operand2.compile(), ");\n"]);

    Once we have completed building the SourceNode structure for the whole input program, we can generate the compiled source and the source map by calling the SourceNode.prototype.toStringWithSourceMap method. This method returns an object with two properties: code, which is a string containing the generated JavaScript source code; and map, which is the source map.

    Implementing Compilation

    Now that we have a strategy for generating code, and understand how to maintain line and column information so that we can generate source maps easily, we can add the methods to compile our AST nodes to lib/rpn/ast.js.

    To play nice with the global JavaScript environment, we will namespace push, pop, etc, under __rpn.

    function push(val) {
      return ["__rpn.push(", val, ");\n"];
    }
     
    AstNode.prototype.compile = function (data) {
      throw new Error("Not Yet Implemented");
    };
    AstNode.prototype.compileReference = function (data) {
      return this.compile(data);
    };
    AstNode.prototype._sn = function (originalFilename, chunk) {
      return new SourceNode(this._line, this._column, originalFilename, chunk);
    };
     
    exports.Number.prototype.compile = function (data) {
      return this._sn(data.originalFilename,
                      push(this._value.toString()));
    };
     
    exports.Variable.prototype.compileReference = function (data) {
      return this._sn(data.originalFilename,
                      push(["'", this._name, "'"]));
    };
    exports.Variable.prototype.compile = function (data) {
      return this._sn(data.originalFilename,
                      push(["window.", this._name]));
    };
     
    exports.Expression.prototype.compile = function (data) {
      var temp = "__rpn.temp";
      var output = this._sn(data.originalFilename, "");
     
      switch (this._operator.symbol) {
      case 'print':
        return output
          .add(this._left.compile(data))
          .add(this._right.compile(data))
          .add([temp, " = __rpn.pop();\n"])
          .add(["if (", temp, " <= 0) throw new Error('argument must be greater than 0');\n"])
          .add(["if (Math.floor(", temp, ") != ", temp,
                ") throw new Error('argument must be an integer');\n"])
          .add([this._operator.compile(data), "(__rpn.pop(), ", temp, ");\n"]);
      case '=':
        return output
          .add(this._right.compile(data))
          .add(this._left.compileReference(data))
          .add(["window[__rpn.pop()] ", this._operator.compile(data), " __rpn.pop();\n"]);
      case '/':
        return output
          .add(this._left.compile(data))
          .add(this._right.compile(data))
          .add([temp, " = __rpn.pop();\n"])
          .add(["if (", temp, " === 0) throw new Error('divide by zero error');\n"])
          .add(push(["__rpn.pop() ", this._operator.compile(data), " ", temp]));
      default:
        return output
          .add(this._left.compile(data))
          .add(this._right.compile(data))
          .add([temp, " = __rpn.pop();\n"])
          .add(push(["__rpn.pop() ", this._operator.compile(data), " ", temp]));
      }
    };
     
    exports.Operator.prototype.compile = function (data) {
      if (this.symbol === "print") {
        return this._sn(data.originalFilename,
                        "__rpn.print");
      }
      else {
        return this._sn(data.originalFilename,
                        this.symbol);
      }
    };

    Gluing it Together

    From here we have done all the difficult work, and we can run a victory lap by connecting the modules together with a public API, and by creating a command line script to call the compiler.

    The public API resides in lib/rpn.js. It also contains the preamble, to initialize __rpn:

    var jison = require("jison");
    var sourceMap = require("source-map");
    var lex = require("./rpn/lex").lex;
    var bnf = require("./rpn/bnf").bnf;
     
    var parser = new jison.Parser({
      lex: lex,
      bnf: bnf
    });
     
    parser.yy = require("./rpn/ast");
     
    function getPreamble () {
      return new sourceMap.SourceNode(null, null, null, "")
        .add("var __rpn = {};\n")
        .add("__rpn._stack = [];\n")
        .add("__rpn.temp = 0;\n")
     
        .add("__rpn.push = function (val) {\n")
        .add("  __rpn._stack.push(val);\n")
        .add("};\n")
     
        .add("__rpn.pop = function () {\n")
        .add("  if (__rpn._stack.length > 0) {\n")
        .add("    return __rpn._stack.pop();\n")
        .add("  }\n")
        .add("  else {\n")
        .add("    throw new Error('can\\\'t pop from empty stack');\n")
        .add("  }\n")
        .add("};\n")
     
        .add("__rpn.print = function (val, repeat) {\n")
        .add("  while (repeat-- > 0) {\n")
        .add("    var el = document.createElement('div');\n")
        .add("    var txt = document.createTextNode(val);\n")
        .add("    el.appendChild(txt);\n")
        .add("    document.body.appendChild(el);\n")
        .add("  }\n")
        .add("};\n");
    }
     
    exports.compile = function (input, data) {
      var expressions = parser.parse(input.toString());
      var preamble = getPreamble();
     
      var result = new sourceMap.SourceNode(null, null, null, preamble);
      result.add(expressions.map(function (exp) {
        return exp.compile(data);
      }));
     
      return result;
    };

    Create the command line script in bin/rpn.js:

    #!/usr/bin/env node
    var fs = require("fs");
    var rpn = require("rpn");
     
    process.argv.slice(2).forEach(function (file) {
      var input = fs.readFileSync(file);
      var output = rpn.compile(input, {
        originalFilename: file
      }).toStringWithSourceMap({
        file: file.replace(/\.[\w]+$/, ".js.map")
      });
      var sourceMapFile = file.replace(/\.[\w]+$/, ".js.map");
      fs.writeFileSync(file.replace(/\.[\w]+$/, ".js"),
                       output.code + "\n//# sourceMappingURL=" + sourceMapFile);
      fs.writeFileSync(sourceMapFile, output.map);
    });

    Note that our script will automatically add the //# sourceMappingURL comment directive so that the browser’s debugger knows where to find the source map.

    After you create the script, update your package.json:

    ...
    "bin": {
      "rpn.js": "./bin/rpn.js"
    },
    ...

    And link the package again so that the script is installed on your system:

    $ npm link .

    Seeing Results

    Here is an RPN program that we can use to test our compiler. I have saved it in examples/simple-example.rpn:

    a 8 =;
    b 3 =;
    c a b 1 - / =;
    c 1 print;

    Next, compile the script:

    $ cd examples/
    $ rpn.js simple-example.rpn

    This generates simple-example.js and simple-example.js.map. When we include the JavaScript file in a web page we should see the result of the computation printed on the page:

    Screenshot of simple-example.rpn's result

    Great success!

    However, we aren’t always so lucky, and our arithmetic might have some errors. Consider the following example, examples/with-error.rpn:

    a 9 =;
    b 3 =;
    c a b / =;
    c a b c - / =;
    c 1 print;

    We can compile this script and include the resulting JavaScript in a web page, but this time we won’t see any output on the page.

    By opening the debugger, setting the pause on exceptions option, and reloading, we can see how daunting debugging without source maps can be:

    Screenshot of enabling pause on exceptions.

    Screenshot of debugging with-error.rpn without source maps.

    The generated JavaScript is difficult to read, and unfamiliar to anyone who authored the original RPN script. By enabling source maps in the debugger, we can refresh and the exact line where the error ocurred in our original source will be highlighted:

    Screenshot of enabling source maps.


    Screenshot of debugging with-error.rpn with source maps.

    The debugging experience with source maps is orders of magnitude improved, and makes compiling languages to JavaScript a serious possibility.

    At the end of the day though, the debugging experience is only as good as the information encoded in the source maps by your compiler. It can be hard to judge the quality of your source maps simply by looking at the set of source location coordinates that they are mapping between, so Tobias Koppers created a tool to let you easily visualize your source maps.

    Here is the visualization of one of our source maps:


    Screenshot of the source map visualization tool.

    Good luck writing your own compiler that targets JavaScript!

    References