1. an overview of TraceMonkey

    This post was written by David Mandelin who works on Mozilla’s JavaScript team.

    Firefox 3.5 has a new JavaScript engine, TraceMonkey, that runs many JavaScript programs 3-4x faster than Firefox 3, speeding up existing web apps and enabling new ones. This article gives a peek under the hood at the major parts of TraceMonkey and how they speed up JS. This will also explain what kinds of programs get the best speedup from TraceMonkey and what kinds of things you can do to get your program to run faster.

    Why it’s hard to run JS fast: dynamic typing

    High-level dynamic languages such as JavaScript and Python make programming more productive, but they have always been slow compared to statically typed languages like Java or C. A typical rule of thumb was that a JS program might be 10x slower than an equivalent Java program.

    There are two main reasons JS and other dynamic scripting languages usually run slower than Java or C. The first reason is that in dynamic languages it is generally not possible to determine the types of values ahead of time. Because of this, the language must store all values in a generic format and process values using generic operations.

    In Java, by contrast, the programmer declares types for variables and methods, so the compiler can determine the types of values ahead of time. The compiler can then generate code that uses specialized formats and operations that run much faster than generic operations. I will call these type-specialized operations.

    The second main reason that dynamic languages run slower is that scripting languages are usually implemented with interpreters, while statically typed languages are compiled to native code. Interpreters are easier to create, but they incur extra runtime overhead for tracking their internal state. Languages like Java compile to machine language, which requires almost no state tracking overhead.

    Let’s make this concrete with a picture. Here are the slowdowns in picture form for a simple numeric add operation: a + b, where a and b are integers. For now, ignore the rightmost bar and focus on the comparison of the Firefox 3 JavaScript interpreter vs. a Java JIT. Each column shows the steps that have to be done to complete the add operation in each programming language. Time goes downward, and the height of each box is proportional to the time it takes to finish the steps in the box.

    time diagram of add operation

    In the middle, Java simply runs one machine language add instruction, which runs in time T (one processor cycle). Because the Java compiler knows that the operands are standard machine integers, it can use a standard integer add machine language instruction. That’s it.

    On the left, SpiderMonkey (the JS interpreter in FF3) takes about 40 times as long. The brown boxes are interpreter overhead: the interpreter must read the add operation and jump to the interpreter’s code for a generic add. The orange boxes represent extra work that has to be done because the interpreter doesn’t know the operand types. The interpreter has to unpack the generic representations of a and i, figure out their types, select the specific addition operation, convert the values to the right types, and at the end, convert the result back to a generic format.

    The diagram shows that using an interpreter instead of a compiler is slowing things down a little bit, but not having type information is slowing things down a lot. If we want JS to run more than a little faster than in FF3, by Amdahl’s law, we need to do something about types.

    Getting types by tracing

    Our goal in TraceMonkey is to compile type-specialized code. To do that, TraceMonkey needs to know the types of variables. But JavaScript doesn’t have type declarations, and we also said that it’s practically impossible for a JS engine to figure out the types ahead of time. So if we want to just compile everything ahead of time, we’re stuck.

    So let’s turn the problem around. If we let the program run for a bit in an interpreter, the engine can directly observe the types of values. Then, the engine can use those types to compile fast type-specialized code. Finally, the engine can start running the type-specialized code, and it will run much faster.

    There are a few key details about this idea. First, when the program runs, even if there are many if statements and other branches, the program always goes only one way. So the engine doesn’t get to observe types for a whole method — the engine observes types through the paths, which we call traces, that the program actually takes. Thus, while standard compilers compile methods, TraceMonkey compiles traces. One side benefit of trace-at-a-time compilation is that function calls that happen on a trace are inlined, making traced function calls very fast.

    Second, compiling type-specialized code takes time. If a piece of code is going to run only one or a few times, which is common with web code, it can easily take more time to compile and run the code than it would take to simply run the code in an interpreter. So it only pays to compile hot code (code that is executed many times). In TraceMonkey, we arrange this by tracing only loops. TraceMonkey initially runs everything in the interpreter, and starts recording traces through a loop once it gets hot (runs more than a few times).

    Tracing only hot loops has an important consequence: code that runs only a few times won’t speed up in TraceMonkey. Note that this usually doesn’t matter in practice, because code that runs only a few times usually runs too fast to be noticeable. Another consequence is that paths through a loop that are not taken at all never need to be compiled, saving compile time.

    Finally, above we said that TraceMonkey figures out the types of values by observing execution, but as we all know, past performance does not guarantee future results: the types might be different the next time the code is run, or the 500th next time. And if we try to run code that was compiled for numbers when the values are actually strings, very bad things will happen. So TraceMonkey must insert type checks into the compiled code. If a check doesn’t pass, TraceMonkey must leave the current trace and compile a new trace for the new types. This means that code with many branches or type changes tends to run a little slower in TraceMonkey, because it takes time to compile the extra traces and jump from one to another.

    TraceMonkey in action

    Now, we’ll show tracing in action by example on this sample program, which adds the first N whole numbers to a starting value:

     function addTo(a, n) {
       for (var i = 0; i < n; ++i)
         a = a + i;
       return a;
     }
     
     var t0 = new Date();
     var n = addTo(0, 10000000);
     print(n);
     print(new Date() - t0);

    TraceMonkey always starts running the program in the interpreter. Every time the program starts a loop iteration, TraceMonkey briefly enters monitoring mode to increment a counter for that loop. In FF3.5, when the counter reaches 2, the loop is considered hot and it’s time to trace.

    Now TraceMonkey continues running in the interpreter but starts recording a trace as the code runs. The trace is simply the code that runs up to the end of the loop, along with the types used. The types are determined by looking at the actual values. In our example, the loop executes this sequence of JavaScript statements, which becomes our trace:

        a = a + i;    // a is an integer number (0 before, 1 after)
        ++i;          // i is an integer number (1 before, 2 after)
        if (!(i < n)) // n is an integer number (10000000)
          break;

    That’s what the trace looks like in a JavaScript-like notation. But TraceMonkey needs more information in order to compile the trace. The real trace looks more like this:

      trace_1_start:
        ++i;            // i is an integer number (0 before, 1 after)
        temp = a + i;   // a is an integer number (1 before, 2 after)
        if (lastOperationOverflowed())
          exit_trace(OVERFLOWED);
        a = temp;
        if (!(i < n))   // n is an integer number (10000000)
          exit_trace(BRANCHED);
        goto trace_1_start;

    This trace represents a loop, and it should be compiled as a loop, so we express that directly using a goto. Also, integer addition can overflow, which requires special handling (for example, redoing with floating-point addition), which in turn requires exiting the trace. So the trace must include an overflow check. Finally, the trace exits in the same way if the loop condition is false. The exit codes tell TraceMonkey why the trace was exited, so that TraceMonkey can decide what to do next (such as whether to redo the add or exit the loop). Note that traces are recorded in a special internal format that is never exposed to the programmer — the notation used above is just for expository purposes.

    After recording, the trace is ready to be compiled to type-specialized machine code. This compilation is performed by a tiny JIT compiler (named, appropriately enough, nanojit) and the results are stored in memory, ready to be executed by the CPU.

    The next time the interpreter passes the loop header, TraceMonkey will start executing the compiled trace. The program now runs very fast.

    On iteration 65537, the integer addition will overflow. (2147450880 + 65537 = 2147516417, which is greater than 2^31-1 = 2147483647, the largest signed 32-bit integer.) At this point, the trace exits with an OVERFLOWED code. Seeing this, TraceMonkey will return to interpreter mode and redo the addition. Because the interpreter does everything generically, the addition overflow is handled and everything works as normal. TraceMonkey will also start monitoring this exit point, and if the overflow exit point ever becomes hot, a new trace will be started from that point.

    But in this particular program, what happens instead is that the program passes the loop header again. TraceMonkey knows it has a trace for this point, but TraceMonkey also knows it can’t use that trace because that trace was for integer values, but a is now in a floating-point format. So TraceMonkey records a new trace:

      trace_2_start:
        ++i;            // i is an integer number
        a = a + i;      // a is a floating-point number
        if (!(i < n))   // n is an integer number (10000000)
          exit_trace(BRANCHED);
        goto trace_2_start;

    TraceMonkey then compiles the new trace, and on the next loop iteration, starts executing it. In this way, TraceMonkey keeps the JavaScript running as machine code, even when types change. Eventually the trace will exit with a BRANCHED code. At this point, TraceMonkey will return to the interpreter, which takes over and finishes running the program.

    Here are the run times for this program on my laptop (2.2GHz MacBook Pro):

    System Run Time (ms)
    SpiderMonkey (FF3) 990
    TraceMonkey (FF3.5) 45
    Java (using int) 25
    Java (using double) 74
    C (using int) 5
    C (using double) 15

    This program gets a huge 22x speedup from tracing and runs about as fast as Java! Functions that do simple arithmetic inside loops usually get big speedups from tracing. Many of the bit operation and math SunSpider benchmarks, such bitops-3bit-bits-in-byte, ctrypto-sha1, and math-spectral-norm get 6x-22x speedups.

    Functions that use more complex operations, such as object manipulation, get a smaller speedup, usually 2-5x. This follows mathematically from Amdahl’s law and the fact that complex operations take longer. Looking back at the time diagram, consider a more complex operation that takes time 30T for the green part. The orange and brown parts will still be about 30T together, so eliminating them gives a 2x speedup. The SunSpider benchmark string-fasta is an example of this kind of program: most of the time is taken by string operations that have a relatively long time for the green box.

    Here is a version of our example program you can try in the browser:

    Numerical result:

    Run time:

    Average run time:

    Understanding and fixing performance problems

    Our goal is to make TraceMonkey reliably fast enough that you can write your code in the way that best expresses your ideas, without worrying about performance. If TraceMonkey isn’t speeding up your program, we hope you’ll report it as a bug so we can improve the engine. That said, of course, you may need your program to run faster in today’s FF3.5. In this section, we’ll explain some tools and techniques for fixing performance of a program that doesn’t get a good (2x or more) speedup with the tracing JIT enabled. (You can disable the jit by going to about:config and setting the pref javascript.options.jit.content to false.)

    The first step is understanding the cause of the problem. The most common cause is a trace abort, which simply means that TraceMonkey was unable to finish recording a trace, and gave up. The usual result is that the loop containing the abort will run in the interpreter, so you won’t get a speedup on that loop. Sometimes, one path through the loop is traced, but there is an abort on another path, which will cause TraceMonkey to switch back and forth between interpreting and running native code. This can leave you with a reduced speedup, no speedup, or even a slowdown: switching modes takes time, so rapid switching can lead to poor performance.

    With a debug build of the browser or a JS shell (which I build myself – we don’t publish these builds) you can tell TraceMonkey to print information about aborts by setting the TMFLAGS environment variable. I usually do it like this:

    TMFLAGS=minimal,abort
    dist/MinefieldDebug.app/Contents/MacOS/firefox
    

    The minimal option prints out all the points where recording starts and where recording successfully finishes. This gives a basic idea of what the tracer is trying to do. The abort option prints out all the points where recording was aborted due to an unsupported construct. (Setting TMFLAGS=help will print the list of other TMFLAGS options and then exit.)

    (Note also that TMFLAGS is the new way to print the debug information. If you are using a debug build of the FF3.5 release, the environment variable setting is TRACEMONKEY=abort.)

    Here’s an example program that doesn’t get much of a speedup in TraceMonkey.

    function runExample2() {
      var t0 = new Date;
     
      var sum = 0;
      for (var i = 0; i < 100000; ++i) {
        sum += i;
      }
     
      var prod = 1;
      for (var i = 1; i < 100000; ++i) {
        eval("prod *= i");
      }
      var dt = new Date - t0;
      document.getElementById(example2_time').innerHTML = dt + ' ms';
    }

    Run time:

    If we set TMFLAGS=minimal,abort, we’ll get this:

    Recording starting from ab.js:5@23
    recording completed at  ab.js:5@23 via closeLoop
     
    Recording starting from ab.js:5@23
    recording completed at  ab.js:5@23 via closeLoop
     
    Recording starting from ab.js:10@63
    Abort recording of tree ab.js:10@63 at ab.js:11@70: eval.
     
    Recording starting from ab.js:10@63
    Abort recording of tree ab.js:10@63 at ab.js:11@70: eval.
     
    Recording starting from ab.js:10@63
    Abort recording of tree ab.js:10@63 at ab.js:11@70: eval.

    The first two pairs of lines show that the first loop, starting at line 5, traced fine. The following lines showed that TraceMonkey started tracing the loop on line 10, but failed each time because of an eval.

    An important note about this debug output is that you will typically see some messages referring to inner trees growing, stabilizing, and so on. These really aren’t problems: they usually just indicate a delay in finishing tracing a loop because of the way TraceMonkey links inner and outer loops. And in fact, if you look further down the output after such aborts, you will usually see that the loops eventually do trace.

    Otherwise, aborts are mainly caused by JavaScript constructs that are not yet supported by tracing. The trace recording process is easier to implement for a basic operation like + than it is for an advanced feature like arguments. We didn’t have time to do robust, secure tracing of every last JavaScript feature in time for the FF3.5 release, so some of the more advanced ones, like arguments, aren’t traced in FF3.5.0. Other advanced features that are not traced include getters and setters, with, and eval. There is partial support for closures, depending on exactly how they are used. Refactoring to avoid these constructs can help performance.

    Two particularly important JavaScript features that are not traced are:

    • Recursion. TraceMonkey doesn’t see repetition that occurs through recursion as a loop, so it doesn’t try to trace it. Refactoring to use explicit for or while loops will generally give better performance.
    • Getting or setting a DOM property. (DOM method calls are fine.) Avoiding these constructs is generally impossible, but refactoring the code to move DOM property access out of hot loops and performance-critical segments should help.

    We are actively working on tracing all the features named above. For example, support for tracing arguments is already available in nightly builds.

    Here is the slow example program refactored to avoid eval. Of course, I could have simply done the multiplication inline. Instead, I used a function created by eval because that’s a more general way of refactoring an eval. Note that the eval still can’t be traced, but it only runs once so it doesn’t matter.

    function runExample3() {
      var t0 = new Date;
     
      var sum = 0;
      for (var i = 0; i < 100000; ++i) {
        sum += i;
      }
     
      var prod = 1;
      var mul = eval("(function(i) { return prod * i; })");
     
      for (var i = 1; i < 100000; ++i) {
        prod = mul(i);
      }
      var dt = new Date - t0;
      document.getElementById('example3_time').innerHTML = dt + ' ms';
    }

    Run time:

    There are a few more esoteric situations that can also hurt tracing performance. One of them is trace explosion, which happens when a loop has many paths through it. Consider a loop with 10 if statements in a row: the loop has 1024 paths, potentially causing 1024 traces to be recorded. That would use up too much memory, so TraceMonkey caps each loop at 32 traces. If the loop has fewer than 32 hot traces, it will perform well. But if each path occurs with equal frequency, then only 3% of the paths are traced, and performance will suffer.

    This kind of problem is best analyzed with TraceVis, which creates visualizations of TraceMonkey performance. Currently, the build system only supports enabling TraceVis for shell builds, but the basic system can also run in the browser, and there is ongoing work to enable TraceVis in a convenient form in the browser.

    The blog post on TraceVis is currently the most detailed explanation of what the diagrams mean and how to use them to diagnose performance problems. The post also contains a detailed analysis of a diagram that is helpful in understanding how TraceMonkey works in general.

    Comparative JITerature

    Here I will give a few comparisons to other JavaScript JIT designs. I’ll focus more on hypothetical designs than competing engines, because I don’t know details about them — I’ve read the release information and skimmed a few bits of code. Another big caveat is that real-world performance depends at least as much on engineering details as it does on engine architecture.

    One design option could be a called a per-method non-specializing JIT. By this, I mean a JIT compiler that compiles a method at a time and generates generic code, just like what the interpreter does. Thus, the brown boxes from our diagrams are cut out. This kind of JIT doesn’t need to take time to record and compile traces, but it also does not type-specialize, so the orange boxes remain. Such an engine can still be made pretty fast by carefully designing and optimizing the orange box code. But the orange box can’t be completely eliminated in this design, so the maximum performance on numeric programs won’t be as good as a type-specializing engine.

    As far as I can tell, as of this writing Nitro and V8 are both lightweight non-specializing JITs. (I’m told that V8 does try to guess a few types by looking at the source code (such as guessing that a is an integer in a >> 2) in order to do a bit of type specialization.) It seem that TraceMonkey is generally faster on numeric benchmarks, as predicted above. But TraceMonkey suffers a bit on benchmarks that use more objects, because our object operations and memory management haven’t been optimized as heavily.

    A further development of the basic JIT is the per-method type-specializing JIT. This kind of a JIT tries to type-specialize a method based on the argument types the method is called with. Like TraceMonkey, this requires some runtime observation: the basic design checks the argument types each time a method is called, and if those types have not been seen before, compiles a new version of the method. Also like TraceMonkey, this design can heavily specialize code and remove both the brown and orange boxes.

    I’m not aware that anyone has deployed a per-method type-specializing JIT for JavaScript, but I wouldn’t be surprised if people are working on it.

    The main disadvantage of a per-method type-specializing JIT compared to a tracing JIT is that the basic per-method JIT only directly observes the input types to a method. It must try to infer types for variables inside the method algorithmically, which is difficult for JavaScript, especially if the method reads object properties. Thus, I would expect that a per-method type-specializing JIT would have to use generic operations for some parts of the method. The main advantage of the per-method design is that the method needs to be compiled exactly once per set of input types, so it’s not vulnerable to trace explosion. In turn, I think a per-method JIT would tend to be faster on methods that have many paths, and a tracing JIT would tend to be faster on highly type-specializable methods, especially if the method also reads a lot of values from properties.

    Conclusion

    By now, hopefully you have a good idea of what makes JavaScript engines fast, how TraceMonkey works, and how to analyze and fix some performance issues that may occur running JavaScript under TraceMonkey. Please report bugs if you run into any significant performance problems. Bug reports are also a good place for us to give additional tuning advice. Finally, we’re trying to improve constantly, so check out nightly TraceMonkey builds if you’re into the bleeding edge.

  2. cross-site xmlhttprequest with CORS

    XMLHttpRequest is used within many Ajax libraries, but till the release of browsers such as Firefox 3.5 and Safari 4 has only been usable within the framework of the same-origin policy for JavaScript. This meant that a web application using XMLHttpRequest could only make HTTP requests to the domain it was loaded from, and not to other domains. Developers expressed the desire to safely evolve capabilities such as XMLHttpRequest to make cross-site requests, for better, safer mash-ups within web applications. The Cross-Origin Resource Sharing (CORS) specification consists of a simple header exchange between client-and-server, and is used by IE8′s proprietary XDomainRequest object as well as by XMLHttpRequest in browsers such as Firefox 3.5 and Safari 4 to make cross-site requests. These browsers make it possible to make asynchronous HTTP calls within script to other domains, provided the resources being retrieved are returned with the appropriate CORS headers.

    A Quick Overview of CORS

    Firefox 3.5 and Safari 4 implement the CORS specification, using XMLHttpRequest as an “API container” that sends and receives the appropriate headers on behalf of the web developer, thus allowing cross-site requests. IE8 implements part of the CORS specification, using XDomainRequest as a similar “API container” for CORS, enabling simple cross-site GET and POST requests. Notably, these browsers send the ORIGIN header, which provides the scheme (http:// or https://) and the domain of the page that is making the cross-site request. Server developers have to ensure that they send the right headers back, notably the Access-Control-Allow-Origin header for the ORIGIN in question (or ” * ” for all domains, if the resource is public) .

    The CORS standard works by adding new HTTP headers that allow servers to serve resources to permitted origin domains. Browsers support these headers and enforce the restrictions they establish. Additionally, for HTTP request methods that can cause side-effects on user data (in particular, for HTTP methods other than GET, or for POST usage with certain MIME types), the specification mandates that browsers “preflight” the request, soliciting supported methods from the server with an HTTP OPTIONS request header, and then, upon “approval” from the server, sending the actual request with the actual HTTP request method. Servers can also notify clients whether “credentials” (including Cookies and HTTP Authentication data) should be sent with requests.

    Capability Detection

    XMLHttpRequest can make cross-site requests in Firefox 3.5 and in Safari 4; cross-site requests in previous versions of these browsers will fail. It is always possible to try to initiate the cross-site request first, and if it fails, to conclude that the browser in question cannot handle cross-site requests from XMLHttpRequest (based on handling failure conditions or exceptions, e.g. not getting a 200 status code back). In Firefox 3.5 and Safari 4, a cross-site XMLHttpRequest will not successfully obtain the resource if the server doesn’t provide the appropriate CORS headers (notably the Access-Control-Allow-Origin header) back with the resource, although the request will go through. And in older browsers, an attempt to make a cross-site XMLHttpRequest will simply fail (a request won’t be sent at all).

    Both Safari 4 and Firefox 3.5 provide the withCredentials property on XMLHttpRequest in keeping with the emerging XMLHttpRequest Level 2 specification, and this can be used to detect an XMLHttpRequest object that implements CORS (and thus allows cross-site requests). This allows for a convenient “object detection” mechanism:

    if (XMLHttpRequest)
    {
        var request = new XMLHttpRequest();
        if (request.withCredentials !== undefined)
        {
          // make cross-site requests
        }
    }

    Alternatively, you can also use the “in” operator:

    if("withCredentials" in request)
    {
      // make cross-site requests
    }

    Thus, the withCredentials property can be used in the context of capability detection. We’ll discuss the use of “withCredentials” as a means to send Cookies and HTTP-Auth data to sites later on in this article.

    “Simple” Requests using GET or POST

    IE8, Safari 4, and Firefox 3.5 allow simple GET and POST cross-site requests. “Simple” requests don’t set custom headers, and the request body only uses plain text (namely, the text/plain Content-Type).

    Let us assume the following code snippet is served from a page on site http://foo.example and is making a call to http://bar.other:

     
    var url = "http://bar.other/publicNotaries/"
    if(XMLHttpRequest)
    {
      var request = new XMLHttpRequest();
      if("withCredentials" in request)
      {
       // Firefox 3.5 and Safari 4
       request.open('GET', url, true);
       request.onreadystatechange = handler;
       request.send();
      }
      else if (XDomainRequest)
      {
       // IE8
       var xdr = new XDomainRequest();
       xdr.open("get", url);
       xdr.send();
     
       // handle XDR responses -- not shown here :-)
      }
     
     // This version of XHR does not support CORS  
     // Handle accordingly
    }

    Firefox 3.5, IE8, and Safari 4 take care of sending and receiving the right headers. Here is the Simple Request example. It is also instructive to look at the headers sent back by the server. Notably, amongst the other request headers, the browser would send the following in order to enable the simple request above:

    GET /publicNotaries/ HTTP/1.1
    Referer: http://foo.example/notary-mashup/
    Origin: http://foo.example

    Note the use of the “Origin” HTTP header that is part of the CORS specification.

    And, amongst the other response headers, the server at http://bar.other would include:

    Access-Control-Allow-Origin: http://foo.example
    Content-Type: application/xml
    ......

    A more complete treatment of CORS and XMLHttpRequest can be found here, on the Mozilla Developer Wiki.

    “Preflighted” Request

    The CORS specification mandates that requests that use methods other than POST or GET, or that use custom headers, or request bodies other than text/plain, are preflighted. A preflighted request first sends the OPTIONS header to the resource on the other domain, to check and see if the actual request is safe to send. This capability is currently not supported by IE8′s XDomainRequest object, but is supported by Firefox 3.5 and Safari 4 with XMLHttpRequest. The web developer does not need to worry about the mechanics of preflighting, since the implementation handles that.

    The code snippet below shows code from a web page on http://foo.example calling a resource on http://bar.other. For simplicity, we leave out the section on object and capability detection, since we’ve covered that already:

    var invocation = new XMLHttpRequest();
    var url = 'http://bar.other/resources/post-here/';
    var body = '
    Arun';
    function callOtherDomain(){
    if(invocation)
    {
        invocation.open('POST', url, true);
        invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
        invocation.setRequestHeader('Content-Type', 'application/xml');
        invocation.onreadystatechange = handler;
        invocation.send(body);
    }

    You can see this example in action here. Looking at the header exchange between client and server is really instructive. A more detailed treatment of this can be found on the Mozilla Developer Wiki.

    In this case, before Firefox 3.5 sends the request, it first uses the OPTIONS header:

    OPTIONS /resources/post-here/ HTTP/1.1
    Origin: http://foo.example
    Access-Control-Request-Method: POST
    Access-Control-Request-Headers: X-PINGOTHER

    Then, amongst the other response headers, the server responds with:

    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: http://arunranga.com
    Access-Control-Allow-Methods: POST, GET, OPTIONS
    Access-Control-Allow-Headers: X-PINGOTHER
    Access-Control-Max-Age: 1728000

    At which point, the actual response is sent:

    POST /resources/post-here/ HTTP/1.1
    ...
    Content-Type: application/xml; charset=UTF-8
    X-PINGOTHER: pingpong
    ...

    Credentialed Requests

    By default, “credentials” such as Cookies and HTTP Auth information are not sent in cross-site requests using XMLHttpRequest. In order to send them, you have to set the withCredentials property of the XMLHttpRequest object. This is a new property introduced in Firefox 3.5 and Safari 4. IE8′s XDomainRequest object does not have this capability.

    Again, let us assume some JavaScript on a page on http://foo.example wishes to call a resource on http://bar.other and send Cookies with the request, such that the response is cognizant of Cookies the user may have acquired.

    var request = new XMLHttpRequest();
    var url = 'http://bar.other/resources/credentialed-content/';
    function callOtherDomain(){
      if(request)
      {
       request.open('GET', url, true);
       request.withCredentials = "true";
       request.onreadystatechange = handler;
       request.send();
      }

    Note that withCredentials is false (and NOT set) by default. The header exchange is similar to the case of of a simple GET request, with the exception that now an HTTP Cookie header is sent with the request header. You can see this sample in action here.

    A Note on Security

    In general, data requested from a remote site should be treated as untrusted. Executing JavaScript code retrieved from a third-party site without first determining its validity is NOT recommended. Server administrators should be careful about leaking private data, and should judiciously determine that resources can be called in a cross-site manner.

    References

  3. HTML5 drag and drop in Firefox 3.5

    This post is from Les Orchard, who works on Mozilla’s web development team.

    Introduction

    Drag and drop is one of the most fundamental interactions afforded by graphical user interfaces. In one gesture, it allows users to pair the selection of an object with the execution of an action, often including a second object in the operation. It’s a simple yet powerful UI concept used to support copying, list reordering, deletion (ala the Trash / Recycle Bin), and even the creation of link relationships.

    Since it’s so fundamental, offering drag and drop in web applications has been a no-brainer ever since browsers first offered mouse events in DHTML. But, although mousedown, mousemove, and mouseup made it possible, the implementation has been limited to the bounds of the browser window. Additionally, since these events refer only to the object being dragged, there’s a challenge to find the subject of the drop when the interaction is completed.

    Of course, that doesn’t prevent most modern JavaScript frameworks from abstracting away most of the problems and throwing in some flourishes while they’re at it. But, wouldn’t it be nice if browsers offered first-class support for drag and drop, and maybe even extended it beyond the window sandbox?

    As it turns out, this very wish is answered by the HTML 5 specification section on new drag-and-drop events, and Firefox 3.5 includes an implementation of those events.

    If you want to jump straight to the code, I’ve put together some simple demos of the new events.

    I’ve even scratched an itch of my own and built the beginnings of an outline editor, where every draggable element is also a drop target—of which there could be dozens to hundreds in a complex document, something that gave me some minor hair-tearing moments in the past while trying to make do with plain old mouse events.

    And, all the above can be downloaded or cloned from a GitHub repository I’ve created expecially for this article.

    The New Drag and Drop Events

    So, with no further ado, here are the new drag and drop events, in roughly the order you might expect to see them fired:

    dragstart
    A drag has been initiated, with the dragged element as the event target.
    drag
    The mouse has moved, with the dragged element as the event target.
    dragenter
    The dragged element has been moved into a drop listener, with the drop listener element as the event target.
    dragover
    The dragged element has been moved over a drop listener, with the drop listener element as the event target. Since the default behavior is to cancel drops, returning false or calling preventDefault() in the event handler indicates that a drop is allowed here.
    dragleave
    The dragged element has been moved out of a drop listener, with the drop listener element as the event target.
    drop
    The dragged element has been successfully dropped on a drop listener, with the drop listener element as the event target.
    dragend
    A drag has been ended, successfully or not, with the dragged element as the event target.

    Like the mouse events of yore, listeners can be attached to elements using addEventListener() directly or by way of your favorite JS library.

    Consider the following example using jQuery, also available as a live demo:

        <div id="newschool">
            <div class="dragme">Drag me!</div>
            <div class="drophere">Drop here!</div>
        </div>
     
        <script type="text/javascript">
            $(document).ready(function() {
                $('#newschool .dragme')
                    .attr('draggable', 'true')
                    .bind('dragstart', function(ev) {
                        var dt = ev.originalEvent.dataTransfer;
                        dt.setData("Text", "Dropped in zone!");
                        return true;
                    })
                    .bind('dragend', function(ev) {
                        return false;
                    });
                $('#newschool .drophere')
                    .bind('dragenter', function(ev) {
                        $(ev.target).addClass('dragover');
                        return false;
                    })
                    .bind('dragleave', function(ev) {
                        $(ev.target).removeClass('dragover');
                        return false;
                    })
                    .bind('dragover', function(ev) {
                        return false;
                    })
                    .bind('drop', function(ev) {
                        var dt = ev.originalEvent.dataTransfer;
                        alert(dt.getData('Text'));
                        return false;
                    });
            });
        </script>

    Thanks to the new events and jQuery, this example is both short and simple—but it packs in a lot of functionality, as the rest of this article will explain.

    Before moving on, there are at least three things about the above code that are worth mentioning:

    • Drop targets are enabled by virtue of having listeners for drop events. But, per the HTML 5 spec, draggable elements need an attribute of draggable="true", set either in markup or in JavaScript.

      Thus, $('#newschool .dragme').attr('draggable', 'true').

    • The original DOM event (as opposed to jQuery’s event wrapper) offers a property called dataTransfer. Beyond just manipulating elements, the new drag and drop events accomodate the transmission of user-definable data during the course of the interaction.
    • Since these are first-class events, you can apply the technique of Event Delegation.

      What’s that? Well, imagine you have a list of 1000 list items—as part of a deeply-nested outline document, for instance. Rather than needing to attach listeners or otherwise fiddle with all 1000 items, simply attach a listener to the parent node (eg. the <ul> element) and all events from the children will propagate up to the single parent listener. As a bonus, all new child elements added after page load will enjoy the same benefits.

      Check out this demo, and the associated JS code to see more about these events and Event Delegation.

    Using dataTransfer

    As mentioned in the last section, the new drag and drop events let you send data along with a dragged element. But, it’s even better than that: Your drop targets can receive data transferred by content objects dragged into the window from other browser windows, and even other applications.

    Since the example is a bit longer, check out the live demo and associated code to get an idea of what’s possible with dataTransfer.

    In a nutshell, the stars of this show are the setData() and getData() methods of the dataTransfer property exposed by the Event object.

    The setData() method is typically called in the dragstart listener, loading dataTransfer up with one or more strings of content with associated recommended content types.

    For illustration, here’s a quick snippet from the example code:

        var dt = ev.originalEvent.dataTransfer;    
        dt.setData('text/plain', $('#logo').parent().text());
        dt.setData('text/html', $('#logo').parent().html());
        dt.setData('text/uri-list', $('#logo')[0].src);

    On the other end, getData() allows you to query for content by type (eg. text/html followed by text/plain). This, in turn, allows you to decide on acceptable content types at the time of the drop event or even during dragover to offer feedback for unacceptable types during the drag.

    Here’s another example from the receiving end of the example code:

        var dt = ev.originalEvent.dataTransfer;    
        $('.content_url .content').text(dt.getData('text/uri-list'));
        $('.content_text .content').text(dt.getData('text/plain'));
        $('.content_html .content').html(dt.getData('text/html'));

    Where dataTransfer really shines, though, is that it allows your drop targets to receive content from sources outside your defined draggable elements and even from outside the browser altogether. Firefox accepts such drags, and attempts to populate dataTransfer with appropriate content types extracted from the external object.

    Thus, you could select some text in a word processor window and drop it into one of your elements, and at least expect to find it available as text/plain content.

    You can also select content in another browser window, and expect to see text/html appear in your events. Check out the outline editing demo and see what happens when you try dragging various elements (eg. images, tables, and lists) and highlighted content from other windows onto the items there.

    Using Drag Feedback Images

    An important aspect of the drag and drop interaction is a representation of the thing being dragged. By default in Firefox, this is a “ghost” image of the dragged element itself. But, the dataTransfer property of the original Event object exposes the method setDragImage() for use in customizing this representation.

    There’s a live demo of this feature, as well as associated JS code available. The gist, however, is sketched out in these code snippets:

        var dt = ev.originalEvent.dataTransfer;    
     
        dt.setDragImage( $('#feedback_image h2')[0], 0, 0);
     
        dt.setDragImage( $('#logo')[0], 32, 32); 
     
        var canvas = document.createElement("canvas");
        canvas.width = canvas.height = 50;
     
        var ctx = canvas.getContext("2d");
        ctx.lineWidth = 8;
        ctx.moveTo(25,0);
        ctx.lineTo(50, 50);
        ctx.lineTo(0, 50);
        ctx.lineTo(25, 0);
        ctx.stroke();
     
        dt.setDragImage(canvas, 25, 25);

    You can supply a DOM node as the first parameter to setDragImage(), which includes everything from text to images to <canvas> elements. The second two parameters indicate at what left and top offset the mouse should appear in the image while dragging.

    For example, since the #logo image is 64×64, the parameters in the second setDragImage() method places the mouse right in the center of the image. On the other hand, the first call positions the feedback image such that the mouse rests in the upper left corner.

    Using Drop Effects

    As mentioned at the start of this article, the drag and drop interaction has been used to support actions such as copying, moving, and linking. Accordingly, the HTML 5 specification accomodates these operations in the form of the effectAllowed and dropEffect properties exposed by the Event object.

    For a quick fix, check out the a live demo of this feature, as well as the associated JS code.

    The basic idea is that the dragstart event listener can set a value for effectAllowed like so:

        var dt = ev.originalEvent.dataTransfer;
        switch (ev.target.id) {
            case 'effectdrag0': dt.effectAllowed = 'copy'; break;
            case 'effectdrag1': dt.effectAllowed = 'move'; break;
            case 'effectdrag2': dt.effectAllowed = 'link'; break;
            case 'effectdrag3': dt.effectAllowed = 'all'; break;
            case 'effectdrag4': dt.effectAllowed = 'none'; break;
        }

    The choices available for this property include the following:

    none
    no operation is permitted
    copy
    copy only
    move
    move only
    link
    link only
    copyMove
    copy or move only
    copyLink
    copy or link only
    linkMove
    link or move only
    all
    copy, move, or link

    On the other end, the dragover event listener can set the value of the dropEffect property to indicate the expected effect invoked on a successful drop. If the value does not match up with effectAllowed, the drop will be considered cancelled on completion.

    In the a live demo, you should be able to see that only elements with matching effects can be dropped into the appropriate drop zones. This is accomplished with code like the follwoing:

        var dt = ev.originalEvent.dataTransfer;
        switch (ev.target.id) {
            case 'effectdrop0': dt.dropEffect = 'copy'; break;
            case 'effectdrop1': dt.dropEffect = 'move'; break;
            case 'effectdrop2': dt.dropEffect = 'link'; break;
            case 'effectdrop3': dt.dropEffect = 'all'; break;
            case 'effectdrop4': dt.dropEffect = 'none'; break;
        }

    Although the OS itself can provide some feedback, you can also use these properties to update your own visible feedback, both on the dragged element and on the drop zone itself.

    Conclusion

    The new first-class drag and drop events in HTML5 and Firefox make supporting this form of UI interaction simple, concise, and powerful in the browser. But beyond the new simplicity of these events, the ability to transfer content between applications opens brand new avenues for web-based applications and collaboration with desktop software in general.

  4. using web workers: working smarter, not harder

    This article is written by Malte Ubl, who has done a lot of great work with using Web Workers as part of the bespin project.

    In recent years, the user experience of web applications has grown richer and richer. In-browser applications like GMail, Meebo and Bespin give us an impression of how the web will look and feel in the future. One of the key aspects of creating a great user experience is to build applications that are highly responsive. Users hate to wait and they hate those moments where an application seems to work for a while, then stops responding to their input.

    At the core of modern client-side web applications lies the JavaScript programming language. JavaScript and the DOM that it talks to is inherently single-threaded. This means that in JavaScript only one thing can happen at any given time. Even if your computer has 32 cores it will keep only one of those cores busy when it’s doing a long computation.  For example if you calculate the perfect trajectory to get to the moon it won’t be able to render an animation that shows the trajectory at the same time and it won’t be able to react to any user events like clicks or typing on the keyboard while it’s doing that calculation.

    Concurrency

    To maintain responsiveness while performing intense computations concurrency is a part of most modern programming languages. In the past concurrency was often achieved by the use of threads. Threads, however, make it increasingly hard for the programmer to understand the program flow which often leads to very hard to understand bugs and chaotic behavior when different threads manipulate the same data simultaneously.

    Web Workers, which were recommended by the WHATWG, were introduced in Firefox 3.5 to add concurrency to JavaScript applications without also introducing the problems associated with multithreaded programs. Starting a worker is easy – just use the new Worker interface.

    In this example the worker.js file will be loaded and the a new thread will be created to execute that code.

    // Start worker from file "worker.js"
    var worker = new Worker("worker.js");

    Communication between the main UI thread and workers is done by passing messages using the postMessage method. postMessage was added for cross-window communication in Firefox 3. To send a message from the worker back to the page, you just post a message:

    // Send a message back to the main UI thread
    postMessage("Hello Page!");

    To catch the message from the worker, you define an “onmessage” callback on the worker object. Here we just alert the event data that is passed to the callback function. In this case, “event.data” contains the “Hello Page!” string that was sent above.

    worker.onmessage = function (event) {
      alert(event.data);
      // Send a message to the worker
      worker.postMessage("Hello Worker");
    }

    To send a message to the worker we call the postMessage method on the worker object. To receive these messages inside the worker, simply define an onmessage function that will be called every time a message is posted to the worker.

    Error Handling

    There are two levels at which you can recover from runtime errors that occur in a worker. First, you can define an onerror function within the worker. Second, you can handle errors from the outside the worker by attaching an onerror handler on to the worker object:

    worker.onerror = function (event) {
      alert(event.message);
      event.preventDefault();
    }

    The event.preventDefault() method prevents the default action, which would be to display the error to the user or at least show it in the error console. Here we alert the error message instead.

    Shared Nothing

    Workers share absolutely no state with the page they are associated with or with any other workers; the only way they can interact at all is through postMessage. Workers also have no access to the DOM, so they can not directly manipulate the web page. There is thus no risk of problems with data integrity when multiple workers want to manipulate the same data at once.

    A standard setup that is using workers would consist of a page JavaScript component that is listening for user events. When an event occurs that triggers an intensive calculation a message is sent to the worker which then starts the computation. The script on the page, however, can terminate immediately and listen for more user events. As soon as the worker is done, it sends a return message to the page which can then, for example, display the result.


    The unresponsive script warning that is being displayed by browsers when a script is taking a long time to execute is a thing of the past when using web workers.

    The Fibonacci Example

    Next is an example of a worker that calculates the Fibonacci numbers from 0 to 99 in the background. Actually, because calculating Fibonacci numbers using this very inefficient method can take a lot of time for larger numbers (as in greater than something like 30) the script might never finish on your computer (or crash because it blows out the stack), but when doing it in a worker this has no effect on the responsiveness of the main web page. So you can still draw a complex animation to make the waiting time for the next number a little more fun.

    This HTML page contains a script that starts a worker from the file “fib-worker.js”. Messages from the worker are displayed on the browser’s console using console.log.

    <!DOCTYPE html>
    <html>
        <head>
          <title>Web Worker API Demo</title>
          <script type="text/javascript">
            var worker = new Worker("fib-worker.js");
            worker.onmessage = function (event) {
              console.log(event.data.index +" -> " + event.data.value)
            }
          </script>  
        </head>
        <body>
        </body>
    </html>

    The JavaScript file that implements the worker contains a loop that calculates Fibonacci numbers and sends the result to the page.

    // File fib-worker.js
    function fib(n) {
       return n < 2 ? n : fib(n-1) + fib(n-2);
    }
     
    for(var i = 0; i < 100; ++i) {
       postMessage({
          index: i,
          value: fib(i)
       })
    }

    In the example above we see that we can also pass complex objects to the postMessage. These objects can contain everything that can be transmitted via JSON. This means that functions cannot be passed across worker boundaries and that the objects are passed by value rather than by reference.

    Worker APIs

    Workers support a function called importScripts. You can use this to load more source files into the worker.

    importScripts("file.js");
    importScripts("foo.js", "bar.js");

    When you pass multiple parameters to the function the scripts will be downloaded in parallel but executed in the order of definition. The function does not return until all scripts have been downloaded and executed.

    Here we load an external JavaScript file that calculates SHA-1 hash sums from strings and then we use it to hash responses from AJAX requests. We also use the standard XMLHttpRequest object to retrieve the content of the URL which is passed in via the onmessage event. The interesting part is that we don’t have to worry about making the AJAX request asynchronous because the worker itself is asynchronous with respect to page rendering, so a little waiting for the HTTP request does not hurt as much.

    importScripts("sha1.js")
     
    function onmessage(event) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', event.data, false);
        xhr.send();
        postMessage(sha1(xhr.responseText));
    }

    Other APIs Available to Workers

    Workers may use XMLHttpRequest for AJAX requests as seen above and access the client sided database using web storage API. Here the APIs are identical to their usage in regular JavaScript.

    The setTimeout and setInterval (and the clearTimeout and clearInterval friends) functions, which enable executing code after a given period of time or at certain intervals, are also available within the worker as is the well known navigator object, which can be inspected to get information about the current browser.

    More APIs may be added in the future.

    Browser Compatibility

    As of this writing (and to the knowledge of the author), Firefox 3.5 is the only browser that supports the ability to pass complex objects via postMessage and that implements the extended APIs defined above. Safari 4 implements a very basic version of the Worker API. For other browsers it is possible to use Workers via Google Gears, which originally introduced the concept to browsers.

    Real World Usage

    In the Bespin project, which is a browser based source code editor, we successfully used workers to implement CPU intensive features like real-time source code error checking and code completion. We also created a shim that implements the Worker API in terms of Google Gears and which adds the missing features to the worker implementation of Safari 4 and also moved to using transparent custom events on top of the postMessage interface. These components will be released as a stand-alone library to be usable in other projects in the future.

    Web Workers will play an important role in making the Open Web an even more powerful platform for sophisticated applications. Because in the end all they do is execute JavaScript, it’s easy to make scripts work on clients which do yet have the luxury of web workers. So go ahead and add them to your applications today to make them feel just a little more responsive and more pleasant to use.

  5. video – more than just a tag

    This article is written by Paul Rouget, Mozilla contributor and purveyor of extraordinary Open Web demos.

    Starting with Firefox 3.5, you can embed a video in a web page like an image. This means video is now a part of the document, and finally, a first class citizen of the Open Web. Like all other elements, you can use it with CSS and JavaScript. Let’s see what this all means …

    The Basics

    First, you need a video to play. Firefox supports the Theora codec (see here to know all media formats supported by the audio and video elements).

    Add the video to your document:

    <video id="myVideo" src="myFile.ogv"/>

    You might need to add some “fallback” code if the browser doesn’t support the video tag. Just include some HTML (which could be a warning, or even some Flash) inside the video tag.

    <video id="myVideo" src="myFile.ogv">
    <strong>Your browser is not awesome enough!</strong>
    </video>

    Here’s some more information about the fallback mechanism.

    HTML Attributes

    You can find all the available attributes here.

    Some important attributes:

    • autoplay: The video will be played just after the page loads.
    • autobuffer: By default (without this attribute), the video file is not downloaded unless you click on the play button. Adding this attribute starts downloading the video just after the page loads.
    • controls: by default (without this attribute), the video doesn’t include any controls (play/pause button, volume, etc.). Use this attribute if you want the default controls.
    • height/width: The size of the video

    Example:

    <video id="myVideo" src="myFile.ogv" 
       autobuffer="true" controls="true"/>

    You don’t have to add the “true” value to some of these attributes in HTML5, but it’s neater to do so. If you’re not in an XML document, you can simply write:

    <video id="myVideo" src="myFile.ogv" autobuffer controls/>

    JavaScript API

    Like any other HTML element, you have access to the video element via the Document Object Model (DOM):

    var myVideo = document.getElementById("myVideo");

    Once you obtain a handle to the video element, you can use the JavaScript API for video.

    Here is a short list of some useful methods and properties (and see here for more of the DOM API for audio and video elements):

    • play() / pause(): Play and pause your video.
    • currentTime: The current playback time, in seconds. You can change this to seek.
    • duration: The duration of the video.
    • muted: Is the sound muted?
    • ended: Has the video ended?
    • paused: Is the video paused?
    • volume: To determine the volume, and to change it.

    Example:

    <button onclick="myVideo.play()">Play</button>
    <button onclick="myVideo.volume = 0.5">Set Volume</button>
    <button onclick="alert(myVideo.volume)">Volume?</button>

    Events

    You know how to control a video (play/pause, seek, change the volume, etc.). You have almost everything you need to create your own controls. But you need some feedback from the video, and for that, let’s see the different events you can listen to:

    • canplay: The video is ready to play
    • canplaythrough: The video is ready to play without interruption (if the download rate doesn’t change)
    • load: The video is ready to play without interruption (the video has been downloaded entirely)
    • ended: The video just ended
    • play: The video just started playing
    • pause: The video has been paused
    • seeking: The video is seeking (it can take some seconds)
    • seeked: The seeking process just finished
    • timeupdate: While the video is playing, the currentTime is updated. Every time the currentTime is updated, timeupdate is fired.

    Here’s a full list of events.

    For example, you can follow the percentage of the video that has just been played:

    function init() 
    {
      var video = document.getElementById("myVideo");
      var textbox = document.getElementById("sometext");
      video.addEventListener("timeupdate", function() {
      textbox.value = Math.round(100 * (video.currentTime / video.duration)) + "%"; }
     
    }
    <video id="myVideo" src="myFile.ogv" 
                autoplay="true" onplay="init()"/>
    <input id="sometext"/>

    Showing all this in action, here’s a nice open video player using the Video API.

    Now that you’re familiar with some of the broad concepts behind the Video API, let’s really delve into the video as a part of the Open Web, introducing video to CSS, SVG, and Canvas.

    CSS and SVG

    A video element is an HTML element. That means you can use CSS to style it.

    A simple example: using the CSS Image Border rule (a new CSS 3 feature introduced in Firefox 3.5). You can view how it works on the Mozilla Developer Wiki.

    And obviously, you can use it with the video tag:

     
    <video id="myVideo" src="myFile.ogv" 
    style="-moz-border-image: 
               url(tv-border.jpg) 25 31 37 31 stretch stretch; 
               border-width: 20px;"/>

    One of my demos uses this very trick.

    Since Firefox 3.5 provides some new snazzy new CSS features, you can do some really fantastic things. Take a look at the infamous washing machine demo, in which I subject an esteemed colleague to some rotation.

    It uses some CSS rules:

    And some SVG:

    Because the video element is like any other HTML element, you can add some HTML content over the video itself, like I do in this demo. As you can see, there is a <div> element on top of the video (position: absolute;).

    Time for a Break

    Well, we’ve just seen how far we can go with the video element, both how to control it and how to style it. That’s great, and it’s powerful. I strongly encourage you to read about the new web features available in Firefox 3.5, and to think about what you can do with such features and the video element.

    You can do so much with the power of the Open Web. You can compute the pixels of the video. You can, for example, try to find some shapes in the video, follow the shapes, and draw something as an attachment to these shapes. That’s what I do here! Let’s see how it actually works.

    Canvas & Video

    Another HTML 5 element is canvas. With this element, you can draw bitmap data (see the canvas reference, and I strongly suggest this canvas overview). But something you might not know is that you can copy the content of an <img/> element, a <canvas/> element and a <video/> element.

    That’s a really important point for the video element. It gives you a way to play with the values of the pixels of the video frames.

    You can do a “screenshot” of the current frame of the video in a canvas.

    function screenshot() {
     var video = document.getElementById("myVideo");
     var canvas = document.getElementById("myCanvas");
     var ctx = canvas.getContext("2d");
     
     ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
    }
    <video id="myVideo" src="myFile.ogv" autoplay="true" with="600" height="400"/>
    <canvas id="myCanvas" with="600" height="400"/>
    <button onclick="screenshot()">Copy current frame to canvas</button>

    You can first apply a transformation to your canvas (see the documentation). You can also copy a thumbnail of the video.

    If you draw every frame in a canvas, your canvas will look like a video element. And you can draw what you want in this canvas, after drawing the frame. That’s what I do in this demo.

    Once you have a video frame in your canvas, you can compute the values of the pixels.

    Some things you should know if you want to compute the pixels values of a frame:

    • you can’t use this mechanism with a video from another domain.
    • you can’t use this mechanism with a video from a file:/// URL (which would be useful during the development of your web application). But you can change this behavior for testing: in about:config, change the value of “security.fileuri.strict_origin_policy” to “false”. But be very careful! editing about:config — that’s an expert feature!
    • There are two ways to display the result of your application on the top of the video:
      • use your canvas as a video (if you draw the frame every time), and then draw directly into the canvas
      • use a transparent canvas on the top of the video
    • the canvas element can be “display: none”
    • the video element can be “display: none”

    About JavaScript

    For the image processing, you will need to do a lot of computation. Here are some tricks:

    • copy your frame in a small canvas. If the canvas is three times smaller than the video, it means nine times fewer pixels to compute.
    • avoid recursion. In a recursion, the script engine doesn’t use the JIT optimization.
    • if you want to do a distance between colors, use the L.A.B colorspace.
    • if you want to find the center of an object, compute its centroid. See the “computeFrame” function that I use in this JavaScript snippet for my demo.
    • if the algorithm is really heavy, you can use a Worker thread, but take into account that you will need to send the content of the canvas to the thread. It’s a big array, and objects are automatically JSONified before being sent. It can take a while.

    Conclusion

    As you can see, you can do powerful things with the video element, the canvas element, CSS3, SVG and the new JavaScript engine. You have everything in your hands to create a completely new way to use Video on the web. It’s up to you now — upgrade the web!

    References

  6. another great CSS media query demo

    This demo is from Daniel Glazman who works actively on web standards and is a long-time mozilla contributor.

    CSS Media Queries were originally a proposal submitted to the CSS Working Group by Opera Software and are now implemented in Firefox 3.5. In short, Media Queries extend the media declaration attached to a stylesheet to allow matching based on the rendering device’s intrinsic properties.

    Let’s take a link element declaring a stylesheet inside an HTML document:

    <link rel="stylesheet" type="text/css" href="style.css"
          media="screen">

    Now imagine you want this stylesheet to apply to the document if and only if the width of the content window is less than 300 pixels… CSS Media Queries make it simple to declare:

    <link rel="stylesheet" type="text/css" href="style.css"
          media="screen and (max-width: 300px)">

    Available properties include viewport’s width and height, device’s width and height, orientation (portrait or landscape), viewport’s aspect ratio, device’s aspect ratio, colormap, resolution and type of device.

    It’s then very easy to have one single web page ready for consumption on a wide variety of devices, ranging from mobile devices to monochrome tty displays.

    When viewing the demo, please don’t forget to resize the window from large to very very small (less than 100px!) to see it in action.

    Loading via planet, RSS or a reader without JavaScript? Click here instead.

  7. open video codecs discussion at Mozilla

    On Tuesday, July 28th, 2009, Mozilla hosted a brownbag and lunch discussion with Davis Freeberg and Dan Miller on the subject of open video codecs. Dan Miller is one of the founders of On2 and is largely responsible for the free release of VP3, which is the basis for the Theora codec. Davis Freeberg hosts a popular blog in which he comments extensively on the state of video on the Internet.


    Download: (320×240) Ogg Theora | MP4
  8. slick tables with css 3 selectors

    This article and demo come to us courtesy of Ivan Enderlin, author of the HOA Framework and longtime web developer.

    This is the article that accompanies the demo below, showing the use of CSS3 selectors implemented in Firefox 3.5 for easy and stylish tables.

    CSS3 Selectors for Quick and Pretty Tables

    View the Demo | CSS3 Selectors for Quick and Pretty Tables


    See this demo step by step.

    Basic HTML Table

    First, we start by writing a simple HTML table. Note: we do not have any classes or ids, which is what makes this all so fantastic:

    <table>
      <thead>
        <th>...</th>
        ...
        <th>...</th>
      </thead>
      <tbody>
        <tr>
          <td>...</td>
          ...
          <td>...</td>
        <tr>
        ...
        <tr>
          <td>...</td>
          ...
          <td>...</td>
        <tr>
      </tbody>
    </table>

    And now, let us write some CSS to make the plain old table look a bit more stylish:

    table {
        font: 90%/1.5em "Lucida Grande", Geneva,
                        "DejaVu Sans", "Bitstream Vera Sans", AnjaliOldLipi,
                        "Lucida sans", "Trebuchet MS", Arial, Verdana;
        text-align: center;
        border: 4px black double;
        border-spacing: 0;
        -moz-border-radius: 12px;
        -moz-box-shadow: #6a3d37 5px 5px 6px;
        -webkit-border-radius: 12px;
        -webkit-box-shadow: #6a3d37 5px 5px 6px;
        border-radius: 12px;
        box-shadow: #6a3d37 5px 5px 6px;
        background: #b59d5c
    }

    The use of border-spacing, border-radius and box-shadow properties make for a quick and easy way to inject a little beauty into the table.

    First Selection

    Now, we would like to style all the th tags. This is easy with CSS Selectors:

    th {
        color: #fff;
        font-size: 110%;
        text-shadow: #6a3d37 2px 2px 2px
    }

    Reminder: if we write table th we intend to select all the th elements which are child elements of the the table element, and if we write thead > th, we intend to select all the th elements which are direct children of the thead element. Well, it was just a reminder :-)

    More Nuanced Selection

    The th tag represents a table header. We would like to select the first table header. Hmm… maybe we should use the first-of-type pseudo-class. It represents an element that is the first sibling of its type in the list of children of its parent element. So now we have:

     
    th:first-of-type {
    font-weight: bold;
    font-style: italic
    }

    Even and odd rows

    A recurrent problem with tables is: how to select even and odd rows? The solution is the nth-child() pseudo-class. All these pseudo-classes understand the an+b syntax — to select all the even elements, we use 2n; to select all the odd elements, we use the 2n+1 elements; to select all third elements, we use 3n. In other words, this matches the bth child of an element after all the children have been split into groups of a elements each.

    So, let’s style the even and odd rows:

     
    tr:nth-child(odd) {
        color: #e0d8cb;
        background: #474644
    }
     
    tr:nth-child(even) {
        color: #6a3d37
    }

    Padding on first and last columns

    Now, we want to add a padding to the first and the last column. I remind you again that we do not have any classes or IDs, and that the number of columns is unknown.

    The solution is the first-of-type and the last-of-type pseudo-classes. We select all the first and last th and td like this:

     
    th:first-of-type,
    td:first-of-type {
        padding: 0 0 0 4em
    }
     
    th:last-of-type,
    td:last-of-type {
        padding: 0 4em 0 0
    }

    The two last rows

    Now, we would like to combine many pseudo-classes (and introduce a new one).

    Let’s say we would like to select row number 1, number 4 and number 7. The mathematical expression is not so simple as we hoped. The tips is to split our rows in groups of 3, like this: 3n. But, that will select rows number 3, 6 and 9. Almost there! In these groups, we will select the first element, so 3n+1 (or 3n-2 if you like to complicate things).

    That’s good, but that will select a row in our two last non-opaque rows. Ideally, we should say: “select the first row of each groups of three rows, but not the last row (which will be selected, because the last is the 7th row).” Simple. We are going to use the not pseudo-class, combined with the last-child pseudo-class (or last-of-type, which also works here).

    Thus:

     
    tr:nth-last-child(-n+2) {
        opacity: .75
    }
     
    tr:nth-child(3n+1):not(:last-child) td {
        text-shadow: red 0 0 8px
    }

    The final source is:

    table {
        display: table;
        font: 90%/1.5em "Lucida Grande", Geneva,
                        "DejaVu Sans", "Bitstream Vera Sans", AnjaliOldLipi,
                        "Lucida sans", "Trebuchet MS", Arial, Verdana;
        text-align: center;
        border: 4px black double;
        border-spacing: 0;
        -moz-border-radius: 12px;
        -moz-box-shadow: #6a3d37 5px 5px 6px;
        -webkit-border-radius: 12px;
        -webkit-box-shadow: #6a3d37 5px 5px 6px;
        border-radius: 12px;
        box-shadow: #6a3d37 5px 5px 6px;
        background: #b59d5c
    }
     
    th {
        color: #fff;
        font-size: 110%;
        text-shadow: #6a3d37 2px 2px 2px
    }
     
        th:first-of-type {
            font-weight: bold;
            font-style: italic
        }
     
    tr:nth-child(odd) {
        color: #e0d8cb;
        background: #474644
    }
     
    tr:nth-child(even) {
        color: #6a3d37
    }
     
    th:first-of-type,
    td:first-of-type {
        padding: 0 0 0 4em
    }
     
    th:last-of-type,
    td:last-of-type {
        padding: 0 4em 0 0
    }
     
    tr:nth-last-child(-n+2) {
        opacity: .75
    }
     
    tr:nth-child(3n+1):not(:last-child) td {
        text-shadow: red 0 0 8px
    }


    View this demo step by step
    .

  9. synchronous XHR requests in Firefox 3.5

    This post is from Doug Turner who has previous written about Geolocation. Doug works on Mozilla’s mobile project.

    XMLHttpRequests (XHR) can be either synchronous or asynchronous. Although most people use asynchronous requests there are instances where you might want to use a synchronous request. That is, wait until the XMLHttpRequest call completes to continue executing JavaScript. In Firefox 3 and earlier the browser would still fire timer events and respond to input events during a synchronous XHR request. In Firefox 3.5 and later input events such as mouse moves and timeouts will be suspended until the synchronous request completes. This allows the synchronous request to block.

    For example:

    function hello() {
         alert(“hello”);
    }
     
    setTimeout(hello, 20);
     
    var req = new XMLHttpRequest();
    req.open('GET', 'http://www.mozilla.org/', false);
    req.send(null);

    Prior to Firefox 3.5, it was impossible to determine if the “hello” function would be invoked during or after the XHR request. This led to all sorts of timing issues in web applications that used synchronous XHR requests.

    The solution to this problem has been to delay input events and timeouts until after “req.send” returns.

    For more information see the two bugs on the issue.

  10. css transforms: styling the web in two dimensions

    One feature that Firefox 3.5 adds to its CSS implementation is transform functions. These let you manipulate elements in two dimensional space by rotating, skewing, scaling, and translating them to alter their appearance.

    I’ve put together a demo that shows how some of these functions work.

    There are four animating objects in this demo. Let’s take a look at each of them.

    Rotating the Firefox logo

    On the left, we see the Firefox logo in a nice box, happily spinning in place. This is done by periodically setting the rotation value of the image object, whose ID is logoimg, like this:

      var logo = document.getElementById("logoimg");
     
      logoAngle = logoAngle + 2;
      if (logoAngle >= 360) {
        logoAngle = logoAngle - 360;
      }
     
      var style = "-moz-transform: rotate(" + logoAngle + "deg)";
      logo.setAttribute("style", style);

    Every time the animation function is run, we rotate it by 2° around its origin by constructing a style string of the form -moz-transform: rotate(Ndeg).

    By default, all elements’ origins are at their centers (that is, 50% along each axis). The origin can be changed using the -moz-transform-origin attribute.

    Skewing text

    We have two examples of skewing in this demo; the first skews horizontally, which causes the text to “lean” back and forth along the X axis. The second skews vertically, which causes the baseline to pivot along the Y axis.

    In both cases, the code to accomplish this animation is essentially identical, so let’s just look at the code for skewing horizontally:

      text1SkewAngle = text1SkewAngle + text1SkewOffset;
      if (text1SkewAngle > 45) {
        text1SkewAngle = 45;
        text1SkewOffset = -2;
      } else if (text1SkewAngle < -45) {
        text1SkewAngle = -45;
        text1SkewOffset = 2;
      }
     
      text1.style.MozTransform = "skewx(" + text1SkewAngle + "deg)";

    This code updates the current amount by which the text is skewed, starting at zero degrees and moving back and forth between -45° and 45° at a rate of 2° each time the animation function is called. Positive values skew the element to the right and negative values to the left.

    Then the element’s transform style is updated, setting the transform function to be of the form skewx(Ndeg), then setting the element’s style.MozTransform property to that value.

    Scaling elements

    The last of the examples included in the demo shows how to scale an element using the scale transform function:

      text3Scale = text3Scale + text3ScaleOffset;
      if (text3Scale > 6) {
        text3Scale = 6;
        text3ScaleOffset = -0.1;
        text3.innerHTML = "It's going away so fast!"
        text3.style.color = "blue";
      } else if (text3Scale < 1) {
        text3Scale = 1;
        text3ScaleOffset = 0.1;
        text3.innerHTML = "It's coming right at us!";
        text3.style.color = "red";
      }
     
      text3.style.MozTransform = "scale(" + text3Scale + ")";

    This code scales the element up and down between its original size (a scale factor of 1) and a scale factor of 6, moving by 0.1 units each frame. This is done by building a transform of the form scale(N), then setting the element’s style.MozTransform property to that value.

    In addition, just for fun, we’re also changing the text and the color of the text in the block as we switch scaling directions, by setting the value of the block’s innerHTML property to the new contents.

    Final notes

    Three more tidbits to take away from this:

    First, note that as the scaling text grows wider, the document’s width changes to fit it, getting wider as the text grows so that its right edge passes the edge of the document, then narrower as it shrinks again. You can see this by watching the scroll bar at the bottom of the Firefox browser window.

    Second, note that you can actually select and copy the text not only while the elements are transformed, but the selection remains intact while the text continues to transform (although when we change the contents of the scaling example, the selection goes away).

    Third, I didn’t cover all the possible transforms here. For example, I skipped over the translate transform function, which lets you translate an object horizontally or vertically (basically, shifting its position by an offset). You can get a full list of the supported transforms on the Mozilla Developer Center web site.

    Obviously this demo is somewhat frivolous (as demos are prone to be). However, there are genuinely useful things you can do with these when designing interfaces; for example, you can draw text rotated by 90° along the Y axis of a table in order to fit row labels in a narrow but tall space.