Mozilla

Featured Articles

Sort by:

View:

  1. Understanding the CSS box model for inline elements

    In a web page, every element is rendered as a rectangular box. The box model describes how the element’s content, padding, border, and margin determine the space occupied by the element and its relation to other elements in the page.

    Depending on the element’s display property, its box may be one of two types: a block box or an inline box. The box model is applied differently to these two types. In this article we’ll see how the box model is applied to inline boxes, and how a new feature in the Firefox Developer Tools can help you visualize the box model for inline elements.

    Inline boxes and line boxes

    Inline boxes are laid out horizontally in a box called a line box:

    2-inline-boxes

    If there isn’t enough horizontal space to fit all elements into a single line, another line box is created under the first one. A single inline element may then be split across lines:

    line-boxes

    The box model for inline boxes

    When an inline box is split across more than one line, it’s still logically a single box. This means that any horizontal padding, border, or margin is only applied to the start of the first line occupied by the box, and the end of the last line.

    For example, in the screenshot below, the highlighted span is split across 2 lines. Its horizontal padding doesn’t apply to the end of the first line or the beginning of the second line:

    horizontal-padding

    Also, any vertical padding, border, or margin applied to an element will not push away elements above or below it:

    vertical-padding

    However, note that vertical padding and border are still applied, and the padding still pushes out the border:

    vertical-border-padding

    If you need to adjust the height between lines, use line-height instead.

    Inspecting inline elements with devtools

    When debugging layout issues, it’s important to have tools that give you the complete picture. One of these tools is the highlighter, which all browsers include in their devtools. You can use it to select elements for closer inspection, but it also gives you information about layout.

    layout-info

    In the example above, the highlighter in Firefox 39 is used to highlight an inline element split across several lines.

    The highlighter displays guides to help you align elements, gives the complete dimensions of the node, and displays an overlay showing the box model.

    From Firefox 39 onwards, the box model overlay for split inline elements shows each individual line occupied by the element. In this example the content region is displayed in light blue and is split over four lines. A right padding is also defined for the node, and the highlighter shows the padding region in purple.

    Highlighting each individual line box is important for understanding how the box model is applied to inline elements, and also helps you check the space between lines and the vertical alignment of inline boxes.

     

  2. Using the Firefox DevTools to Debug fetch() on GitHub

    Firefox Nightly recently added preliminary support for Fetch, a modern, Promise-based replacement for XMLHttpRequest (XHR). Our initial work supported most of the Fetch Specification, but not quite all of it. Specifically, when Fetch first appeared in Nightly, we hadn’t yet implemented serializing and de-serializing of FormData objects.

    GitHub was already using Fetch in production with a home-grown polyfill, and required support for serializing FormData in order to upload images to GitHub Issues. Thus, when our early, incomplete implementation of Fetch landed in Nightly, the GitHub polyfill stepped out of the way, and image uploads from Firefox broke.

    In the 15-minute video below, Dan Callahan shows a real-world instance of using the Firefox Developer Tools to help find, file, and fix Bug 1143857: “Fetch does not serialize FormData body; breaks GitHub.” This isn’t a canned presentation, but rather a comprehensive, practical demonstration of actually debugging minified JavaScript and broken event handlers using the Firefox DevTools, reporting a Gecko bug in Bugzilla, and ultimately testing a patched build of Firefox.

    Use the following links to jump to a specific section of the video on YouTube:

    • 0:13 – The error
    • 0:50 – Using the Network Panel
    • 1:30 – Editing and Resending HTTP Requests
    • 2:02 – Hypothesis: FormData was coerced to a String, not serialized
    • 2:40 – Prettifying minified JavaScript
    • 3:10 – Setting breakpoints on event handlers
    • 4:57 – Navigating the call stack
    • 7:54 – Setting breakpoints on lines
    • 8:56 – GitHub’s FormData constructor
    • 10:48 – Invoking fetch()
    • 11:53 – Verifying the bug by testing fetch() on another domain
    • 12:52 – Checking the docs for fetch()
    • 13:42 – Filing a Gecko bug in Bugzilla
    • 14:42 – The lifecycle of Bug 1143857: New, Duplicate, Reopened, Resolved
    • 15:41 – Verifying a fixed build of Firefox

    We expect Firefox Developer Edition version 39 to ship later this month with full support for the Fetch API.

  3. This API is so Fetching!

    For more than a decade the Web has used XMLHttpRequest (XHR) to achieve asynchronous requests in JavaScript. While very useful, XHR is not a very nice API. It suffers from lack of separation of concerns. The input, output and state are all managed by interacting with one object, and state is tracked using events. Also, the event-based model doesn’t play well with JavaScript’s recent focus on Promise- and generator-based asynchronous programming.

    The Fetch API intends to fix most of these problems. It does this by introducing the same primitives to JS that are used in the HTTP protocol. In addition, it introduces a utility function fetch() that succinctly captures the intention of retrieving a resource from the network.

    The Fetch specification, which defines the API, nails down the semantics of a user agent fetching a resource. This, combined with ServiceWorkers, is an attempt to:

    1. Improve the offline experience.
    2. Expose the building blocks of the Web to the platform as part of the extensible web movement.

    As of this writing, the Fetch API is available in Firefox 39 (currently Nightly) and Chrome 42 (currently dev). Github has a Fetch polyfill.

    Feature detection

    Fetch API support can be detected by checking for Headers,Request, Response or fetch on the window or worker scope.

    Simple fetching

    The most useful, high-level part of the Fetch API is the fetch() function. In its simplest form it takes a URL and returns a promise that resolves to the response. The response is captured as a Response object.

    fetch("/data.json").then(function(res) {
      // res instanceof Response == true.
      if (res.ok) {
        res.json().then(function(data) {
          console.log(data.entries);
        });
      } else {
        console.log("Looks like the response wasn't perfect, got status", res.status);
      }
    }, function(e) {
      console.log("Fetch failed!", e);
    });

    Submitting some parameters, it would look like this:

    fetch("http://www.example.org/submit.php", {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded"
      },
      body: "firstName=Nikhil&favColor=blue&password=easytoguess"
    }).then(function(res) {
      if (res.ok) {
        alert("Perfect! Your settings are saved.");
      } else if (res.status == 401) {
        alert("Oops! You are not authorized.");
      }
    }, function(e) {
      alert("Error submitting form!");
    });

    The fetch() function’s arguments are the same as those passed to the
    Request() constructor, so you may directly pass arbitrarily complex requests to fetch() as discussed below.

    Headers

    Fetch introduces 3 interfaces. These are Headers, Request and
    Response. They map directly to the underlying HTTP concepts, but have
    certain visibility filters in place for privacy and security reasons, such as
    supporting CORS rules and ensuring cookies aren’t readable by third parties.

    The Headers interface is a simple multi-map of names to values:

    var content = "Hello World";
    var reqHeaders = new Headers();
    reqHeaders.append("Content-Type", "text/plain"
    reqHeaders.append("Content-Length", content.length.toString());
    reqHeaders.append("X-Custom-Header", "ProcessThisImmediately");

    The same can be achieved by passing an array of arrays or a JS object literal
    to the constructor:

    reqHeaders = new Headers({
      "Content-Type": "text/plain",
      "Content-Length": content.length.toString(),
      "X-Custom-Header": "ProcessThisImmediately",
    });

    The contents can be queried and retrieved:

    console.log(reqHeaders.has("Content-Type")); // true
    console.log(reqHeaders.has("Set-Cookie")); // false
    reqHeaders.set("Content-Type", "text/html");
    reqHeaders.append("X-Custom-Header", "AnotherValue");
     
    console.log(reqHeaders.get("Content-Length")); // 11
    console.log(reqHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]
     
    reqHeaders.delete("X-Custom-Header");
    console.log(reqHeaders.getAll("X-Custom-Header")); // []

    Some of these operations are only useful in ServiceWorkers, but they provide
    a much nicer API to Headers.

    Since Headers can be sent in requests, or received in responses, and have various limitations about what information can and should be mutable, Headers objects have a guard property. This is not exposed to the Web, but it affects which mutation operations are allowed on the Headers object.
    Possible values are:

    • “none”: default.
    • “request”: guard for a Headers object obtained from a Request (Request.headers).
    • “request-no-cors”: guard for a Headers object obtained from a Request created
      with mode “no-cors”.
    • “response”: naturally, for Headers obtained from Response (Response.headers).
    • “immutable”: Mostly used for ServiceWorkers, renders a Headers object
      read-only.

    The details of how each guard affects the behaviors of the Headers object are
    in the specification. For example, you may not append or set a “request” guarded Headers’ “Content-Length” header. Similarly, inserting “Set-Cookie” into a Response header is not allowed so that ServiceWorkers may not set cookies via synthesized Responses.

    All of the Headers methods throw TypeError if name is not a valid HTTP Header name. The mutation operations will throw TypeError if there is an immutable guard. Otherwise they fail silently. For example:

    var res = Response.error();
    try {
      res.headers.set("Origin", "http://mybank.com");
    } catch(e) {
      console.log("Cannot pretend to be a bank!");
    }

    Request

    The Request interface defines a request to fetch a resource over HTTP. URL, method and headers are expected, but the Request also allows specifying a body, a request mode, credentials and cache hints.

    The simplest Request is of course, just a URL, as you may do to GET a resource.

    var req = new Request("/index.html");
    console.log(req.method); // "GET"
    console.log(req.url); // "http://example.com/index.html"

    You may also pass a Request to the Request() constructor to create a copy.
    (This is not the same as calling the clone() method, which is covered in
    the “Reading bodies” section.).

    var copy = new Request(req);
    console.log(copy.method); // "GET"
    console.log(copy.url); // "http://example.com/index.html"

    Again, this form is probably only useful in ServiceWorkers.

    The non-URL attributes of the Request can only be set by passing initial
    values as a second argument to the constructor. This argument is a dictionary.

    var uploadReq = new Request("/uploadImage", {
      method: "POST",
      headers: {
        "Content-Type": "image/png",
      },
      body: "image data"
    });

    The Request’s mode is used to determine if cross-origin requests lead to valid responses, and which properties on the response are readable. Legal mode values are "same-origin", "no-cors" (default) and "cors".

    The "same-origin" mode is simple, if a request is made to another origin with this mode set, the result is simply an error. You could use this to ensure that
    a request is always being made to your origin.

    var arbitraryUrl = document.getElementById("url-input").value;
    fetch(arbitraryUrl, { mode: "same-origin" }).then(function(res) {
      console.log("Response succeeded?", res.ok);
    }, function(e) {
      console.log("Please enter a same-origin URL!");
    });

    The "no-cors" mode captures what the web platform does by default for scripts you import from CDNs, images hosted on other domains, and so on. First, it prevents the method from being anything other than “HEAD”, “GET” or “POST”. Second, if any ServiceWorkers intercept these requests, they may not add or override any headers except for these. Third, JavaScript may not access any properties of the resulting Response. This ensures that ServiceWorkers do not affect the semantics of the Web and prevents security and privacy issues that could arise from leaking data across domains.

    "cors" mode is what you’ll usually use to make known cross-origin requests to access various APIs offered by other vendors. These are expected to adhere to
    the CORS protocol. Only a limited set of headers is exposed in the Response, but the body is readable. For example, you could get a list of Flickr’s most interesting photos today like this:

    var u = new URLSearchParams();
    u.append('method', 'flickr.interestingness.getList');
    u.append('api_key', '<insert api key here>');
    u.append('format', 'json');
    u.append('nojsoncallback', '1');
     
    var apiCall = fetch('https://api.flickr.com/services/rest?' + u);
     
    apiCall.then(function(response) {
      return response.json().then(function(json) {
        // photo is a list of photos.
        return json.photos.photo;
      });
    }).then(function(photos) {
      photos.forEach(function(photo) {
        console.log(photo.title);
      });
    });

    You may not read out the “Date” header since Flickr does not allow it via
    Access-Control-Expose-Headers.

    response.headers.get("Date"); // null

    The credentials enumeration determines if cookies for the other domain are
    sent to cross-origin requests. This is similar to XHR’s withCredentials
    flag, but tri-valued as "omit" (default), "same-origin" and "include".

    The Request object will also give the ability to offer caching hints to the user-agent. This is currently undergoing some security review. Firefox exposes the attribute, but it has no effect.

    Requests have two read-only attributes that are relevant to ServiceWorkers
    intercepting them. There is the string referrer, which is set by the UA to be
    the referrer of the Request. This may be an empty string. The other is
    context which is a rather large enumeration defining what sort of resource is being fetched. This could be “image” if the request is from an tag in the controlled document, “worker” if it is an attempt to load a worker script, and so on. When used with the fetch() function, it is “fetch”.

    Response

    Response instances are returned by calls to fetch(). They can also be created by JS, but this is only useful in ServiceWorkers.

    We have already seen some attributes of Response when we looked at fetch(). The most obvious candidates are status, an integer (default value 200) and statusText (default value “OK”), which correspond to the HTTP status code and reason. The ok attribute is just a shorthand for checking that status is in the range 200-299 inclusive.

    headers is the Response’s Headers object, with guard “response”. The url attribute reflects the URL of the corresponding request.

    Response also has a type, which is “basic”, “cors”, “default”, “error” or
    “opaque”.

    • "basic": normal, same origin response, with all headers exposed except
      “Set-Cookie” and “Set-Cookie2″.
    • "cors": response was received from a valid cross-origin request. Certain headers and the body may be accessed.
    • "error": network error. No useful information describing the error is available. The Response’s status is 0, headers are empty and immutable. This is the type for a Response obtained from Response.error().
    • "opaque": response for “no-cors” request to cross-origin resource. Severely
      restricted

    The “error” type results in the fetch() Promise rejecting with TypeError.

    There are certain attributes that are useful only in a ServiceWorker scope. The
    idiomatic way to return a Response to an intercepted request in ServiceWorkers is:

    addEventListener('fetch', function(event) {
      event.respondWith(new Response("Response body", {
        headers: { "Content-Type" : "text/plain" }
      });
    });

    As you can see, Response has a two argument constructor, where both arguments are optional. The first argument is a body initializer, and the second is a dictionary to set the status, statusText and headers.

    The static method Response.error() simply returns an error response. Similarly, Response.redirect(url, status) returns a Response resulting in
    a redirect to url.

    Dealing with bodies

    Both Requests and Responses may contain body data. We’ve been glossing over it because of the various data types body may contain, but we will cover it in detail now.

    A body is an instance of any of the following types.

    In addition, Request and Response both offer the following methods to extract their body. These all return a Promise that is eventually resolved with the actual content.

    • arrayBuffer()
    • blob()
    • json()
    • text()
    • formData()

    This is a significant improvement over XHR in terms of ease of use of non-text data!

    Request bodies can be set by passing body parameters:

    var form = new FormData(document.getElementById('login-form'));
    fetch("/login", {
      method: "POST",
      body: form
    })

    Responses take the first argument as the body.

    var res = new Response(new File(["chunk", "chunk"], "archive.zip",
                           { type: "application/zip" }));

    Both Request and Response (and by extension the fetch() function), will try to intelligently determine the content type. Request will also automatically set a “Content-Type” header if none is set in the dictionary.

    Streams and cloning

    It is important to realise that Request and Response bodies can only be read once! Both interfaces have a boolean attribute bodyUsed to determine if it is safe to read or not.

    var res = new Response("one time use");
    console.log(res.bodyUsed); // false
    res.text().then(function(v) {
      console.log(res.bodyUsed); // true
    });
    console.log(res.bodyUsed); // true
     
    res.text().catch(function(e) {
      console.log("Tried to read already consumed Response");
    });

    This decision allows easing the transition to an eventual stream-based Fetch API. The intention is to let applications consume data as it arrives, allowing for JavaScript to deal with larger files like videos, and perform things like compression and editing on the fly.

    Often, you’ll want access to the body multiple times. For example, you can use the upcoming Cache API to store Requests and Responses for offline use, and Cache requires bodies to be available for reading.

    So how do you read out the body multiple times within such constraints? The API provides a clone() method on the two interfaces. This will return a clone of the object, with a ‘new’ body. clone() MUST be called before the body of the corresponding object has been used. That is, clone() first, read later.

    addEventListener('fetch', function(evt) {
      var sheep = new Response("Dolly");
      console.log(sheep.bodyUsed); // false
      var clone = sheep.clone();
      console.log(clone.bodyUsed); // false
     
      clone.text();
      console.log(sheep.bodyUsed); // false
      console.log(clone.bodyUsed); // true
     
      evt.respondWith(cache.add(sheep.clone()).then(function(e) {
        return sheep;
      });
    });

    Future improvements

    Along with the transition to streams, Fetch will eventually have the ability to abort running fetch()es and some way to report the progress of a fetch. These are provided by XHR, but are a little tricky to fit in the Promise-based nature of the Fetch API.

    You can contribute to the evolution of this API by participating in discussions on the WHATWG mailing list and in the issues in the Fetch and ServiceWorker specifications.

    For a better web!

    The author would like to thank Andrea Marchesini, Anne van Kesteren and Ben
    Kelly for helping with the specification and implementation.

  4. asm.js Speedups Everywhere

    asm.js is an easy-to-optimize subset of JavaScript. It runs in all browsers without plugins, and is a good target for porting C/C++ codebases such as game engines – which have in fact been the biggest adopters of this approach, for example Unity 3D and Unreal Engine.

    Obviously, developers porting games using asm.js would like them to run well across all browsers. However, each browser has different performance characteristics, because each has a different JavaScript engine, different graphics implementation, and so forth. In this post, we’ll focus on JavaScript execution speed and see the significant progress towards fast asm.js execution that has been happening across the board. Let’s go over each of the four major browsers now.

    Chrome

    Already in 2013, Google released Octane 2.0, a new version of their primary JavaScript benchmark suite, which contained a new asm.js benchmark, zlib. Benchmarks define what browsers optimize: things that matter are included in benchmarks, and browsers then compete to achieve the best scores. Therefore, adding an asm.js benchmark to Octane clearly signaled Google’s belief that asm.js content is important to optimize for.

    A further major development happened more recently, when Google landed TurboFan, a new work-in-progress optimizing compiler for Chrome’s JavaScript engine, v8. TurboFan has a “sea of nodes” architecture (which is new in the JavaScript space, and has been used very successfully elsewhere, for example in the Java server virtual machine), and aims to reach even higher speeds than CrankShaft, the first optimizing compiler for v8.

    While TurboFan is not yet ready to be enabled on all JavaScript content, as of Chrome 41 it is enabled on asm.js. Getting the benefits of TurboFan early on asm.js shows the importance of optimizing asm.js for the Chrome team. And the benefits can be quite substantial: For example, TurboFan speeds up Emscripten‘s zlib benchmark by 13%, and fasta by 24%.

    Safari

    During the last year, Safari’s JavaScript Engine, JavaScriptCore, introduced a new JIT (Just In Time compiler) called FTL. FTL stands for “Fourth Tier LLVM,” as it adds a fourth level of optimization above the three previously-existing ones, and it is based on LLVM, a powerful open source compiler framework. This is exciting because LLVM is a top-tier general-purpose compiler, with many years of optimizations put into it, and Safari gets to reuse all those efforts. As shown in the blogposts linked to earlier, the speedups that FTL provides can be very substantial.

    Another interesting development from Apple this year was the introduction of a new JavaScript benchmark, JetStream. JetStream contains several asm.js benchmarks, an indication that Apple believes asm.js content is important to optimize for, just as when Google added an asm.js benchmark to Octane.

    Internet Explorer

    The JavaScript engine inside Internet Explorer is named Chakra. Last year, the Chakra team blogged about a suite of optimizations coming to IE in Windows 10 and pointed to significant improvements in the scores on asm.js workloads in Octane and JetStream. This is yet another example of how having asm.js workloads in common benchmarks drives measurement and optimization.

    The big news, however, is the recent announcement by the Chakra team that they are working on adding specific asm.js optimizations, to arrive in Windows 10 together with the other optimizations mentioned earlier. These optimizations haven’t made it to the Preview channel yet, so we can’t measure and report on them here. However, we can speculate on the improvements based on the initial impact of landing asm.js optimizations in Firefox. As shown in this benchmark comparisons slide containing measurements from right after the landing, asm.js optimizations immediately brought Firefox to around 2x slower than native performance (from 5-12x native before). Why should these wins translate to Chakra? Because, as explained in our previous post, the asm.js spec provides a predictable way to validate asm.js code and generate high-quality code based on the results.

    So, here’s looking forward to good asm.js performance in Windows 10!

    Firefox

    As we mentioned before, the initial landing of asm.js optimizations in Firefox generally put Firefox within 2x of native in terms of raw throughput. By the end of 2013, we were able to report that the gap had shrunk to around 1.5x native – which is close to the amount of variability that different native compilers have between each other anyhow, so comparisons to “native speed” start to be less meaningful.

    At a high-level, this progress comes from two kinds of improvements: compiler backend optimizations and new JavaScript features. In the area of compiler backend optimizations, there has been a stream of tiny wins (specific to particular code patterns or hardware) making it difficult to point to any one thing. Two significant improvements stand out, though:

    Along with backend optimization work, two new JavaScript features have been incorporated into asm.js which unlock new performance capabilities in the hardware. The first feature, Math.fround, may look simple but it enables the compiler backend to generate single-precision floating-point arithmetic when used carefully in JS. As described in this post, the switch can result in anywhere from a 5% – 60% speedup, depending on the workload. The second feature is much bigger: SIMD.js. This is still a stage 1 proposal for ES7 so the new SIMD operations and the associated asm.js extensions are only available in Firefox Nightly. Initial results are promising though.

    Separate from all these throughput optimizations, there have also been a set of load time optimizations in Firefox: off-main-thread and parallel compilation of asm.js code as well as caching of the compiled machine code. As described in this post, these optimizations significantly improve the experience of starting a Unity- or Epic-sized asm.js application. Existing asm.js workloads in the benchmarks mentioned above do not test this aspect of asm.js performance so we put together a new benchmark suite named Massive that does. Looking at Firefox’s Massive score over time, we can see the load-time optimizations contributing to a more than 6x improvement (more details in the Hacks post introducing the Massive benchmark).

    The Bottom Line

    What is most important, in the end, are not the underlying implementation details, nor even specific performance numbers on this benchmark or that. What really matters is that applications run well. The best way to check that is to actually run real-world games! A nice example of an asm.js-using game is Dead Trigger 2, a Unity 3D game:

    The video shows the game running on Firefox, but as it uses only standard web APIs, it should work in any browser. We tried it now, and it renders quite smoothly on Firefox, Chrome and Safari. We are looking forward to testing it on the next Preview version of Internet Explorer as well.

    Another example is Cloud Raiders:

    As with Unity, the developers of Cloud Raiders were able to compile their existing C++ codebase (using Emscripten) to run on the web without relying on plugins. The result runs well in all four of the major browsers.

    In conclusion, asm.js performance has made great strides over the last year. There is still room for improvement – sometimes performance is not perfect, or a particular API is missing, in one browser or another – but all major browsers are working to make sure that asm.js runs quickly. We can see that by looking at the benchmarks they are optimizing on, which contain asm.js, and in the new improvements they are implementing in their JavaScript engines, which are often motivated by asm.js. As a result, games that not long ago would have required plugins are quickly getting to the point where they can run well without them, in modern browsers across the web.

  5. Firefox Developer Edition 38: 64-bits and more

    In celebration of the 10th anniversary of Firefox, we unveiled Firefox Developer Edition, the first browser created specifically for developers. At that time, we also announced plans to ship a 64-bit version of Firefox. Today we’re happy to announce the next phase of that plan: 64-bit builds for Firefox Developer Edition are now available on Windows, adding to the already supported platforms of OS X and Linux.

    A 64-bit build is a major step toward giving users rich, desktop-quality app experiences in the browser. Let’s also take a look at at some of the other features that make this a release worth noting. If you haven’t downloaded the Developer Edition browser yet, it’s a fine time to give it a try. Here’s why:

    DevEditionEpic

    Unreal demo in Win 64-bit Developer Edition

    Run larger applications

    A 32-bit browser is limited to 4GB of address space. That address space is further whittled down by fragmentation issues. Meanwhile, web applications are getting bigger and bigger. Browser-based games that deliver performant, native-like gameplay, such as those built with Epic Games’ Unreal Engine, are often much larger than we expect from traditional web applications. These games ship with large assets that must be stored in memory so they can be synchronously loaded.

    For some of the largest of these apps, a 64-bit browser means the difference between whether or not a game will run. For example, when porting to asm.js it’s recommended to keep heap size to 512mb in a 32-bit browser. That goes up to 2GB in a 64-bit version of Firefox.

    Emscripten helps port C and C++ code to run on the Web and deliver native-like performance. For an in-depth look at how assets are stored and accessed using a variety of methods in asm.js/emscripten built applications, read Alon Zakai’s post on Synchronous Execution and Filesystem Access in Emscripten.

    Gain faster execution and increased security

    64-bit Firefox just goes faster. We get access to new hardware registers and instructions to speed up JavaScript code.

    For asm.js code, the increased address space also lets us use hardware memory protection to safely remove bounds checks from asm.js heap accesses. The gains are pretty dramatic: 8%-17% on the asmjs-apps-*-throughput tests as reported on arewefastyet.com.

    The larger 64-bit address space also improves the effectiveness of ASLR (address space layout randomization), making it more difficult for web content to exploit the browser.

    Firefox Developer Edition additions and improvements

    Beyond the new 64-bit capabilities, the Firefox 38 Developer Edition release implements many new features, as it does every 6 weeks when it is updated. Some of these are described below. For all the details and associated bugs in progress, you’ll want to visit the release notes.

    WebRTC changes

    In a post about WebRTC from 2013, we documented some workarounds and limitations of WebRTC mozRTCPeerConnection. One fix involved adding multiple MediaStreams to one mozRTCPeerConnection and renegotiating on an existing session.

    The new version of Firefox Developer Edition fixes these issues. We now support adding multiple media streams (camera, screen sharing, audio stream) to the same mozRTCPeerConnection within a WebRTC conversation. This allows the developer to call the addStream method for each additional stream, which in turn triggers the onAddStream event for the clients.

    Renegotiation allows streams to be modified during a conversation, for example sharing a screen stream during a conversation. This is now possible without re-creating a session.

    webrtcexample

    WebRTC with multiple streams

    Last week we announced that WebRTC requires Perfect Forward Secrecy (PFS) starting in Firefox 38. We’ll dig a little deeper into details of our WebRTC implementation in an upcoming article. Stay tuned.

    The BroadcastChannel API

    The BroadcastChannel API allows simple messaging between browser contexts with the same user agent and origin is now available. Here’s more detail and some ideas for how to use the BroadcastChannel API in Firefox 38.

    Support for KeyboardEvent.code

    KeyboardEvent.code is now enabled by default. The code attribute give a developer the ability to determine which physical key is pressed without keyboard layout or keyboard state modifications.

    keyboard.code

    KeyboardEvent code attribute

    For more examples of uses cases see the motivation section of the UI Events Specification (formerly DOM Level 3 Events).

    XHR logging

    The Network Monitor already displays a great deal of information on XMLHttpRequests, but often the console is used to debug code along with network requests. In the latest Developer Edition of Firefox, the console now supports filtering XMLHttpRequests within console logging.

    xhrnet

    Network Monitor XHR Request

    xhrfilter

    XHR logging in console

    Let us know what you think

    Many additional improvements are available in this version. Download it now. Tell a friend.

    As always, you can take a close look at the Developer Edition release notes. Please be sure to share your feedback and feature ideas in the Firefox Developer Tools UserVoice channel.

  6. Birdsongs, Musique Concrète, and the Web Audio API

    In January 2015, my friend and collaborator Brian Belet and I presented Oiseaux de Même — an audio soundscape app created from recordings of birds — at the first Web Audio Conference. In this post I’d like to describe my experience of implementing this app using the Web Audio API, Twitter Bootstrap, Node.js, and REST APIs.

    Screenshot showing Birds of a Feather, a soundscape created with field recordings of birds that are being seen in your vicinity.

    Screenshot showing Birds of a Feather, a soundscape created with field recordings of birds that are being seen in your vicinity.

    What is it? Musique Concrète and citizen science

    We wanted to create a web-based Musique Concrète, building an artistic sound experience by processing field recordings. We decided to use xeno-canto — a library of over 200,000 recordings of 9,000 different bird species — as our source of recordings. Almost all the recordings are licensed under Creative Commons by their generous recordists. We select recordings from this library based on data from eBird, a database of tens of millions of bird sightings contributed by bird watchers everywhere. By using the Geolocation API to retrieve eBird sightings near to the listeners’ location, our soundscape can consist of recordings of bird species that bird watchers have reported recently near the listener — each user gets a personalized soundscape that changes daily.

    Use of the Web Audio API

    We use the browser’s Web Audio API to play back the sounds from xeno-canto. The Web Audio API allows developers to play back, record, analyze, and process sound by creating AudioNodes that are connected together, like an old modular synthesizer.

    Our soundscape is implemented using four AudioBuffer nodes, each of which plays a field recording in a loop. These loops are placed in a stereo field using Panner nodes, and mixed together before being sent to the listener’s speakers or headphones.

    Controls

    After all the sounds have loaded and begin playing, we offer users several controls for manipulating the sounds as they play:

    • The Pan button randomizes the spatial location of the sound in 3D space.
    • The Rate button randomizes the playback rate.
    • The Reverse button reverses the direction of sound playback.
    • Finally, the Share button lets you capture the state of the soundscape and save that snapshot for later.

    The controls described above are implemented as typical JavaScript event handlers. When the Pan button is pressed, for example, we run this handler:

    // sets the X,Y,Z position of the Panner to random values between -1 and +1
    BirdSongPlayer.prototype.randomizePanner = function() {
      this.resetLastActionTime();
      // NOTE: x = -1 is LEFT
      this.panPosition = { x: 2 * Math.random() - 1, y: 2 * Math.random() - 1, z: 2 * Math.random() - 1}
      this.panner.setPosition( this.panPosition.x, this.panPosition.y, this.panPosition.z);
    }

    Some parts of the Web Audio API are write-only

    I had a few minor issues where I had to work around shortcomings in the Web Audio API. Other authors have already documented similar experiences; I’ll summarize mine briefly here:

    • Can’t read Panner position: In the event handler for the Share button, I want to retrieve and store the current Audio Buffer playback rate and Panner position. However, the current Panner node does not allow retrieval of the position after setting it. Hence, I store the new Panner position in an instance variable in addition to calling setPosition().

      This has had a minimal impact on my code so far. My longer-term concern is that I’d rather store the position in the Panner and retrieve it from there, instead of storing a copy elsewhere. In my experience, multiple copies of the same information becomes a readability and maintainability problem as code grows bigger and more complex.

    • Can’t read AudioBuffer’s playbackRate: The Rate button described above calls linearRampToValueAtTime() on the playbackRate AudioParam. As far as I can tell, AudioParams don’t let me retrieve their values after calling linearRampToValueAtTime(), so I’m obliged to keep a duplicate copy of this value in my JS object.
    • Can’t read AudioBuffer playback position: I’d like to show the user the current playback position for each of my sound loops, but the API doesn’t provide this information. Could I compute it myself? Unfortunately, after a few iterations of ramping an AudioBuffer’s playbackRate between random values, it is very difficult to compute the current playback position within the buffer. Unlike some API users, I don’t need a highly accurate position, I just want to visualize for my users when the current sound loop restarts.

    Debugging with the Web Audio inspector

    Firefox’s Web Audio inspector shows how Audio Nodes are connected to one another.

    Firefox’s Web Audio inspector shows how Audio Nodes are connected to one another.



    I had great success using Firefox’s Web Audio inspector to watch my Audio Nodes being created and interconnected as my code runs.

    In the screenshot above, you can see the four AudioBufferSources, each feeding through a GainNode and PannerNode before being summed by an AudioDestination. Note that each recording is also connected to an AnalyzerNode; the Analyzers are used to create the scrolling amplitude graphs for each loop.

    Visualizing sound loops

    As the soundscape evolves, users often want to know which bird species is responsible for a particular sound they hear in the mix. We use a scrolling visualization for each loop that shows instantaneous amplitude, creating distinctive shapes you can correlate with what you’re hearing. The visualization uses the Analyzer node to perform a fast Fourier transform (FFT) on the sound, which yields the amplitude of the sound at every frequency. We compute the average of all those amplitudes, and then draw that amplitude at the right edge of a Canvas. As the contents of the Canvas shift sideways on every animation frame, the result is a horizontally scrolling amplitude graph.

    BirdSongPlayer.prototype.initializeVUMeter = function() {
      // set up VU meter
      var myAnalyser = this.analyser;
      var volumeMeterCanvas = $(this.playerSelector).find('canvas')[0];
      var graphicsContext = volumeMeterCanvas.getContext('2d');
      var previousVolume = 0;
     
      requestAnimationFrame(function vuMeter() {
        // get the average, bincount is fftsize / 2
        var array =  new Uint8Array(myAnalyser.frequencyBinCount);
        myAnalyser.getByteFrequencyData(array);
        var average = getAverageVolume(array);
        average = Math.max(Math.min(average, 128), 0);
     
        // draw the rightmost line in black right before shifting
        graphicsContext.fillStyle = 'rgb(0,0,0)'
        graphicsContext.fillRect(258, 128 - previousVolume, 2, previousVolume);
     
        // shift the drawing over one pixel
        graphicsContext.drawImage(volumeMeterCanvas, -1, 0);
     
        // clear the rightmost column state
        graphicsContext.fillStyle = 'rgb(245,245,245)'
        graphicsContext.fillRect(259, 0, 1, 130);
     
        // set the fill style for the last line (matches bootstrap button)
        graphicsContext.fillStyle = '#5BC0DE'
        graphicsContext.fillRect(258, 128 - average, 2, average);
     
        requestAnimationFrame(vuMeter);
        previousVolume = average;
      });
    }

    What’s next

    I’m continuing to work on cleaning up my JavaScript code for this project. I have several user interface improvements suggested by my Mozillia colleagues that I’d like to try. And Prof. Belet and I are considering what other sources of geotagged sounds we can use to make more soundscapes with. In the meantime, please try Oiseaux de Même for yourself and let us know what you think!

  7. Synchronous Execution and Filesystem Access in Emscripten

    Emscripten helps port C and C++ code to run on the Web. When doing such porting, we have to work around limitations of the web platform, one of which is that code must be asynchronous: you can’t have long-running code on the Web, it must be split up into events, because other important things – rendering, input, etc. – can’t happen while your code is running. But, it is common to have C and C++ code that is synchronous! This post will review how Emscripten helps handle this problem, using a variety of methods. We’ll look at preloading a virtual filesystem as well as a recently-added option to execute your compiled code in a special interpreter. We’ll also get the chance to play some Doom!

    First, let’s take a more concrete look at  the problem. Consider, for example,

    FILE *f = fopen("data.txt", "rb");
    fread(buffer, 100, 1, f);
    fclose(f);

    This C code opens a file and reads from it synchronously. Now, in the browser we don’t have local filesystem access (content is sandboxed, for security), so when reading a file, we might be issuing a remote request to a server, or loading from IndexedDB – both of which are asynchronous! How, then, does anything get ported at all? Let’s go over three approaches to handling this problem.

    1. Preloading to Emscripten’s virtual filesystem

    The first tool Emscripten has is a virtual in-memory filesystem, implemented in JavaScript (credit goes to inolen for most of the code), which can be pre-populated before the program runs. If you know which files will be accessed, you can preload them (using emcc’s –preload-file option), and when the code executes, copies of the files are already in memory, ready for synchronous access.

    On small to medium amounts of data, this is a simple and useful technique. The compiled code doesn’t know it’s using a virtual filesystem, everything looks normal and synchronous to it. Things just work. However, with large amounts of data, it can be too expensive to preload it all into memory. You might only need each file for a short time – for example, if you load it into a WebGL shader, and then forget about it on the CPU side – but if it’s all preloaded, you have to hold it all in memory at once. Also, the Emscripten virtual filesystem works hard to be as POSIX-compliant as it can, supporting things like permissions, mmap, etc., which add overhead that might be unnecessary in some applications.

    How much of a problem this is depends not just on the amount of data you load, but also the browser and the operating system. For example, on a 32-bit browser you are generally limited to 4GB of virtual address space, and fragmentation can be a problem. For these reasons, 64-bit browsers can sometimes succeed in running applications that need a lot of memory while 32-bit browsers fail (or fail some of the time). To some extent you can try to work around memory fragmentation problems by splitting up your data into separate asset bundles, by running Emscripten’s file packager separately several times, instead of using –preload-file once for everything. Each bundle is a combination of JavaScript that you load on your page, and a binary file with the data of all the files you packaged in that asset bundle, so in this way you get multiple smaller files rather than one big one. You can also run the file packager with –no-heap-copy, which will keep the downloaded asset bundle data in separate typed arrays instead of copying them into your program’s memory. However, even at best, these things can only help some of the time with memory fragmentation, in an unpredictable manner.

    Preloading all the data is therefore not always a viable solution: With large amounts of data, we might not have enough memory, or fragmentation might be a problem. Also, we might not know ahead of time which files we will need. And in general, even if preloading works for a project, we would still like to avoid it so that we can use as little memory as possible, as things generally run faster that way. That’s why we need the 2 other approaches to handling the problem of synchronous code, which we will discuss now.

    2. Refactor code to be asynchronous

    The second approach is to refactor your code to turn synchronous into asynchronous code. Emscripten provides asynchronous APIs you can use for this purpose, for example, the fread() in the example above could be replaced with an asynchronous network download (emscripten_async_wget, emscripten_async_wget_data), or an asynchronous access of locally-cached data in IndexedDB (emscripten_idb_async_load, emscripten_idb_async_store, etc.).

    And if you have synchronous code doing something other than filesystem access, for example rendering, Emscripten provides a generic API to do an asynchronous callback (emscripten_async_call). For the common case of a main loop which should be called once per frame from the browser’s event loop, Emscripten has a main loop API (emscripten_set_main_loop, etc.).

    Concretely, an fread() would be replaced with something like

    emscripten_async_wget_data("filename.txt", 0, onLoad, onError);

    where the first parameter is the filename on the remote server, then an optional void* argument (that will be passed to the callbacks), then callbacks on load and on error. The tricky thing is that the code that should execute right after the fread() would need to be in the onLoad callback – that’s where the refactoring comes in. Sometimes this is easy to do, but it might not be.

    Refactoring code to be asynchronous is generally the optimal thing to do. It makes your application use the APIs that are available on the Web in the way they are intended to be used. However, it does require changes to your project, and may require that the entire thing be designed in an event-friendly manner, which can be difficult if it wasn’t already structured that way. For these reasons, Emscripten has one more approach that can help you here.

    3. The Emterpreter: Run synchronous code asynchronously, automatically

    The Emterpreter is a fairly new option in Emscripten that was initially developed for startup-time reasons. It compiles your code into a binary bytecode, and ships it with a little interpreter (written in JavaScript, of course), in which the code can be executed. Code running in an interpreter is “manually executed” by us, so we can control it more easily than normal JavaScript, and we can add the capability to pause and resume, which is what we need to turn synchronous code into asynchronous code. Emterpreter-Async, the Emterpreter plus support for running synchronous code asynchronously, was therefore fairly easy to add on top of the existing Emterpreter option.

    The idea of an automatic transformation from synchronous to asynchronous code was experimented with by Lu Wang during his internship over the summer of 2014: the Asyncify option. Asyncify rewrites code at the LLVM level to support pausing and resuming execution: you write synchronous code, and the compiler rewrites it to run asynchronously. Returning to the fread() example from before, Asyncify would automatically break up the function around that call, and put the code after the call into a callback function – basically, it does what we suggested you do manually in the “Refactor code to be asynchronous” section above. This can work surprisingly well: For example, Lu ported vim, a large application with a lot of synchronous code in it, to the Web. And it works! However, we hit significant limitations in terms of increased code size because of how Asyncify restructures your code.

    The Emterpreter’s async support avoids the code size problem that Asyncify hit because it is an interpreter running bytecode: The bytecode is always the same size (in fact, smaller than asm.js), and we can manipulate control flow on it manually in the interpreter, without instrumenting the code.

    Of course, running in an interpreter can be quite slow, and this one is no exception – speed can be significantly slower than usual. Therefore, this is not a mode in which you want to run most of your code. But, the Emterpreter gives you the option to decide which parts of your codebase are interpreted and which are not, and this is crucial to productive use of this option, as we will now see.

    Let’s make this concrete by showing the option in practice on the Doom codebase. Here is a normal port of Doom (specifically Boon:, the Doom code with Freedoom open art assets). That link is just Doom compiled with Emscripten, not using synchronous code or the Emterpreter at all, yet. It looks like the game works in that link – do we even need anything else? It turns out that we need synchronous execution in two places in Doom: First, for filesystem access. Since Doom is from 1993, the size of the game is quite small compared to today’s hardware. We can preload all of the data files and things just work (that’s what happens in that link). So far, so good!

    The second problem, though, is trickier: For the most part Doom renders a whole frame in each iteration of the main loop (which we can call from the browser’s event loop one at a time), however it also does some visual effects using synchronous code. Those effects are not shown in that first link – Doom fans may have noticed something was missing! :)

    Here is a build with the Emterpreter-Async option enabled. This runs the entire application as bytecode in the interpreter, and it’s quite slow, as expected. Ignoring speed for now, you might notice that when you start a game, there is a “wipe” effect right before you begin to play, that wasn’t in the previous build. It looks kind of like a descending wave. Here’s a screenshot:

    22297That effect is written synchronously (note the screen update and sleep). The result is that in the initial port of the game, the wipe effect code is executed, but the JavaScript frame doesn’t end yet so no rendering happens. For this reason, we don’t see the wipe in the first build! But we do see it in the second, because we enabled the Emterpreter-Async option, which supports synchronous code.

    The second build is slow. What can we do? The Emterpreter lets you decide which code runs normally, as full-speed asm.js, and which is interpreted. We want to run only what we absolutely must run in the interpreter, and everything else in asm.js, so things are as fast as possible. For purposes of synchronous code, the code we must interpret is anything that is on the stack during a synchronous operation. To understand what that means, imagine that the callstack currently looks like this:

    main() => D_DoomMain() => D_Display() => D_Wipe() => I_uSleep()

    and the last of those does a call to sleep. Then the Emterpreter turns this synchronous operation into an asynchronous operation by saving where execution is right now in the current method (this is easy using the interpreter’s program counter, as well as since all local variables are already stored in a stack on a global typed array), then doing the same for the methods calling it, and while doing so to exit them all (which is also easy, each call to the interpreter is a call to a JavaScript method, which just returns). After that, we can do a setTimeout() for when we want to resume. So far, we have saved what we were doing, stopped, set an asynchronous callback for some time in the future, and we can then return control to the browser’s event loop, so it can render and so forth.

    When the asynchronous callback fires sometime later, we reverse the first part of the process: We call into the interpreter for main(), jump to the right position in it, then continue to do so for the rest of the call stack – basically, recreating the call stack exactly as it was before. At this point we can resume execution in the interpreter, and it is as if we never left: synchronous execution has been turned asynchronous.

    That means that if D_Wipe() does a synchronous operation, it must be interpreted, and anything that can call it as well, and so forth, recursively. The good news is that often such code tends to be small and doesn’t need to be fast: it’s typically event-loop handling code, and not code actually doing hard work. Talking abstractly, it’s common to see callstacks like these in games:

    main() => MainLoop() => RunTasks() => PhysicsTask() => HardWork()

    and

    main() => MainLoop() => RunTasks() => IOTask() => LoadFile()

    Assuming LoadFile() does a synchronous read of a file, it must be interpreted. As we mentioned above, this means everything that can be on the stack together with it must also be interpreted: main(), MainLoop(), RunTasks(), and IOTask() – but not any of the physics methods. In other words, if you never have physics and networking on the stack at the same time (a network event calling something that ends up calling physics, or a physics event that somehow decides to do a network request all of a sudden), then you can run networking in the interpreter, and physics at full speed. This is the case in Doom, and also other real-world codebases (and even in ones that are tricky, as in Em-DOSBox which has recursion in a crucial method, sometimes a solution can be found).

    Here is a build of Doom with that optimization enabled – it only interprets what we absolutely must interpret. It runs at about the same speed as the original, optimized build and it also has the wipe effect fully working. Also, the wipe effect is nice and smooth, which it wasn’t before: even though the wipe method itself must be interpreted – because it calls sleep() – the rendering code it calls in between sleeping can run at full speed, as that rendering code is never on the stack while sleeping!

    To have synchronous code working properly while the project stays at full speed, it is crucial to run exactly the right methods in the interpreter. Here is a list of the methods we need in Doom (in the ‘whitelist’ option there) – only 15 out of 1,425, or ~1%. To help you find a list for your project, the Emterpreter provides both static and dynamic tools, see the docs for more details.

    Conclusion

    Emscripten is often used to port code that contains synchronous portions, but long-running synchronous code is not possible on the Web. As described in this article, there are three approaches to handling that situation:

    • If the synchronous code just does file access, then preloading everything is a simple solution.
    • However, if there is a great amount of data, or you don’t know what you’ll need ahead of time, this might not work well. Another option is to refactor your code to be asynchronous.
    • If that isn’t an option either, perhaps because the refactoring is too extensive, then Emscripten now offers the Emterpreter option to run parts of your codebase in an interpreter which does support synchronous execution.

    Together, these approaches provide a range of options for handling synchronous code, and in particular the common case of synchronous filesystem access.

  8. What’s new in Web Audio

    Introduction

    It’s been a while since we said anything on Hacks about the Web Audio API. However, with Firefox 37/38 hitting our Developer Edition/Nightly browser channels, there are some interesting new features to talk about!

    This article presents you with some new Web Audio tricks to watch out for, such as the new StereoPannerNode, promise-based methods, and more.

    Simple stereo panning

    Firefox 37 introduces the StereoPannerNode interface, which allows you to add a stereo panning effect to an audio source simply and easily. It takes a single property: pan—an a-rate AudioParam that can accept numeric values between -1.0 (full left channel pan) and 1.0 (full right channel pan).

    But don’t we already have a PannerNode?

    You may have already used the older PannerNode interface, which allows you to position sounds in 3D. Connecting a sound source to a PannerNode causes it to be “spatialised”, meaning that it is placed into a 3D space and you can then specify the position of the listener inside. The browser then figures out how to make the sources sound, applying panning and doppler shift effects, and other nice 3D “artifacts” if the sounds are moving over time, etc:

    var audioContext = new AudioContext();
    var pannerNode = audioContext.createPanner();
     
    // The listener is 100 units to the right of the 3D origin
    audioContext.listener.setPosition(100, 0, 0);
     
    // The panner is in the 3D origin
    pannerNode.setPosition(0, 0, 0);

    This works well with WebGL-based games as both environments use similar units for positioning—an array of x, y, z values. So you could easily update the position, orientation, and velocity of the PannerNodes as you update the position of the entities in your 3D scene.

    But what if you are just building a conventional music player where the songs are already stereo tracks, and you actually don’t care at all about 3D? You have to go through a more complicated setup process than should be necessary, and it can also be computationally more expensive. With the increased usage of mobile devices, every operation you don’t perform is a bit more battery life you save, and users of your website will love you for it.

    Enter StereoPannerNode

    StereoPannerNode is a much better solution for simple stereo use cases, as described above. You don’t need to care about the listener’s position; you just need to connect source nodes that you want to spatialise to a StereoPannerNode instance, then use the pan parameter.

    To use a stereo panner, first create a StereoPannerNode using createStereoPanner(), and then connect it to your audio source. For example:

    var audioCtx = window.AudioContext();
    // You can use any type of source
    var source = audioCtx.createMediaElementSource(myAudio);
    var panNode = audioCtx.createStereoPanner();
     
    source.connect(panNode);
    panNode.connect(audioCtx.destination);

    To change the amount of panning applied, you just update the pan property value:

    panNode.pan.value = 0.5; // places the sound halfway to the right
    panNode.pan.value = 0.0; // centers it
    panNode.pan.value = -0.5; // places the sound halfway to the left

    You can see http://mdn.github.io/stereo-panner-node/ for a complete example.

    Also, since pan is an a-rate AudioParam you can design nice smooth curves using parameter automation, and the values will be updated per sample. Trying to do this kind of change over time would sound weird and unnatural if you updated the value over multiple requestAnimationFrame calls. And you can’t automate PannerNode positions either.

    For example, this is how you could set up a panning transition from left to right that lasts two seconds:

    panNode.pan.setValueAtTime(-1, audioContext.currentTime);
    panNode.pan.linearRampToValueAtTime(1, audioContext.currentTime + 2);

    The browser will take care of updating the pan value for you. And now, as of recently, you can also visualise these curves using the Firefox Devtools Web Audio Editor.

    Detecting when StereoPannerNode is available

    It might be the case that the Web Audio implementation you’re using has not implemented this type of node yet. (At the time of this writing, it is supported in Firefox 37 and Chrome 42 only.) If you try to use StereoPannerNode in these cases, you’re going to generate a beautiful undefined is not a function error instead.

    To make sure StereoPannerNodes are available, just check whether the createStereoPanner() method exists in your AudioContext:

    if (audioContext.createStereoPanner) {
        // StereoPannerNode is supported!
    }

    If it doesn’t, you will need to revert back to the older PannerNode.

    Changes to the default PannerNode panning algorithm

    The default panning algorithm type used in PannerNodes used to be HRTF, which is a high quality algorithm that rendered its output using a convolution with human-based data (thus it’s very realistic). However it is also very computationally expensive, requiring the processing to be run in additional threads to ensure smooth playback.

    Authors often don’t require such a high level of quality and just need something that is good enough, so the default PannerNode.type is now equalpower, which is much cheaper to compute. If you want to go back to using the high quality panning algorithm instead, you just need to change the type:

    pannerNodeInstance.type = 'HRTF';

    Incidentally, a PannerNode using type = 'equalpower' results in the same algorithm that StereoPannerNode uses.

    Promise-based methods

    Another interesting feature that has been recently added to the Web Audio spec is Promise-based versions of certain methods. These are OfflineAudioContext.startRendering() and AudioContext.decodeAudioData.

    The below sections show how the method calls look with and without Promises.

    OfflineAudioContext.startRendering()

    Let’s suppose we want to generate a minute of audio at 44100 Hz. We’d first create the context:

    var offlineAudioContext = new OfflineAudioContext(2, 44100 * 60, 44100);

    Classic code

    offlineAudioContext.addEventListener('oncomplete', function(e) {
        // rendering complete, results are at `e.renderedBuffer`
    });
    offlineAudioContext.startRendering();

    Promise-based code

    offlineAudioContext.startRendering().then(function(renderedBuffer) {
        // rendered results in `renderedBuffer`
    });

    AudioContext.decodeAudioData

    Likewise, when decoding an audio track we would create the context first:

    var audioContext = new AudioContext();

    Classic code

    audioContext.decodeAudioData(data, function onSuccess(decodedBuffer) {
        // decoded data is decodedBuffer
    }, function onError(e) {
        // guess what... something didn't work out well!
    });

    Promise-based code

    audioContext.decodeAudioData(data).then(function(decodedBuffer) {
        // decoded data is decodedBuffer
    }, function onError(e) {
        // guess what... something didn't work out well!
    });

    In both cases the differences don’t seem major, but if you’re composing the results of promises sequentially or if you’re waiting on an event to complete before calling several other methods, promises are really helpful to avoid callback hell.

    Detecting support for Promise-based methods

    Again, you don’t want to get the dreaded undefined is not a function error message if the browser you’re running your code on doesn’t support these new versions of the methods.

    A quick way to check for support: look at the returned type of these calls. If they return a Promise, we’re in luck. If they don’t, we have to keep using the old methods:

    if((new OfflineAudioContext(1, 1, 44100)).startRendering() != undefined) {
        // Promise with startRendering is supported
    }
     
    if((new AudioContext()).decodeAudioData(new Uint8Array(1)) != undefined) {
        // Promise with decodeAudioData is supported
    }

    Audio workers

    Although the spec has not been finalised and they are not implemented in any browser yet, it is also worth giving a mention to Audio Workers, which —you’ve guessed it— are a specialised type of web worker for use by Web Audio code.

    Audio Workers will replace the almost-obsolete ScriptProcessorNode. Originally, this was the way to run your own custom nodes inside the audio graph, but they actually run on the main thread causing all sorts of problems, from audio glitches (if the main thread becomes stalled) to unresponsive UI code (if the ScriptProcessorNodes aren’t fast enough to process their data).

    The biggest feature of audio workers is that they run in their own separate thread, just like any other Worker. This ensures that audio processing is prioritised and we avoid sound glitches, which human ears are very sensitive to.

    There is an ongoing discussion on the w3c web audio list; if you are interested in this and other Web Audio developments, you should go check it out.

    Exciting times for audio on the Web!

  9. Embedding an HTTP Web Server in Firefox OS

    Nearing the end of last year, Mozilla employees were gathered together for a week of collaboration and planning. During that week, a group was formed to envision what the future of Firefox OS might be surrounding a more P2P-focused Web. In particular, we’ve been looking at harnessing technologies to collectively enable offline P2P connections such as Bluetooth, NFC and WiFi Direct.

    Since these technologies only provide a means to communicate between devices, it became immediately clear that we would also need a protocol for apps to send and receive data. I quickly realized that we already have a standard protocol for transmitting data in web apps that we could leverage – HTTP.

    By utilizing HTTP, we would already have everything we’d need for apps to send and receive data on the client side, but we would still need a web server running in the browser to enable offline P2P communications. While this type of HTTP server functionality might be best suited as part of a standardized WebAPI to be baked into Gecko, we actually already have everything we need in Firefox OS to implement this in JavaScript today!

    navigator.mozTCPSocket

    Packaged apps have access to both raw TCP and UDP network sockets, but since we’re dealing with HTTP, we only need to work with TCP sockets. Access to the TCPSocket API is exposed through navigator.mozTCPSocket which is currently only exposed to “privileged” packaged apps with the tcp-socket permission:

    "type": "privileged",
    "permissions": {
      "tcp-socket": {}
    },

    In order to respond to incoming HTTP requests, we need to create a new TCPSocket that listens on a known port such as 8080:

    var socket = navigator.mozTCPSocket.listen(8080);

    When an incoming HTTP request is received, the TCPSocket needs to handle the request through the onconnect handler. The onconnect handler will receive a TCPSocket object used to service the request. The TCPSocket you receive will then call its own ondata handler each time additional HTTP request data is received:

    socket.onconnect = function(connection) {
      connection.ondata = function(evt) {
        console.log(evt.data);
      };
    };

    Typically, an HTTP request will result in a single calling of the ondata handler. However, in cases where the HTTP request payload is very large, such as for file uploads, the ondata handler will be triggered each time the buffer is filled, until the entire request payload is delivered.

    In order to respond to the HTTP request, we must send data to the TCPSocket we received from the onconnect handler:

    connection.ondata = function(evt) {
      var response = 'HTTP/1.1 200 OK\r\n';
      var body = 'Hello World!';
     
      response += 'Content-Length: ' + body.length + '\r\n';
      response += '\r\n';
      response += body;
     
      connection.send(response);
      connection.close();
    };

    The above example sends a proper HTTP response with “Hello World!” in the body. Valid HTTP responses must contain a status line which consists of the HTTP version HTTP/1.1, the response code 200 and the response reason OK terminated by a CR+LF \r\n character sequence. Immediately following the status line are the HTTP headers, one per line, separated by a CR+LF character sequence. After the headers, an additional CR+LF character sequence is required to separate the headers from the body of the HTTP response.

    FxOS Web Server

    Now, it is likely that we will want to go beyond simple static “Hello World!” responses to do things like parsing the URL path and extracting parameters from the HTTP request in order to respond with dynamic content. It just so happens that I’ve already implemented a basic-featured HTTP server library that you can include in your own Firefox OS apps!

    FxOS Web Server can parse all parts of the HTTP request for various content types including application/x-www-form-urlencoded and multipart/form-data. It can also gracefully handle large HTTP requests for file uploads and can send large binary responses for serving up content such as images and videos. You can either download the source code for FxOS Web Server on GitHub to include in your projects manually or you can utilize Bower to fetch the latest version:

    bower install justindarc/fxos-web-server --save

    Once you have the source code downloaded, you’ll need to include dist/fxos-web-server.js in your app using a <script> tag or a module loader like RequireJS.

    Simple File Storage App

    Next, I’m going to show you how to use FxOS Web Server to build a simple Firefox OS app that lets you use your mobile device like a portable flash drive for storing and retrieving files. You can see the source code for the finished product on GitHub.

    Before we get into the code, let’s set up our app manifest to get permission to access DeviceStorage and TCPSocket:

    {
      "version": "1.0.0",
      "name": "WebDrive",
      "description": "A Firefox OS app for storing files from a web browser",
      "launch_path": "/index.html",
      "icons": {
        "128": "/icons/icon_128.png"
      },
      "type": "privileged",
      "permissions": {
        "device-storage:sdcard": { "access": "readwrite" },
        "tcp-socket": {}
      }
    }

    Our app won’t need much UI, just a listing of files in the “WebDrive” folder on the device, so our HTML will be pretty simple:

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>WebDrive</title>
      <meta name="description" content="A Firefox OS app for storing files from a web browser">
      <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
      <script src="bower_components/fxos-web-server/dist/fxos-web-server.js"></script>
      <script src="js/storage.js"></script>
      <script src="js/app.js"></script>
    </head>
    <body>
      <h1>WebDrive</h1>
      <hr>
      <h3>Files</h3>
      <ul id="list"></ul>
    </body>
    </html>

    As you can see, I’ve included fxos-web-server.js in addition to app.js. I’ve also included a DeviceStorage helper module called storage.js since enumerating files can get somewhat complex. This will help keep the focus on our code specific to the task at hand.

    The first thing we’ll need to do is create new instances of the HTTPServer and Storage objects:

    var httpServer = new HTTPServer(8080);
    var storage = new Storage('sdcard');

    This will initialize a new HTTPServer on port 8080 and a new instance of our Storage helper pointing to the device’s SD card. In order for our HTTPServer instance to be useful, we must listen for and handle the “request” event. When an incoming HTTP request is received, the HTTPServer will emit a “request” event that passes the parsed HTTP request as an HTTPRequest object to the event handler.

    The HTTPRequest object contains various properties of an HTTP request including the HTTP method, path, headers, query parameters and form data. In addition to the request data, an HTTPResponse object is also passed to the “request” event handler. The HTTPResponse object allows us to send our response as a file or string and set the response headers:

    httpServer.addEventListener('request', function(evt) {
      var request  = evt.request;
      var response = evt.response;
     
      // Handle request here...
    });

    When a user requests the root URL of our web server, we’ll want to present them with a listing of files stored in the “WebDrive” folder on the device along with a file input for uploading new files. For convenience, we’ll create two helper functions to generate the HTML string to send in our HTTP response. One will just generate the listing of files which we’ll reuse to display the files on the device locally and the other will generate the entire HTML document to send in the HTTP response:

    function generateListing(callback) {
      storage.list('WebDrive', function(directory) {
        if (!directory || Object.keys(directory).length === 0) {
          callback('<li>No files found</li>');
          return;
        }
     
        var html = '';
        for (var file in directory) {
          html += `<li><a href="/${encodeURIComponent(file)}" target="_blank">${file}</a></li>`;
        }
     
        callback(html);
      });
    }
     
    function generateHTML(callback) {
      generateListing(function(listing) {
        var html =
    `<!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>WebDrive</title>
    </head>
    <body>
      <h1>WebDrive</h1>
      <form method="POST" enctype="multipart/form-data">
        <input type="file" name="file">
        <button type="submit">Upload</button>
      </form>
      <hr>
      <h3>Files</h3>
      <ul>${listing}</ul>
    </body>
    </html>`;
     
        callback(html);
      });
    }

    You’ll notice that we’re using ES6 Template Strings for generating our HTML. If you’re not familiar with Template Strings, they allow us to have multi-line strings that automatically include whitespace and new lines and we can do basic string interpolation that automatically inserts values inside the ${} syntax. This is especially useful for generating HTML because it allows us to span multiple lines so our template markup remains highly readable when embedded within JavaScript code.

    Now that we have our helper functions, let’s send our HTML response in our “request” event handler:

    httpServer.addEventListener('request', function(evt) {
      var request  = evt.request;
      var response = evt.response;
     
      generateHTML(function(html) {
        response.send(html);
      });
    });

    As of right now, our “request” event handler will always respond with an HTML page listing all the files in the device’s “WebDrive” folder. However, we must first start the HTTPServer before we can receive any requests. We’ll do this once the DOM is ready and while we’re at it, let’s also render the file listing locally:

    window.addEventListener('DOMContentLoaded', function(evt) {
      generateListing(function(listing) {
        list.innerHTML = listing;
      });
     
      httpServer.start();
    });

    We should also be sure to stop the HTTPServer when the app is terminated, otherwise the network socket may never be freed:

    window.addEventListener('beforeunload', function(evt) {
      httpServer.stop();
    });

    At this point, our web server should be up and running! Go ahead and install the app on your device or simulator using WebIDE. Once installed, launch the app and point your desktop browser to your device’s IP address at port 8080 (e.g.: http://10.0.1.12:8080).

    You should see our index page load in your desktop browser, but the upload form still isn’t wired up and if you have any files in your “WebDrive” folder on your device, they cannot be downloaded yet. Let’s first wire up the file upload by first creating another helper function to save files received in an HTTPRequest:

    function saveFile(file, callback) {
      var arrayBuffer = BinaryUtils.stringToArrayBuffer(file.value);
      var blob = new Blob([arrayBuffer]);
     
      storage.add(blob, 'WebDrive/' + file.metadata.filename, callback);
    }

    This function will first convert the file’s contents to an ArrayBuffer using the BinaryUtils utility that comes with fxos-web-server.js. We then create a Blob that we pass to our Storage helper to save it to the SD card in the “WebDrive” folder. Note that the filename can be extracted from the file’s metadata object since it gets passed to the server using ‘multipart/form-data’ encoding.

    Now that we have a helper for saving an uploaded file, let’s wire it up in our “request” event handler:

    httpServer.addEventListener('request', function(evt) {
      var request  = evt.request;
      var response = evt.response;
     
      if (request.method === 'POST' && request.body.file) {
        saveFile(request.body.file, function() {
          generateHTML(function(html) {
            response.send(html);
          });
     
          generateListing(function(html) {
            list.innerHTML = html;
          });
        });
     
        return;
      }
     
      generateHTML(function(html) {
        response.send(html);
      });
    });

    Now, anytime an HTTP POST request is received that contains a “file” parameter in the request body, we will save the file to the “WebDrive” folder on the SD card and respond with an updated file listing index page. At the same time, we’ll also update the file listing on the local device to display the newly-added file.

    The only remaining part of our app to wire up is the ability to download files. Once again, let’s update the “request” event handler to do this:

    httpServer.addEventListener('request', function(evt) {
      var request  = evt.request;
      var response = evt.response;
     
      if (request.method === 'POST' && request.body.file) {
        saveFile(request.body.file, function() {
          generateHTML(function(html) {
            response.send(html);
          });
     
          generateListing(function(html) {
            list.innerHTML = html;
          });
        });
     
        return;
      }
     
      var path = decodeURIComponent(request.path);
      if (path !== '/') {
        storage.get('WebDrive' + path, function(file) {
          if (!file) {
            response.send(null, 404);
            return;
          }
     
          response.headers['Content-Type'] = file.type;
          response.sendFile(file);
        });
     
        return;
      }
     
      generateHTML(function(html) {
        response.send(html);
      });
    });

    This time, our “request” event handler will check the requested path to see if a URL other than the root is being requested. If so, we assume that the user is requesting to download a file which we then proceed to get using our Storage helper. If the file cannot be found, we return an HTTP 404 error. Otherwise, we set the “Content-Type” in the response header to the file’s MIME type and send the file with the HTTPResponse object.

    You can now re-install the app to your device or simulator using WebIDE and once again point your desktop browser to your device’s IP address at port 8080. Now, you should be able to upload and download files from your device using your desktop browser!

    The possible use cases enabled by embedding a web server into Firefox OS apps are nearly limitless. Not only can you serve up web content from your device to a desktop browser, as we just did here, but you can also serve up content from one device to another. That also means that you can use HTTP to send and receive data between apps on the same device! Since its inception, FxOS Web Server has been used as a foundation for several exciting experiments at Mozilla:

    • wifi-columns

      Guillaume Marty has combined FxOS Web Server with his amazing jsSMS Master System/Game Gear emulator to enable multi-player gaming across two devices in conjunction with WiFi Direct.

    • sharing

      Several members of the Gaia team have used FxOS Web Server and dns-sd.js to create an app that allows users to discover and share apps with friends over WiFi.

    • firedrop

      I have personally used FxOS Web Server to build an app that lets you share files with nearby users without an Internet connection using WiFi Direct. You can see the app in action here:

    I look forward to seeing all the exciting things that are built next with FxOS Web Server!

  10. Introducing node-firefox

    NOTE: we presented this project last Sunday at FOSDEM, but not everyone could make it to Brussels, so here’s a post explaining what node-firefox is and how can it help you superturbocharge your Firefox OS app development!

    At Mozilla we’re always looking for ways in which we can make developers’ lives easier. When aspiring app developers told us that it was cumbersome to get started writing Open Web Apps, we worked on turning App Manager into a more beginner friendly environment, which in turn gave way to WebIDE. This tool simplifies many actions that were slow and tedious before, such as creating a new app, downloading and installing simulators or running and debugging apps.

    But there was still a segment of developers that felt left out: power users! They already have their node.js-based build toolchains, with tasks such as asset optimisation, code hinting, or test running. They often also use tools such as Browserify, and perhaps they don’t even write JavaScript, favouring alternatives such as CoffeeScript instead, but all these goodies require you to build the app or website before you push it again to your device or reload the browser.

    Essentially, we were telling these developers to leave their beloved command line (or editor shortcuts!) to go to WebIDE and click a button to deploy the app, and then go back to their editor of choice. And they most unanimously answered: “But we don’t like to click! We like the terminal!”

    How can we make this more efficient?

    People didn’t like this because it implied changing contexts. It is inefficient, we are engineers, and if there one thing that engineers like more than building new things it is probably optimising and streamlining processes.

    Since we already have a build script, the only step that is left in order to get our apps onto the runtime is deploying, and that’s what we are using WebIDE for. So the obvious question would be: can we do whatever WebIDE is doing to deploy, but programmatically?

    Servers and actors

    Every Firefox runtime has something called the remote debugger server. This is not enabled by default, for obvious security reasons, but when enabled, clients can connect to it and take advantage of its various functionalities, such as installing apps, accessing the console, etc. And this is what WebIDE does internally.

    Each of these functionalities is provided by an actor. For example, suppose we want to list the installed apps. We would…

    • first find the webApps actor
    • then run the getAll command
    • and get a list of apps in response

    Another example would be installing a packaged app. The steps would be:

    • first zip the app contents, using whatever library or way you like
    • then get the webApps actor
    • call the uploadPackage command in the webApps actor with the contents of the ZIP file
    • the result of this call is a File actor
    • call the install command in the webApps actor with the returned File actor
    • done!

    Therefore all the magic for installing apps is not in WebIDE—it is in the servers! We can take advantage of this magic programmatically, but building a client from scratch involves establishing TCP connections and parsing packets, which is not what you want to be doing: you want to write apps and push them to devices instead!

    Despair not, as node-firefox will abstract that for you. It is not a monolithic piece of code, but a series of node.js modules, each one of them performing a different task, hosted on its own separate repository and published to the npm registry like good module citizens. You can use as many of them as you need in your scripts or task runners, and thus you can finally build and run your app without ever leaving the command line.

    Show, don’t tell

    But enough of talking and describing; let’s see how to write a script that starts a simulator!

    First install the module in your project, using npm:

    npm install --save node-firefox-start-simulator

    And this would be the script:

    var startSimulator = require('node-firefox-start-simulator');
     
    startSimulator({ version: '2.2' })
      .then(function(simulator) {
        console.log('Listening in port', simulator.port);
      });

    That’s it! With just a few lines of code you are able to programmatically start a version 2.2 simulator. If you don’t care about the version, just don’t pass in any option to startSimulator, and it will start the first simulator it finds:

    startSimulator().then(function(simulator) {
      // your code
    });

    We can also see this in action. Here’s us starting a simulator, installing an app and launching it, all from a node.js script:

    Starting simulator, running app from node.js

    The code for this example is actually the example for the node-firefox-uninstall-app module. Each of the node-firefox modules come with an examples folder so you can get started rather quickly.

    As we mentioned at the beginning, many web developers that move to app development want to keep using their task runners, so we also wrote an example of how to use node-firefox with gulp.

    Let’s run the default-one task. This starts a simulator, deploys an app, and for a bit more of a challenge, also keeps watching for CSS changes. If you edit and save any of the app’s stylesheets, the file watcher will detect the change, and send the new file contents to the runtime, which will replace them on the fly, without having to stop, push and relaunch the whole app. Look at me changing the background colour from austere dark blue to the timeless Paul Rouget pink!

    Starting simulator, launching app with gulp

    Live CSS reloading is really great to build and experiment with UI interfaces. Not having to reload the app and then navigate to the particular layout you want to work in saves lots of time—I wish I’d had that when I was programming Android apps!

    But we can outdo this. The default-all task will do the same as default-one, but for all the simulators installed in your system, so you can see the effect of your CSS changes in all the simulators at the same time:

    Starting all simulators, launching app and live CSS reload with gulp.

    Unfortunately there is a bug in the 2.1 and 2.2 simulators, and those don’t reload the stylesheet changes, but it’s been filed and will be fixed.

    What can we do so far?

    The current set of modules lets you find ports where runtimes are listening, find and start simulators; connect to runtimes; find, install, uninstall and launch apps, and reload stylesheets.

    Philosophy

    You might have noticed a pattern already, but just in case it wasn’t evident enough, we are trying to write deliberately simple modules. Each module should perform only one action, return a Promise and use as few dependencies as possible.

    Small modules are easier to understand, use, and test. Also, most of the future Web APIs are designed to work with Promises, and we want to write code for the future, not for the past. In addition, reducing the number of dependencies also makes it easier for new people to get started on contributing to a module, as there are fewer new unfamiliar elements to understand.

    Finally, since all the modules work the same way, when you know how to use one module you know how to use the rest—the only thing that changes is the parameters, and the result.

    Dream ideas (or: what we cannot do yet)

    There’s a number of things that we’d like to see happen in the future. Some people call them features, but I call them ‘dream ideas.’

    A recurrent one is the WebCLI: a counterpart equivalent to WebIDE, where everything you can do with WebIDE could be done with a command line tool. I keep switching back and forth between “this is a good idea” and “perhaps we don’t need this at all and a library of tasks will be enough”, but people seemed to like the idea, so maybe it’s not that bad!

    Another great feature would be the ability to attach the DevTools debugger to an app that was launched from the command line but that just crashed. Launching apps from the command line is great, but command line debuggers are not that exciting! Why not use the best of both worlds?

    Or maybe it would be neat to control any browser from the command line, interfacing via Valence!

    And finally, there is my favourite dream idea: Firefox OS custom editions. Imagine if we could just write a script that would create an empty Firefox OS slate, pull in our favourite apps and settings, and generate a whole Firefox OS image that we could then flash to devices. And since it is not a binary blob but a script, we could just publish it on its repository, and other people could remix and build their own Firefox OS based editions.

    How do we get there?

    There’s still a long way ahead of us, and lots of areas that need work. Perhaps the most urgent task is to get better multiplatform support. Currently we can only interact with runtimes through the network, but no physical devices. Also, support on platforms other than Mac OS is largely lacking.

    Testing is another important aspect. If we test early, often and profusely we will be able to detect problems such as the CSS bug I stumbled upon when building the gulp demo. We want to have these modules running on several platforms and connecting to other different platforms, including physical devices.

    Of course we need more modules, and more examples! To make sure no two people start writing the same module, we are discussing and proposing new modules in the top project issue tracker. And we’d love to see more examples, or even just better examples that hook existing functionality in other node modules with our code. For example, one could add manifest validation via the firefox-app-validator-manifest module.

    And, as always, we need you. We are not you, so we cannot know what you need or what thoughts cross your mind. And we certainly cannot use software the same way you use it either. We need your input and your contributions!

    We’re looking forward to seeing what you create with node-firefox. File issues, or talk to us on irc if you have questions. We hang out mostly in the #apps and #devtools channels in irc.mozilla.org.

    Thanks

    It would be dishonest not to thank Nicola Greco, whom I mentored last summer when he was interning at Mozilla. He came up with the initial idea of building individual node modules that would help you develop Firefox OS apps. Go check out his final intern presentation, as it’s really entertaining and illustrative!

    Many thanks to all the (infinitely patient) DevToolers Ryan Stinnet, Alexandre Poirot, Jeff Griffiths and Dave Camp, who helped us find our way around remote servers and actors and whatnot, and huge thanks to Heather Arthur who wrote firefox-client and made writing node-firefox way more pleasant than it would have been otherwise.