croczilla.com 
 home   zap   svg   xtf   jssh   bits&pieces   blog   personal   
  home > zap > hacking zap

Hacking zap

JS enhancements

Zap is based on a modified xulrunner build which provides some enhancements over a normal build:

JS modules

The JS module system (see bug 238324) adds a way to define code in a JS file, declare some symbols as 'exports' and then import these symbols into other JS files:

File mymodule.js (installed in dist/bin/modules)

EXPORTED_SYMBOLS = ["foo", "bar"];

var hidden_val = 0;

function foo() {
  return hidden_val;
}

function bar() {
  hidden_val += 1;
}
File myclient1.js
Components.utils.import("resource://gre/modules/mymodule.jsm");
...
foo(); //-> returns the current value of mymodule::hidden_val
bar(); //-> increment mymodule::hidden_val
hidden_val; //-> not defined
File myclient2.js
Components.utils.import("resource://gre/modules/mymodule.jsm");
...
foo(); //-> returns the current value of mymodule::hidden_val
bar(); //-> increment mymodule::hidden_val
hidden_val; //-> not defined

myclient.js implements 3 objects (hidden_val, foo and bar) and marks two of them as 'exported' by listing their names in the 'EXPORTED_SYMBOLS' array.

Other js files can import the myclient.js module with "Components.utils.import('path_of_module');". This will cause myclient.js to be loaded into memory (if it hasn't already) and all symbols listed in the 'EXPORTED_SYMBOLS' array to be set as properties on the importing file's global object.

If a module is imported by several clients, all clients will 'share' the same module. I.e. if myclient1::foo() returns '1' and myclient2 executes myclient2::bar(), a subsequent invocation of myclient1::foo() will yield '2'. The module file only gets loaded once during a Mozilla session, by the first client that imports it.

Note that module mechanism is not the same as pulling in scripts into a xul (or html) file using code such as:

<window>
  ...
  <script type="application/javascript" src="myJSFile1.js"/>
  <script type="application/javascript" src="myJSFile2.js"/>
  ...
</window>
In this example, myJSFile1.js and myJSFile2.js both share the same global object, i.e. any symbol defined in myJSFile1.js is accessible from myJSFile2.js and vice versa. Also when a second window gets opened, new copies of myFile1.js and myFile2.js will be loaded into memory.

The js module mechanism is especially useful for implementing JS XPCOM modules, because it allows several JS XPCOM objects to share some library-type code without having to implement this library code as an XPCOM object itself (and being limited to XPCOM types).

JS getObjectId()

To be written. See bug 317485.

C++ enhancements

XPCOM autoproxification

To be written

Necko UDP sockets

To be written

ZAP base library

JS and XPCOM utility code in mozilla/zap/base

ArrayUtils.js

ArrayUtils.js is a JS module providing some utility functions for JS array manipulation. See the documentation inline in mozilla/zap/base/ArrayUtils.js for details.
You can try the following code in the debug shell (Tools > Debug Shell):
Components.utils.import("resource://gre/modules/ArrayUtils.js"); <shift-enter>
   -> [ArrayUtils.js]
var a = ["C++", "is", "great", "but", 
         "JS", "is", "better", "than", "C++"]; <shift-enter>
a <shift-enter>
   -> C++,is,great,but,JS,is,better,than,C++
arraysubst("Java", "C++", a); <shift-enter>
a <shift-enter>
   -> Java,is,great,but,JS,is,better,than,Java

AsyncUtils.js

AsyncUtils.js is a JS module providing utility functions for asynchronous code execution. See the documentation inline in mozilla/zap/base/AsyncUtils.js for details.
Sample debug shell session:
Components.utils.import("resource://gre/modules/AsyncUtils.js"); <shift-enter>
   -> [object BackstagePass]
schedule(function() {print("BOO\n");}, 5000); <shift-enter>
   -> [xpconnect wrapped nsITimer @ 0xXXXXXXXX (native @ 0xXXXXXXXX)]
   -> (after 5 seconds:) BOO