Mozilla

Articles

Sort by:

View:

  1. 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.

  2. 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.

  3. 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!

  4. WebRTC requires Perfect Forward Secrecy (PFS) starting in Firefox 38

    Today, we are announcing that Firefox 38 will take further measures to secure users’ communications by removing support in WebRTC for all DTLS cipher suites that do not support forward secrecy. For developers: if you have a WebRTC application or server that doesn’t support PFS ciphers, you will need to update your code.

    Forward secrecy, also known as Perfect Forward Secrecy (PFS), is a feature of a cryptographic protocol that limits the damage of a key compromise: “This means that the compromise of one [session] cannot lead to the compromise of others, and also that there is not a single secret value which can lead to the compromise of multiple [sessions]”.

    The PFS suites in TLS and DTLS use an ephemeral Diffie-Hellman key exchange (DHE) or elliptic-curve Diffie-Hellman (ECDHE) to create a different shared secret key for each session. The WebRTC security architecture recommends that PFS suites be preferred for WebRTC.

    Due to bug 102794, Firefox is unable to act as a server for DHE cipher suites. We plan to add complete DHE support, but until then we recommend the use of the ECDHE cipher suites.

    Existing users of the webrtc.org codebase who are using OpenSSL and derivatives such as BoringSSL need to update to enable ECDHE ciphers. This bug contains more details.

    If you have a WebRTC application or server that doesn’t support PFS ciphers, you should be working on getting that resolved ASAP. Firefox 38 is scheduled for Beta the week of March 30th, and a general release is planned for Tuesday, May 12th.

  5. 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.

  6. 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!

  7. Introducing @counter-style

    Introduction

    The characters that indicate items in a list are called counters — they can be bullets or numbers. They are defined using the list-style-type CSS property. CSS1 introduced a list of predefined styles to be used as counter markers. The initial list was then slightly extended with addition of more predefined counter styles in CSS2.1. Even with 14 predefined counter styles, it still failed to address use cases from around the world.

    Now, the CSS Counter Styles Level 3 specification, which reached Candidate Recommendation last week, adds new predefined counter styles to the existing list that should address most common counter use cases.

    In addition to the new predefined styles, the spec also offers an open-ended solution for the needs of worldwide typography by introducing the @counter-style at-rule — which lets us define custom counter styles or even extend existing ones — and the symbols() function. The latter is a shorthand for defining inline styles and is useful when the fine-grained control that @counter-style offers is not needed.

    This article provides a guide to using the new counter features of CSS Level 3.

    @counter-style

    A @counter-style at-rule is identified by a name and defined with a set of descriptors. It takes a numerical counter value and converts it into a string or image representation. A custom counter style definition looks like this:

    @counter-style blacknwhite {
      system: cyclic;
      negative: "(" ")";
      prefix: "/";
      symbols: ◆ ◇;
      suffix: "/ ";
      range: 2 4;
      speak-as: "bullets";
    }

    The different available descriptors have the following meanings:

    1. system – the system descriptor lets the author specify an algorithm to convert the numerical counter value to a basic string representation. For example, the cyclic system cycles repeatedly through the list of symbols provided to create counter representations.
    2. negative – the negative descriptor provides the ability to specify additional symbols, such as a negative sign, to be appended/prepended to a counter representation if the counter value is negative. If only one symbol is specified, it will be added in front of the marker representation. A second value, if specified (as in the example below), will be added after the marker.
      @counter-style neg {
        system: numeric;
        symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
        negative: "(" ")";
      }

      The above counter style definition will wrap negative markers in a pair of parentheses, instead of preceding them with the minus sign.

    3. prefix – specifies a symbol that will be prepended to the final counter representation.
    4. suffix – specifies a symbol that will be appended to the final counter representation.The default value of the suffix descriptor is a full stop followed by a space. If you need to replace the full stop “.” with a parenthesis, you can specify the suffix descriptor:
      @counter-style decimal-parenthesis {
        system: numeric;
        symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
        suffix: ") ";
      }
    5. rangerange lets the author define a range of values over which a counter style is applicable. If a counter value falls outside the specified range, then the specified or default fallback style is used to represent that particular counter value, for example:
      @counter-style range-example {
        system: cyclic;
        symbols: A B C D;
        range:  4 8;
       }

      The above rule will apply the style only for counter values starting from 4 to 8. The fallback style, decimal, will be used for the rest of the markers.

    6. pad – as the name suggests, the pad descriptor lets the author specify a padding length when the counter representations need to be of a minimum length. For example, if you want the counters to start at 01 and go through 02, 03, 04, etc., then the following pad descriptor should be used:
      @counter-style decimal-new {
        system: numeric;
        symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
        pad: 2 "0";
      }

      (For a better way to achieve the same result, but without specifying the counter symbols, see the section below about extending existing systems.)

    7. fallback – the fallback specifies a style to fall back to if the specified system is unable to construct a counter representation or if a particular counter value falls outside the specified range.
    8. symbols and additive-symbols – specify the symbols that will be used to construct the counter representation. The symbols descriptor is used in most cases other than when the system specified is ‘additive.’ While symbols specifies individual symbols, the additive-symbols descriptor is composed of what are known as additive tuples – , which each consist of a symbol and a non-negative weight.Symbols specified can be strings, images in the form url(image-name) or identifiers. The below example uses images as symbols.
      @counter-style winners-list {
        system: fixed;
        symbols: url(gold-medal.svg) url(silver-medal.svg) url(bronze-medal.svg);
        suffix: " ";
      }
    9. speak-as – specifies how a counter value should be spoken by speech synthesizers such as screen readers. For example, the author can specify a marker symbol to be read out as a word, a number, or as an audio cue for a bullet point. The example below reads out the counter values as numbers.
      @counter-style circled-digits {
        system: fixed;
        symbols: ➀ ➁ ➂;
        suffix: ' ';
        speak-as: numbers;
      }

      You can then use a named style with list-style-type or with the counters() function as you normally would use a predefined counter style.

      ul {
        list-style-type: circled-digits;
      }

      On a supported browser, the counter style above will render lists with markers like this:

      @counter-style demo image

    The system descriptor

    The system descriptor takes one of the predefined algorithms, which describe how to convert a numerical counter value to its representation. The system descriptor can have values that are cyclic, numeric, alphabetic, symbolic, additive, fixed and extends.

    If the system specified is cyclic, it will cycle through the list of symbols provided. Once the end of the list is reached, it will loop back to the beginning and start over. The fixed system is similar, but once the list of symbols is exhausted, it will resort to the fallback style to represent the rest of the markers. The symbolic, numeric and alphabetic systems are similar to the above two, but with their own subtle differences.

    The additive system requires that the additive-symbols descriptor be specified instead of the symbols descriptor. additive-symbols takes a list of additive tuples. Each additive tuple consists of a symbol and its numerical weight. The additive system is used to represent “sign-value” numbering systems such as the Roman numerals.

    We can rewrite the Roman numerals as a @counter-style rule using the additive system like this:

    @counter-style custom-roman {
      system: additive;
      range: 1 100;
      additive-symbols: 100 C, 90 XC, 50 L, 40 XL, 10 X, 9 IX, 5 V, 4 IV, 1 I;
    }

    Extending existing or custom counter styles

    The extends system lets authors create custom counter styles based on existing ones. Authors can use the algorithm of another counter style, but alter its other aspects. If a @counter-style rule using the extends system has any unspecified descriptors, their values will be taken from the extended counter style specified.

    For example, if you want to define a new style which is similar to decimal, but has a string “Chapter ” in front of all the marker values, then rather than creating an entirely new style you can use the extends system to extend the  decimal style like this:

    @counter-style chapters {
      system: extends decimal;
      prefix: 'Chapter ';
    }

    Or, if you need the decimal style to start numbers from 01, 02, 03.. instead of 1, 2, 3.., you can simply specify the pad descriptor:

    @counter-style decimal-new {
      system: extends decimal;
      pad: 2 "0";
    }

    A counter style using the extends system should not specify the symbols and additive-symbols descriptors.

    See the reference page on MDN for details and usage examples of all system values.

    A shorthand – The symbols() function

    While a @counter-style at-rule lets you tailor a custom counter style, often such elaborate control is not needed. That is where the symbols() function comes in. symbols() lets you define inline counter styles as function properties. Since the counter styles defined in this way are nameless (anonymous), they can not be reused elsewhere in the stylesheet.

    An example anonymous counter style looks like this:

    ul {
        list-style-type: symbols(fixed url(one.svg) url(two.svg));
    }

    Even more predefined counter styles

    CSS Lists 3 vastly extends the number of predefined styles available. Along with the predefined styles such as decimal, disc, circle and square that existed before, additional styles such as hebrew, thai, gujarati, disclosure-open/close, etc. are also added to the predefined list. The full list of predefined styles enabled by the spec can be seen here.

    Browser support

    Support for @counter-style and the symbols() function along with the new predefined styles landed in Firefox 33. Google Chrome hasn’t implemented @counter-styles or the symbols() function yet, but most of the new numeric and alphabetic predefined styles have been implemented. There is no support in IE so far. Support has already landed in the latest releases of Firefox for Android and in the upcoming Firefox OS 2.1, which has support for @counter-style. Support for symbols() will land in Firefox OS 2.2.

    Examples

    Check out this demo page and see if @counter-style is supported in your favorite browsers.

  8. Exploring object-fit

    On web documents, a common problem concerns the display of different sized images (or videos) in the same place. Perhaps you are writing a dynamic gallery app that accepts user submissions. You can’t guarantee that everyone will upload images of exactly the same aspect ratio, so what do you do?

    Letting the aspect ratio distort to fit the containing replaced element nearly always looks horrible. And doing some kind of dynamic cropping or resizing on the fly each time might be more work than you have the capability to implement. (For instance, maybe you’re working on a CMS and don’t have permission to edit anything except the page content.)

    The CSS Image Values and Replaced Content module provides properties called object-fit — which solves such problems, and object-position — which sets the horizontal and vertical position of the content inside the element.

    These elements have decent support across modern browsers (with the exception of IE). In this article we’ll look at a few examples of how they can be used.

    Note: object-fit works with SVG content, but the same effect can also be achieved by setting the preserveAspectRatio="" attribute in the SVG itself.

    How do object-fit and object-position work?

    You can successfully apply object-fit to any replaced element, for example:

    img {
      height: 100px;
      width: 100px;
      object-fit: contain;
    }

    The five possible values of object-fit are as follows:

    1. contain: The content (e.g. the image) will be resized so that it is fully displayed with intrinsic aspect ratio preserved, but still fits inside the dimensions set for the element.
    2. fill: The content will expand to exactly fill the dimensions set for the element, even if this does break its aspect ratio.
    3. cover: Preserves the aspect ratio of the content, but alters the width and height so that the content completely covers the element. The smaller of the two is made to fit the element exactly, and the larger overflows the element and is cropped.
    4. none: Completely ignores any height or weight set on the element, and just uses the replaced element content’s intrinsic dimensions.
    5. scale-down: The content is sized as if none or contain were specified, whichever would result in a smaller replaced element size.

    object-position works in exactly the same way as background-position does for background images; for example:

    img {
      height: 100px;
      width: 100px;
      object-fit: contain;
      object-position: top 70px;
    }

    Percentages work, but they’re actually resolved against the excess available space — the difference between the element’s width & the replaced content’s final rendered width. So object-position: 50% 50% (the default value) will always exactly center the replaced element. Furthermore, object-position: 0% 0% always means align with top-left corner, object-position: 100% 100% *always* means align with bottom-right corner, etc.

    The keywords top, center, right, etc. are really just handy aliases for 0%, 50%, 100%, etc.

    Note: You can see some object position examples in our basic example page.

    The effects of the different object-fit values

    The following code examples show the effects of the different object-fit values.

    Letterboxing images with object-fit: contain

    Sometimes referred to as letter-boxing, there are times when you will want to preserve the aspect ratio of the images on a page, but get them to fit inside the same area. For example, you might have a content management system that allows you to upload products on an e-commerce site or images for an image gallery, with lots of different content authors. They may upload images in roughly the right size, but the dimensions are not always exact, and you want to fit each image into the same amount of space.

    Having images with the aspect ratio shifted usually looks horrible, so you can letterbox them instead with object-fit: contain (object-fit: contain example):

    img {
      width: 480px;
      height: 320px;
      background: black;
    }
     
    .contain {
    	object-fit: contain;
    }

    Cropping images with object-fit:cover

    A different solution is to maintain aspect ratio, but crop each image to the same size so it completely envelops the <img> element, with any overflow being hidden. This can be done easily with object-fit:cover (object-fit: cover example):

    .cover {
      object-fit: cover;
    }

    Overriding a video’s aspect ratio with object-fit: fill

    Going in the opposite direction, it is also possible to take a video and force it to change aspect ratio. Maybe some of your content editor’s videos have a broken aspect ratio, and you want to fix them all on the fly, in one easy fell swoop?

    Take the following video image:

    a video with a broken aspect ratioIf we embedded it into a page with this:

    <video controls="controls" src="windowsill.webm"
        width="426" height="240">
      …
    </video>

    It would look terrible: the video would appear letter-boxed, since the <video> element always tries to maintain the source file’s intrinsic aspect ratio. We could fix this by applying object-fit: fill (object-fit: fill example):

    .fill {
      object-fit: fill;
    }

    This overrides the video’s intrinsic aspect ratio, forcing it to completely fill the <video> element so it displays correctly.

    Interesting transition effects

    Combining object-fit and object-position with CSS transitions can lead to some pretty interesting effects for image or video galleries. For example:

    .none {
      width: 200px;
      height: 200px;
     
      overflow: hidden;
      object-fit: none;
      object-position: 25% 50%;
      transition: 1s width, 1s height;
    }
     
    .none:hover, .none:focus {
    	height: 350px;
    	width: 350px;
    }

    Only a small part of the image is shown, and the element grows to reveal more of the image when it is focused/hovered (object-fit: none example).

    This is because by setting object-fit: none on the <img>, we cause the content to completely ignore any width and height set earlier, and spill out of the sides of the element. We then use overflow: hidden to crop anything that spills out. A transition is then used to smoothly increase the size of the <img> element when it’s hovered/focused, which reveals more of the image.

    Gallery example

    To show a slightly more applied usage of object-fit, we have created a gallery example:

    an image gallery showing sixteen pictures in a four by four grid

    an image gallery showing one large image

    The 16 images are loaded via XHR, and inserted into the images as ObjectURLs.

    for(i = 1; i <= thumbs.length ; i++) {
      var requestObj = 'images/pic' + i + '.jpg';
      retrieveImage(requestObj,i-1);
    }
     
    function retrieveImage(requestObj,imageNo) {
      var request = new XMLHttpRequest();
      request.open('GET', requestObj, true);
      request.responseType = 'blob';
     
      request.onload = function() {
        var objectURL = URL.createObjectURL(request.response);
        thumbs[imageNo].setAttribute('src',objectURL);
        thumbs[imageNo].onclick = function() {
          ...
        }
      }
     
      request.send();
    }

    Each image in turn is given an onclick handler so that when clicked the images appear full size, filling the screen (the main image, initially set to display: none; in the CSS is given a class of blowup, which makes it display and fill the whole screen; the main image’s src is then set to the same object URL as the thumb that was clicked).

    thumbs[imageNo].onclick = function() {
      mainImg.setAttribute('src',objectURL);
      mainImg.className = 'blowup';
      for(i = 0; i < thumbs.length; i++) {
        thumbs[i].className = 'thumb darken';
      }
    }

    Clicking a full size image makes it disappear again.

    mainImg.onclick = function() {
      mainImg.className = 'main';
      for(i = 0; i < thumbs.length; i++) {
        thumbs[i].className = 'thumb';
      }
    }

    All the sizing is done with percentages so that the grid remains in proportion whatever the screen size.

    body > div {
      height: 25%;
    }
     
    .thumb {
      float: left;
      width: 25%;
      height: 100%;
      object-fit: cover;
    }

    Note: the thumbnails have all been given tabindex="0" to make them focusable by tabbing (you can make anything appear in the page’s tab order by setting on tabindex="0" on it), and the onclick handler that makes the full size images appear has been doubled up with an onfocus handler to provide basic keyboard accessibility:

    thumbs[imageNo].onfocus = function() {
      mainImg.setAttribute('src',objectURL);
      mainImg.className = 'blowup';
      for(i = 0; i < thumbs.length; i++) {
        thumbs[i].className = 'thumb darken';
      }
    }

    The clever parts come with the usage of object-fit:

    1. The thumbnails: These have object-fit: cover set on them so that all image thumbs will appear at the same size, at the proper aspect ratio, but cropped different amounts. This looks pretty decent, and creates a nice effect when you resize the window.
    2. The main image: This has object-fit: contain and object-position: center set on it, so that it will appear in full, at the correct aspect ratio and as big as it can be.
  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. Open Web Apps feedback: Consolidating our channels

    In August 2014 we announced the opening of a new feedback channel for web apps on UserVoice. It has led to some good discussions and here are a few highlights:

    We would like to sincerely thank those who have provided input and participated in all of the discussions. Unfortunately, after some great initial levels of participation we have since seen usage fall, so at this time we think it is best to discontinue use of openwebapps.uservoice.com. With UserVoice’s handy data exporting services, we’ve made sure we have an archived copy of the ideas posted and interactions that took place on the site.

    Please keep the feedback and feature suggestions coming. It’s essential for us to continue to hear from developers like you. We’d simply like to redirect feedback back to mailing lists/newsgroups (see this list of IRC channels and mailing lists for some Mozilla app-specific channels), specifiction.org/ which aims to be a forum for building web standards, and Bugzilla instances like Mozilla’s.

    Note: The Firefox Developer Tools feedback channel hosted on UserVoice (ffdevtools.uservoice.com) is very active and is most definitely remaining open!