Labs/Jetpack/JEP/28: Difference between revisions

From MozillaWiki
< Labs‎ | Jetpack‎ | JEP
Jump to navigation Jump to search
(→‎memory: updated)
(added information about memory metadata objects)
Line 102: Line 102:
=== <tt>memory</tt> ===
=== <tt>memory</tt> ===


<tt>memory</tt> is an object that exposes functionality to track objects of interest and help prevent memory leaks.
<tt>memory</tt> is an object that exposes functionality to track objects of interest and help diagnose and prevent memory leaks.


<tt>memory.'''track'''(''object'', [''bin''])</tt>
<tt>memory.'''track'''(''object'', [''bin''])</tt>
Line 110: Line 110:
<tt>memory.'''getObjects'''([''bin''])</tt>
<tt>memory.'''getObjects'''([''bin''])</tt>


Returns an <tt>Array</tt> of all live tracked objects that have been categorized with the given bin name. If ''bin'' isn't provided, all live tracked objects are returned.
Returns an <tt>Array</tt> containing information about tracked objects that have been categorized with the given bin name. If ''bin'' isn't provided, information about all live tracked objects are returned.
 
Each element of the array is an object with the following keys:
 
{|cellpadding="5" cellspacing="0" border="1" width="100%"
|<tt>weakref</tt>
|A weak reference to the object being tracked. Call <tt>get()</tt> on this object to retrieve its strong reference; if a strong reference to the object no longer exists, <tt>get()</tt> will return <tt>null</tt>.
|-
|<tt>created</tt>
|A <tt>Date</tt> representing the date and time that <tt>memory.track()</tt> was called on the object being tracked.
|-
|<tt>filename</tt>
|The name of the file that called <tt>memory.track()</tt> on the object being tracked.
|-
|<tt>lineNo</tt>
|The line number of the file that called <tt>memory.track()</tt> on the object being tracked.
|}


<tt>memory.'''getBins'''()</tt>
<tt>memory.'''getBins'''()</tt>

Revision as of 00:36, 29 September 2009

Abstract

The Cuddlefish Minilib builds on JEP 25 - Boosters to provide a basic infrastructure for developing traditional XULRunner Extensions. It will also be the basis for Jetpack, as Jetpack itself is a XULRunner Extension.

Motivation and Rationale

In many ways, this JEP is a refactored formalization of Jetpack's current implementation that will allow many of Jetpack's core benefits to be leveraged by any XULRunner Extension. Another way of putting this is that Cuddlefish nicely decouples functionality that is specific to Jetpack from functionality that many other extensions—Labs extensions in particular—would like to have, and which they often end up re-implementing from scratch to some extent.

Additionally, by moving to a SecurableModule-based architecture, Jetpack's runtime can easily be decoupled from the about:jetpack page, which will resolve a number of deficiencies (such as the inability to look at the API documentation and use the built-in code editor simultaneously).

Requirements and Scope

To address issues present in traditional Extension development, Cuddlefish provides mechanisms for:

  • writing and executing test cases, inspired by Python's nose package,
  • tracking JS objects of interest to aid in memory profiling and leak detection,
  • registering callbacks that perform cleanup tasks when modules are unloaded,
  • easily reporting errors with full stack tracebacks,
  • dropping-in optional third-party packages or SecurableModules.

Cuddlefish should also have the following characteristics:

  • Beautiful, concise documentation.
  • A rigorous test suite ensuring that Cuddlefish doesn't break as the Mozilla platform evolves.
  • Solid developer ergonomics ensuring that developers can easily find out why something they're doing isn't working.

As is implied by the word "minilib", Cuddlefish is intended to be very small and only contain the bare minimum of functionality that all extensions need. This means, for instance, that a module that wraps clipboard access, or a module that computes SHA1 hashes, will not be included in Cuddlefish—though such modules may certainly be bundled with an extension and easily loaded using Cuddlefish.

The following are outside the scope of Cuddlefish:

  • Cuddlefish doesn't "touch" the command line at all; it's just a drop-in library to include in existing XULRunner Extensions or applications. As such, the following are out of scope:
  • A tool for creating new XULRunner Extension or application directory structures "from scratch".
  • A build system for creating XPIs or XULRunner applications.
  • A documentation system.
  • A package management system.
  • A user interface. Cuddlefish doesn't make any assumptions about whether you're using XUL, HTML, stdout, or something else. The exception to this is the logging console, which obviously needs something to output to, but multiple implementations will be built-in to the minilib, with the option for clients to provide their own.

Usage

Cuddlefish consists of a single directory that can be dropped-into an extension's directory structure and loaded either through a <script> tag in a chrome-privileged document or a JS module.

For example, assuming that the Cuddlefish directory is placed in the extension's chrome/content/lib directory, a file at chrome/content/main.html can load it like so:

<html>
  <script src="lib/cuddlefish.js"></script>
  <script>
  var loader = new Cuddlefish.Loader({rootPath: "lib/"});
  loader.runScript("console.log('hello');");
  loader.unload();
  </script>
</html>

The Loader class encapsulates the Cuddlefish library and runtime; the caller has full control (and responsibility!) over its lifecycle. This means, for instance, that a document can instantiate a Loader that continues existing long after the document is closed; alternatively, a JS module can instantiate a Loader that stops existing well before the containing application process terminates. This freedom of control allows for a wide range of behavior, including the ability for application-wide functionality to be "streamed in" and automatically updated without requiring a restart.

Globals

Every script and module loaded by Cuddlefish comes with a handful of globals to make life easier for developers.

In addition to the globals provided by the SecurableModule standard and the Mozilla platform, each module has the following global variables that reflect idioms present in most Mozilla platform/extension code:

  • Cc is mapped to Components.classes.
  • Ci is mapped to Components.interfaces.
  • Cu is mapped to Components.utils.
  • Cr is mapped to Components.results.

In addition to these, the following globals are available to all modules.

console

console is an object with methods similar to Firebug's console object:

console.log(object[, object, ...])

Logs an informational message to the console. Depending on console's underlying implementation and user interface, you may be able to introspect into the properties of non-primitive objects that are logged.

console.info(object[, object, ...])

A synonym for console.log().

console.warn(object[, object, ...])

Logs a warning message to the console.

console.error(object[, object, ...])

Logs an error message to the console.

console.debug(object[, object, ...])

Logs a debug message to the console.

console.exception(exception)

Logs the given exception instance as an error, outputting information about the exception's stack traceback if one is available.

console.trace()

Inserts a stack trace into the console at the point this function is called.

memory

memory is an object that exposes functionality to track objects of interest and help diagnose and prevent memory leaks.

memory.track(object, [bin])

Marks object for being tracked, and categorizes it with the given bin name. If bin isn't specified, the memory tracker attempts to infer a bin name by first checking the object's constructor.name; if that fails or results in the generic Object, the stack is inspected and the name of the current function being executed—which is assumed to be a constructor function—is used. If that fails, then the object is placed in a bin named generic.

memory.getObjects([bin])

Returns an Array containing information about tracked objects that have been categorized with the given bin name. If bin isn't provided, information about all live tracked objects are returned.

Each element of the array is an object with the following keys:

weakref A weak reference to the object being tracked. Call get() on this object to retrieve its strong reference; if a strong reference to the object no longer exists, get() will return null.
created A Date representing the date and time that memory.track() was called on the object being tracked.
filename The name of the file that called memory.track() on the object being tracked.
lineNo The line number of the file that called memory.track() on the object being tracked.

memory.getBins()

Returns an Array containing the names of all bins that aren't currently empty.

Modules

The following modules come built-in with Cuddlefish and can be retrieved with a call to require().

timer

The timer module provides access to web-like timing functionality.

timer.setTimeout(callback, ms)

Schedules callback to be called in ms milliseconds. Returns an integer ID that can later be used to undo this scheduling, if callback hasn't yet been called.

timer.clearTimeout(id)

Given an integer ID passed back from setTimeout(), prevents the callback with the ID from being called (if it hasn't yet been called).

url

The url module provides functionality for the parsing and retrieving of URLs.

url.resolve(base, relative)

Returns an absolute URL given a base URL and a relative URL.

url.parse(url)

Parses the URL and returns an object with following keys:

scheme The name of the protocol in the URL.
userPass The username:password part of the URL; null if not present.
host The host of the URL, null if not present.
port The port number of the URL, null if none was specified.
path The path component of the URL.

traceback

The traceback module contains functionality similar to Python's traceback module.

JSON Traceback Objects

Tracebacks are stored in JSON format. The stack is represented as an array in which the most recent stack frame is the last element; each element thus represents a stack frame and has the following keys:

filename The name of the file that the stack frame takes place in.
lineNo The line number is being executed at the stack frame.
funcName The name of the function being executed at the stack frame, or null if the function is anonymous or the stack frame is being executed in a top-level script or module.

Functions

traceback.fromException(exception)

Attempts to extract the traceback from exception, returning the JSON representation of the traceback or null if no traceback could be extracted.

traceback.get()

Returns the JSON representation of the stack at the point that this function is called.

traceback.format([tbOrException])

Given a JSON representation of the stack or an exception instance, returns a formatted plain text representation of it, similar to Python's formatted stack tracebacks. If no argument is provided, the stack at the point this function is called is used.

unload

The unload module allows modules to register callbacks that are called when Cuddlefish is unloaded. It is similar to the SecurableModule of the same name in the Narwhal platform.

unload.when(callback)

Registers callback to be called when unload.send() is called.

unload.send()

Sends an unload signal, thereby triggering all callbacks registered via unload.when(). In general, this function need not be manually called; it is automatically triggered when the containing Cuddlefish Loader's unload() method is called.

Reference Implementation

An in-progress reference implementation for Cuddlefish can be found at:

 http://hg.mozilla.org/users/avarma_mozilla.com/jep-28/

Just check out the Mercurial repository and read the README.