Bug 935220: Uplift Add-on SDK to Firefox. r=me
authorDave Townsend <dtownsend@oxymoronical.com>
Tue, 05 Nov 2013 13:51:58 -0800
changeset 168278 f4fdb40f96b1321df9417302ac970ba66e2ab3da
parent 168277 9150f892e4eae19e2087fe0bddf133b58995093b
child 168279 cc6a86be98fdebb302ec7beb04344e69e5de65df
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs935220
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 935220: Uplift Add-on SDK to Firefox. r=me https://github.com/mozilla/addon-sdk/compare/firefox27...50697e6182cb4f79f9605b7cd1d1f5084cfaf03f
addon-sdk/Makefile.in
addon-sdk/source/data/index.html
addon-sdk/source/data/mofo_logo.SVG
addon-sdk/source/data/moz_favicon.ico
addon-sdk/source/data/pagemod-css-include-file.css
addon-sdk/source/data/test-content-symbiont.js
addon-sdk/source/data/test-context-menu.js
addon-sdk/source/data/test-iframe-postmessage.html
addon-sdk/source/data/test-iframe.html
addon-sdk/source/data/test-iframe.js
addon-sdk/source/data/test-message-manager.js
addon-sdk/source/data/test-net-url.txt
addon-sdk/source/data/test-page-mod.html
addon-sdk/source/data/test-page-worker.html
addon-sdk/source/data/test-page-worker.js
addon-sdk/source/data/test-sidebar-addon-global.html
addon-sdk/source/data/test-trusted-document.html
addon-sdk/source/data/test.html
addon-sdk/source/data/testLocalXhr.json
addon-sdk/source/doc/module-source/sdk/places/favicon.md
addon-sdk/source/doc/module-source/sdk/tabs.md
addon-sdk/source/doc/module-source/sdk/ui.md
addon-sdk/source/doc/module-source/sdk/ui/sidebar.md
addon-sdk/source/doc/static-files/media/screenshots/sidebar-menu.png
addon-sdk/source/doc/static-files/media/screenshots/sidebar.png
addon-sdk/source/examples/library-detector/package.json
addon-sdk/source/lib/sdk/content/symbiont.js
addon-sdk/source/lib/sdk/io/buffer.js
addon-sdk/source/lib/sdk/io/fs.js
addon-sdk/source/lib/sdk/io/stream.js
addon-sdk/source/lib/sdk/system/events.js
addon-sdk/source/lib/sdk/ui/sidebar.js
addon-sdk/source/lib/sdk/ui/sidebar/contract.js
addon-sdk/source/lib/sdk/ui/sidebar/view.js
addon-sdk/source/lib/sdk/window/helpers.js
addon-sdk/source/lib/sdk/window/utils.js
addon-sdk/source/lib/toolkit/loader.js
addon-sdk/source/python-lib/cuddlefish/__init__.py
addon-sdk/source/python-lib/cuddlefish/manifest.py
addon-sdk/source/python-lib/cuddlefish/rdf.py
addon-sdk/source/python-lib/cuddlefish/templates.py
addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-1-pack/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-2-unpack/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-3-pack/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/fullName/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/none/package.json
addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/title/package.json
addon-sdk/source/python-lib/cuddlefish/tests/preferences-files/packages/no-prefs/package.json
addon-sdk/source/python-lib/cuddlefish/tests/preferences-files/packages/simple-prefs/package.json
addon-sdk/source/python-lib/cuddlefish/tests/test_init.py
addon-sdk/source/python-lib/cuddlefish/tests/test_linker.py
addon-sdk/source/python-lib/cuddlefish/tests/test_rdf.py
addon-sdk/source/python-lib/cuddlefish/tests/test_xpi.py
addon-sdk/source/test/addons/addon-page/data/index.html
addon-sdk/source/test/addons/addon-page/main.js
addon-sdk/source/test/addons/addon-page/package.json
addon-sdk/source/test/addons/places/favicon-helpers.js
addon-sdk/source/test/addons/places/main.js
addon-sdk/source/test/addons/places/package.json
addon-sdk/source/test/addons/places/places-helper.js
addon-sdk/source/test/addons/places/tests/test-places-bookmarks.js
addon-sdk/source/test/addons/places/tests/test-places-events.js
addon-sdk/source/test/addons/places/tests/test-places-favicon.js
addon-sdk/source/test/addons/places/tests/test-places-history.js
addon-sdk/source/test/addons/places/tests/test-places-host.js
addon-sdk/source/test/addons/places/tests/test-places-utils.js
addon-sdk/source/test/addons/self/data/data.md
addon-sdk/source/test/addons/self/main.js
addon-sdk/source/test/addons/self/package.json
addon-sdk/source/test/addons/symbiont/data/test-trusted-document.html
addon-sdk/source/test/addons/symbiont/main.js
addon-sdk/source/test/addons/symbiont/package.json
addon-sdk/source/test/buffers/test-read-types.js
addon-sdk/source/test/buffers/test-write-types.js
addon-sdk/source/test/favicon-helpers.js
addon-sdk/source/test/fixtures.js
addon-sdk/source/test/fixtures/index.html
addon-sdk/source/test/fixtures/loader/json/invalid.json
addon-sdk/source/test/fixtures/loader/json/manifest.json
addon-sdk/source/test/fixtures/loader/json/nodotjson.json.js
addon-sdk/source/test/fixtures/loader/json/test.json
addon-sdk/source/test/fixtures/loader/json/test.json.js
addon-sdk/source/test/fixtures/mofo_logo.SVG
addon-sdk/source/test/fixtures/moz_favicon.ico
addon-sdk/source/test/fixtures/pagemod-css-include-file.css
addon-sdk/source/test/fixtures/test-content-symbiont.js
addon-sdk/source/test/fixtures/test-context-menu.js
addon-sdk/source/test/fixtures/test-iframe-postmessage.html
addon-sdk/source/test/fixtures/test-iframe.html
addon-sdk/source/test/fixtures/test-iframe.js
addon-sdk/source/test/fixtures/test-message-manager.js
addon-sdk/source/test/fixtures/test-net-url.txt
addon-sdk/source/test/fixtures/test-page-mod.html
addon-sdk/source/test/fixtures/test-page-worker.html
addon-sdk/source/test/fixtures/test-page-worker.js
addon-sdk/source/test/fixtures/test-sidebar-addon-global.html
addon-sdk/source/test/fixtures/test-trusted-document.html
addon-sdk/source/test/fixtures/test.html
addon-sdk/source/test/fixtures/testLocalXhr.json
addon-sdk/source/test/places-helper.js
addon-sdk/source/test/test-addon-installer.js
addon-sdk/source/test/test-addon-page.js
addon-sdk/source/test/test-buffer.js
addon-sdk/source/test/test-content-loader.js
addon-sdk/source/test/test-content-script.js
addon-sdk/source/test/test-content-symbiont.js
addon-sdk/source/test/test-context-menu.js
addon-sdk/source/test/test-loader.js
addon-sdk/source/test/test-net-url.js
addon-sdk/source/test/test-page-mod.js
addon-sdk/source/test/test-page-worker.js
addon-sdk/source/test/test-panel.js
addon-sdk/source/test/test-places-bookmarks.js
addon-sdk/source/test/test-places-events.js
addon-sdk/source/test/test-places-favicon.js
addon-sdk/source/test/test-places-history.js
addon-sdk/source/test/test-places-host.js
addon-sdk/source/test/test-places-utils.js
addon-sdk/source/test/test-promise.js
addon-sdk/source/test/test-self.js
addon-sdk/source/test/test-system-events.js
addon-sdk/source/test/test-ui-button.js
addon-sdk/source/test/test-ui-sidebar.js
addon-sdk/source/test/test-widget.js
addon-sdk/source/test/test-window-utils.js
addon-sdk/source/test/test-xhr.js
--- a/addon-sdk/Makefile.in
+++ b/addon-sdk/Makefile.in
@@ -8,17 +8,16 @@ libs::
 	$(PYTHON) $(srcdir)/copy_source.py $(topsrcdir) $(srcdir)/source/lib $(FINAL_TARGET)/modules/commonjs >copy_source.mk
 	$(MAKE) -f copy_source.mk libs
 
 include $(topsrcdir)/config/rules.mk
 
 TEST_FILES = \
   source/app-extension \
   source/bin \
-  source/data \
   source/python-lib \
   source/test \
   source/package.json \
   source/mapping.json \
   $(NULL)
 
 # Remove this once the test harness uses the APIs built into Firefox
 TEST_FILES += source/lib
--- a/addon-sdk/source/doc/module-source/sdk/places/favicon.md
+++ b/addon-sdk/source/doc/module-source/sdk/places/favicon.md
@@ -30,17 +30,17 @@ such, will only return favicon URLs for 
     });
 
     // An optional callback can be provided to handle
     // the promise's resolve and reject states
     getFavicon("http://mozilla.org", function (url) {
       console.log(url); // http://mozorg.cdn.mozilla.net/media/img/favicon.ico
     });
 
-@param object {string, tab}
+@param object {string|tab}
   A value that represents the URL of the page to get the favicon URL from.
   Can be a URL `String` or a [`Tab`](modules/sdk/tabs.html#Tab).
 
 @param callback {function}
   An optional callback function that will be used in both resolve and
   reject cases.
 
 @returns {promise}
--- a/addon-sdk/source/doc/module-source/sdk/tabs.md
+++ b/addon-sdk/source/doc/module-source/sdk/tabs.md
@@ -121,16 +121,20 @@ content (see the
       tab.attach({
         contentScript: 'self.postMessage(document.body.innerHTML);',
         onMessage: function (message) {
           console.log(message);
         }
       });
     });
 
+Note that `tab.attach` is tab-centric: if the user navigates to a new
+page in the same tab, then the worker and content scripts will be
+reattached to the new page.
+
 ## Private Windows ##
 
 If your add-on has not opted into private browsing, then you won't see any
 tabs that are hosted by private browser windows.
 
 Tabs hosted by private browser windows won't be seen if you enumerate the
 `tabs` module itself, and you won't receive any events for them.
 
@@ -341,44 +345,49 @@ Makes this tab active, which will bring 
 
 <api name="getThumbnail">
 @method
 Returns thumbnail data URI of the page currently loaded in this tab.
 </api>
 
 <api name="attach">
 @method
-  Create a page mod and attach it to the document in the tab.
+  Create a [Worker](modules/sdk/content/worker.html) and attach it to
+  every document loaded in the tab. Note that this is tab-centric: if
+  the user navigates to a new page in the same tab, then the worker and
+  content scripts will be reattached to the new page.
 
 **Example**
 
     var tabs = require("sdk/tabs");
 
     tabs.on('ready', function(tab) {
       tab.attach({
           contentScript:
             'document.body.style.border = "5px solid red";'
       });
     });
 
 @param options {object}
-  Options for the page mod, with the following keys:
+  Options for the worker, with the following keys:
 
 @prop [contentScriptFile] {string,array}
     The local file URLs of content scripts to load.  Content scripts specified
     by this option are loaded *before* those specified by the `contentScript`
     option. Optional.
 @prop [contentScript] {string,array}
-    The texts of content scripts to load.  Content scripts specified by this
-    option are loaded *after* those specified by the `contentScriptFile` option.
+    A string or an array of strings of code to be evaluated in the context.
+    Content scripts specified by this option are loaded *after*
+    those specified by the `contentScriptFile` option.
     Optional.
 @prop [onMessage] {function}
-    A function called when the page mod receives a message from content scripts.
-    Listeners are passed a single argument, the message posted from the
-    content script. Optional.
+    A function called when the content worker receives a message from
+    content scripts. Listeners are passed a single argument, the
+    message posted from the content script.
+    Optional.
 
 @returns {Worker}
   The [Worker](modules/sdk/content/worker.html#Worker) object can be used to
   communicate with the content script.
   See [Content Scripts guide](dev-guide/guides/content-scripts/index.html)
   to learn the details.
 
 </api>
deleted file mode 100644
--- a/addon-sdk/source/doc/module-source/sdk/ui.md
+++ /dev/null
@@ -1,214 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- contributed by Erik Vold [evold@mozilla.com] -->
-
-This module exports a two constructor functions `Button` which constructs a
-new toolbar button, and `Sidebar` which constructs a sidebar (with a button).
-
-Sidebars are displayed on the left side of your browser. Its content is specified as
-local HTML, so the appearance and behaviour of the sidebar
-is limited only by what you can do using HTML, CSS and JavaScript.
-
-The screenshot below shows a sidebar whose content is built from tweets:
-
-<!-- add screen shot here -->
-
-Sidebars are useful for presenting temporary interfaces to users in a way that is
-easier for users to ignore and dismiss than a modal dialog 
-and easier for users to keep around than a Panel, since sidebars are
-displayed at the side of the browser until the user decides to close it.
-
-A sidebar's content is loaded anew as soon as it is opened, and unloads
-when the user closes the sidebar.
-
-Your add-on can receive notifications when a sidebar is shown or hidden by
-listening to its `show` and `hide` events.
-
-Opening a sidebar in a window will close an already opened sidebar in that window.
-
-## Sidebar Content ##
-
-The sidebar's content is specified as HTML, which is loaded from the URL
-supplied in the `url` option to the sidebar's constructor.
-
-You can load remote HTML into the sidebar:
-
-    var sidebar = require("sdk/ui").Sidebar({
-      id: 'a-new-sidebar',
-      title: 'A New Sidebar',
-      icon: './icon.png',
-      url: './index.html'
-    });
-
-    sidebar.show();
-
-This will load HTML that's been packaged with your add-on, and this is
-most probably how you will create sidebars. To do this, save
-the `index.html` HTML file in your add-on's `data` directory.
-
-## Sidebar Positioning ##
-
-By default the sidebars appears on the left side of the currently active browser window.
-
-
-## Updating Sidebar Content ##
-
-You can update the sidebar's content simply by setting the sidebar's `url`
-property.  Note this will change the sidebar's url for all windows.
-
-## Scripting Sidebar Content ##
-
-You can't directly access your sidebar's content from your main add-on code.
-To access the sidebar's content, you need to add a `<script>` into the sidebar.
-
-The sidebar's scripts will have access to a `addon` global, with you can
-communicate with your main add-on code, like so:
-
-`lib/main.js`:
-
-    let sidebar = Sidebar({
-      id: 'a-new-sidebar',
-      title: 'A New Sidebar',
-      icon: './icon.png',
-      url: './index.html',
-      onAttach: function (worker) {
-        worker.port.on('message', function() {  // part 2
-            // do things...
-            worker.port.emit('message', 'I have information for you!');  // part 3
-        });
-      }
-    });
-
-`data/index.html`
-
-<pre class="brush: html">
-&lt;html&gt;
-  &lt;head&gt;&lt;/head&gt;
-  &lt;body&gt;
-    ...
-    &lt;script&gt;
-    addon.port.on('message', function(msg) {  // part 4
-      // msg will == 'I have information for you!'
-    });
-    // starting communication here..
-    addon.port.emit('message');  // part 1
-    &lt;/script&gt;
-  &lt;/body&gt;
-&lt;/html&gt;
-</pre>
-
-<api name="Sidebar">
-@class
-The Sidebar object.
-
-Once a sidebar object has been created it can be shown and hidden,
-in the active window, using its
-`show()` and `hide()` methods. Once a sidebar is no longer needed it can be
-removed/destructed using `destroy()`.
-
-<api name="Sidebar">
-@constructor
-Creates a sidebar.
-@param options {object}
-  Options for the sidebar, with the following keys:
-  @prop id {string}
-    The `id` of the sidebar.
-  @prop title {string}
-    A title for the sidebar.
-  @prop icon {string, object}
-    The icon used for the sidebar's button.
-  @prop url {string, URL}
-    The URL of the content to load in the sidebar.
-  @prop [onAttach] {function}
-    Include this to listen to the sidebar's `attach` event.
-  @prop [onShow] {function}
-    Include this to listen to the sidebar's `show` event.
-  @prop [onHide] {function}
-    Include this to listen to the sidebar's `hide` event.
-</api>
-
-<api name="id">
-@property {string}
-The `id` for the sidebar.
-</api>
-
-<api name="title">
-@property {string}
-The `title` of the sidebar.
-</api>
-
-<api name="icon">
-@property {string, object}
-The global icon for the sidebar.
-</api>
-
-<api name="url">
-@property {string}
-The URL of content loaded into the sidebar. 
-</api>
-
-<api name="destroy">
-@method
-Destroys the sidebar, once destroyed, the sidebar can no longer be used.
-</api>
-
-<api name="show">
-@method
-Displays the sidebar in the active window.
-</api>
-
-<api name="hide">
-@method
-Hides the sidebar in the active window.
-</api>
-
-<api name="on">
-@method
-  Registers an event listener with the sidebar.
-@param type {string}
-  The type of event to listen for.
-@param listener {function}
-  The listener function that handles the event.
-</api>
-
-<api name="once">
-@method
-  Registers an event listener with the sidebar.
-  The difference between `on` and `once` is that
-  `on` will continue listening until it is
-  removed, whereas `once` is removed automatically
-  upon the first event it catches.
-@param type {string}
-  The type of event to listen for.
-@param listener {function}
-  The listener function that handles the event.
-</api>
-
-<api name="removeListener">
-@method
-  Unregisters/removes an event listener from the sidebar.
-@param type {string}
-  The type of event for which `listener` was registered.
-@param listener {function}
-  The listener function that was registered.
-</api>
-
-<api name="attach">
-@event
-This event is emitted when the sidebar's window
-is created and the `addon` global was added.
-</api>
-
-<api name="show">
-@event
-This event is emitted when the sidebar is shown.
-</api>
-
-<api name="hide">
-@event
-This event is emitted when the sidebar is hidden.
-</api>
-
-</api>
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/doc/module-source/sdk/ui/sidebar.md
@@ -0,0 +1,378 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+The `sidebar` module enables you to create sidebars. A sidebar is a a strip
+of user interface real estate for your add-on that's attached to the
+left-hand side of the browser window. A sidebar is a bit like a widget,
+in that it's a persistent user interface element belonging to your add-on
+that's attached to the browser window. However, it's much bigger than a
+widget and is suitable for more presenting more complex interfaces.
+
+## Creating, showing, and hiding sidebars
+
+You construct a `Sidebar` object using the [`Sidebar()`](modules/sdk/ui/sidebar.html#Sidebar(options)) constructor.
+
+Once you've done that, you can show the sidebar in the currently active window
+by calling the Sidebar's [`show()`](modules/sdk/ui/sidebar.html#show()) method. If a new window is opened from a
+window that has a sidebar visible, the new window gets a sidebar, too.
+
+You can hide the sidebar in the currently active window by calling its
+[`hide()`](modules/sdk/ui/sidebar.html#hide()) method.
+
+Alternatively, the View->Sidebar submenu in Firefox will contain a new item
+which the user can use to show or hide the sidebar:
+
+<img class="image-center" src="static-files/media/screenshots/sidebar-menu.png" alt="Opening sidebar from a menu">
+
+The sidebar generates a [`show`](modules/sdk/ui/sidebar.html#show) event when it is shown and a [`hide`](modules/sdk/ui/sidebar.html#hide) event when
+it is hidden.
+
+Once you've finished using the sidebar you can destroy it by calling its
+[`dispose()`](file:///Users/Work/mozilla/jetpack-sdk/doc/modules/sdk/ui/sidebar.html#dispose()) method.
+
+To show what a sidebar looks like, here's a sidebar that displays the results
+of running the [W3C Validator](http://validator.w3.org/) on the current page:
+
+<img class="image-center" src="static-files/media/screenshots/sidebar.png" alt="Simple sidebar example">
+
+
+## Specifying sidebar content
+
+The content of a sidebar is specified using HTML, which is loaded from the URL
+supplied in the `url` option to the sidebar's constructor. Unlike modules
+such as [`panel`](modules/sdk/panel.html), the content must be local,
+typically loaded from the add-on's `data` directory via a URL constructed
+using [`self.data.url()`](modules/sdk/self.html#data):
+
+    var sidebar = require("sdk/ui/sidebar").Sidebar({
+      id: 'my-sidebar',
+      title: 'My sidebar',
+      url: require("sdk/self").data.url("sidebar.html")
+    });
+
+You can include JavaScript and CSS from the HTML as you would with any web
+page, for example using `<script>` and `<link>` tags containing a path
+relative to the HTML file itself.
+
+<pre class="brush: html">
+
+&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+  &lt;head&gt;
+    &lt;link href="stuff.css" type="text/css" rel="stylesheet"&gt;
+  &lt;/head&gt;
+  &lt;body&gt;
+    &lt;script type="text/javascript" src="stuff.js"&gt;&lt;/script&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
+
+</pre>
+
+You can update the sidebar's content by setting the sidebar's `url`
+property. This will change the sidebar's content across all windows.
+
+## Communicating with sidebar scripts ##
+
+You can't directly access your sidebar's content from your main add-on code,
+but you can send messages between your main add-on code and scripts loaded
+into your sidebar.
+
+On the sidebar end of the conversation, sidebar scripts get a global
+variable `addon` that contains a `port` for sending and receiving
+messages.
+
+On the add-on side, you must listen for the sidebar's `attach` event,
+which is triggered whenever the DOM for a new sidebar instance is loaded
+and its scripts are attached. This message passes a `worker` object into
+the listener function, and you can use that worker to communicate with the
+script loaded into the new sidebar instance.
+
+Here's a simple but complete add-on that shows how to set up communication
+between main.js and a script in a sidebar:
+
+The HTML file includes just a script, "sidebar.js":
+
+<pre class="brush: html">
+
+&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+  &lt;body&gt;
+    Content for my sidebar
+    &lt;script type="text/javascript" src="sidebar.js"&gt;&lt;/script&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
+
+</pre>
+
+The "sidebar.js" file sends a `ready` message to main.js using `port.emit()`,
+and adds a listener to the `init` message that logs the message payload.
+
+    addon.port.emit("ready");
+    addon.port.on("init", sayStuff);
+
+    function sayStuff(message) {
+      console.log("got the message '" + message + "'" );
+    }
+
+The "main.js" file creates a sidebar object and adds a listener to its
+`attach` event. The listener listens for the `ready` message from the
+sidebar script, and responds with an `init` message:
+
+    var sidebar = require("sdk/ui/sidebar").Sidebar({
+      id: 'my-sidebar',
+      title: 'My sidebar',
+      url: require("sdk/self").data.url("sidebar.html"),
+      onAttach: function (worker) {
+        worker.port.on("ready", function() {
+          worker.port.emit("init", "message from main.js");
+        });
+      }
+    });
+
+Try running the add-on, and showing the sidebar using the
+"View->Sidebar->My sidebar" menu item. You should see console output like:
+
+<pre>
+example-add-on: got the message 'message from main.js'
+</pre>
+
+You *can't* send the sidebar script
+messages in the `attach` event listener, because the script may not be
+initialized yet. It's safer, as in this example, to have the script
+message "main.js" as soon as it is loaded, and have "main.js" listen
+for that message before responding.
+
+<api name="Sidebar">
+@class
+The Sidebar object. Once a sidebar has been created it can be shown and hidden
+in the active window using its
+[`show()`](modules/sdk/ui/sidebar.html#show()) and
+[`hide()`](modules/sdk/ui/sidebar.html#hide()) methods.
+Once a sidebar is no longer needed it can be
+destroyed using [`dispose()`](modules/sdk/ui/sidebar.html#dispose()).
+
+<api name="Sidebar">
+@constructor
+Creates a sidebar.
+
+     var sidebar = require("sdk/ui/sidebar").Sidebar({
+    id: 'my-sidebar',
+    title: 'My sidebar',
+    url: require("sdk/self").data.url("sidebar.html"),
+    onAttach: function (worker) {
+      console.log("attaching");
+    },
+    onShow: function () {
+      console.log("showing");
+    },
+    onHide: function () {
+      console.log("hiding");
+    },
+    onDetach: function () {
+      console.log("detaching");
+    }
+    });
+
+@param options {object}
+  Options for the sidebar, with the following keys:
+  @prop id {string}
+    The `id` of the sidebar. This used to identify this sidebar in its chrome window. It must be unique.
+  @prop title {string}
+A title for the sidebar. This will be used for the label for your sidebar
+in the "Sidebar" submenu in Firefox, and will be shown at the top of your
+sidebar when it is open.
+  @prop url {string}
+    The URL of the content to load in the sidebar. This must be a local URL (typically, loaded from the "data" folder using `self.data.url()`).
+  @prop [onAttach] {function}
+    Listener for the sidebar's `attach` event.
+  @prop [onDetach] {function}
+    Listener for the sidebar's `detach` event.
+  @prop [onShow] {function}
+    Listener for the sidebar's `show` event.
+  @prop [onHide] {function}
+    Listener for the sidebar's `hide` event.
+</api>
+
+<api name="id">
+@property {string}
+The id of the sidebar. This used to identify this sidebar in its chrome window. It must be unique.
+</api>
+
+<api name="title">
+@property {string}
+The title of the sidebar. This will be used for the label for your sidebar
+in the "Sidebar" submenu in Firefox, and will be shown at the top of your
+sidebar when it is open.
+</api>
+
+<api name="url">
+@property {string}
+    The URL of the content to load in the sidebar. This must be a local URL (typically, loaded from the "data" folder using `self.data.url()`).
+</api>
+
+<api name="dispose">
+@method
+Destroys the sidebar. Once destroyed, the sidebar can no longer be used.
+</api>
+
+<api name="show">
+@method
+Displays the sidebar in the active window.
+</api>
+
+<api name="hide">
+@method
+Hides the sidebar in the active window.
+</api>
+
+<api name="on">
+@method
+  Registers an event listener with the sidebar.
+@param type {string}
+  The type of event to listen for.
+@param listener {function}
+  The listener function that handles the event.
+</api>
+
+<api name="once">
+@method
+  Registers an event listener with the sidebar.
+  The difference between `on` and `once` is that
+  `on` will continue listening until it is
+  removed, whereas `once` is removed automatically
+  upon the first event it catches.
+@param type {string}
+  The type of event to listen for.
+@param listener {function}
+  The listener function that handles the event.
+</api>
+
+<api name="removeListener">
+@method
+  Unregisters/removes an event listener from the sidebar.
+@param type {string}
+  The type of event for which `listener` was registered.
+@param listener {function}
+  The listener function that was registered.
+</api>
+
+<api name="attach">
+@event
+This event is emitted when a worker is attached to a sidebar, as a result of any of the following:
+
+* calling the sidebar's [`show()`](modules/sdk/ui/sidebar.html#show()) method,
+when the sidebar is not shown in the currently active window
+* changing the sidebar's [`url`](modules/sdk/ui/sidebar.html#url) property
+* the user switching the sidebar on using the "Sidebar" submenu in Firefox,
+when the sidebar is not shown in the currently active window
+* the user opening a new window from a window that has the sidebar showing
+
+This is the event you should listen to if you need to communicate with the
+scripts loaded into the sidebar. It is passed a [`worker`](modules/sdk/content/worker.html)
+as an argument, which defines `port.emit()` and `port.on()` methods that you can use
+to send messages to, and receive messages from, scripts loaded into the sidebar.
+
+This code listens to `attach` and in the listener, starts listening to a message called "ready"
+from the script. When the listener receives the "ready" message it sends an "init" message to
+the script:
+
+    var sidebar = require("sdk/ui/sidebar").Sidebar({
+      id: 'my-sidebar',
+      title: 'My Sidebar',
+      url: require("sdk/self").data.url("sidebar.html"),
+      onAttach: function (worker) {
+        // listen for a "ready" message from the script
+        worker.port.on("ready", function() {
+          // send an "init" message to the script
+          worker.port.emit("init", "message from main.js");
+        });
+      }
+    });
+
+Here's the corresponding script, that sends "ready" as soon as it runs, and listens for
+the "init" message from main.js:
+
+    addon.port.emit("ready");
+    addon.port.on("init", sayStuff);
+
+    function sayStuff(message) {
+      console.log("got the message '" + message + "'" );
+    }
+
+You should not try to send messages to the script in your `attach` handler, because it's not
+guaranteed that the script is listening to them yet. It's safer to start by listening for a
+message from the script, as in this example.
+
+</api>
+
+<api name="detach">
+@event
+This event is emitted when a worker is detached from a sidebar, as a result of either of the following:
+
+* calling the sidebar's [`hide()`](modules/sdk/ui/sidebar.html#hide()) method,
+when the sidebar is being shown in the currently active window
+* the user switching the sidebar off using the "Sidebar" submenu in Firefox,
+when the sidebar is being shown in the currently active window
+
+The `detach` listener receives a [`worker`](modules/sdk/content/worker.html) object as a parameter.
+This object is the same as the worker passed into the corresponding `attach` event. After
+`detach`, this worker can no longer be used to communicate with the scripts in that sidebar
+instance, because it has been unloaded.
+
+If you listen to `attach`, and in the listener take a reference to the worker object that's
+passed into it, so you can send it messages later on, then you should probably listen to `detach`,
+and in its handler, remove your reference to the worker.
+
+Here's an add-on that adds each worker to an array in the `attach` handler, and makes sure
+that its references are cleaned up by listening to `detach` and removing workers as they are
+detached:
+
+    var workerArray = [];
+
+    function attachWorker(worker) {
+      workerArray.push(worker);
+    }
+
+    function detachWorker(worker) {
+      var index = workerArray.indexOf(worker);
+      if(index != -1) {
+        workerArray.splice(index, 1);
+      }
+    }
+
+    var sidebar = require("sdk/ui/sidebar").Sidebar({
+      id: 'my-sidebar',
+      title: 'My Sidebar',
+      url: require("sdk/self").data.url("sidebar.html"),
+      onAttach: attachWorker,
+      onDetach: detachWorker
+    });
+
+</api>
+
+<api name="show">
+@event
+This event is emitted when the sidebar is shown, as a result of any of the following:
+
+* calling the sidebar's [`show()`](modules/sdk/ui/sidebar.html#show()) method,
+when the sidebar is not shown in the currently active window
+* changing the sidebar's [`url`](modules/sdk/ui/sidebar.html#url) property
+* the user switching the sidebar on using the "Sidebar" submenu in Firefox,
+when the sidebar is not shown in the currently active window
+* the user opening a new window from a window that has the sidebar showing
+
+</api>
+
+<api name="hide">
+@event
+This event is emitted when the sidebar is hidden, as a result of either of the following:
+
+* calling the sidebar's [`hide()`](modules/sdk/ui/sidebar.html#hide()) method,
+when the sidebar is being shown in the currently active window
+* the user switching the sidebar off using the "Sidebar" submenu in Firefox,
+when the sidebar is being shown in the currently active window
+
+</api>
+
+</api>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d3ed4c3a31b5fb95c29d5a0123bd4a6c050fc206
GIT binary patch
literal 14961
zc$~GnWmHt(8#X+{z<@Ax4JAW|#L(S{2#82`BPc12BFqrdAqaxf(%oG{mq<%9fOL1m
z%kTfJ=fnGcf6s?=&f0t5wfA-Hb>C;N6Q-g50w0$e7XSd@zf@M#1OPC=kMC<ZpvOCX
z>7Vb94@_IRS8@PAMGW4p1r`7R0%)jdKL`B(eX#?a1YaJX+~P>SD|f|ow@`}n%Wy!R
znmUcXbvRWq8jf*1)p3dd*%bjzQa{F~zj$~4+4oFFWBXHjhvcjIKhx93@z<vOfbfh8
z1BdOO?wVbB=i>SwH-;{QYi`4h`Mn)ZMf~c3>dDueH|eGrvqO#jE%`OyT>R>08&TI)
zac4Q7PZjmn06Z1|o=`D>=tf&u<wq$^p9|n~KhJOVZk}lfG2nF7IRL=jQ5L7~aJo7-
zxG`Lu>g}>O)7U+M1^_;k)HbPj{*sRw*gQC~h-!AsyV*a#Je#?+H#@Nc0E7Sl!^9y`
zQBh;()6U&HT3T8FKspt*cyfLHaB+KkwI-u+NJ2u=vUI`D!7-BKKEAX*lB_e;nBe=_
z?_#~z&i6EH;u`VwJZ^A5sbb*zU>YtpRx`f!3IKR`xB>t)wr}s3FYoankjUuhy5yvT
z+dEx7J)msj-P!P;{To?1Irof-yt*Ou%1T4~KxRSZ(P&C!;U5qP6qwPITTqJX85lWx
zc(^~jy*a$RyqcVv`tWo3$1C96++2P^QR1)0-QC@wpkOO2D**uk2M5Q^qnp;&R=1Cc
zjLctl$$v{qO2)^>Ra8}H*3LXVJ^!t(CI9$QUS5%(pN~eP4V_LC5)=J`BezcO&L19n
zdU~{MPc9!GUK*dgFg($)KGA)5s%Cy-^5OLK{=x3ksiOX|x%+8NO-+4$y^z9|jrZwW
z?_CAmV|%|dnK#GI$g};6huzcr=H}+k&d#y1v5kW(S<U0=>FI@qg`0<mM>Gu%4qjYb
z9A7^i9Ua}?-JhPG4h#&euC88PUEe=Etgo-{@9(#_w{LH6_x1H%-`sR}cmMhG=jQhA
z>gMkE@86FTaesGref`*Tb9;OH@bECH2Cse83v<_0*U}RbgHsU*b76-Ddiok!JH8Qo
zrYucC%S?>*1cHeH02)@0h64b?hc6Z7w7qBdQlH3@=`|iiz5R5dz8^`-Mis?(FzhPO
zV34BL<M7_na{gBjOZW#7cASsTzX1i?Svou{h#8q#XQ_zQaO{<_iK(AF2{%$6Yo71#
z0@7{9y|VLs_p#{W^M<yLp2(!2In%4W`^m|gRB;`T;j%Wj!s`hyCAC-<`wpBYqo;9e
zp4)_A*Y|g)c2I`y_Q1+{eNE=b@)`^xCrN_Jc}-?FF|wy|9f&{#3EXpcK_&-v|Ne%?
z<a%h2z{&?&ECyxBMZjel+dj=NtXemu!i=7XVg@~7Bv8U3Q<KHP0cK!ZHx%IDdoexf
zV$`>iRYP4KdBxE65+p9}*XbJs=6rZ;7KJis9Kv*QdhnluWzLOUogSa7p>jl`Xg+`u
zVhsiIg3NyPzg)K1iP>|FiAgaE%$0a5ON4`M2?^y!aH8nio>ntGc(t)?Ol55S?L+BX
z5^_N`tYq0Q6BeYZ$}Y~J&u6ws?As3NoL+^`_X$hjW@+QUKfP1!ZS6;KJcPTL^I<b#
zTDgd1qCJa7d?4&!Y{*r_XDR7PJiZjXbxUUbNwjpN!avm6k9XbhQX>7Io}V*Sa18so
z;%&4}ImywvkO`C(eo)=@MY;=`z5$b!?kvdhAH50g(6fa5rV{M?kf}YIij)2<xi<F%
z+Y4_U(J7mOmfqQ{YHTW7Knyl76M=Y`3+dD!tXq@02b_t5FRvw>aBRQ(<EzYyaa(Lu
zmo+4qMZCDaGTi3pGc~0ux$DSa6xRP>=>oUg-QSPy|3U`8;JsF>=TU%k#3%nwt9^w&
zM|Gm5ksv&<KCA3mtcFXQ;;A+PTzS{$nmlqk|BkXOPc=^lW9di1{IS>4?f2@BO={Za
zAKKvgR+B?pC=`G^o}r=f@1_o)(s_0OhwTiyBh3h#IPm5Pc6Oq&N-*&RG%~LT-FlP5
z*Qcok!9BJNc=o9~1IFuO&zIu&y!<GLo|M*sM8289?x)`(jq|R>Mr(!RwV=MG!NEJT
z7q36BMp3G;wH+yqoW8hp(ft18sM5jC1!8QI*1@a)o0>nsill7$OJP^n>&k8TDVrxe
zzunz&ftob(_E5r7TE|9b<@uLu8;?9z@LT(3qA;Y-o^dhrs|Zq>OVGs^ApNsB3i{3O
zGaVM@&TX9QkRlbxkU0%Gw}YQ>(!%aQi62##`@h#BPkWBhPH-eui={cv8Pm-w$A&HC
zTdcRLn%)n07jN9!6L6V=_>t6sX79TPRI{~$<04H^M|zbYnrf1PIYSK%jb9~%i?fDb
zyS44zlD~b?&n>Sp#rg1N1aJ2^f-+MLwkquTo@nPYpWFlc&_^?0rU4@yw&*)dcC*ZG
z?;0__J+=wMy|bj<DPc!D^W8IVtfwyaN;WiUc1>BYRxlIPjJl^BO3uR>PYjjRigl~4
zR8(E0O|5mC#h*PZ((kUeuSsrTBRQ!S)OGYttCh^v8l=}Z<fFR$-8)O3k~56I_}-&~
z1UGW>?U(hncL@fDlHtPAqV=NRI4ZN5{2OOtNs}S89c9M+XIH0B@Jlb5b7Nz;-Xxc>
zCyMX$`nbV$+tHaJqE-m9$T39qe15-HS67#|oggj?m0PmXt5ilkvJMiGXUc2TLgS^Q
z?);NPg3q;3)$cAh1%Fi8^15`c)ThSCCcB(Fj1B*OU9~8h`lW{<d_l~SRN_0K_f)0Z
z(_gT$SZ}L4yJloJ^(z&%TBUI;vj#|-o@tg+JQc4;fQl08pNE~`kzaW%75icZ178`Q
zE~j}Lq?;;KBvG*}eAK0)XF~_8(0qVS|Cv~iwOz4#o+hYZlvCOw?C$tj5M>@Dn0)0;
z1_c!fzQRplp}QK_c}6YhM|7>C7Oto!e?8IF-muZ__SHscBsi^r4_6F51Wd$bsxL&<
zV~6t9+Y5p@*OXo@PQ|mmo_Yce;v^v@C9lXLN{kH?Pc0>j`w*h!_Qkwhp&fxaV%!LW
z$X)w<Iz8br!GH)8)7SuLbDhTiSZoB-2%D|Qn^f*bHsCeL!lyGi4)G!vP!=u$S3yp_
z_|(7OJxA(A8g4(Xx15vdp~WjWYee`vioGN%;}C{JMk|m-4<Y}AYI1rX9l@9YpD2xj
z3pP(ec)BI5ONAsWn1dp{yvwfw$sJB1<ThQFGT0#b(L`SSIBzaP!|Z4<Z00L**;moV
zSZTJT;x5IulB_;{3=a}piEAE9f?_yK2c#)*xt1@X`hNkQ$(N2`O;8ENqoT$!>rI-_
ztiRT5mnB<?d;W8}Ko$^!Iu*<K{XHuWd+%1MN^*9NWJvg2|2aokT{VvkD;_JdJ10j3
zD&(}JBJ%AcRuAW$yCz${wWO-oWpE<cHZHg`i>}Iw^C}{;`{ZJfU26Ax9_|{U9(8(B
z!djSIJxG<4^_RB0cqSi<i*UGp5$S$`mD&fFcjEDxhXKF-jS`osD!;gQS0$|y;P>jH
z9n_qC{aHEvnHu{)jRy8g$n&r+0<SDFSPn)BEfM4??VuI>qji|RPndh5M%<C$xS^(|
zAtMWqHCDW#X4V(p`s+B?^>X&EhLa8#o*y>f(<Qv3DR4JJI}AKIOVjaAjM?X=t;kuJ
zO-F=so3okWwb@;&#JCa2quVb-#a$Zxq?iyDl}ZxT;{Xc=iCnenUwXc1=KcSz81FCU
zi9bb(9JD;rgypc&@&5&;=q|3Z4$f7|oP2UI5uJn{ii<OEEBVLn&h><=_CHFpP@%$t
zS;A&;U*8lEZms6@<%%&YDlu+me*NVG=`n;u3IBY3If*Wv>-iRz@Lf6Yk%}z=bx)tE
zrfRchHkX9RnVRw)#otp8WhdSx9C6xf<ts7_N01F~Z=f*YqJ(E1b!IrTzJ8>oxFIVj
zl7VwcOL80L#k1b`M&y&_!hed2xdiGb1p>vCgb{{R&kHB65;&4y##@qK+3X}+mYw;{
z=t_KK0gH@BMB)c!_)*zZ@aZIksR1eNeNAVgl7{$~+vCFf+nuF#U$<R$#vcc?6szmY
zhe5L6NRq0=$oEvXukbU_1&>Shba^M(u#>P@Rb;>R%NQFxfl?ZvuPZy+^$X~F<~=D3
zXxm9`o<Z#JKTM=r{ok!OS|?0REu&IbK0CZmdxGLwQgIu9{QKo?d;1fsTP}uH@~wBj
zPu<`zryH*3oR`0R4c?+(MdPX9y<wj_3Dud1^A@nQyyZ9dX)!amD6ws3WYu^sl5tC7
z&w}-um^_S%h*g+X>Fbt(eT|jT;neGXtRAo>8C4CIL8Mt}`jQRxV~mcD4U7t+<=K{f
z6w*_(Rw&%(Q}{cii5l$LI*we-v{JayHOTH7d2!r4BO08a(R>wg75Zbn&uHGC9T{62
zky@DX{uiE@N<NbzyqyM1QwaJ5YTQHk@Z44u6}ho&IQmvqL(VkBo*O0g^9qOO@BLnS
z7EqB5&U3%~we6^={>;66caT2*uhU2Vnx><{c(abOvfFPp!nR%p%>wFLEt}Mpzshwb
zJ1C96=v9?}UGn!TVfWlY%Dh;1C#aj5`NL0aGQMWGvuZT<RmS9vyfSl}3$Cf4<XT~S
zm95iqEg#d%HQ6Af%P-kN@P+A9uDkK*dne~k8EjWFo1w|U%KVj+U8lzHMYI}_r<L92
zLoE+buDg~c>b^J9H^=mqqMxbWdyThP(V8Dl>ZQk_j#-2b&00b#XIInjrt&~UDMPW!
zDLgH#ft%xPC|2CCe{~CM^beORoZws0F7&qf6Te0Ot@P3XYA&%Z^q}0B?Zde9XW{wN
zweqhD5JSVUR2hUOK6uoO27EyS`J&xCoM^#!8jW(a+Hc{**=`+ONVUorY4071I%F_w
zQTt7xP(M+<7&{*IU7XAPAZc#b%H?l{If4iV23L{eyfqe%&rDPA8uT4WGcxvUkj5@^
z^G3Mv`b19CfER|J%KmLE(@FXb{^5F>$22ry^p<Oo7MJ94<cvdU`%X4<{q=|h*eklB
zZmvJz8_=Z9)XDQxf>|5EcNJw9j|GYKVTN|}_1Sqk26!(ha2X&^53gSz0ulpohEv{L
z2)ugrjL{P<8VT1(7aJ#FHg5AQnVZB8ff~CN5+Qf?_H4x^SolQ$f&5k9qAt}__HzHl
zP%18qrocCMCC8&F)uIBP*(<{VxSV)7Bs}O0l`F}UB+Z1{Uu@umuI0@_pR_WEauc0t
z4j1??U;VyuO(2IXt|8uD&IU27@q3{V6v3|u3cQ(_D-j1iyAn)-40F4-{cYDsxh4VZ
zAhepTjg7r}>1W6}ntAv67auO*TlsUop)pZ{!0&qSp)YoB?eERrHpv8~YHn4*IFEh4
zB&Q4hgIe1b730f0soUGwu(%*}F#kTKwH(>k{y<c{uAQ<^7pNdT$E15%s><Ki!{zhf
zv(7@-jj(9-{pw@vWw%@<kS-RBX_3tFPGZqAE%l224G#htB`0d~bsYDxq9QUjB;adT
zb(sZp12q7(86Cu6=j99gp^bie5N_`Cxw<zH0?g!iGcklx$L$o-k;s#2*l}qcHyGoq
zW~7`CRt2{HbJ5iaclT>F6vT!LMHm8S1CCvDKoE4DlXUgLZ-pCEekQ_CmyJLt6?n++
za9eX%>rW&z1CkW~0-)@JUjucE8Hk9C^$GYk-E%pgy$jQLQ|cKihmi<DpjIXN#0OI`
zl8}FsmP*YO;jk|jzYnOkKCW@|lDT#jeS1G3$5Mk+%GC?i7I#Lo1FSN1pS^0aLK6p7
z8DS(Y{|b2iRE`4T=LK6%@EGkfb%Dml@*w0KeolgTa}4pJF0|U7jmK!BK$X101Wk=n
z9(ROX(m`B}fN#dgQnv&9bhjjNuMV-ut|_Y7+VI~8!JwnVJSeja{hOAE<ULoBNLCw$
zq`+fb%}2bP3jF((eT_iIM=z<sU@REWKzW@5Xp$c4^U7^YY=0BfH74nHU{L?LFPI{0
z$ljNVFd?S5mPy~8nb)#!fT2g$=H{|5o0CgB-j#tZBo=;J=s+G?t<=c?b~j^-JSB5g
z?v^#NqX#YfylKpf9-i>Q-Eq%Nq~ISf@8mK}y)PJ)Qs+;ewM-Zo&y(r@{hQmJt^lcq
zM{+woiw#N1qpiluR%RdK7EWH!XVnn60ym6>3FR!Yb2;o;q|jOd&W8*@d|1`WeOM5+
z{a14Fs+NF49<CvVwQqKtAn>pjRsodA%B6AoUn^~U4pkHf7Hhn!tNHeDcS>IY(ORSe
zWFYmK&=j7ljM!)KDM5BuD%>B6(0U5&+}e5ELRt%#P`Oe!EI^7bX9A~A&qHI={fLG8
zO9C~H^w=By3R=t9WryIb;}ZdYcQdKm)y@nVK@ayNW6iwD6vtBZBY8zn4$V32skgVs
z=6=u=8TrRfbvn1*W!oJE7bND0X{Fy<h;Fv|1F-*?<Nr`x&mas7EZO}?NbEAQ^b(ps
zIb~C$0GUlGSYKZc=*iliD2x}GSW@Psl``jk084JT4qmebJHGtF)<#8eZAQCm5ewO4
zPvZE*A}ot1fj#5Zck!y%r<wDl0yCb&;f&0`2|F-v{=Gek6F1nA5yISJ<!p%`zu{YR
z`>7pKiX$S);eh#lV5zBCQpR_<@{q28Mvy88et9W-6fuNk4#Pj_66-Kew}MQ;wbBeI
z>CgfX7i#q_fgDF-apbrPw)m~_B;EsLynZJp^%m5_x5~Z_2Px-wF-r~k`co%_x007$
ze)|m@_oQ&R%Gx=B9e+iM7lhiKRcjy`Y3^ceqCI_{t<WmhFa2qkPVFT<d-y-1!1Z<E
zJbVl+w$gd_TSFD}Zm7D)N$b71ai==lV)cdHbgJ8E!#QnY>OH#yI}?FNTTI#y*#)O2
zL^(Xdo8aw8(}~+3V#tqdzEA-<1uCs$uFG-E!H=^81R{#bp4<=-x@1>Jswx=uz3NPT
zCmHx5llLW@g?F|*z=xC%$J<Y(`W^Xg&2a-ABq{0{g>;jp#Vps`m^Je$%@2R-Zi11d
zIwQ)D)EzOo4E{#(y<&U=<sR?1NXc6+v7s3FOFJo9I&TQR7s1?jYv*~*WXAj|9dz~3
zy&^j0^8T2zlwoCR{DcsG(L?j+EE@TjGo39f&cD|or2$f@GBM!PYd`c;oV2#s2;b(q
z%jW4EBJ8XxW0Fp|?PiD`uIz{9`9xpX{|@zQ49a|PoFjcJl{U*jJ46Axk0J2LbmP+}
zZ>n=96MR})nhQ1lHZlGNO?b5Oyd7;Bw>%m_890(qX+eFdllF=4rOXARs8(9YGKGDj
znXz&0$!J6=<1qGFh%Im0bCY^mKKOYTpo$$haQMA_;HG&VP_nD0G&ZmwrZcqq;on8E
zs;MUo=k0kc4JMqlpZ-&jRc84b_gmrpb4BOLPzAhrG?R2vRQT(33Q<`yTskX_^0!O7
z7)C;r%{^x{D92AxKi}2L2vZ7zu$~(yyObOj)1g`dE)3cMQXHLe76SS>t~Y?vZy$pF
z7H7KMS_^~Mx@{J1O_aW2bcQGcHYYbsYeG<Q3nNpWH2qff68a5<F7U6qo{%a6|GJUT
z0J3dN&}!tZq}ePQT$OH73xh^LV{*)9kT95ScLxqT*<#y!G5yyNhx@Bt5V%!}&yGvq
zAU~~}>kVaT&NF%FLqKPJ>t7%Ty9x``n77&d^=kzn0{ZP$oA)vXsvU9fwqXJ|NG`{y
zRjkn3uuC)pKzQmS>*bL{fmTa;W^0c~pTy57;SNDHCX5Uaa05^PH3UMA)}SGDW~5Oq
z5?FEA|11qT8(7V8xctcz`Gdh9{u5rI5*;|-F)wXdP6@Yz_<-LF*r&}**V`}e_B^Ly
zkfHhcGZSX-<kaPbc}t^^6ec~wpFf&L5Kj!tSF!@w$bZ^rX;K-J!G+%P;V!TT_NwWp
zDg9l=-So8}ZMq%Hsa*ShufP7e-zJEx`GRv8>GkO79zN(cwao|9|1VJb!2Fp+d{}km
zC(9^a-R*8@5Go#HwHE_?Q@hK!2Dba!^&8xxr7T+QLgUNWAb};RPYC%Y38uv+;PbXz
zYn>@N=iV}{bsDS0YBIAh4OnB$B3ftZn+mkoyOIW;40TZ^$Ar`7|Ih^Vpw;%pI2^Bk
z|Eueq*`fplx{Z`{&>rTrUC~aEZ?w`0UKo=|(21nYb$$F3T)6VK9i1|WqlWTdIlcA4
zMHQ9Z$IwACKGww~<L7)<96iw(i!hp@vzTHzgeo$CLwplye|B>zqxrnYPbp5uq7|+V
z%7Wfrk3k)lns#J6GC$Lo94#=>4z0gqHg9)BoWtq}p>WcR-vkx}LDH)gUZdw{(nE3N
z*i*WsK=7fIl}GMD+)IWbhjId59SKd&oQ$Rxfs5vEX+89lr!W41z#9)ZUSPBmT?%U_
zKGUGObb59h#9lZafALB21^r-dnio~Y3o{n2)9nbN+p9kh@$&HUWkBJzxlGKq+SkjV
z1CG=%dmGyhT~G7&rLcfRk68bh@kXG7F@J=?MlcO9@Xzwp*DFa9NL#OigifH1hW|)1
z+R6Q8^_sabG#>|>7Kc3q+P;TvemFNiKnN>);7y4;Ae}5=egO>BHn-?!8>E1N-Dij~
zUA_aJcbo|%<h3PCG|(^kY3g5oNte2~yFhDQ%{Mr=T_K&k|IIo3Pv4f<Z#x4}>59<l
zJFCpnHIZ+T6t8b4?;G9ihSw+EN){gIBcpzczLO}fq6sjU6$PB(gW5lwb1q#Sn7k=7
z+3IYr9{BDfl7L$!<w02`h)GQx0@o5ZBdeVz*N}|_S{{mAOr+nRvrVMmAW$0pNtr7{
zz<}5Y`Vc6sX%}tD7f!~i&(7P7Z#^d~L7%W7!nwJ_hykX5{y6bCi6zu-jdei2dJM0K
zz0{Jthpp)AL79hR%4iHcFb_C@m=C=NWD9|6lMCwU>4@ZYgbWFb#Lr{uh=}Ow<Ot^p
zQ_32QOc`r0=&vb{5Ki>dh?FAv`o!+MyvQ_QJ+kQbU}c0`KYQ(3I|G<4zffI&E8C`4
zrTOSz*rNL}b5ej)c81W4tA~00i6Z-WC`eD!j_(gJD`OWA%;xBU1$J^>`}eZ{_ZUdt
zC3reucpwFr<+5|9Z74VQ+c#4ZuY9eivy<kXKPc?<wI;S3p<Ur(vS;*xKZz_y7Jgfq
zQ=~jO|C|Axe!cLGLH#2E$j(ehdjeOr^ohJ3*IIi(fC2=*Q!KMGy7;l+sE7Qt*9YI2
zUM?BITT3JQH|sO~_HWj>+E?dMsF8qJdAQw6=V$DN!wm^}q%Jk|#p}I{*pg2kks>>6
zvMl4i_@2z!1HO{o^z#|%0JbGQ0`nhWOgNa;C1w;yK}%(v$Or@k-TNxC1-%Y4$Kc&}
zb5nowuhQemJeRP%0CffNk4tmiwuIZrY5i!-=-^g!w4`%C>@;vng%7rlXzbWq^^&SB
z^E~|Ij+94Qj)b?L;~-;#eIRK>aGXJcMlsy=6IxngA$d}|Ax>{gQ`6>}>$Rs<c|}8h
z;(svHjm+_4F=_^kwI}p3AH-JvE-PI-UXi?QkgX3l^L&?s`|zXsN94I7eX^Rf!2?UX
z5H~b~@iT=Ywr?|!Tp{s~E|l6f4O@|BQ3N$!#yhG6D@YfQy7Lqbn|Rk_{(%#{adWlR
z`Hbr97Ewoe_I6ZOMt4xx!lCxU%HLSfBUbp5d&@fyc9n~}F-Kg2%EJHfcDs8Ir#WAS
z1$l9=WSG)&%IF|eW;l(_%ky<GQ8Dm!zupuJQ5&F|*br0jzlg4*J_#KSO!$E5yyDD`
zxjkZDnpjz45%akW)=@@LKsZ^<^a2uDn=+B$`dySi@$ZQUqv?|&G8@5zyQo@Gqb|(k
zS8Yb$C$MoP&sQ@4?kW&;MU5z8SIvUp>}=2s-saYiFI)Udy#9t0wL3v~95;yxIr@-#
zR5~UyPatYid}!+6SeY0fUZ*a${O+5dFGSB)K@VIKlGevrUAB_2IEB^|QW2u1%xdBv
zXDA1_#`g^kg4uUZA8YI+H=Qf#*2(79^7844wRLE$eCD9_eq1@&F+vm~`lzrQ@6p8{
z#|WF93=h|I$!0kw(zq*YhKvM3`3Uca!b|h45tH1Nj*hd<pta8oMzofPtyMKo&rsNh
zmY=>i{2CO@Kyj%JC9(`wPEIpa48Psw4&4)W3u$=4u1ZEXUxMKy^=D!f)zaN}fCpOV
zQ(Me}x_c1wI+-BkC@GdrHt(XG0A;W52Th~he9uinfp-B|AD9G3QH@--_>ROfmxzA>
zELx97)8fgGOcfQW?JQq}5PacDnf7DWeL}xO$2HEgL#``v_#ym7s`pD<8RhSec3ZK=
z<*e6<tmZEDjWxf1g+-WDORPiGL?LkL@_YC`(&MR|b=Vvc_<(n4pPM6y5Q=d-t7J*~
zKj?1%V6_A*Dk|!`b~Auqq!tmz_~CrqF32g{nb+jF9c&Dhi&w`^Cny3W3BZ@(0A8mN
zYpYs<?Te;W?*nIJB0K+Po`TodQvY_$zBRtT5l&%?8i}*}FQDR%w${^vJU9*4%nDJU
zS874b;$5iSYEKl+JSnI`2u370g9*4;k^~=ymVNp7VH~Tu&)Z@A&4IJ{JVMSaaLW2~
zXM4yL=tG*Ie9@!@Q#JD_stY9{EPFj3iJ)b04MlAXPf-ws$mvnuotlVK8~5@aRf!J<
z*iDSmxu4e>F>ZSJ7d;P)S%Zbj;g-<Q^1NUBE&E-aOy2$4x|H=!i~sxn6Emg5dsc_7
z0Nkv-<g*m=JXo@ba9W3tUC@*OvOZoB0;5z+e)L^ycxr#4>2JW4*QDy^h;;Mn*=MoR
z#s0BSrE3;bBj=iK@knd3S|;9nM!`{u;D9WZ{AgnQ!*5KVO?iswAs!{Y5QOhEw{^Gz
zM4v6Zni9=9mU?zJn-;LIqdj0VBw;fv7mK8+`SR4hxK=-;Vs^oEkpy^Jim`NNk{kUE
z>>7*!V#(q?1VjG0cUE2yC~?~D>`2i3oHN{}e*Z)5ZD8WRA?|M3XFUM*zDgubSac^|
z+SpB=tb#{i^u8?i^(Zdiv@h4!b4kiUC2o<t1c(jYRB5}xK6&D#QR$%zi?sC=4Lj?w
zYUj^r*&=#NNO3W8VFyXckESV7RbAfeUj29HoG8V=2EJ&#c)?PP7k*l*$pmg8`IM=I
zYrLn8&trqXi)jd|d&z}Y_K805Z;Q}P!$q6H(avINIMDkKg%!F|de(^n-0R%6Z2d5x
zbyo!jW-E){A2r%}$~5n{fM0={A56erQ$JP@8$}Mwdu{mIorJic^~HI$14bco?b~(%
zsN$JNF%4!}e1N!)#VGTxn0%%_5f)uR`)O*NMG)#$gVvn;`%*i<G%b@Fv2p6%rJ6cD
z$bFz?xqXb3J*;0Y=>W)10toEQ1iL7<o0|xR$R(><#ildykY(Rxvs5gK&UEd6JKi~W
zNft>3@@jOb93Cxe>p6nT!S<Q86nrNhad}^>j$?W%z77;lUVW-5IzF-3qfQ~0-wjE4
zXC`;mdR;}U4_ubf-}|GK>#>3THP&Rk&tRr3{k=hh_)Wz}4oI}Wn!wd%C6-2R`_AHF
zC|&HaPo9IQInhrio#)>?lM}nBp9a4qdbag<Z@IF-9SkSZ#r0cG$p-3!`r37_Ueoa~
zc`mluOgT8}``sJ%o%I>KCjS<+c0gd{_@u(Wr=V~0(@gnojboK*jCAYuLL$}Gefi~e
zcA1^>c&XQ1q2#zNx762X27zB_kc8;Huuu~3g(gR=6UCVi-VZds>_czGAS=d{pk|Be
z4%t~7YG_mc(&r1Q=1Q60t!6dOt#gW>JEU%<d{H+GOJd_#^MGPhX^e_qi~7Q_th#Uz
zS8(xC&zF{`QR}8{_64?s+frQg7)~kiwpTk|pR-Z&Kn%G|1eE!Z;Z;*&+WUOf^t0<(
z^-oZEcEtMKsfV*U;nKssM(0y81XOar(F3Ft^{PUTV~-zyY2d|o=NgGTmRHy!&OcSy
z;?K|*QK`3QD|RkebsXW7>GJf>a0S-ue)Jw*fE0cr#pe#kpVHV&RQX_Y{Aez2vEw%!
zA;8TA%^{Njq>MFx>9Oq<(T(l8fAT?$Q865*MKVU)ApYqcZ*YKeKfbAZZf0pB9ZzK?
zc#LN}uKCwlj9-PLZLEbMk;Fv=Z~JGwQa|eX78W(Ip35S7`Bj@_C`;)g1dZpkPx-UG
zq?3c9!*T5Q6UI`s{`vMX@{=P?k`NL6GID}Q5gNNB6-rnE7T%k!GIPLx`v#({td{*P
zp~zN&@%QCty_Q4|2?GPryYKH_E-vr><6X%OSbgm>hp|83-2Xo11)+0!eMqV=v2h!B
z8<b#w$)%gsogm~{-~A>Hfda(%5vCdwC&{$s*BoVEgz;k@>B3?TJNKOM35Sc4*Up+X
zZC5RPEy_HPJust;d(8)9Fp`Xa{ZSsDsm1MLV56zpDHNF?6#Iz6e|LgAEn%tH!!5%B
zCexk6EJdiYzr$;`VO}Ec=bjYXVB0XzyKPDWJ;YKSrTU#xm7Bn2(44P;>D=Rl->S~&
z7_(M=Ejl@oS;52d#Bb1o1!GXk)0d0;Zw=jMtZHD;2GS_iJBOl+fvO6u2Lpf7yg5JX
zdY)T>MY7vxsg;}5RF7L@tuNniJXZQ0Pd&vx9DFgP&9-QHwEx(E)sB`I_4fTKV9Wn8
zpo4soGD9(m6kh^I0$)w!W?t58oWYQPxlQuRkB>*4LDbxM^tDPa6edFB^K<b?3No=s
z3;1fr=ms(E?ah1t{JdbvU*&1Tgc{3#j~NW+-n_wYX_7N=dD05Qkw|s`K+q8;t@T|$
zuLGH+m%*hf->*YP7fO)TgVoFjZV{P{UIcJaFDIHJ|8J#!*W2@yD>&edktkn`!w*g$
zlKrmc+!Eu-dAqjg@2uvB`{jx)7RB1pZ<}iyCS)R=OhrVEAK}g2e{*|Pw~;18A1%Gu
zJ{IBIPPLxKwz!a?o{<hJT^jziWA4cr)QD@p9)~XxsDHPPIq!vbWwF;VlQ}$R+H!2G
zaQt;dKPs;f`}4B=Y`)hNaAba^|HD1>XX+`+o?4rT+i%H_=q)9l(_-t@GNZ5m(cTK1
z$T<Fz-_0tM$WD<XV9K0mHsfpzC(0c=&b#`eN6!Ks8!=<qvLD)8d!4EE-I__T*J-?5
z7>>C(d#PlXcfE+ScY?BuSNWOkdFEh+w}8w?uMN+%)N}@WHAS2H_(kxTpS>AWapB%h
z$?Z0|&8s7-1)6i18N4uJ&2!<7k1(XWesyy*uE$0g+$LQ5ay!va@a0|K)@<nB_@1B!
z8~#p(9xzM<z;p7u;-aOiX4rq60<`M<rPxONHgCjnQnn?3(&ny)0ZdbJ+{FN<7uR}?
zir_pf#N9s2Wu+sa(`7=zhP+h&&!>E5`%qp%@mZogJOE7vUvx7NGfE??Lhe3d=(hOR
z;dPxlc9}mZ1a=q~^z_5I^FQnYN2UAUpnI#CmoKO@Ck-0fT@7A1mc`Q|QZ5fUc&unG
zW7n;vex7sLt#tAJ6nD?kcFx)g=V|k3O5zTokd`>1^6tl&&C+Sc@e8u|>y?ziTUtc8
z2$i8F=x};&Eq(8d{$iH-Gl9$aXx{D{5p~<V83*Lu#{Ki0i%sNkbRJo-MrBk2<`3OR
zP&teFVz+BuwqaZikLd?t3fCHTw${`NFG}py3qs`J!Td%hpCz`>34!UVA?3no#b#=~
z&|w<=Ilnwcrp+|b!iPRvyw5<m!_rSW1n}Ja?-4cV0O$!_#@9?8ov`2!&lBB(1uk$5
zTgrN4>2OLa;?2E;7p0<OeRr7JGmxDbS^c3n&=0ZoQ<=mm{nxw^1$ct0rJ`NvvSIQ}
z0AF9M8q}9z$;wjxMel&Y5#&11-xvF^93VOLi$d`OO4p){<PcXBCTI4b1nDc{fwYpU
zSg)8$kiTZI_fXp5_*(9;;`NPym!mSC44k~Tc@u7qR@o+4OIh>FAgg>#LeoXxbnzA;
zkZ(vp*Af0vS9{mbb)gOjC*<NBDkLymP85|9*n0npFNx5P)b+JNg|h%Tf3o^>Jk|m-
z0fUZYT4o+@GR`0DVDHYPAIT=(^*x)0WD{iCL54R2EMlufAe@bAWFUYY22~DqTS&Ma
zXtX<BB1hb}Ozn2wvo2N>;H1fAlo6jYd@1t}1eNbSL1S_n{)><Fjl8Xclk*CPbr^_g
z*jLUv2^oe|6f;DP{P?K|)wabOa0k9oKRHq0E_J<G7Qd;k>b4r0zytR@fBHfJO6b4J
z^H!oB=`BWZ9WtFH&J^V!ae6>JDUfjw-Kw(Q%TqeO7D2V+ob}f{BLw3|J(Db^&-x=r
z06KO1O85TFy$0TEj87^tQRF@YdlF!uVO_>a-IsYQm#o5DmK4T;1-=>d9kG{Pp-XZh
z0{Yz6c6Dz5g!VxrNAPN`xxmy!3tQ`HmM{*?7MWneC@a@`Bj)}7BNR|itZ#PU*&tR|
zx+){@hg`^lKP~~SgwQVhug{OD&6(bfC#SpG-}k#EpenrVBg<+gcxqku$he(tcZHoB
zWfwop?@4nr1~Uc*1~a$=KpjW|db*_RVWEabPhDGwQm8Hm&z}QwCKCyEr2oP+$5wdG
z_o@0^p?znG#jtY(;t(U`9jr9G{8Db8Dob4vSq={>+{MIg{2DNk)$>+f4j0u9r=6t<
zDj6R9SX}ql^7N6j&uT<q-}}TAo+)~{?RDY9%4O9$iSSc5F^;HnG8!u~UIifsTSw<*
zwoFP;NR)#^)?}dkshmp6pr_e}H<WQX4Dn|>o-H)S*b<VV2G1hYpL)Jz_jLbv4A;8s
z!UDG_{swIbVN~C8830pfQd#b`75ugYxbtzUy(<|c^wM|aN$Kmand2|50k43sfz%+?
zN!eO(U<a_po~upX52>S5prcTxy-8VulbY*BMq~x6Ch(H8kJXGH!{V*dO{Jc{#TE7O
z8Q}~&Ev=wsP=58Q#1lxaLn)_+i38M-4acnDbCI$qD#!SA6B?>2EsB-^+#Ll%L)vox
zYJ4rkJikP>1e)V}6AZjYI}`Z@guK*Sv*s5B<pacD!-zuJT}<qW3N%X`?S6ixn9QRU
zm$s_=w;lM-9PD+06$rC6G3riWjSxc&I;gzM2jBuQc3Uhru|C^oyAi>#G??`{LwRiR
z&qMN+4a{LO+9ABcN5x4s!c*-G^56g@X^yU*pwSS}RU<wy<~?pbj~a|{c5Lp8{Fe8w
zdj|k1o6)YxTK_``he%D#dQBw(*KZdnkQrG&v~62#QZU=(-y^3(9YFHLCdB_(Z4$d7
zublQxN8_r%-{A~{K`WvwQ`Jz;6|K{D%x=uvLnez#T?Li2YI{5UxBER`pN8T~<bQPT
zG5y_Mir*N@e&9s%!Cb8$Ndjb0c1F=c-%n-|VHh%oMquhyfv=TyVsm_7|Ey-@#yvhh
zR7q%~*bUmAEm&=6qS4FluCOSqUYNAM_@nVWMKr+|o@JiPNzHFY{$W*Xm|Ac$+pZ!g
ztlo9R>=!na`gK~sTIf1eVT&QVAWXf~2}aAV7JQ`mjbL|dU~(-*4nc1qRe>$$9Z!&p
z7z|+00g)ge860R1csb8|e6GanOBBu!)iGy_G;@}_e`s8jhkiT-7T##bA3uCKz==Rs
z<Pv33sBG-}GVn$4E-wQM0U+Bffg<=5j*jBJY<UfY?iMmaoj=&`66}gNZ=VkD$%vX5
zddCVWc#i|Z#3)rHT0=xk;$uSWuA(EZYj@VLnFMbXl))@z#TpiOU)L!@fbYw4W(jYu
zJ3Z{%w=~HjZaxTq0V70#%zWTe*?#N_NkdXTv^;V;@R>0;u`*nzWA$d;y;Sn4YYq$p
z15?;Z!ep3wm;CQN%<HsByZ49QA+-IV5#YpRm-qy#7NCAr8oqxY)QA)UyO+szAT%`I
zFwb+_{aznnJdV?+<BoY3lgaU_I&j$N^wlSx;GsMd`LWh?c1&=hhk?DzEv)AJBZC))
zIqsKK%ZwMDuW*B_?S51kXTpYk2U7#EK=SxQ@~AcysunOI$=g662R{bEVx*8=8L>&>
zl!k$}?86vKLS-hUBZ<YP1+MX7gB(;^#Ll2!N(3<vyjcPZp$5qUbp{rqyo~^pVt;D)
zMW;6l@I;e53p0<tB?x&F(kIz@Lo&iI{qTbHe;GD`3V%{tYH15Y&1<SAmlfE0MIsX;
z$l)0}Ck&KZyp?$@F5P*dv&zS0M|b?k)@&qxn;JPW`UT>%!~s;8(dP*|*a>gyb+Ot^
zHJ8{3p9XUM38>EtefK65Xh`BR@j`y{L)nFWzhFuDCtqgT(5PaK0|F{^D#qXfcQ|iO
zRX)Is)(PO|&=K8(&&=f1Fm(IEj(c2-=OR5omr%#B$SnKGSY2*JOxCZoV)F|ciA|-*
zyn=#7IT}nR{EDT%28(xN%93y7CHOV$VIOMdZ&ndN>DIsTG0Ri_rz_`gJco7eLq?B>
z7#%ey<=CVRCk&g2(I5Rrww-^Ah$XdNNV6DEQ$tcQW+xjC%sf^m&reyGE8|K~=o-mb
zK4|n*`xZB$HN@H;W(1m{?wfkt^D2d6OOOuu|1|{y^#cQxpqIR(#Z6p;(EoM2F36VB
z{C@}jzhnpXL7T?G_(VUlS@Y^Pt?l8FC8!U(CczA;wHJkT`Jb#Uu0mgs;N3kN2_~AS
zkQUvlX-oYi@Lp%#>d7>VMXrpe(#_xb`T4Uql|n9YLZSpMMTiS^2DyteeM81DWUpdQ
z<@B+xxaU87>2C!#=IdptM=LOof43ATBx0FDL*Hzto?~4OJxBqt?}k*{pBV)rjRIqq
zDhAH)=8x~me$JP_bmIfR$mRyp2RmxtWy4}zU93%v|98MU7k#sfs^W>?0jt-51?6JY
zlB*+==`p41KRGOD^u#%7P2WWb7n?7VJ??4;v8!cw!u{YtuXom8H98y!V{R{Uc;%1e
zewlN>`F(05ta$b_fZIi-4@LZTD?Iq!GYX|4#wl6c$ElhR64GBuUev`a7`hdnx(JKY
zX+4QxQn9P!_+a;`?Q{dK3{O(ipqp0sN@NAN<8-JG*P?%G*}d(OG!%osl4bt<jnuiM
zK$HIl;X-TdK`$zI_n2jpv}d(|qzg7+J=QnX?lXnZy~}tA;%6sXQO<O^wTknX>y<gj
zq0}R$?0RY0{srm0H*=b&ny*j79UhR*f1gNq&Hh=Rx__JK;|o_i3liThTW%xJhC$%M
z^XK1R)@Bv3tS24_Kezt0bnJa#c;ocW9#Bz?@S~oot9AYbb+8C#FV12#y6#5WNoSC#
zU|u#qkf)v9TG<+w4Lm~317r_bFVic+Bkh8YG$QFB?J(KDM!rzv-!Cl4b^J?^`dvR|
zMv*~J$&F^HMYq&ZxPhzmWf3F-j2-4n4#H^iCy;Z6*Uy|s3mFX@!{o^(fB$zVPr^;c
zxF!*dDhHqZ{r<g(^pWz27`wL(PFmS;{kW>g3KY7}3QZa4V+_J-4`Cw!k4_qs>AqPY
z1J7OTi^sa#Ej8KuUi5k4s@H+bMk;S`toQDh<W@>&dW$2h-qmsRn)xKZ-ZLQ!ysOF>
zOxPd>K?$#XhZo@d({l8ZE2!3#Oj{mHGCQ(jQO-@2bNhFaa!4UPb-lg0GS;chV;tku
z%93XVbI7I50c90@50a+ry3y^~`$X|UQ(rRAU)vj6Yj0ntRFh3dsnvo(wcvf`N1;(_
zh*|&tq0(lcka90iogXeVdl0J3961$$N@n%y&De^>0+mD}tA#|zSJra^GM`5x<$Btu
zs0Ga_du$D9=6`@36?UlHBc>mD`O+S-@JH4x;dz1>zLT*OT<{;lYpB+}G(up8THgpH
zuvJCoOkQX-I2qjF`*)$xQY1Fq6Z!et-6^xNx#maH8)f9vFE)_k5?}~Wo1m~r-FU0j
zFSm;Png{%MbwBg?I6Osn7fg90zb=6i`mrW~^;mxs!P(hWO2mDBHQlMPEVoMqwOH2a
zroB68{Xil<%|Qf*KjL$M8mA7|@%M8(0w-h8Cykflf@RS20Q<hJ7Atou&>}Ssoq<Sz
z7=WPM7<zm^lsd)R7#KZj1L2xNSdQq9=)V%H_iRaZx04Q%`XNzZcB=A%?$;pH#h(-B
zF8P<3EP=ZGi=Mxw_!iFVb(Q}qd{3a5BTwV1VS)uSW-$5TMfgc<A8OJgTMqX1Uk?Ha
z;wX2FoZI>hiYtBRD=(naAiyOG+Sb<F9KB6+kL0m}HR@&DC4;cHegiOKHMIA5Tu1mC
zBa!C#inIthyFk-y)c1cHp0<8?5|8pk$)K@xu|zyf%<zDw{EPqG?pjA|AP^&Q!$pqz
zMZEvH8af2r`a>(40h=JEm{)4?{Le^7Mw%-EHW6!@y+ge{uSoEpGeqQgA1w)Sa5%Cl
z-|ec;n@rgEZt{aI3F>h%0uaIsIXx!dRx<vJaK{yy2$2oww_{#Na%+j83EApPm!jJB
zij-F4t9R6Zqwxcf=P*ZCfwM8bMm#H*IU@6R1I%5Sln~VC3Dw@sPSQX#f~R1~Cn+XG
zXFSry-QO`g!-3%_-aRY$M>t=(Jkpc5w6_TdqX$lN^~XgKVF~}p&WA3<{aBj*L3d*A
zvi!$!dh1!tV;rhIvWbz%;^hdGGF4zY7|i6zmn6$q58{Igxkjca%3wuNiQ)3q2U^0B
zmWMFQ!=1T<CVw)?SNGjg59cT84?BPS&Uqh>c^_UR(mdfmwUxQ~oBnXSw10&qsruC8
z;d9-?EOp?KRc{m%6m8XI773#T;3x-h)e&2>=a_f#ZYn6Yo6px*Fxtb<o!Svav>9SB
zS|SqbhA@}_!wV#aAlP>j9sR*80uGf)>qUISWx~P!hH2pRD;<QXjKa}mJ%mP5!qLv;
z<=Rjw64A?UDL_ZtT}nA@@H1xe$3IeS09>W$9)9E^d!&D8ulcQaYjo&3Kn(hUkU=hy
zX6varK<zQ#j{@o`{Nqc41Ghu7wTVP!iDWMT_&7nu%e+IsiE)s!$o%)R@Qj2&Y~?+G
z7{YbglvytE=aVXrp`@?Mzyd1Cc0GJ{u)Y}jH_!!6EelvswToR-m&Z{e#m(nK4`3Ry
zODd`aV|x?qQwv?!O1xmi#l$w)hxPsW%JgE<XKwS2*AbZ{?AsGbFe3pGCd^_YfAp8q
zpzAZa+{H81pmupAIk?(W_7Q(D+{$_N3(#ZEDGw~6(uY49bd{9@kl{co=arN4F5cj<
zV+HV``C#kjT&}XRmy>&SOMdhOmGdgGC2fpE`t0RB<`}b}_e8On9gk~3y1q+Ch7pay
z2W|(>f-H%8q!7#iJXsJ>K2ZYagjC=x8v7{#CzJ#FfX0l*cnY#4>>&*Vye1;TGT7%(
z1aJX=V4x`U;j*7(Wf6spS+eG_Yo?7q-*Z(w7E!N}SfGDshGwhw4q!=uUAbXw$g&U)
zy}0?lbe|kd1J;3X1;AiWf*w_|#Wm1kQs8z$ak$z|0=X_G6-bM5V!IG^xTJj{HzX7d
zEC!|A3>&P<#XJ27L9iq~p<(Y`MoM#MZ~*pI*;Aw4era%}pZxX1j6U8Eo5eDv|9<Cu
N`CMJGRNg$`{{i6TD#QQ)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8a69a3eb2d9f17c66d5470c66949c5508fdae868
GIT binary patch
literal 120085
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
L7=3gx$`1QK1_1$_
--- a/addon-sdk/source/examples/library-detector/package.json
+++ b/addon-sdk/source/examples/library-detector/package.json
@@ -1,9 +1,9 @@
 {
     "name": "library-detector-sdk",
     "license": "MPL 2.0",
     "author": "",
     "version": "0.1",
-    "fullName": "library-detector-sdk",
+    "title": "library-detector-sdk",
     "id": "jid1-R4rSVNkBANnvGQ",
     "description": "a basic add-on"
 }
--- a/addon-sdk/source/lib/sdk/content/symbiont.js
+++ b/addon-sdk/source/lib/sdk/content/symbiont.js
@@ -10,17 +10,18 @@ module.metadata = {
 const { Worker } = require('./worker');
 const { Loader } = require('./loader');
 const hiddenFrames = require('../frame/hidden-frame');
 const observers = require('../deprecated/observer-service');
 const unload = require('../system/unload');
 const { getDocShell } = require("../frame/utils");
 const { ignoreWindow } = require('../private-browsing/utils');
 
-const assetsURI = require('../self').data.url();
+// Everything coming from add-on's xpi considered an asset.
+const assetsURI = require('../self').data.url().replace(/data\/$/, "");
 
 /**
  * This trait is layered on top of `Worker` and in contrast to symbiont
  * Worker constructor requires `content` option that represents content
  * that will be loaded in the provided frame, if frame is not provided
  * Worker will create hidden one.
  */
 const Symbiont = Worker.resolve({
--- a/addon-sdk/source/lib/sdk/io/buffer.js
+++ b/addon-sdk/source/lib/sdk/io/buffer.js
@@ -1,55 +1,105 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
+
+'use strict';
 
 module.metadata = {
-  "stability": "experimental"
+  'stability': 'experimental'
 };
 
+/*
+ * Encodings supported by TextEncoder/Decoder:
+ * utf-8, utf-16le, utf-16be
+ * http://encoding.spec.whatwg.org/#interface-textencoder
+ *
+ * Node however supports the following encodings:
+ * ascii, utf-8, utf-16le, usc2, base64, hex
+ */
 
-const { Cu } = require("chrome");
-const { TextEncoder, TextDecoder } = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
+const { Cu } = require('chrome');
+const { isNumber } = require('sdk/lang/type');
+const { TextEncoder, TextDecoder } = Cu.import('resource://gre/modules/commonjs/toolkit/loader.js', {});
 
 exports.TextEncoder = TextEncoder;
 exports.TextDecoder = TextDecoder;
 
+/**
+ * Use WeakMaps to work around Bug 929146, which prevents us from adding
+ * getters or values to typed arrays
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=929146
+ */
+const parents = new WeakMap();
+const views = new WeakMap();
 
-function Buffer(subject, encoding) {
-    var type = typeof(subject);
-    switch (type) {
-      case "number":
-        // Create typed array of the given size if number.
-        return Uint8Array(subject > 0 ? Math.floor(subject) : 0);
-      case "string":
-        // If string encode it and use buffer for the returned Uint8Array
-        // to create a local patched version that acts like node buffer.
-        encoding = encoding || "utf8";
-        return Uint8Array(TextEncoder(encoding).encode(subject).buffer);
-      case "object":
-        // If array or alike just make a copy with a local patched prototype.
+function Buffer(subject, encoding /*, bufferLength */) {
+
+  // Allow invocation without `new` constructor
+  if (!(this instanceof Buffer))
+    return new Buffer(subject, encoding, arguments[2]);
+
+  var type = typeof(subject);
+
+  switch (type) {
+    case 'number':
+      // Create typed array of the given size if number.
+      try {
+        let buffer = Uint8Array(subject > 0 ? Math.floor(subject) : 0);
+        return buffer;
+      } catch (e) {
+        if (/size and count too large/.test(e.message) ||
+            /invalid arguments/.test(e.message))
+          throw new RangeError('Could not instantiate buffer: size of buffer may be too large');
+        else
+          throw new Error('Could not instantiate buffer');
+      }
+      break;
+    case 'string':
+      // If string encode it and use buffer for the returned Uint8Array
+      // to create a local patched version that acts like node buffer.
+      encoding = encoding || 'utf8';
+      return Uint8Array(TextEncoder(encoding).encode(subject).buffer);
+    case 'object':
+      // This form of the constructor uses the form of
+      // Uint8Array(buffer, offset, length);
+      // So we can instantiate a typed array within the constructor
+      // to inherit the appropriate properties, where both the
+      // `subject` and newly instantiated buffer share the same underlying
+      // data structure.
+      if (arguments.length === 3)
+        return Uint8Array(subject, encoding, arguments[2]);
+      // If array or alike just make a copy with a local patched prototype.
+      else
         return Uint8Array(subject);
-     default:
-        throw new TypeError("must start with number, buffer, array or string");
-    }
+    default:
+      throw new TypeError('must start with number, buffer, array or string');
+  }
 }
 exports.Buffer = Buffer;
 
 // Tests if `value` is a Buffer.
 Buffer.isBuffer = value => value instanceof Buffer
 
 // Returns true if the encoding is a valid encoding argument & false otherwise
-Buffer.isEncoding = encoding => !!ENCODINGS[String(encoding).toLowerCase()]
+Buffer.isEncoding = function (encoding) {
+  if (!encoding) return false;
+  try {
+    TextDecoder(encoding);
+  } catch(e) {
+    return false;
+  }
+  return true;
+}
 
 // Gives the actual byte length of a string. encoding defaults to 'utf8'.
 // This is not the same as String.prototype.length since that returns the
 // number of characters in a string.
-Buffer.byteLength = (value, encoding = "utf8") =>
+Buffer.byteLength = (value, encoding = 'utf8') =>
   TextEncoder(encoding).encode(value).byteLength
 
 // Direct copy of the nodejs's buffer implementation:
 // https://github.com/joyent/node/blob/b255f4c10a80343f9ce1cee56d0288361429e214/lib/buffer.js#L146-L177
 Buffer.concat = function(list, length) {
   if (!Array.isArray(list))
     throw new TypeError('Usage: Buffer.concat(list[, length])');
 
@@ -80,180 +130,217 @@ Buffer.concat = function(list, length) {
     pos += buf.length;
   }
 
   return buffer;
 };
 
 // Node buffer is very much like Uint8Array although it has bunch of methods
 // that typically can be used in combination with `DataView` while preserving
-// access by index. Since in SDK echo module has it's own set of bult-ins it
+// access by index. Since in SDK each module has it's own set of bult-ins it
 // ok to patch ours to make it nodejs Buffer compatible.
 Buffer.prototype = Uint8Array.prototype;
 Object.defineProperties(Buffer.prototype, {
+  parent: {
+    get: function() { return parents.get(this, undefined); }
+  },
   view: {
-    get: function() this._view || (this._view = DataView(this.buffer))
+    get: function () {
+      let view = views.get(this, undefined);
+      if (view) return view;
+      view = DataView(this.buffer);
+      views.set(this, view);
+      return view;
+    }
   },
   toString: {
     value: function(encoding, start, end) {
-      encoding = !!encoding ? (encoding + '').toLowerCase() : "utf8";
+      encoding = !!encoding ? (encoding + '').toLowerCase() : 'utf8';
       start = Math.max(0, ~~start);
       end = Math.min(this.length, end === void(0) ? this.length : ~~end);
       return TextDecoder(encoding).decode(this.subarray(start, end));
     }
   },
   toJSON: {
-    value: function() ({ type: "Buffer", data: Array.slice(this, 0) })
+    value: function() {
+      return { type: 'Buffer', data: Array.slice(this, 0) };
+    }
   },
   get: {
-    value: function(offset) this[offset]
+    value: function(offset) {
+      return this[offset];
+    }
   },
   set: {
-    value: function(offset, value) this[offset] = value
+    value: function(offset, value) { this[offset] = value; }
   },
   copy: {
-    value: function(target, offset, start, end)
-      Uint8Array.set(target, this.subarray(start, end), offset)
+    value: function(target, offset, start, end) {
+      let length = this.length;
+      let targetLength = target.length;
+      offset = isNumber(offset) ? offset : 0;
+      start = isNumber(start) ? start : 0;
+
+      if (start < 0)
+        throw new RangeError('sourceStart is outside of valid range');
+      if (end < 0)
+        throw new RangeError('sourceEnd is outside of valid range');
+
+      // If sourceStart > sourceEnd, or targetStart > targetLength,
+      // zero bytes copied
+      if (start > end ||
+          offset > targetLength
+          )
+        return 0;
+
+      // If `end` is not defined, or if it is defined
+      // but would overflow `target`, redefine `end`
+      // so we can copy as much as we can
+      if (end - start > targetLength - offset ||
+          end == null) {
+        let remainingTarget = targetLength - offset;
+        let remainingSource = length - start;
+        if (remainingSource <= remainingTarget)
+          end = length;
+        else
+          end = start + remainingTarget;
+      }
+
+      Uint8Array.set(target, this.subarray(start, end), offset);
+      return end - start;
+    }
   },
   slice: {
-    value: Buffer.prototype.subarray
+    value: function(start, end) {
+      let length = this.length;
+      start = ~~start;
+      end = end != null ? end : length;
+
+      if (start < 0) {
+        start += length;
+        if (start < 0) start = 0;
+      } else if (start > length)
+        start = length;
+
+      if (end < 0) {
+        end += length;
+        if (end < 0) end = 0;
+      } else if (end > length)
+        end = length;
+
+      if (end < start)
+        end = start;
+
+      // This instantiation uses the Uint8Array(buffer, offset, length) version
+      // of construction to share the same underling data structure
+      let buffer = new Buffer(this.buffer, start, end - start);
+
+      // If buffer has a value, assign its parent value to the
+      // buffer it shares its underlying structure with. If a slice of
+      // a slice, then use the root structure
+      if (buffer.length > 0)
+        parents.set(buffer, this.parent || this);
+
+      return buffer;
+    }
   },
   write: {
-    value: function(string, offset, length, encoding = "utf8") {
-      if (typeof(offset) === "string")
+    value: function(string, offset, length, encoding = 'utf8') {
+      // write(string, encoding);
+      if (typeof(offset) === 'string' && Number.isNaN(parseInt(offset))) {
         ([offset, length, encoding]) = [0, null, offset];
-      else if (typeof(length) === "string")
+      }
+      // write(string, offset, encoding);
+      else if (typeof(length) === 'string')
         ([length, encoding]) = [null, length];
 
+      if (offset < 0 || offset > this.length)
+        throw new RangeError('offset is outside of valid range');
+
       offset = ~~offset;
-      length = length || this.length - offset;
+
+      // Clamp length if it would overflow buffer, or if its
+      // undefined
+      if (length == null || length + offset > this.length)
+        length = this.length - offset;
+
       let buffer = TextEncoder(encoding).encode(string);
       let result = Math.min(buffer.length, length);
       if (buffer.length !== length)
         buffer = buffer.subarray(0, length);
+
       Uint8Array.set(this, buffer, offset);
       return result;
     }
   },
   fill: {
     value: function fill(value, start, end) {
+      let length = this.length;
       value = value || 0;
       start = start || 0;
-      end = end || this.length;
+      end = end || length;
 
-      if (typeof(value) === "string")
+      if (typeof(value) === 'string')
         value = value.charCodeAt(0);
-      if (typeof(value) !== "number" || isNaN(value))
-        throw TypeError("value is not a number");
+      if (typeof(value) !== 'number' || isNaN(value))
+        throw TypeError('value is not a number');
       if (end < start)
-        throw new RangeError("end < start");
+        throw new RangeError('end < start');
 
       // Fill 0 bytes; we're done
       if (end === start)
         return 0;
-      if (this.length == 0)
+      if (length == 0)
         return 0;
 
-      if (start < 0 || start >= this.length)
-        throw RangeError("start out of bounds");
+      if (start < 0 || start >= length)
+        throw RangeError('start out of bounds');
 
-      if (end < 0 || end > this.length)
-        throw RangeError("end out of bounds");
+      if (end < 0 || end > length)
+        throw RangeError('end out of bounds');
 
       let index = start;
       while (index < end) this[index++] = value;
     }
   }
 });
 
 // Define nodejs Buffer's getter and setter functions that just proxy
 // to internal DataView's equivalent methods.
-[["readUInt16LE", "getUint16", true],
- ["readUInt16BE", "getUint16", false],
- ["readInt16LE", "getInt16", true],
- ["readInt16BE", "getInt16", false],
- ["readUInt32LE", "getInt32", true],
- ["readUInt32BE", "getInt32", false],
- ["readInt32LE", "getInt32", true],
- ["readInt32BE", "getInt32", false],
- ["readFloatLE", "getFloat32", true],
- ["readFloatBE", "getFloat32", false],
- ["readDoubleLE", "getFloat64", true],
- ["readDoubleBE", "getFloat64", false],
- ["readUInt8", "getUint8"],
- ["readInt8", "getInt8"]].forEach(([alias, name, littleEndian]) => {
+
+// TODO do we need to check architecture to see if it's default big/little endian?
+[['readUInt16LE', 'getUint16', true],
+ ['readUInt16BE', 'getUint16', false],
+ ['readInt16LE', 'getInt16', true],
+ ['readInt16BE', 'getInt16', false],
+ ['readUInt32LE', 'getUint32', true],
+ ['readUInt32BE', 'getUint32', false],
+ ['readInt32LE', 'getInt32', true],
+ ['readInt32BE', 'getInt32', false],
+ ['readFloatLE', 'getFloat32', true],
+ ['readFloatBE', 'getFloat32', false],
+ ['readDoubleLE', 'getFloat64', true],
+ ['readDoubleBE', 'getFloat64', false],
+ ['readUInt8', 'getUint8'],
+ ['readInt8', 'getInt8']].forEach(([alias, name, littleEndian]) => {
   Object.defineProperty(Buffer.prototype, alias, {
     value: function(offset) this.view[name](offset, littleEndian)
   });
 });
 
-[["writeUInt16LE", "setUint16", true],
- ["writeUInt16BE", "setUint16", false],
- ["writeInt16LE", "setInt16", true],
- ["writeInt16BE", "setInt16", false],
- ["writeUInt32LE", "setUint32", true],
- ["writeUInt32BE", "setUint32", false],
- ["writeInt32LE", "setInt32", true],
- ["writeInt32BE", "setInt32", false],
- ["writeFloatLE", "setFloat32", true],
- ["writeFloatBE", "setFloat32", false],
- ["writeDoubleLE", "setFloat64", true],
- ["writeDoubleBE", "setFloat64", false],
- ["writeUInt8", "setUint8"],
- ["writeInt8", "setInt8"]].forEach(([alias, name, littleEndian]) => {
+[['writeUInt16LE', 'setUint16', true],
+ ['writeUInt16BE', 'setUint16', false],
+ ['writeInt16LE', 'setInt16', true],
+ ['writeInt16BE', 'setInt16', false],
+ ['writeUInt32LE', 'setUint32', true],
+ ['writeUInt32BE', 'setUint32', false],
+ ['writeInt32LE', 'setInt32', true],
+ ['writeInt32BE', 'setInt32', false],
+ ['writeFloatLE', 'setFloat32', true],
+ ['writeFloatBE', 'setFloat32', false],
+ ['writeDoubleLE', 'setFloat64', true],
+ ['writeDoubleBE', 'setFloat64', false],
+ ['writeUInt8', 'setUint8'],
+ ['writeInt8', 'setInt8']].forEach(([alias, name, littleEndian]) => {
   Object.defineProperty(Buffer.prototype, alias, {
     value: function(value, offset) this.view[name](offset, value, littleEndian)
   });
 });
-
-
-// List of supported encodings taken from:
-// http://mxr.mozilla.org/mozilla-central/source/dom/encoding/labelsencodings.properties
-const ENCODINGS = { "unicode-1-1-utf-8": 1, "utf-8": 1, "utf8": 1,
-  "866": 1, "cp866": 1, "csibm866": 1, "ibm866": 1, "csisolatin2": 1,
-  "iso-8859-2": 1, "iso-ir-101": 1, "iso8859-2": 1, "iso88592": 1,
-  "iso_8859-2": 1, "iso_8859-2:1987": 1, "l2": 1, "latin2": 1, "csisolatin3": 1,
-  "iso-8859-3": 1, "iso-ir-109": 1, "iso8859-3": 1, "iso88593": 1,
-  "iso_8859-3": 1, "iso_8859-3:1988": 1, "l3": 1, "latin3": 1, "csisolatin4": 1,
-  "iso-8859-4": 1, "iso-ir-110": 1, "iso8859-4": 1, "iso88594": 1,
-  "iso_8859-4": 1, "iso_8859-4:1988": 1, "l4": 1, "latin4": 1,
-  "csisolatincyrillic": 1, "cyrillic": 1, "iso-8859-5": 1, "iso-ir-144": 1,
-  "iso8859-5": 1, "iso88595": 1, "iso_8859-5": 1, "iso_8859-5:1988": 1,
-  "arabic": 1, "asmo-708": 1, "csiso88596e": 1, "csiso88596i": 1,
-  "csisolatinarabic": 1, "ecma-114": 1, "iso-8859-6": 1, "iso-8859-6-e": 1,
-  "iso-8859-6-i": 1, "iso-ir-127": 1, "iso8859-6": 1, "iso88596": 1,
-  "iso_8859-6": 1, "iso_8859-6:1987": 1, "csisolatingreek": 1, "ecma-118": 1,
-  "elot_928": 1, "greek": 1, "greek8": 1, "iso-8859-7": 1, "iso-ir-126": 1,
-  "iso8859-7": 1, "iso88597": 1, "iso_8859-7": 1, "iso_8859-7:1987": 1,
-  "sun_eu_greek": 1, "csiso88598e": 1, "csisolatinhebrew": 1, "hebrew": 1,
-  "iso-8859-8": 1, "iso-8859-8-e": 1, "iso-ir-138": 1, "iso8859-8": 1,
-  "iso88598": 1, "iso_8859-8": 1, "iso_8859-8:1988": 1, "visual": 1,
-  "csiso88598i": 1, "iso-8859-8-i": 1, "logical": 1, "csisolatin6": 1,
-  "iso-8859-10": 1, "iso-ir-157": 1, "iso8859-10": 1, "iso885910": 1,
-  "l6": 1, "latin6": 1, "iso-8859-13": 1, "iso8859-13": 1, "iso885913": 1,
-  "iso-8859-14": 1, "iso8859-14": 1, "iso885914": 1, "csisolatin9": 1,
-  "iso-8859-15": 1, "iso8859-15": 1, "iso885915": 1, "iso_8859-15": 1,
-  "l9": 1, "iso-8859-16": 1, "cskoi8r": 1, "koi": 1, "koi8": 1, "koi8-r": 1,
-  "koi8_r": 1, "koi8-u": 1, "csmacintosh": 1, "mac": 1, "macintosh": 1,
-  "x-mac-roman": 1, "dos-874": 1, "iso-8859-11": 1, "iso8859-11": 1,
-  "iso885911": 1, "tis-620": 1, "windows-874": 1, "cp1250": 1,
-  "windows-1250": 1, "x-cp1250": 1, "cp1251": 1, "windows-1251": 1,
-  "x-cp1251": 1, "ansi_x3.4-1968": 1, "ascii": 1, "cp1252": 1, "cp819": 1,
-  "csisolatin1": 1, "ibm819": 1, "iso-8859-1": 1, "iso-ir-100": 1,
-  "iso8859-1": 1, "iso88591": 1, "iso_8859-1": 1, "iso_8859-1:1987": 1,
-  "l1": 1, "latin1": 1, "us-ascii": 1, "windows-1252": 1, "x-cp1252": 1,
-  "cp1253": 1, "windows-1253": 1, "x-cp1253": 1, "cp1254": 1, "csisolatin5": 1,
-  "iso-8859-9": 1, "iso-ir-148": 1, "iso8859-9": 1, "iso88599": 1,
-  "iso_8859-9": 1, "iso_8859-9:1989": 1, "l5": 1, "latin5": 1,
-  "windows-1254": 1, "x-cp1254": 1, "cp1255": 1, "windows-1255": 1,
-  "x-cp1255": 1, "cp1256": 1, "windows-1256": 1, "x-cp1256": 1, "cp1257": 1,
-  "windows-1257": 1, "x-cp1257": 1, "cp1258": 1, "windows-1258": 1,
-  "x-cp1258": 1, "x-mac-cyrillic": 1, "x-mac-ukrainian": 1, "chinese": 1,
-  "csgb2312": 1, "csiso58gb231280": 1, "gb2312": 1, "gb_2312": 1,
-  "gb_2312-80": 1, "gbk": 1, "iso-ir-58": 1, "x-gbk": 1, "gb18030": 1,
-  "hz-gb-2312": 1, "big5": 1, "big5-hkscs": 1, "cn-big5": 1, "csbig5": 1,
-  "x-x-big5": 1, "cseucpkdfmtjapanese": 1, "euc-jp": 1, "x-euc-jp": 1,
-  "csiso2022jp": 1, "iso-2022-jp": 1, "csshiftjis": 1, "ms_kanji": 1,
-  "shift-jis": 1, "shift_jis": 1, "sjis": 1, "windows-31j": 1, "x-sjis": 1,
-  "cseuckr": 1, "csksc56011987": 1, "euc-kr": 1, "iso-ir-149": 1, "korean": 1,
-  "ks_c_5601-1987": 1, "ks_c_5601-1989": 1, "ksc5601": 1, "ksc_5601": 1,
-  "windows-949": 1, "csiso2022kr": 1, "iso-2022-kr": 1, "utf-16": 1,
-  "utf-16le": 1, "utf-16be": 1, "x-user-defined": 1 };
--- a/addon-sdk/source/lib/sdk/io/fs.js
+++ b/addon-sdk/source/lib/sdk/io/fs.js
@@ -806,22 +806,17 @@ function readFile(path, encoding, callba
     encoding = null
   }
 
   let buffer = null;
   try {
     let readStream = new ReadStream(path);
     readStream.on("data", function(data) {
       if (!buffer) buffer = data;
-      else {
-        let bufferred = buffer
-        buffer = new Buffer(buffer.length + data.length);
-        bufferred.copy(buffer, 0);
-        data.copy(buffer, bufferred.length);
-      }
+      else buffer = Buffer.concat([buffer, data], 2);
     });
     readStream.on("error", function onError(error) {
       callback(error);
     });
     readStream.on("end", function onEnd() {
       // Note: Need to destroy before invoking a callback
       // so that file descriptor is released.
       readStream.destroy();
--- a/addon-sdk/source/lib/sdk/io/stream.js
+++ b/addon-sdk/source/lib/sdk/io/stream.js
@@ -134,17 +134,17 @@ const StreamListener = Class({
   },
 
   // Next three methods are part of `nsIStreamListener` interface and are
   // invoked by `nsIInputStreamPump.asyncRead`.
   onDataAvailable: function(request, context, input, offset, count) {
     let stream = this.stream;
     let buffer = new ArrayBuffer(count);
     nsIBinaryInputStream(stream).readArrayBuffer(count, buffer);
-    emit(stream, "data", new Buffer(buffer, stream.encoding));
+    emit(stream, "data", new Buffer(buffer));
   },
 
   // Next two methods implement `nsIRequestObserver` interface and are invoked
   // by `nsIInputStreamPump.asyncRead`.
   onStartRequest: function() {},
   // Called to signify the end of an asynchronous request. We only care to
   // discover errors.
   onStopRequest: function(request, context, status) {
--- a/addon-sdk/source/lib/sdk/system/events.js
+++ b/addon-sdk/source/lib/sdk/system/events.js
@@ -28,18 +28,30 @@ const Subject = Class({
       object: object
     };
   },
   getHelperForLanguage: function() {},
   getInterfaces: function() {}
 });
 
 function emit(type, event) {
-  let subject = 'subject' in event ? Subject(event.subject) : null;
-  let data = 'data' in event ? event.data : null;
+  // From bug 910599
+  // We must test to see if 'subject' or 'data' is a defined property
+  // of the event object, but also allow primitives to be passed in,
+  // which the `in` operator breaks, yet `null` is an object, hence
+  // the long conditional
+  let subject = event && typeof event === 'object' && 'subject' in event ?
+    Subject(event.subject) :
+    null;
+  let data = event && typeof event === 'object' ?
+    // An object either returns its `data` property or null
+    ('data' in event ? event.data : null) :
+    // All other types return themselves (and cast to strings/null
+    // via observer service)
+    event;
   notifyObservers(subject, type, data);
 }
 exports.emit = emit;
 
 const Observer = Class({
   extends: Unknown,
   initialize: function initialize(listener) {
     this.listener = listener;
--- a/addon-sdk/source/lib/sdk/ui/sidebar.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar.js
@@ -12,29 +12,32 @@ module.metadata = {
 
 const { Class } = require('../core/heritage');
 const { merge } = require('../util/object');
 const { Disposable } = require('../core/disposable');
 const { off, emit, setListeners } = require('../event/core');
 const { EventTarget } = require('../event/target');
 const { URL } = require('../url');
 const { add, remove, has, clear, iterator } = require('../lang/weak-set');
+const { id: addonID } = require('../self');
 const { WindowTracker } = require('../deprecated/window-utils');
 const { isShowing } = require('./sidebar/utils');
 const { isBrowser, getMostRecentBrowserWindow, windows, isWindowPrivate } = require('../window/utils');
 const { ns } = require('../core/namespace');
 const { remove: removeFromArray } = require('../util/array');
 const { show, hide, toggle } = require('./sidebar/actions');
 const { Worker: WorkerTrait } = require('../content/worker');
 const { contract: sidebarContract } = require('./sidebar/contract');
 const { create, dispose, updateTitle, updateURL, isSidebarShowing, showSidebar, hideSidebar } = require('./sidebar/view');
 const { defer } = require('../core/promise');
 const { models, views, viewsFor, modelFor } = require('./sidebar/namespace');
 const { isLocalURL } = require('../url');
 const { ensure } = require('../system/unload');
+const { identify } = require('./id');
+const { uuid } = require('../util/uuid');
 
 const Worker = WorkerTrait.resolve({
   _injectInDocument: '__injectInDocument'
 }).compose({
   get _injectInDocument() true
 });
 
 const sidebarNS = ns();
@@ -42,19 +45,26 @@ const sidebarNS = ns();
 const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
 
 let sidebars = {};
 
 const Sidebar = Class({
   implements: [ Disposable ],
   extends: EventTarget,
   setup: function(options) {
+    // inital validation for the model information
     let model = sidebarContract(options);
+
+    // save the model information
     models.set(this, model);
 
+    // generate an id if one was not provided
+    model.id = model.id || addonID + '-' + uuid();
+
+    // further validation for the title and url
     validateTitleAndURLCombo({}, this.title, this.url);
 
     const self = this;
     const internals = sidebarNS(self);
     const windowNS = internals.windowNS = ns();
 
     // see bug https://bugzilla.mozilla.org/show_bug.cgi?id=886148
     ensure(this, 'destroy');
@@ -114,23 +124,33 @@ const Sidebar = Class({
             function onWebPanelSidebarUnload() {
               windowNS(window).onWebPanelSidebarUnload = null;
 
               // uncheck the associated menuitem
               bar.setAttribute('checked', 'false');
 
               emit(self, 'hide', {});
               emit(self, 'detach', worker);
+              windowNS(window).worker = null;
             }
             windowNS(window).onWebPanelSidebarUnload = onWebPanelSidebarUnload;
             panelBrowser.contentWindow.addEventListener('unload', onWebPanelSidebarUnload, true);
 
             // check the associated menuitem
             bar.setAttribute('checked', 'true');
 
+            function onWebPanelSidebarReady() {
+              panelBrowser.contentWindow.removeEventListener('DOMContentLoaded', onWebPanelSidebarReady, false);
+              windowNS(window).onWebPanelSidebarReady = null;
+
+              emit(self, 'ready', worker);
+            }
+            windowNS(window).onWebPanelSidebarReady = onWebPanelSidebarReady;
+            panelBrowser.contentWindow.addEventListener('DOMContentLoaded', onWebPanelSidebarReady, false);
+
             function onWebPanelSidebarLoad() {
               panelBrowser.contentWindow.removeEventListener('load', onWebPanelSidebarLoad, true);
               windowNS(window).onWebPanelSidebarLoad = null;
 
               // TODO: decide if returning worker is acceptable..
               //emit(self, 'show', { worker: worker });
               emit(self, 'show', {});
             }
@@ -168,24 +188,29 @@ const Sidebar = Class({
         }
 
         let panelBrowser = sidebar && sidebar.contentDocument.getElementById(WEB_PANEL_BROWSER_ID);
         if (windowNS(window).onWebPanelSidebarCreated) {
           panelBrowser && panelBrowser.removeEventListener('DOMWindowCreated', windowNS(window).onWebPanelSidebarCreated, true);
           windowNS(window).onWebPanelSidebarCreated = null;
         }
 
+        if (windowNS(window).onWebPanelSidebarReady) {
+          panelBrowser && panelBrowser.contentWindow.removeEventListener('DOMContentLoaded', windowNS(window).onWebPanelSidebarReady, false);
+          windowNS(window).onWebPanelSidebarReady = null;
+        }
+
         if (windowNS(window).onWebPanelSidebarLoad) {
           panelBrowser && panelBrowser.contentWindow.removeEventListener('load', windowNS(window).onWebPanelSidebarLoad, true);
           windowNS(window).onWebPanelSidebarLoad = null;
         }
 
         if (windowNS(window).onWebPanelSidebarUnload) {
           panelBrowser && panelBrowser.contentWindow.removeEventListener('unload', windowNS(window).onWebPanelSidebarUnload, true);
-          windowNS(window).onWebPanelSidebarUnload = null;
+          windowNS(window).onWebPanelSidebarUnload();
         }
       }
     });
 
     views.set(this, bars);
 
     add(sidebars, this);
   },
@@ -203,20 +228,23 @@ const Sidebar = Class({
     updateTitle(this, v);
     return modelFor(this).title = v;
   },
   get url() (modelFor(this) || {}).url,
   set url(v) {
     // destroyed?
     if (!modelFor(this))
       return;
+
     // validation
     if (!isLocalURL(v))
       throw Error('the url must be a valid local url');
+
     validateTitleAndURLCombo(this, this.title, v);
+
     // do update
     updateURL(this, v);
     modelFor(this).url = v;
   },
   show: function() {
     return showSidebar(null, this);
   },
   hide: function() {
@@ -255,16 +283,20 @@ function validateTitleAndURLCombo(sideba
 
   return false;
 }
 
 isShowing.define(Sidebar, isSidebarShowing.bind(null, null));
 show.define(Sidebar, showSidebar.bind(null, null));
 hide.define(Sidebar, hideSidebar.bind(null, null));
 
+identify.define(Sidebar, function(sidebar) {
+  return sidebar.id;
+});
+
 function toggleSidebar(window, sidebar) {
   // TODO: make sure this is not private
   window = window || getMostRecentBrowserWindow();
   if (isSidebarShowing(window, sidebar)) {
     return hideSidebar(window, sidebar);
   }
   return showSidebar(window, sidebar);
 }
--- a/addon-sdk/source/lib/sdk/ui/sidebar/contract.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar/contract.js
@@ -4,24 +4,24 @@
 'use strict';
 
 const { contract } = require('../../util/contract');
 const { isValidURI, URL, isLocalURL } = require('../../url');
 const { isNil, isObject, isString } = require('../../lang/type');
 
 exports.contract = contract({
   id: {
-  	is: [ 'string' ],
+  	is: [ 'string', 'undefined' ],
   	ok: v => /^[a-z0-9-_]+$/i.test(v),
     msg: 'The option "id" must be a valid alphanumeric id (hyphens and ' +
          'underscores are allowed).'
   },
   title: {
   	is: [ 'string' ],
   	ok: v => v.length
   },
   url: {
     is: [ 'string' ],
     ok: v => isLocalURL(v),
     map: function(v) v.toString(),
-    msg: 'The option "url" must be a valid URI.'
+    msg: 'The option "url" must be a valid local URI.'
   }
 });
--- a/addon-sdk/source/lib/sdk/ui/sidebar/view.js
+++ b/addon-sdk/source/lib/sdk/ui/sidebar/view.js
@@ -67,17 +67,25 @@ function updateTitle(sidebar, title) {
     if (isSidebarShowing(window, sidebar)) {
       document.getElementById('sidebar-title').setAttribute('value', title);
     }
   }
 }
 exports.updateTitle = updateTitle;
 
 function updateURL(sidebar, url) {
+  let eleID = makeID(sidebar.id);
+
   for (let window of windows(null, { includePrivate: true })) {
+    // update the menuitem
+    let mi = window.document.getElementById(eleID);
+    if (mi) {
+      mi.setAttribute('sidebarurl', url)
+    }
+
     // update sidebar, if showing
     if (isSidebarShowing(window, sidebar)) {
       showSidebar(window, sidebar, url);
     }
   }
 }
 exports.updateURL = updateURL;
 
@@ -129,17 +137,20 @@ function isSidebarShowing(window, sideba
 exports.isSidebarShowing = isSidebarShowing;
 
 function showSidebar(window, sidebar, newURL) {
   window = window || getMostRecentBrowserWindow();
 
   let { promise, resolve, reject } = defer();
   let model = modelFor(sidebar);
 
-  if (!isPrivateBrowsingSupported && isWindowPrivate(window)) {
+  if (!newURL && isSidebarShowing(window, sidebar)) {
+    resolve({});
+  }
+  else if (!isPrivateBrowsingSupported && isWindowPrivate(window)) {
     reject(Error('You cannot show a sidebar on private windows'));
   }
   else {
     sidebar.once('show', resolve);
 
     let menuitem = window.document.getElementById(makeID(model.id));
     menuitem.setAttribute('checked', true);
 
--- a/addon-sdk/source/lib/sdk/window/helpers.js
+++ b/addon-sdk/source/lib/sdk/window/helpers.js
@@ -1,38 +1,33 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 const { defer } = require('../core/promise');
 const events = require('../system/events');
-const { setImmediate } = require('../timers');
 const { open: openWindow, onFocus, getToplevelWindow,
-        isInteractive } = require('./utils');
+        isInteractive, getOuterId } = require('./utils');
+const { Ci } = require("chrome");
 
 function open(uri, options) {
   return promise(openWindow.apply(null, arguments), 'load');
 }
 exports.open = open;
 
 function close(window) {
-  // We shouldn't wait for unload, as it is dispatched
-  // before the window is actually closed. 'domwindowclosed' isn't great either,
-  // because it's fired midway through window teardown (see bug 874502
-  // comment 15). We could go with xul-window-destroyed, but _that_ doesn't
-  // provide us with a subject by which to disambiguate notifications. So we
-  // end up just doing the dumb thing and round-tripping through the event loop
-  // with setImmediate.
   let deferred = defer();
   let toplevelWindow = getToplevelWindow(window);
-  events.on("domwindowclosed", function onclose({subject}) {
-    if (subject == toplevelWindow) {
-      events.off("domwindowclosed", onclose);
-      setImmediate(function() deferred.resolve(window));
+  let outerId = getOuterId(toplevelWindow);
+  events.on("outer-window-destroyed", function onclose({subject}) {
+    let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
+    if (id == outerId) {
+      events.off("outer-window-destroyed", onclose);
+      deferred.resolve();
     }
   }, true);
   window.close();
   return deferred.promise;
 }
 exports.close = close;
 
 function focus(window) {
--- a/addon-sdk/source/lib/sdk/window/utils.js
+++ b/addon-sdk/source/lib/sdk/window/utils.js
@@ -292,18 +292,17 @@ exports.openDialog = openDialog;
 function windows(type, options) {
   options = options || {};
   let list = [];
   let winEnum = WM.getEnumerator(type);
   while (winEnum.hasMoreElements()) {
     let window = winEnum.getNext().QueryInterface(Ci.nsIDOMWindow);
     // Only add non-private windows when pb permission isn't set,
     // unless an option forces the addition of them.
-    // XXXbz should this be checking window.closed?
-    if (options.includePrivate || !isWindowPrivate(window)) {
+    if (!window.closed && (options.includePrivate || !isWindowPrivate(window))) {
       list.push(window);
     }
   }
   return list;
 }
 exports.windows = windows;
 
 /**
--- a/addon-sdk/source/lib/toolkit/loader.js
+++ b/addon-sdk/source/lib/toolkit/loader.js
@@ -33,16 +33,17 @@ module.metadata = {
 
 const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu,
         results: Cr, manager: Cm } = Components;
 const systemPrincipal = CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')();
 const { loadSubScript } = Cc['@mozilla.org/moz/jssubscript-loader;1'].
                      getService(Ci.mozIJSSubScriptLoader);
 const { notifyObservers } = Cc['@mozilla.org/observer-service;1'].
                         getService(Ci.nsIObserverService);
+const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
 
 // Define some shortcuts.
 const bind = Function.call.bind(Function.bind);
 const getOwnPropertyNames = Object.getOwnPropertyNames;
 const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
 const define = Object.defineProperties;
 const prototypeOf = Object.getPrototypeOf;
 const create = Object.create;
@@ -152,16 +153,28 @@ var serializeStack = iced(function seria
     return frame.name + "@" +
            frame.fileName + ":" +
            frame.lineNumber + "\n" +
            stack;
   }, "");
 })
 exports.serializeStack = serializeStack
 
+function readURI(uri) {
+  let stream = NetUtil.newChannel(uri, 'UTF-8', null).open();
+  let count = stream.available();
+  let data = NetUtil.readInputStreamToString(stream, count, {
+    charset: 'UTF-8'
+  });
+
+  stream.close();
+
+  return data;
+}
+
 // Function takes set of options and returns a JS sandbox. Function may be
 // passed set of options:
 //  - `name`: A string value which identifies the sandbox in about:memory. Will
 //    throw exception if omitted.
 // - `principal`: String URI or `nsIPrincipal` for the sandbox. Defaults to
 //    system principal.
 // - `prototype`: Ancestor for the sandbox that will be created. Defaults to
 //    `{}`.
@@ -308,17 +321,21 @@ const load = iced(function load(loader, 
 
   return module;
 });
 exports.load = load;
 
 // Utility function to check if id is relative.
 function isRelative(id) { return id[0] === '.'; }
 // Utility function to normalize module `uri`s so they have `.js` extension.
-function normalize(uri) { return uri.substr(-3) === '.js' ? uri : uri + '.js'; }
+function normalize(uri) {
+  return isJSURI(uri) ? uri :
+         isJSONURI(uri) ? uri :
+         uri + '.js';
+}
 // Utility function to join paths. In common case `base` is a
 // `requirer.uri` but in some cases it may be `baseURI`. In order to
 // avoid complexity we require `baseURI` with a trailing `/`.
 const resolve = iced(function resolve(id, base) {
   if (!isRelative(id)) return id;
   let paths = id.split('/');
   let result = base.split('/');
   result.pop();
@@ -366,19 +383,41 @@ const Require = iced(function Require(lo
       throw Error('Module: Can not resolve "' + id + '" module required by ' +
                   requirer.id + ' located at ' + requirer.uri, requirer.uri);
 
     let module = null;
     // If module is already cached by loader then just use it.
     if (uri in modules) {
       module = modules[uri];
     }
-    // Otherwise load and cache it. We also freeze module to prevent it from
-    // further changes at runtime.
-    else {
+    else if (isJSONURI(uri)) {
+      let data;
+
+      // First attempt to load and parse json uri
+      // ex: `test.json`
+      // If that doesn't exist, check for `test.json.js`
+      // for node parity
+      try {
+        data = JSON.parse(readURI(uri));
+        module = modules[uri] = Module(requirement, uri);
+        module.exports = data;
+        freeze(module);
+      }
+      catch (err) {
+        // If error thrown from JSON parsing, throw that, do not
+        // attempt to find .json.js file
+        if (err && /JSON\.parse/.test(err.message))
+          throw err;
+        uri = uri + '.js';
+      }
+    }
+    // If not yet cached, load and cache it.
+    // We also freeze module to prevent it from further changes
+    // at runtime.
+    if (!(uri in modules)) {
       module = modules[uri] = Module(requirement, uri);
       freeze(load(loader, module));
     }
 
     return module.exports;
   }
   // Make `require.main === module` evaluate to true in main module scope.
   require.main = loader.main === requirer ? requirer : undefined;
@@ -499,10 +538,13 @@ const Loader = iced(function Loader(opti
         // Only set main if it has not being set yet!
         set: function(module) { main = main || module; }
       }
     }
   }));
 });
 exports.Loader = Loader;
 
+let isJSONURI = uri => uri.substr(-5) === '.json';
+let isJSURI = uri => uri.substr(-3) === '.js';
+
 });
 
--- a/addon-sdk/source/python-lib/cuddlefish/__init__.py
+++ b/addon-sdk/source/python-lib/cuddlefish/__init__.py
@@ -167,17 +167,17 @@ parser_groups = (
                                            " repository"),
                                      action="store_true",
                                      default=False,
                                      cmds=['run', 'test', 'testex', 'testpkgs',
                                            'testall'])),
         (("", "--strip-sdk",), dict(dest="bundle_sdk",
                                     help=("Do not ship SDK modules in the xpi"),
                                     action="store_false",
-                                    default=True,
+                                    default=False,
                                     cmds=['run', 'test', 'testex', 'testpkgs',
                                           'testall', 'xpi'])),
         (("", "--force-use-bundled-sdk",), dict(dest="force_use_bundled_sdk",
                                     help=("When --strip-sdk isn't passed, "
                                           "force using sdk modules shipped in "
                                           "the xpi instead of firefox ones"),
                                     action="store_true",
                                     default=False,
@@ -549,31 +549,31 @@ def initializer(env_root, args, out=sys.
     for d in ['lib','data','test','doc']:
         os.mkdir(os.path.join(path,d))
         print >>out, '*', d, 'directory created'
     open(os.path.join(path,'README.md'),'w').write('')
     print >>out, '* README.md written'
     jid = create_jid()
     print >>out, '* generated jID automatically:', jid
     open(os.path.join(path,'package.json'),'w').write(PACKAGE_JSON % {'name':addon.lower(),
-                                                   'fullName':addon,
+                                                   'title':addon,
                                                    'id':jid })
     print >>out, '* package.json written'
     open(os.path.join(path,'test','test-main.js'),'w').write(TEST_MAIN_JS)
     print >>out, '* test/test-main.js written'
     open(os.path.join(path,'lib','main.js'),'w').write('')
     print >>out, '* lib/main.js written'
     open(os.path.join(path,'doc','main.md'),'w').write('')
     print >>out, '* doc/main.md written'
     if len(args) == 1:
         print >>out, '\nYour sample add-on is now ready.'
         print >>out, 'Do "cfx test" to test it and "cfx run" to try it.  Have fun!'
     else:
         print >>out, '\nYour sample add-on is now ready in the \'' + args[1] +  '\' directory.'
-        print >>out, 'Change to that directory, then do "cfx test" to test it, \nand "cfx run" to try it.  Have fun!' 
+        print >>out, 'Change to that directory, then do "cfx test" to test it, \nand "cfx run" to try it.  Have fun!'
     return {"result":0, "jid":jid}
 
 def buildJID(target_cfg):
     if "id" in target_cfg:
         jid = target_cfg["id"]
     else:
         import uuid
         jid = str(uuid.uuid4())
@@ -592,17 +592,17 @@ def run(arguments=sys.argv[1:], target_c
                          parser_groups=parser_groups,
                          usage=usage,
                          version=display_version,
                          defaults=defaults)
 
     (options, args) = parse_args(**parser_kwargs)
 
     config_args = get_config_args(options.config, env_root);
-    
+
     # reparse configs with arguments from local.json
     if config_args:
         parser_kwargs['arguments'] += config_args
         (options, args) = parse_args(**parser_kwargs)
 
     command = args[0]
 
     if command == "init":
--- a/addon-sdk/source/python-lib/cuddlefish/manifest.py
+++ b/addon-sdk/source/python-lib/cuddlefish/manifest.py
@@ -601,19 +601,23 @@ class ManifestBuilder:
                 return self._handle_module(mi)
         return None
 
     def _find_module_in_package(self, pkgname, sections, name, looked_in):
         # require("a/b/c") should look at ...\a\b\c.js on windows
         filename = os.sep.join(name.split("/"))
         # normalize filename, make sure that we do not add .js if it already has
         # it.
-        if not filename.endswith(".js"):
+        if not filename.endswith(".js") and not filename.endswith(".json"):
           filename += ".js"
-        basename = filename[:-3]
+
+        if filename.endswith(".js"):
+          basename = filename[:-3]
+        if filename.endswith(".json"):
+          basename = filename[:-5]
 
         pkg = self.pkg_cfg.packages[pkgname]
         if isinstance(sections, basestring):
             sections = [sections]
         for section in sections:
             for sdir in pkg.get(section, []):
                 js = os.path.join(pkg.root_dir, sdir, filename)
                 looked_in.append(js)
--- a/addon-sdk/source/python-lib/cuddlefish/rdf.py
+++ b/addon-sdk/source/python-lib/cuddlefish/rdf.py
@@ -117,17 +117,17 @@ def gen_manifest(template_root_dir, targ
     install_rdf = os.path.join(template_root_dir, "install.rdf")
     manifest = RDFManifest(install_rdf)
     dom = manifest.dom
 
     manifest.set("em:id", jid)
     manifest.set("em:version",
                  target_cfg.get('version', '1.0'))
     manifest.set("em:name",
-                 target_cfg.get('fullName', target_cfg['name']))
+                 target_cfg.get('title', target_cfg.get('fullName', target_cfg['name'])))
     manifest.set("em:description",
                  target_cfg.get("description", ""))
     manifest.set("em:creator",
                  target_cfg.get("author", ""))
     manifest.set("em:bootstrap", str(bootstrap).lower())
     # XPIs remain packed by default, but package.json can override that. The
     # RDF format accepts "true" as True, anything else as False. We expect
     # booleans in the .json file, not strings.
--- a/addon-sdk/source/python-lib/cuddlefish/templates.py
+++ b/addon-sdk/source/python-lib/cuddlefish/templates.py
@@ -17,16 +17,16 @@ exports["test main async"] = function(as
 
 require("sdk/test").run(exports);
 '''
 
 #Template used by package.json
 PACKAGE_JSON = '''\
 {
   "name": "%(name)s",
-  "fullName": "%(fullName)s",
+  "title": "%(title)s",
   "id": "%(id)s",
   "description": "a basic add-on",
   "author": "",
   "license": "MPL 2.0",
   "version": "0.1"
 }
 '''
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-1-pack/package.json
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-1-pack/package.json
@@ -1,10 +1,10 @@
 {
     "name": "empty",
     "license": "MPL 2.0",
     "author": "",
     "version": "0.1",
-    "fullName": "empty",
+    "title": "empty",
     "id": "jid1-80fr8b6qeRlQSQ",
     "unpack": false,
     "description": "test unpack= support"
 }
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-2-unpack/package.json
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-2-unpack/package.json
@@ -1,10 +1,10 @@
 {
     "name": "empty",
     "license": "MPL 2.0",
     "author": "",
     "version": "0.1",
-    "fullName": "empty",
+    "title": "empty",
     "id": "jid1-80fr8b6qeRlQSQ",
     "unpack": true,
     "description": "test unpack= support"
 }
--- a/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-3-pack/package.json
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/bug-715340-files/pkg-3-pack/package.json
@@ -1,9 +1,9 @@
 {
     "name": "empty",
     "license": "MPL 2.0",
     "author": "",
     "version": "0.1",
-    "fullName": "empty",
+    "title": "empty",
     "id": "jid1-80fr8b6qeRlQSQ",
     "description": "test unpack= support"
 }
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/fullName/package.json
@@ -0,0 +1,9 @@
+{
+    "name": "empty",
+    "license": "MPL 2.0",
+    "author": "",
+    "version": "0.1",
+    "fullName": "a long fullName",
+    "id": "jid1-80123",
+    "description": "test addon name fallback to 'fullName' key"
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/none/package.json
@@ -0,0 +1,9 @@
+{
+    "name": "a long none",
+    "license": "MPL 2.0",
+    "author": "",
+    "version": "0.1",
+
+    "id": "jid1-80123",
+    "description": "test addon name falls back all the way to the 'name' key"
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/bug-906359-files/title/package.json
@@ -0,0 +1,9 @@
+{
+    "name": "empty",
+    "license": "MPL 2.0",
+    "author": "",
+    "version": "0.1",
+    "title": "a long title",
+    "id": "jid1-80123",
+    "description": "test addon name comes from the 'title' key"
+}
--- a/addon-sdk/source/python-lib/cuddlefish/tests/preferences-files/packages/no-prefs/package.json
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/preferences-files/packages/no-prefs/package.json
@@ -1,6 +1,6 @@
 {
     "id": "jid1-fZHqN9JfrDBa8A",
-    "fullName": "No Prefs Test",
+    "title": "No Prefs Test",
     "author": "Erik Vold",
     "loader": "lib/main.js"
 }
--- a/addon-sdk/source/python-lib/cuddlefish/tests/preferences-files/packages/simple-prefs/package.json
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/preferences-files/packages/simple-prefs/package.json
@@ -1,11 +1,11 @@
 {
     "id": "jid1-fZHqN9JfrDBa8A",
-    "fullName": "Simple Prefs Test",
+    "title": "Simple Prefs Test",
     "author": "Erik Vold",
     "preferences": [{
         "name": "test",
         "type": "bool",
         "title": "tëst",
         "value": false
     },
     {
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_init.py
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/test_init.py
@@ -43,17 +43,17 @@ class TestInit(unittest.TestCase):
         package_json = os.path.join(basedir,"package.json")
         test_main_js = os.path.join(basedir,"test","test-main.js")
         self.assertTrue(os.path.exists(main_js))
         self.assertTrue(os.path.exists(package_json))
         self.assertTrue(os.path.exists(test_main_js))
         self.assertEqual(open(main_js,"r").read(),"")
         self.assertEqual(open(package_json,"r").read() % {"id":"tmp_addon_id" },
                          PACKAGE_JSON % {"name":"tmp_addon_sample",
-                                         "fullName": "tmp_addon_SAMPLE",
+                                         "title": "tmp_addon_SAMPLE",
                                          "id":init_run["jid"] })
         self.assertEqual(open(test_main_js,"r").read(),TEST_MAIN_JS)
 
         # Let's check that the addon is initialized
         out, err = StringIO(), StringIO()
         init_run = initializer(None, ["init"], out, err)
         out, err = out.getvalue(), err.getvalue()
         self.failIfEqual(init_run["result"],0)
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_linker.py
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/test_linker.py
@@ -183,26 +183,23 @@ class Contents(unittest.TestCase):
             try:
                 # regrettably, run() always finishes with sys.exit()
                 cuddlefish.run(["xpi"], # --strip-xpi is now the default
                                stdout=stdout)
             except SystemExit, e:
                 self.failUnlessEqual(e.args[0], 0)
             zf = zipfile.ZipFile("seven.xpi", "r")
             names = zf.namelist()
-            # the first problem found in bug 664840 was that cuddlefish.js
-            # (the loader) was stripped out on windows, due to a /-vs-\ bug
-            self.assertIn("resources/addon-sdk/lib/sdk/loader/cuddlefish.js", names)
-            # the second problem found in bug 664840 was that an addon
+            # problem found in bug 664840 was that an addon
             # without an explicit tests/ directory would copy all files from
             # the package into a bogus JID-PKGNAME-tests/ directory, so check
             # for that
             testfiles = [fn for fn in names if "seven/tests" in fn]
             self.failUnlessEqual([], testfiles)
-            # the third problem was that data files were being stripped from
+            # another problem was that data files were being stripped from
             # the XPI. Note that data/ is only supposed to be included if a
             # module that actually gets used does a require("self") .
             self.assertIn("resources/seven/data/text.data",
                           names)
             self.failIf("seven/lib/unused.js"
                         in names, names)
         self.run_in_subdir("x", _test)
 
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_rdf.py
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/test_rdf.py
@@ -36,10 +36,19 @@ class RDFTests(unittest.TestCase):
                 # these ones should remain packed
                 self.failUnlessEqual(m.get("em:unpack"), "false")
                 self.failUnlessIn("<em:unpack>false</em:unpack>", str(m), n)
             else:
                 # and these should be unpacked
                 self.failUnlessEqual(m.get("em:unpack"), "true")
                 self.failUnlessIn("<em:unpack>true</em:unpack>", str(m), n)
 
+    def testTitle(self):
+        basedir = os.path.join(test_dir, 'bug-906359-files')
+        for n in ['title', 'fullName', 'none']:
+            cfg = packaging.get_config_in_dir(os.path.join(basedir, n))
+            m = rdf.gen_manifest(template_dir, cfg, jid='JID')
+            self.failUnlessEqual(m.get('em:name'), 'a long ' + n)
+            self.failUnlessIn('<em:name>a long ' + n + '</em:name>', str(m), n)
+
+
 if __name__ == '__main__':
     unittest.main()
--- a/addon-sdk/source/python-lib/cuddlefish/tests/test_xpi.py
+++ b/addon-sdk/source/python-lib/cuddlefish/tests/test_xpi.py
@@ -44,17 +44,17 @@ class PrefsTests(unittest.TestCase):
         optsxul = self.xpi.read('options.xul').decode("utf-8")
         self.failUnlessEqual(self.xpi_harness_options["jetpackID"],
                              "jid1-fZHqN9JfrDBa8A@jetpack")
 
         root = ElementTree.XML(optsxul.encode('utf-8'))
 
         xulNamespacePrefix = \
             "{http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul}"
-        
+
         settings = root.findall(xulNamespacePrefix + 'setting')
 
         def assertPref(setting, name, prefType, title):
             packageName = 'jid1-fZHqN9JfrDBa8A@jetpack'
             self.failUnlessEqual(setting.get('data-jetpack-id'), packageName)
             self.failUnlessEqual(setting.get('pref'),
                                  'extensions.' + packageName + '.' + name)
             self.failUnlessEqual(setting.get('pref-name'), name)
@@ -69,17 +69,17 @@ class PrefsTests(unittest.TestCase):
         menuItems = settings[2].findall(
             '%(0)smenulist/%(0)smenupopup/%(0)smenuitem' % { "0": xulNamespacePrefix })
         radios = settings[3].findall(
             '%(0)sradiogroup/%(0)sradio' % { "0": xulNamespacePrefix })
 
         def assertOption(option, value, label):
             self.failUnlessEqual(option.get('value'), value)
             self.failUnlessEqual(option.get('label'), label)
-        
+
         assertOption(menuItems[0], "0", "label1")
         assertOption(menuItems[1], "1", "label2")
         assertOption(radios[0], "red", "rouge")
         assertOption(radios[1], "blue", "bleu")
 
         prefsjs = self.xpi.read('defaults/preferences/prefs.js').decode("utf-8")
         exp = [u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test", false);',
                u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test2", "\u00FCnic\u00F8d\u00E9");',
@@ -252,17 +252,16 @@ class SmallXPI(unittest.TestCase):
                     "components/harness.js",
                     # the real template also has 'bootstrap.js', but the fake
                     # one in tests/static-files/xpi-template doesn't
                     "harness-options.json",
                     "install.rdf",
                     "defaults/preferences/prefs.js",
                     "resources/",
                     "resources/addon-sdk/",
-                    "resources/addon-sdk/data/",
                     "resources/addon-sdk/lib/",
                     "resources/addon-sdk/lib/sdk/",
                     "resources/addon-sdk/lib/sdk/self.js",
                     "resources/addon-sdk/lib/sdk/core/",
                     "resources/addon-sdk/lib/sdk/util/",
                     "resources/addon-sdk/lib/sdk/net/",
                     "resources/addon-sdk/lib/sdk/core/promise.js",
                     "resources/addon-sdk/lib/sdk/util/object.js",
rename from addon-sdk/source/data/index.html
rename to addon-sdk/source/test/addons/addon-page/data/index.html
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/addon-page/main.js
@@ -0,0 +1,167 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+module.metadata = {
+  engines: {
+    'Firefox': '*'
+  }
+};
+
+const { isTabOpen, activateTab, openTab,
+        closeTab, getURI } = require('sdk/tabs/utils');
+const windows = require('sdk/deprecated/window-utils');
+const { LoaderWithHookedConsole } = require('sdk/test/loader');
+const { setTimeout } = require('sdk/timers');
+const { is } = require('sdk/system/xul-app');
+const tabs = require('sdk/tabs');
+const isAustralis = "gCustomizeMode" in windows.activeBrowserWindow;
+const { set: setPref } = require("sdk/preferences/service");
+const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
+
+let uri = require('sdk/self').data.url('index.html');
+
+function isChromeVisible(window) {
+  let x = window.document.documentElement.getAttribute('disablechrome')
+  return x !== 'true';
+}
+
+exports['test add-on page deprecation message'] = function(assert) {
+  let { loader, messages } = LoaderWithHookedConsole(module);
+  loader.require('sdk/addon-page');
+  setPref(DEPRECATE_PREF, true);
+
+  assert.equal(messages.length, 1, "only one error is dispatched");
+  assert.equal(messages[0].type, "error", "the console message is an error");
+
+  let msg = messages[0].msg;
+
+  assert.ok(msg.indexOf("DEPRECATED") === 0,
+            "The message is deprecation message");
+
+  loader.unload();
+};
+
+exports['test that add-on page has no chrome'] = function(assert, done) {
+  let { loader } = LoaderWithHookedConsole(module);
+  loader.require('sdk/addon-page');
+
+  let window = windows.activeBrowserWindow;
+  let tab = openTab(window, uri);
+
+  assert.ok(isChromeVisible(window), 'chrome is visible for non addon page');
+
+  // need to do this in another turn to make sure event listener
+  // that sets property has time to do that.
+  setTimeout(function() {
+    activateTab(tab);
+
+    assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
+      'chrome is not visible for addon page');
+
+    closeTab(tab);
+    assert.ok(isChromeVisible(window), 'chrome is visible again');
+    loader.unload();
+    assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
+    done();
+  });
+};
+
+exports['test that add-on page with hash has no chrome'] = function(assert, done) {
+  let { loader } = LoaderWithHookedConsole(module);
+  loader.require('sdk/addon-page');
+
+  let window = windows.activeBrowserWindow;
+  let tab = openTab(window, uri + "#foo");
+
+  assert.ok(isChromeVisible(window), 'chrome is visible for non addon page');
+
+  // need to do this in another turn to make sure event listener
+  // that sets property has time to do that.
+  setTimeout(function() {
+    activateTab(tab);
+
+    assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
+      'chrome is not visible for addon page');
+
+    closeTab(tab);
+    assert.ok(isChromeVisible(window), 'chrome is visible again');
+    loader.unload();
+    assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
+    done();
+  });
+};
+
+exports['test that add-on page with querystring has no chrome'] = function(assert, done) {
+  let { loader } = LoaderWithHookedConsole(module);
+  loader.require('sdk/addon-page');
+
+  let window = windows.activeBrowserWindow;
+  let tab = openTab(window, uri + '?foo=bar');
+
+  assert.ok(isChromeVisible(window), 'chrome is visible for non addon page');
+
+  // need to do this in another turn to make sure event listener
+  // that sets property has time to do that.
+  setTimeout(function() {
+    activateTab(tab);
+
+    assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
+      'chrome is not visible for addon page');
+
+    closeTab(tab);
+    assert.ok(isChromeVisible(window), 'chrome is visible again');
+    loader.unload();
+    assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
+    done();
+  });
+};
+
+exports['test that add-on page with hash and querystring has no chrome'] = function(assert, done) {
+  let { loader } = LoaderWithHookedConsole(module);
+  loader.require('sdk/addon-page');
+
+  let window = windows.activeBrowserWindow;
+  let tab = openTab(window, uri + '#foo?foo=bar');
+
+  assert.ok(isChromeVisible(window), 'chrome is visible for non addon page');
+
+  // need to do this in another turn to make sure event listener
+  // that sets property has time to do that.
+  setTimeout(function() {
+    activateTab(tab);
+
+    assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
+      'chrome is not visible for addon page');
+
+    closeTab(tab);
+    assert.ok(isChromeVisible(window), 'chrome is visible again');
+    loader.unload();
+    assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
+    done();
+  });
+};
+
+exports['test that malformed uri is not an addon-page'] = function(assert, done) {
+  let { loader } = LoaderWithHookedConsole(module);
+  loader.require('sdk/addon-page');
+
+  let window = windows.activeBrowserWindow;
+  let tab = openTab(window, uri + 'anguage');
+
+  // need to do this in another turn to make sure event listener
+  // that sets property has time to do that.
+  setTimeout(function() {
+    activateTab(tab);
+
+    assert.ok(isChromeVisible(window), 'chrome is visible for malformed uri');
+
+    closeTab(tab);
+    loader.unload();
+    done();
+  });
+};
+
+require('sdk/test/runner').runTestsFromModule(module);
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/addon-page/package.json
@@ -0,0 +1,3 @@
+{
+  "id": "test-addon-page"
+}
rename from addon-sdk/source/test/favicon-helpers.js
rename to addon-sdk/source/test/addons/places/favicon-helpers.js
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/places/main.js
@@ -0,0 +1,24 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+module.metadata = {
+  'engines': {
+    'Firefox': '*'
+  }
+};
+
+const { safeMerge: merge } = require('sdk/util/object');
+
+merge(module.exports,
+  require('./tests/test-places-bookmarks'),
+  require('./tests/test-places-events'),
+  require('./tests/test-places-favicon'),
+  require('./tests/test-places-history'),
+  require('./tests/test-places-host'),
+  require('./tests/test-places-utils')
+);
+
+require('sdk/test/runner').runTestsFromModule(module);
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/places/package.json
@@ -0,0 +1,3 @@
+{
+  "id": "test-places"
+}
rename from addon-sdk/source/test/places-helper.js
rename to addon-sdk/source/test/addons/places/places-helper.js
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/places/tests/test-places-bookmarks.js
@@ -0,0 +1,965 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+'use strict';
+
+module.metadata = {
+  'engines': {
+    'Firefox': '*'
+  }
+};
+
+const { Cc, Ci } = require('chrome');
+const { request } = require('sdk/addon/host');
+const { filter } = require('sdk/event/utils');
+const { on, off } = require('sdk/event/core');
+const { setTimeout } = require('sdk/timers');
+const { newURI } = require('sdk/url/utils');
+const { defer, all } = require('sdk/core/promise');
+const { defer: async } = require('sdk/lang/functional');
+const { before, after } = require('sdk/test/utils');
+
+const {
+  Bookmark, Group, Separator,
+  save, search, remove,
+  MENU, TOOLBAR, UNSORTED
+} = require('sdk/places/bookmarks');
+const {
+  invalidResolve, invalidReject, createTree,
+  compareWithHost, createBookmark, createBookmarkItem,
+  createBookmarkTree, addVisits, resetPlaces
+} = require('../places-helper');
+const { promisedEmitter } = require('sdk/places/utils');
+const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
+                    getService(Ci.nsINavBookmarksService);
+const tagsrv = Cc['@mozilla.org/browser/tagging-service;1'].
+                    getService(Ci.nsITaggingService);
+
+exports.testDefaultFolders = function (assert) {
+  var ids = [
+    bmsrv.bookmarksMenuFolder,
+    bmsrv.toolbarFolder,
+    bmsrv.unfiledBookmarksFolder
+  ];
+  [MENU, TOOLBAR, UNSORTED].forEach(function (g, i) {
+    assert.ok(g.id === ids[i], ' default group matches id');
+  });
+};
+
+exports.testValidation = function (assert) {
+  assert.throws(() => {
+    Bookmark({ title: 'a title' });
+  }, /The `url` property must be a valid URL/, 'throws empty URL error');
+
+  assert.throws(() => {
+    Bookmark({ title: 'a title', url: 'not.a.url' });
+  }, /The `url` property must be a valid URL/, 'throws invalid URL error');
+
+  assert.throws(() => {
+    Bookmark({ url: 'http://foo.com' });
+  }, /The `title` property must be defined/, 'throws title error');
+
+  assert.throws(() => {
+    Bookmark();
+  }, /./, 'throws any error');
+
+  assert.throws(() => {
+    Group();
+  }, /The `title` property must be defined/, 'throws title error for group');
+
+  assert.throws(() => {
+    Bookmark({ url: 'http://foo.com', title: 'my title', tags: 'a tag' });
+  }, /The `tags` property must be a Set, or an array/, 'throws error for non set/array tag');
+};
+
+exports.testCreateBookmarks = function (assert, done) {
+  var bm = Bookmark({
+    title: 'moz',
+    url: 'http://mozilla.org',
+    tags: ['moz1', 'moz2', 'moz3']
+  });
+
+  save(bm).on('data', (bookmark, input) => {
+    assert.equal(input, bm, 'input is original input item');
+    assert.ok(bookmark.id, 'Bookmark has ID');
+    assert.equal(bookmark.title, 'moz');
+    assert.equal(bookmark.url, 'http://mozilla.org');
+    assert.equal(bookmark.group, UNSORTED, 'Unsorted folder is default parent');
+    assert.ok(bookmark !== bm, 'bookmark should be a new instance');
+    compareWithHost(assert, bookmark);
+  }).on('end', bookmarks => {
+    assert.equal(bookmarks.length, 1, 'returned bookmarks in end');
+    assert.equal(bookmarks[0].url, 'http://mozilla.org');
+    assert.equal(bookmarks[0].tags.has('moz1'), true, 'has first tag');
+    assert.equal(bookmarks[0].tags.has('moz2'), true, 'has second tag');
+    assert.equal(bookmarks[0].tags.has('moz3'), true, 'has third tag');
+    assert.pass('end event is called');
+    done();
+  });
+};
+
+exports.testCreateGroup = function (assert, done) {
+  save(Group({ title: 'mygroup', group: MENU })).on('data', g => {
+    assert.ok(g.id, 'Bookmark has ID');
+    assert.equal(g.title, 'mygroup', 'matches title');
+    assert.equal(g.group, MENU, 'Menu folder matches');
+    compareWithHost(assert, g);
+  }).on('end', results => {
+    assert.equal(results.length, 1);
+    assert.pass('end event is called');
+    done();
+  });
+};
+
+exports.testCreateSeparator = function (assert, done) {
+  save(Separator({ group: MENU })).on('data', function (s) {
+    assert.ok(s.id, 'Separator has id');
+    assert.equal(s.group, MENU, 'Parent group matches');
+    compareWithHost(assert, s);
+  }).on('end', function (results) {
+    assert.equal(results.length, 1);
+    assert.pass('end event is called');
+    done();
+  });
+};
+
+exports.testCreateError = function (assert, done) {
+  let bookmarks = [
+    { title: 'moz1', url: 'http://moz1.com', type: 'bookmark'},
+    { title: 'moz2', url: 'invalidurl', type: 'bookmark'},
+    { title: 'moz3', url: 'http://moz3.com', type: 'bookmark'}
+  ];
+
+  let dataCount = 0, errorCount = 0;
+  save(bookmarks).on('data', bookmark => {
+    assert.ok(/moz[1|3]/.test(bookmark.title), 'valid bookmarks complete');
+    dataCount++;
+  }).on('error', (reason, item) => {
+    assert.ok(
+      /The `url` property must be a valid URL/.test(reason),
+      'Error event called with correct reason');
+    assert.equal(item, bookmarks[1], 'returns input that failed in event');
+    errorCount++;
+  }).on('end', items => {
+    assert.equal(dataCount, 2, 'data event called twice');
+    assert.equal(errorCount, 1, 'error event called once');
+    assert.equal(items.length, bookmarks.length, 'all items should be in result');
+    assert.equal(items[0].toString(), '[object Bookmark]',
+      'should be a saved instance');
+    assert.equal(items[2].toString(), '[object Bookmark]',
+      'should be a saved instance');
+    assert.equal(items[1], bookmarks[1], 'should be original, unsaved object');
+
+    search({ query: 'moz' }).on('end', items => {
+      assert.equal(items.length, 2, 'only two items were successfully saved');
+      bookmarks[1].url = 'http://moz2.com/';
+      dataCount = errorCount = 0;
+      save(bookmarks).on('data', bookmark => {
+        dataCount++;
+      }).on('error', reason => errorCount++)
+      .on('end', items => {
+        assert.equal(items.length, 3, 'all 3 items saved');
+        assert.equal(dataCount, 3, '3 data events called');
+        assert.equal(errorCount, 0, 'no error events called');
+        search({ query: 'moz' }).on('end', items => {
+          assert.equal(items.length, 3, 'only 3 items saved');
+          items.map(item =>
+            assert.ok(/moz\d\.com/.test(item.url), 'correct item'))
+          done();
+        });
+      });
+    });
+  });
+};
+
+exports.testSaveDucktypes = function (assert, done) {
+  save({
+    title: 'moz',
+    url: 'http://mozilla.org',
+    type: 'bookmark'
+  }).on('data', (bookmark) => {
+    compareWithHost(assert, bookmark);
+    done();
+  });
+};
+
+exports.testSaveDucktypesParent = function (assert, done) {
+  let folder = { title: 'myfolder', type: 'group' };
+  let bookmark = { title: 'mozzie', url: 'http://moz.com', group: folder, type: 'bookmark' };
+  let sep = { type: 'separator', group: folder };
+  save([sep, bookmark]).on('end', (res) => {
+    compareWithHost(assert, res[0]);
+    compareWithHost(assert, res[1]);
+    assert.equal(res[0].group.title, 'myfolder', 'parent is ducktyped group');
+    assert.equal(res[1].group.title, 'myfolder', 'parent is ducktyped group');
+    done();
+  });
+};
+
+/*
+ * Tests the scenario where the original bookmark item is resaved
+ * and does not have an ID or an updated date, but should still be
+ * mapped to the item it created previously
+ */
+exports.testResaveOriginalItemMapping = function (assert, done) {
+  let bookmark = Bookmark({ title: 'moz', url: 'http://moz.org' });
+  save(bookmark).on('data', newBookmark => {
+    bookmark.title = 'new moz';
+    save(bookmark).on('data', newNewBookmark => {
+      assert.equal(newBookmark.id, newNewBookmark.id, 'should be the same bookmark item');
+      assert.equal(bmsrv.getItemTitle(newBookmark.id), 'new moz', 'should have updated title');
+      done();
+    });
+  });
+};
+
+exports.testCreateMultipleBookmarks = function (assert, done) {
+  let data = [
+    Bookmark({title: 'bm1', url: 'http://bm1.com'}),
+    Bookmark({title: 'bm2', url: 'http://bm2.com'}),
+    Bookmark({title: 'bm3', url: 'http://bm3.com'}),
+  ];
+  save(data).on('data', function (bookmark, input) {
+    let stored = data.filter(({title}) => title === bookmark.title)[0];
+    assert.equal(input, stored, 'input is original input item');
+    assert.equal(bookmark.title, stored.title, 'titles match');
+    assert.equal(bookmark.url, stored.url, 'urls match');
+    compareWithHost(assert, bookmark);
+  }).on('end', function (bookmarks) {
+    assert.equal(bookmarks.length, 3, 'all bookmarks returned');
+    done();
+  });
+};
+
+exports.testCreateImplicitParent = function (assert, done) {
+  let folder = Group({ title: 'my parent' });
+  let bookmarks = [
+    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: folder }),
+    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: folder }),
+    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: folder })
+  ];
+  save(bookmarks).on('data', function (bookmark) {
+    if (bookmark.type === 'bookmark') {
+      assert.equal(bookmark.group.title, folder.title, 'parent is linked');
+      compareWithHost(assert, bookmark);
+    } else if (bookmark.type === 'group') {
+      assert.equal(bookmark.group.id, UNSORTED.id, 'parent ID of group is correct');
+      compareWithHost(assert, bookmark);
+    }
+  }).on('end', function (results) {
+    assert.equal(results.length, 3, 'results should only hold explicit saves');
+    done();
+  });
+};
+
+exports.testCreateExplicitParent = function (assert, done) {
+  let folder = Group({ title: 'my parent' });
+  let bookmarks = [
+    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: folder }),
+    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: folder }),
+    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: folder })
+  ];
+  save(bookmarks.concat(folder)).on('data', function (bookmark) {
+    if (bookmark.type === 'bookmark') {
+      assert.equal(bookmark.group.title, folder.title, 'parent is linked');
+      compareWithHost(assert, bookmark);
+    } else if (bookmark.type === 'group') {
+      assert.equal(bookmark.group.id, UNSORTED.id, 'parent ID of group is correct');
+      compareWithHost(assert, bookmark);
+    }
+  }).on('end', function () {
+    done();
+  });
+};
+
+exports.testCreateNested = function (assert, done) {
+  let topFolder = Group({ title: 'top', group: MENU });
+  let midFolder = Group({ title: 'middle', group: topFolder });
+  let bookmarks = [
+    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder }),
+    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder }),
+    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder })
+  ];
+  let dataEventCount = 0;
+  save(bookmarks).on('data', function (bookmark) {
+    if (bookmark.type === 'bookmark') {
+      assert.equal(bookmark.group.title, midFolder.title, 'parent is linked');
+    } else if (bookmark.title === 'top') {
+      assert.equal(bookmark.group.id, MENU.id, 'parent ID of top group is correct');
+    } else {
+      assert.equal(bookmark.group.title, topFolder.title, 'parent title of middle group is correct');
+    }
+    dataEventCount++;
+    compareWithHost(assert, bookmark);
+  }).on('end', () => {
+    assert.equal(dataEventCount, 5, 'data events for all saves have occurred');
+    assert.ok('end event called');
+    done();
+  });
+};
+
+/*
+ * Was a scenario when implicitly saving a bookmark that was already created,
+ * it was not being properly fetched and attempted to recreate
+ */
+exports.testAddingToExistingParent = function (assert, done) {
+  let group = { type: 'group', title: 'mozgroup' };
+  let bookmarks = [
+    { title: 'moz1', url: 'http://moz1.com', type: 'bookmark', group: group },
+    { title: 'moz2', url: 'http://moz2.com', type: 'bookmark', group: group },
+    { title: 'moz3', url: 'http://moz3.com', type: 'bookmark', group: group }
+  ],
+  firstBatch, secondBatch;
+
+  saveP(bookmarks).then(data => {
+    firstBatch = data;
+    return saveP([
+      { title: 'moz4', url: 'http://moz4.com', type: 'bookmark', group: group },
+      { title: 'moz5', url: 'http://moz5.com', type: 'bookmark', group: group }
+    ]);
+  }, assert.fail).then(data => {
+    secondBatch = data;
+    assert.equal(firstBatch[0].group.id, secondBatch[0].group.id,
+      'successfully saved to the same parent');
+    done();
+  }, assert.fail);
+};
+
+exports.testUpdateParent = function (assert, done) {
+  let group = { type: 'group', title: 'mozgroup' };
+  saveP(group).then(item => {
+    item[0].title = 'mozgroup-resave';
+    return saveP(item[0]);
+  }).then(item => {
+    assert.equal(item[0].title, 'mozgroup-resave', 'group saved successfully');
+    done();
+  });
+};
+
+exports.testUpdateSeparator = function (assert, done) {
+  let sep = [Separator(), Separator(), Separator()];
+  saveP(sep).then(item => {
+    item[0].index = 2;
+    return saveP(item[0]);
+  }).then(item => {
+    assert.equal(item[0].index, 2, 'updated index of separator');
+    done();
+  });
+};
+
+exports.testPromisedSave = function (assert, done) {
+  let topFolder = Group({ title: 'top', group: MENU });
+  let midFolder = Group({ title: 'middle', group: topFolder });
+  let bookmarks = [
+    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
+    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
+    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
+  ];
+  let first, second, third;
+  saveP(bookmarks).then(bms => {
+    first = bms.filter(b => b.title === 'moz1')[0];
+    second = bms.filter(b => b.title === 'moz2')[0];
+    third = bms.filter(b => b.title === 'moz3')[0];
+    assert.equal(first.index, 0);
+    assert.equal(second.index, 1);
+    assert.equal(third.index, 2);
+    first.index = 3;
+    return saveP(first);
+  }).then(() => {
+    assert.equal(bmsrv.getItemIndex(first.id), 2, 'properly moved bookmark');
+    assert.equal(bmsrv.getItemIndex(second.id), 0, 'other bookmarks adjusted');
+    assert.equal(bmsrv.getItemIndex(third.id), 1, 'other bookmarks adjusted');
+    done();
+  });
+};
+
+exports.testPromisedErrorSave = function (assert, done) {
+  let bookmarks = [
+    { title: 'moz1', url: 'http://moz1.com', type: 'bookmark'},
+    { title: 'moz2', url: 'invalidurl', type: 'bookmark'},
+    { title: 'moz3', url: 'http://moz3.com', type: 'bookmark'}
+  ];
+  saveP(bookmarks).then(invalidResolve, reason => {
+    assert.ok(
+      /The `url` property must be a valid URL/.test(reason),
+      'Error event called with correct reason');
+
+    bookmarks[1].url = 'http://moz2.com';
+    return saveP(bookmarks);
+  }).then(res => {
+    return searchP({ query: 'moz' });
+  }).then(res => {
+    assert.equal(res.length, 3, 'all 3 should be saved upon retry');
+    res.map(item => assert.ok(/moz\d\.com/.test(item.url), 'correct item'));
+    done();
+  }, invalidReject);
+};
+
+exports.testMovingChildren = function (assert, done) {
+  let topFolder = Group({ title: 'top', group: MENU });
+  let midFolder = Group({ title: 'middle', group: topFolder });
+  let bookmarks = [
+    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
+    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
+    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
+  ];
+  save(bookmarks).on('end', bms => {
+    let first = bms.filter(b => b.title === 'moz1')[0];
+    let second = bms.filter(b => b.title === 'moz2')[0];
+    let third = bms.filter(b => b.title === 'moz3')[0];
+    assert.equal(first.index, 0);
+    assert.equal(second.index, 1);
+    assert.equal(third.index, 2);
+    /* When moving down in the same container we take
+     * into account the removal of the original item. If you want
+     * to move from index X to index Y > X you must use
+     * moveItem(id, folder, Y + 1)
+     */
+    first.index = 3;
+    save(first).on('end', () => {
+      assert.equal(bmsrv.getItemIndex(first.id), 2, 'properly moved bookmark');
+      assert.equal(bmsrv.getItemIndex(second.id), 0, 'other bookmarks adjusted');
+      assert.equal(bmsrv.getItemIndex(third.id), 1, 'other bookmarks adjusted');
+      done();
+    });
+  });
+};
+
+exports.testMovingChildrenNewFolder = function (assert, done) {
+  let topFolder = Group({ title: 'top', group: MENU });
+  let midFolder = Group({ title: 'middle', group: topFolder });
+  let newFolder = Group({ title: 'new', group: MENU });
+  let bookmarks = [
+    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
+    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
+    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
+  ];
+  save(bookmarks).on('end', bms => {
+    let first = bms.filter(b => b.title === 'moz1')[0];
+    let second = bms.filter(b => b.title === 'moz2')[0];
+    let third = bms.filter(b => b.title === 'moz3')[0];
+    let definedMidFolder = first.group;
+    let definedNewFolder;
+    first.group = newFolder;
+    assert.equal(first.index, 0);
+    assert.equal(second.index, 1);
+    assert.equal(third.index, 2);
+    save(first).on('data', (data) => {
+      if (data.type === 'group') definedNewFolder = data;
+    }).on('end', (moved) => {
+      assert.equal(bmsrv.getItemIndex(second.id), 0, 'other bookmarks adjusted');
+      assert.equal(bmsrv.getItemIndex(third.id), 1, 'other bookmarks adjusted');
+      assert.equal(bmsrv.getItemIndex(first.id), 0, 'properly moved bookmark');
+      assert.equal(bmsrv.getFolderIdForItem(first.id), definedNewFolder.id,
+        'bookmark has new parent');
+      assert.equal(bmsrv.getFolderIdForItem(second.id), definedMidFolder.id,
+        'sibling bookmarks did not move');
+      assert.equal(bmsrv.getFolderIdForItem(third.id), definedMidFolder.id,
+        'sibling bookmarks did not move');
+      done();
+    });
+  });
+};
+
+exports.testRemoveFunction = function (assert) {
+  let topFolder = Group({ title: 'new', group: MENU });
+  let midFolder = Group({ title: 'middle', group: topFolder });
+  let bookmarks = [
+    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
+    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
+    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
+  ];
+  remove([midFolder, topFolder].concat(bookmarks)).map(item => {
+    assert.equal(item.remove, true, 'remove toggled `remove` property to true');
+  });
+};
+
+exports.testRemove = function (assert, done) {
+  let id;
+  createBookmarkItem().then(data => {
+    id = data.id;
+    compareWithHost(assert, data); // ensure bookmark exists
+    save(remove(data)).on('data', (res) => {
+      assert.pass('data event should be called');
+      assert.ok(!res, 'response should be empty');
+    }).on('end', () => {
+      assert.throws(function () {
+        bmsrv.getItemTitle(id);
+      }, 'item should no longer exist');
+      done();
+    });
+  });
+};
+
+/*
+ * Tests recursively removing children when removing a group
+ */
+exports.testRemoveAllChildren = function (assert, done) {
+  let topFolder = Group({ title: 'new', group: MENU });
+  let midFolder = Group({ title: 'middle', group: topFolder });
+  let bookmarks = [
+    Bookmark({ title: 'moz1', url: 'http://moz1.com', group: midFolder}),
+    Bookmark({ title: 'moz2', url: 'http://moz2.com', group: midFolder}),
+    Bookmark({ title: 'moz3', url: 'http://moz3.com', group: midFolder})
+  ];
+
+  let saved = [];
+  save(bookmarks).on('data', (data) => saved.push(data)).on('end', () => {
+    save(remove(topFolder)).on('end', () => {
+      assert.equal(saved.length, 5, 'all items should have been saved');
+      saved.map((item) => {
+        assert.throws(function () {
+          bmsrv.getItemTitle(item.id);
+        }, 'item should no longer exist');
+      });
+      done();
+    });
+  });
+};
+
+exports.testResolution = function (assert, done) {
+  let firstSave, secondSave;
+  createBookmarkItem().then((item) => {
+    firstSave = item;
+    assert.ok(item.updated, 'bookmark has updated time');
+    item.title = 'my title';
+    // Ensure delay so a different save time is set
+    return delayed(item);
+  }).then(saveP)
+  .then(items => {
+    let item = items[0];
+    secondSave = item;
+    assert.ok(firstSave.updated < secondSave.updated, 'snapshots have different update times');
+    firstSave.title = 'updated title';
+    return saveP(firstSave, { resolve: (mine, theirs) => {
+      assert.equal(mine.title, 'updated title', 'correct data for my object');
+      assert.equal(theirs.title, 'my title', 'correct data for their object');
+      assert.equal(mine.url, theirs.url, 'other data is equal');
+      assert.equal(mine.group, theirs.group, 'other data is equal');
+      assert.ok(mine !== firstSave, 'instance is not passed in');
+      assert.ok(theirs !== secondSave, 'instance is not passed in');
+      assert.equal(mine.toString(), '[object Object]', 'serialized objects');
+      assert.equal(theirs.toString(), '[object Object]', 'serialized objects');
+      mine.title = 'a new title';
+      return mine;
+    }});
+  }).then((results) => {
+    let result = results[0];
+    assert.equal(result.title, 'a new title', 'resolve handles results');
+    done();
+  });
+};
+
+/*
+ * Same as the resolution test, but with the 'unsaved' snapshot
+ */
+exports.testResolutionMapping = function (assert, done) {
+  let bookmark = Bookmark({ title: 'moz', url: 'http://bookmarks4life.com/' });
+  let saved;
+  saveP(bookmark).then(data => {
+    saved = data[0];
+    saved.title = 'updated title';
+    // Ensure a delay for different updated times
+    return delayed(saved);
+  }).then(saveP)
+  .then(() => {
+    bookmark.title = 'conflicting title';
+    return saveP(bookmark, { resolve: (mine, theirs) => {
+      assert.equal(mine.title, 'conflicting title', 'correct data for my object');
+      assert.equal(theirs.title, 'updated title', 'correct data for their object');
+      assert.equal(mine.url, theirs.url, 'other data is equal');
+      assert.equal(mine.group, theirs.group, 'other data is equal');
+      assert.ok(mine !== bookmark, 'instance is not passed in');
+      assert.ok(theirs !== saved, 'instance is not passed in');
+      assert.equal(mine.toString(), '[object Object]', 'serialized objects');
+      assert.equal(theirs.toString(), '[object Object]', 'serialized objects');
+      mine.title = 'a new title';
+      return mine;
+    }});
+  }).then((results) => {
+    let result = results[0];
+    assert.equal(result.title, 'a new title', 'resolve handles results');
+    done();
+  });
+};
+
+exports.testUpdateTags = function (assert, done) {
+  createBookmarkItem({ tags: ['spidermonkey'] }).then(bookmark => {
+    bookmark.tags.add('jagermonkey');
+    bookmark.tags.add('ionmonkey');
+    bookmark.tags.delete('spidermonkey');
+    save(bookmark).on('data', saved => {
+      assert.equal(saved.tags.size, 2, 'should have 2 tags');
+      assert.ok(saved.tags.has('jagermonkey'), 'should have added tag');
+      assert.ok(saved.tags.has('ionmonkey'), 'should have added tag');
+      assert.ok(!saved.tags.has('spidermonkey'), 'should not have removed tag');
+      done();
+    });
+  });
+};
+
+/*
+ * View `createBookmarkTree` in `./places-helper.js` to see
+ * expected tree construction
+ */
+
+exports.testSearchByGroupSimple = function (assert, done) {
+  createBookmarkTree().then(() => {
+     // In initial release of Places API, groups can only be queried
+     // via a 'simple query', which is one folder set, and no other
+     // parameters
+    return searchP({ group: UNSORTED });
+  }).then(results => {
+    let groups = results.filter(({type}) => type === 'group');
+    assert.equal(groups.length, 2, 'returns folders');
+    assert.equal(results.length, 7,
+      'should return all bookmarks and folders under UNSORTED');
+    assert.equal(groups[0].toString(), '[object Group]', 'returns instance');
+    return searchP({
+      group: groups.filter(({title}) => title === 'mozgroup')[0]
+    });
+  }).then(results => {
+    let groups = results.filter(({type}) => type === 'group');
+    assert.equal(groups.length, 1, 'returns one subfolder');
+    assert.equal(results.length, 6,
+      'returns all children bookmarks/folders');
+    assert.ok(results.filter(({url}) => url === 'http://w3schools.com/'),
+      'returns nested children');
+    done();
+  }).then(null, assert.fail);
+};
+
+exports.testSearchByGroupComplex = function (assert, done) {
+  let mozgroup;
+  createBookmarkTree().then(results => {
+    mozgroup = results.filter(({title}) => title === 'mozgroup')[0];
+    return searchP({ group: mozgroup, query: 'javascript' });
+  }).then(results => {
+    assert.equal(results.length, 1, 'only one javascript result under mozgroup');
+    assert.equal(results[0].url, 'http://w3schools.com/', 'correct result');
+    return searchP({ group: mozgroup, url: '*.mozilla.org' });
+  }).then(results => {
+    assert.equal(results.length, 2, 'expected results');
+    assert.ok(
+      !results.filter(({url}) => /developer.mozilla/.test(url)).length,
+      'does not find results from other folders');
+    done();
+  }, assert.fail);
+};
+
+exports.testSearchEmitters = function (assert, done) {
+  createBookmarkTree().then(() => {
+    let count = 0;
+    search({ tags: ['mozilla', 'firefox'] }).on('data', data => {
+      assert.ok(/mozilla|firefox/.test(data.title), 'one of the correct items');
+      assert.ok(data.tags.has('firefox'), 'has firefox tag');
+      assert.ok(data.tags.has('mozilla'), 'has mozilla tag');
+      assert.equal(data + '', '[object Bookmark]', 'returns bookmark');
+      count++;
+    }).on('end', data => {
+      assert.equal(count, 3, 'data event was called for each item');
+      assert.equal(data.length, 3,
+        'should return two bookmarks that have both mozilla AND firefox');
+      assert.equal(data[0].title, 'mozilla.com', 'returns correct bookmark');
+      assert.equal(data[1].title, 'mozilla.org', 'returns correct bookmark');
+      assert.equal(data[2].title, 'firefox', 'returns correct bookmark');
+      assert.equal(data[0] + '', '[object Bookmark]', 'returns bookmarks');
+      done();
+    });
+  });
+};
+
+exports.testSearchTags = function (assert, done) {
+  createBookmarkTree().then(() => {
+    // AND tags
+    return searchP({ tags: ['mozilla', 'firefox'] });
+  }).then(data => {
+    assert.equal(data.length, 3,
+      'should return two bookmarks that have both mozilla AND firefox');
+    assert.equal(data[0].title, 'mozilla.com', 'returns correct bookmark');
+    assert.equal(data[1].title, 'mozilla.org', 'returns correct bookmark');
+    assert.equal(data[2].title, 'firefox', 'returns correct bookmark');
+    assert.equal(data[0] + '', '[object Bookmark]', 'returns bookmarks');
+    return searchP([{tags: ['firefox']}, {tags: ['javascript']}]);
+  }).then(data => {
+    // OR tags
+    assert.equal(data.length, 6,
+      'should return all bookmarks with firefox OR javascript tag');
+    done();
+  });
+};
+
+/*
+ * Tests 4 scenarios
+ * '*.mozilla.com'
+ * 'mozilla.com'
+ * 'http://mozilla.com/'
+ * 'http://mozilla.com/*'
+ */
+exports.testSearchURL = function (assert, done) {
+  createBookmarkTree().then(() => {
+    return searchP({ url: 'mozilla.org' });
+  }).then(data => {
+    assert.equal(data.length, 2, 'only URLs with host domain');
+    assert.equal(data[0].url, 'http://mozilla.org/');
+    assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
+    return searchP({ url: '*.mozilla.org' });
+  }).then(data => {
+    assert.equal(data.length, 3, 'returns domain and when host is other than domain');
+    assert.equal(data[0].url, 'http://mozilla.org/');
+    assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
+    assert.equal(data[2].url, 'http://developer.mozilla.org/en-US/');
+    return searchP({ url: 'http://mozilla.org' });
+  }).then(data => {
+    assert.equal(data.length, 1, 'only exact URL match');
+    assert.equal(data[0].url, 'http://mozilla.org/');
+    return searchP({ url: 'http://mozilla.org/*' });
+  }).then(data => {
+    assert.equal(data.length, 2, 'only URLs that begin with query');
+    assert.equal(data[0].url, 'http://mozilla.org/');
+    assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
+    return searchP([{ url: 'mozilla.org' }, { url: 'component.fm' }]);
+  }).then(data => {
+    assert.equal(data.length, 3, 'returns URLs that match EITHER query');
+    assert.equal(data[0].url, 'http://mozilla.org/');
+    assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
+    assert.equal(data[2].url, 'http://component.fm/');
+  }).then(() => {
+    done();
+  });
+};
+
+/*
+ * Searches url, title, tags
+ */
+exports.testSearchQuery = function (assert, done) {
+  createBookmarkTree().then(() => {
+    return searchP({ query: 'thunder' });
+  }).then(data => {
+    assert.equal(data.length, 3);
+    assert.equal(data[0].title, 'mozilla.com', 'query matches tag, url, or title');
+    assert.equal(data[1].title, 'mozilla.org', 'query matches tag, url, or title');
+    assert.equal(data[2].title, 'thunderbird', 'query matches tag, url, or title');
+    return searchP([{ query: 'rust' }, { query: 'component' }]);
+  }).then(data => {
+    // rust OR component
+    assert.equal(data.length, 3);
+    assert.equal(data[0].title, 'mozilla.com', 'query matches tag, url, or title');
+    assert.equal(data[1].title, 'mozilla.org', 'query matches tag, url, or title');
+    assert.equal(data[2].title, 'web audio components', 'query matches tag, url, or title');
+    return searchP([{ query: 'moz', tags: ['javascript']}]);
+  }).then(data => {
+    assert.equal(data.length, 1);
+    assert.equal(data[0].title, 'mdn',
+      'only one item matches moz query AND has a javascript tag');
+  }).then(() => {
+    done();
+  });
+};
+
+/*
+ * Test caching on bulk calls.
+ * Each construction of a bookmark item snapshot results in
+ * the recursive lookup of parent groups up to the root groups --
+ * ensure that the appropriate instances equal each other, and no duplicate
+ * fetches are called
+ *
+ * Implementation-dependent, this checks the host event `sdk-places-bookmarks-get`,
+ * and if implementation changes, this could increase or decrease
+ */
+
+exports.testCaching = function (assert, done) {
+  let count = 0;
+  let stream = filter(request, ({event}) =>
+    /sdk-places-bookmarks-get/.test(event));
+  on(stream, 'data', handle);
+
+  let group = { type: 'group', title: 'mozgroup' };
+  let bookmarks = [
+    { title: 'moz1', url: 'http://moz1.com', type: 'bookmark', group: group },
+    { title: 'moz2', url: 'http://moz2.com', type: 'bookmark', group: group },
+    { title: 'moz3', url: 'http://moz3.com', type: 'bookmark', group: group }
+  ];
+
+  /*
+   * Use timeout in tests since the platform calls are synchronous
+   * and the counting event shim may not have occurred yet
+   */
+
+  saveP(bookmarks).then(() => {
+    assert.equal(count, 0, 'all new items and root group, no fetches should occur');
+    count = 0;
+    return saveP([
+      { title: 'moz4', url: 'http://moz4.com', type: 'bookmark', group: group },
+      { title: 'moz5', url: 'http://moz5.com', type: 'bookmark', group: group }
+    ]);
+  // Test `save` look-up
+  }).then(() => {
+    assert.equal(count, 1, 'should only look up parent once');
+    count = 0;
+    return searchP({ query: 'moz' });
+  }).then(results => {
+    // Should query for each bookmark (5) from the query (id -> data),
+    // their parent during `construct` (1) and the root shouldn't
+    // require a lookup
+    assert.equal(count, 6, 'lookup occurs once for each item and parent');
+    off(stream, 'data', handle);
+    done();
+  });
+
+  function handle ({data}) count++
+};
+
+/*
+ * Search Query Options
+ */
+
+exports.testSearchCount = function (assert, done) {
+  let max = 8;
+  createBookmarkTree()
+  .then(testCount(1))
+  .then(testCount(2))
+  .then(testCount(3))
+  .then(testCount(5))
+  .then(testCount(10))
+  .then(() => {
+    done();
+  });
+
+  function testCount (n) {
+    return function () {
+      return searchP({}, { count: n }).then(results => {
+        if (n > max) n = max;
+        assert.equal(results.length, n,
+          'count ' + n + ' returns ' + n + ' results');
+      });
+    };
+  }
+};
+
+exports.testSearchSort = function (assert, done) {
+  let urls = [
+    'http://mozilla.com/', 'http://webaud.io/', 'http://mozilla.com/webfwd/',
+    'http://developer.mozilla.com/', 'http://bandcamp.com/'
+  ];
+
+  saveP(
+    urls.map(url =>
+      Bookmark({ url: url, title: url.replace(/http:\/\/|\//g,'')}))
+  ).then(() => {
+    return searchP({}, { sort: 'title' });
+  }).then(results => {
+    checkOrder(results, [4,3,0,2,1]);
+    return searchP({}, { sort: 'title', descending: true });
+  }).then(results => {
+    checkOrder(results, [1,2,0,3,4]);
+    return searchP({}, { sort: 'url' });
+  }).then(results => {
+    checkOrder(results, [4,3,0,2,1]);
+    return searchP({}, { sort: 'url', descending: true });
+  }).then(results => {
+    checkOrder(results, [1,2,0,3,4]);
+    return addVisits(['http://mozilla.com/', 'http://mozilla.com']);
+  }).then(() =>
+    saveP(Bookmark({ url: 'http://github.com', title: 'github.com' }))
+  ).then(() => addVisits('http://bandcamp.com/'))
+  .then(() => searchP({ query: 'webfwd' }))
+  .then(results => {
+    results[0].title = 'new title for webfwd';
+    return saveP(results[0]);
+  })
+  .then(() =>
+    searchP({}, { sort: 'visitCount' })
+  ).then(results => {
+    assert.equal(results[5].url, 'http://mozilla.com/',
+      'last entry is the highest visit count');
+    return searchP({}, { sort: 'visitCount', descending: true });
+  }).then(results => {
+    assert.equal(results[0].url, 'http://mozilla.com/',
+      'first entry is the highest visit count');
+    return searchP({}, { sort: 'date' });
+  }).then(results => {
+    assert.equal(results[5].url, 'http://bandcamp.com/',
+      'latest visited should be first');
+    return searchP({}, { sort: 'date', descending: true });
+  }).then(results => {
+    assert.equal(results[0].url, 'http://bandcamp.com/',
+      'latest visited should be at the end');
+    return searchP({}, { sort: 'dateAdded' });
+  }).then(results => {
+    assert.equal(results[5].url, 'http://github.com/',
+     'last added should be at the end');
+    return searchP({}, { sort: 'dateAdded', descending: true });
+  }).then(results => {
+    assert.equal(results[0].url, 'http://github.com/',
+      'last added should be first');
+    return searchP({}, { sort: 'lastModified' });
+  }).then(results => {
+    assert.equal(results[5].url, 'http://mozilla.com/webfwd/',
+      'last modified should be last');
+    return searchP({}, { sort: 'lastModified', descending: true });
+  }).then(results => {
+    assert.equal(results[0].url, 'http://mozilla.com/webfwd/',
+      'last modified should be first');
+  }).then(() => {
+    done();
+  });
+
+  function checkOrder (results, nums) {
+    assert.equal(results.length, nums.length, 'expected return count');
+    for (let i = 0; i < nums.length; i++) {
+      assert.equal(results[i].url, urls[nums[i]], 'successful order');
+    }
+  }
+};
+
+exports.testSearchComplexQueryWithOptions = function (assert, done) {
+  createBookmarkTree().then(() => {
+    return searchP([
+      { tags: ['rust'], url: '*.mozilla.org' },
+      { tags: ['javascript'], query: 'mozilla' }
+    ], { sort: 'title' });
+  }).then(results => {
+    let expected = [
+      'http://developer.mozilla.org/en-US/',
+      'http://mozilla.org/'
+    ];
+    for (let i = 0; i < expected.length; i++)
+      assert.equal(results[i].url, expected[i], 'correct ordering and item');
+    done();
+  });
+};
+
+exports.testCheckSaveOrder = function (assert, done) {
+  let group = Group({ title: 'mygroup' });
+  let bookmarks = [
+    Bookmark({ url: 'http://url1.com', title: 'url1', group: group }),
+    Bookmark({ url: 'http://url2.com', title: 'url2', group: group }),
+    Bookmark({ url: 'http://url3.com', title: 'url3', group: group }),
+    Bookmark({ url: 'http://url4.com', title: 'url4', group: group }),
+    Bookmark({ url: 'http://url5.com', title: 'url5', group: group })
+  ];
+  saveP(bookmarks).then(results => {
+    for (let i = 0; i < bookmarks.length; i++)
+      assert.equal(results[i].url, bookmarks[i].url,
+        'correct ordering of bookmark results');
+    done();
+  });
+};
+
+before(exports, (name, assert, done) => resetPlaces(done));
+after(exports, (name, assert, done) => resetPlaces(done));
+
+function saveP () {
+  return promisedEmitter(save.apply(null, Array.slice(arguments)));
+}
+
+function searchP () {
+  return promisedEmitter(search.apply(null, Array.slice(arguments)));
+}
+
+function delayed (value, ms) {
+  let { promise, resolve } = defer();
+  setTimeout(() => resolve(value), ms || 10);
+  return promise;
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/places/tests/test-places-events.js
@@ -0,0 +1,291 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+'use strict';
+
+module.metadata = {
+  'engines': {
+    'Firefox': '*'
+  }
+};
+
+const { Cc, Ci } = require('chrome');
+const { defer, all } = require('sdk/core/promise');
+const { filter } = require('sdk/event/utils');
+const { on, off } = require('sdk/event/core');
+const { events } = require('sdk/places/events');
+const { setTimeout } = require('sdk/timers');
+const { before, after } = require('sdk/test/utils');
+const {
+  search
+} = require('sdk/places/history');
+const {
+  invalidResolve, invalidReject, createTree, createBookmark,
+  compareWithHost, addVisits, resetPlaces, createBookmarkItem,
+  removeVisits
+} = require('../places-helper');
+const { save, MENU, UNSORTED } = require('sdk/places/bookmarks');
+const { promisedEmitter } = require('sdk/places/utils');
+
+exports['test bookmark-item-added'] = function (assert, done) {
+  function handler ({type, data}) {
+    if (type !== 'bookmark-item-added') return;
+    if (data.title !== 'bookmark-added-title') return;
+
+    assert.equal(type, 'bookmark-item-added', 'correct type in bookmark-added event');
+    assert.equal(data.type, 'bookmark', 'correct data in bookmark-added event');
+    assert.ok(data.id != null, 'correct data in bookmark-added event');
+    assert.ok(data.parentId != null, 'correct data in bookmark-added event');
+    assert.ok(data.index != null, 'correct data in bookmark-added event');
+    assert.equal(data.url, 'http://moz.com/', 'correct data in bookmark-added event');
+    assert.ok(data.dateAdded != null, 'correct data in bookmark-added event');
+    events.off('data', handler);
+    done();
+  }
+  events.on('data', handler);
+  createBookmark({ title: 'bookmark-added-title' });
+};
+
+exports['test bookmark-item-changed'] = function (assert, done) {
+  let id;
+  let complete = makeCompleted(done);
+  function handler ({type, data}) {
+    if (type !== 'bookmark-item-changed') return;
+    if (data.id !== id) return;
+    assert.equal(type, 'bookmark-item-changed',
+      'correct type in bookmark-item-changed event');
+    assert.equal(data.type, 'bookmark',
+      'correct data in bookmark-item-changed event');
+    assert.equal(data.property, 'title',
+      'correct property in bookmark-item-changed event');
+    assert.equal(data.value, 'bookmark-changed-title-2',
+      'correct value in bookmark-item-changed event');
+    assert.ok(data.id === id, 'correct id in bookmark-item-changed event');
+    assert.ok(data.parentId != null, 'correct data in bookmark-added event');
+
+    events.off('data', handler);
+    complete();
+  }
+  events.on('data', handler);
+
+  createBookmarkItem({ title: 'bookmark-changed-title' }).then(item => {
+    id = item.id;
+    item.title = 'bookmark-changed-title-2';
+    return saveP(item);
+  }).then(complete);
+};
+
+exports['test bookmark-item-moved'] = function (assert, done) {
+  let id;
+  let complete = makeCompleted(done);
+  function handler ({type, data}) {
+    if (type !== 'bookmark-item-moved') return;
+    if (data.id !== id) return;
+    assert.equal(type, 'bookmark-item-moved',
+      'correct type in bookmark-item-moved event');
+    assert.equal(data.type, 'bookmark',
+      'correct data in bookmark-item-moved event');
+    assert.ok(data.id === id, 'correct id in bookmark-item-moved event');
+    assert.equal(data.previousParentId, UNSORTED.id,
+      'correct previousParentId');
+    assert.equal(data.currentParentId, MENU.id,
+      'correct currentParentId');
+    assert.equal(data.previousIndex, 0, 'correct previousIndex');
+    assert.equal(data.currentIndex, 0, 'correct currentIndex');
+
+    events.off('data', handler);
+    complete();
+  }
+  events.on('data', handler);
+
+  createBookmarkItem({
+    title: 'bookmark-moved-title',
+    group: UNSORTED
+  }).then(item => {
+    id = item.id;
+    item.group = MENU;
+    return saveP(item);
+  }).then(complete);
+};
+
+exports['test bookmark-item-removed'] = function (assert, done) {
+  let id;
+  let complete = makeCompleted(done);
+  function handler ({type, data}) {
+    if (type !== 'bookmark-item-removed') return;
+    if (data.id !== id) return;
+    assert.equal(type, 'bookmark-item-removed',
+      'correct type in bookmark-item-removed event');
+    assert.equal(data.type, 'bookmark',
+      'correct data in bookmark-item-removed event');
+    assert.ok(data.id === id, 'correct id in bookmark-item-removed event');
+    assert.equal(data.parentId, UNSORTED.id,
+      'correct parentId in bookmark-item-removed');
+    assert.equal(data.url, 'http://moz.com/',
+      'correct url in bookmark-item-removed event');
+    assert.equal(data.index, 0,
+      'correct index in bookmark-item-removed event');
+
+    events.off('data', handler);
+    complete();
+  }
+  events.on('data', handler);
+
+  createBookmarkItem({
+    title: 'bookmark-item-remove-title',
+    group: UNSORTED
+  }).then(item => {
+    id = item.id;
+    item.remove = true;
+    return saveP(item);
+  }).then(complete);
+};
+
+exports['test bookmark-item-visited'] = function (assert, done) {
+  let id;
+  let complete = makeCompleted(done);
+  function handler ({type, data}) {
+    if (type !== 'bookmark-item-visited') return;
+    if (data.id !== id) return;
+    assert.equal(type, 'bookmark-item-visited',
+      'correct type in bookmark-item-visited event');
+    assert.ok(data.id === id, 'correct id in bookmark-item-visited event');
+    assert.equal(data.parentId, UNSORTED.id,
+      'correct parentId in bookmark-item-visited');
+    assert.ok(data.transitionType != null,
+      'has a transition type in bookmark-item-visited event');
+    assert.ok(data.time != null,
+      'has a time in bookmark-item-visited event');
+    assert.ok(data.visitId != null,
+      'has a visitId in bookmark-item-visited event');
+    assert.equal(data.url, 'http://bookmark-item-visited.com/',
+      'correct url in bookmark-item-visited event');
+
+    events.off('data', handler);
+    complete();
+  }
+  events.on('data', handler);
+
+  createBookmarkItem({
+    title: 'bookmark-item-visited',
+    url: 'http://bookmark-item-visited.com/'
+  }).then(item => {
+    id = item.id;
+    return addVisits('http://bookmark-item-visited.com/');
+  }).then(complete);
+};
+
+exports['test history-start-batch, history-end-batch, history-start-clear'] = function (assert, done) {
+  let complete = makeCompleted(done, 4);
+  let startEvent = filter(events, ({type}) => type === 'history-start-batch');
+  let endEvent = filter(events, ({type}) => type === 'history-end-batch');
+  let clearEvent = filter(events, ({type}) => type === 'history-start-clear');
+  function startHandler ({type, data}) {
+    assert.pass('history-start-batch called');
+    assert.equal(type, 'history-start-batch',
+      'history-start-batch has correct type');
+    off(startEvent, 'data', startHandler);
+    on(endEvent, 'data', endHandler);
+    complete();
+  }
+  function endHandler ({type, data}) {
+    assert.pass('history-end-batch called');
+    assert.equal(type, 'history-end-batch',
+      'history-end-batch has correct type');
+    off(endEvent, 'data', endHandler);
+    complete();
+  }
+  function clearHandler ({type, data}) {
+    assert.pass('history-start-clear called');
+    assert.equal(type, 'history-start-clear',
+      'history-start-clear has correct type');
+    off(clearEvent, 'data', clearHandler);
+    complete();
+  }
+ 
+  on(startEvent, 'data', startHandler);
+  on(clearEvent, 'data', clearHandler);
+
+  createBookmark().then(() => {
+    resetPlaces(complete);
+  })
+};
+
+exports['test history-visit, history-title-changed'] = function (assert, done) {
+  let complete = makeCompleted(() => {
+    off(titleEvents, 'data', titleHandler);
+    off(visitEvents, 'data', visitHandler);
+    done();
+  }, 6);
+  let visitEvents = filter(events, ({type}) => type === 'history-visit');
+  let titleEvents = filter(events, ({type}) => type === 'history-title-changed');
+
+  let urls = ['http://moz.com/', 'http://firefox.com/', 'http://mdn.com/'];
+
+  function visitHandler ({type, data}) {
+    assert.equal(type, 'history-visit', 'correct type in history-visit');
+    assert.ok(~urls.indexOf(data.url), 'history-visit has correct url');
+    assert.ok(data.visitId != null, 'history-visit has a visitId');
+    assert.ok(data.time != null, 'history-visit has a time');
+    assert.ok(data.sessionId != null, 'history-visit has a sessionId');
+    assert.ok(data.referringId != null, 'history-visit has a referringId');
+    assert.ok(data.transitionType != null, 'history-visit has a transitionType');
+    complete();
+  }
+
+  function titleHandler ({type, data}) {
+    assert.equal(type, 'history-title-changed',
+      'correct type in history-title-changed');
+    assert.ok(~urls.indexOf(data.url),
+      'history-title-changed has correct url');
+    assert.ok(data.title, 'history-title-changed has title');
+    complete();
+  }
+
+  on(titleEvents, 'data', titleHandler);
+  on(visitEvents, 'data', visitHandler);
+  addVisits(urls);
+}
+
+exports['test history-delete-url'] = function (assert, done) {
+  let complete = makeCompleted(() => {
+    events.off('data', handler);
+    done();
+  }, 3);
+  let urls = ['http://moz.com/', 'http://firefox.com/', 'http://mdn.com/'];
+  function handler({type, data}) {
+    if (type !== 'history-delete-url') return;
+    assert.equal(type, 'history-delete-url',
+      'history-delete-url has correct type');
+    assert.ok(~urls.indexOf(data.url), 'history-delete-url has correct url');
+    complete();
+  }
+
+  events.on('data', handler);
+  addVisits(urls).then(() => {
+    removeVisits(urls);
+  });
+};
+
+exports['test history-page-changed'] = function (assert) {
+  assert.pass('history-page-changed tested in test-places-favicons');
+};
+
+exports['test history-delete-visits'] = function (assert) {
+  assert.pass('TODO test history-delete-visits');
+};
+
+before(exports, (name, assert, done) => resetPlaces(done));
+after(exports, (name, assert, done) => resetPlaces(done));
+
+function saveP () {
+  return promisedEmitter(save.apply(null, Array.slice(arguments)));
+}
+
+function makeCompleted (done, countTo) {
+  let count = 0;
+  countTo = countTo || 2;
+  return function () {
+    if (++count === countTo) done();
+  };
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/places/tests/test-places-favicon.js
@@ -0,0 +1,188 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+module.metadata = {
+  'engines': {
+    'Firefox': '*'
+  }
+};
+
+const { Cc, Ci, Cu } = require('chrome');
+const { getFavicon } = require('sdk/places/favicon');
+const tabs = require('sdk/tabs');
+const open = tabs.open;
+const port = 8099;
+const host = 'http://localhost:' + port;
+const { onFaviconChange, serve, binFavicon } = require('../favicon-helpers');
+const { once } = require('sdk/system/events');
+const { defer } = require('sdk/core/promise');
+const { resetPlaces } = require('../places-helper');
+const faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
+                         getService(Ci.nsIFaviconService);
+
+exports.testStringGetFaviconCallbackSuccess = function (assert, done) {
+  let name = 'callbacksuccess'
+  let srv = makeServer(name);
+  let url = host + '/' + name + '.html';
+  let favicon = host + '/' + name + '.ico';
+  let tab;
+
+  onFaviconChange(url, function (faviconUrl) {
+    getFavicon(url, function (url) {
+      assert.equal(favicon, url, 'Callback returns correct favicon url');
+      complete(tab, srv, done);
+    });
+  });
+
+  open({
+    url: url,
+    onOpen: function (newTab) tab = newTab,
+    inBackground: true
+  });
+};
+
+exports.testStringGetFaviconCallbackFailure = function (assert, done) {
+  let name = 'callbackfailure';
+  let srv = makeServer(name);
+  let url = host + '/' + name + '.html';
+  let tab;
+
+  waitAndExpire(url).then(function () {
+    getFavicon(url, function (url) {
+      assert.equal(url, null, 'Callback returns null');
+      complete(tab, srv, done);
+    });
+  });
+
+  open({
+    url: url,
+    onOpen: function (newTab) tab = newTab,
+    inBackground: true
+  });
+};
+
+exports.testStringGetFaviconPromiseSuccess = function (assert, done) {
+  let name = 'promisesuccess'
+  let srv = makeServer(name);
+  let url = host + '/' + name + '.html';
+  let favicon = host + '/' + name + '.ico';
+  let tab;
+
+  onFaviconChange(url, function (faviconUrl) {
+    getFavicon(url).then(function (url) {
+      assert.equal(url, favicon, 'Callback returns null');
+    }, function (err) {
+      assert.fail('Reject should not be called');
+    }).then(complete.bind(null, tab, srv, done));
+  });
+
+  open({
+    url: url,
+    onOpen: function (newTab) tab = newTab,
+    inBackground: true
+  });
+};
+
+exports.testStringGetFaviconPromiseFailure = function (assert, done) {
+  let name = 'promisefailure'
+  let srv = makeServer(name);
+  let url = host + '/' + name + '.html';
+  let tab;
+
+  waitAndExpire(url).then(function () {
+    getFavicon(url).then(invalidResolve(assert), validReject(assert, 'expired url'))
+      .then(complete.bind(null, tab, srv, done));
+  });
+
+  open({
+    url: url,
+    onOpen: function (newTab) tab = newTab,
+    inBackground: true
+  });
+};
+
+exports.testTabsGetFaviconPromiseSuccess = function (assert, done) {
+  let name = 'tabs-success'
+  let srv = makeServer(name);
+  let url = host + '/' + name + '.html';
+  let favicon = host + '/' + name + '.ico';
+  let tab;
+
+  onFaviconChange(url, function () {
+    getFavicon(tab).then(function (url) {
+      assert.equal(url, favicon, "getFavicon should return url for tab");
+      complete(tab, srv, done);
+    });
+  });
+
+  open({
+    url: url,
+    onOpen: function (newTab) tab = newTab,
+    inBackground: true
+  });
+};
+
+
+exports.testTabsGetFaviconPromiseFailure = function (assert, done) {
+  let name = 'tabs-failure'
+  let srv = makeServer(name);
+  let url = host + '/' + name + '.html';
+  let tab;
+
+  waitAndExpire(url).then(function () {
+    getFavicon(tab).then(invalidResolve(assert), validReject(assert, 'expired tab'))
+      .then(complete.bind(null, tab, srv, done));
+  });
+
+  open({
+    url: url,
+    onOpen: function (newTab) tab = newTab,
+    inBackground: true
+  });
+};
+
+exports.testRejects = function (assert, done) {
+  getFavicon({})
+    .then(invalidResolve(assert), validReject(assert, 'Object'))
+  .then(getFavicon(null))
+    .then(invalidResolve(assert), validReject(assert, 'null'))
+  .then(getFavicon(undefined))
+    .then(invalidResolve(assert), validReject(assert, 'undefined'))
+  .then(getFavicon([]))
+    .then(invalidResolve(assert), validReject(assert, 'Array'))
+    .then(done);
+};
+
+function invalidResolve (assert) {
+  return function () assert.fail('Promise should not be resolved successfully');
+}
+
+function validReject (assert, name) {
+  return function () assert.pass(name + ' correctly rejected');
+}
+
+function makeServer (name) {
+  return serve({name: name, favicon: binFavicon, port: port, host: host});
+}
+
+function waitAndExpire (url) {
+  let deferred = defer();
+  onFaviconChange(url, function (faviconUrl) {
+    once('places-favicons-expired', function () {
+      deferred.resolve();
+    });
+    faviconService.expireAllFavicons();
+  });
+  return deferred.promise;
+}
+
+function complete(tab, srv, done) {
+  tab.close(function () {
+    resetPlaces(() => {
+      srv.stop(done);
+    });
+  });
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/places/tests/test-places-history.js
@@ -0,0 +1,249 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+'use strict';
+
+module.metadata = {
+  'engines': {
+    'Firefox': '*'
+  }
+};
+
+const { Cc, Ci } = require('chrome');
+const { defer, all } = require('sdk/core/promise');
+const { has } = require('sdk/util/array');
+const { setTimeout } = require('sdk/timers');
+const { before, after } = require('sdk/test/utils');
+const { set } = require('sdk/preferences/service');
+const {
+  search 
+} = require('sdk/places/history');
+const {
+  invalidResolve, invalidReject, createTree,
+  compareWithHost, addVisits, resetPlaces
+} = require('../places-helper');
+const { promisedEmitter } = require('sdk/places/utils');
+
+exports.testEmptyQuery = function (assert, done) {
+  let within = toBeWithin();
+  addVisits([
+    'http://simplequery-1.com', 'http://simplequery-2.com'
+  ]).then(searchP).then(results => {
+    assert.equal(results.length, 2, 'Correct number of entries returned');
+    assert.equal(results[0].url, 'http://simplequery-1.com/',
+      'matches url');
+    assert.equal(results[1].url, 'http://simplequery-2.com/',
+      'matches url');
+    assert.equal(results[0].title, 'Test visit for ' + results[0].url,
+      'title matches');
+    assert.equal(results[1].title, 'Test visit for ' + results[1].url,
+      'title matches');
+    assert.equal(results[0].visitCount, 1, 'matches access');
+    assert.equal(results[1].visitCount, 1, 'matches access');
+    assert.ok(within(results[0].time), 'accurate access time');
+    assert.ok(within(results[1].time), 'accurate access time');
+    assert.equal(Object.keys(results[0]).length, 4,
+      'no addition exposed properties on history result');
+    done();
+  }, invalidReject);
+};
+
+exports.testVisitCount = function (assert, done) {
+  addVisits([
+    'http://simplequery-1.com', 'http://simplequery-1.com',
+    'http://simplequery-1.com', 'http://simplequery-1.com'
+  ]).then(searchP).then(results => {
+    assert.equal(results.length, 1, 'Correct number of entries returned');
+    assert.equal(results[0].url, 'http://simplequery-1.com/', 'correct url');
+    assert.equal(results[0].visitCount, 4, 'matches access count');
+    done();
+  }, invalidReject);
+};
+
+/*
+ * Tests 4 scenarios
+ * '*.mozilla.org'
+ * 'mozilla.org'
+ * 'http://mozilla.org/'
+ * 'http://mozilla.org/*'
+ */
+exports.testSearchURL = function (assert, done) {
+  addVisits([
+    'http://developer.mozilla.org', 'http://mozilla.org',
+    'http://mozilla.org/index', 'https://mozilla.org'
+  ]).then(() => searchP({ url: '*.mozilla.org' }))
+  .then(results => {
+    assert.equal(results.length, 4, 'returns all entries');
+    return searchP({ url: 'mozilla.org' });
+  }).then(results => {
+    assert.equal(results.length, 3, 'returns entries where mozilla.org is host');
+    return searchP({ url: 'http://mozilla.org/' });
+  }).then(results => {
+    assert.equal(results.length, 1, 'should just be an exact match');
+    return searchP({ url: 'http://mozilla.org/*' });
+  }).then(results => {
+    assert.equal(results.length, 2, 'should match anything starting with substring');
+    done();
+  });
+};
+
+// Disabling due to intermittent Bug 892619
+// TODO solve this
+/*
+exports.testSearchTimeRange = function (assert, done) {
+  let firstTime, secondTime;
+  addVisits([
+    'http://earlyvisit.org', 'http://earlyvisit.org/earlytown.html'
+  ]).then(searchP).then(results => {
+    firstTime = results[0].time;
+    var deferred = defer();
+    setTimeout(function () deferred.resolve(), 1000);
+    return deferred.promise;
+  }).then(() => {
+    return addVisits(['http://newvisit.org', 'http://newvisit.org/whoawhoa.html']);
+  }).then(searchP).then(results => {
+    results.filter(({url, time}) => {
+      if (/newvisit/.test(url)) secondTime = time;
+    });
+    return searchP({ from: firstTime - 1000 });
+  }).then(results => {
+    assert.equal(results.length, 4, 'should return all entries');
+    return searchP({ to: firstTime + 500 });
+  }).then(results => {
+    assert.equal(results.length, 2, 'should return only first entries');
+    results.map(item => {
+      assert.ok(/earlyvisit/.test(item.url), 'correct entry');
+    });
+    return searchP({ from: firstTime + 500 });
+  }).then(results => {
+    assert.equal(results.length, 2, 'should return only last entries');
+    results.map(item => {
+      assert.ok(/newvisit/.test(item.url), 'correct entry');
+    });
+    done();
+  });
+};
+*/
+exports.testSearchQuery = function (assert, done) {
+  addVisits([
+    'http://mozilla.com', 'http://webaud.io', 'http://mozilla.com/webfwd'
+  ]).then(() => {
+    return searchP({ query: 'moz' });
+  }).then(results => {
+    assert.equal(results.length, 2, 'should return urls that match substring');
+    results.map(({url}) => {
+      assert.ok(/moz/.test(url), 'correct item');
+    });
+    return searchP([{ query: 'webfwd' }, { query: 'aud.io' }]);
+  }).then(results => {
+    assert.equal(results.length, 2, 'should OR separate queries');
+    results.map(({url}) => {
+      assert.ok(/webfwd|aud\.io/.test(url), 'correct item');
+    });
+    done();
+  });
+};
+
+/*
+ * Query Options
+ */
+
+exports.testSearchCount = function (assert, done) {
+  addVisits([
+    'http://mozilla.com', 'http://webaud.io', 'http://mozilla.com/webfwd',
+    'http://developer.mozilla.com', 'http://bandcamp.com'
+  ]).then(testCount(1))
+  .then(testCount(2))
+  .then(testCount(3))
+  .then(testCount(5))
+  .then(done);
+
+  function testCount (n) {
+    return function () {
+      return searchP({}, { count: n }).then(results => {
+        assert.equal(results.length, n,
+          'count ' + n + ' returns ' + n + ' results');
+      });
+    };
+  }
+};
+
+exports.testSearchSort = function (assert, done) {
+  let places = [
+    'http://mozilla.com/', 'http://webaud.io/', 'http://mozilla.com/webfwd/',
+    'http://developer.mozilla.com/', 'http://bandcamp.com/'
+  ];
+  addVisits(places).then(() => {
+    return searchP({}, { sort: 'title' });
+  }).then(results => {
+    checkOrder(results, [4,3,0,2,1]);
+    return searchP({}, { sort: 'title', descending: true });
+  }).then(results => {
+    checkOrder(results, [1,2,0,3,4]);
+    return searchP({}, { sort: 'url' });
+  }).then(results => {
+    checkOrder(results, [4,3,0,2,1]);
+    return searchP({}, { sort: 'url', descending: true });
+  }).then(results => {
+    checkOrder(results, [1,2,0,3,4]);
+    return addVisits('http://mozilla.com') // for visit conut
+      .then(() => addVisits('http://github.com')); // for checking date
+  }).then(() => {
+    return searchP({}, { sort: 'visitCount' });
+  }).then(results => {
+    assert.equal(results[5].url, 'http://mozilla.com/',
+      'last entry is the highest visit count');
+    return searchP({}, { sort: 'visitCount', descending: true });
+  }).then(results => {
+    assert.equal(results[0].url, 'http://mozilla.com/',
+      'first entry is the highest visit count');
+    return searchP({}, { sort: 'date' });
+  }).then(results => {
+    assert.equal(results[5].url, 'http://github.com/',
+      'latest visited should be first');
+    return searchP({}, { sort: 'date', descending: true });
+  }).then(results => {
+    assert.equal(results[0].url, 'http://github.com/',
+      'latest visited should be at the end');
+  }).then(done);
+
+  function checkOrder (results, nums) {
+    assert.equal(results.length, nums.length, 'expected return count');
+    for (let i = 0; i < nums.length; i++) {
+      assert.equal(results[i].url, places[nums[i]], 'successful order');
+    }
+  }
+};
+
+exports.testEmitters = function (assert, done) {
+  let urls = [
+    'http://mozilla.com/', 'http://webaud.io/', 'http://mozilla.com/webfwd/',
+    'http://developer.mozilla.com/', 'http://bandcamp.com/'
+  ];
+  addVisits(urls).then(() => {
+    let count = 0;
+    search().on('data', item => {
+      assert.ok(~urls.indexOf(item.url), 'data value found in url list');
+      count++;
+    }).on('end', results => {
+      assert.equal(results.length, 5, 'correct count of items');
+      assert.equal(count, 5, 'data event called 5 times');
+      done();
+    });
+  });
+};
+
+function toBeWithin (range) {
+  range = range || 2000;
+  var current = new Date() * 1000; // convert to microseconds
+  return compared => { 
+    return compared - current < range;
+  };
+}
+
+function searchP () {
+  return promisedEmitter(search.apply(null, Array.slice(arguments)));
+}
+
+before(exports, (name, assert, done) => resetPlaces(done));
+after(exports, (name, assert, done) => resetPlaces(done));
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/places/tests/test-places-host.js
@@ -0,0 +1,303 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+'use strict';
+
+module.metadata = {
+  'engines': {
+    'Firefox': '*'
+  }
+};
+
+const { Cc, Ci } = require('chrome');
+const { defer, all } = require('sdk/core/promise');
+const { setTimeout } = require('sdk/timers');
+const { newURI } = require('sdk/url/utils');
+const { send } = require('sdk/addon/events');
+const { set } = require('sdk/preferences/service');
+const { before, after } = require('sdk/test/utils');
+
+require('sdk/places/host/host-bookmarks');
+require('sdk/places/host/host-tags');
+require('sdk/places/host/host-query');
+const {
+  invalidResolve, invalidReject, createTree,
+  compareWithHost, createBookmark, createBookmarkTree, resetPlaces
+} = require('../places-helper');
+
+const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
+                    getService(Ci.nsINavBookmarksService);
+const hsrv = Cc['@mozilla.org/browser/nav-history-service;1'].
+              getService(Ci.nsINavHistoryService);
+const tagsrv = Cc['@mozilla.org/browser/tagging-service;1'].
+              getService(Ci.nsITaggingService);
+
+exports.testBookmarksCreate = function (assert, done) {
+  let items = [{
+    title: 'my title',
+    url: 'http://test-places-host.com/testBookmarksCreate/',
+    tags: ['some', 'tags', 'yeah'],
+    type: 'bookmark'
+  }, {
+    title: 'my folder',
+    type: 'group',
+    group: bmsrv.bookmarksMenuFolder
+  }, {
+    type: 'separator',
+    group: bmsrv.unfiledBookmarksFolder
+  }];
+
+  all(items.map(function (item) {
+    return send('sdk-places-bookmarks-create', item).then(function (data) {
+      compareWithHost(assert, data);
+    }, invalidReject(assert));
+  })).then(function () {
+    done();
+  }, invalidReject(assert));
+};
+
+exports.testBookmarksCreateFail = function (assert, done) {
+  let items = [{
+    title: 'my title',
+    url: 'not-a-url',
+    type: 'bookmark'
+  }, {
+    type: 'group',
+    group: bmsrv.bookmarksMenuFolder
+  }, {
+    group: bmsrv.unfiledBookmarksFolder
+  }];
+  all(items.map(function (item) {
+    return send('sdk-places-bookmarks-create', item).then(null, function (reason) {
+      assert.ok(reason, 'bookmark create should fail');
+    });
+  })).then(done);
+};
+
+exports.testBookmarkLastUpdated = function (assert, done) {
+  let timestamp;
+  let item;
+  createBookmark({
+    url: 'http://test-places-host.com/testBookmarkLastUpdated'
+  }).then(function (data) {
+    item = data;
+    timestamp = item.updated;
+    return send('sdk-places-bookmarks-last-updated', { id: item.id });
+  }).then(function (updated) {
+    let { resolve, promise } = defer();
+    assert.equal(timestamp, updated, 'should return last updated time');
+    item.title = 'updated mozilla';
+    setTimeout(() => {
+      resolve(send('sdk-places-bookmarks-save', item));
+    }, 100);
+    return promise;
+  }).then(function (data) {
+    assert.ok(data.updated > timestamp, 'time has elapsed and updated the updated property');
+    done();
+  });
+};
+
+exports.testBookmarkRemove = function (assert, done) {
+  let id;
+  createBookmark({
+    url: 'http://test-places-host.com/testBookmarkRemove/'
+  }).then(function (data) {
+    id = data.id;
+    compareWithHost(assert, data); // ensure bookmark exists
+    bmsrv.getItemTitle(id); // does not throw an error
+    return send('sdk-places-bookmarks-remove', data);
+  }).then(function () {
+    assert.throws(function () {
+      bmsrv.getItemTitle(id);
+    }, 'item should no longer exist');
+    done();
+  }, assert.fail);
+};
+
+exports.testBookmarkGet = function (assert, done) {
+  let bookmark;
+  createBookmark({
+    url: 'http://test-places-host.com/testBookmarkGet/'
+  }).then(function (data) {
+    bookmark = data;
+    return send('sdk-places-bookmarks-get', { id: data.id });
+  }).then(function (data) {
+    'title url index group updated type tags'.split(' ').map(function (prop) {
+      if (prop === 'tags') {
+        for (let tag of bookmark.tags) {
+          assert.ok(~data.tags.indexOf(tag),
+            'correctly fetched tag ' + tag);
+        }
+        assert.equal(bookmark.tags.length, data.tags.length,
+          'same amount of tags');
+      }
+      else
+        assert.equal(bookmark[prop], data[prop], 'correctly fetched ' + prop);
+    });
+    done();
+  });
+};
+
+exports.testTagsTag = function (assert, done) {
+  let url;
+  createBookmark({
+    url: 'http://test-places-host.com/testTagsTag/',
+  }).then(function (data) {
+    url = data.url;
+    return send('sdk-places-tags-tag', {
+      url: data.url, tags: ['mozzerella', 'foxfire']
+    });
+  }).then(function () {
+    let tags = tagsrv.getTagsForURI(newURI(url));
+    assert.ok(~tags.indexOf('mozzerella'), 'first tag found');
+    assert.ok(~tags.indexOf('foxfire'), 'second tag found');
+    assert.ok(~tags.indexOf('firefox'), 'default tag found');
+    assert.equal(tags.length, 3, 'no extra tags');
+    done();
+  });
+};
+
+exports.testTagsUntag = function (assert, done) {
+  let item;
+  createBookmark({
+    url: 'http://test-places-host.com/testTagsUntag/',
+    tags: ['tag1', 'tag2', 'tag3']
+  }).then(data => {
+    item = data;
+    return send('sdk-places-tags-untag', {
+      url: item.url,
+      tags: ['tag2', 'firefox']
+    });
+  }).then(function () {
+    let tags = tagsrv.getTagsForURI(newURI(item.url));
+    assert.ok(~tags.indexOf('tag1'), 'first tag persisted');
+    assert.ok(~tags.indexOf('tag3'), 'second tag persisted');
+    assert.ok(!~tags.indexOf('firefox'), 'first tag removed');
+    assert.ok(!~tags.indexOf('tag2'), 'second tag removed');
+    assert.equal(tags.length, 2, 'no extra tags');
+    done();
+  });
+};
+
+exports.testTagsGetURLsByTag = function (assert, done) {
+  let item;
+  createBookmark({
+    url: 'http://test-places-host.com/testTagsGetURLsByTag/'
+  }).then(function (data) {
+    item = data;
+    return send('sdk-places-tags-get-urls-by-tag', {
+      tag: 'firefox'
+    });
+  }).then(function(urls) {
+    assert.equal(item.url, urls[0], 'returned correct url');
+    assert.equal(urls.length, 1, 'returned only one url');
+    done();
+  });
+};
+
+exports.testTagsGetTagsByURL = function (assert, done) {
+  let item;
+  createBookmark({
+    url: 'http://test-places-host.com/testTagsGetURLsByTag/',
+    tags: ['firefox', 'mozilla', 'metal']
+  }).then(function (data) {
+    item = data;
+    return send('sdk-places-tags-get-tags-by-url', {
+      url: data.url,
+    });
+  }).then(function(tags) {
+    assert.ok(~tags.indexOf('firefox'), 'returned first tag');
+    assert.ok(~tags.indexOf('mozilla'), 'returned second tag');
+    assert.ok(~tags.indexOf('metal'), 'returned third tag');
+    assert.equal(tags.length, 3, 'returned all tags');
+    done();
+  });
+};
+
+exports.testHostQuery = function (assert, done) {
+  all([
+    createBookmark({
+      url: 'http://firefox.com/testHostQuery/',
+      tags: ['firefox', 'mozilla']
+    }),
+    createBookmark({
+      url: 'http://mozilla.com/testHostQuery/',
+      tags: ['mozilla']
+    }),
+    createBookmark({ url: 'http://thunderbird.com/testHostQuery/' })
+  ]).then(data => {
+    return send('sdk-places-query', {
+      queries: { tags: ['mozilla'] },
+      options: { sortingMode: 6, queryType: 1 } // sort by URI ascending, bookmarks only
+    });
+  }).then(results => {
+    assert.equal(results.length, 2, 'should only return two');
+    assert.equal(results[0].url,
+      'http://mozilla.com/testHostQuery/', 'is sorted by URI asc');
+    return send('sdk-places-query', {
+      queries: { tags: ['mozilla'] },
+      options: { sortingMode: 5, queryType: 1 } // sort by URI descending, bookmarks only
+    });
+  }).then(results => {
+    assert.equal(results.length, 2, 'should only return two');
+    assert.equal(results[0].url,
+      'http://firefox.com/testHostQuery/', 'is sorted by URI desc');
+    done();
+  });
+};
+
+exports.testHostMultiQuery = function (assert, done) {
+  all([
+    createBookmark({
+      url: 'http://firefox.com/testHostMultiQuery/',
+      tags: ['firefox', 'mozilla']
+    }),
+    createBookmark({
+      url: 'http://mozilla.com/testHostMultiQuery/',
+      tags: ['mozilla']
+    }),
+    createBookmark({ url: 'http://thunderbird.com/testHostMultiQuery/' })
+  ]).then(data => {
+    return send('sdk-places-query', {
+      queries: [{ tags: ['firefox'] }, { uri: 'http://thunderbird.com/testHostMultiQuery/' }],
+      options: { sortingMode: 5, queryType: 1 } // sort by URI descending, bookmarks only
+    });
+  }).then(results => {
+    assert.equal(results.length, 2, 'should return 2 results ORing queries');
+    assert.equal(results[0].url,
+      'http://firefox.com/testHostMultiQuery/', 'should match URL or tag');
+    assert.equal(results[1].url,
+      'http://thunderbird.com/testHostMultiQuery/', 'should match URL or tag');
+    return send('sdk-places-query', {
+      queries: [{ tags: ['firefox'], url: 'http://mozilla.com/testHostMultiQuery/' }],
+      options: { sortingMode: 5, queryType: 1 } // sort by URI descending, bookmarks only
+    });
+  }).then(results => {
+    assert.equal(results.length, 0, 'query props should be AND\'d');
+    done();
+  });
+};
+
+exports.testGetAllBookmarks = function (assert, done) {
+  createBookmarkTree().then(() => {
+    return send('sdk-places-bookmarks-get-all', {});
+  }).then(res => {
+    assert.equal(res.length, 8, 'all bookmarks returned');
+    done();
+  }, assert.fail);
+};
+
+exports.testGetAllChildren = function (assert, done) {
+  createBookmarkTree().then(results => {
+    return send('sdk-places-bookmarks-get-children', {
+      id: results.filter(({title}) => title === 'mozgroup')[0].id
+    });
+  }).then(results => {
+    assert.equal(results.length, 5,
+      'should return all children and folders at a single depth');
+    done();
+  });
+};
+
+before(exports, (name, assert, done) => resetPlaces(done));
+after(exports, (name, assert, done) => resetPlaces(done));
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/places/tests/test-places-utils.js
@@ -0,0 +1,79 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+'use strict';
+
+module.metadata = {
+  'engines': {
+    'Firefox': '*'
+  }
+};
+
+const { defer, all } = require('sdk/core/promise');
+const { setTimeout } = require('sdk/timers');
+const { TreeNode } = require('sdk/places/utils');
+
+exports['test construct tree'] = function (assert) {
+  let tree = TreeNode(1);
+  tree.add([2, 3, 4]);
+  tree.get(2).add([2.1, 2.2, 2.3]);
+  let newTreeNode = TreeNode(4.3);
+  newTreeNode.add([4.31, 4.32]);
+  tree.get(4).add([4.1, 4.2, newTreeNode]);
+
+  assert.equal(tree.get(2).value, 2, 'get returns node with correct value');
+  assert.equal(tree.get(2.3).value, 2.3, 'get returns node with correct value');
+  assert.equal(tree.get(4.32).value, 4.32, 'get returns node even if created from nested node');
+  assert.equal(tree.get(4).children.length, 3, 'nodes have correct children length');
+  assert.equal(tree.get(3).children.length, 0, 'nodes have correct children length');
+
+  assert.equal(tree.get(4).get(4.32).value, 4.32, 'node.get descends from itself');
+  assert.equal(tree.get(4).get(2), null, 'node.get descends from itself fails if not descendant');
+};
+
+exports['test walk'] = function (assert) {
+  let resultsAll = [];
+  let tree = TreeNode(1);
+  tree.add([2, 3, 4]);
+  tree.get(2).add([2.1, 2.2]);
+
+  tree.walk(function (node) {
+    resultsAll.push(node.value);
+  });
+
+  [1, 2, 2.1, 2.2, 3, 4].forEach(function (num) {
+    assert.ok(~resultsAll.indexOf(num), 'function applied to each node from root');
+  });
+
+  let resultsNode = [];
+  tree.get(2).walk(function (node) resultsNode.push(node.value));
+
+  [2, 2.1, 2.2].forEach(function (num) {
+    assert.ok(~resultsNode.indexOf(num), 'function applied to each node from node');
+  });
+};
+
+exports['test async walk'] = function (assert, done) {
+  let resultsAll = [];
+  let tree = TreeNode(1);
+  tree.add([2, 3, 4]);
+  tree.get(2).add([2.1, 2.2]);
+
+  tree.walk(function (node) {
+    let deferred = defer();
+    setTimeout(function () {
+      resultsAll.push(node.value);
+      deferred.resolve(node.value);
+    }, node.value === 2 ? 50 : 5);
+    return deferred.promise;
+  }).then(function () {
+    [1, 2, 2.1, 2.2, 3, 4].forEach(function (num) {
+      assert.ok(~resultsAll.indexOf(num), 'function applied to each node from root');
+    });
+    assert.ok(resultsAll.indexOf(2) < resultsAll.indexOf(2.1),
+      'child should wait for parent to complete');
+    assert.ok(resultsAll.indexOf(2) < resultsAll.indexOf(2.2),
+      'child should wait for parent to complete');
+    done();
+  });
+};
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/self/data/data.md
@@ -0,0 +1,1 @@
+# hello world
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/self/main.js
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const self = require("sdk/self");
+
+exports["test self.data.load"] = assert => {
+
+  assert.equal(self.data.load("data.md"),
+               "# hello world\n",
+               "paths work");
+
+  assert.equal(self.data.load("./data.md"),
+               "# hello world\n",
+               "relative paths work");
+};
+
+require("sdk/test/runner").runTestsFromModule(module);
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/self/package.json
@@ -0,0 +1,3 @@
+{
+  "id": "test-self"
+}
rename from addon-sdk/source/data/test-trusted-document.html
rename to addon-sdk/source/test/addons/symbiont/data/test-trusted-document.html
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/symbiont/main.js
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { data } = require("sdk/self");
+const { Symbiont } = require("sdk/content/symbiont");
+
+exports["test:direct communication with trusted document"] = function(assert, done) {
+  let worker = Symbiont({
+    contentURL: data.url("test-trusted-document.html")
+  });
+
+  worker.port.on('document-to-addon', function (arg) {
+    assert.equal(arg, "ok", "Received an event from the document");
+    worker.destroy();
+    done();
+  });
+  worker.port.emit('addon-to-document', 'ok');
+};
+
+exports["test:`addon` is not available when a content script is set"] = function(assert, done) {
+  let worker = Symbiont({
+    contentURL: data.url("test-trusted-document.html"),
+    contentScript: "new " + function ContentScriptScope() {
+      self.port.emit("cs-to-addon", "addon" in unsafeWindow);
+    }
+  });
+
+  worker.port.on('cs-to-addon', function (hasAddon) {
+    assert.equal(hasAddon, false,
+      "`addon` is not available");
+    worker.destroy();
+    done();
+  });
+};
+
+require("sdk/test/runner").runTestsFromModule(module);
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/symbiont/package.json
@@ -0,0 +1,3 @@
+{
+  "id": "test-symbiont"
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/buffers/test-read-types.js
@@ -0,0 +1,368 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+const { Buffer } = require('sdk/io/buffer');
+
+exports.testReadDouble = helper('readDoubleLE/readDoubleBE', function (assert) {
+  var buffer = new Buffer(8);
+
+  buffer[0] = 0x55;
+  buffer[1] = 0x55;
+  buffer[2] = 0x55;
+  buffer[3] = 0x55;
+  buffer[4] = 0x55;
+  buffer[5] = 0x55;
+  buffer[6] = 0xd5;
+  buffer[7] = 0x3f;
+  assert.equal(1.1945305291680097e+103, buffer.readDoubleBE(0));
+  assert.equal(0.3333333333333333, buffer.readDoubleLE(0));
+
+  buffer[0] = 1;
+  buffer[1] = 0;
+  buffer[2] = 0;
+  buffer[3] = 0;
+  buffer[4] = 0;
+  buffer[5] = 0;
+  buffer[6] = 0xf0;
+  buffer[7] = 0x3f;
+  assert.equal(7.291122019655968e-304, buffer.readDoubleBE(0));
+  assert.equal(1.0000000000000002, buffer.readDoubleLE(0));
+
+  buffer[0] = 2;
+  assert.equal(4.778309726801735e-299, buffer.readDoubleBE(0));
+  assert.equal(1.0000000000000004, buffer.readDoubleLE(0));
+
+  buffer[0] = 1;
+  buffer[6] = 0;
+  buffer[7] = 0;
+  assert.equal(7.291122019556398e-304, buffer.readDoubleBE(0));
+  assert.equal(5e-324, buffer.readDoubleLE(0));
+
+  buffer[0] = 0xff;
+  buffer[1] = 0xff;
+  buffer[2] = 0xff;
+  buffer[3] = 0xff;
+  buffer[4] = 0xff;
+  buffer[5] = 0xff;
+  buffer[6] = 0x0f;
+  buffer[7] = 0x00;
+  assert.ok(isNaN(buffer.readDoubleBE(0)));
+  assert.equal(2.225073858507201e-308, buffer.readDoubleLE(0));
+
+  buffer[6] = 0xef;
+  buffer[7] = 0x7f;
+  assert.ok(isNaN(buffer.readDoubleBE(0)));
+  assert.equal(1.7976931348623157e+308, buffer.readDoubleLE(0));
+
+  buffer[0] = 0;
+  buffer[1] = 0;
+  buffer[2] = 0;
+  buffer[3] = 0;
+  buffer[4] = 0;
+  buffer[5] = 0;
+  buffer[6] = 0xf0;
+  buffer[7] = 0x3f;
+  assert.equal(3.03865e-319, buffer.readDoubleBE(0));
+  assert.equal(1, buffer.readDoubleLE(0));
+
+  buffer[6] = 0;
+  buffer[7] = 0x40;
+  assert.equal(3.16e-322, buffer.readDoubleBE(0));
+  assert.equal(2, buffer.readDoubleLE(0));
+
+  buffer[7] = 0xc0;
+  assert.equal(9.5e-322, buffer.readDoubleBE(0));
+  assert.equal(-2, buffer.readDoubleLE(0));
+
+  buffer[6] = 0x10;
+  buffer[7] = 0;
+  assert.equal(2.0237e-320, buffer.readDoubleBE(0));
+  assert.equal(2.2250738585072014e-308, buffer.readDoubleLE(0));
+
+  buffer[6] = 0;
+  assert.equal(0, buffer.readDoubleBE(0));
+  assert.equal(0, buffer.readDoubleLE(0));
+  assert.equal(false, 1 / buffer.readDoubleLE(0) < 0);
+
+  buffer[7] = 0x80;
+  assert.equal(6.3e-322, buffer.readDoubleBE(0));
+  assert.equal(0, buffer.readDoubleLE(0));
+  assert.equal(true, 1 / buffer.readDoubleLE(0) < 0);
+
+  buffer[6] = 0xf0;
+  buffer[7] = 0x7f;
+  assert.equal(3.0418e-319, buffer.readDoubleBE(0));
+  assert.equal(Infinity, buffer.readDoubleLE(0));
+
+  buffer[6] = 0xf0;
+  buffer[7] = 0xff;
+  assert.equal(3.04814e-319, buffer.readDoubleBE(0));
+  assert.equal(-Infinity, buffer.readDoubleLE(0));
+});
+
+
+exports.testReadFloat = helper('readFloatLE/readFloatBE', function (assert) {
+  var buffer = new Buffer(4);
+
+  buffer[0] = 0;
+  buffer[1] = 0;
+  buffer[2] = 0x80;
+  buffer[3] = 0x3f;
+  assert.equal(4.600602988224807e-41, buffer.readFloatBE(0));
+  assert.equal(1, buffer.readFloatLE(0));
+
+  buffer[0] = 0;
+  buffer[1] = 0;
+  buffer[2] = 0;
+  buffer[3] = 0xc0;
+  assert.equal(2.6904930515036488e-43, buffer.readFloatBE(0));
+  assert.equal(-2, buffer.readFloatLE(0));
+
+  buffer[0] = 0xff;
+  buffer[1] = 0xff;
+  buffer[2] = 0x7f;
+  buffer[3] = 0x7f;
+  assert.ok(isNaN(buffer.readFloatBE(0)));
+  assert.equal(3.4028234663852886e+38, buffer.readFloatLE(0));
+
+  buffer[0] = 0xab;
+  buffer[1] = 0xaa;
+  buffer[2] = 0xaa;
+  buffer[3] = 0x3e;
+  assert.equal(-1.2126478207002966e-12, buffer.readFloatBE(0));
+  assert.equal(0.3333333432674408, buffer.readFloatLE(0));
+
+  buffer[0] = 0;
+  buffer[1] = 0;
+  buffer[2] = 0;
+  buffer[3] = 0;
+  assert.equal(0, buffer.readFloatBE(0));
+  assert.equal(0, buffer.readFloatLE(0));
+  assert.equal(false, 1 / buffer.readFloatLE(0) < 0);
+
+  buffer[3] = 0x80;
+  assert.equal(1.793662034335766e-43, buffer.readFloatBE(0));
+  assert.equal(0, buffer.readFloatLE(0));
+  assert.equal(true, 1 / buffer.readFloatLE(0) < 0);
+
+  buffer[0] = 0;
+  buffer[1] = 0;
+  buffer[2] = 0x80;
+  buffer[3] = 0x7f;
+  assert.equal(4.609571298396486e-41, buffer.readFloatBE(0));
+  assert.equal(Infinity, buffer.readFloatLE(0));
+
+  buffer[0] = 0;
+  buffer[1] = 0;
+  buffer[2] = 0x80;
+  buffer[3] = 0xff;
+  assert.equal(4.627507918739843e-41, buffer.readFloatBE(0));
+  assert.equal(-Infinity, buffer.readFloatLE(0));
+});
+
+
+exports.testReadInt8 = helper('readInt8', function (assert) {
+  var data = new Buffer(4);
+
+  data[0] = 0x23;
+  assert.equal(0x23, data.readInt8(0));
+
+  data[0] = 0xff;
+  assert.equal(-1, data.readInt8(0));
+
+  data[0] = 0x87;
+  data[1] = 0xab;
+  data[2] = 0x7c;
+  data[3] = 0xef;
+  assert.equal(-121, data.readInt8(0));
+  assert.equal(-85, data.readInt8(1));
+  assert.equal(124, data.readInt8(2));
+  assert.equal(-17, data.readInt8(3));
+});
+
+
+exports.testReadInt16 = helper('readInt16BE/readInt16LE', function (assert) {
+  var buffer = new Buffer(6);
+
+  buffer[0] = 0x16;
+  buffer[1] = 0x79;
+  assert.equal(0x1679, buffer.readInt16BE(0));
+  assert.equal(0x7916, buffer.readInt16LE(0));
+
+  buffer[0] = 0xff;
+  buffer[1] = 0x80;
+  assert.equal(-128, buffer.readInt16BE(0));
+  assert.equal(-32513, buffer.readInt16LE(0));
+
+  /* test offset with weenix */
+  buffer[0] = 0x77;
+  buffer[1] = 0x65;
+  buffer[2] = 0x65;
+  buffer[3] = 0x6e;
+  buffer[4] = 0x69;
+  buffer[5] = 0x78;
+  assert.equal(0x7765, buffer.readInt16BE(0));
+  assert.equal(0x6565, buffer.readInt16BE(1));
+  assert.equal(0x656e, buffer.readInt16BE(2));
+  assert.equal(0x6e69, buffer.readInt16BE(3));
+  assert.equal(0x6978, buffer.readInt16BE(4));
+  assert.equal(0x6577, buffer.readInt16LE(0));
+  assert.equal(0x6565, buffer.readInt16LE(1));
+  assert.equal(0x6e65, buffer.readInt16LE(2));
+  assert.equal(0x696e, buffer.readInt16LE(3));
+  assert.equal(0x7869, buffer.readInt16LE(4));
+});
+
+
+exports.testReadInt32 = helper('readInt32BE/readInt32LE', function (assert) {
+  var buffer = new Buffer(6);
+
+  buffer[0] = 0x43;
+  buffer[1] = 0x53;
+  buffer[2] = 0x16;
+  buffer[3] = 0x79;
+  assert.equal(0x43531679, buffer.readInt32BE(0));
+  assert.equal(0x79165343, buffer.readInt32LE(0));
+
+  buffer[0] = 0xff;
+  buffer[1] = 0xfe;
+  buffer[2] = 0xef;
+  buffer[3] = 0xfa;
+  assert.equal(-69638, buffer.readInt32BE(0));
+  assert.equal(-84934913, buffer.readInt32LE(0));
+
+  buffer[0] = 0x42;
+  buffer[1] = 0xc3;
+  buffer[2] = 0x95;
+  buffer[3] = 0xa9;
+  buffer[4] = 0x36;
+  buffer[5] = 0x17;
+  assert.equal(0x42c395a9, buffer.readInt32BE(0));
+  assert.equal(-1013601994, buffer.readInt32BE(1));
+  assert.equal(-1784072681, buffer.readInt32BE(2));
+  assert.equal(-1449802942, buffer.readInt32LE(0));
+  assert.equal(917083587, buffer.readInt32LE(1));
+  assert.equal(389458325, buffer.readInt32LE(2));
+});
+
+
+/*
+ * We need to check the following things:
+ *  - We are correctly resolving big endian (doesn't mean anything for 8 bit)
+ *  - Correctly resolving little endian (doesn't mean anything for 8 bit)
+ *  - Correctly using the offsets
+ *  - Correctly interpreting values that are beyond the signed range as unsigned
+ */
+exports.testReadUInt8 = helper('readUInt8', function (assert) {
+  var data = new Buffer(4);
+
+  data[0] = 23;
+  data[1] = 23;
+  data[2] = 23;
+  data[3] = 23;
+  assert.equal(23, data.readUInt8(0));
+  assert.equal(23, data.readUInt8(1));
+  assert.equal(23, data.readUInt8(2));
+  assert.equal(23, data.readUInt8(3));
+
+  data[0] = 255; /* If it became a signed int, would be -1 */
+  assert.equal(255, data.readUInt8(0));
+});
+
+
+/*
+ * Test 16 bit unsigned integers. We need to verify the same set as 8 bit, only
+ * now some of the issues actually matter:
+ *  - We are correctly resolving big endian
+ *  - Correctly resolving little endian
+ *  - Correctly using the offsets
+ *  - Correctly interpreting values that are beyond the signed range as unsigned
+ */
+exports.testReadUInt16 = helper('readUInt16LE/readUInt16BE', function (assert) {
+  var data = new Buffer(4);
+
+  data[0] = 0;
+  data[1] = 0x23;
+  data[2] = 0x42;
+  data[3] = 0x3f;
+  assert.equal(0x23, data.readUInt16BE(0));
+  assert.equal(0x2342, data.readUInt16BE(1));
+  assert.equal(0x423f, data.readUInt16BE(2));
+  assert.equal(0x2300, data.readUInt16LE(0));
+  assert.equal(0x4223, data.readUInt16LE(1));
+  assert.equal(0x3f42, data.readUInt16LE(2));
+
+  data[0] = 0xfe;
+  data[1] = 0xfe;
+  assert.equal(0xfefe, data.readUInt16BE(0));
+  assert.equal(0xfefe, data.readUInt16LE(0));
+});
+
+
+/*
+ * Test 32 bit unsigned integers. We need to verify the same set as 8 bit, only
+ * now some of the issues actually matter:
+ *  - We are correctly resolving big endian
+ *  - Correctly using the offsets
+ *  - Correctly interpreting values that are beyond the signed range as unsigned
+ */
+exports.testReadUInt32 = helper('readUInt32LE/readUInt32BE', function (assert) {
+  var data = new Buffer(8);
+
+  data[0] = 0x32;
+  data[1] = 0x65;
+  data[2] = 0x42;
+  data[3] = 0x56;
+  data[4] = 0x23;
+  data[5] = 0xff;
+  assert.equal(0x32654256, data.readUInt32BE(0));
+  assert.equal(0x65425623, data.readUInt32BE(1));
+  assert.equal(0x425623ff, data.readUInt32BE(2));
+  assert.equal(0x56426532, data.readUInt32LE(0));
+  assert.equal(0x23564265, data.readUInt32LE(1));
+  assert.equal(0xff235642, data.readUInt32LE(2));
+});
+
+function helper (description, fn) {
+  let bulkAssert = {
+    equal: function (a, b) {
+      if (a !== b) throw new Error('Error found in ' + description);
+    },
+    ok: function (value) {
+      if (!value) throw new Error('Error found in ' + description);
+    },
+    throws: function (shouldThrow) {
+      let didItThrow = false;
+      try {
+        shouldThrow();
+      } catch (e) {
+        didItThrow = e;
+      }
+      if (!didItThrow)
+        throw new Error('Error found in ' + description + ': ' + shouldThrow + ' should have thrown');
+    }
+  };
+  return function (assert) {
+    fn(bulkAssert);
+    // If we get here, no errors thrown
+    assert.pass('All tests passed for ' + description);
+  };
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/buffers/test-write-types.js
@@ -0,0 +1,602 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+const { Buffer } = require('sdk/io/buffer');
+
+exports.testWriteDouble = helper('writeDoubleBE/writeDoubleLE', function (assert) {
+  var buffer = new Buffer(16);
+
+  buffer.writeDoubleBE(2.225073858507201e-308, 0);
+  buffer.writeDoubleLE(2.225073858507201e-308, 8);
+  assert.equal(0x00, buffer[0]);
+  assert.equal(0x0f, buffer[1]);
+  assert.equal(0xff, buffer[2]);
+  assert.equal(0xff, buffer[3]);
+  assert.equal(0xff, buffer[4]);
+  assert.equal(0xff, buffer[5]);
+  assert.equal(0xff, buffer[6]);
+  assert.equal(0xff, buffer[7]);
+  assert.equal(0xff, buffer[8]);
+  assert.equal(0xff, buffer[9]);
+  assert.equal(0xff, buffer[10]);
+  assert.equal(0xff, buffer[11]);
+  assert.equal(0xff, buffer[12]);
+  assert.equal(0xff, buffer[13]);
+  assert.equal(0x0f, buffer[14]);
+  assert.equal(0x00, buffer[15]);
+
+  buffer.writeDoubleBE(1.0000000000000004, 0);
+  buffer.writeDoubleLE(1.0000000000000004, 8);
+  assert.equal(0x3f, buffer[0]);
+  assert.equal(0xf0, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x02, buffer[7]);
+  assert.equal(0x02, buffer[8]);
+  assert.equal(0x00, buffer[9]);
+  assert.equal(0x00, buffer[10]);
+  assert.equal(0x00, buffer[11]);
+  assert.equal(0x00, buffer[12]);
+  assert.equal(0x00, buffer[13]);
+  assert.equal(0xf0, buffer[14]);
+  assert.equal(0x3f, buffer[15]);
+
+  buffer.writeDoubleBE(-2, 0);
+  buffer.writeDoubleLE(-2, 8);
+  assert.equal(0xc0, buffer[0]);
+  assert.equal(0x00, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x00, buffer[7]);
+  assert.equal(0x00, buffer[8]);
+  assert.equal(0x00, buffer[9]);
+  assert.equal(0x00, buffer[10]);
+  assert.equal(0x00, buffer[11]);
+  assert.equal(0x00, buffer[12]);
+  assert.equal(0x00, buffer[13]);
+  assert.equal(0x00, buffer[14]);
+  assert.equal(0xc0, buffer[15]);
+
+  buffer.writeDoubleBE(1.7976931348623157e+308, 0);
+  buffer.writeDoubleLE(1.7976931348623157e+308, 8);
+  assert.equal(0x7f, buffer[0]);
+  assert.equal(0xef, buffer[1]);
+  assert.equal(0xff, buffer[2]);
+  assert.equal(0xff, buffer[3]);
+  assert.equal(0xff, buffer[4]);
+  assert.equal(0xff, buffer[5]);
+  assert.equal(0xff, buffer[6]);
+  assert.equal(0xff, buffer[7]);
+  assert.equal(0xff, buffer[8]);
+  assert.equal(0xff, buffer[9]);
+  assert.equal(0xff, buffer[10]);
+  assert.equal(0xff, buffer[11]);
+  assert.equal(0xff, buffer[12]);
+  assert.equal(0xff, buffer[13]);
+  assert.equal(0xef, buffer[14]);
+  assert.equal(0x7f, buffer[15]);
+
+  buffer.writeDoubleBE(0 * -1, 0);
+  buffer.writeDoubleLE(0 * -1, 8);
+  assert.equal(0x80, buffer[0]);
+  assert.equal(0x00, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x00, buffer[7]);
+  assert.equal(0x00, buffer[8]);
+  assert.equal(0x00, buffer[9]);
+  assert.equal(0x00, buffer[10]);
+  assert.equal(0x00, buffer[11]);
+  assert.equal(0x00, buffer[12]);
+  assert.equal(0x00, buffer[13]);
+  assert.equal(0x00, buffer[14]);
+  assert.equal(0x80, buffer[15]);
+
+  buffer.writeDoubleBE(Infinity, 0);
+  buffer.writeDoubleLE(Infinity, 8);
+  assert.equal(0x7F, buffer[0]);
+  assert.equal(0xF0, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x00, buffer[7]);
+  assert.equal(0x00, buffer[8]);
+  assert.equal(0x00, buffer[9]);
+  assert.equal(0x00, buffer[10]);
+  assert.equal(0x00, buffer[11]);
+  assert.equal(0x00, buffer[12]);
+  assert.equal(0x00, buffer[13]);
+  assert.equal(0xF0, buffer[14]);
+  assert.equal(0x7F, buffer[15]);
+  assert.equal(Infinity, buffer.readDoubleBE(0));
+  assert.equal(Infinity, buffer.readDoubleLE(8));
+
+  buffer.writeDoubleBE(-Infinity, 0);
+  buffer.writeDoubleLE(-Infinity, 8);
+  assert.equal(0xFF, buffer[0]);
+  assert.equal(0xF0, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x00, buffer[7]);
+  assert.equal(0x00, buffer[8]);
+  assert.equal(0x00, buffer[9]);
+  assert.equal(0x00, buffer[10]);
+  assert.equal(0x00, buffer[11]);
+  assert.equal(0x00, buffer[12]);
+  assert.equal(0x00, buffer[13]);
+  assert.equal(0xF0, buffer[14]);
+  assert.equal(0xFF, buffer[15]);
+  assert.equal(-Infinity, buffer.readDoubleBE(0));
+  assert.equal(-Infinity, buffer.readDoubleLE(8));
+
+  buffer.writeDoubleBE(NaN, 0);
+  buffer.writeDoubleLE(NaN, 8);
+  // Darwin ia32 does the other kind of NaN.
+  // Compiler bug.  No one really cares.
+  assert.ok(0x7F === buffer[0] || 0xFF === buffer[0]);
+  assert.equal(0xF8, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x00, buffer[7]);
+  assert.equal(0x00, buffer[8]);
+  assert.equal(0x00, buffer[9]);
+  assert.equal(0x00, buffer[10]);
+  assert.equal(0x00, buffer[11]);
+  assert.equal(0x00, buffer[12]);
+  assert.equal(0x00, buffer[13]);
+  assert.equal(0xF8, buffer[14]);
+  // Darwin ia32 does the other kind of NaN.
+  // Compiler bug.  No one really cares.
+  assert.ok(0x7F === buffer[15] || 0xFF === buffer[15]);
+  assert.ok(isNaN(buffer.readDoubleBE(0)));
+  assert.ok(isNaN(buffer.readDoubleLE(8)));
+});
+
+exports.testWriteFloat = helper('writeFloatBE/writeFloatLE', function (assert) {
+  var buffer = new Buffer(8);
+
+  buffer.writeFloatBE(1, 0);
+  buffer.writeFloatLE(1, 4);
+  assert.equal(0x3f, buffer[0]);
+  assert.equal(0x80, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x80, buffer[6]);
+  assert.equal(0x3f, buffer[7]);
+
+  buffer.writeFloatBE(1 / 3, 0);
+  buffer.writeFloatLE(1 / 3, 4);
+  assert.equal(0x3e, buffer[0]);
+  assert.equal(0xaa, buffer[1]);
+  assert.equal(0xaa, buffer[2]);
+  assert.equal(0xab, buffer[3]);
+  assert.equal(0xab, buffer[4]);
+  assert.equal(0xaa, buffer[5]);
+  assert.equal(0xaa, buffer[6]);
+  assert.equal(0x3e, buffer[7]);
+
+  buffer.writeFloatBE(3.4028234663852886e+38, 0);
+  buffer.writeFloatLE(3.4028234663852886e+38, 4);
+  assert.equal(0x7f, buffer[0]);
+  assert.equal(0x7f, buffer[1]);
+  assert.equal(0xff, buffer[2]);
+  assert.equal(0xff, buffer[3]);
+  assert.equal(0xff, buffer[4]);
+  assert.equal(0xff, buffer[5]);
+  assert.equal(0x7f, buffer[6]);
+  assert.equal(0x7f, buffer[7]);
+
+  buffer.writeFloatLE(1.1754943508222875e-38, 0);
+  buffer.writeFloatBE(1.1754943508222875e-38, 4);
+  assert.equal(0x00, buffer[0]);
+  assert.equal(0x00, buffer[1]);
+  assert.equal(0x80, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x80, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x00, buffer[7]);
+
+  buffer.writeFloatBE(0 * -1, 0);
+  buffer.writeFloatLE(0 * -1, 4);
+  assert.equal(0x80, buffer[0]);
+  assert.equal(0x00, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x80, buffer[7]);
+
+  buffer.writeFloatBE(Infinity, 0);
+  buffer.writeFloatLE(Infinity, 4);
+  assert.equal(0x7F, buffer[0]);
+  assert.equal(0x80, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x80, buffer[6]);
+  assert.equal(0x7F, buffer[7]);
+  assert.equal(Infinity, buffer.readFloatBE(0));
+  assert.equal(Infinity, buffer.readFloatLE(4));
+
+  buffer.writeFloatBE(-Infinity, 0);
+  buffer.writeFloatLE(-Infinity, 4);
+  // Darwin ia32 does the other kind of NaN.
+  // Compiler bug.  No one really cares.
+  assert.ok(0xFF === buffer[0] || 0x7F === buffer[0]);
+  assert.equal(0x80, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x80, buffer[6]);
+  assert.equal(0xFF, buffer[7]);
+  assert.equal(-Infinity, buffer.readFloatBE(0));
+  assert.equal(-Infinity, buffer.readFloatLE(4));
+
+  buffer.writeFloatBE(NaN, 0);
+  buffer.writeFloatLE(NaN, 4);
+  // Darwin ia32 does the other kind of NaN.
+  // Compiler bug.  No one really cares.
+  assert.ok(0x7F === buffer[0] || 0xFF === buffer[0]);
+  assert.equal(0xc0, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0xc0, buffer[6]);
+  // Darwin ia32 does the other kind of NaN.
+  // Compiler bug.  No one really cares.
+  assert.ok(0x7F === buffer[7] || 0xFF === buffer[7]);
+  assert.ok(isNaN(buffer.readFloatBE(0)));
+  assert.ok(isNaN(buffer.readFloatLE(4)));
+});
+
+
+exports.testWriteInt8 = helper('writeInt8', function (assert) {
+  var buffer = new Buffer(2);
+
+  buffer.writeInt8(0x23, 0);
+  buffer.writeInt8(-5, 1);
+
+  assert.equal(0x23, buffer[0]);
+  assert.equal(0xfb, buffer[1]);
+
+  /* Make sure we handle truncation correctly */
+  assert.throws(function() {
+    buffer.writeInt8(0xabc, 0);
+  });
+  assert.throws(function() {
+    buffer.writeInt8(0xabc, 0);
+  });
+
+  /* Make sure we handle min/max correctly */
+  buffer.writeInt8(0x7f, 0);
+  buffer.writeInt8(-0x80, 1);
+
+  assert.equal(0x7f, buffer[0]);
+  assert.equal(0x80, buffer[1]);
+  assert.throws(function() {
+    buffer.writeInt8(0x7f + 1, 0);
+  });
+  assert.throws(function() {
+    buffer.writeInt8(-0x80 - 1, 0);
+  });
+});
+
+
+exports.testWriteInt16 = helper('writeInt16LE/writeInt16BE', function (assert) {
+  var buffer = new Buffer(6);
+
+  buffer.writeInt16BE(0x0023, 0);
+  buffer.writeInt16LE(0x0023, 2);
+  assert.equal(0x00, buffer[0]);
+  assert.equal(0x23, buffer[1]);
+  assert.equal(0x23, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+
+  buffer.writeInt16BE(-5, 0);
+  buffer.writeInt16LE(-5, 2);
+  assert.equal(0xff, buffer[0]);
+  assert.equal(0xfb, buffer[1]);
+  assert.equal(0xfb, buffer[2]);
+  assert.equal(0xff, buffer[3]);
+
+  buffer.writeInt16BE(-1679, 1);
+  buffer.writeInt16LE(-1679, 3);
+  assert.equal(0xf9, buffer[1]);
+  assert.equal(0x71, buffer[2]);
+  assert.equal(0x71, buffer[3]);
+  assert.equal(0xf9, buffer[4]);
+
+  /* Make sure we handle min/max correctly */
+  buffer.writeInt16BE(0x7fff, 0);
+  buffer.writeInt16BE(-0x8000, 2);
+  assert.equal(0x7f, buffer[0]);
+  assert.equal(0xff, buffer[1]);
+  assert.equal(0x80, buffer[2]);
+  assert.equal(0x00, buffer[3]);
+  assert.throws(function() {
+    buffer.writeInt16BE(0x7fff + 1, 0);
+  });
+  assert.throws(function() {
+    buffer.writeInt16BE(-0x8000 - 1, 0);
+  });
+
+  buffer.writeInt16LE(0x7fff, 0);
+  buffer.writeInt16LE(-0x8000, 2);
+  assert.equal(0xff, buffer[0]);
+  assert.equal(0x7f, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x80, buffer[3]);
+  assert.throws(function() {
+    buffer.writeInt16LE(0x7fff + 1, 0);
+  });
+  assert.throws(function() {
+    buffer.writeInt16LE(-0x8000 - 1, 0);
+  });
+});
+
+exports.testWriteInt32 = helper('writeInt32BE/writeInt32LE', function (assert) {
+  var buffer = new Buffer(8);
+
+  buffer.writeInt32BE(0x23, 0);
+  buffer.writeInt32LE(0x23, 4);
+  assert.equal(0x00, buffer[0]);
+  assert.equal(0x00, buffer[1]);
+  assert.equal(0x00, buffer[2]);
+  assert.equal(0x23, buffer[3]);
+  assert.equal(0x23, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x00, buffer[7]);
+
+  buffer.writeInt32BE(-5, 0);
+  buffer.writeInt32LE(-5, 4);
+  assert.equal(0xff, buffer[0]);
+  assert.equal(0xff, buffer[1]);
+  assert.equal(0xff, buffer[2]);
+  assert.equal(0xfb, buffer[3]);
+  assert.equal(0xfb, buffer[4]);
+  assert.equal(0xff, buffer[5]);
+  assert.equal(0xff, buffer[6]);
+  assert.equal(0xff, buffer[7]);
+
+  buffer.writeInt32BE(-805306713, 0);
+  buffer.writeInt32LE(-805306713, 4);
+  assert.equal(0xcf, buffer[0]);
+  assert.equal(0xff, buffer[1]);
+  assert.equal(0xfe, buffer[2]);
+  assert.equal(0xa7, buffer[3]);
+  assert.equal(0xa7, buffer[4]);
+  assert.equal(0xfe, buffer[5]);
+  assert.equal(0xff, buffer[6]);
+  assert.equal(0xcf, buffer[7]);
+
+  /* Make sure we handle min/max correctly */
+  buffer.writeInt32BE(0x7fffffff, 0);
+  buffer.writeInt32BE(-0x80000000, 4);
+  assert.equal(0x7f, buffer[0]);
+  assert.equal(0xff, buffer[1]);
+  assert.equal(0xff, buffer[2]);
+  assert.equal(0xff, buffer[3]);
+  assert.equal(0x80, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x00, buffer[7]);
+  assert.throws(function() {
+    buffer.writeInt32BE(0x7fffffff + 1, 0);
+  });
+  assert.throws(function() {
+    buffer.writeInt32BE(-0x80000000 - 1, 0);
+  });
+
+  buffer.writeInt32LE(0x7fffffff, 0);
+  buffer.writeInt32LE(-0x80000000, 4);
+  assert.equal(0xff, buffer[0]);
+  assert.equal(0xff, buffer[1]);
+  assert.equal(0xff, buffer[2]);
+  assert.equal(0x7f, buffer[3]);
+  assert.equal(0x00, buffer[4]);
+  assert.equal(0x00, buffer[5]);
+  assert.equal(0x00, buffer[6]);
+  assert.equal(0x80, buffer[7]);
+  assert.throws(function() {
+    buffer.writeInt32LE(0x7fffffff + 1, 0);
+  });
+  assert.throws(function() {
+    buffer.writeInt32LE(-0x80000000 - 1, 0);
+  });
+});
+
+/*
+ * We need to check the following things:
+ *  - We are correctly resolving big endian (doesn't mean anything for 8 bit)
+ *  - Correctly resolving little endian (doesn't mean anything for 8 bit)
+ *  - Correctly using the offsets
+ *  - Correctly interpreting values that are beyond the signed range as unsigned
+ */
+exports.testWriteUInt8 = helper('writeUInt8', function (assert) {
+  var data = new Buffer(4);
+
+  data.writeUInt8(23, 0);
+  data.writeUInt8(23, 1);
+  data.writeUInt8(23, 2);
+  data.writeUInt8(23, 3);
+  assert.equal(23, data[0]);
+  assert.equal(23, data[1]);
+  assert.equal(23, data[2]);
+  assert.equal(23, data[3]);
+
+  data.writeUInt8(23, 0);
+  data.writeUInt8(23, 1);
+  data.writeUInt8(23, 2);
+  data.writeUInt8(23, 3);
+  assert.equal(23, data[0]);
+  assert.equal(23, data[1]);
+  assert.equal(23, data[2]);
+  assert.equal(23, data[3]);
+
+  data.writeUInt8(255, 0);
+  assert.equal(255, data[0]);
+
+  data.writeUInt8(255, 0);
+  assert.equal(255, data[0]);
+});
+
+
+exports.testWriteUInt16 = helper('writeUInt16BE/writeUInt16LE', function (assert) {
+  var value = 0x2343;
+  var data = new Buffer(4);
+
+  data.writeUInt16BE(value, 0);
+  assert.equal(0x23, data[0]);
+  assert.equal(0x43, data[1]);
+
+  data.writeUInt16BE(value, 1);
+  assert.equal(0x23, data[1]);
+  assert.equal(0x43, data[2]);
+
+  data.writeUInt16BE(value, 2);
+  assert.equal(0x23, data[2]);
+  assert.equal(0x43, data[3]);
+
+  data.writeUInt16LE(value, 0);
+  assert.equal(0x23, data[1]);
+  assert.equal(0x43, data[0]);
+
+  data.writeUInt16LE(value, 1);
+  assert.equal(0x23, data[2]);
+  assert.equal(0x43, data[1]);
+
+  data.writeUInt16LE(value, 2);
+  assert.equal(0x23, data[3]);
+  assert.equal(0x43, data[2]);
+
+  value = 0xff80;
+  data.writeUInt16LE(value, 0);
+  assert.equal(0xff, data[1]);
+  assert.equal(0x80, data[0]);
+
+  data.writeUInt16BE(value, 0);
+  assert.equal(0xff, data[0]);
+  assert.equal(0x80, data[1]);
+});
+
+
+exports.testWriteUInt32 = helper('writeUInt32BE/writeUInt32LE', function (assert) {
+  var data = new Buffer(6);
+  var value = 0xe7f90a6d;
+
+  data.writeUInt32BE(value, 0);
+  assert.equal(0xe7, data[0]);
+  assert.equal(0xf9, data[1]);
+  assert.equal(0x0a, data[2]);
+  assert.equal(0x6d, data[3]);
+
+  data.writeUInt32BE(value, 1);
+  assert.equal(0xe7, data[1]);
+  assert.equal(0xf9, data[2]);
+  assert.equal(0x0a, data[3]);
+  assert.equal(0x6d, data[4]);
+
+  data.writeUInt32BE(value, 2);
+  assert.equal(0xe7, data[2]);
+  assert.equal(0xf9, data[3]);
+  assert.equal(0x0a, data[4]);
+  assert.equal(0x6d, data[5]);
+
+  data.writeUInt32LE(value, 0);
+  assert.equal(0xe7, data[3]);
+  assert.equal(0xf9, data[2]);
+  assert.equal(0x0a, data[1]);
+  assert.equal(0x6d, data[0]);
+
+  data.writeUInt32LE(value, 1);
+  assert.equal(0xe7, data[4]);
+  assert.equal(0xf9, data[3]);
+  assert.equal(0x0a, data[2]);
+  assert.equal(0x6d, data[1]);
+
+  data.writeUInt32LE(value, 2);
+  assert.equal(0xe7, data[5]);
+  assert.equal(0xf9, data[4]);
+  assert.equal(0x0a, data[3]);
+  assert.equal(0x6d, data[2]);
+});
+
+function helper (description, fn) {
+  return function (assert) {
+    let bulkAssert = {
+      equal: function (a, b) {
+        if (a !== b) throw new Error('Error found in ' + description);
+      },
+      ok: function (value) {
+        if (!value) throw new Error('Error found in ' + description);
+      },
+      /*
+       * TODO
+       * There should be errors when setting outside of the value range
+       * of the data type (like writeInt8 with value of 1000), but DataView
+       * does not throw; seems to just grab the appropriate max bits.
+       * So ignoring this test for now
+       */
+      throws: function (shouldThrow) {
+        assert.pass(description + ': Need to implement error handling for setting buffer values ' +
+          'outside of the data types\' range.');
+        /*
+        let didItThrow = false;
+        try {
+          shouldThrow();
+        } catch (e) {
+          didItThrow = e;
+        }
+        if (!didItThrow)
+          throw new Error('Error found in ' + description + ': ' + shouldThrow + ' should have thrown');
+        */
+      }
+    };
+    fn(bulkAssert);
+    // If we get here, no errors thrown
+    assert.pass('All tests passed for ' + description);
+  };
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/fixtures.js
@@ -0,0 +1,6 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+exports.url = path =>
+  module.uri.substr(0, module.uri.lastIndexOf("/") + 1) + "fixtures/" + path
copy from addon-sdk/source/data/index.html
copy to addon-sdk/source/test/fixtures/index.html
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/fixtures/loader/json/invalid.json
@@ -0,0 +1,3 @@
+{
+  invalidjson
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/fixtures/loader/json/manifest.json
@@ -0,0 +1,14 @@
+{
+  "name": "Jetpack Loader Test",
+  "version": "1.0.1",
+  "dependencies": {
+    "async": "*",
+    "underscore": "*"
+  },
+  "contributors": [
+    "ash nazg durbatulûk",
+    "ash nazg gimbatul",
+    "ash nazg thrakatulûk",
+    "agh burzum-ishi krimpatul"
+  ]
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/fixtures/loader/json/nodotjson.json.js
@@ -0,0 +1,4 @@
+module.exports = {
+  "filename": "nodotjson.json.js",
+  "data": {}
+};
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/fixtures/loader/json/test.json
@@ -0,0 +1,3 @@
+{
+  "filename": "test.json"
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/fixtures/loader/json/test.json.js
@@ -0,0 +1,3 @@
+module.exports = {
+  "filename": "test.json.js"
+};
rename from addon-sdk/source/data/mofo_logo.SVG
rename to addon-sdk/source/test/fixtures/mofo_logo.SVG
rename from addon-sdk/source/data/moz_favicon.ico
rename to addon-sdk/source/test/fixtures/moz_favicon.ico
rename from addon-sdk/source/data/pagemod-css-include-file.css
rename to addon-sdk/source/test/fixtures/pagemod-css-include-file.css
rename from addon-sdk/source/data/test-content-symbiont.js
rename to addon-sdk/source/test/fixtures/test-content-symbiont.js
rename from addon-sdk/source/data/test-context-menu.js
rename to addon-sdk/source/test/fixtures/test-context-menu.js
rename from addon-sdk/source/data/test-iframe-postmessage.html
rename to addon-sdk/source/test/fixtures/test-iframe-postmessage.html
rename from addon-sdk/source/data/test-iframe.html
rename to addon-sdk/source/test/fixtures/test-iframe.html
rename from addon-sdk/source/data/test-iframe.js
rename to addon-sdk/source/test/fixtures/test-iframe.js
rename from addon-sdk/source/data/test-message-manager.js
rename to addon-sdk/source/test/fixtures/test-message-manager.js
rename from addon-sdk/source/data/test-net-url.txt
rename to addon-sdk/source/test/fixtures/test-net-url.txt
rename from addon-sdk/source/data/test-page-mod.html
rename to addon-sdk/source/test/fixtures/test-page-mod.html
rename from addon-sdk/source/data/test-page-worker.html
rename to addon-sdk/source/test/fixtures/test-page-worker.html
rename from addon-sdk/source/data/test-page-worker.js
rename to addon-sdk/source/test/fixtures/test-page-worker.js
rename from addon-sdk/source/data/test-sidebar-addon-global.html
rename to addon-sdk/source/test/fixtures/test-sidebar-addon-global.html
copy from addon-sdk/source/data/test-trusted-document.html
copy to addon-sdk/source/test/fixtures/test-trusted-document.html
rename from addon-sdk/source/data/test.html
rename to addon-sdk/source/test/fixtures/test.html
rename from addon-sdk/source/data/testLocalXhr.json
rename to addon-sdk/source/test/fixtures/testLocalXhr.json
--- a/addon-sdk/source/test/test-addon-installer.js
+++ b/addon-sdk/source/test/test-addon-installer.js
@@ -5,16 +5,17 @@
 "use strict";
 
 const { Cc, Ci, Cu } = require("chrome");
 const AddonInstaller = require("sdk/addon/installer");
 const observers = require("sdk/deprecated/observer-service");
 const { setTimeout } = require("sdk/timers");
 const tmp = require("sdk/test/tmp-file");
 const system = require("sdk/system");
+const fixtures = require("./fixtures");
 
 const testFolderURL = module.uri.split('test-addon-installer.js')[0];
 const ADDON_URL = testFolderURL + "fixtures/addon-install-unit-test@mozilla.com.xpi";
 const ADDON_PATH = tmp.createFromURL(ADDON_URL);
 
 exports["test Install"] = function (assert, done) {
 
   // Save all events distpatched by bootstrap.js of the installed addon
deleted file mode 100644
--- a/addon-sdk/source/test/test-addon-page.js
+++ /dev/null
@@ -1,167 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict';
-
-module.metadata = {
-  engines: {
-    'Firefox': '*'
-  }
-};
-
-const { isTabOpen, activateTab, openTab,
-        closeTab, getURI } = require('sdk/tabs/utils');
-const windows = require('sdk/deprecated/window-utils');
-const { LoaderWithHookedConsole } = require('sdk/test/loader');
-const { setTimeout } = require('sdk/timers');
-const { is } = require('sdk/system/xul-app');
-const tabs = require('sdk/tabs');
-const isAustralis = "gCustomizeMode" in windows.activeBrowserWindow;
-const { set: setPref } = require("sdk/preferences/service");
-const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
-
-let uri = require('sdk/self').data.url('index.html');
-
-function isChromeVisible(window) {
-  let x = window.document.documentElement.getAttribute('disablechrome')
-  return x !== 'true';
-}
-
-exports['test add-on page deprecation message'] = function(assert) {
-  let { loader, messages } = LoaderWithHookedConsole(module);
-  loader.require('sdk/addon-page');
-  setPref(DEPRECATE_PREF, true);
-
-  assert.equal(messages.length, 1, "only one error is dispatched");
-  assert.equal(messages[0].type, "error", "the console message is an error");
-
-  let msg = messages[0].msg;
-
-  assert.ok(msg.indexOf("DEPRECATED") === 0,
-            "The message is deprecation message");
-
-  loader.unload();
-};
-
-exports['test that add-on page has no chrome'] = function(assert, done) {
-  let { loader } = LoaderWithHookedConsole(module);
-  loader.require('sdk/addon-page');
-
-  let window = windows.activeBrowserWindow;
-  let tab = openTab(window, uri);
-
-  assert.ok(isChromeVisible(window), 'chrome is visible for non addon page');
-
-  // need to do this in another turn to make sure event listener
-  // that sets property has time to do that.
-  setTimeout(function() {
-    activateTab(tab);
-
-    assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
-      'chrome is not visible for addon page');
-
-    closeTab(tab);
-    assert.ok(isChromeVisible(window), 'chrome is visible again');
-    loader.unload();
-    assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
-    done();
-  });
-};
-
-exports['test that add-on page with hash has no chrome'] = function(assert, done) {
-  let { loader } = LoaderWithHookedConsole(module);
-  loader.require('sdk/addon-page');
-
-  let window = windows.activeBrowserWindow;
-  let tab = openTab(window, uri + "#foo");
-
-  assert.ok(isChromeVisible(window), 'chrome is visible for non addon page');
-
-  // need to do this in another turn to make sure event listener
-  // that sets property has time to do that.
-  setTimeout(function() {
-    activateTab(tab);
-
-    assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
-      'chrome is not visible for addon page');
-
-    closeTab(tab);
-    assert.ok(isChromeVisible(window), 'chrome is visible again');
-    loader.unload();
-    assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
-    done();
-  });
-};
-
-exports['test that add-on page with querystring has no chrome'] = function(assert, done) {
-  let { loader } = LoaderWithHookedConsole(module);
-  loader.require('sdk/addon-page');
-
-  let window = windows.activeBrowserWindow;
-  let tab = openTab(window, uri + '?foo=bar');
-
-  assert.ok(isChromeVisible(window), 'chrome is visible for non addon page');
-
-  // need to do this in another turn to make sure event listener
-  // that sets property has time to do that.
-  setTimeout(function() {
-    activateTab(tab);
-
-    assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
-      'chrome is not visible for addon page');
-
-    closeTab(tab);
-    assert.ok(isChromeVisible(window), 'chrome is visible again');
-    loader.unload();
-    assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
-    done();
-  });
-};
-
-exports['test that add-on page with hash and querystring has no chrome'] = function(assert, done) {
-  let { loader } = LoaderWithHookedConsole(module);
-  loader.require('sdk/addon-page');
-
-  let window = windows.activeBrowserWindow;
-  let tab = openTab(window, uri + '#foo?foo=bar');
-
-  assert.ok(isChromeVisible(window), 'chrome is visible for non addon page');
-
-  // need to do this in another turn to make sure event listener
-  // that sets property has time to do that.
-  setTimeout(function() {
-    activateTab(tab);
-
-    assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
-      'chrome is not visible for addon page');
-
-    closeTab(tab);
-    assert.ok(isChromeVisible(window), 'chrome is visible again');
-    loader.unload();
-    assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
-    done();
-  });
-};
-
-exports['test that malformed uri is not an addon-page'] = function(assert, done) {
-  let { loader } = LoaderWithHookedConsole(module);
-  loader.require('sdk/addon-page');
-
-  let window = windows.activeBrowserWindow;
-  let tab = openTab(window, uri + 'anguage');
-
-  // need to do this in another turn to make sure event listener
-  // that sets property has time to do that.
-  setTimeout(function() {
-    activateTab(tab);
-
-    assert.ok(isChromeVisible(window), 'chrome is visible for malformed uri');
-
-    closeTab(tab);
-    loader.unload();
-    done();
-  });
-};
-
-require('test').run(exports);
--- a/addon-sdk/source/test/test-buffer.js
+++ b/addon-sdk/source/test/test-buffer.js
@@ -1,90 +1,566 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+
+/*
+ * Many of these tests taken from Joyent's Node
+ * https://github.com/joyent/node/blob/master/test/simple/test-buffer.js
+ */
+
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
 const { Buffer, TextEncoder, TextDecoder } = require('sdk/io/buffer');
+const { safeMerge } = require('sdk/util/object');
+
+const ENCODINGS = ['utf-8', 'utf-16le', 'utf-16be'];
+
+exports.testBufferMain = function (assert) {
+  let b = Buffer('abcdef');
+
+  // try to create 0-length buffers
+  new Buffer('');
+  new Buffer(0);
+  // test encodings supported by node;
+  // this is different than what node supports, details
+  // in buffer.js
+  ENCODINGS.forEach(enc => {
+    new Buffer('', enc);
+    assert.pass('Creating a buffer with ' + enc + ' does not throw');
+  });
+
+  ENCODINGS.forEach(function(encoding) {
+    // Does not work with utf8
+    if (encoding === 'utf-8') return;
+    var b = new Buffer(10);
+    b.write('あいうえお', encoding);
+    assert.equal(b.toString(encoding), 'あいうえお',
+      'encode and decodes buffer with ' + encoding);
+  });
+
+  // invalid encoding for Buffer.toString
+  assert.throws(() => {
+    b.toString('invalid');
+  }, TypeError, 'invalid encoding for Buffer.toString');
+
+  // try to toString() a 0-length slice of a buffer, both within and without the
+  // valid buffer range
+  assert.equal(new Buffer('abc').toString('utf8', 0, 0), '',
+    'toString 0-length buffer, valid range');
+  assert.equal(new Buffer('abc').toString('utf8', -100, -100), '',
+    'toString 0-length buffer, invalid range');
+  assert.equal(new Buffer('abc').toString('utf8', 100, 100), '',
+    'toString 0-length buffer, invalid range');
+
+  // try toString() with a object as a encoding
+  assert.equal(new Buffer('abc').toString({toString: function() {
+    return 'utf8';
+  }}), 'abc', 'toString with object as an encoding');
+
+  // test for buffer overrun
+  var buf = new Buffer([0, 0, 0, 0, 0]); // length: 5
+  var sub = buf.slice(0, 4); // length: 4
+  var written = sub.write('12345', 'utf8');
+  assert.equal(written, 4, 'correct bytes written in slice');
+  assert.equal(buf[4], 0, 'correct origin buffer value');
+
+  // Check for fractional length args, junk length args, etc.
+  // https://github.com/joyent/node/issues/1758
+  Buffer(3.3).toString(); // throws bad argument error in commit 43cb4ec
+  assert.equal(Buffer(-1).length, 0);
+  assert.equal(Buffer(NaN).length, 0);
+  assert.equal(Buffer(3.3).length, 3);
+  assert.equal(Buffer({length: 3.3}).length, 3);
+  assert.equal(Buffer({length: 'BAM'}).length, 0);
+
+  // Make sure that strings are not coerced to numbers.
+  assert.equal(Buffer('99').length, 2);
+  assert.equal(Buffer('13.37').length, 5);
+};
 
 exports.testIsEncoding = function (assert) {
-  Object.keys(ENCODINGS).forEach(encoding => {
+  ENCODINGS.map(encoding => {
     assert.ok(Buffer.isEncoding(encoding),
       'Buffer.isEncoding ' + encoding + ' truthy');
   });
-  ['not-encoding', undefined, null, 100, {}].forEach(encoding => {
+  ['not-encoding', undefined, null, 100, {}].map(encoding => {
     assert.ok(!Buffer.isEncoding(encoding),
       'Buffer.isEncoding ' + encoding + ' falsy');
   });
 };
 
+exports.testBufferCopy = function (assert) {
+  // counter to ensure unique value is always copied
+  var cntr = 0;
+  var b = Buffer(1024); // safe constructor
+
+  assert.strictEqual(1024, b.length);
+  b[0] = -1;
+  assert.strictEqual(b[0], 255);
+
+  var shimArray = [];
+  for (var i = 0; i < 1024; i++) {
+    b[i] = i % 256;
+    shimArray[i] = i % 256;
+  }
+
+  compareBuffers(assert, b, shimArray, 'array notation');
+
+  var c = new Buffer(512);
+  assert.strictEqual(512, c.length);
+  // copy 512 bytes, from 0 to 512.
+  b.fill(++cntr);
+  c.fill(++cntr);
+  var copied = b.copy(c, 0, 0, 512);
+  assert.strictEqual(512, copied,
+    'copied ' + copied + ' bytes from b into c');
+
+  compareBuffers(assert, b, c, 'copied to other buffer');
+
+  // copy c into b, without specifying sourceEnd
+  b.fill(++cntr);
+  c.fill(++cntr);
+  var copied = c.copy(b, 0, 0);
+  assert.strictEqual(c.length, copied,
+    'copied ' + copied + ' bytes from c into b w/o sourceEnd');
+  compareBuffers(assert, b, c,
+    'copied to other buffer without specifying sourceEnd');
+
+  // copy c into b, without specifying sourceStart
+  b.fill(++cntr);
+  c.fill(++cntr);
+  var copied = c.copy(b, 0);
+  assert.strictEqual(c.length, copied,
+    'copied ' + copied + ' bytes from c into b w/o sourceStart');
+  compareBuffers(assert, b, c,
+    'copied to other buffer without specifying sourceStart');
+
+  // copy longer buffer b to shorter c without targetStart
+  b.fill(++cntr);
+  c.fill(++cntr);
+
+  var copied = b.copy(c);
+  assert.strictEqual(c.length, copied,
+    'copied ' + copied + ' bytes from b into c w/o targetStart');
+  compareBuffers(assert, b, c,
+    'copy long buffer to shorter buffer without targetStart');
+
+  // copy starting near end of b to c
+  b.fill(++cntr);
+  c.fill(++cntr);
+  var copied = b.copy(c, 0, b.length - Math.floor(c.length / 2));
+  assert.strictEqual(Math.floor(c.length / 2), copied,
+    'copied ' + copied + ' bytes from end of b into beg. of c');
+
+  let successStatus = true;
+  for (var i = 0; i < Math.floor(c.length / 2); i++) {
+    if (b[b.length - Math.floor(c.length / 2) + i] !== c[i])
+      successStatus = false;
+  }
+
+  for (var i = Math.floor(c.length /2) + 1; i < c.length; i++) {
+    if (c[c.length-1] !== c[i])
+      successStatus = false;
+  }
+  assert.ok(successStatus,
+    'Copied bytes from end of large buffer into beginning of small buffer');
+
+  // try to copy 513 bytes, and check we don't overrun c
+  b.fill(++cntr);
+  c.fill(++cntr);
+  var copied = b.copy(c, 0, 0, 513);
+  assert.strictEqual(c.length, copied,
+    'copied ' + copied + ' bytes from b trying to overrun c');
+  compareBuffers(assert, b, c,
+    'copying to buffer that would overflow');
+
+  // copy 768 bytes from b into b
+  b.fill(++cntr);
+  b.fill(++cntr, 256);
+  var copied = b.copy(b, 0, 256, 1024);
+  assert.strictEqual(768, copied,
+    'copied ' + copied + ' bytes from b into b');
+
+  compareBuffers(assert, b, shimArray.map(()=>cntr),
+    'copy partial buffer to itself');
+
+  // copy string longer than buffer length (failure will segfault)
+  var bb = new Buffer(10);
+  bb.fill('hello crazy world');
+
+  // copy throws at negative sourceStart
+  assert.throws(function() {
+    Buffer(5).copy(Buffer(5), 0, -1);
+  }, RangeError, 'buffer copy throws at negative sourceStart');
+
+  // check sourceEnd resets to targetEnd if former is greater than the latter
+  b.fill(++cntr);
+  c.fill(++cntr);
+  var copied = b.copy(c, 0, 0, 1025);
+  assert.strictEqual(copied, c.length,
+    'copied ' + copied + ' bytes from b into c');
+  compareBuffers(assert, b, c, 'copying should reset sourceEnd if targetEnd if sourceEnd > targetEnd');
+
+  // throw with negative sourceEnd
+  assert.throws(function() {
+    b.copy(c, 0, 0, -1);
+  }, RangeError, 'buffer copy throws at negative sourceEnd');
+
+  // when sourceStart is greater than sourceEnd, zero copied
+  assert.equal(b.copy(c, 0, 100, 10), 0);
+
+  // when targetStart > targetLength, zero copied
+  assert.equal(b.copy(c, 512, 0, 10), 0);
+
+  // try to copy 0 bytes worth of data into an empty buffer
+  b.copy(new Buffer(0), 0, 0, 0);
+
+  // try to copy 0 bytes past the end of the target buffer
+  b.copy(new Buffer(0), 1, 1, 1);
+  b.copy(new Buffer(1), 1, 1, 1);
+
+  // try to copy 0 bytes from past the end of the source buffer
+  b.copy(new Buffer(1), 0, 2048, 2048);
+};
+
+exports.testBufferWrite = function (assert) {
+  let b = Buffer(1024);
+  b.fill(0);
+
+  assert.throws(() => {
+    b.write('test string', 0, 5, 'invalid');
+  }, TypeError, 'invalid encoding with buffer write throws');
+  // try to write a 0-length string beyond the end of b
+  assert.throws(function() {
+    b.write('', 2048);
+  }, RangeError, 'writing a 0-length string beyond buffer throws');
+  // throw when writing to negative offset
+  assert.throws(function() {
+    b.write('a', -1);
+  }, RangeError, 'writing negative offset on buffer throws');
+
+  // throw when writing past bounds from the pool
+  assert.throws(function() {
+    b.write('a', 2048);
+  }, RangeError, 'writing past buffer bounds from pool throws');
+
+  // testing for smart defaults and ability to pass string values as offset
+
+  // previous write API was the following:
+  // write(string, encoding, offset, length)
+  // this is planned on being removed in node v0.13,
+  // we will not support it
+  var writeTest = new Buffer('abcdes');
+  writeTest.write('n', 'utf8');
+//  writeTest.write('o', 'utf8', '1');
+  writeTest.write('d', '2', 'utf8');
+  writeTest.write('e', 3, 'utf8');
+//  writeTest.write('j', 'utf8', 4);
+  assert.equal(writeTest.toString(), 'nbdees',
+    'buffer write API alternative syntax works');
+};
+
+exports.testBufferWriteEncoding = function (assert) {
+
+  // Node #1210 Test UTF-8 string includes null character
+  var buf = new Buffer('\0');
+  assert.equal(buf.length, 1);
+  buf = new Buffer('\0\0');
+  assert.equal(buf.length, 2);
+
+  buf = new Buffer(2);
+  var written = buf.write(''); // 0byte
+  assert.equal(written, 0);
+  written = buf.write('\0'); // 1byte (v8 adds null terminator)
+  assert.equal(written, 1);
+  written = buf.write('a\0'); // 1byte * 2
+  assert.equal(written, 2);
+  // TODO, these tests write 0, possibly due to character encoding
+/*
+  written = buf.write('あ'); // 3bytes
+  assert.equal(written, 0);
+  written = buf.write('\0あ'); // 1byte + 3bytes
+  assert.equal(written, 1);
+*/
+  written = buf.write('\0\0あ'); // 1byte * 2 + 3bytes
+  buf = new Buffer(10);
+  written = buf.write('あいう'); // 3bytes * 3 (v8 adds null terminator)
+  assert.equal(written, 9);
+  written = buf.write('あいう\0'); // 3bytes * 3 + 1byte
+  assert.equal(written, 10);
+};
+
+exports.testBufferWriteWithMaxLength = function (assert) {
+  // Node #243 Test write() with maxLength
+  var buf = new Buffer(4);
+  buf.fill(0xFF);
+  var written = buf.write('abcd', 1, 2, 'utf8');
+  assert.equal(written, 2);
+  assert.equal(buf[0], 0xFF);
+  assert.equal(buf[1], 0x61);
+  assert.equal(buf[2], 0x62);
+  assert.equal(buf[3], 0xFF);
+
+  buf.fill(0xFF);
+  written = buf.write('abcd', 1, 4);
+  assert.equal(written, 3);
+  assert.equal(buf[0], 0xFF);
+  assert.equal(buf[1], 0x61);
+  assert.equal(buf[2], 0x62);
+  assert.equal(buf[3], 0x63);
+
+  buf.fill(0xFF);
+  // Ignore legacy API
+  /*
+     written = buf.write('abcd', 'utf8', 1, 2); // legacy style
+     console.log(buf);
+     assert.equal(written, 2);
+     assert.equal(buf[0], 0xFF);
+     assert.equal(buf[1], 0x61);
+     assert.equal(buf[2], 0x62);
+     assert.equal(buf[3], 0xFF);
+     */
+};
+
+exports.testBufferSlice = function (assert) {
+  var asciiString = 'hello world';
+  var offset = 100;
+  var b = Buffer(1024);
+  b.fill(0);
+
+  for (var i = 0; i < asciiString.length; i++) {
+    b[i] = asciiString.charCodeAt(i);
+  }
+  var asciiSlice = b.toString('utf8', 0, asciiString.length);
+  assert.equal(asciiString, asciiSlice);
+
+  var written = b.write(asciiString, offset, 'utf8');
+  assert.equal(asciiString.length, written);
+  asciiSlice = b.toString('utf8', offset, offset + asciiString.length);
+  assert.equal(asciiString, asciiSlice);
+
+  var sliceA = b.slice(offset, offset + asciiString.length);
+  var sliceB = b.slice(offset, offset + asciiString.length);
+  compareBuffers(assert, sliceA, sliceB,
+    'slicing is idempotent');
+
+  let sliceTest = true;
+  for (var j = 0; j < 100; j++) {
+    var slice = b.slice(100, 150);
+    if (50 !== slice.length)
+      sliceTest = false;
+    for (var i = 0; i < 50; i++) {
+      if (b[100 + i] !== slice[i])
+        sliceTest = false;
+    }
+  }
+  assert.ok(sliceTest, 'massive slice runs do not affect buffer');
+
+  // Single argument slice
+  let testBuf = new Buffer('abcde');
+  assert.equal('bcde', testBuf.slice(1).toString(), 'single argument slice');
+
+  // slice(0,0).length === 0
+  assert.equal(0, Buffer('hello').slice(0, 0).length, 'slice(0,0) === 0');
+
+  var buf = new Buffer('0123456789');
+  assert.equal(buf.slice(-10, 10), '0123456789', 'buffer slice range correct');
+  assert.equal(buf.slice(-20, 10), '0123456789', 'buffer slice range correct');
+  assert.equal(buf.slice(-20, -10), '', 'buffer slice range correct');
+  assert.equal(buf.slice(0, -1), '012345678', 'buffer slice range correct');
+  assert.equal(buf.slice(2, -2), '234567', 'buffer slice range correct');
+  assert.equal(buf.slice(0, 65536), '0123456789', 'buffer slice range correct');
+  assert.equal(buf.slice(65536, 0), '', 'buffer slice range correct');
+
+  let sliceTest = true;
+  for (var i = 0, s = buf.toString(); i < buf.length; ++i) {
+    if (buf.slice(-i) != s.slice(-i)) sliceTest = false;
+    if (buf.slice(0, -i) != s.slice(0, -i)) sliceTest = false;
+  }
+  assert.ok(sliceTest, 'buffer.slice should be consistent');
+
+  // Make sure modifying a sliced buffer, affects original and vice versa
+  b.fill(0);
+  let sliced = b.slice(0, 10);
+  let babyslice = sliced.slice(0, 5);
+
+  for (let i = 0; i < sliced.length; i++)
+    sliced[i] = 'jetpack'.charAt(i);
+
+  compareBuffers(assert, b, sliced,
+    'modifying sliced buffer affects original');
+
+  compareBuffers(assert, b, babyslice,
+    'modifying sliced buffer affects child-sliced buffer');
+
+  for (let i = 0; i < sliced.length; i++)
+    b[i] = 'odinmonkey'.charAt(i);
+
+  compareBuffers(assert, b, sliced,
+    'modifying original buffer affects sliced');
+
+  compareBuffers(assert, b, babyslice,
+    'modifying original buffer affects grandchild sliced buffer');
+};
+
+exports.testSlicingParents = function (assert) {
+  let root = Buffer(5);
+  let child = root.slice(0, 4);
+  let grandchild = child.slice(0, 3);
+
+  assert.equal(root.parent, undefined, 'a new buffer should not have a parent');
+
+  // make sure a zero length slice doesn't set the .parent attribute
+  assert.equal(root.slice(0,0).parent, undefined,
+    '0-length slice should not have a parent');
+
+  assert.equal(child.parent, root,
+    'a valid slice\'s parent should be the original buffer (child)');
+
+  assert.equal(grandchild.parent, root,
+    'a valid slice\'s parent should be the original buffer (grandchild)');
+};
+
 exports.testIsBuffer = function (assert) {
   let buffer = new Buffer('content', 'utf8');
   assert.ok(Buffer.isBuffer(buffer), 'isBuffer truthy on buffers');
   assert.ok(!Buffer.isBuffer({}), 'isBuffer falsy on objects');
   assert.ok(!Buffer.isBuffer(new Uint8Array()),
     'isBuffer falsy on Uint8Array');
+  assert.ok(Buffer.isBuffer(buffer.slice(0)), 'Buffer#slice should be a new buffer');
+};
+
+exports.testBufferConcat = function (assert) {
+  let zero = [];
+  let one = [ new Buffer('asdf') ];
+  let long = [];
+  for (let i = 0; i < 10; i++) long.push(new Buffer('asdf'));
+
+  let flatZero = Buffer.concat(zero);
+  let flatOne = Buffer.concat(one);
+  let flatLong = Buffer.concat(long);
+  let flatLongLen = Buffer.concat(long, 40);
+
+  assert.equal(flatZero.length, 0);
+  assert.equal(flatOne.toString(), 'asdf');
+  assert.equal(flatOne, one[0]);
+  assert.ok(flatLong.toString(), (new Array(10+1).join('asdf')));
+  assert.equal(flatLongLen.toString(), (new Array(10+1).join('asdf')));
 };
 
 exports.testBufferByteLength = function (assert) {
   let str = '\u00bd + \u00bc = \u00be';
   assert.equal(Buffer.byteLength(str), 12,
     'correct byteLength of string');
+
+  assert.equal(14, Buffer.byteLength('Il était tué'));
+  assert.equal(14, Buffer.byteLength('Il était tué', 'utf8'));
+  // We do not currently support these encodings
+  /*
+  ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach(function(encoding) {
+  assert.equal(24, Buffer.byteLength('Il était tué', encoding));
+  });
+  assert.equal(12, Buffer.byteLength('Il était tué', 'ascii'));
+  assert.equal(12, Buffer.byteLength('Il était tué', 'binary'));
+  */
 };
 
 exports.testTextEncoderDecoder = function (assert) {
   assert.ok(TextEncoder, 'TextEncoder exists');
   assert.ok(TextDecoder, 'TextDecoder exists');
 };
 
-// List of supported encodings taken from:
-// http://mxr.mozilla.org/mozilla-central/source/dom/encoding/labelsencodings.properties
-const ENCODINGS = { "unicode-1-1-utf-8": 1, "utf-8": 1, "utf8": 1,
-  "866": 1, "cp866": 1, "csibm866": 1, "ibm866": 1, "csisolatin2": 1,
-  "iso-8859-2": 1, "iso-ir-101": 1, "iso8859-2": 1, "iso88592": 1,
-  "iso_8859-2": 1, "iso_8859-2:1987": 1, "l2": 1, "latin2": 1, "csisolatin3": 1,
-  "iso-8859-3": 1, "iso-ir-109": 1, "iso8859-3": 1, "iso88593": 1,
-  "iso_8859-3": 1, "iso_8859-3:1988": 1, "l3": 1, "latin3": 1, "csisolatin4": 1,
-  "iso-8859-4": 1, "iso-ir-110": 1, "iso8859-4": 1, "iso88594": 1,
-  "iso_8859-4": 1, "iso_8859-4:1988": 1, "l4": 1, "latin4": 1,
-  "csisolatincyrillic": 1, "cyrillic": 1, "iso-8859-5": 1, "iso-ir-144": 1,
-  "iso8859-5": 1, "iso88595": 1, "iso_8859-5": 1, "iso_8859-5:1988": 1,
-  "arabic": 1, "asmo-708": 1, "csiso88596e": 1, "csiso88596i": 1,
-  "csisolatinarabic": 1, "ecma-114": 1, "iso-8859-6": 1, "iso-8859-6-e": 1,
-  "iso-8859-6-i": 1, "iso-ir-127": 1, "iso8859-6": 1, "iso88596": 1,
-  "iso_8859-6": 1, "iso_8859-6:1987": 1, "csisolatingreek": 1, "ecma-118": 1,
-  "elot_928": 1, "greek": 1, "greek8": 1, "iso-8859-7": 1, "iso-ir-126": 1,
-  "iso8859-7": 1, "iso88597": 1, "iso_8859-7": 1, "iso_8859-7:1987": 1,
-  "sun_eu_greek": 1, "csiso88598e": 1, "csisolatinhebrew": 1, "hebrew": 1,
-  "iso-8859-8": 1, "iso-8859-8-e": 1, "iso-ir-138": 1, "iso8859-8": 1,
-  "iso88598": 1, "iso_8859-8": 1, "iso_8859-8:1988": 1, "visual": 1,
-  "csiso88598i": 1, "iso-8859-8-i": 1, "logical": 1, "csisolatin6": 1,
-  "iso-8859-10": 1, "iso-ir-157": 1, "iso8859-10": 1, "iso885910": 1,
-  "l6": 1, "latin6": 1, "iso-8859-13": 1, "iso8859-13": 1, "iso885913": 1,
-  "iso-8859-14": 1, "iso8859-14": 1, "iso885914": 1, "csisolatin9": 1,
-  "iso-8859-15": 1, "iso8859-15": 1, "iso885915": 1, "iso_8859-15": 1,
-  "l9": 1, "iso-8859-16": 1, "cskoi8r": 1, "koi": 1, "koi8": 1, "koi8-r": 1,
-  "koi8_r": 1, "koi8-u": 1, "csmacintosh": 1, "mac": 1, "macintosh": 1,
-  "x-mac-roman": 1, "dos-874": 1, "iso-8859-11": 1, "iso8859-11": 1,
-  "iso885911": 1, "tis-620": 1, "windows-874": 1, "cp1250": 1,
-  "windows-1250": 1, "x-cp1250": 1, "cp1251": 1, "windows-1251": 1,
-  "x-cp1251": 1, "ansi_x3.4-1968": 1, "ascii": 1, "cp1252": 1, "cp819": 1,
-  "csisolatin1": 1, "ibm819": 1, "iso-8859-1": 1, "iso-ir-100": 1,
-  "iso8859-1": 1, "iso88591": 1, "iso_8859-1": 1, "iso_8859-1:1987": 1,
-  "l1": 1, "latin1": 1, "us-ascii": 1, "windows-1252": 1, "x-cp1252": 1,
-  "cp1253": 1, "windows-1253": 1, "x-cp1253": 1, "cp1254": 1, "csisolatin5": 1,
-  "iso-8859-9": 1, "iso-ir-148": 1, "iso8859-9": 1, "iso88599": 1,
-  "iso_8859-9": 1, "iso_8859-9:1989": 1, "l5": 1, "latin5": 1,
-  "windows-1254": 1, "x-cp1254": 1, "cp1255": 1, "windows-1255": 1,
-  "x-cp1255": 1, "cp1256": 1, "windows-1256": 1, "x-cp1256": 1, "cp1257": 1,
-  "windows-1257": 1, "x-cp1257": 1, "cp1258": 1, "windows-1258": 1,
-  "x-cp1258": 1, "x-mac-cyrillic": 1, "x-mac-ukrainian": 1, "chinese": 1,
-  "csgb2312": 1, "csiso58gb231280": 1, "gb2312": 1, "gb_2312": 1,
-  "gb_2312-80": 1, "gbk": 1, "iso-ir-58": 1, "x-gbk": 1, "gb18030": 1,
-  "hz-gb-2312": 1, "big5": 1, "big5-hkscs": 1, "cn-big5": 1, "csbig5": 1,
-  "x-x-big5": 1, "cseucpkdfmtjapanese": 1, "euc-jp": 1, "x-euc-jp": 1,
-  "csiso2022jp": 1, "iso-2022-jp": 1, "csshiftjis": 1, "ms_kanji": 1,
-  "shift-jis": 1, "shift_jis": 1, "sjis": 1, "windows-31j": 1, "x-sjis": 1,
-  "cseuckr": 1, "csksc56011987": 1, "euc-kr": 1, "iso-ir-149": 1, "korean": 1,
-  "ks_c_5601-1987": 1, "ks_c_5601-1989": 1, "ksc5601": 1, "ksc_5601": 1,
-  "windows-949": 1, "csiso2022kr": 1, "iso-2022-kr": 1, "utf-16": 1,
-  "utf-16le": 1, "utf-16be": 1, "x-user-defined": 1 };
+exports.testOverflowedBuffers = function (assert) {
+  assert.throws(function() {
+    new Buffer(0xFFFFFFFF);
+  }, RangeError, 'correctly throws buffer overflow');
+
+  assert.throws(function() {
+    new Buffer(0xFFFFFFFFF);
+  }, RangeError, 'correctly throws buffer overflow');
+
+  assert.throws(function() {
+    var buf = new Buffer(8);
+    buf.readFloatLE(0xffffffff);
+  }, RangeError, 'correctly throws buffer overflow with readFloatLE');
+
+  assert.throws(function() {
+    var buf = new Buffer(8);
+    buf.writeFloatLE(0.0, 0xffffffff);
+  }, RangeError, 'correctly throws buffer overflow with writeFloatLE');
+
+  //ensure negative values can't get past offset
+  assert.throws(function() {
+    var buf = new Buffer(8);
+    buf.readFloatLE(-1);
+  }, RangeError, 'correctly throws with readFloatLE negative values');
+
+  assert.throws(function() {
+    var buf = new Buffer(8);
+    buf.writeFloatLE(0.0, -1);
+  }, RangeError, 'correctly throws with writeFloatLE with negative values');
+
+  assert.throws(function() {
+    var buf = new Buffer(8);
+    buf.readFloatLE(-1);
+  }, RangeError, 'correctly throws with readFloatLE with negative values');
+};
 
+exports.testReadWriteDataTypeErrors = function (assert) {
+  var buf = new Buffer(0);
+  assert.throws(function() { buf.readUInt8(0); }, RangeError,
+    'readUInt8(0) throws');
+  assert.throws(function() { buf.readInt8(0); }, RangeError,
+    'readInt8(0) throws');
+
+  [16, 32].forEach(function(bits) {
+    var buf = new Buffer(bits / 8 - 1);
+    assert.throws(function() { buf['readUInt' + bits + 'BE'](0); },
+      RangeError,
+      'readUInt' + bits + 'BE');
+
+    assert.throws(function() { buf['readUInt' + bits + 'LE'](0); },
+      RangeError,
+      'readUInt' + bits + 'LE');
+
+    assert.throws(function() { buf['readInt' + bits + 'BE'](0); },
+      RangeError,
+      'readInt' + bits + 'BE()');
+
+    assert.throws(function() { buf['readInt' + bits + 'LE'](0); },
+      RangeError,
+      'readInt' + bits + 'LE()');
+  });
+};
+
+safeMerge(exports, require('./buffers/test-write-types'));
+safeMerge(exports, require('./buffers/test-read-types'));
+
+function compareBuffers (assert, buf1, buf2, message) {
+  let status = true;
+  for (let i = 0; i < Math.min(buf1.length, buf2.length); i++) {
+    if (buf1[i] !== buf2[i])
+      status = false;
+  }
+  assert.ok(status, 'buffer successfully copied: ' + message);
+}
 require('sdk/test').run(exports);
--- a/addon-sdk/source/test/test-content-loader.js
+++ b/addon-sdk/source/test/test-content-loader.js
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 const { Loader } = require('sdk/content/loader');
 const self = require("sdk/self");
+const fixtures = require("./fixtures");
 
 exports['test:contentURL'] = function(assert) {
   let loader = Loader(),
       value, emitted = 0, changes = 0;
 
   assert.throws(
     function() loader.contentURL = 4,
     /The `contentURL` option must be a valid URL./,
@@ -167,17 +168,17 @@ exports['test:contentScript'] = function
   loader.contentScript = value = ["1;", "2;"];
   assert.equal(
     value,
     loader.contentScript
   );
 };
 
 exports['test:contentScriptFile'] = function(assert) {
-  let loader = Loader(), value, uri = self.data.url("test-content-loader.js");
+  let loader = Loader(), value, uri = fixtures.url("test-content-loader.js");
   assert.equal(
     null,
     loader.contentScriptFile,
     '`contentScriptFile` defaults to `null`'
   );
   loader.contentScriptFile = value = uri;
   assert.equal(
     value,
--- a/addon-sdk/source/test/test-content-script.js
+++ b/addon-sdk/source/test/test-content-script.js
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const hiddenFrames = require("sdk/frame/hidden-frame");
 const { create: makeFrame } = require("sdk/frame/utils");
 const { window } = require("sdk/addon/window");
 const { Loader } = require('sdk/test/loader');
 const { URL } = require("sdk/url");
-const testURI = require("sdk/self").data.url("test.html");
+const testURI = require("./fixtures").url("test.html");
 const testHost = URL(testURI).scheme + '://' + URL(testURI).host;
 
 /*
  * Utility function that allow to easily run a proxy test with a clean
  * new HTML document. See first unit test for usage.
  */
 function createProxyTest(html, callback) {
   return function (assert, done) {
--- a/addon-sdk/source/test/test-content-symbiont.js
+++ b/addon-sdk/source/test/test-content-symbiont.js
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const { Cc, Ci } = require('chrome');
 const { Symbiont } = require('sdk/content/symbiont');
 const self = require('sdk/self');
+const fixtures = require("./fixtures");
 const { close } = require('sdk/window/helpers');
 const app = require("sdk/system/xul-app");
 
 function makeWindow() {
   let content =
     '<?xml version="1.0"?>' +
     '<window ' +
     'xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">' +
@@ -22,17 +23,17 @@ function makeWindow() {
 
   return Cc["@mozilla.org/embedcomp/window-watcher;1"].
          getService(Ci.nsIWindowWatcher).
          openWindow(null, url, null, features.join(","), null);
 }
 
 exports['test:constructing symbiont && validating API'] = function(assert) {
   let contentScript = ["1;", "2;"];
-  let contentScriptFile = self.data.url("test-content-symbiont.js");
+  let contentScriptFile = fixtures.url("test-content-symbiont.js");
 
   // We can avoid passing a `frame` argument. Symbiont will create one
   // by using HiddenFrame module
   let contentSymbiont = Symbiont({
     contentScriptFile: contentScriptFile,
     contentScript: contentScript,
     contentScriptWhen: "start"
   });
@@ -70,16 +71,18 @@ exports["test:communication with worker 
   if (app.is('Fennec')) {
     assert.pass('Test skipped on Fennec');
     done();
   }
 
   let window = makeWindow();
   let contentSymbiont;
 
+  console.log(window)
+
   function onMessage1(message) {
     assert.equal(message, 1, "Program gets message via onMessage.");
     contentSymbiont.removeListener('message', onMessage1);
     contentSymbiont.on('message', onMessage2);
     contentSymbiont.postMessage(2);
   };
 
   function onMessage2(message) {
@@ -149,38 +152,9 @@ exports["test:document element present o
         assert.ok(message, "document element present on 'start'");
       else
         assert.pass("document element not necessarily present on 'start'");
       done();
     }
   });
 };
 
-exports["test:direct communication with trusted document"] = function(assert, done) {
-  let worker = Symbiont({
-    contentURL: require("sdk/self").data.url("test-trusted-document.html")
-  });
-
-  worker.port.on('document-to-addon', function (arg) {
-    assert.equal(arg, "ok", "Received an event from the document");
-    worker.destroy();
-    done();
-  });
-  worker.port.emit('addon-to-document', 'ok');
-};
-
-exports["test:`addon` is not available when a content script is set"] = function(assert, done) {
-  let worker = Symbiont({
-    contentURL: require("sdk/self").data.url("test-trusted-document.html"),
-    contentScript: "new " + function ContentScriptScope() {
-      self.port.emit("cs-to-addon", "addon" in unsafeWindow);
-    }
-  });
-
-  worker.port.on('cs-to-addon', function (hasAddon) {
-    assert.equal(hasAddon, false,
-      "`addon` is not available");
-    worker.destroy();
-    done();
-  });
-};
-
 require("test").run(exports);
--- a/addon-sdk/source/test/test-context-menu.js
+++ b/addon-sdk/source/test/test-context-menu.js
@@ -16,16 +16,17 @@ const ITEM_CLASS = "addon-context-menu-i
 const SEPARATOR_CLASS = "addon-context-menu-separator";
 const OVERFLOW_THRESH_DEFAULT = 10;
 const OVERFLOW_THRESH_PREF =
   "extensions.addon-sdk.context-menu.overflowThreshold";
 const OVERFLOW_MENU_CLASS = "addon-content-menu-overflow-menu";
 const OVERFLOW_POPUP_CLASS = "addon-content-menu-overflow-popup";
 
 const TEST_DOC_URL = module.uri.replace(/\.js$/, ".html");
+const data = require("./fixtures");
 
 // Tests that when present the separator is placed before the separator from
 // the old context-menu module
 exports.testSeparatorPosition = function (assert, done) {
   let test = new TestHelper(assert, done);
   let loader = test.newLoader();
 
   // Create the old separator
@@ -889,17 +890,17 @@ exports.testContentScriptFile = function
     },
     new RegExp("The 'contentScriptFile' option must be a local file URL " +
     "or an array of local file URLs."),
     "Item throws when contentScriptFile is a remote URL");
 
   // But accept files from data folder
   let item = new loader.cm.Item({
     label: "item",
-    contentScriptFile: require("sdk/self").data.url("test-context-menu.js")
+    contentScriptFile: data.url("test-context-menu.js")
   });
 
   test.showMenu(null, function (popup) {
     test.checkMenu([item], [], []);
     test.done();
   });
 };
 
@@ -2664,28 +2665,28 @@ exports.testItemNoImage = function (asse
 }
 
 
 // Test image support.
 exports.testItemImage = function (assert, done) {
   let test = new TestHelper(assert, done);
   let loader = test.newLoader();
 
-  let imageURL = require("sdk/self").data.url("moz_favicon.ico");
+  let imageURL = data.url("moz_favicon.ico");
   let item = new loader.cm.Item({ label: "item", image: imageURL });
   let menu = new loader.cm.Menu({ label: "menu", image: imageURL, items: [
     loader.cm.Item({ label: "subitem" })
   ]});
   assert.equal(item.image, imageURL, "Should have set the image correctly");
   assert.equal(menu.image, imageURL, "Should have set the image correctly");
 
   test.showMenu(null, function (popup) {
     test.checkMenu([item, menu], [], []);
 
-    let imageURL2 = require("sdk/self").data.url("dummy.ico");
+    let imageURL2 = data.url("dummy.ico");
     item.image = imageURL2;
     menu.image = imageURL2;
     assert.equal(item.image, imageURL2, "Should have set the image correctly");
     assert.equal(menu.image, imageURL2, "Should have set the image correctly");
     test.checkMenu([item, menu], [], []);
 
     item.image = null;
     menu.image = null;
@@ -2696,17 +2697,17 @@ exports.testItemImage = function (assert
     test.done();
   });
 };
 
 // Test image URL validation.
 exports.testItemImageValidURL = function (assert, done) {
   let test = new TestHelper(assert, done);
   let loader = test.newLoader();
- 
+
   assert.throws(function(){
       new loader.cm.Item({
         label: "item 1",
         image: "foo"
       })
     }, /Image URL validation failed/
   );
 
@@ -2720,18 +2721,18 @@ exports.testItemImageValidURL = function
 
   assert.throws(function(){
       new loader.cm.Item({
         label: "item 3",
         image: 0
       })
     }, /Image URL validation failed/
   );
-   
-  let imageURL = require("sdk/self").data.url("moz_favicon.ico");
+
+  let imageURL = data.url("moz_favicon.ico");
   let item4 = new loader.cm.Item({ label: "item 4", image: imageURL });
   let item5 = new loader.cm.Item({ label: "item 5", image: null });
   let item6 = new loader.cm.Item({ label: "item 6", image: undefined });
 
   assert.equal(item4.image, imageURL, "Should be proper image URL");
   assert.equal(item5.image, null, "Should be null image");
   assert.equal(item6.image, undefined, "Should be undefined image");
 
@@ -3223,17 +3224,17 @@ TestHelper.prototype = {
                          "Item should not have image");
         this.assert.ok(!elt.classList.contains("menu-iconic") && !elt.classList.contains("menuitem-iconic"),
                          "The iconic classes should not be present")
       }
     }
   },
 
   // Asserts that the context menu looks OK given the arguments.  presentItems
-  // are items that have been added to the menu.  absentItems are items that 
+  // are items that have been added to the menu.  absentItems are items that
   // shouldn't match the current context.  removedItems are items that have been
   // removed from the menu.
   checkMenu: function (presentItems, absentItems, removedItems) {
     // Count up how many top-level items there are
     let total = 0;
     for (let item of presentItems) {
       if (absentItems.indexOf(item) < 0 && removedItems.indexOf(item) < 0)
         total++;
--- a/addon-sdk/source/test/test-loader.js
+++ b/addon-sdk/source/test/test-loader.js
@@ -31,17 +31,17 @@ exports['test syntax errors'] = function
   let loader = Loader({ paths: { '': uri } });
 
   try {
     let program = main(loader, 'main');
   } catch (error) {
     assert.equal(error.name, "SyntaxError", "throws syntax error");
     assert.equal(error.fileName.split("/").pop(), "error.js",
               "Error contains filename");
-    assert.equal(error.lineNumber, 11, "error is on line 11")
+    assert.equal(error.lineNumber, 11, "error is on line 11");
     let stack = parseStack(error.stack);
 
     assert.equal(stack.pop().fileName, uri + "error.js",
                  "last frame file containing syntax error");
     assert.equal(stack.pop().fileName, uri + "main.js",
                  "previous frame is a requirer module");
     assert.equal(stack.pop().fileName, module.uri,
                  "previous to it is a test module");
@@ -142,17 +142,51 @@ exports['test early errors in module'] =
     assert.equal(frame.lineNumber, 7, "caller line is in the stack");
 
 
     assert.equal(stack.pop().fileName, module.uri,
                  "this test module is next in the stack");
   } finally {
     unload(loader);
   }
-}
+};
+
+exports['test require json'] = function (assert) {
+  let data = require('./fixtures/loader/json/manifest.json');
+  assert.equal(data.name, 'Jetpack Loader Test', 'loads json with strings');
+  assert.equal(data.version, '1.0.1', 'loads json with strings');
+  assert.equal(data.dependencies.async, '*', 'loads json with objects');
+  assert.equal(data.dependencies.underscore, '*', 'loads json with objects');
+  assert.equal(data.contributors.length, 4, 'loads json with arrays');
+  assert.ok(Array.isArray(data.contributors), 'loads json with arrays');
+  data.version = '2.0.0';
+  let newdata = require('./fixtures/loader/json/manifest.json');
+  assert.equal(newdata.version, '2.0.0',
+    'JSON objects returned should be cached and the same instance');
+
+  try {
+    require('./fixtures/loader/json/invalid.json');
+    assert.fail('Error not thrown when loading invalid json');
+  } catch (err) {
+    assert.ok(err, 'error thrown when loading invalid json');
+    assert.ok(/JSON\.parse/.test(err.message),
+      'should thrown an error from JSON.parse, not attempt to load .json.js');
+  }
+ 
+  // Try again to ensure an empty module isn't loaded from cache
+  try {
+    require('./fixtures/loader/json/invalid.json');
+    assert.fail('Error not thrown when loading invalid json a second time');
+  } catch (err) {
+    assert.ok(err,
+      'error thrown when loading invalid json a second time');
+    assert.ok(/JSON\.parse/.test(err.message),
+      'should thrown an error from JSON.parse a second time, not attempt to load .json.js');
+  }
+};
 
 exports['test setting metadata for newly created sandboxes'] = function(assert) {
   let addonID = 'random-addon-id';
   let uri = root + '/fixtures/loader/cycles/';
   let loader = Loader({ paths: { '': uri }, id: addonID });
 
   let dbg = new Debugger();
   dbg.onNewGlobalObject = function(global) {
@@ -160,11 +194,28 @@ exports['test setting metadata for newly
 
     let metadata = Cu.getSandboxMetadata(global.unsafeDereference());
     assert.ok(metadata, 'this global has attached metadata');
     assert.equal(metadata.URI, uri + 'main.js', 'URI is set properly');
     assert.equal(metadata.addonID, addonID, 'addon ID is set');
   }
 
   let program = main(loader, 'main');
-}
+};
+
+exports['test require .json, .json.js'] = function (assert) {
+  let testjson = require('./fixtures/loader/json/test.json');
+  assert.equal(testjson.filename, 'test.json',
+    'require("./x.json") should load x.json, not x.json.js');
+
+  let nodotjson = require('./fixtures/loader/json/nodotjson.json');
+  assert.equal(nodotjson.filename, 'nodotjson.json.js',
+    'require("./x.json") should load x.json.js when x.json does not exist');
+  nodotjson.data.prop = 'hydralisk';
+
+  // require('nodotjson.json') and require('nodotjson.json.js')
+  // should resolve to the same file
+  let nodotjsonjs = require('./fixtures/loader/json/nodotjson.json.js');
+  assert.equal(nodotjsonjs.data.prop, 'hydralisk',
+    'js modules are cached whether access via .json.js or .json');
+};
 
 require('test').run(exports);
--- a/addon-sdk/source/test/test-net-url.js
+++ b/addon-sdk/source/test/test-net-url.js
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { readURI, readURISync } = require("sdk/net/url");
-const { data } = require("sdk/self");
+const data = require("./fixtures");
 
 const utf8text = "Hello, ゼロ!";
 const latin1text = "Hello, ゼロ!";
 
 const dataURIutf8 = "data:text/plain;charset=utf-8," + encodeURIComponent(utf8text);
 const dataURIlatin1 = "data:text/plain;charset=ISO-8859-1," + escape(latin1text);
 const chromeURI = "chrome://global-platform/locale/accessible.properties";
 
--- a/addon-sdk/source/test/test-page-mod.js
+++ b/addon-sdk/source/test/test-page-mod.js
@@ -8,25 +8,28 @@ const testPageMod = require("./pagemod-t
 const { Loader } = require('sdk/test/loader');
 const tabs = require("sdk/tabs");
 const timer = require("sdk/timers");
 const { Cc, Ci, Cu } = require("chrome");
 const { open, getFrames, getMostRecentBrowserWindow } = require('sdk/window/utils');
 const windowUtils = require('sdk/deprecated/window-utils');
 const { getTabContentWindow, getActiveTab, setTabURL, openTab, closeTab } = require('sdk/tabs/utils');
 const xulApp = require("sdk/system/xul-app");
-const { data, isPrivateBrowsingSupported } = require('sdk/self');
+const { isPrivateBrowsingSupported } = require('sdk/self');
 const { isPrivate } = require('sdk/private-browsing');
 const { openWebpage } = require('./private-browsing/helper');
 const { isTabPBSupported, isWindowPBSupported, isGlobalPBSupported } = require('sdk/private-browsing/utils');
 const promise = require("sdk/core/promise");
 const { pb } = require('./private-browsing/helper');
 const { URL } = require("sdk/url");
-const testPageURI = require("sdk/self").data.url("test.html");
+
 const { waitUntil } = require("sdk/test/utils");
+const data = require("./fixtures");
+
+const testPageURI = data.url("test.html");
 
 // The following adds Debugger constructor to the global namespace.
 const { addDebuggerToGlobal } =
   Cu.import('resource://gre/modules/jsdebugger.jsm', {});
 addDebuggerToGlobal(this);
 
 function Isolate(worker) {
   return "(" + worker + ")()";
@@ -306,17 +309,17 @@ exports.testMixedContext = function(asse
     }
   );
 };
 
 exports.testHistory = function(assert, done) {
   // We need a valid url in order to have a working History API.
   // (i.e do not work on data: or about: pages)
   // Test bug 679054.
-  let url = require("sdk/self").data.url("test-page-mod.html");
+  let url = data.url("test-page-mod.html");
   let callbackDone = null;
   testPageMod(assert, done, url, [{
       include: url,
       contentScriptWhen: 'end',
       contentScript: 'new ' + function WorkerScope() {
         history.pushState({}, "", "#");
         history.replaceState({foo: "bar"}, "", "#");
         self.postMessage(history.state);
@@ -686,18 +689,17 @@ exports.testContentScriptOptionsOption =
   );
 };
 
 exports.testPageModCss = function(assert, done) {
   let [pageMod] = testPageMod(assert, done,
     'data:text/html;charset=utf-8,<div style="background: silver">css test</div>', [{
       include: ["*", "data:*"],
       contentStyle: "div { height: 100px; }",
-      contentStyleFile:
-        require("sdk/self").data.url("pagemod-css-include-file.css")
+      contentStyleFile: data.url("pagemod-css-include-file.css")
     }],
     function(win, done) {
       let div = win.document.querySelector("div");
       assert.equal(
         div.clientHeight,
         100,
         "PageMod contentStyle worked"
       );
--- a/addon-sdk/source/test/test-page-worker.js
+++ b/addon-sdk/source/test/test-page-worker.js
@@ -3,17 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { Loader } = require('sdk/test/loader');
 const Pages = require("sdk/page-worker");
 const Page = Pages.Page;
 const { URL } = require("sdk/url");
-const testURI = require("sdk/self").data.url("test.html");
+const fixtures = require("./fixtures");
+const testURI = fixtures.url("test.html");
 
 const ERR_DESTROYED =
   "Couldn't find the worker to receive this message. " +
   "The script may not be initialized yet, or may already have been unloaded.";
 
 exports.testSimplePageCreation = function(assert, done) {
   let page = new Page({
     contentScript: "self.postMessage(window.location.href)",
@@ -259,18 +260,18 @@ exports.testLoadContentPage = function(a
     onMessage: function(message) {
       // The message is an array whose first item is the test method to call
       // and the rest of whose items are arguments to pass it.
       let msg = message.shift();
       if (msg == "done")
         return done();
       assert[msg].apply(assert, message);
     },
-    contentURL: require("sdk/self").data.url("test-page-worker.html"),
-    contentScriptFile: require("sdk/self").data.url("test-page-worker.js"),
+    contentURL: fixtures.url("test-page-worker.html"),
+    contentScriptFile: fixtures.url("test-page-worker.js"),
     contentScriptWhen: "ready"
   });
 }
 
 exports.testAllowScriptDefault = function(assert, done) {
   let page = Page({
     onMessage: function(message) {
       assert.ok(message, "Script is allowed to run by default.");
--- a/addon-sdk/source/test/test-panel.js
+++ b/addon-sdk/source/test/test-panel.js
@@ -17,18 +17,19 @@ const self = require('sdk/self');
 const { open, close, focus, ready } = require('sdk/window/helpers');
 const { isPrivate } = require('sdk/private-browsing');
 const { isWindowPBSupported, isGlobalPBSupported } = require('sdk/private-browsing/utils');
 const { defer, all } = require('sdk/core/promise');
 const { getMostRecentBrowserWindow } = require('sdk/window/utils');
 const { getWindow } = require('sdk/panel/window');
 const { pb } = require('./private-browsing/helper');
 const { URL } = require('sdk/url');
+const fixtures = require('./fixtures')
 
-const SVG_URL = self.data.url('mofo_logo.SVG');
+const SVG_URL = fixtures.url('mofo_logo.SVG');
 const Isolate = fn => '(' + fn + ')()';
 
 function ignorePassingDOMNodeWarning(type, message) {
   if (type !== 'warn' || !message.startsWith('Passing a DOM node'))
     console[type](message);
 }
 
 function makeEmptyPrivateBrowserWindow(options) {
deleted file mode 100644
--- a/addon-sdk/source/test/test-places-bookmarks.js
+++ /dev/null
@@ -1,967 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-'use strict';
-
-module.metadata = {
-  'engines': {
-    'Firefox': '*'
-  }
-};
-
-const { Cc, Ci } = require('chrome');
-const { request } = require('sdk/addon/host');
-const { filter } = require('sdk/event/utils');
-const { on, off } = require('sdk/event/core');
-const { setTimeout } = require('sdk/timers');
-const { newURI } = require('sdk/url/utils');
-const { defer, all } = require('sdk/core/promise');
-const { defer: async } = require('sdk/lang/functional');
-const { before, after } = require('sdk/test/utils');
-
-const {
-  Bookmark, Group, Separator,
-  save, search, remove,
-  MENU, TOOLBAR, UNSORTED
-} = require('sdk/places/bookmarks');
-const {
-  invalidResolve, invalidReject, createTree,
-  compareWithHost, createBookmark, createBookmarkItem,
-  createBookmarkTree, addVisits, resetPlaces
-} = require('./places-helper');
-const { promisedEmitter } = require('sdk/places/utils');
-const bmsrv = Cc['@mozilla.org/browser/nav-bookmarks-service;1'].
-                    getService(Ci.nsINavBookmarksService);
-const tagsrv = Cc['@mozilla.org/browser/tagging-service;1'].
-                    getService(Ci.nsITaggingService);
-
-exports.testDefaultFolders = function (assert) {
-  var ids = [
-    bmsrv.bookmarksMenuFolder,
-    bmsrv.toolbarFolder,
-    bmsrv.unfiledBookmarksFolder
-  ];
-  [MENU, TOOLBAR, UNSORTED].forEach(function (g, i) {
-    assert.ok(g.id === ids[i], ' default group matches id');
-  });