Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Wed, 08 Aug 2012 15:09:49 -0700
changeset 112940 52ff63c1941765a276cf9f87326db6600c60866d
parent 112939 21b4797e4cb3e03e541bbe3b0bb0e79312dd9d98 (current diff)
parent 107290 4e3fb1f9f72adcb30c3c130d2417079f50de7d5b (diff)
child 112941 826f67c39bdc42065a19df95ee7c0b53a9474b0d
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone17.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
Merge from mozilla-central.
b2g/installer/package-manifest.in
build/application.ini.in
build/mobile/devicemanagerSUT.py
caps/src/nsSecurityManagerFactory.cpp
config/system-headers
configure.in
content/base/public/nsIDocument.h
content/base/public/nsINode.h
content/base/src/Makefile.in
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsGenericElement.cpp
content/base/src/nsGkAtomList.h
content/base/test/Makefile.in
content/events/public/nsEventNameList.h
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMEvent.h
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
content/html/content/public/nsHTMLMediaElement.h
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsHTMLAudioElement.cpp
content/html/content/src/nsHTMLMediaElement.cpp
content/media/MediaResource.cpp
content/media/nsAudioStream.cpp
content/media/nsAudioStream.h
content/media/nsBuiltinDecoder.cpp
content/media/nsBuiltinDecoderReader.h
content/media/nsBuiltinDecoderStateMachine.cpp
content/xul/content/src/nsXULElement.cpp
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
dom/Makefile.in
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsIScriptContext.h
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
dom/base/nsPIDOMWindow.h
dom/bindings/Codegen.py
dom/dom-config.mk
dom/indexedDB/IndexedDatabaseManager.cpp
dom/ipc/AudioParent.cpp
dom/ipc/ContentParent.cpp
dom/ipc/PBrowser.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/workers/Events.cpp
dom/workers/Exceptions.cpp
dom/workers/File.cpp
dom/workers/Location.cpp
dom/workers/Navigator.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerScope.cpp
editor/libeditor/html/nsHTMLEditRules.cpp
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/html/nsTableEditor.cpp
embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
image/src/imgStatusTracker.h
ipc/glue/GeckoChildProcessHost.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/src/config/system-headers
js/src/configure.in
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/Parser.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.h
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsfuninlines.h
js/src/jsobj.h
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsutil.h
js/src/jswrapper.cpp
js/src/jswrapper.h
js/src/jsxml.cpp
js/src/shell/js.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/shell/xpcshell.cpp
js/xpconnect/src/XPCComponents.cpp
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/base/crashtests/crashtests.list
layout/base/nsCSSRendering.cpp
layout/base/nsCSSRendering.h
layout/base/nsDisplayList.h
layout/base/nsLayoutDebugger.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/base/nsPresContext.cpp
layout/base/nsPresShell.cpp
layout/build/Makefile.in
layout/generic/crashtests/crashtests.list
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsTextFrame.h
layout/generic/nsTextFrameThebes.cpp
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
layout/style/nsCSSParser.cpp
layout/style/nsCSSPseudoClasses.cpp
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsStyleStruct.h
layout/style/nsStyleStructInlines.h
layout/style/test/Makefile.in
layout/svg/base/src/nsSVGUtils.cpp
layout/svg/base/src/nsSVGUtils.h
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/Makefile.in
mobile/android/base/gfx/LayerController.java
mobile/android/chrome/content/browser.js
mobile/android/themes/core/aboutReader.css
modules/libpref/src/Preferences.cpp
modules/libpref/src/init/all.js
netwerk/base/public/nsNetUtil.h
netwerk/cache/nsCacheEntry.cpp
netwerk/cache/nsCacheEntry.h
netwerk/cache/nsCacheRequest.h
netwerk/cache/nsCacheService.cpp
netwerk/cache/nsCacheService.h
netwerk/cache/nsDiskCacheDevice.cpp
netwerk/cache/nsDiskCacheMap.cpp
netwerk/protocol/http/SpdySession2.cpp
netwerk/protocol/http/SpdySession3.cpp
netwerk/protocol/http/SpdyStream3.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
testing/tps/tps/pulse.py
toolkit/components/downloads/nsDownloadManager.cpp
toolkit/components/intl/nsCharsetMenu.cpp
toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
toolkit/components/telemetry/TelemetryHistograms.h
toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
toolkit/mozapps/extensions/AddonRepository.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/installer/packager.mk
toolkit/webapps/WebappsInstaller.jsm
toolkit/xre/nsAppRunner.cpp
widget/nsGUIEvent.h
xpcom/idl-parser/xpidl.py
xpcom/reflect/xptcall/src/md/unix/Makefile.in
--- a/Makefile.in
+++ b/Makefile.in
@@ -76,17 +76,17 @@ DIST_GARBAGE = config.cache config.log c
    netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
    $(topsrcdir)/.mozconfig.mk $(topsrcdir)/.mozconfig.out
 
 default alldep all:: $(topsrcdir)/configure config.status
 	$(RM) -r $(DIST)/sdk
 	$(RM) -r $(DIST)/include
 	$(RM) -r $(DIST)/private
 	$(RM) -r $(DIST)/public
-	$(RM) -r $(DIST)/bin/components
+	$(RM) $(DIST)/chrome.manifest
 	$(RM) -r _tests
 
 $(topsrcdir)/configure: $(topsrcdir)/configure.in
 	@echo "STOP!  configure.in has changed, and your configure is out of date."
 	@echo "Please rerun autoconf and re-configure your build directory."
 	@echo "To ignore this message, touch 'configure' in the source directory,"
 	@echo "but your build might not succeed."
 	@exit 1
--- a/b2g/chrome/content/forms.js
+++ b/b2g/chrome/content/forms.js
@@ -56,16 +56,17 @@ let FormAssistant = {
           submit: true,
           image: true
         };
     
         if (evt.target instanceof HTMLSelectElement) { 
           content.setTimeout(function showIMEForSelect() {
             sendAsyncMessage("Forms:Input", getJSON(evt.target));
           });
+          this.previousTarget = evt.target;
         } else if (evt.target instanceof HTMLOptionElement &&
                    evt.target.parentNode instanceof HTMLSelectElement) {
           content.setTimeout(function showIMEForSelect() {
             sendAsyncMessage("Forms:Input", getJSON(evt.target.parentNode));
           });
         } else if ((target instanceof HTMLInputElement && !ignore[target.type]) ||
                     target instanceof HTMLTextAreaElement) {
           this.isKeyboardOpened = this.tryShowIme(evt.target);
@@ -176,19 +177,31 @@ let FormAssistant = {
 FormAssistant.init();
 
 
 function getJSON(element) {
   let type = element.type || "";
 
   // FIXME/bug 344616 is input type="number"
   // Until then, let's return 'number' even if the platform returns 'text'
+  // Related to Bug 769352 - Implement <input type=date>
   let attributeType = element.getAttribute("type") || "";
-  if (attributeType && attributeType.toLowerCase() === "number")
-    type = "number";
+
+  if (attributeType) {
+    var typeLowerCase = attributeType.toLowerCase(); 
+    switch (typeLowerCase) {
+      case "number":
+      case "date":
+      case "time":
+      case "datetime":
+      case "datetime-local":
+        type = typeLowerCase;
+        break;
+    }
+  }
 
   return {
     "type": type.toLowerCase(),
     "choices": getListForElement(element)
   };
 }
 
 function getListForElement(element) {
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -49,17 +49,16 @@ function getContentWindow() {
 }
 
 // FIXME Bug 707625
 // Please don't add more permissions here.
 // XXX never grant 'content-camera' to non-gaia apps
 function addPermissions(urls) {
   let permissions = [
     'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'pin-app',
-    'websettings-read', 'websettings-readwrite',
     'content-camera', 'wifi-manage', 'desktop-notification',
     'geolocation', 'device-storage', 'alarms'
   ];
 
   urls.forEach(function(url) {
     url = url.trim();
     if (url) {
       let uri = Services.io.newURI(url, null, null);
--- a/browser/base/content/macBrowserOverlay.xul
+++ b/browser/base/content/macBrowserOverlay.xul
@@ -22,21 +22,25 @@
 
 # All JS files which are not content (only) dependent that browser.xul
 # wishes to include *must* go into the global-scripts.inc file
 # so that they can be shared by this overlay.
 #include global-scripts.inc
 
 <script type="application/javascript">
   function OpenBrowserWindowFromDockMenu() {
-    let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
-                      .getService(Ci.nsIMacDockSupport);
-    dockSupport.activateApplication(true);
+    let win = OpenBrowserWindow();
+    win.addEventListener("load", function listener() {
+      win.removeEventListener("load", listener);
+      let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
+        .getService(Ci.nsIMacDockSupport);
+      dockSupport.activateApplication(true);
+    });
 
-    return OpenBrowserWindow();
+    return win;
   }
 
   addEventListener("load",   function() { gBrowserInit.nonBrowserWindowStartup()  }, false);
   addEventListener("unload", function() { gBrowserInit.nonBrowserWindowShutdown() }, false);
 </script>
 
 # All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the 
 # browser-sets.inc file for sharing with hiddenWindow.xul.
--- a/browser/components/sessionstore/test/browser_595601-restore_hidden.js
+++ b/browser/components/sessionstore/test/browser_595601-restore_hidden.js
@@ -38,21 +38,26 @@ function test_loadTabs(restoreHiddenTabs
   newWindowWithState(state, function (win, needsRestore, isRestoring) {
     if (firstProgress) {
       firstProgress = false;
       is(isRestoring, 3, "restoring 3 tabs concurrently");
     } else {
       ok(isRestoring < 4, "restoring max. 3 tabs concurrently");
     }
 
-    if (win.gBrowser.tabs.length - needsRestore == expectedTabs) {
+    // We're explicity checking for (isRestoring == 1) here because the test
+    // progress listener is called before the session store one. So when we're
+    // called with one tab left to restore we know that the last tab has
+    // finished restoring and will soon be handled by the SS listener.
+    let tabsNeedingRestore = win.gBrowser.tabs.length - needsRestore;
+    if (isRestoring == 1 && tabsNeedingRestore == expectedTabs) {
       is(win.gBrowser.visibleTabs.length, 4, "only 4 visible tabs");
 
       TabsProgressListener.uninit();
-      callback();
+      executeSoon(callback);
     }
   });
 }
 
 let TabsProgressListener = {
   init: function (win) {
     this.window = win;
 
--- a/browser/installer/windows/Makefile.in
+++ b/browser/installer/windows/Makefile.in
@@ -53,16 +53,17 @@ PPL_LOCALE_ARGS = \
   --l10n-dir=$(LOCALE_MERGEDIR)/browser/installer \
   --l10n-dir=$(call EXPAND_LOCALE_SRCDIR,browser/locales)/installer \
   --l10n-dir=$(topsrcdir)/browser/locales/en-US/installer \
   $(NULL)
 else
 PPL_LOCALE_ARGS=$(call EXPAND_LOCALE_SRCDIR,browser/locales)/installer
 endif
 
+.DEFAULT_GOAL := installer
 installer::
 	$(MAKE) -C .. installer-stage
 	$(MAKE) $(CONFIG_DIR)/setup.exe
 
 # For building the uninstaller during the application build so it can be
 # included for mar file generation.
 uninstaller::
 	$(RM) -r $(CONFIG_DIR)
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -149,33 +149,34 @@ libs-%:
 	$(NSINSTALL) -D $(DIST)/install
 	@$(MAKE) -C ../../toolkit/locales libs-$* BOTH_MANIFESTS=1
 	@$(MAKE) -C ../../services/sync/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
 	@$(MAKE) -C ../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
 	@$(MAKE) -C ../../intl/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
 	@$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=$(PREF_DIR) BOTH_MANIFESTS=1
 	@$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
 
-
 repackage-win32-installer: WIN32_INSTALLER_OUT=$(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe
-repackage-win32-installer: $(call ESCAPE_SPACE,$(WIN32_INSTALLER_IN)) $(SUBMAKEFILES) libs-$(AB_CD)
+repackage-win32-installer: $(call ESCAPE_WILDCARD,$(WIN32_INSTALLER_IN)) $(SUBMAKEFILES) libs-$(AB_CD)
 	@echo "Repackaging $(WIN32_INSTALLER_IN) into $(WIN32_INSTALLER_OUT)."
 	$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY) export
 	$(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen l10ngen/setup.exe l10ngen/7zSD.sfx
 	$(MAKE) repackage-zip \
 	  AB_CD=$(AB_CD) \
 	  MOZ_PKG_FORMAT=SFX7Z \
 	  ZIP_IN="$(WIN32_INSTALLER_IN)" \
 	  ZIP_OUT="$(WIN32_INSTALLER_OUT)" \
 	  SFX_HEADER="$(PWD)/../installer/windows/l10ngen/7zSD.sfx \
 	              $(topsrcdir)/browser/installer/windows/app.tag"
 
 ifeq (WINNT,$(OS_ARCH))
-repackage-win32-installer-%:
+repackage-win32-installer-%: $(STAGEDIST)
 	@$(MAKE) repackage-win32-installer AB_CD=$* WIN32_INSTALLER_IN="$(WIN32_INSTALLER_IN)"
+
+repackage-zip-%: repackage-win32-installer-%
 else
 repackage-win32-installer-%: ;
 endif
 
 
 clobber-zip:
 	$(RM) $(STAGEDIST)/chrome/$(AB_CD).jar \
 	  $(STAGEDIST)/chrome/$(AB_CD).manifest \
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -31,17 +31,17 @@ TEST_DIRS += mobile/sutagent/android \
           mobile/sutagent/android/watcher \
           mobile/sutagent/android/ffxcp \
           mobile/sutagent/android/fencp \
           mobile/robocop \
           $(NULL)
 endif
 
 ifdef MOZ_APP_BASENAME
-DIST_FILES = application.ini
+DIST_FILES = $(srcdir)/application.ini
 
 ifneq (android,$(MOZ_WIDGET_TOOLKIT))
 ifdef MOZ_UPDATER
 DIST_FILES += update-settings.ini
 endif
 endif
 
 ifdef LIBXUL_SDK
@@ -127,22 +127,20 @@ GARBAGE_DIRS += $(_LEAKTEST_DIR)
 		$(NULL)
 
 leaktest.py: leaktest.py.in
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $^ > $@
 	chmod +x $@
 GARBAGE += leaktest.py
 
 ifdef MOZ_APP_BASENAME
-application.ini: application.ini.in $(APP_INI_DEPS)
-	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $< > $@
-GARBAGE += application.ini
+$(FINAL_TARGET)/application.ini: $(APP_INI_DEPS)
 
 ifdef MOZ_APP_STATIC_INI
-application.ini.h: appini_header.py application.ini 
+application.ini.h: appini_header.py $(FINAL_TARGET)/application.ini
 	$(PYTHON) $^ > $@
 export:: application.ini.h
 GARBAGE += application.ini.h
 endif
 endif
 
 libs:: $(_LEAKTEST_FILES)
 	$(INSTALL) $^ $(_LEAKTEST_DIR)
rename from build/application.ini.in
rename to build/application.ini
--- a/build/macosx/universal/flight.mk
+++ b/build/macosx/universal/flight.mk
@@ -91,13 +91,14 @@ ifdef ENABLE_TESTS
 # dist/bin. It doesn't matter which one we use.
 	if test -d $(DIST_ARCH_1)/test-package-stage -a                 \
                 -d $(DIST_ARCH_2)/test-package-stage; then              \
            cp $(DIST_ARCH_1)/test-package-stage/mochitest/automation.py \
              $(DIST_ARCH_2)/test-package-stage/mochitest/;              \
            cp $(DIST_ARCH_1)/test-package-stage/reftest/automation.py   \
              $(DIST_ARCH_2)/test-package-stage/reftest/;                \
            $(TOPSRCDIR)/build/macosx/universal/unify                 \
+             --unify-with-sort "\.manifest$$" \
              --unify-with-sort "all-test-dirs\.list$$"               \
              $(DIST_ARCH_1)/test-package-stage                          \
              $(DIST_ARCH_2)/test-package-stage                          \
              $(DIST_UNI)/test-package-stage; fi
 endif
--- a/build/mobile/devicemanager.py
+++ b/build/mobile/devicemanager.py
@@ -433,17 +433,17 @@ class DeviceManager:
   def getInfo(self, directive=None):
     """
     Returns information about the device:
     Directive indicates the information you want to get, your choices are:
     os - name of the os
     id - unique id of the device
     uptime - uptime of the device
     uptimemillis - uptime of the device in milliseconds (NOT supported on all
-                   platforms)
+                   implementations)
     systime - system time of the device
     screen - screen resolution
     memory - memory stats
     process - list of running processes (same as ps)
     disk - total, free, available bytes on disk
     power - power status (charge, battery temp)
     all - all of them - or call it with no parameters to get all the information
     returns:
--- a/build/mobile/devicemanagerSUT.py
+++ b/build/mobile/devicemanagerSUT.py
@@ -502,26 +502,21 @@ class DeviceManagerSUT(DeviceManager):
       if (failIfRunning):
         return None
 
     try:
       data = self.runCmds([{ 'cmd': 'exec ' + appname }])
     except AgentError:
       return None
 
-    # wait up to 30 seconds for process to start up
-    timeslept = 0
-    while (timeslept <= 30):
-      process = self.processExist(appname)
-      if (process is not None):
-        break
-      time.sleep(3)
-      timeslept += 3
+    # The 'exec' command may wait for the process to start and end, so checking
+    # for the process here may result in process = None.
+    process = self.processExist(appname)
+    if (self.debug >= 4): print "got pid: %s for process: %s" % (process, appname)
 
-    if (self.debug >= 4): print "got pid: %s for process: %s" % (process, appname)
     return process
 
   # external function
   # DEPRECATED: Use shell() or launchApplication() for new code
   # returns:
   #  success: output filename
   #  failure: None
   def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
@@ -913,17 +908,17 @@ class DeviceManagerSUT(DeviceManager):
     if (self.debug > 3): print "INFO: rebt- got status back: " + str(status)
     return status
 
   # Returns information about the device:
   # Directive indicates the information you want to get, your choices are:
   # os - name of the os
   # id - unique id of the device
   # uptime - uptime of the device
-  # uptimemillis - uptime of the device in milliseconds
+  # uptimemillis - uptime of the device in milliseconds (SUTAgent 1.11+)
   # systime - system time of the device
   # screen - screen resolution
   # rotation - rotation of the device (in degrees)
   # memory - memory stats
   # process - list of running processes (same as ps)
   # disk - total, free, available bytes on disk
   # power - power status (charge, battery temp)
   # all - all of them - or call it with no parameters to get all the information
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -148,17 +148,18 @@ class RemoteAutomation(Automation):
                   # no "tests" component -- maybe this isn't robocop?
                   i = -1
                 if (i > 0):
                   self.procName = '.'.join(parts[0:i])
                   print "Robocop derived process name: "+self.procName
 
             # Setting timeout at 1 hour since on a remote device this takes much longer
             self.timeout = 3600
-            time.sleep(15)
+            # The benefit of the following sleep is unclear; it was formerly 15 seconds
+            time.sleep(1)
 
         @property
         def pid(self):
             hexpid = self.dm.processExist(self.procName)
             if (hexpid == None):
                 hexpid = "0x0"
             return int(hexpid, 0)
     
--- a/build/mobile/robocop/FennecNativeActions.java.in
+++ b/build/mobile/robocop/FennecNativeActions.java.in
@@ -54,17 +54,17 @@ public class FennecNativeActions impleme
     public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation, Assert asserter) {
         mSolo = robocop;
         mInstr = instrumentation;
         mGeckoApp = activity;
         mAsserter = asserter;
         // Set up reflexive access of java classes and methods.
         try {
             mClassLoader = activity.getClassLoader();
-            mGel = mClassLoader.loadClass("org.mozilla.gecko.GeckoEventListener");
+            mGel = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
             mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent");
             mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
             Class [] parameters = new Class[2];
             parameters[0] = String.class;
             parameters[1] = mGel;
             mRegisterGEL = mGas.getMethod("registerGeckoEventListener", parameters);
             mUnregisterGEL = mGas.getMethod("unregisterGeckoEventListener", parameters);
             parameters = new Class[1];
--- a/build/mobile/robocop/FennecNativeDriver.java.in
+++ b/build/mobile/robocop/FennecNativeDriver.java.in
@@ -83,17 +83,17 @@ public class FennecNativeDriver implemen
         mSolo = robocop;
 
         // Set up table of fennec_ids.
         mLocators = convertTextToTable(getFile("/mnt/sdcard/fennec_ids.txt"));
 
         // Set up reflexive access of java classes and methods.
         try {
             mClassLoader = activity.getClassLoader();
-            mGel = mClassLoader.loadClass("org.mozilla.gecko.GeckoEventListener");
+            mGel = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener");
             mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent");
             mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
             Class [] parameters = new Class[2];
             parameters[0] = String.class;
             parameters[1] = mGel;
             mRegisterGEL = mGas.getMethod("registerGeckoEventListener", parameters);
             mUnregisterGEL = mGas.getMethod("unregisterGeckoEventListener", parameters);
             parameters = new Class[1];
--- a/build/pymake/pymake/data.py
+++ b/build/pymake/pymake/data.py
@@ -1381,17 +1381,17 @@ class _CommandWrapper(object):
         process.call(self.cline, loc=self.loc, cb=self._cb, context=self.context, **self.kwargs)
 
 class _NativeWrapper(_CommandWrapper):
     def __init__(self, cline, ignoreErrors, loc, context,
                  pycommandpath, **kwargs):
         _CommandWrapper.__init__(self, cline, ignoreErrors, loc, context,
                                  **kwargs)
         # get the module and method to call
-        parts, badchar = process.clinetoargv(cline)
+        parts, badchar = process.clinetoargv(cline, blacklist_gray=False)
         if parts is None:
             raise DataError("native command '%s': shell metacharacter '%s' in command line" % (cline, badchar), self.loc)
         if len(parts) < 2:
             raise DataError("native command '%s': no method name specified" % cline, self.loc)
         if pycommandpath:
             self.pycommandpath = re.split('[%s\s]+' % os.pathsep,
                                           pycommandpath)
         else:
--- a/build/pymake/pymake/process.py
+++ b/build/pymake/pymake/process.py
@@ -10,29 +10,39 @@ import subprocess, shlex, re, logging, s
 subprocess._cleanup = lambda: None
 import command, util
 if sys.platform=='win32':
     import win32process
 
 _log = logging.getLogger('pymake.process')
 
 _escapednewlines = re.compile(r'\\\n')
-_blacklist = re.compile(r'[$><;[~`|&()]' +
+# Characters that most likely indicate a shell script and that native commands
+# should reject
+_blacklist = re.compile(r'[$><;\[~`|&]' +
     r'|\${|(?:^|\s){(?:$|\s)')  # Blacklist ${foo} and { commands }
+# Characters that probably indicate a shell script, but that native commands
+# shouldn't just reject
+_graylist = re.compile(r'[()]')
+# Characters that indicate we need to glob
 _needsglob = re.compile(r'[\*\?]')
-def clinetoargv(cline):
+
+def clinetoargv(cline, blacklist_gray):
     """
     If this command line can safely skip the shell, return an argv array.
     @returns argv, badchar
     """
-
     str = _escapednewlines.sub('', cline)
     m = _blacklist.search(str)
     if m is not None:
         return None, m.group(0)
+    if blacklist_gray:
+        m = _graylist.search(str)
+        if m is not None:
+            return None, m.group(0)
 
     args = shlex.split(str, comments=True)
 
     if len(args) and args[0].find('=') != -1:
         return None, '='
 
     return args, None
 
@@ -60,17 +70,17 @@ shellwords = (':', '.', 'break', 'cd', '
 def call(cline, env, cwd, loc, cb, context, echo, justprint=False):
     #TODO: call this once up-front somewhere and save the result?
     shell, msys = util.checkmsyscompat()
 
     shellreason = None
     if msys and cline.startswith('/'):
         shellreason = "command starts with /"
     else:
-        argv, badchar = clinetoargv(cline)
+        argv, badchar = clinetoargv(cline, blacklist_gray=True)
         if argv is None:
             shellreason = "command contains shell-special character '%s'" % (badchar,)
         elif len(argv) and argv[0] in shellwords:
             shellreason = "command starts with shell primitive '%s'" % (argv[0],)
         else:
             argv = doglobbing(argv, cwd)
 
     if shellreason is not None:
--- a/build/pymake/tests/native-simple.mk
+++ b/build/pymake/tests/native-simple.mk
@@ -1,11 +1,12 @@
 ifndef TOUCH
 TOUCH = touch
 endif
 
-all: testfile {testfile2}
+all: testfile {testfile2} (testfile3)
 	test -f testfile
 	test -f {testfile2}
+	test -f "(testfile3)"
 	@echo TEST-PASS
 
-testfile {testfile2}:
-	$(TOUCH) $@
+testfile {testfile2} (testfile3):
+	$(TOUCH) "$@"
--- a/caps/src/nsSecurityManagerFactory.cpp
+++ b/caps/src/nsSecurityManagerFactory.cpp
@@ -102,18 +102,18 @@ netscape_security_enablePrivilege(JSCont
     rv = securityManager->EnableCapability(cap.ptr());
     if (NS_FAILED(rv))
         return JS_FALSE;
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSFunctionSpec PrivilegeManager_static_methods[] = {
-    { "enablePrivilege",    netscape_security_enablePrivilege,      1,0},
-    {nullptr,nullptr,0,0}
+    JS_FS("enablePrivilege", netscape_security_enablePrivilege, 1, 0),
+    JS_FS_END
 };
 
 /*
  * "Steal" calls to netscape.security.PrivilegeManager.enablePrivilege,
  * et al. so that code that worked with 4.0 can still work.
  */
 NS_IMETHODIMP 
 nsSecurityNameSet::InitializeNameSet(nsIScriptContext* aScriptContext)
--- a/config/config.mk
+++ b/config/config.mk
@@ -115,16 +115,27 @@ OS_CONFIG	:= $(OS_ARCH)$(OS_RELEASE)
 
 FINAL_LINK_LIBS = $(DEPTH)/config/final-link-libs
 FINAL_LINK_COMPS = $(DEPTH)/config/final-link-comps
 FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names
 
 MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
 MOZ_WIDGET_SUPPORT_LIBS    = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
 
+ifdef _MSC_VER
+ifdef .PYMAKE
+PYCOMMANDPATH += $(topsrcdir)/build
+CC_WRAPPER ?= %cl InvokeClWithDependencyGeneration
+CXX_WRAPPER ?= %cl InvokeClWithDependencyGeneration
+else
+CC_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
+CXX_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
+endif # .PYMAKE
+endif # _MSC_VER
+
 CC := $(CC_WRAPPER) $(CC)
 CXX := $(CXX_WRAPPER) $(CXX)
 MKDIR ?= mkdir
 SLEEP ?= sleep
 TOUCH ?= touch
 
 ifdef .PYMAKE
 PYCOMMANDPATH += $(topsrcdir)/config
@@ -557,30 +568,29 @@ PBBUILD_SETTINGS = GCC_VERSION="$(GCC_VE
 ifdef MACOS_SDK_DIR
 PBBUILD_SETTINGS += SDKROOT="$(MACOS_SDK_DIR)"
 endif # MACOS_SDK_DIR
 ifdef MACOSX_DEPLOYMENT_TARGET
 export MACOSX_DEPLOYMENT_TARGET
 PBBUILD_SETTINGS += MACOSX_DEPLOYMENT_TARGET="$(MACOSX_DEPLOYMENT_TARGET)"
 endif # MACOSX_DEPLOYMENT_TARGET
 
-ifdef MOZ_USING_CCACHE
-ifdef CLANG_CXX
-export CCACHE_CPP2=1
-endif
-endif
-
 ifdef MOZ_OPTIMIZE
 ifeq (2,$(MOZ_OPTIMIZE))
 # Only override project defaults if the config specified explicit settings
 PBBUILD_SETTINGS += GCC_MODEL_TUNING= OPTIMIZATION_CFLAGS="$(MOZ_OPTIMIZE_FLAGS)"
 endif # MOZ_OPTIMIZE=2
 endif # MOZ_OPTIMIZE
 endif # OS_ARCH=Darwin
 
+ifdef MOZ_USING_CCACHE
+ifdef CLANG_CXX
+export CCACHE_CPP2=1
+endif
+endif
 
 ifdef MOZ_NATIVE_MAKEDEPEND
 MKDEPEND_DIR =
 MKDEPEND = $(MOZ_NATIVE_MAKEDEPEND)
 else
 MKDEPEND_DIR = $(CONFIG_TOOLS)/mkdepend
 MKDEPEND = $(MKDEPEND_DIR)/mkdepend$(BIN_SUFFIX)
 endif
--- a/config/makefiles/test/Makefile.in
+++ b/config/makefiles/test/Makefile.in
@@ -123,16 +123,17 @@ checkup: $(eval include $(srcdir)/check-
 $(check-export-targets): $(check-export-targets-preqs)
 	@$(TOUCH) $@
 # </CHECK: export-targets.mk>
 
 ###########################################################################
 ##{ <CHECK: xpidl.mk>
 check-xpidl-preqs=\
   $(call mkdir_deps,$(dir-ts)) \
+  $(topsrcdir)/config/config.mk \
   $(topsrcdir)/config/makefiles/makeutils.mk \
   $(topsrcdir)/config/makefiles/xpidl.mk \
   $(srcdir)/check-xpidl.mk \
   $(NULL)
 
 check-xpidl-args =\
   "topsrcdir=$(topsrcdir)" \
   "srcdir=$(srcdir)" \
--- a/config/makefiles/test/check-xpidl.mk
+++ b/config/makefiles/test/check-xpidl.mk
@@ -3,29 +3,34 @@
 # 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/.
 
 ifdef VERBOSE
   $(warning loading test)
 endif
 
+# Limit scope, we only need install_cmd= for testing
+INCLUDED_AUTOCONF_MK = 1
+include $(topsrcdir)/config/config.mk
+
 USE_AUTOTARGETS_MK = 1
 include $(topsrcdir)/config/makefiles/makeutils.mk
 
 basedir  = blah
 DIST     = $(basedir)/dist
 DI       = $(DIST)/include
 IDL_DIR  = $(basedir)/idl
 INSTALL := cp
 
 XPIDLSRCS = $(srcdir)/check-xpidl.mk
 
 include $(topsrcdir)/config/makefiles/xpidl.mk
 
+
 $(call requiredfunction,topsrcdir)
 $(call requiredfunction,XPIDL_GEN_DIR)
 
 HIDE=@
 check-xpidl: xpidl-install-src xpidl-install-headers
 	$(HIDE)test -d $(DIST)                   || exit 90
 	$(HIDE)test -f $(DI)/check-xpidl.mk      || exit 91
 	$(HIDE)test -f $(IDL_DIR)/check-xpidl.mk || exit 92
--- a/config/makefiles/xpidl.mk
+++ b/config/makefiles/xpidl.mk
@@ -34,16 +34,18 @@ ifndef INCLUDED_XPIDL_MK #{
 endif #} INCLUDED_XPIDL_MK
 
 
 ###########################################################################
 ## processing targets
 ###########################################################################
 ifdef _xpidl-todo_ #{
 
+$(call requiredfunction,install_cmd)
+
 ## Logic batch #1
 xpidl-install-src-preqs=\
   $(XPIDLSRCS) \
   $(call mkdir_deps,$(IDL_DIR)) \
   $(NULL)
 
 xpidl-install-src: $(xpidl-install-src-preqs)
 	$(call install_cmd,$(IFLAGS1) $(foreach val,$^,$(call mkdir_stem,$(val))))
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1769,16 +1769,17 @@ CHECK_FROZEN_VARIABLES = $(foreach var,$
   $(if $(subst $($(var)_FROZEN),,'$($(var))'),$(error Makefile variable '$(var)' changed value after including rules.mk. Was $($(var)_FROZEN), now $($(var)).)))
 
 libs export::
 	$(CHECK_FROZEN_VARIABLES)
 
 default all::
 	if test -d $(DIST)/bin ; then touch $(DIST)/bin/.purgecaches ; fi
 
+.DEFAULT_GOAL ?= default
 
 #############################################################################
 # Derived targets and dependencies
 
 include $(topsrcdir)/config/makefiles/autotargets.mk
 ifneq ($(NULL),$(AUTO_DEPS))
   default all libs tools export:: $(AUTO_DEPS)
 endif
--- a/config/system-headers
+++ b/config/system-headers
@@ -590,16 +590,17 @@ Processes.h
 process.h
 Process.h
 proto/dos.h
 proto/exec.h
 psap.h
 Pt.h
 pthread.h
 pthread_np.h
+pulse/pulseaudio.h
 pwd.h
 Python.h
 QDOffscreen.h
 queue
 Quickdraw.h
 QuickDraw.h
 QuickTimeComponents.h
 quipu/attr.h
--- a/config/tests/makefiles/autodeps/Makefile.in
+++ b/config/tests/makefiles/autodeps/Makefile.in
@@ -22,20 +22,22 @@ include $(topsrcdir)/config/rules.mk
 
 autotgt_tests = .deps/autotargets.mk.ts
 
 tgts =\
   .deps/.mkdir.done\
   $(autotgt_tests)
   $(NULL)
 
+export MAKE
+export .PYMAKE
 
 ##------------------_##
 ##---]  TARGETS  [---##
 ##------------------_##
 all::
 
 check:: $(tgts)
 
 # Only run unit test when autotargets.mk is modified
 $(autotgt_tests): $(topsrcdir)/config/makefiles/autotargets.mk
-	MAKECMD=$(MAKE) $(PYTEST) $(srcdir)/check_mkdir.tpy
+	$(PYTEST) $(srcdir)/check_mkdir.tpy
 	@$(TOUCH) $@
--- a/config/tests/makefiles/autodeps/check_mkdir.tpy
+++ b/config/tests/makefiles/autodeps/check_mkdir.tpy
@@ -63,17 +63,17 @@ def path2posix(src):
     move to {build,config,tools,toolkit}/python for use in a library
     """
 
     ## (drive, tail) = os.path.splitdrive(src)
     ## Support path testing on all platforms
     drive = ''
     winpath = src.find(':')
     if -1 != winpath and 10 > winpath:
-        (drive, tail) = src.split(':', 2)
+        (drive, tail) = src.split(':', 1)
 
     if drive:
         todo = [ '', drive.rstrip(':').lstrip('/').lstrip('\\') ]
         todo.extend( tail.lstrip('/').lstrip('\\').split('\\') ) # c:\a => [a]
     else: # os.name == 'posix'
         todo = src.split('\\')
 
     dst = '/'.join(todo)
@@ -93,81 +93,79 @@ def checkMkdir(work, debug=False):
     Note:
     Exception() rather than self.assertTrue() is used in this test
     function to enable scatch cleanup on test exit/failure conditions.
     Not guaranteed by python closures on early exit.
     """
 
     logging.debug("Testing: checkMkdir")
 
-    if False:
-        path = os.path.abspath(__file__).split(os.sep)
+    # On Windows + Pymake, don't convert paths to POSIX
+    skipposix = sys.platform == "win32" and os.environ.get(".PYMAKE") == "1"
+    if skipposix:
+        path = os.path.abspath(__file__)
+        dirname_fun = os.path.dirname
     else:
-        path = path2posix(os.path.abspath(__file__)).split('/')
-        
-    root = os.path.join(os.sep, *path[:-5])
-    src = os.path.join(os.sep, *path[:-1])
+        path = path2posix(os.path.abspath(__file__))
+        import posixpath
+        dirname_fun = posixpath.dirname
+
+    src = dirname_fun(path)
+    # root is 5 directories up from path
+    root = reduce(lambda x, _: dirname_fun(x), xrange(5), path)
 
     rootP = path2posix(root)
     srcP  = path2posix(src)
     workP = path2posix(work)
 
     # C:\foo -vs- /c/foo
     # [0] command paths use /c/foo
     # [1] os.path.exists() on mingw() requires C:\
     paths = [
-        [ # function generated
-            "%s/mkdir_bycall" % (workP),
-            "%s/mkdir_bycall" % (work),
-        ],
-        [ # explicit dependency
-            "%s/mkdir_bydep"  % (workP),
-            "%s/mkdir_bydep"  % (work),
-        ],
-        [ # by GENERATED_DIRS macro
-            "%s/mkdir_bygen"  % (workP),
-            "%s/mkdir_bygen"  % (work),
-        ]
-        ]
+        "mkdir_bycall", # function generated
+        "mkdir_bydep",  # explicit dependency
+        "mkdir_bygen",  # by GENERATED_DIRS macro
+    ]
 
     ## Use make from the parent "make check" call when available
     cmd = { 'make': 'make' }
-    shell0 = os.environ.get('MAKECMD')
+    shell0 = os.environ.get('MAKE')
     if shell0:
         shell = os.path.splitext(shell0)[0] # strip: .exe, .py
         if -1 != shell.find('make'):
             print "MAKE COMMAND FOUND: %s" % (shell0)
-            cmd['make'] = path2posix(shell0)
+            cmd['make'] = shell0 if skipposix else path2posix(shell0)
 
     args = []
     args.append('%s' % (cmd['make']))
-    args.append('-C %s'                % (workP))
-    args.append("-f %s/testor.tmpl"    % (srcP))
-    args.append('topsrcdir=%s'         % (rootP))
-    args.append('deps_mkdir_bycall=%s' % paths[0][0])
-    args.append('deps_mkdir_bydep=%s'  % paths[1][0])
-    args.append('deps_mkdir_bygen=%s'  % paths[2][0])
+    args.append('-C %s'                % (work if skipposix else workP))
+    args.append("-f %s/testor.tmpl"    % (src if skipposix else srcP))
+    args.append('topsrcdir=%s'         % (root if skipposix else rootP))
+    args.append('deps_mkdir_bycall=%s' % paths[0])
+    args.append('deps_mkdir_bydep=%s'  % paths[1])
+    args.append('deps_mkdir_bygen=%s'  % paths[2])
     args.append('checkup') # target
 
     # Call will fail on mingw with output redirected ?!?
     if debug:
         pass
     if False: # if not debug:
         args.append('>/dev/null')
 
     cmd = '%s' % (' '.join(args))
     logging.debug("Running: %s" % (cmd))
     rc = call(cmd, shell=True)
     if rc:
         raise Exception("make failed ($?=%s): cmd=%s" % (rc, cmd))
 
     for i in paths:
-        logging.debug("Did testing mkdir(%s) succeed?" % (i[1]))
-        if not os.path.exists(i[1]):
-            raise Exception("Test path %s does not exist" % (i[1]))
+        path = os.path.join(work, i)
+        logging.debug("Did testing mkdir(%s) succeed?" % (path))
+        if not os.path.exists(path):
+            raise Exception("Test path %s does not exist" % (path))
 
 
 def parseargs():
     """
     Support additional command line arguments for testing
     
     Returns:
     hash - arguments of interested parsed from the command line
--- a/configure.in
+++ b/configure.in
@@ -189,17 +189,17 @@ if test -n "$gonkdir" ; then
         ;;
     i?86)
         ARCH_DIR=arch-x86
         ;;
     esac
 
     CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/frameworks/base/include -I$gonkdir/external/dbus $CPPFLAGS -I$gonkdir/frameworks/base/services/sensorservice -I$gonkdir/frameworks/base/services/camera"
     CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
-    CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS $STLPORT_CPPFLAGS"
+    CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS $STLPORT_CPPFLAGS"
     dnl Add -llog by default, since we use it all over the place.
     LIBS="$LIBS -llog $STLPORT_LIBS"
 
     LDFLAGS="-mandroid -L$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib -Wl,-rpath-link=$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib --sysroot=$gonkdir/out/target/product/$GONK_PRODUCT/obj/ $LDFLAGS"
 
     dnl prevent cross compile section from using these flags as host flags
     if test -z "$HOST_CPPFLAGS" ; then
         HOST_CPPFLAGS=" "
@@ -4145,16 +4145,17 @@ MOZ_JSDEBUGGER=1
 MOZ_AUTH_EXTENSION=1
 MOZ_OGG=1
 MOZ_RAW=
 MOZ_SYDNEYAUDIO=
 MOZ_SPEEX_RESAMPLER=1
 MOZ_CUBEB=
 MOZ_VORBIS=
 MOZ_TREMOR=
+MOZ_FLOATING_POINT_AUDIO=
 MOZ_WAVE=1
 MOZ_MEDIA=
 MOZ_OPUS=1
 MOZ_WEBM=1
 MOZ_WEBRTC=1
 MOZ_WEBRTC_SIGNALING=
 MOZ_MEDIA_PLUGINS=
 MOZ_MEDIA_NAVIGATOR=
@@ -5195,16 +5196,34 @@ if test -n "$MOZ_WEBRTC"; then
     MOZ_VP8=1
     MOZ_VP8_ENCODER=1
     MOZ_VP8_ERROR_CONCEALMENT=1
 fi
 
 AC_SUBST(MOZ_WEBRTC)
 
 dnl ========================================================
+dnl = Disable floating point audio.
+dnl ========================================================
+MOZ_ARG_DISABLE_BOOL(floating-point,
+[ --disable-floating-point     Disable floating point audio],
+    MOZ_FLOATING_POINT_AUDIO=,
+    MOZ_FLOATING_POINT_AUDIO=1)
+
+
+case "$target_cpu" in
+arm*)
+;;
+*)
+    AC_DEFINE(MOZ_FLOATING_POINT_AUDIO)
+    MOZ_FLOATING_POINT_AUDIO=1
+;;
+esac
+
+dnl ========================================================
 dnl = Enable Raw Codecs
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(raw,
 [  --enable-raw           Enable support for RAW media],
     MOZ_RAW=1,
     MOZ_RAW=)
 
 if test -n "$MOZ_RAW"; then
@@ -5222,24 +5241,16 @@ MOZ_ARG_DISABLE_BOOL(ogg,
     MOZ_OGG=,
     MOZ_OGG=1)
 
 if test -n "$MOZ_OGG"; then
     AC_DEFINE(MOZ_OGG)
     MOZ_SYDNEYAUDIO=1
     MOZ_CUBEB=1
     MOZ_MEDIA=1
-    case "$target_cpu" in
-    arm*)
-        MOZ_TREMOR=1
-    ;;
-    *)
-        MOZ_VORBIS=1
-    ;;
-    esac
 
     dnl Checks for __attribute__(aligned()) directive
     AC_CACHE_CHECK([__attribute__ ((aligned ())) support],
         [ac_cv_c_attribute_aligned],
         [ac_cv_c_attribute_aligned=0
          CFLAGS_save="${CFLAGS}"
          CFLAGS="${CFLAGS} -Werror"
          for ac_cv_c_attr_align_try in 64 32 16 8; do
@@ -5359,24 +5370,21 @@ fi
 AC_SUBST(MOZ_NATIVE_LIBVPX)
 AC_SUBST(MOZ_LIBVPX_CFLAGS)
 AC_SUBST(MOZ_LIBVPX_LIBS)
 
 if test "$MOZ_WEBM"; then
     MOZ_SYDNEYAUDIO=1
     MOZ_CUBEB=1
     MOZ_MEDIA=1
-    case "$target_cpu" in
-    arm*)
+    if test -n "$MOZ_FLOATING_POINT_AUDIO"; then
+        MOZ_VORBIS=1
+    else
         MOZ_TREMOR=1
-    ;;
-    *)
-        MOZ_VORBIS=1
-    ;;
-    esac
+    fi
 fi
 
 if test -n "$MOZ_VP8" -a -z "$MOZ_NATIVE_LIBVPX"; then
 
     dnl Detect if we can use an assembler to compile optimized assembly for libvpx.
     dnl We currently require yasm on all x86 platforms and require yasm 1.1.0 on Win32.
     dnl We currently require gcc on all arm platforms.
     VPX_AS=$YASM
@@ -5546,16 +5554,36 @@ dnl ====================================
 dnl If using sydneyaudio with Linux, ensure that the alsa library is available
 if test -n "$MOZ_SYDNEYAUDIO" -a "$OS_TARGET" = "Linux"; then
     PKG_CHECK_MODULES(MOZ_ALSA, alsa, ,
          [echo "$MOZ_ALSA_PKG_ERRORS"
           AC_MSG_ERROR([Need alsa for Ogg, Wave or WebM decoding on Linux.  Disable with --disable-ogg --disable-wave --disable-webm.  (On Ubuntu, you might try installing the package libasound2-dev.)])])
 fi
 
 dnl ========================================================
+dnl = Enable PulseAudio
+dnl ========================================================
+
+MOZ_ARG_ENABLE_BOOL(pulseaudio,
+[  --enable-pulseaudio          Enable PulseAudio support (experimental)],
+MOZ_PULSEAUDIO=1,
+MOZ_PULSEAUDIO=)
+
+if test -n "$MOZ_PULSEAUDIO"; then
+    AC_DEFINE(MOZ_CUBEB)
+    PKG_CHECK_MODULES(MOZ_PULSEAUDIO, libpulse, ,
+         [echo "$MOZ_PULSEAUDIO_PKG_ERRORS"
+          AC_MSG_ERROR([pulseaudio audio backend requires libpulse package])])
+fi
+
+AC_SUBST(MOZ_PULSEAUDIO)
+AC_SUBST(MOZ_PULSEAUDIO_CFLAGS)
+AC_SUBST(MOZ_PULSEAUDIO_LIBS)
+
+dnl ========================================================
 dnl = Enable GStreamer
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(gstreamer,
 [  --enable-gstreamer           Enable GStreamer support],
 MOZ_GSTREAMER=1,
 MOZ_GSTREAMER=)
 
 if test "$MOZ_GSTREAMER"; then
@@ -7685,30 +7713,24 @@ else
     changequote(,)
     CL_INCLUDES_PREFIX=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/^\([^:]*:[^:]*:\).*stdio.h$/\1/p'`
     changequote([,])
     if test -z "$CL_INCLUDES_PREFIX"; then
         AC_MSG_ERROR([Cannot find cl -showIncludes prefix.])
     fi
     AC_SUBST(CL_INCLUDES_PREFIX)
     rm -f dummy-hello.c
-    dnl cl.py provides dependency generation for MSVC
-    CC_WRAPPER='$(PYTHON) -O $(topsrcdir)/build/cl.py'
-    CXX_WRAPPER='$(PYTHON) -O $(topsrcdir)/build/cl.py'
     COMPILER_DEPEND=1
   fi
 fi
 fi # MOZ_AUTO_DEPS
 MDDEPDIR='.deps'
 AC_SUBST(MOZ_AUTO_DEPS)
 AC_SUBST(COMPILER_DEPEND)
 AC_SUBST(MDDEPDIR)
-AC_SUBST(CC_WRAPPER)
-AC_SUBST(CXX_WRAPPER)
-
 
 dnl ========================================================
 dnl =
 dnl = Static Build Options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Static build options)
 
new file mode 100644
--- /dev/null
+++ b/content/base/public/DirectionalityUtils.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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/. */
+
+#ifndef DirectionalityUtils_h___
+#define DirectionalityUtils_h___
+
+class nsIContent;
+class nsIDocument;
+class nsINode;
+
+namespace mozilla {
+namespace dom {
+class Element;
+} // namespace dom
+} // namespace mozilla
+
+namespace mozilla {
+
+namespace directionality {
+
+enum Directionality {
+  eDir_NotSet = 0,
+  eDir_RTL    = 1,
+  eDir_LTR    = 2
+};
+
+void SetDirectionality(mozilla::dom::Element* aElement, Directionality aDir,
+                       bool aNotify = true);
+
+/**
+ * Set the directionality of an element according to the algorithm defined at
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality,
+ * not including elements with auto direction.
+ *
+ * @return the directionality that the element was set to
+ */
+Directionality RecomputeDirectionality(mozilla::dom::Element* aElement,
+                                       bool aNotify = true);
+
+/**
+ * Set the directionality of any descendants of a node that do not themselves
+ * have a dir attribute.
+ * For performance reasons we walk down the descendant tree in the rare case
+ * of setting the dir attribute, rather than walking up the ancestor tree in
+ * the much more common case of getting the element's directionality.
+ */
+void SetDirectionalityOnDescendants(mozilla::dom::Element* aElement, 
+                                    Directionality aDir,
+                                    bool aNotify = true);
+
+} // end namespace directionality
+
+} // end namespace mozilla
+
+#endif /* DirectionalityUtils_h___ */
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Element_h__
 #define mozilla_dom_Element_h__
 
 #include "mozilla/dom/FragmentOrElement.h" // for base class
 #include "nsChangeHint.h"                  // for enum
 #include "nsEventStates.h"                 // for member
+#include "mozilla/dom/DirectionalityUtils.h"
 
 class nsEventStateManager;
 class nsFocusManager;
 class nsGlobalWindow;
 class nsICSSDeclaration;
 class nsISMILAttr;
 
 // Element-specific flags
@@ -211,16 +212,28 @@ public:
 
   /**
    * Returns an atom holding the name of the "class" attribute on this
    * content node (if applicable).  Returns null if there is no
    * "class" attribute for this type of content node.
    */
   virtual nsIAtom *GetClassAttributeName() const = 0;
 
+  inline mozilla::directionality::Directionality GetDirectionality() const {
+    if (HasFlag(NODE_HAS_DIRECTION_RTL)) {
+      return mozilla::directionality::eDir_RTL;
+    }
+
+    if (HasFlag(NODE_HAS_DIRECTION_LTR)) {
+      return mozilla::directionality::eDir_LTR;
+    }
+
+    return mozilla::directionality::eDir_NotSet;
+  }
+
 protected:
   /**
    * Method to get the _intrinsic_ content state of this element.  This is the
    * state that is independent of the element's presentation.  To get the full
    * content state, use State().  See nsEventStates.h for
    * the possible bits that could be set here.
    */
   virtual nsEventStates IntrinsicState() const;
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -43,16 +43,17 @@ nsReferencedElement.h \
 nsTreeSanitizer.h \
 nsXMLNameSpaceMap.h \
 nsIXFormsUtilityService.h \
 $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom mozilla
 
 EXPORTS_mozilla/dom = \
+		DirectionalityUtils.h \
 		Element.h \
 		FragmentOrElement.h \
 		FromParser.h \
 		$(NULL)
 
 EXPORTS_mozilla = \
 		CORSMode.h \
 		$(NULL)
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -18,16 +18,17 @@
 #include "nsILoadContext.h"              // for member (in nsCOMPtr)
 #include "nsILoadGroup.h"                // for member (in nsCOMPtr)
 #include "nsINode.h"                     // for base class
 #include "nsIScriptGlobalObject.h"       // for member (in nsCOMPtr)
 #include "nsIStructuredCloneContainer.h" // for member (in nsCOMPtr)
 #include "nsPIDOMWindow.h"               // for use in inline functions
 #include "nsPropertyTable.h"             // for member
 #include "nsTHashtable.h"                // for member
+#include "mozilla/dom/DirectionalityUtils.h"
 
 class imgIRequest;
 class nsAString;
 class nsBindingManager;
 class nsCSSStyleSheet;
 class nsDOMNavigationTiming;
 class nsEventStates;
 class nsFrameLoader;
@@ -392,16 +393,20 @@ public:
    * callers are expected to take action as needed if they want this
    * change to actually change anything immediately.
    * @see nsBidiUtils.h
    */
   void SetBidiOptions(PRUint32 aBidiOptions)
   {
     mBidiOptions = aBidiOptions;
   }
+
+  inline mozilla::directionality::Directionality GetDocumentDirectionality() {
+    return mDirectionality;
+  }
   
   /**
    * Access HTTP header data (this may also get set from other
    * sources, like HTML META tags).
    */
   virtual void GetHeaderData(nsIAtom* aHeaderField, nsAString& aData) const = 0;
   virtual void SetHeaderData(nsIAtom* aheaderField, const nsAString& aData) = 0;
 
@@ -1848,16 +1853,19 @@ protected:
   // If mIsStaticDocument is true, mOriginalDocument points to the original
   // document.
   nsCOMPtr<nsIDocument> mOriginalDocument;
 
   // The bidi options for this document.  What this bitfield means is
   // defined in nsBidiUtils.h
   PRUint32 mBidiOptions;
 
+  // The root directionality of this document.
+  mozilla::directionality::Directionality mDirectionality;
+
   nsCString mContentLanguage;
 private:
   nsCString mContentType;
 protected:
 
   // The document's security info
   nsCOMPtr<nsISupports> mSecurityInfo;
 
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -140,18 +140,26 @@ enum {
   NODE_HAS_ACCESSKEY           = 0x00020000U,
 
   // Set if the node is handling a click.
   NODE_HANDLING_CLICK          = 0x00040000U,
 
   // Set if the node has had :hover selectors matched against it
   NODE_HAS_RELEVANT_HOVER_RULES = 0x00080000U,
 
+  // Set if the node has right-to-left directionality
+  NODE_HAS_DIRECTION_RTL        = 0x00100000U,
+
+  // Set if the node has left-to-right directionality
+  NODE_HAS_DIRECTION_LTR        = 0x00200000U,
+
+  NODE_ALL_DIRECTION_FLAGS      = NODE_HAS_DIRECTION_LTR | NODE_HAS_DIRECTION_RTL,
+
   // Remaining bits are node type specific.
-  NODE_TYPE_SPECIFIC_BITS_OFFSET =        20
+  NODE_TYPE_SPECIFIC_BITS_OFFSET =        22
 };
 
 /**
  * Class used to detect unexpected mutations. To use the class create an
  * nsMutationGuard on the stack before unexpected mutations could occur.
  * You can then at any time call Mutated to check if any unexpected mutations
  * have occurred.
  *
@@ -1274,16 +1282,18 @@ private:
     // Set if element has pointer locked
     ElementHasPointerLock,
     // Set if the node may have DOMMutationObserver attached to it.
     NodeMayHaveDOMMutationObserver,
     // Set if node is Content
     NodeIsContent,
     // Set if the node has animations or transitions
     ElementHasAnimations,
+    // Set if node has a dir attribute with a valid value (ltr or rtl)
+    NodeHasValidDirAttribute,
     // Guard value
     BooleanFlagCount
   };
 
   void SetBoolFlag(BooleanFlag name, bool value) {
     PR_STATIC_ASSERT(BooleanFlagCount <= 8*sizeof(mBoolFlags));
     mBoolFlags = (mBoolFlags & ~(1 << name)) | (value << name);
   }
@@ -1341,16 +1351,19 @@ public:
   void SetMayHaveDOMMutationObserver()
     { SetBoolFlag(NodeMayHaveDOMMutationObserver, true); }
   bool HasListenerManager() { return HasFlag(NODE_HAS_LISTENERMANAGER); }
   bool HasPointerLock() const { return GetBoolFlag(ElementHasPointerLock); }
   void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); }
   void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
   bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
   void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
+  void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
+  void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
+  bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
 protected:
   void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
   void SetInDocument() { SetBoolFlag(IsInDocument); }
   void SetNodeIsContent() { SetBoolFlag(NodeIsContent); }
   void ClearInDocument() { ClearBoolFlag(IsInDocument); }
   void SetIsElement() { SetBoolFlag(NodeIsElement); }
   void SetHasID() { SetBoolFlag(ElementHasID); }
   void ClearHasID() { ClearBoolFlag(ElementHasID); }
new file mode 100644
--- /dev/null
+++ b/content/base/src/DirectionalityUtils.cpp
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* 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/. */
+
+#include "mozilla/dom/DirectionalityUtils.h"
+#include "nsINode.h"
+#include "nsIContent.h"
+#include "nsIDocument.h"
+#include "mozilla/dom/Element.h"
+#include "nsIDOMNodeFilter.h"
+#include "nsTreeWalker.h"
+#include "nsIDOMHTMLDocument.h"
+
+
+namespace mozilla {
+
+namespace directionality {
+
+typedef mozilla::dom::Element Element;
+
+void
+SetDirectionality(Element* aElement, Directionality aDir, bool aNotify)
+{
+  aElement->UnsetFlags(NODE_ALL_DIRECTION_FLAGS);
+  switch (aDir) {
+    case eDir_RTL:
+      aElement->SetFlags(NODE_HAS_DIRECTION_RTL);
+      break;
+    case eDir_LTR:
+      aElement->SetFlags(NODE_HAS_DIRECTION_LTR);
+      break;
+    default:
+      break;
+  }
+
+  aElement->UpdateState(aNotify);
+}
+
+Directionality
+RecomputeDirectionality(Element* aElement, bool aNotify)
+{
+  Directionality dir = eDir_LTR;
+
+  if (aElement->HasValidDir()) {
+    dir = aElement->GetDirectionality();
+  } else {
+    Element* parent = aElement->GetElementParent();
+    if (parent) {
+      // If the element doesn't have an explicit dir attribute with a valid
+      // value, the directionality is the same as the parent element (but
+      // don't propagate the parent directionality if it isn't set yet).
+      Directionality parentDir = parent->GetDirectionality();
+      if (parentDir != eDir_NotSet) {
+        dir = parentDir;
+      }
+    } else {
+      // If there is no parent element, the directionality is the same as the
+      // document direction.
+      Directionality documentDir =
+        aElement->OwnerDoc()->GetDocumentDirectionality();
+      if (documentDir != eDir_NotSet) {
+        dir = documentDir;
+      }
+    }
+    
+    SetDirectionality(aElement, dir, aNotify);
+  }
+  return dir;
+}
+
+void
+SetDirectionalityOnDescendants(Element* aElement, Directionality aDir,
+                               bool aNotify)
+{
+  for (nsIContent* child = aElement->GetFirstChild(); child; ) {
+    if (!child->IsElement()) {
+      child = child->GetNextNode(aElement);
+      continue;
+    }
+
+    Element* element = child->AsElement();
+    if (element->HasValidDir()) {
+      child = child->GetNextNonChildNode(aElement);
+      continue;
+    }
+    SetDirectionality(element, aDir, aNotify);
+    child = child->GetNextNode(aElement);
+  }
+}
+
+} // end namespace directionality
+
+} // end namespace mozilla
+
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -48,16 +48,17 @@ EXPORTS_NAMESPACES = mozilla/dom
 EXPORTS_mozilla/dom = \
   Link.h \
   $(NULL)
 
 LOCAL_INCLUDES = \
 		$(NULL)
 
 CPPSRCS		= \
+		DirectionalityUtils.cpp \
 		nsAtomListUtils.cpp \
 		nsAttrAndChildArray.cpp \
 		nsAttrValue.cpp \
 		nsAttrValueOrString.cpp \
 		nsCCUncollectableMarker.cpp \
 		nsChannelPolicy.cpp \
 		nsCommentNode.cpp \
 		nsContentAreaDragDrop.cpp \
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -86,16 +86,17 @@
 // for radio group stuff
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIRadioVisitor.h"
 #include "nsIFormControl.h"
 
 #include "nsXMLEventsManager.h"
 
 #include "nsBidiUtils.h"
+#include "mozilla/dom/DirectionalityUtils.h"
 
 #include "nsIDOMUserDataHandler.h"
 #include "nsIDOMXPathEvaluator.h"
 #include "nsIXPathEvaluatorInternal.h"
 #include "nsIParserService.h"
 #include "nsContentCreatorFunctions.h"
 
 #include "nsIScriptContext.h"
@@ -165,16 +166,17 @@
 
 #include "mozilla/Preferences.h"
 
 #include "imgILoader.h"
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
+using namespace mozilla::directionality;
 
 typedef nsTArray<Link*> LinkArray;
 
 // Reference to the document which requested DOM full-screen mode.
 nsWeakPtr nsDocument::sFullScreenDoc = nullptr;
 
 // Reference to the root document of the branch containing the document
 // which requested DOM full-screen mode.
@@ -1505,17 +1507,18 @@ nsIDocument::nsIDocument()
     mRemovedFromDocShell(false),
     // mAllowDNSPrefetch starts true, so that we can always reliably && it
     // with various values that might disable it.  Since we never prefetch
     // unless we get a window, and in that case the docshell value will get
     // &&-ed in, this is safe.
     mAllowDNSPrefetch(true),
     mIsBeingUsedAsImage(false),
     mHasLinksToUpdate(false),
-    mPartID(0)
+    mPartID(0),
+    mDirectionality(eDir_LTR)
 {
   SetInDocument();
 }
 
 // NOTE! nsDocument::operator new() zeroes out all members, so don't
 // bother initializing members to 0.
 
 nsDocument::nsDocument(const char* aContentType)
@@ -5578,16 +5581,25 @@ nsDocument::SetDir(const nsAString& aDir
         if (shell) {
           nsPresContext *context = shell->GetPresContext();
           NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
           context->SetBidi(options, true);
         } else {
           // No presentation; just set it on ourselves
           SetBidiOptions(options);
         }
+        Directionality dir = elt->mValue == IBMBIDI_TEXTDIRECTION_RTL ?
+                               eDir_RTL : eDir_LTR;
+        SetDocumentDirectionality(dir);
+        // Set the directionality of the root element and its descendants, if any
+        Element* rootElement = GetRootElement();
+        if (rootElement) {
+          SetDirectionality(rootElement, dir, true);
+          SetDirectionalityOnDescendants(rootElement, dir);
+        }
       }
 
       break;
     }
   }
 
   return NS_OK;
 }
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1043,16 +1043,22 @@ protected:
   void DestroyElementMaps();
 
   // Refreshes the hrefs of all the links in the document.
   void RefreshLinkHrefs();
 
   nsIContent* GetFirstBaseNodeWithHref();
   nsresult SetFirstBaseNodeWithHref(nsIContent *node);
 
+  inline void
+  SetDocumentDirectionality(mozilla::directionality::Directionality aDir)
+  {
+    mDirectionality = aDir;
+  }
+
   // Get the first <title> element with the given IsNodeOfType type, or
   // return null if there isn't one
   nsIContent* GetTitleContent(PRUint32 aNodeType);
   // Find the first "title" element in the given IsNodeOfType type and
   // append the concatenation of its text node children to aTitle. Do
   // nothing if there is no such element.
   void GetTitleFromElement(PRUint32 aNodeType, nsAString& aTitle);
 
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -46,16 +46,17 @@
 #include "nsDOMTokenList.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsDOMError.h"
 #include "nsDOMString.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsMutationEvent.h"
 #include "nsNodeUtils.h"
+#include "mozilla/dom/DirectionalityUtils.h"
 #include "nsDocument.h"
 #include "nsAttrValueOrString.h"
 #ifdef MOZ_XUL
 #include "nsXULElement.h"
 #endif /* MOZ_XUL */
 #include "nsFrameManager.h"
 #include "nsFrameSelection.h"
 #ifdef DEBUG
@@ -123,16 +124,17 @@
 #include "mozilla/Telemetry.h"
 
 #include "mozilla/CORSMode.h"
 
 #include "nsStyledElement.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
+using namespace mozilla::directionality;
 
 nsEventStates
 Element::IntrinsicState() const
 {
   return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE :
                         NS_EVENT_STATE_MOZ_READONLY;
 }
 
@@ -1353,16 +1355,23 @@ nsGenericElement::BindToTree(nsIDocument
                NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES |
                // And the restyle bits
                ELEMENT_ALL_RESTYLE_FLAGS);
   } else {
     // If we're not in the doc, update our subtree pointer.
     SetSubtreeRootPointer(aParent->SubtreeRoot());
   }
 
+  // This has to be here, rather than in nsGenericHTMLElement::BindToTree, 
+  //  because it has to happen after updating the parent pointer, but before
+  //  recursively binding the kids.
+  if (IsHTML()) {
+    RecomputeDirectionality(this, false);
+  }
+
   // If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children
   // that also need to be told that they are moving.
   nsresult rv;
   if (hadForceXBL) {
     nsBindingManager* bmgr = OwnerDoc()->BindingManager();
 
     // First check if we have a binding...
     nsXBLBinding* contBinding =
@@ -1538,16 +1547,23 @@ nsGenericElement::UnbindFromTree(bool aD
 #endif
   {
     nsDOMSlots *slots = GetExistingDOMSlots();
     if (slots) {
       slots->mBindingParent = nullptr;
     }
   }
 
+  // This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree, 
+  //  because it has to happen after unsetting the parent pointer, but before
+  //  recursively unbinding the kids.
+  if (IsHTML()) {
+    RecomputeDirectionality(this, false);
+  }
+
   if (aDeep) {
     // Do the kids. Don't call GetChildCount() here since that'll force
     // XUL to generate template children, which there is no need for since
     // all we're going to do is unbind them anyway.
     PRUint32 i, n = mAttrsAndChildren.ChildCount();
 
     for (i = 0; i < n; ++i) {
       // Note that we pass false for aNullParent here, since we don't want
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -265,16 +265,17 @@ GK_ATOM(details, "details")
 GK_ATOM(deviceAspectRatio, "device-aspect-ratio")
 GK_ATOM(deviceHeight, "device-height")
 GK_ATOM(deviceWidth, "device-width")
 GK_ATOM(dfn, "dfn")
 GK_ATOM(dialog, "dialog")
 GK_ATOM(difference, "difference")
 GK_ATOM(digit, "digit")
 GK_ATOM(dir, "dir")
+GK_ATOM(directionality, "directionality")
 GK_ATOM(disableOutputEscaping, "disable-output-escaping")
 GK_ATOM(disabled, "disabled")
 GK_ATOM(display, "display")
 GK_ATOM(distinct, "distinct")
 GK_ATOM(div, "div")
 GK_ATOM(dl, "dl")
 GK_ATOM(doctypePublic, "doctype-public")
 GK_ATOM(doctypeSystem, "doctype-system")
@@ -1753,16 +1754,17 @@ GK_ATOM(svgMaskFrame, "SVGMaskFrame")
 GK_ATOM(svgOuterSVGFrame, "SVGOuterSVGFrame")
 GK_ATOM(svgOuterSVGAnonChildFrame, "SVGOuterSVGAnonChildFrame")
 GK_ATOM(svgPathGeometryFrame, "SVGPathGeometryFrame")
 GK_ATOM(svgPatternFrame, "SVGPatternFrame")
 GK_ATOM(svgRadialGradientFrame, "SVGRadialGradientFrame")
 GK_ATOM(svgStopFrame, "SVGStopFrame")
 GK_ATOM(svgSwitchFrame, "SVGSwitchFrame")
 GK_ATOM(svgTextFrame, "SVGTextFrame")
+GK_ATOM(svgTextFrame2, "SVGTextFrame2")
 GK_ATOM(svgTextPathFrame, "SVGTextPathFrame")
 GK_ATOM(svgTSpanFrame, "SVGTSpanFrame")
 GK_ATOM(svgUseFrame, "SVGUseFrame")
 GK_ATOM(HTMLVideoFrame, "VideoFrame")
 GK_ATOM(onloadstart, "onloadstart")
 GK_ATOM(onprogress, "onprogress")
 GK_ATOM(onsuspend, "onsuspend")
 GK_ATOM(onemptied, "onemptied")
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -376,16 +376,18 @@ MOCHITEST_FILES_B = \
 		file_csp_redirects_page.sjs \
 		file_csp_redirects_main.html \
 		file_csp_redirects_resource.sjs \
 		test_bug346485.html \
 		test_bug560780.html \
 		test_bug562652.html \
 		test_bug562137.html \
 		file_bug562137.txt \
+		test_bug562169-1.html \
+		test_bug562169-2.html \
 		test_bug548193.html \
 		file_bug548193.sjs \
 		test_html_colors_quirks.html \
 		test_html_colors_standards.html \
 		test_bug300992.html \
 		test_websocket_hello.html \
 		file_websocket_hello_wsh.py \
 		test_websocket_basic.html \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug562169-1.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=562169
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 562169</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562169">Mozilla Bug 562169</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <div dir="rtl" id="z"></div>  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 562169 **/
+/** Test that adding an child to an element with dir="rtl" makes the
+      child have rtl directionality, and removing the child makes it
+     go back to ltr directionality **/
+
+function checkSelector(element, expectedDir, expectedChild)
+{
+    ok(element.querySelector(":dir("+expectedDir+")") == expectedChild,
+       "direction should be " + expectedDir);
+}
+
+var x = document.createElement("div");
+var y = document.createElement("div");
+x.appendChild(y);
+checkSelector(x, "ltr", y);
+$(z).appendChild(x);
+checkSelector(x, "rtl", y);
+$(z).removeChild(x);
+checkSelector(x, "ltr", y);
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug562169-2.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=562169
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 562169</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562169">Mozilla Bug 562169</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 562169 **/
+/** Test that a newly created element has ltr directionality **/
+
+ok(document.createElement("div").mozMatchesSelector(":dir(ltr)"),
+   "Element should be ltr on creation");
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/events/public/nsEventStates.h
+++ b/content/events/public/nsEventStates.h
@@ -243,16 +243,20 @@ private:
 // Content is in the sub-suboptimal region.
 #define NS_EVENT_STATE_SUB_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(39)
 // Handler for click to play plugin (vulnerable w/update)
 #define NS_EVENT_STATE_VULNERABLE_UPDATABLE NS_DEFINE_EVENT_STATE_MACRO(40)
 // Handler for click to play plugin (vulnerable w/no update)
 #define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(41)
 // Platform does not support plugin content (some mobile platforms)
 #define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(42)
+// Element is ltr (for :dir pseudo-class)
+#define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(43)
+// Element is rtl (for :dir pseudo-class)
+#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(44)
 
 /**
  * NOTE: do not go over 63 without updating nsEventStates::InternalType!
  */
 
 #define ESM_MANAGED_STATES (NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS |     \
                             NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER |   \
                             NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -48,16 +48,17 @@
 #include "nsScriptLoader.h"
 #include "nsRuleData.h"
 
 #include "nsPresState.h"
 #include "nsILayoutHistoryState.h"
 
 #include "nsHTMLParts.h"
 #include "nsContentUtils.h"
+#include "mozilla/dom/DirectionalityUtils.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsGkAtoms.h"
 #include "nsEventStateManager.h"
 #include "nsIDOMEvent.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsITextControlFrame.h"
 #include "nsIForm.h"
@@ -91,16 +92,17 @@
 #include "HTMLPropertiesCollection.h"
 #include "nsVariant.h"
 #include "nsDOMSettableTokenList.h"
 #include "nsThreadUtils.h"
 #include "nsTextFragment.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
+using namespace mozilla::directionality;
 
 class nsINodeInfo;
 class nsIDOMNodeList;
 class nsRuleWalker;
 
 // XXX todo: add in missing out-of-memory checks
 
 //----------------------------------------------------------------------
@@ -1682,16 +1684,34 @@ nsGenericHTMLElement::UpdateEditableStat
   if (value != eInherit) {
     DoSetEditableFlag(!!value, aNotify);
     return;
   }
 
   nsStyledElement::UpdateEditableState(aNotify);
 }
 
+nsEventStates
+nsGenericHTMLElement::IntrinsicState() const
+{
+  nsEventStates state = nsGenericHTMLElementBase::IntrinsicState();
+
+  if (GetDirectionality() == eDir_RTL) {
+    state |= NS_EVENT_STATE_RTL;
+    state &= ~NS_EVENT_STATE_LTR;
+  } else { // at least for HTML, directionality is exclusively LTR or RTL
+    NS_ASSERTION(GetDirectionality() == eDir_LTR,
+                 "HTML element's directionality must be either RTL or LTR");
+    state |= NS_EVENT_STATE_LTR;
+    state &= ~NS_EVENT_STATE_RTL;
+  }
+
+  return state;
+}
+
 nsresult
 nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                  nsIContent* aBindingParent,
                                  bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElementBase::BindToTree(aDocument, aParent,
                                                      aBindingParent,
                                                      aCompileEventHandlers);
@@ -1884,16 +1904,30 @@ nsGenericHTMLElement::AfterSetAttr(PRInt
       NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
         "Expected string value for script body");
       nsresult rv = AddScriptEventListener(aName, aValue->GetStringValue());
       NS_ENSURE_SUCCESS(rv, rv);
     }
     else if (aNotify && aName == nsGkAtoms::spellcheck) {
       SyncEditorsOnSubtree(this);
     }
+    else if (aName == nsGkAtoms::dir) {
+      Directionality dir;
+      if (aValue &&
+          (aValue->Equals(nsGkAtoms::ltr, eIgnoreCase) ||
+           aValue->Equals(nsGkAtoms::rtl, eIgnoreCase))) {
+        SetHasValidDir();
+        dir = aValue->Equals(nsGkAtoms::rtl, eIgnoreCase) ? eDir_RTL : eDir_LTR;
+        SetDirectionality(this, dir, aNotify);
+      } else {
+        ClearHasValidDir();
+        dir = RecomputeDirectionality(this, aNotify);
+      }
+      SetDirectionalityOnDescendants(this, dir, aNotify);
+    }
   }
 
   return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,
                                                 aValue, aNotify);
 }
 
 nsEventListenerManager*
 nsGenericHTMLElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -44,16 +44,18 @@ typedef nsMappedAttributeElement nsGener
 class nsGenericHTMLElement : public nsGenericHTMLElementBase
 {
 public:
   nsGenericHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElementBase(aNodeInfo)
   {
     NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
                  "Unexpected namespace");
+    AddStatesSilently(NS_EVENT_STATE_LTR);
+    SetFlags(NODE_HAS_DIRECTION_LTR);
   }
 
   /** Typesafe, non-refcounting cast from nsIContent.  Cheaper than QI. **/
   static nsGenericHTMLElement* FromContent(nsIContent *aContent)
   {
     if (aContent->IsHTML())
       return static_cast<nsGenericHTMLElement*>(aContent);
     return nullptr;
@@ -197,16 +199,18 @@ public:
   nsresult PostHandleEventForAnchors(nsEventChainPostVisitor& aVisitor);
   bool IsHTMLLink(nsIURI** aURI) const;
 
   // HTML element methods
   void Compact() { mAttrsAndChildren.Compact(); }
 
   virtual void UpdateEditableState(bool aNotify);
 
+  virtual nsEventStates IntrinsicState() const;
+
   // Helper for setting our editable flag and notifying
   void DoSetEditableFlag(bool aEditable, bool aNotify) {
     SetEditableFlag(aEditable);
     UpdateState(aNotify);
   }
 
   virtual bool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -111,18 +111,17 @@ nsHTMLAudioElement::MozSetup(PRUint32 aC
     return NS_ERROR_FAILURE;
   }
 
   if (mAudioStream) {
     mAudioStream->Shutdown();
   }
 
   mAudioStream = nsAudioStream::AllocateStream();
-  nsresult rv = mAudioStream->Init(aChannels, aRate,
-                                   nsAudioStream::FORMAT_FLOAT32);
+  nsresult rv = mAudioStream->Init(aChannels, aRate);
   if (NS_FAILED(rv)) {
     mAudioStream->Shutdown();
     mAudioStream = nullptr;
     return rv;
   }
 
   MetadataLoaded(aChannels, aRate, true, nullptr);
   mAudioStream->SetVolume(mVolume);
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -2816,16 +2816,18 @@ void nsHTMLMediaElement::PlaybackEnded()
     DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
   }
 
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::loop)) {
     SetCurrentTime(0);
     return;
   }
 
+  Pause();
+
   FireTimeUpdate(false);
   DispatchAsyncEvent(NS_LITERAL_STRING("ended"));
 }
 
 void nsHTMLMediaElement::SeekStarted()
 {
   DispatchAsyncEvent(NS_LITERAL_STRING("seeking"));
   ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -1098,18 +1098,17 @@ MediaStreamGraphImpl::CreateOrDestroyAud
   // XXX allocating a nsAudioStream could be slow so we're going to have to do
   // something here ... preallocation, async allocation, multiplexing onto a single
   // stream ...
 
   AudioSegment* audio = track->Get<AudioSegment>();
   aStream->mAudioPlaybackStartTime = aAudioOutputStartTime;
   aStream->mAudioOutput = nsAudioStream::AllocateStream();
   aStream->mAudioOutput->Init(audio->GetChannels(),
-                              track->GetRate(),
-                              audio->GetFirstFrameFormat());
+                              track->GetRate());
 }
 
 void
 MediaStreamGraphImpl::PlayAudio(MediaStream* aStream,
                                 GraphTime aFrom, GraphTime aTo)
 {
   if (!aStream->mAudioOutput)
     return;
--- a/content/media/nsAudioStream.cpp
+++ b/content/media/nsAudioStream.cpp
@@ -55,17 +55,17 @@ static const PRInt64 MS_PER_S = 1000;
 class nsNativeAudioStream : public nsAudioStream
 {
  public:
   NS_DECL_ISUPPORTS
 
   ~nsNativeAudioStream();
   nsNativeAudioStream();
 
-  nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
+  nsresult Init(PRInt32 aNumChannels, PRInt32 aRate);
   void Shutdown();
   nsresult Write(const void* aBuf, PRUint32 aFrames);
   PRUint32 Available();
   void SetVolume(double aVolume);
   void Drain();
   void Pause();
   void Resume();
   PRInt64 GetPosition();
@@ -90,17 +90,17 @@ class nsNativeAudioStream : public nsAud
 class nsRemotedAudioStream : public nsAudioStream
 {
  public:
   NS_DECL_ISUPPORTS
 
   nsRemotedAudioStream();
   ~nsRemotedAudioStream();
 
-  nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
+  nsresult Init(PRInt32 aNumChannels, PRInt32 aRate);
   void Shutdown();
   nsresult Write(const void* aBuf, PRUint32 aFrames);
   PRUint32 Available();
   void SetVolume(double aVolume);
   void Drain();
   void Pause();
   void Resume();
   PRInt64 GetPosition();
@@ -417,21 +417,21 @@ nsNativeAudioStream::nsNativeAudioStream
 
 nsNativeAudioStream::~nsNativeAudioStream()
 {
   Shutdown();
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS0(nsNativeAudioStream)
 
-nsresult nsNativeAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat)
+nsresult nsNativeAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate)
 {
   mRate = aRate;
   mChannels = aNumChannels;
-  mFormat = aFormat;
+  mFormat = MOZ_AUDIO_DATA_FORMAT;
 
   if (sa_stream_create_pcm(reinterpret_cast<sa_stream_t**>(&mAudioHandle),
                            NULL,
                            SA_MODE_WRONLY,
                            SA_PCM_FORMAT_S16_NE,
                            aRate,
                            aNumChannels) != SA_SUCCESS) {
     mAudioHandle = nullptr;
@@ -469,63 +469,38 @@ nsresult nsNativeAudioStream::Write(cons
   if (mInError)
     return NS_ERROR_FAILURE;
 
   PRUint32 samples = aFrames * mChannels;
   nsAutoArrayPtr<short> s_data(new short[samples]);
 
   if (s_data) {
     double scaled_volume = GetVolumeScale() * mVolume;
-    switch (mFormat) {
-      case FORMAT_U8: {
-        const PRUint8* buf = static_cast<const PRUint8*>(aBuf);
-        PRInt32 volume = PRInt32((1 << 16) * scaled_volume);
-        for (PRUint32 i = 0; i < samples; ++i) {
-          s_data[i] = short(((PRInt32(buf[i]) - 128) * volume) >> 8);
-        }
-        break;
-      }
-      case FORMAT_S16_LE: {
-        const short* buf = static_cast<const short*>(aBuf);
-        PRInt32 volume = PRInt32((1 << 16) * scaled_volume);
-        for (PRUint32 i = 0; i < samples; ++i) {
-          short s = buf[i];
-#if defined(IS_BIG_ENDIAN)
-          s = ((s & 0x00ff) << 8) | ((s & 0xff00) >> 8);
-#endif
-          s_data[i] = short((PRInt32(s) * volume) >> 16);
-        }
-        break;
-      }
-      case FORMAT_FLOAT32: {
-        const float* buf = static_cast<const float*>(aBuf);
-        for (PRUint32 i = 0; i <  samples; ++i) {
-          float scaled_value = floorf(0.5 + 32768 * buf[i] * scaled_volume);
-          if (buf[i] < 0.0) {
-            s_data[i] = (scaled_value < -32768.0) ?
-              -32768 :
-              short(scaled_value);
-          } else {
-            s_data[i] = (scaled_value > 32767.0) ?
-              32767 :
-              short(scaled_value);
-          }
-        }
-        break;
+    const SampleType* buf = static_cast<const SampleType*>(aBuf);
+    for (PRUint32 i = 0; i <  samples; ++i) {
+      float scaled_value = floorf(0.5 + 32768 * buf[i] * scaled_volume);
+      if (buf[i] < 0.0) {
+        s_data[i] = (scaled_value < -32768.0) ?
+          -32768 :
+          short(scaled_value);
+      } else {
+        s_data[i] = (scaled_value > 32767.0) ?
+          32767 :
+          short(scaled_value);
       }
     }
+  }
 
-    if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
-                        s_data.get(),
-                        samples * sizeof(short)) != SA_SUCCESS)
-    {
-      PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error"));
-      mInError = true;
-      return NS_ERROR_FAILURE;
-    }
+  if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
+                      s_data.get(),
+                      samples * sizeof(short)) != SA_SUCCESS)
+  {
+    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error"));
+    mInError = true;
+    return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 PRUint32 nsNativeAudioStream::Available()
 {
   // If the audio backend failed to open, lie and say we'll accept some
   // data.
@@ -639,36 +614,22 @@ nsRemotedAudioStream::~nsRemotedAudioStr
 {
   Shutdown();
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS0(nsRemotedAudioStream)
 
 nsresult
 nsRemotedAudioStream::Init(PRInt32 aNumChannels,
-                           PRInt32 aRate,
-                           SampleFormat aFormat)
+                           PRInt32 aRate)
 {
   mRate = aRate;
   mChannels = aNumChannels;
-  mFormat = aFormat;
-
-  switch (mFormat) {
-    case FORMAT_U8: {
-      mBytesPerFrame = sizeof(PRUint8) * mChannels;
-      break;
-    }
-    case FORMAT_S16_LE: {
-      mBytesPerFrame = sizeof(short) * mChannels;
-      break;
-    }
-    case FORMAT_FLOAT32: {
-      mBytesPerFrame = sizeof(float) * mChannels;
-    }
-  }
+  mFormat = MOZ_AUDIO_DATA_FORMAT;
+  mBytesPerFrame = sizeof(SampleType) * mChannels;
 
   nsCOMPtr<nsIRunnable> event = new AudioInitEvent(this);
   NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
   return NS_OK;
 }
 
 void
 nsRemotedAudioStream::Shutdown()
@@ -856,17 +817,17 @@ private:
 class nsBufferedAudioStream : public nsAudioStream
 {
  public:
   NS_DECL_ISUPPORTS
 
   nsBufferedAudioStream();
   ~nsBufferedAudioStream();
 
-  nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat);
+  nsresult Init(PRInt32 aNumChannels, PRInt32 aRate);
   void Shutdown();
   nsresult Write(const void* aBuf, PRUint32 aFrames);
   PRUint32 Available();
   void SetVolume(double aVolume);
   void Drain();
   void Pause();
   void Resume();
   PRInt64 GetPosition();
@@ -958,43 +919,33 @@ nsBufferedAudioStream::nsBufferedAudioSt
 nsBufferedAudioStream::~nsBufferedAudioStream()
 {
   Shutdown();
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS0(nsBufferedAudioStream)
 
 nsresult
-nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat)
+nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate)
 {
   cubeb* cubebContext = GetCubebContext();
 
   if (!cubebContext || aNumChannels < 0 || aRate < 0) {
     return NS_ERROR_FAILURE;
   }
 
   mRate = aRate;
   mChannels = aNumChannels;
-  mFormat = aFormat;
+  mFormat = MOZ_AUDIO_DATA_FORMAT;
 
   cubeb_stream_params params;
   params.rate = aRate;
   params.channels = aNumChannels;
-  switch (aFormat) {
-  case FORMAT_S16_LE:
-    params.format = CUBEB_SAMPLE_S16LE;
-    mBytesPerFrame = sizeof(short) * aNumChannels;
-    break;
-  case FORMAT_FLOAT32:
-    params.format = CUBEB_SAMPLE_FLOAT32NE;
-    mBytesPerFrame = sizeof(float) * aNumChannels;
-    break;
-  default:
-    return NS_ERROR_FAILURE;
-  }
+  params.format = CUBEB_SAMPLE_FLOAT32NE;
+  mBytesPerFrame = sizeof(float) * aNumChannels;
 
   {
     cubeb_stream* stream;
     if (cubeb_stream_init(cubebContext, &stream, "nsBufferedAudioStream", params,
                           GetCubebLatency(), DataCallback_S, StateCallback_S, this) == CUBEB_OK) {
       mCubebStream.own(stream);
     }
   }
@@ -1216,39 +1167,20 @@ nsBufferedAudioStream::DataCallback(void
     PRUint8* output = reinterpret_cast<PRUint8*>(aBuffer);
     for (int i = 0; i < 2; ++i) {
       // Fast path for unity volume case.
       if (scaled_volume == 1.0) {
         memcpy(output, input[i], input_size[i]);
         output += input_size[i];
       } else {
         // Adjust volume as each sample is copied out.
-        switch (mFormat) {
-        case FORMAT_S16_LE: {
-          PRInt32 volume = PRInt32(1 << 16) * scaled_volume;
-
-          const short* src = static_cast<const short*>(input[i]);
-          short* dst = reinterpret_cast<short*>(output);
-          for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) {
-            dst[j] = short((PRInt32(src[j]) * volume) >> 16);
-          }
-          output += input_size[i];
-          break;
-        }
-        case FORMAT_FLOAT32: {
-          const float* src = static_cast<const float*>(input[i]);
-          float* dst = reinterpret_cast<float*>(output);
-          for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) {
-            dst[j] = src[j] * scaled_volume;
-          }
-          output += input_size[i];
-          break;
-        }
-        default:
-          return -1;
+        const float* src = static_cast<const float*>(input[i]);
+        float* dst = reinterpret_cast<float*>(output);
+        for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) {
+          dst[j] = src[j] * scaled_volume;
         }
       }
     }
 
     NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Must copy complete frames");
 
     // Notify any blocked Write() call that more space is available in mBuffer.
     mon.NotifyAll();
--- a/content/media/nsAudioStream.h
+++ b/content/media/nsAudioStream.h
@@ -6,16 +6,24 @@
 #if !defined(nsAudioStream_h_)
 #define nsAudioStream_h_
 
 #include "nscore.h"
 #include "nsISupportsImpl.h"
 #include "nsIThread.h"
 #include "nsAutoPtr.h"
 
+#ifndef MOZ_FLOATING_POINT_AUDIO
+#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_S16_LE)
+typedef short SampleType;
+#else
+#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_FLOAT32)
+typedef float SampleType;
+#endif
+
 // Access to a single instance of this class must be synchronized by
 // callers, or made from a single thread.  One exception is that access to
 // GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels,Format}
 // is thread-safe without external synchronization.
 class nsAudioStream : public nsISupports
 {
 public:
 
@@ -23,18 +31,17 @@ public:
   {
     FORMAT_U8,
     FORMAT_S16_LE,
     FORMAT_FLOAT32
   };
 
   nsAudioStream()
     : mRate(0),
-      mChannels(0),
-      mFormat(FORMAT_S16_LE)
+      mChannels(0)
   {}
 
   virtual ~nsAudioStream();
 
   // Initialize Audio Library. Some Audio backends require initializing the
   // library before using it.
   static void InitLibrary();
 
@@ -51,17 +58,17 @@ public:
   // you may receive an implementation which forwards to a compositing process.
   static nsAudioStream* AllocateStream();
 
   // Initialize the audio stream. aNumChannels is the number of audio
   // channels (1 for mono, 2 for stereo, etc) and aRate is the sample rate
   // (22050Hz, 44100Hz, etc).
   // Unsafe to call with a monitor held due to synchronous event execution
   // on the main thread, which may attempt to acquire any held monitor.
-  virtual nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat) = 0;
+  virtual nsresult Init(PRInt32 aNumChannels, PRInt32 aRate) = 0;
 
   // Closes the stream. All future use of the stream is an error.
   // Unsafe to call with a monitor held due to synchronous event execution
   // on the main thread, which may attempt to acquire any held monitor.
   virtual void Shutdown() = 0;
 
   // Write audio data to the audio hardware.  aBuf is an array of frames in
   // the format specified by mFormat of length aCount.  If aFrames is larger
@@ -101,17 +108,17 @@ public:
   // Returns the minimum number of audio frames which must be written before
   // you can be sure that something will be played.
   // Unsafe to call with a monitor held due to synchronous event execution
   // on the main thread, which may attempt to acquire any held monitor.
   virtual PRInt32 GetMinWriteSize() = 0;
 
   int GetRate() { return mRate; }
   int GetChannels() { return mChannels; }
-  SampleFormat GetFormat() { return mFormat; }
+  SampleFormat GetFormat() { return MOZ_AUDIO_DATA_FORMAT; }
 
 protected:
   nsCOMPtr<nsIThread> mAudioPlaybackThread;
   int mRate;
   int mChannels;
   SampleFormat mFormat;
 };
 
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -952,17 +952,17 @@ nsresult nsBuiltinDecoder::GetSeekable(n
 
   if (IsSeekable()) {
     double end = IsInfinite() ? std::numeric_limits<double>::infinity()
                               : initialTime + GetDuration();
     aSeekable->Add(initialTime, end);
     return NS_OK;
   }
 
-  if (mDecoderStateMachine->IsSeekableInBufferedRanges()) {
+  if (mDecoderStateMachine && mDecoderStateMachine->IsSeekableInBufferedRanges()) {
     return GetBuffered(aSeekable);
   } else {
     // The stream is not seekable using only buffered ranges, and is not
     // seekable. Don't allow seeking (return no ranges in |seekable|).
     return NS_OK;
   }
 }
 
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -47,36 +47,34 @@ public:
 
   // True if we have an active audio bitstream.
   bool mHasAudio;
 
   // True if we have an active video bitstream.
   bool mHasVideo;
 };
 
-#ifdef MOZ_TREMOR
+#ifndef MOZ_FLOATING_POINT_AUDIO
 #include <ogg/os_types.h>
 typedef ogg_int32_t VorbisPCMValue;
 typedef short AudioDataValue;
 
-#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_S16_LE)
 #define MOZ_CLIP_TO_15(x) ((x)<-32768?-32768:(x)<=32767?(x):32767)
 // Convert the output of vorbis_synthesis_pcmout to a AudioDataValue
 #define MOZ_CONVERT_VORBIS_SAMPLE(x) \
  (static_cast<AudioDataValue>(MOZ_CLIP_TO_15((x)>>9)))
 // Convert a AudioDataValue to a float for the Audio API
 #define MOZ_CONVERT_AUDIO_SAMPLE(x) ((x)*(1.F/32768))
 #define MOZ_SAMPLE_TYPE_S16LE 1
 
-#else /*MOZ_VORBIS*/
+#else /* MOZ_FLOATING_POINT_AUDIO == 1*/
 
 typedef float VorbisPCMValue;
 typedef float AudioDataValue;
 
-#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_FLOAT32)
 #define MOZ_CONVERT_VORBIS_SAMPLE(x) (x)
 #define MOZ_CONVERT_AUDIO_SAMPLE(x) (x)
 #define MOZ_SAMPLE_TYPE_FLOAT32 1
 
 #endif
 
 // Holds chunk a decoded audio frames.
 class AudioData {
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -1003,17 +1003,17 @@ void nsBuiltinDecoderStateMachine::Audio
   // monitor held, as on Android those methods do a synchronous dispatch to
   // the main thread. If the audio thread holds the decoder monitor while
   // it does a synchronous dispatch to the main thread, we can get deadlocks
   // if the main thread tries to acquire the decoder monitor before the
   // dispatched event has finished (or even started!) running. Methods which
   // are unsafe to call with the decoder monitor held are documented as such
   // in nsAudioStream.h.
   nsRefPtr<nsAudioStream> audioStream = nsAudioStream::AllocateStream();
-  audioStream->Init(channels, rate, MOZ_AUDIO_DATA_FORMAT);
+  audioStream->Init(channels, rate);
 
   {
     // We must hold the monitor while setting mAudioStream or whenever we query
     // the playback position off the audio thread. This ensures the audio stream
     // is always alive when we use it off the audio thread. Note that querying
     // the playback position does not do a synchronous dispatch to the main
     // thread, so it's safe to call with the decoder monitor held.
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
--- a/content/media/test/test_paused_after_ended.html
+++ b/content/media/test/test_paused_after_ended.html
@@ -9,33 +9,40 @@
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 var manager = new MediaTestManager;
 
 function ended(evt) {
   var v = evt.target;
-  is(v.paused, false, v._name + " must not be paused after end");
+  is(v.gotPause, true, "We should have received a \"pause\" event.")
+  is(v.paused, true, v._name + " must be paused after end");
   manager.finished(v.token);
 }
 
+function pause(evt) {
+  var v = evt.target;
+  v.gotPause = true;
+}
+
 function startTest(test, token) {
   var v = document.createElement('video');
   v.token = token;
   manager.started(v.token);
   v.src = test.name;
   v._name = test.name;
   v._finished = false;
   v.load();
   is(v.paused, true,  v._name + " must be paused at start");
 
   v.play();
   is(v.paused, false, v._name + " must not be paused after play");
 
+  v.addEventListener("pause", pause, false);
   v.addEventListener("ended", ended, false);
 }
 
 manager.runTests(gPausedAfterEndedTests, startTest);
 
 </script>
 </pre>
 </body>
--- a/content/media/test/test_replay_metadata.html
+++ b/content/media/test/test_replay_metadata.html
@@ -27,16 +27,17 @@ var manager = new MediaTestManager;
 function seekStarted(evt) {
   var v = evt.target;
   v._gotSeekStarted = true;
 }
 
 function seekEnded(evt) {
   var v = evt.target;
   v._gotSeekEnded = true;
+  v.play();
 }
 
 function loadedData(evt) {
   var v = evt.target;
   v._loadedDataCount++;
   ok(v._loadedDataCount <= 1, "No more than 1 onloadeddata event for " + v._name);
 }
 
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2492,38 +2492,36 @@ nsXULPrototypeScript::Compile(const PRUn
     }
 
     nsCAutoString urlspec;
     nsContentUtils::GetWrapperSafeScriptFilename(aDocument, aURI, urlspec);
 
     // Ok, compile it to create a prototype script object!
 
     nsScriptObjectHolder<JSScript> newScriptObject(context);
-    uint32_t opts = JS_GetOptions(context->GetNativeContext());
-    if (!mOutOfLine) {
-        // If the script was inline, tell the JS parser to save source for
-        // Function.prototype.toSource(). If it's outline, we retrieve the
-        // source from the files on demand.
-        opts &= ~JSOPTION_ONLY_CNG_SOURCE;
-        JS_SetOptions(context->GetNativeContext(), opts);
-    }
+
+    // If the script was inline, tell the JS parser to save source for
+    // Function.prototype.toSource(). If it's out of line, we retrieve the
+    // source from the files on demand.
+    bool saveSource = !mOutOfLine;
+
     rv = context->CompileScript(aText,
                                 aTextLength,
                                 // Use the enclosing document's principal
                                 // XXX is this right? or should we use the
                                 // protodoc's?
                                 // If we start using the protodoc's, make sure
                                 // the DowngradePrincipalIfNeeded stuff in
                                 // nsXULDocument::OnStreamComplete still works!
                                 aDocument->NodePrincipal(),
                                 urlspec.get(),
                                 aLineNo,
                                 mLangVersion,
-                                newScriptObject);
-    JS_SetOptions(context->GetNativeContext(), opts);
+                                newScriptObject,
+                                saveSource);
     if (NS_FAILED(rv))
         return rv;
 
     Set(newScriptObject);
     return rv;
 }
 
 void
--- a/docshell/base/LoadContext.cpp
+++ b/docshell/base/LoadContext.cpp
@@ -92,19 +92,9 @@ LoadContext::GetAppId(PRUint32* aAppId)
   MOZ_ASSERT(mIsNotNull);
 
   NS_ENSURE_ARG_POINTER(aAppId);
 
   *aAppId = mAppId;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-LoadContext::GetExtendedOrigin(nsIURI* aUri, nsACString& aResult)
-{
-  MOZ_ASSERT(mIsNotNull);
-
-  nsIScriptSecurityManager* ssmgr = nsContentUtils::GetSecurityManager();
-
-  return ssmgr->GetExtendedOrigin(aUri, mAppId, mIsInBrowserElement, aResult);
-}
-
 } // namespace mozilla
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -11390,30 +11390,16 @@ nsDocShell::IsAppOfType(PRUint32 aAppTyp
 
 NS_IMETHODIMP
 nsDocShell::GetIsContent(bool *aIsContent)
 {
     *aIsContent = (mItemType == typeContent);
     return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDocShell::GetExtendedOrigin(nsIURI *aUri, nsACString &aResult)
-{
-    bool isInBrowserElement;
-    GetIsInBrowserElement(&isInBrowserElement);
-
-    nsCOMPtr<nsIScriptSecurityManager> ssmgr =
-      do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
-    NS_ENSURE_TRUE(ssmgr, NS_ERROR_FAILURE);
-
-    return ssmgr->GetExtendedOrigin(aUri, mAppId, isInBrowserElement, aResult);
-}
-
-
 bool
 nsDocShell::IsOKToLoadURI(nsIURI* aURI)
 {
     NS_PRECONDITION(aURI, "Must have a URI!");
     
     if (!mFiredUnloadEvent) {
         return true;
     }
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -223,17 +223,16 @@ public:
     // Don't use NS_DECL_NSILOADCONTEXT because some of nsILoadContext's methods
     // are shared with nsIDocShell (appID, etc.) and can't be declared twice.
     NS_IMETHOD GetAssociatedWindow(nsIDOMWindow**);
     NS_IMETHOD GetTopWindow(nsIDOMWindow**);
     NS_IMETHOD IsAppOfType(PRUint32, bool*);
     NS_IMETHOD GetIsContent(bool*);
     NS_IMETHOD GetUsePrivateBrowsing(bool*);
     NS_IMETHOD SetUsePrivateBrowsing(bool);
-    NS_IMETHOD GetExtendedOrigin(nsIURI *uri, nsACString & retval);
 
     // Restores a cached presentation from history (mLSHE).
     // This method swaps out the content viewer and simulates loads for
     // subframes.  It then simulates the completion of the toplevel load.
     nsresult RestoreFromHistory();
 
     // Perform a URI load from a refresh timer.  This is just like the
     // ForceRefreshURI method on nsIRefreshURI, but makes sure to take
--- a/docshell/base/nsILoadContext.idl
+++ b/docshell/base/nsILoadContext.idl
@@ -2,24 +2,23 @@
  * vim: ft=cpp tw=78 sw=2 et ts=2 sts=2 cin
  * 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/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMWindow;
-interface nsIURI;
 
 /**
  * An nsILoadContext represents the context of a load.  This interface
  * can be queried for various information about where the load is
  * happening.
  */
-[scriptable, uuid(386806c3-c4cb-4b3d-b05d-c08ea10f5585)]
+[scriptable, uuid(48b5bf16-e0c7-11e1-b28e-91726188709b)]
 interface nsILoadContext : nsISupports
 {
   /**
    * associatedWindow is the window with which the load is associated, if any.
    * Note that the load may be triggered by a document which is different from
    * the document in associatedWindow, and in fact the source of the load need
    * not be same-origin with the document in associatedWindow.  This attribute
    * may be null if there is no associated window.
@@ -74,24 +73,9 @@ interface nsILoadContext : nsISupports
   readonly attribute boolean isInBrowserElement;
 
   /**
    * Returns the app id of the app the load is occurring is in. Returns
    * nsIScriptSecurityManager::NO_APP_ID if the load is not part of an app.
    */
   readonly attribute unsigned long appId;
 
-  /**
-   * Get the extended origin of a channel in this load context.
-   * The extended origin is a string that has more information than the origin
-   * and can be used to isolate data or permissions between different
-   * principals while taking into account parameters like the app id or the
-   * fact that the load is taking place in a mozbrowser.
-   *
-   * In some cases this function will simply return the origin for the
-   * channel's URI.
-   *
-   * The extendedOrigin is intended to be an opaque identifier. It is
-   * currently "human-readable" but no callers should assume it will stay
-   * as-is and it might be crypto-hashed at some point.
-   */
-  AUTF8String GetExtendedOrigin(in nsIURI channel);
 };
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -269,17 +269,17 @@ let DOMApplicationRegistry = {
     });
   },
 
   // clones a app object, without the manifest
   _cloneAppObject: function(aApp) {
     let clone = {
       installOrigin: aApp.installOrigin,
       origin: aApp.origin,
-      receipts: aApp.receipts,
+      receipts: aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null,
       installTime: aApp.installTime,
       manifestURL: aApp.manifestURL,
       progress: aApp.progress || 0.0,
       status: aApp.status || "installed"
     };
     return clone;
   },
 
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -40,18 +40,18 @@ public:
 
   virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
                               NS_ISCRIPTCONTEXTPRINCIPAL_IID)
 
 #define NS_ISCRIPTCONTEXT_IID \
-{ 0x9a4df96d, 0xa231, 0x4108, \
-  { 0xb5, 0xbc, 0xaf, 0x67, 0x7a, 0x36, 0xa7, 0x44 } }
+{ 0x8bdcea47, 0x6704, 0x4dd9, \
+  { 0xa1, 0x48, 0x05, 0x34, 0xcf, 0xe2, 0xdd, 0x57 } }
 
 /* This MUST match JSVERSION_DEFAULT.  This version stuff if we don't
    know what language we have is a little silly... */
 #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
 
 /**
  * It is used by the application to initialize a runtime and run scripts.
  * A script runtime would implement this interface.
@@ -109,27 +109,29 @@ public:
    * @param aText a PRUnichar buffer containing script source
    * @param aTextLength number of characters in aText
    * @param aPrincipal the principal that produced the script
    * @param aURL the URL or filename for error messages
    * @param aLineNo the starting line number of the script for error messages
    * @param aVersion the script language version to use when executing
    * @param aScriptObject an executable object that's the result of compiling
    *                      the script.
+   * @param aSaveSource force the source code to be saved by the JS engine in memory
    *
    * @return NS_OK if the script source was valid and got compiled.
    *
    **/
   virtual nsresult CompileScript(const PRUnichar* aText,
                                  PRInt32 aTextLength,
                                  nsIPrincipal* aPrincipal,
                                  const char* aURL,
                                  PRUint32 aLineNo,
                                  PRUint32 aVersion,
-                                 nsScriptObjectHolder<JSScript>& aScriptObject) = 0;
+                                 nsScriptObjectHolder<JSScript>& aScriptObject,
+                                 bool aSaveSource = false) = 0;
 
   /**
    * Execute a precompiled script object.
    *
    * @param aScriptObject an object representing the script to be executed
    * @param aScopeObject an object telling the scope in which to execute,
    *                     or nullptr to use a default scope
    * @param aRetValue the result of executing the script, may be null in
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1077,31 +1077,16 @@ nsJSContext::nsJSContext(JSRuntime *aRun
     sContextList->mPrev = &mNext;
   }
   sContextList = this;
 
   ++sContextCount;
 
   mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS | JSOPTION_ALLOW_XML;
 
-  // The JS engine needs to keep the source code around in order to implement
-  // Function.prototype.toSource(). JSOPTION_ONLY_CNG_SOURCE causes the JS
-  // engine to retain the source code for scripts compiled in compileAndGo mode
-  // and compiled function bodies (from JS_CompileFunction*). In practice, this
-  // means content scripts and event handlers. It'd be nice to stop there and
-  // simply stub out requests for source on chrome code. Life is not so easy,
-  // unfortunately. Nobody relies on chrome toSource() working in core browser
-  // code, but chrome tests use it. The worst offenders are addons, which like
-  // to monkeypatch chrome functions by calling toSource() on them and using
-  // regular expression to modify them. So, even though we don't keep it in
-  // memory, we have to provide a way to get chrome source somehow. Enter
-  // SourceHook. When the JS engine is asked to provide the source for a
-  // function it doesn't have in memory, it calls this function to load it.
-  mDefaultJSOptions |= JSOPTION_ONLY_CNG_SOURCE;
-
   mContext = ::JS_NewContext(aRuntime, gStackSize);
   if (mContext) {
     ::JS_SetContextPrivate(mContext, static_cast<nsIScriptContext *>(this));
 
     // Preserve any flags the context callback might have set.
     mDefaultJSOptions |= ::JS_GetOptions(mContext);
 
     // Make sure the new context gets the default context options
@@ -1558,17 +1543,18 @@ nsJSContext::EvaluateString(const nsAStr
 
 nsresult
 nsJSContext::CompileScript(const PRUnichar* aText,
                            PRInt32 aTextLength,
                            nsIPrincipal *aPrincipal,
                            const char *aURL,
                            PRUint32 aLineNo,
                            PRUint32 aVersion,
-                           nsScriptObjectHolder<JSScript>& aScriptObject)
+                           nsScriptObjectHolder<JSScript>& aScriptObject,
+                           bool aSaveSource /* = false */)
 {
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
   JSObject* scopeObject = ::JS_GetGlobalObject(mContext);
   xpc_UnmarkGrayObject(scopeObject);
 
@@ -1585,25 +1571,30 @@ nsJSContext::CompileScript(const PRUnich
   // Since the caller is responsible for parsing the version strings, we just
   // check it isn't JSVERSION_UNKNOWN.
   if (!ok || JSVersion(aVersion) == JSVERSION_UNKNOWN)
     return NS_OK;
     
   XPCAutoRequest ar(mContext);
 
 
-  JSScript* script =
-    ::JS_CompileUCScriptForPrincipalsVersion(mContext,
-                                             scopeObject,
-                                             nsJSPrincipals::get(aPrincipal),
-                                             static_cast<const jschar*>(aText),
-                                             aTextLength,
-                                             aURL,
-                                             aLineNo,
-                                             JSVersion(aVersion));
+  JS::CompileOptions options(mContext);
+  JS::CompileOptions::SourcePolicy sp = aSaveSource ?
+    JS::CompileOptions::SAVE_SOURCE :
+    JS::CompileOptions::LAZY_SOURCE;
+  options.setPrincipals(nsJSPrincipals::get(aPrincipal))
+         .setFileAndLine(aURL, aLineNo)
+         .setVersion(JSVersion(aVersion))
+         .setSourcePolicy(sp);
+  JS::RootedObject rootedScope(mContext, scopeObject);
+  JSScript* script = JS::Compile(mContext,
+                                 rootedScope,
+                                 options,
+                                 static_cast<const jschar*>(aText),
+                                 aTextLength);
   if (!script) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return aScriptObject.set(script);
 }
 
 nsresult
 nsJSContext::ExecuteScript(JSScript* aScriptObject,
@@ -2022,19 +2013,18 @@ nsJSContext::BindCompiledEventHandler(ns
 
 // serialization
 nsresult
 nsJSContext::Serialize(nsIObjectOutputStream* aStream, JSScript* aScriptObject)
 {
   if (!aScriptObject)
     return NS_ERROR_FAILURE;
 
-  return nsContentUtils::XPConnect()->WriteScript(aStream, mContext, aScriptObject);
-    xpc_UnmarkGrayScript(aScriptObject);
-
+  return nsContentUtils::XPConnect()->WriteScript(aStream, mContext,
+                                                  xpc_UnmarkGrayScript(aScriptObject));
 }
 
 nsresult
 nsJSContext::Deserialize(nsIObjectInputStream* aStream,
                          nsScriptObjectHolder<JSScript>& aResult)
 {
   NS_TIME_FUNCTION_MIN(1.0);
   
@@ -2625,24 +2615,24 @@ TraceMallocDumpAllocations(JSContext *cx
         JS_ReportError(cx, "can't dump to %s: %s", pathname.ptr(), strerror(errno));
         return JS_FALSE;
     }
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSFunctionSpec TraceMallocFunctions[] = {
-    {"TraceMallocDisable",         TraceMallocDisable,         0, 0},
-    {"TraceMallocEnable",          TraceMallocEnable,          0, 0},
-    {"TraceMallocOpenLogFile",     TraceMallocOpenLogFile,     1, 0},
-    {"TraceMallocChangeLogFD",     TraceMallocChangeLogFD,     1, 0},
-    {"TraceMallocCloseLogFD",      TraceMallocCloseLogFD,      1, 0},
-    {"TraceMallocLogTimestamp",    TraceMallocLogTimestamp,    1, 0},
-    {"TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0},
-    {nullptr,                       nullptr,                     0, 0}
+    JS_FS("TraceMallocDisable",         TraceMallocDisable,         0, 0),
+    JS_FS("TraceMallocEnable",          TraceMallocEnable,          0, 0),
+    JS_FS("TraceMallocOpenLogFile",     TraceMallocOpenLogFile,     1, 0),
+    JS_FS("TraceMallocChangeLogFD",     TraceMallocChangeLogFD,     1, 0),
+    JS_FS("TraceMallocCloseLogFD",      TraceMallocCloseLogFD,      1, 0),
+    JS_FS("TraceMallocLogTimestamp",    TraceMallocLogTimestamp,    1, 0),
+    JS_FS("TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0),
+    JS_FS_END
 };
 
 #endif /* NS_TRACE_MALLOC */
 
 #ifdef MOZ_JPROF
 
 #include <signal.h>
 
@@ -3947,18 +3937,17 @@ ReadSourceFromFilename(JSContext *cx, co
     return NS_ERROR_FAILURE;
   memcpy(*src, decoded.get(), decoded.Length()*sizeof(jschar));
 
   return NS_OK;
 }
 
 /*
   The JS engine calls this function when it needs the source for a chrome JS
-  function. See the comment in nsJSContext::nsJSContext about
-  JSOPTION_ONLY_CGN_SOURCE.
+  function. See the comment in nsJSRuntime::Init().
 */
 static bool
 SourceHook(JSContext *cx, JSScript *script, jschar **src, uint32_t *length)
 {
   *src = NULL;
   *length = 0;
 
   if (!nsContentUtils::IsCallerChrome())
@@ -3972,17 +3961,16 @@ SourceHook(JSContext *cx, JSScript *scri
   if (NS_FAILED(rv)) {
     xpc::Throw(cx, rv);
     return false;
   }
 
   return true;
 }
 
-
 //static
 nsresult
 nsJSRuntime::Init()
 {
   if (sIsInitialized) {
     if (!nsContentUtils::XPConnect())
       return NS_ERROR_NOT_AVAILABLE;
 
@@ -3995,31 +3983,52 @@ nsJSRuntime::Init()
 
   rv = CallGetService(kJSRuntimeServiceContractID, &sRuntimeService);
   // get the JSRuntime from the runtime svc, if possible
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = sRuntimeService->GetRuntime(&sRuntime);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // The JS engine needs to keep the source code around in order to implement
+  // Function.prototype.toSource(). It'd be nice to not have to do this for
+  // chrome code and simply stub out requests for source on it. Life is not so
+  // easy, unfortunately. Nobody relies on chrome toSource() working in core
+  // browser code, but chrome tests use it. The worst offenders are addons,
+  // which like to monkeypatch chrome functions by calling toSource() on them
+  // and using regular expressions to modify them. We avoid keeping most browser
+  // JS source code in memory by setting LAZY_SOURCE on JS::CompileOptions when
+  // compiling some chrome code. This causes the JS engine not save the source
+  // code in memory. When the JS engine is asked to provide the source for a
+  // function compiled with LAZY_SOURCE, it calls SourceHook to load it.
+  ///
+  // Note we do have to retain the source code in memory for scripts compiled in
+  // compileAndGo mode and compiled function bodies (from
+  // JS_CompileFunction*). In practice, this means content scripts and event
+  // handlers.
   JS_SetSourceHook(sRuntime, SourceHook);
 
   // Let's make sure that our main thread is the same as the xpcom main thread.
   NS_ASSERTION(NS_IsMainThread(), "bad");
 
   sPrevGCSliceCallback = js::SetGCSliceCallback(sRuntime, DOMGCSliceCallback);
 
   // Set up the structured clone callbacks.
   static JSStructuredCloneCallbacks cloneCallbacks = {
     NS_DOMReadStructuredClone,
     NS_DOMWriteStructuredClone,
     NS_DOMStructuredCloneError
   };
   JS_SetStructuredCloneCallbacks(sRuntime, &cloneCallbacks);
 
+  static js::DOMCallbacks DOMcallbacks = {
+    InstanceClassHasProtoAtDepth
+  };
+  SetDOMCallbacks(sRuntime, &DOMcallbacks);
+
   // Set these global xpconnect options...
   Preferences::RegisterCallback(MaxScriptRunTimePrefChangedCallback,
                                 "dom.max_script_run_time");
   MaxScriptRunTimePrefChangedCallback("dom.max_script_run_time", nullptr);
 
   Preferences::RegisterCallback(MaxScriptRunTimePrefChangedCallback,
                                 "dom.max_chrome_script_run_time");
   MaxScriptRunTimePrefChangedCallback("dom.max_chrome_script_run_time",
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -67,17 +67,18 @@ public:
                                            bool* aIsUndefined);
 
   virtual nsresult CompileScript(const PRUnichar* aText,
                                  PRInt32 aTextLength,
                                  nsIPrincipal *principal,
                                  const char *aURL,
                                  PRUint32 aLineNo,
                                  PRUint32 aVersion,
-                                 nsScriptObjectHolder<JSScript>& aScriptObject);
+                                 nsScriptObjectHolder<JSScript>& aScriptObject,
+                                 bool aSaveSource = false);
   virtual nsresult ExecuteScript(JSScript* aScriptObject,
                                  JSObject* aScopeObject,
                                  nsAString* aRetValue,
                                  bool* aIsUndefined);
 
   virtual nsresult CompileEventHandler(nsIAtom *aName,
                                        PRUint32 aArgCount,
                                        const char** aArgNames,
--- a/dom/bindings/BindingGen.py
+++ b/dom/bindings/BindingGen.py
@@ -35,21 +35,17 @@ def generate_binding_cpp(config, outputp
 def main():
 
     # Parse arguments.
     from optparse import OptionParser
     usagestring = "usage: %prog [header|cpp] configFile outputPrefix webIDLFile"
     o = OptionParser(usage=usagestring)
     o.add_option("--verbose-errors", action='store_true', default=False,
                  help="When an error happens, display the Python traceback.")
-    o.add_option("--use-jsop-accessors", action='store_true', default=False,
-                 dest='useJSOPAccessors',
-                 help="Use JSPropertyOps instead of JSNatives for getters and setters")
     (options, args) = o.parse_args()
-    Codegen.generateNativeAccessors = not options.useJSOPAccessors
 
     if len(args) != 4 or (args[0] != "header" and args[0] != "cpp"):
         o.error(usagestring)
     buildTarget = args[0]
     configFile = os.path.normpath(args[1])
     outputPrefix = args[2]
     webIDLFile = os.path.normpath(args[3])
 
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -237,17 +237,18 @@ CreateInterfacePrototypeObject(JSContext
 
   return ourProto;
 }
 
 JSObject*
 CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
                        JSObject* protoProto, JSClass* protoClass,
                        JSClass* constructorClass, JSNative constructor,
-                       unsigned ctorNargs, Prefable<JSFunctionSpec>* methods,
+                       unsigned ctorNargs, JSClass* instanceClass,
+                       Prefable<JSFunctionSpec>* methods,
                        Prefable<JSPropertySpec>* properties,
                        Prefable<ConstantSpec>* constants,
                        Prefable<JSFunctionSpec>* staticMethods, const char* name)
 {
   MOZ_ASSERT(protoClass || constructorClass || constructor,
              "Need at least one class or a constructor!");
   MOZ_ASSERT(!(methods || properties) || protoClass,
              "Methods or properties but no protoClass!");
@@ -259,16 +260,19 @@ CreateInterfaceObjects(JSContext* cx, JS
 
   JSObject* proto;
   if (protoClass) {
     proto = CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
                                            methods, properties, constants);
     if (!proto) {
       return NULL;
     }
+
+    js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
+                        JS::PrivateValue(instanceClass));
   }
   else {
     proto = NULL;
   }
 
   JSObject* interface;
   if (constructorClass || constructor) {
     interface = CreateInterfaceObject(cx, global, receiver, constructorClass,
@@ -318,16 +322,29 @@ DoHandleNewBindingWrappingFailure(JSCont
     xpcObjectHelper helper(value);
     return NativeInterface2JSObjectAndThrowIfFailed(lccx, cx, vp, helper, NULL,
                                                     true);
   }
 
   return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
 }
 
+// Can only be called with the immediate prototype of the instance object. Can
+// only be called on the prototype of an object known to be a DOM instance.
+JSBool
+InstanceClassHasProtoAtDepth(JSHandleObject protoObject, uint32_t protoID,
+                             uint32_t depth)
+{
+  JSClass* instanceClass = static_cast<JSClass*>(
+    js::GetReservedSlot(protoObject, DOM_PROTO_INSTANCE_CLASS_SLOT).toPrivate());
+  MOZ_ASSERT(IsDOMClass(instanceClass));
+  DOMJSClass* domClass = DOMJSClass::FromJSClass(instanceClass);
+  return (uint32_t)domClass->mInterfaceChain[depth] == protoID;
+}
+
 // Only set allowNativeWrapper to false if you really know you need it, if in
 // doubt use true. Setting it to false disables security wrappers.
 bool
 XPCOMObjectToJsval(JSContext* cx, JSObject* scope, xpcObjectHelper &helper,
                    const nsIID* iid, bool allowNativeWrapper, JS::Value* rval)
 {
   XPCLazyCallContext lccx(JS_CALLER, cx, scope);
 
@@ -426,21 +443,22 @@ XrayResolveProperty(JSContext* cx, JSObj
   for (size_t prefIdx = 0; prefIdx < methodCount; ++prefIdx) {
     MOZ_ASSERT(methods[prefIdx].specs);
     if (methods[prefIdx].enabled) {
       // Set i to be the index into our full list of ids/specs that we're
       // looking at now.
       size_t i = methods[prefIdx].specs - methodSpecs;
       for ( ; methodIds[i] != JSID_VOID; ++i) {
         if (id == methodIds[i]) {
-          JSFunction *fun = JS_NewFunctionById(cx, methodSpecs[i].call,
+          JSFunction *fun = JS_NewFunctionById(cx, methodSpecs[i].call.op,
                                                methodSpecs[i].nargs, 0,
                                                wrapper, id);
           if (!fun)
               return false;
+          SET_JITINFO(fun, methodSpecs[i].call.info);
           JSObject *funobj = JS_GetFunctionObject(fun);
           desc->value.setObject(*funobj);
           desc->attrs = methodSpecs[i].flags;
           desc->obj = wrapper;
           desc->setter = nullptr;
           desc->getter = nullptr;
           return true;
         }
@@ -451,20 +469,44 @@ XrayResolveProperty(JSContext* cx, JSObj
   for (size_t prefIdx = 0; prefIdx < attributeCount; ++prefIdx) {
     MOZ_ASSERT(attributes[prefIdx].specs);
     if (attributes[prefIdx].enabled) {
       // Set i to be the index into our full list of ids/specs that we're
       // looking at now.
       size_t i = attributes[prefIdx].specs - attributeSpecs;
       for ( ; attributeIds[i] != JSID_VOID; ++i) {
         if (id == attributeIds[i]) {
-          desc->attrs = attributeSpecs[i].flags;
+          // Because of centralization, we need to make sure we fault in the
+          // JitInfos as well. At present, until the JSAPI changes, the easiest
+          // way to do this is wrap them up as functions ourselves.
+          desc->attrs = attributeSpecs[i].flags & ~JSPROP_NATIVE_ACCESSORS;
+          // They all have getters, so we can just make it.
+          JSObject *global = JS_GetGlobalForObject(cx, wrapper);
+          JSFunction *fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].getter.op,
+                                           0, 0, global, NULL);
+          if (!fun)
+            return false;
+          SET_JITINFO(fun, attributeSpecs[i].getter.info);
+          JSObject *funobj = JS_GetFunctionObject(fun);
+          desc->getter = js::CastAsJSPropertyOp(funobj);
+          desc->attrs |= JSPROP_GETTER;
+          if (attributeSpecs[i].setter.op) {
+            // We have a setter! Make it.
+            fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].setter.op,
+                                 1, 0, global, NULL);
+            if (!fun)
+              return false;
+            SET_JITINFO(fun, attributeSpecs[i].setter.info);
+            funobj = JS_GetFunctionObject(fun);
+            desc->setter = js::CastAsJSStrictPropertyOp(funobj);
+            desc->attrs |= JSPROP_SETTER;
+          } else {
+            desc->setter = NULL;
+          }
           desc->obj = wrapper;
-          desc->setter = attributeSpecs[i].setter;
-          desc->getter = attributeSpecs[i].getter;
           return true;
         }
       }
     }
   }
 
   for (size_t prefIdx = 0; prefIdx < constantCount; ++prefIdx) {
     MOZ_ASSERT(constants[prefIdx].specs);
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -282,16 +282,18 @@ struct Prefable {
  *                  This is null if we should not create an interface object or
  *                  if it should be a function object.
  * constructor is the JSNative to use as a constructor.  If this is non-null, it
  *             should be used as a JSNative to back the interface object, which
  *             should be a Function.  If this is null, then we should create an
  *             object of constructorClass, unless that's also null, in which
  *             case we should not create an interface object at all.
  * ctorNargs is the length of the constructor function; 0 if no constructor
+ * instanceClass is the JSClass of instance objects for this class.  This can
+ *               be null if this is not a concrete proto.
  * methods and properties are to be defined on the interface prototype object;
  *                        these arguments are allowed to be null if there are no
  *                        methods or properties respectively.
  * constants are to be defined on the interface object and on the interface
  *           prototype object; allowed to be null if there are no constants.
  * staticMethods are to be defined on the interface object; allowed to be null
  *               if there are no static methods.
  *
@@ -302,17 +304,18 @@ struct Prefable {
  *
  * returns the interface prototype object if protoClass is non-null, else it
  * returns the interface object.
  */
 JSObject*
 CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* receiver,
                        JSObject* protoProto, JSClass* protoClass,
                        JSClass* constructorClass, JSNative constructor,
-                       unsigned ctorNargs, Prefable<JSFunctionSpec>* methods,
+                       unsigned ctorNargs, JSClass* instanceClass,
+                       Prefable<JSFunctionSpec>* methods,
                        Prefable<JSPropertySpec>* properties,
                        Prefable<ConstantSpec>* constants,
                        Prefable<JSFunctionSpec>* staticMethods, const char* name);
 
 template <class T>
 inline bool
 WrapNewBindingObject(JSContext* cx, JSObject* scope, T* value, JS::Value* vp)
 {
@@ -547,16 +550,22 @@ GetParentPointer(T* aObject)
 }
 
 inline nsISupports*
 GetParentPointer(const ParentObject& aObject)
 {
   return ToSupports(aObject.mObject);
 }
 
+// Can only be called with the immediate prototype of the instance object. Can
+// only be called on the prototype of an object known to be a DOM instance.
+JSBool
+InstanceClassHasProtoAtDepth(JSHandleObject protoObject, uint32_t protoID,
+                             uint32_t depth);
+
 // Only set allowNativeWrapper to false if you really know you need it, if in
 // doubt use true. Setting it to false disables security wrappers.
 bool
 XPCOMObjectToJsval(JSContext* cx, JSObject* scope, xpcObjectHelper &helper,
                    const nsIID* iid, bool allowNativeWrapper, JS::Value* rval);
 
 template<class T>
 inline bool
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -133,17 +133,18 @@ class CGPrototypeJSClass(CGThing):
         CGThing.__init__(self)
         self.descriptor = descriptor
     def declare(self):
         # We're purely for internal consumption
         return ""
     def define(self):
         return """
 static JSClass PrototypeClass = {
-  "%sPrototype", 0,
+  "%sPrototype",
+  JSCLASS_HAS_RESERVED_SLOTS(1),
   JS_PropertyStub,       /* addProperty */
   JS_PropertyStub,       /* delProperty */
   JS_PropertyStub,       /* getProperty */
   JS_StrictPropertyStub, /* setProperty */
   JS_EnumerateStub,
   JS_ResolveStub,
   JS_ConvertStub,
   NULL,                  /* finalize */
@@ -927,60 +928,60 @@ class MethodDefiner(PropertyDefiner):
     def generateArray(self, array, name, doIdArrays):
         if len(array) == 0:
             return ""
 
         def pref(m):
             return m["pref"]
 
         def specData(m):
-            return (m["name"], m["name"], m["length"], m["flags"])
+            isQI = (m["name"] == 'QueryInterface')
+            jitinfo = ("&%s_methodinfo" % m["name"]) if not isQI else "NULL"
+            accessor = "genericMethod" if not isQI else "QueryInterface"
+            return (m["name"], accessor, jitinfo, m["length"], m["flags"])
 
         return self.generatePrefableArray(
             array, name,
-            '  JS_FN("%s", %s, %s, %s)',
+            '  JS_FNINFO("%s", %s, %s, %s, %s)',
             '  JS_FS_END',
             'JSFunctionSpec',
             pref, specData, doIdArrays)
 
 class AttrDefiner(PropertyDefiner):
     def __init__(self, descriptor, name):
         PropertyDefiner.__init__(self, descriptor, name)
         self.name = name
         self.chrome = [m for m in descriptor.interface.members if m.isAttr()]
         self.regular = [m for m in self.chrome if not isChromeOnly(m)]
 
     def generateArray(self, array, name, doIdArrays):
         if len(array) == 0:
             return ""
 
         def flags(attr):
-            flags = "JSPROP_SHARED | JSPROP_ENUMERATE"
-            if generateNativeAccessors:
-                flags = "JSPROP_NATIVE_ACCESSORS | " + flags
-            elif attr.readonly:
-                return "JSPROP_READONLY | " + flags
-            return flags
+            return "JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS"
 
         def getter(attr):
-            return "get_" + attr.identifier.name
+            return ("{(JSPropertyOp)genericGetter, &%(name)s_getterinfo}"
+                    % {"name" : attr.identifier.name})
 
         def setter(attr):
             if attr.readonly:
-                return "NULL"
-            return "set_" + attr.identifier.name
+                return "JSOP_NULLWRAPPER"
+            return ("{(JSStrictPropertyOp)genericSetter, &%(name)s_setterinfo}"
+                    % {"name" : attr.identifier.name})
 
         def specData(attr):
             return (attr.identifier.name, flags(attr), getter(attr),
                     setter(attr))
 
         return self.generatePrefableArray(
             array, name,
-            '  { "%s", 0, %s, (JSPropertyOp)%s, (JSStrictPropertyOp)%s }',
-            '  { 0, 0, 0, 0, 0 }',
+            '  { "%s", 0, %s, %s, %s}',
+            '  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }',
             'JSPropertySpec',
             PropertyDefiner.getControllingPref, specData, doIdArrays)
 
 class ConstDefiner(PropertyDefiner):
     """
     A class for definining constants on the interface object
     """
     def __init__(self, descriptor, name):
@@ -1118,22 +1119,24 @@ class CGCreateInterfaceObjectsMethod(CGA
             constructHook = CONSTRUCT_HOOK_NAME
             constructArgs = methodLength(self.descriptor.interface.ctor())
         else:
             constructHook = "ThrowingConstructor"
             constructArgs = 0
 
         call = CGGeneric(("return dom::CreateInterfaceObjects(aCx, aGlobal, aReceiver, parentProto,\n"
                           "                                   %s, %s, %s, %d,\n"
+                          "                                   %s,\n"
                           "                                   %%(methods)s, %%(attrs)s, %%(consts)s, %%(staticMethods)s,\n"
                           "                                   %s);") % (
             "&PrototypeClass" if needInterfacePrototypeObject else "NULL",
             "&InterfaceObjectClass" if needInterfaceObjectClass else "NULL",
             constructHook if needConstructor else "NULL",
             constructArgs,
+            "&Class.mBase" if self.descriptor.concrete else "NULL",
             '"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL"))
 
         if self.properties.hasChromeOnly():
             if self.descriptor.workers:
                 accessCheck = "mozilla::dom::workers::GetWorkerPrivateFromContext(aCx)->IsChromeWorker()"
             else:
                 accessCheck = "xpc::AccessCheck::isChrome(js::GetObjectCompartment(aGlobal))"
             accessCheck = "if (" + accessCheck + ") {\n"
@@ -2397,16 +2400,18 @@ class CGArgumentConverter(CGThing):
 
 def getWrapTemplateForType(type, descriptorProvider, result, successCode,
                            isCreator):
     """
     Reflect a C++ value stored in "result", of IDL type "type" into JS.  The
     "successCode" is the code to run once we have successfully done the
     conversion.  The resulting string should be used with string.Template, it
     needs the following keys when substituting: jsvalPtr/jsvalRef/obj.
+
+    Returns (templateString, infallibility of conversion template)
     """
     haveSuccessCode = successCode is not None
     if not haveSuccessCode:
         successCode = "return true;"
 
     def setValue(value, callWrapValue=False):
         """
         Returns the code to set the jsval to value. If "callWrapValue" is true
@@ -2435,32 +2440,32 @@ def getWrapTemplateForType(type, descrip
             failureCode = "return false;"
         str = ("if (!%s) {\n" +
                CGIndenter(CGGeneric(failureCode)).define() + "\n" +
                "}\n" +
                successCode) % (wrapCall)
         return str
     
     if type is None or type.isVoid():
-        return setValue("JSVAL_VOID")
+        return (setValue("JSVAL_VOID"), True)
 
     if type.isArray():
         raise TypeError("Can't handle array return values yet")
 
     if type.isSequence():
         if type.nullable():
             # Nullable sequences are Nullable< nsTArray<T> >
-            return """
+            (recTemplate, recInfall) = getWrapTemplateForType(type.inner, descriptorProvider,
+                                                              "%s.Value()" % result, successCode,
+                                                              isCreator)
+            return ("""
 if (%s.IsNull()) {
 %s
 }
-%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(),
-         getWrapTemplateForType(type.inner, descriptorProvider,
-                                "%s.Value()" % result, successCode,
-                                isCreator))
+%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(), recTemplate), recInfall)
 
         # Now do non-nullable sequences.  We use setting the element
         # in the array as our succcess code because when we succeed in
         # wrapping that's what we should do.
         innerTemplate = wrapForType(
             type.inner, descriptorProvider,
             {
                 'result' :  "%s[i]" % result,
@@ -2469,26 +2474,26 @@ if (%s.IsNull()) {
                                 "  return false;\n"
                                 "}"),
                 'jsvalRef': "tmp",
                 'jsvalPtr': "&tmp",
                 'isCreator': isCreator
                 }
             )
         innerTemplate = CGIndenter(CGGeneric(innerTemplate)).define()
-        return ("""
+        return (("""
 uint32_t length = %s.Length();
 JSObject *returnArray = JS_NewArrayObject(cx, length, NULL);
 if (!returnArray) {
   return false;
 }
 jsval tmp;
 for (uint32_t i = 0; i < length; ++i) {
 %s
-}\n""" % (result, innerTemplate)) + setValue("JS::ObjectValue(*returnArray)")
+}\n""" % (result, innerTemplate)) + setValue("JS::ObjectValue(*returnArray)"), False)
 
     if type.isGeckoInterface():
         descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
         if type.nullable():
             wrappingCode = ("if (!%s) {\n" % (result) +
                             CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
                             "}\n")
         else:
@@ -2520,87 +2525,91 @@ for (uint32_t i = 0; i < length; ++i) {
             wrappingCode += wrapAndSetPtr(wrap, failed)
         else:
             if descriptor.notflattened:
                 getIID = "&NS_GET_IID(%s), " % descriptor.nativeType
             else:
                 getIID = ""
             wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID)
             wrappingCode += wrapAndSetPtr(wrap)
-        return wrappingCode
+        return (wrappingCode, False)
 
     if type.isString():
         if type.nullable():
-            return wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalPtr})" % result)
+            return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalPtr})" % result), False)
         else:
-            return wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr})" % result)
+            return (wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr})" % result), False)
 
     if type.isEnum():
         if type.nullable():
             raise TypeError("We don't support nullable enumerated return types "
                             "yet")
-        return """MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s));
+        return ("""MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s));
 JSString* %(resultStr)s = JS_NewStringCopyN(cx, %(strings)s[uint32_t(%(result)s)].value, %(strings)s[uint32_t(%(result)s)].length);
 if (!%(resultStr)s) {
   return false;
 }
 """ % { "result" : result,
         "resultStr" : result + "_str",
-        "strings" : type.inner.identifier.name + "Values::strings" } + setValue("JS::StringValue(%s_str)" % result)
+        "strings" : type.inner.identifier.name + "Values::strings" } +
+        setValue("JS::StringValue(%s_str)" % result), False)
 
     if type.isCallback():
         assert not type.isInterface()
         # XXXbz we're going to assume that callback types are always
         # nullable and always have [TreatNonCallableAsNull] for now.
         # See comments in WrapNewBindingObject explaining why we need
         # to wrap here.
-        return setValue("JS::ObjectOrNullValue(%s)" % result, True)
+        # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
+        return (setValue("JS::ObjectOrNullValue(%s)" % result, True), False)
 
     if type.tag() == IDLType.Tags.any:
         # See comments in WrapNewBindingObject explaining why we need
         # to wrap here.
-        return setValue(result, True)
+        # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
+        return (setValue(result, True), False)
 
     if type.isObject():
         # See comments in WrapNewBindingObject explaining why we need
         # to wrap here.
         if type.nullable():
             toValue = "JS::ObjectOrNullValue(%s)"
         else:
             toValue = "JS::ObjectValue(*%s)"
-        return setValue(toValue % result, True)
+        # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
+        return (setValue(toValue % result, True), False)
 
     if not type.isPrimitive():
         raise TypeError("Need to learn to wrap %s" % type)
 
     if type.nullable():
+        (recTemplate, recInfal) = getWrapTemplateForType(type.inner, descriptorProvider,
+                                                         "%s.Value()" % result, successCode,
+                                                         isCreator)
         return ("if (%s.IsNull()) {\n" % result +
                 CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
-                "}\n" +
-                getWrapTemplateForType(type.inner, descriptorProvider,
-                                       "%s.Value()" % result, successCode,
-                                       isCreator))
+                "}\n" + recTemplate, recInfal)
     
     tag = type.tag()
     
     if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
                IDLType.Tags.uint16, IDLType.Tags.int32]:
-        return setValue("INT_TO_JSVAL(int32_t(%s))" % result)
+        return (setValue("INT_TO_JSVAL(int32_t(%s))" % result), True)
 
     elif tag in [IDLType.Tags.int64, IDLType.Tags.uint64, IDLType.Tags.float,
                  IDLType.Tags.double]:
         # XXXbz will cast to double do the "even significand" thing that webidl
         # calls for for 64-bit ints?  Do we care?
-        return setValue("JS_NumberValue(double(%s))" % result)
+        return (setValue("JS_NumberValue(double(%s))" % result), True)
 
     elif tag == IDLType.Tags.uint32:
-        return setValue("UINT_TO_JSVAL(%s)" % result)
+        return (setValue("UINT_TO_JSVAL(%s)" % result), True)
 
     elif tag == IDLType.Tags.bool:
-        return setValue("BOOLEAN_TO_JSVAL(%s)" % result)
+        return (setValue("BOOLEAN_TO_JSVAL(%s)" % result), True)
 
     else:
         raise TypeError("Need to learn to wrap primitive: %s" % type)
 
 def wrapForType(type, descriptorProvider, templateValues):
     """
     Reflect a C++ value of IDL type "type" into JS.  TemplateValues is a dict
     that should contain:
@@ -2619,21 +2628,35 @@ def wrapForType(type, descriptorProvider
                                   the conversion, if not supplied 'return true;'
                                   will be used as the code
       * 'isCreator' (optional): If true, we're wrapping for the return value of
                                 a [Creator] method.  Assumed false if not set.
     """
     wrap = getWrapTemplateForType(type, descriptorProvider,
                                   templateValues.get('result', 'result'),
                                   templateValues.get('successCode', None),
-                                  templateValues.get('isCreator', False))
+                                  templateValues.get('isCreator', False))[0]
 
     defaultValues = {'obj': 'obj'}
     return string.Template(wrap).substitute(defaultValues, **templateValues)
 
+def infallibleForAttr(attr, descriptorProvider):
+    """
+    Determine the fallibility of changing a C++ value of IDL type "type" into
+    JS for the given attribute. Apart from isCreator, all the defaults are used,
+    since the fallbility does not change based on the boolean values,
+    and the template will be discarded.
+
+    CURRENT ASSUMPTIONS:
+        We assume that successCode for wrapping up return values cannot contain
+        failure conditions.
+    """
+    return getWrapTemplateForType(attr.type, descriptorProvider, 'result', None,\
+                                  memberIsCreator(attr))[1]
+
 def typeNeedsCx(type):
     return (type is not None and
             (type.isCallback() or type.isAny() or type.isObject() or
              (type.isUnion() and
               any(typeNeedsCx(t) for t in type.unroll().flatMemberTypes))))
 
 # Returns a CGThing containing the type of the return value, or None
 # if there is no need for a return value.
@@ -2818,17 +2841,17 @@ class CGPerSignatureCall(CGThing):
         return "\nJS::Value* argv = JS_ARGV(cx, vp);\n"
     def getArgc(self):
         return "argc"
 
     def isFallible(self):
         return not 'infallible' in self.extendedAttributes
 
     def wrap_return_value(self):
-        isCreator = self.idlNode.getExtendedAttribute("Creator") is not None
+        isCreator = memberIsCreator(self.idlNode)
         if isCreator:
             # We better be returning addrefed things!
             assert isResultAlreadyAddRefed(self.descriptor,
                                            self.extendedAttributes)
 
         resultTemplateValues = { 'jsvalRef': '*vp', 'jsvalPtr': 'vp',
                                  'isCreator': isCreator}
         try:
@@ -3124,84 +3147,49 @@ class CGMethodCall(CGThing):
             CGGeneric('MOZ_NOT_REACHED("We have an always-returning default case");\n'
                       'return false;'))
         self.cgRoot = CGWrapper(CGIndenter(CGList(overloadCGThings, "\n")),
                                 pre="\n")
 
     def define(self):
         return self.cgRoot.define()
 
-class CGGetterSetterCall(CGPerSignatureCall):
-    """
-    A class to generate a native object getter or setter call for a
-    particular IDL getter or setter.
-    """
-    def __init__(self, returnType, arguments, nativeMethodName, descriptor,
-                 attr, getter=False, setter=False):
-        assert bool(getter) != bool(setter)
-        CGPerSignatureCall.__init__(self, returnType, [], arguments,
-                                    nativeMethodName, False, descriptor, attr,
-                                    getter=getter, setter=setter)
-    def getArgv(self):
-        if generateNativeAccessors:
-            return CGPerSignatureCall.getArgv(self)
-        return "vp"
-
-class CGGetterCall(CGGetterSetterCall):
+class CGGetterCall(CGPerSignatureCall):
     """
     A class to generate a native object getter call for a particular IDL
     getter.
     """
     def __init__(self, returnType, nativeMethodName, descriptor, attr):
-        CGGetterSetterCall.__init__(self, returnType, [], nativeMethodName,
-                                    descriptor, attr, getter=True)
-    def getArgc(self):
-        if generateNativeAccessors:
-            return CGGetterSetterCall.getArgc()
-        return "0"
-    def getArgvDecl(self):
-        if generateNativeAccessors:
-            return CGPerSignatureCall.getArgvDecl(self)
-        # We just get our stuff from vp
-        return ""
+        CGPerSignatureCall.__init__(self, returnType, [], [],
+                                    nativeMethodName, False, descriptor,
+                                    attr, getter=True)
 
 class FakeArgument():
     def __init__(self, type):
         self.type = type
         self.optional = False
         self.variadic = False
         self.defaultValue = None
 
-class CGSetterCall(CGGetterSetterCall):
+class CGSetterCall(CGPerSignatureCall):
     """
     A class to generate a native object setter call for a particular IDL
     setter.
     """
     def __init__(self, argType, nativeMethodName, descriptor, attr):
-        CGGetterSetterCall.__init__(self, None, [FakeArgument(argType)],
-                                    nativeMethodName, descriptor, attr,
+        CGPerSignatureCall.__init__(self, None, [], [FakeArgument(argType)],
+                                    nativeMethodName, False, descriptor, attr,
                                     setter=True)
     def wrap_return_value(self):
-        if generateNativeAccessors:
-            return CGGetterSetterCall.wrap_return_value(self)
         # We have no return value
         return "\nreturn true;"
     def getArgc(self):
-        if generateNativeAccessors:
-            return CGGetterSetterCall.getArgc(self)
         return "1"
     def getArgvDecl(self):
-        if generateNativeAccessors:
-            return (CGPerSignatureCall.getArgvDecl(self) +
-                    "jsval undef = JS::UndefinedValue();\n"
-                    "if (argc == 0) {\n"
-                    "  argv = &undef;\n"
-                    "  argc = 1;\n"
-                    "}")
-        # We just get our stuff from vp
+        # We just get our stuff from our last arg no matter what
         return ""
 
 class FakeCastableDescriptor():
     def __init__(self, descriptor):
         self.castable = True
         self.workers = descriptor.workers
         self.nativeType = descriptor.nativeType
         self.name = descriptor.name
@@ -3226,100 +3214,191 @@ class CGAbstractBindingMethod(CGAbstract
             str(FailureFatalCastableObjectUnwrapper(
                         FakeCastableDescriptor(self.descriptor),
                         "obj", "self"))))
         return CGList([ self.getThis(), unwrapThis,
                         self.generate_code() ], "\n").define()
 
     def getThis(self):
         return CGIndenter(
-            CGGeneric("JSObject* obj = JS_THIS_OBJECT(cx, vp);\n"
+            CGGeneric("JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));\n"
                       "if (!obj) {\n"
                       "  return false;\n"
                       "}\n"
                       "\n"
                       "%s* self;" % self.descriptor.nativeType))
 
     def generate_code(self):
         assert(False) # Override me
 
 def MakeNativeName(name):
     return name[0].upper() + name[1:]
 
-class CGNativeMethod(CGAbstractBindingMethod):
+class CGGenericMethod(CGAbstractBindingMethod):
     """
     A class for generating the C++ code for an IDL method..
     """
+    def __init__(self, descriptor):
+        args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
+                Argument('JS::Value*', 'vp')]
+        CGAbstractBindingMethod.__init__(self, descriptor, 'genericMethod', args)
+
+    def generate_code(self):
+        return CGIndenter(CGGeneric(
+            "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
+            "JSJitMethodOp method = (JSJitMethodOp)info->op;\n"
+            "return method(cx, obj, self, argc, vp);"))
+
+class CGSpecializedMethod(CGAbstractStaticMethod):
+    """
+    A class for generating the C++ code for a specialized method that the JIT
+    can call with lower overhead.
+    """
     def __init__(self, descriptor, method):
         self.method = method
-        baseName = method.identifier.name
-        args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
-        CGAbstractBindingMethod.__init__(self, descriptor, baseName, args)
-    def generate_code(self):
+        name = method.identifier.name
+        args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
+                Argument('%s*' % descriptor.nativeType, 'self'),
+                Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')]
+        CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args)
+
+    def definition_body(self):
         name = self.method.identifier.name
         nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
         return CGMethodCall([], nativeName, self.method.isStatic(),
-                            self.descriptor, self.method)
-
-class CGNativeGetter(CGAbstractBindingMethod):
+                            self.descriptor, self.method).define()
+
+class CGGenericGetter(CGAbstractBindingMethod):
     """
     A class for generating the C++ code for an IDL attribute getter.
     """
+    def __init__(self, descriptor):
+        args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
+                Argument('JS::Value*', 'vp')]
+        CGAbstractBindingMethod.__init__(self, descriptor, 'genericGetter', args)
+
+    def generate_code(self):
+        return CGIndenter(CGGeneric(
+            "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
+            "JSJitPropertyOp getter = info->op;\n"
+            "return getter(cx, obj, self, vp);"))
+
+class CGSpecializedGetter(CGAbstractStaticMethod):
+    """
+    A class for generating the code for a specialized attribute getter
+    that the JIT can call with lower overhead.
+    """
     def __init__(self, descriptor, attr):
         self.attr = attr
         name = 'get_' + attr.identifier.name
-        if generateNativeAccessors:
-            args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
-                    Argument('JS::Value*', 'vp')]
-        else:
-            args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
-                    Argument('JSHandleId', 'id'), Argument('JS::Value*', 'vp')]
-        CGAbstractBindingMethod.__init__(self, descriptor, name, args)
-
-    def getThis(self):
-        if generateNativeAccessors:
-            return CGAbstractBindingMethod.getThis(self)
-        return CGIndenter(
-            CGGeneric("%s* self;" % self.descriptor.nativeType))
-
-    def generate_code(self):
+        args = [ Argument('JSContext*', 'cx'),
+                 Argument('JSHandleObject', 'obj'),
+                 Argument('%s*' % descriptor.nativeType, 'self'),
+                 Argument('JS::Value*', 'vp') ]
+        CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
+
+    def definition_body(self):
         name = self.attr.identifier.name
         nativeName = "Get" + MakeNativeName(self.descriptor.binaryNames.get(name, name))
-        return CGIndenter(CGGetterCall(self.attr.type, nativeName, self.descriptor,
-                                       self.attr))
-
-class CGNativeSetter(CGAbstractBindingMethod):
+        return CGIndenter(CGGetterCall(self.attr.type, nativeName,
+                                       self.descriptor, self.attr)).define()
+
+class CGGenericSetter(CGAbstractBindingMethod):
     """
     A class for generating the C++ code for an IDL attribute setter.
     """
+    def __init__(self, descriptor):
+        args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
+                Argument('JS::Value*', 'vp')]
+        CGAbstractBindingMethod.__init__(self, descriptor, 'genericSetter', args)
+
+    def generate_code(self):
+        return CGIndenter(CGGeneric(
+                "JS::Value* argv = JS_ARGV(cx, vp);\n"
+                "JS::Value undef = JS::UndefinedValue();\n"
+                "if (argc == 0) {\n"
+                "  argv = &undef;\n"
+                "}\n"
+                "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
+                "JSJitPropertyOp setter = info->op;\n"
+                "if (!setter(cx, obj, self, argv)) {\n"
+                "  return false;\n"
+                "}\n"
+                "*vp = JSVAL_VOID;\n"
+                "return true;"))
+
+class CGSpecializedSetter(CGAbstractStaticMethod):
+    """
+    A class for generating the code for a specialized attribute setter
+    that the JIT can call with lower overhead.
+    """
     def __init__(self, descriptor, attr):
         self.attr = attr
-        baseName = attr.identifier.name
         name = 'set_' + attr.identifier.name
-        if generateNativeAccessors:
-            args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
-                    Argument('JS::Value*', 'vp')]
-        else:
-            args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
-                    Argument('JSHandleId', 'id'), Argument('JSBool', 'strict'),
-                    Argument('JS::Value*', 'vp')]
-        CGAbstractBindingMethod.__init__(self, descriptor, name, args)
-
-    def getThis(self):
-        if generateNativeAccessors:
-            return CGAbstractBindingMethod.getThis(self)
-        return CGIndenter(
-            CGGeneric("%s* self;" % self.descriptor.nativeType))
-
-    def generate_code(self):
+        args = [ Argument('JSContext*', 'cx'),
+                 Argument('JSHandleObject', 'obj'),
+                 Argument('%s*' % descriptor.nativeType, 'self'),
+                 Argument('JS::Value*', 'argv')]
+        CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
+
+    def definition_body(self):
         name = self.attr.identifier.name
         nativeName = "Set" + MakeNativeName(self.descriptor.binaryNames.get(name, name))
-        return CGIndenter(CGSetterCall(self.attr.type, nativeName, self.descriptor,
-                                       self.attr))
+        return CGIndenter(CGSetterCall(self.attr.type, nativeName,
+                                       self.descriptor, self.attr)).define()
+
+def memberIsCreator(member):
+    return member.getExtendedAttribute("Creator") is not None
+
+class CGMemberJITInfo(CGThing):
+    """
+    A class for generating the JITInfo for a property that points to
+    our specialized getter and setter.
+    """
+    def __init__(self, descriptor, member):
+        self.member = member
+        self.descriptor = descriptor
+
+    def declare(self):
+        return ""
+
+    def defineJitInfo(self, infoName, opName, infallible):
+        protoID = "prototypes::id::%s" % self.descriptor.interface.identifier.name
+        depth = "PrototypeTraits<%s>::Depth" % protoID
+        failstr = "true" if infallible else "false"
+        return ("\n"
+                "const JSJitInfo %s = {\n"
+                "  %s,\n"
+                "  %s,\n"
+                "  %s,\n"
+                "  %s,  /* isInfallible. Only relevant for getters. */\n"
+                "  false  /* isConstant. Only relevant for getters. */\n"
+                "};\n" % (infoName, opName, protoID, depth, failstr))
+
+    def define(self):
+        if self.member.isAttr():
+            getterinfo = ("%s_getterinfo" % self.member.identifier.name)
+            getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name)
+            getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
+            getterinfal = getterinfal and infallibleForAttr(self.member, self.descriptor)
+            result = self.defineJitInfo(getterinfo, getter, getterinfal)
+            if not self.member.readonly:
+                setterinfo = ("%s_setterinfo" % self.member.identifier.name)
+                setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name)
+                # Setters are always fallible, since they have to do a typed unwrap.
+                result += self.defineJitInfo(setterinfo, setter, False)
+            return result
+        if self.member.isMethod():
+            methodinfo = ("%s_methodinfo" % self.member.identifier.name)
+            # Actually a JSJitMethodOp, but JSJitPropertyOp by struct definition.
+            method = ("(JSJitPropertyOp)%s" % self.member.identifier.name)
+            # Method, much like setters, are always fallible
+            result = self.defineJitInfo(methodinfo, method, False)
+            return result
+        raise TypeError("Illegal member type to CGPropertyJITInfo")
 
 def getEnumValueName(value):
     # Some enum values can be empty strings.  Others might have weird
     # characters in them.  Deal with the former by returning "_empty",
     # deal with possible name collisions from that by throwing if the
     # enum value is actually "_empty", and throw on any value
     # containing chars other than [a-z] or '-' for now. Replace '-' with '_'.
     value = value.replace('-', '_')
@@ -4047,24 +4126,33 @@ def stripTrailingWhitespace(text):
 class CGDescriptor(CGThing):
     def __init__(self, descriptor):
         CGThing.__init__(self)
 
         assert not descriptor.concrete or descriptor.interface.hasInterfacePrototypeObject()
 
         cgThings = []
         if descriptor.interface.hasInterfacePrototypeObject():
-            cgThings.extend([CGNativeMethod(descriptor, m) for m in
-                             descriptor.interface.members if
-                             m.isMethod() and not m.isStatic()])
-            cgThings.extend([CGNativeGetter(descriptor, a) for a in
-                             descriptor.interface.members if a.isAttr()])
-            cgThings.extend([CGNativeSetter(descriptor, a) for a in
-                             descriptor.interface.members if
-                             a.isAttr() and not a.readonly])
+            hasMethod, hasGetter, hasSetter = False, False, False
+            for m in descriptor.interface.members:
+                if m.isMethod() and not m.isStatic():
+                    cgThings.append(CGSpecializedMethod(descriptor, m))
+                    cgThings.append(CGMemberJITInfo(descriptor, m))
+                    hasMethod = True
+                elif m.isAttr():
+                    cgThings.append(CGSpecializedGetter(descriptor, m))
+                    hasGetter = True
+                    if not m.readonly:
+                        cgThings.append(CGSpecializedSetter(descriptor, m))
+                        hasSetter = True
+                    cgThings.append(CGMemberJITInfo(descriptor, m))
+            if hasMethod: cgThings.append(CGGenericMethod(descriptor))
+            if hasGetter: cgThings.append(CGGenericGetter(descriptor))
+            if hasSetter: cgThings.append(CGGenericSetter(descriptor))
+
 
         if descriptor.concrete:
             if not descriptor.workers and descriptor.wrapperCache:
                 cgThings.append(CGAddPropertyHook(descriptor))
 
             # Always have a finalize hook, regardless of whether the class wants a
             # custom hook.
             cgThings.append(CGClassFinalizeHook(descriptor))
--- a/dom/bindings/DOMJSClass.h
+++ b/dom/bindings/DOMJSClass.h
@@ -18,16 +18,21 @@
 // All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. We have to
 // start at 1 past JSCLASS_GLOBAL_SLOT_COUNT because XPConnect uses
 // that one.
 #define DOM_PROTOTYPE_SLOT (JSCLASS_GLOBAL_SLOT_COUNT + 1)
 
 // We use these flag bits for the new bindings.
 #define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1
 
+// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
+// LSetDOMProperty. Those constants need to be changed accordingly if this value
+// changes.
+#define DOM_PROTO_INSTANCE_CLASS_SLOT 0
+
 namespace mozilla {
 namespace dom {
 
 typedef bool
 (* ResolveProperty)(JSContext* cx, JSObject* wrapper, jsid id, bool set,
                     JSPropertyDescriptor* desc);
 typedef bool
 (* EnumerateProperties)(JS::AutoIdVector& props);
--- a/dom/bindings/GlobalGen.py
+++ b/dom/bindings/GlobalGen.py
@@ -34,21 +34,17 @@ def main():
     # Parse arguments.
     from optparse import OptionParser
     usageString = "usage: %prog [options] webidldir [files]"
     o = OptionParser(usage=usageString)
     o.add_option("--cachedir", dest='cachedir', default=None,
                  help="Directory in which to cache lex/parse tables.")
     o.add_option("--verbose-errors", action='store_true', default=False,
                  help="When an error happens, display the Python traceback.")
-    o.add_option("--use-jsop-accessors", action='store_true', default=False,
-                 dest='useJSOPAccessors',
-                 help="Use JSPropertyOps instead of JSNatives for getters and setters")
     (options, args) = o.parse_args()
-    Codegen.generateNativeAccessors = not options.useJSOPAccessors
 
     if len(args) < 2:
         o.error(usageString)
 
     configFile = args[0]
     baseDir = args[1]
     fileList = args[2:]
 
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -11,25 +11,16 @@ FAIL_ON_WARNINGS := 1
 MODULE           = dom
 LIBRARY_NAME     = dombindings_s
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY   = 1
 
 include $(topsrcdir)/config/config.mk
 
-# Define USE_JSOP_ACCESSORS to a nonempty string like "yes" to use them
-USE_JSOP_ACCESSORS = 
-ifdef USE_JSOP_ACCESSORS
-DEFINES += -DUSE_JSOP_ACCESSORS
-ACCESSOR_OPT = --use-jsop-accessors
-else
-ACCESSOR_OPT =
-endif
-
 # Need this to find all our DOM source files.
 include $(topsrcdir)/dom/dom-config.mk
 
 include $(topsrcdir)/dom/webidl/WebIDL.mk
 
 binding_include_path := mozilla/dom
 all_webidl_files = $(webidl_files)
 # Set exported_binding_headers before adding the test IDL to the mix
@@ -101,26 +92,26 @@ bindinggen_dependencies := \
 $(test_webidl_files): %: $(srcdir)/test/%
 	$(INSTALL) $(IFLAGS1) $(srcdir)/test/$* .
 
 $(binding_header_files): %Binding.h: $(bindinggen_dependencies) \
                                      %.webidl \
                                      $(NULL)
 	PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  $(PLY_INCLUDE) -I$(srcdir)/parser \
-	  $(srcdir)/BindingGen.py $(ACCESSOR_OPT) header \
+	  $(srcdir)/BindingGen.py header \
 	  $(srcdir)/Bindings.conf $*Binding \
 	  $*.webidl
 
 $(binding_cpp_files): %Binding.cpp: $(bindinggen_dependencies) \
                                     %.webidl \
                                     $(NULL)
 	PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  $(PLY_INCLUDE) -I$(srcdir)/parser \
-	  $(srcdir)/BindingGen.py $(ACCESSOR_OPT) cpp \
+	  $(srcdir)/BindingGen.py cpp \
 	  $(srcdir)/Bindings.conf $*Binding \
 	  $*.webidl
 
 $(globalgen_targets): ParserResults.pkl
 
 CACHE_DIR = _cache
 
 globalgen_dependencies := \
@@ -136,17 +127,17 @@ globalgen_dependencies := \
 $(CACHE_DIR)/.done:
 	$(MKDIR) -p $(CACHE_DIR)
 	@$(TOUCH) $@
 
 ParserResults.pkl: $(globalgen_dependencies) \
                    $(all_webidl_files)
 	PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
     $(PLY_INCLUDE) -I$(srcdir)/parser \
-    $(srcdir)/GlobalGen.py $(ACCESSOR_OPT) $(srcdir)/Bindings.conf . \
+    $(srcdir)/GlobalGen.py $(srcdir)/Bindings.conf . \
     --cachedir=$(CACHE_DIR) \
     $(all_webidl_files)
 
 GARBAGE += \
   $(binding_header_files) \
   $(binding_cpp_files) \
   $(all_webidl_files) \
   $(globalgen_targets) \
--- a/dom/bluetooth/BluetoothManager.cpp
+++ b/dom/bluetooth/BluetoothManager.cpp
@@ -8,29 +8,26 @@
 #include "BluetoothManager.h"
 #include "BluetoothCommon.h"
 #include "BluetoothAdapter.h"
 #include "BluetoothService.h"
 #include "BluetoothTypes.h"
 #include "BluetoothReplyRunnable.h"
 
 #include "nsContentUtils.h"
-#include "mozilla/Preferences.h"
 #include "nsIDOMDOMRequest.h"
+#include "nsIPermissionManager.h"
 #include "nsDOMClassInfo.h"
 #include "nsDOMEvent.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMCIDInternal.h"
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/Util.h"
 
-#define DOM_BLUETOOTH_URL_PREF "dom.mozBluetooth.whitelist"
-
 using namespace mozilla;
-using mozilla::Preferences;
 
 USING_BLUETOOTH_NAMESPACE
 
 DOMCI_DATA(BluetoothManager, BluetoothManager)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothManager,
@@ -271,30 +268,47 @@ BluetoothManager::Create(nsPIDOMWindow* 
 }
 
 nsresult
 NS_NewBluetoothManager(nsPIDOMWindow* aWindow,
                        nsIDOMBluetoothManager** aBluetoothManager)
 {
   NS_ASSERTION(aWindow, "Null pointer!");
 
-  bool allowed;
-  nsresult rv = nsContentUtils::IsOnPrefWhitelist(aWindow, DOM_BLUETOOTH_URL_PREF, &allowed);
+  nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ?
+    aWindow :
+    aWindow->GetCurrentInnerWindow();
+
+  // Need the document for security check.
+  nsCOMPtr<nsIDocument> document = innerWindow->GetExtantDoc();
+  NS_ENSURE_TRUE(document, NS_NOINTERFACE);
+
+  nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
+  NS_ENSURE_TRUE(principal, NS_ERROR_UNEXPECTED);
+
+  nsCOMPtr<nsIPermissionManager> permMgr =
+    do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+  NS_ENSURE_TRUE(permMgr, NS_ERROR_UNEXPECTED);
+
+  PRUint32 permission;
+  nsresult rv =
+    permMgr->TestPermissionFromPrincipal(principal, "mozBluetooth", &permission);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (!allowed) {
+  if (permission != nsIPermissionManager::ALLOW_ACTION) {
     *aBluetoothManager = nullptr;
     return NS_OK;
   }
 
   nsRefPtr<BluetoothManager> bluetoothManager = BluetoothManager::Create(aWindow);
   if (!bluetoothManager) {
     NS_ERROR("Cannot create bluetooth manager!");
     return NS_ERROR_FAILURE;
   }
+
   bluetoothManager.forget(aBluetoothManager);
   return NS_OK;
 }
 
 void
 BluetoothManager::Notify(const BluetoothSignal& aData)
 {
 #ifdef DEBUG
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -182,16 +182,21 @@ public:
    *
    * @return True if path set correctly, false otherwise
    */
   virtual bool
   GetDevicePath(const nsAString& aAdapterPath,
                 const nsAString& aDeviceAddress,
                 nsAString& aDevicePath) = 0;
 
+  virtual int
+  GetDeviceServiceChannelInternal(const nsAString& aObjectPath,
+                                  const nsAString& aPattern,
+                                  int aAttributeId) = 0;
+
 protected:
   BluetoothService()
   {
     mBluetoothSignalObserverTable.Init();
   }
 
   virtual ~BluetoothService()
   {
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -333,17 +333,19 @@ GetProperty(DBusMessageIter aIter, Prope
           s = NS_ConvertUTF8toUTF16(tmp);
           arr.AppendElement(s);
         } while (dbus_message_iter_next(&array_val_iter));
         propertyValue = arr;
       } else {
         // This happens when the array is 0-length. Apparently we get a
         // DBUS_TYPE_INVALID type.
         propertyValue = InfallibleTArray<nsString>();
+#ifdef DEBUG
         NS_WARNING("Received array type that's not a string array!");
+#endif
       }
       break;
     default:
       NS_NOTREACHED("Cannot find dbus message type!");
   }
   aProperties.AppendElement(BluetoothNamedValue(propertyName, propertyValue));
   return true;
 }
@@ -600,25 +602,41 @@ BluetoothDBusService::StartInternal()
   MOZ_ASSERT(!NS_IsMainThread());
   
   if (!StartDBus()) {
     NS_WARNING("Cannot start DBus thread!");
     return NS_ERROR_FAILURE;
   }
   
   if (mConnection) {
-    return NS_OK;    
+    return NS_OK;
   }
 
   if (NS_FAILED(EstablishDBusConnection())) {
     NS_WARNING("Cannot start DBus connection!");
     StopDBus();
     return NS_ERROR_FAILURE;
   }
-	
+
+  DBusError err;
+  dbus_error_init(&err);
+
+  // Set which messages will be processed by this dbus connection.
+  // Since we are maintaining a single thread for all the DBus bluez
+  // signals we want, register all of them in this thread at startup.
+  // The event handler will sort the destinations out as needed.
+  for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
+    dbus_bus_add_match(mConnection,
+                       sBluetoothDBusSignals[i],
+                       &err);
+    if (dbus_error_is_set(&err)) {
+      LOG_AND_FREE_DBUS_ERROR(&err);
+    }
+  }
+
   // Add a filter for all incoming messages_base
   if (!dbus_connection_add_filter(mConnection, EventFilter,
                                   NULL, NULL)) {
     NS_WARNING("Cannot create DBus Event Filter for DBus Thread!");
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
@@ -629,17 +647,30 @@ BluetoothDBusService::StopInternal()
 {
   // This could block. It should never be run on the main thread.
   MOZ_ASSERT(!NS_IsMainThread());
   
   if (!mConnection) {
     StopDBus();
     return NS_OK;
   }
-  dbus_connection_remove_filter(mConnection, EventFilter, NULL);
+
+  DBusError err;
+  dbus_error_init(&err);
+  for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
+    dbus_bus_remove_match(mConnection,
+                          sBluetoothDBusSignals[i],
+                          &err);
+    if (dbus_error_is_set(&err)) {
+      LOG_AND_FREE_DBUS_ERROR(&err);
+    }
+  }
+
+  dbus_connection_remove_filter(mConnection, EventFilter, nullptr);
+  
   mConnection = nullptr;
   mBluetoothSignalObserverTable.Clear();
   StopDBus();
   return NS_OK;
 }
 
 nsresult
 BluetoothDBusService::GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable)
@@ -832,8 +863,29 @@ GetObjectPathFromAddress(const nsAString
 bool
 BluetoothDBusService::GetDevicePath(const nsAString& aAdapterPath,
                                     const nsAString& aDeviceAddress,
                                     nsAString& aDevicePath)
 {
   aDevicePath = GetObjectPathFromAddress(aAdapterPath, aDeviceAddress);
   return true;
 }
+
+int
+BluetoothDBusService::GetDeviceServiceChannelInternal(const nsAString& aObjectPath,
+                                                      const nsAString& aPattern,
+                                                      int aAttributeId)
+{
+  // This is a blocking call, should not be run on main thread.
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  const char* deviceObjectPath = NS_ConvertUTF16toUTF8(aObjectPath).get();
+  const char* pattern = NS_ConvertUTF16toUTF8(aPattern).get();
+
+  DBusMessage *reply =
+    dbus_func_args(mConnection, deviceObjectPath,
+                   DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
+                   DBUS_TYPE_STRING, &pattern,
+                   DBUS_TYPE_UINT16, &aAttributeId,
+                   DBUS_TYPE_INVALID);
+
+  return reply ? dbus_returns_int32(reply) : -1;
+}
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -39,16 +39,20 @@ public:
   SetProperty(BluetoothObjectType aType,
               const nsAString& aPath,
               const BluetoothNamedValue& aValue,
               BluetoothReplyRunnable* aRunnable);
   virtual bool
   GetDevicePath(const nsAString& aAdapterPath,
                 const nsAString& aDeviceAddress,
                 nsAString& aDevicePath);
+  virtual int
+  GetDeviceServiceChannelInternal(const nsAString& aObjectPath,
+                                  const nsAString& aPattern,
+                                  int aAttributeId);
 
 private:
   nsresult SendGetPropertyMessage(const nsAString& aPath,
                                   const char* aInterface,
                                   void (*aCB)(DBusMessage *, void *),
                                   BluetoothReplyRunnable* aRunnable);
   nsresult SendDiscoveryMessage(const nsAString& aAdapterPath,
                                 const char* aMessageName,
--- a/dom/browser-element/BrowserElementScrolling.js
+++ b/dom/browser-element/BrowserElementScrolling.js
@@ -112,33 +112,51 @@ const ContentPanning = {
   },
 
   getPannable: function cp_getPannable(node) {
     if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML')
       return [null, null];
 
     let nodeContent = node.ownerDocument.defaultView;
     while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
-      if (node.scrollHeight > node.clientHeight ||
-          node.scrollWidth > node.clientWidth ||
-          ('scrollLeftMax' in node && node.scrollLeftMax > 0) ||
-          ('scrollTopMax' in node && node.scrollTopMax > 0)) {
+      let style = nodeContent.getComputedStyle(node, null);
+
+      let overflow = [style.getPropertyValue('overflow'),
+                      style.getPropertyValue('overflow-x'),
+                      style.getPropertyValue('overflow-y')];
+
+      let rect = node.getBoundingClientRect();
+      let isAuto = (overflow.indexOf('auto') != -1 &&
+                   (rect.height < node.scrollHeight ||
+                    rect.width < node.scrollWidth));
+
+      let isScroll = (overflow.indexOf('scroll') != -1);
+
+      let isScrollableTextarea = (node.tagName == 'TEXTAREA' &&
+          (node.scrollHeight > node.clientHeight ||
+           node.scrollWidth > node.clientWidth ||
+           ('scrollLeftMax' in node && node.scrollLeftMax > 0) ||
+           ('scrollTopMax' in node && node.scrollTopMax > 0)));
+      if (isScroll || isAuto || isScrollableTextarea)
         return [node, this._generateCallback(node)];
-      }
 
       node = node.parentNode;
     }
 
     if (ContentPanning._asyncPanZoomForViewportFrame &&
         nodeContent === content)
       // The parent context is asynchronously panning and zooming our
       // root scrollable frame, so don't use our synchronous fallback.
       return [null, null];
 
-    return [nodeContent, this._generateCallback(nodeContent)];
+    if (nodeContent.scrollMaxX || nodeContent.scrollMaxY) {
+      return [nodeContent, this._generateCallback(nodeContent)];
+    }
+
+    return [null, null];
   },
 
   _generateCallback: function cp_generateCallback(content) {
     function scroll(delta) {
       if (content instanceof Ci.nsIDOMHTMLElement) {
         let oldX = content.scrollLeft, oldY = content.scrollTop;
         content.scrollLeft += delta.x;
         content.scrollTop += delta.y;
--- a/dom/camera/DOMCameraManager.cpp
+++ b/dom/camera/DOMCameraManager.cpp
@@ -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/. */
 
 #include "CameraControl.h"
 #include "DOMCameraManager.h"
 #include "nsDOMClassInfo.h"
 #include "DictionaryHelpers.h"
 
-#define DOM_CAMERA_LOG_LEVEL  3
+#define DOM_CAMERA_LOG_LEVEL  DOM_CAMERA_LOG_NOTHING
 #include "CameraCommon.h"
 
 using namespace mozilla;
 
 DOMCI_DATA(CameraManager, nsIDOMCameraManager)
 
 NS_INTERFACE_MAP_BEGIN(nsDOMCameraManager)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -163,16 +163,31 @@ Contact.prototype = {
             aField[i] = String(aField[i]);
         }
         return aField;
       } else if (aField != null) {
         return [String(aField)];
       }
     };
 
+    function _checkBlobArray(aBlob) {
+      if (Array.isArray(aBlob)) {
+        for (let i = 0; i < aBlob.length; i++) {
+          if (typeof aBlob != 'object') {
+            return null;
+          }
+          if (!(aBlob[i] instanceof Components.interfaces.nsIDOMBlob)) {
+            return null;
+          }
+        }
+        return aBlob;
+      }
+      return null;
+    };
+
     this.name =            _create(aProp.name) || null;
     this.honorificPrefix = _create(aProp.honorificPrefix) || null;
     this.givenName =       _create(aProp.givenName) || null;
     this.additionalName =  _create(aProp.additionalName) || null;
     this.familyName =      _create(aProp.familyName) || null;
     this.honorificSuffix = _create(aProp.honorificSuffix) || null;
     this.nickname =        _create(aProp.nickname) || null;
 
@@ -180,17 +195,17 @@ Contact.prototype = {
       aProp.email = Array.isArray(aProp.email) ? aProp.email : [aProp.email];
       this.email = new Array();
       for (let i = 0; i < aProp.email.length; i++)
         this.email.push(new ContactEmail(aProp.email[i].type, aProp.email[i].address));
     } else {
       this.email = null;
     }
 
-    this.photo =           _create(aProp.photo) || null;
+    this.photo =           _checkBlobArray(aProp.photo) || null;
     this.url =             _create(aProp.url) || null;
     this.category =        _create(aProp.category) || null;
 
     if (aProp.adr) {
       // Make sure adr argument is an array. Instanceof doesn't work.
       aProp.adr = Array.isArray(aProp.adr) ? aProp.adr : [aProp.adr];
 
       this.adr = new Array();
--- a/dom/contacts/tests/Makefile.in
+++ b/dom/contacts/tests/Makefile.in
@@ -12,12 +12,13 @@ relativesrcdir   = @relativesrcdir@
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = \
   $(NULL)
 
 MOCHITEST_FILES = \
   test_contacts_basics.html \
   test_contacts_events.html \
+  test_contacts_blobs.html \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/dom/contacts/tests/test_contacts_basics.html
+++ b/dom/contacts/tests/test_contacts_basics.html
@@ -94,17 +94,16 @@ var properties2 = {
   tel: [{type: "test", number: "123456789"},{type: "home", number: "234567890"}],
   email: [{type: "test", address: "a@b.c"}, {address: "b@c.d"}],
   adr: [adr1, adr2],
   impp: ["im1", "im2"],
   org: ["org1", "org2"],
   jobTitle: ["boss", "superboss"],
   bday: new Date("1980, 12, 01"),
   note: "test note",
-  photo: ["pic1", "pic2"],
   category: ["cat1", "cat2"],
   url: ["www.1.com", "www.2.com"],
   anniversary: new Date("2000, 12, 01"),
   sex: "male",
   genderIdentity: "test"
 };
 
 var sample_id1;
@@ -160,17 +159,16 @@ function checkEmail(email1, email2) {
 function checkContacts(contact1, contact2) {
   checkStr(contact1.name, contact2.name, "Same name");
   checkStr(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
   checkStr(contact1.givenName, contact2.givenName, "Same givenName");
   checkStr(contact1.additionalName, contact2.additionalName, "Same additionalName");
   checkStr(contact1.familyName, contact2.familyName, "Same familyName");
   checkStr(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
   checkStr(contact1.nickname, contact2.nickname, "Same nickname");
-  checkStr(contact1.photo, contact2.photo, "Same photo");
   checkStr(contact1.url, contact2.url, "Same url");
   checkStr(contact1.category, contact2.category, "Same category");
   checkStr(contact1.org, contact2.org, "Same org");
   checkStr(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
   is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
   checkStr(contact1.note, contact2.note, "Same note");
   checkStr(contact1.impp, contact2.impp, "Same impp");
   is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
new file mode 100644
--- /dev/null
+++ b/dom/contacts/tests/test_contacts_blobs.html
@@ -0,0 +1,324 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id={674720}
+-->
+<head>
+  <title>Test for Bug {674720} WebContacts</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={674720}">Mozilla Bug {674720}</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+"use strict";
+
+var comp = SpecialPowers.wrap(Components);
+comp.utils.import("resource://gre/modules/ContactService.jsm");
+SpecialPowers.setBoolPref("dom.mozContacts.enabled", true);
+SpecialPowers.addPermission("contacts", true, document);
+
+var utils = SpecialPowers.getDOMWindowUtils(window);
+
+function getView(size)
+{
+ var buffer = new ArrayBuffer(size);
+ var view = new Uint8Array(buffer);
+ is(buffer.byteLength, size, "Correct byte length");
+ return view;
+}
+
+function getRandomView(size)
+{
+ var view = getView(size);
+ for (var i = 0; i < size; i++) {
+   view[i] = parseInt(Math.random() * 255)
+ }
+ return view;
+}
+
+function getBlob(type, view)
+{
+  return utils.getBlob([view], {type: type});
+}
+
+function getRandomBlob(size)
+{
+  return getBlob("binary/random", getRandomView(size));
+}
+
+function compareBuffers(buffer1, buffer2)
+{
+  if (buffer1.byteLength != buffer2.byteLength) {
+    return false;
+  }
+  var view1 = new Uint8Array(buffer1);
+  var view2 = new Uint8Array(buffer2);
+  for (var i = 0; i < buffer1.byteLength; i++) {
+    if (view1[i] != view2[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+function verifyBuffers(buffer1, buffer2, isLast)
+{
+  ok(compareBuffers(buffer1, buffer2), "Correct blob data");
+  if (isLast)
+    next();
+}
+
+var randomBlob = getRandomBlob(1024);
+var randomBlob2 = getRandomBlob(1024);
+
+var properties1 = {
+  name: "xTestname1",
+  photo: [randomBlob]
+};
+
+var properties2 = {
+  name: "yTestname2",
+  photo: [randomBlob, randomBlob2]
+};
+
+var sample_id1;
+var createResult1;
+var findResult1;
+
+function onUnwantedSuccess() {
+  ok(false, "onUnwantedSuccess: shouldn't get here");
+}
+
+function onFailure() {
+  ok(false, "in on Failure!");
+}
+
+function verifyBlob(blob1, blob2, isLast)
+{
+  dump("islast? " + isLast + "\n");
+  is(blob1 instanceof Components.interfaces.nsIDOMBlob, true,
+     "Instance of nsIDOMBlob");
+  is(blob1 instanceof Components.interfaces.nsIDOMFile,
+     blob2 instanceof Components.interfaces.nsIDOMFile,
+     "Instance of nsIDOMFile");
+  is(blob1.size, blob2.size, "Correct size");
+  is(blob1.type, blob2.type, "Correct type");
+
+  var buffer1;
+  var buffer2;
+
+  var reader1 = new FileReader();
+  reader1.readAsArrayBuffer(blob2);
+  reader1.onload = function(event) {
+    buffer2 = event.target.result;
+    if (buffer1) {
+      verifyBuffers(buffer1, buffer2, isLast);
+    }
+  }
+  
+  var reader2 = new FileReader();
+  reader2.readAsArrayBuffer(blob1);
+  reader2.onload = function(event) {
+    buffer1 = event.target.result;
+    if (buffer2) {
+      verifyBuffers(buffer1, buffer2, isLast);
+    }
+  }
+}
+
+function verifyBlobArray(blobs1, blobs2)
+{
+  is(blobs1 instanceof Array, true, "Got an array object");
+  is(blobs1.length, blobs2.length, "Correct length");
+
+  if (!blobs1.length) {
+    next();
+    return;
+  }
+
+  for (var i = 0; i < blobs1.length; i++)
+    verifyBlob(blobs1[i], blobs2[i], i == blobs1.length - 1);
+}
+
+
+var req;
+var index = 0;
+
+var mozContacts = window.navigator.mozContacts
+
+var steps = [
+  function () {
+    ok(true, "Deleting database");
+    req = mozContacts.clear();
+    req.onsuccess = function () {
+      ok(true, "Deleted the database");
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Adding contact with photo");
+    createResult1 = new mozContact();
+    createResult1.init(properties1);
+    dump("CreateResult1: " + JSON.stringify(createResult1));
+    req = navigator.mozContacts.save(createResult1);
+    req.onsuccess = function () {
+      ok(createResult1.id, "The contact now has an ID.");
+      sample_id1 = createResult1.id;
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Retrieving by substring");
+    var options = {filterBy: ["name"],
+                   filterOp: "contains",
+                   filterValue: properties1.name.substring(0,3)};
+    req = mozContacts.find(options);
+    req.onsuccess = function () {
+      ok(req.result.length == 1, "Found exactly 1 contact.");
+      findResult1 = req.result[0];
+      ok(findResult1.id == sample_id1, "Same ID");
+      verifyBlobArray(createResult1.photo, properties1.photo);
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Adding contact with 2 photos");
+    createResult1 = new mozContact();
+    createResult1.init(properties2);
+    dump("CreateResult1: " + JSON.stringify(createResult1));
+    req = navigator.mozContacts.save(createResult1);
+    req.onsuccess = function () {
+      ok(createResult1.id, "The contact now has an ID.");
+      sample_id1 = createResult1.id;
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Retrieving by substring");
+    var options = {filterBy: ["name"],
+                   filterOp: "contains",
+                   filterValue: properties2.name.substring(0,3)};
+    req = mozContacts.find(options);
+    req.onsuccess = function () {
+      ok(req.result.length == 1, "Found exactly 1 contact.");
+      findResult1 = req.result[0];
+      ok(findResult1.id == sample_id1, "Same ID");
+      verifyBlobArray(createResult1.photo, properties2.photo);
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Adding photo as String");
+    createResult1 = new mozContact();
+    createResult1.init({name: "asdf", photo: ["xyz"]});
+    dump("CreateResult1: " + JSON.stringify(createResult1));
+    req = navigator.mozContacts.save(createResult1);
+    req.onsuccess = function () {
+      ok(createResult1.id, "The contact now has an ID.");
+      sample_id1 = createResult1.id;
+      is(createResult1.photo, null, "No photo")
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Adding photo as String");
+    createResult1 = new mozContact();
+    createResult1.init({name: "jkl", photo: "xyz"});
+    dump("CreateResult1: " + JSON.stringify(createResult1));
+    req = navigator.mozContacts.save(createResult1);
+    req.onsuccess = function () {
+      ok(createResult1.id, "The contact now has an ID.");
+      is(createResult1.photo, null, "No photo")
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Retrieving by substring");
+    var options = {filterBy: ["name"],
+                   filterOp: "contains",
+                   filterValue: "asdf"};
+    req = mozContacts.find(options);
+    req.onsuccess = function () {
+      ok(req.result.length == 1, "Found exactly 1 contact.");
+      findResult1 = req.result[0];
+      ok(findResult1.id == sample_id1, "Same ID");
+      is(findResult1.photo, null, "No photo");
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Adding photo as Object");
+    createResult1 = new mozContact();
+    createResult1.init({photo: [{}]});
+    dump("CreateResult1: " + JSON.stringify(createResult1));
+    req = navigator.mozContacts.save(createResult1);
+    req.onsuccess = function () {
+      ok(createResult1.id, "The contact now has an ID.");
+      is(createResult1.photo, null, "No photo")
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Deleting database");
+    req = mozContacts.clear()
+    req.onsuccess = function () {
+      ok(true, "Deleted the database");
+      next();
+    }
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "all done!\n");
+
+    SimpleTest.finish();
+  }
+];
+
+function next() {
+  ok(true, "Begin!");
+  if (index >= steps.length) {
+    ok(false, "Shouldn't get here!");
+    return;
+  }
+  try {
+    steps[index]();
+  } catch(ex) {
+    ok(false, "Caught exception", ex);
+  }
+  index += 1;
+}
+
+function permissionTest() {
+  if (gContactsEnabled) {
+    next();
+  } else {
+    is(mozContacts, null, "mozContacts is null when not enabled.");
+    SimpleTest.finish();
+  }
+}
+
+var gContactsEnabled = SpecialPowers.getBoolPref("dom.mozContacts.enabled");
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(permissionTest);
+
+ok(true, "test passed");
+</script>
+</pre>
+</body>
+</html>
\ No newline at end of file
--- a/dom/indexedDB/FileManager.cpp
+++ b/dom/indexedDB/FileManager.cpp
@@ -36,17 +36,18 @@ EnumerateToTArray(const PRUint64& aKey,
 
   return PL_DHASH_NEXT;
 }
 
 } // anonymous namespace
 
 nsresult
 FileManager::Init(nsIFile* aDirectory,
-                  mozIStorageConnection* aConnection)
+                  mozIStorageConnection* aConnection,
+                  FactoryPrivilege aPrivilege)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
   mFileInfos.Init();
 
   bool exists;
   nsresult rv = aDirectory->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -98,18 +99,20 @@ FileManager::Init(nsIFile* aDirectory,
     nsCOMPtr<nsIFile> file;
     rv = aDirectory->Clone(getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = file->Append(name);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (flag) {
-      rv = ss->UpdateQuotaInformationForFile(file);
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (aPrivilege != Chrome) {
+        rv = ss->UpdateQuotaInformationForFile(file);
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
     }
     else {
       rv = file->Remove(false);
       if (NS_FAILED(rv)) {
         NS_WARNING("Failed to remove orphaned file!");
       }
     }
   }
--- a/dom/indexedDB/FileManager.h
+++ b/dom/indexedDB/FileManager.h
@@ -55,17 +55,18 @@ public:
   }
 
   bool Invalidated() const
   {
     return mInvalidated;
   }
 
   nsresult Init(nsIFile* aDirectory,
-                mozIStorageConnection* aConnection);
+                mozIStorageConnection* aConnection,
+                FactoryPrivilege aPrivilege);
 
   nsresult Load(mozIStorageConnection* aConnection);
 
   nsresult Invalidate();
 
   already_AddRefed<nsIFile> GetDirectory();
 
   already_AddRefed<FileInfo> GetFileInfo(PRInt64 aId);
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -728,17 +728,17 @@ IndexedDatabaseManager::SetCurrentWindow
 PRUint32
 IndexedDatabaseManager::GetIndexedDBQuotaMB()
 {
   return PRUint32(NS_MAX(gIndexedDBQuotaMB, 0));
 }
 
 nsresult
 IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
-                                                  FactoryPrivilege mPrivilege,
+                                                  FactoryPrivilege aPrivilege,
                                                   nsIFile** aDirectory)
 {
 #ifdef DEBUG
   {
     bool correctThread;
     NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) &&
                  correctThread,
                  "Running on the wrong thread!");
@@ -781,17 +781,17 @@ IndexedDatabaseManager::EnsureOriginIsIn
   rv = patternFile->GetNativePath(pattern);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Now tell SQLite to start tracking this pattern for content.
   nsCOMPtr<mozIStorageServiceQuotaManagement> ss =
     do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE);
 
-  if (mPrivilege != Chrome) {
+  if (aPrivilege != Chrome) {
     rv = ss->SetQuotaForFilenamePattern(pattern,
                                         GetIndexedDBQuotaMB() * 1024 * 1024,
                                         mQuotaCallbackSingleton, nsnull);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // We need to see if there are any files in the directory already. If they
   // are database files then we need to create file managers for them and also
@@ -873,22 +873,22 @@ IndexedDatabaseManager::EnsureOriginIsIn
     }
 
     nsString databaseName;
     rv = stmt->GetString(0, databaseName);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsRefPtr<FileManager> fileManager = new FileManager(aOrigin, databaseName);
 
-    rv = fileManager->Init(fileManagerDirectory, connection);
+    rv = fileManager->Init(fileManagerDirectory, connection, aPrivilege);
     NS_ENSURE_SUCCESS(rv, rv);
 
     fileManagers->AppendElement(fileManager);
 
-    if (mPrivilege != Chrome) {
+    if (aPrivilege != Chrome) {
       rv = ss->UpdateQuotaInformationForFile(file);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     validSubdirs.PutEntry(dbBaseFilename);
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -1686,17 +1686,17 @@ OpenDatabaseHelper::DoDatabaseWork()
   if (mCurrentVersion != mRequestedVersion) {
     mState = eSetVersionPending;
   }
 
   mFileManager = mgr->GetOrCreateFileManager(mASCIIOrigin, mName);
   NS_ENSURE_TRUE(mFileManager, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   if (!mFileManager->Inited()) {
-    rv = mFileManager->Init(fileManagerDirectory, connection);
+    rv = mFileManager->Init(fileManagerDirectory, connection, mPrivilege);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   }
 
   if (!mFileManager->Loaded()) {
     rv = mFileManager->Load(connection);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   }
 
--- a/dom/interfaces/contacts/nsIDOMContactProperties.idl
+++ b/dom/interfaces/contacts/nsIDOMContactProperties.idl
@@ -49,17 +49,17 @@ interface nsIDOMContactProperties : nsIS
   attribute jsval         name;               // DOMString[]
   attribute jsval         honorificPrefix;    // DOMString[]
   attribute jsval         givenName;          // DOMString[]
   attribute jsval         additionalName;     // DOMString[]
   attribute jsval         familyName;         // DOMString[]
   attribute jsval         honorificSuffix;    // DOMString[]
   attribute jsval         nickname;           // DOMString[]
   attribute jsval         email;              // ContactEmail[]
-  attribute jsval         photo;              // DOMString[]
+  attribute jsval         photo;              // nsIDOMBlob[]
   attribute jsval         url;                // DOMString[]
   attribute jsval         category;           // DOMString[]
   attribute jsval         adr;                // ContactAddress[]
   attribute jsval         tel;                // ContactTelephone[]
   attribute jsval         org;                // DOMString[]
   attribute jsval         jobTitle;           // DOMString[]
   attribute jsval         bday;               // Date
   attribute jsval         note;               // DOMString[]
--- a/dom/ipc/AudioParent.cpp
+++ b/dom/ipc/AudioParent.cpp
@@ -292,19 +292,17 @@ AudioParent::SendWriteDone()
   return true;
 }
 
 AudioParent::AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat)
   : mIPCOpen(true)
 {
   mStream = nsAudioStream::AllocateStream();
   NS_ASSERTION(mStream, "AudioStream allocation failed.");
-  if (NS_FAILED(mStream->Init(aNumChannels,
-                              aRate,
-                              (nsAudioStream::SampleFormat) aFormat))) {
+  if (NS_FAILED(mStream->Init(aNumChannels, aRate))) {
       NS_WARNING("AudioStream initialization failed.");
       mStream = nullptr;
       return;
   }
 
   mTimer = do_CreateInstance("@mozilla.org/timer;1");
   mTimer->InitWithCallback(this, 1000, nsITimer::TYPE_REPEATING_SLACK);
 }
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -484,23 +484,19 @@ ContentParent::ContentParent(const nsASt
     // PID along with the warning.
     nsDebugImpl::SetMultiprocessMode("Parent");
 
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content);
 
     bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
     if (useOffMainThreadCompositing) {
-        // FIXME.  Oh please fixme.  Somehow.
-        //
-        // We need the child process's ProcessHandle to do
-        // PCompositor::Open() below (on win32 ... sigh).  We don't
-        // get that until onconnect, but that's too late to open the
-        // compositor channel below.
-        mSubprocess->SyncLaunch();
+        // We need the subprocess's ProcessHandle to create the
+        // PCompositor channel below.  Block just until we have that.
+        mSubprocess->LaunchAndWaitForProcessHandle();
     } else {
         mSubprocess->AsyncLaunch();
     }
     Open(mSubprocess->GetChannel(), mSubprocess->GetChildProcessHandle());
     unused << SendSetID(gContentChildID++);
 
     // NB: internally, this will send an IPC message to the child
     // process to get it to create the CompositorChild.  This
--- a/dom/locales/en-US/chrome/layout/css.properties
+++ b/dom/locales/en-US/chrome/layout/css.properties
@@ -109,16 +109,17 @@ PEMQExpectedExpressionStart=Expected '('
 PEMQExpressionEOF=contents of media query expression
 PEMQExpectedFeatureName=Expected media feature name but found '%1$S'.
 PEMQExpectedFeatureNameEnd=Expected ':' or ')' after media feature name but found '%1$S'.
 PEMQNoMinMaxWithoutValue=Media features with min- or max- must have a value.
 PEMQExpectedFeatureValue=Found invalid value for media feature.
 PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'.
 PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'.
 PEAnonBoxNotAlone=Did not expect anonymous box.
+PEBadDirValue=Expected 'ltr' or 'rtl' in direction selector but found '%1$S'.
 PESupportsConditionStartEOF='not' or '('
 PESupportsConditionInParensStartEOF='not', '(' or identifier
 PESupportsConditionNotEOF='not'
 PESupportsConditionExpectedOpenParen=Expected '(' while parsing supports condition but found '%1$S'.
 PESupportsConditionExpectedCloseParen=Expected ')' while parsing supports condition but found '%1$S'.
 PESupportsConditionExpectedStart=Expected 'not' or '(' while parsing supports condition but found '%1$S'.
 PESupportsConditionExpectedNot=Expected 'not' while parsing supports condition but found '%1$S'.
 PESupportsGroupRuleStart=Expected '{' to begin @supports rule but found '%1$S'.
--- a/dom/network/interfaces/nsIDOMMobileConnection.idl
+++ b/dom/network/interfaces/nsIDOMMobileConnection.idl
@@ -217,21 +217,29 @@ interface nsIDOMMozMobileConnection : ns
 
   /**
    * The 'ussdreceived' event is notified whenever a new USSD message is
    * received.
    */
   attribute nsIDOMEventListener onussdreceived;
 };
 
-[scriptable, uuid(46321d6e-bbce-4b7b-aa32-d17b6aa984fe)]
+[scriptable, uuid(6601c20e-337f-4286-8d6e-0990fc1c2372)]
 interface nsIDOMMozMobileConnectionInfo : nsISupports
 {
   /**
-   * Indicates whether the device is connected to a mobile network.
+   * State of the connection.
+   *
+   * Possible values: 'notSearching', 'searching', 'denied', 'registered'.
+   * null if the state is unknown.
+   */
+  readonly attribute DOMString state;
+
+  /**
+   * Indicates whether the connection is ready. This may be different 
    */
   readonly attribute bool connected;
 
   /**
    * Indicates whether only emergency calls are possible.
    *
    * This flag is only relevant to voice connections and when 'connected' is
    * false.
--- a/dom/network/tests/marionette/manifest.ini
+++ b/dom/network/tests/marionette/manifest.ini
@@ -1,5 +1,10 @@
 
 [test_mobile_networks.js]
 b2g = true
 browser = false
 qemu = true
+
+[test_mobile_voice_state.js]
+b2g = true
+browser = false
+qemu = true
--- a/dom/network/tests/marionette/test_mobile_networks.js
+++ b/dom/network/tests/marionette/test_mobile_networks.js
@@ -1,11 +1,10 @@
-/* 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/. */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // getNetworks() can take some time..
 MARIONETTE_TIMEOUT = 60000;
  
 const WHITELIST_PREF = "dom.mobileconnection.whitelist";
 let uriPrePath = window.location.protocol + "//" + window.location.host;
 SpecialPowers.setCharPref(WHITELIST_PREF, uriPrePath);
 
@@ -30,25 +29,27 @@ function isTelkilaNetwork(network) {
   is(network.shortName, "TelKila");
   is(network.mcc, 310);
   is(network.mnc, 295);
 }
 
 function testConnectionInfo() {
   let voice = connection.voice;
   is(voice.connected, true);
+  is(voice.state, "registered");
   is(voice.emergencyCallsOnly, false);
   is(voice.roaming, false);
   isAndroidNetwork(voice.network);
 
   let data = connection.data;
-  // TODO Bug 762959: enable these checks when data state updates are implemented
-  // is(data.connected, true);
-  // is(data.emergencyCallsOnly, false);
-  // is(data.roaming, false);
+  // data.connected = true means there's an active data call which we
+  // can't predict here.
+  is(data.state, "registered");
+  is(data.emergencyCallsOnly, false);
+  is(data.roaming, false);
   isAndroidNetwork(data.network);
 
   testGetNetworks();
 }
 
 function testGetNetworks() {
   let request = connection.getNetworks();
   ok(request instanceof DOMRequest,
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/marionette/test_mobile_voice_state.js
@@ -0,0 +1,115 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 30000;
+
+const WHITELIST_PREF = "dom.mobileconnection.whitelist";
+let uriPrePath = window.location.protocol + "//" + window.location.host;
+SpecialPowers.setCharPref(WHITELIST_PREF, uriPrePath);
+
+let connection = navigator.mozMobileConnection;
+ok(connection instanceof MozMobileConnection,
+   "connection is instanceof " + connection.constructor);
+
+function setEmulatorVoiceState(state) {
+  runEmulatorCmd("gsm voice " + state, function (result) {
+    is(result[0], "OK");
+  });
+}
+
+function testConnectionInfo() {
+  let voice = connection.voice;
+  is(voice.connected, true);
+  is(voice.state, "registered");
+  is(voice.emergencyCallsOnly, false);
+  is(voice.roaming, false);
+
+  testUnregistered();
+}
+
+function testUnregistered() {
+  setEmulatorVoiceState("unregistered");
+
+  connection.addEventListener("voicechange", function onvoicechange() {
+    connection.removeEventListener("voicechange", onvoicechange);
+
+    is(connection.voice.connected, false);
+    is(connection.voice.state, "notSearching");
+    is(connection.voice.emergencyCallsOnly, false);
+    is(connection.voice.roaming, false);
+
+    testSearching();
+  });
+}
+
+function testSearching() {
+  // For some reason, requesting the "searching" state puts the fake modem
+  // into "registered"... Skipping this test for now.
+  testDenied();
+  return;
+
+  setEmulatorVoiceState("searching");
+
+  connection.addEventListener("voicechange", function onvoicechange() {
+    connection.removeEventListener("voicechange", onvoicechange);
+
+    is(connection.voice.connected, false);
+    is(connection.voice.state, "searching");
+    is(connection.voice.emergencyCallsOnly, false);
+    is(connection.voice.roaming, false);
+
+    testDenied();
+  });
+}
+
+function testDenied() {
+  setEmulatorVoiceState("denied");
+
+  connection.addEventListener("voicechange", function onvoicechange() {
+    connection.removeEventListener("voicechange", onvoicechange);
+
+    is(connection.voice.connected, false);
+    is(connection.voice.state, "denied");
+    is(connection.voice.emergencyCallsOnly, false);
+    is(connection.voice.roaming, false);
+
+    testRoaming();
+  });
+}
+
+function testRoaming() {
+  setEmulatorVoiceState("roaming");
+
+  connection.addEventListener("voicechange", function onvoicechange() {
+    connection.removeEventListener("voicechange", onvoicechange);
+
+    is(connection.voice.connected, true);
+    is(connection.voice.state, "registered");
+    is(connection.voice.emergencyCallsOnly, false);
+    is(connection.voice.roaming, true);
+
+    testHome();
+  });
+}
+
+function testHome() {
+  setEmulatorVoiceState("home");
+
+  connection.addEventListener("voicechange", function onvoicechange() {
+    connection.removeEventListener("voicechange", onvoicechange);
+
+    is(connection.voice.connected, true);
+    is(connection.voice.state, "registered");
+    is(connection.voice.emergencyCallsOnly, false);
+    is(connection.voice.roaming, false);
+
+    cleanUp();
+  });
+}
+
+function cleanUp() {
+  SpecialPowers.clearUserPref(WHITELIST_PREF);
+  finish();
+}
+
+testConnectionInfo();
--- a/dom/settings/SettingsManager.js
+++ b/dom/settings/SettingsManager.js
@@ -139,34 +139,34 @@ SettingsLock.prototype = {
   },
 
   get: function get(aName) {
     if (!this._open) {
       dump("Settings lock not open!\n");
       throw Components.results.NS_ERROR_ABORT;
     }
 
-    if (this._settingsManager.hasReadPrivileges || this._settingsManager.hasReadWritePrivileges) {
+    if (this._settingsManager.hasPrivileges) {
       let req = Services.DOMRequest.createRequest(this._settingsManager._window);
       this._requests.enqueue({ request: req, intent:"get", name: aName });
       this.createTransactionAndProcess();
       return req;
     } else {
       debug("get not allowed");
       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
     }
   },
 
   set: function set(aSettings) {
     if (!this._open) {
       dump("Settings lock not open!\n");
       throw Components.results.NS_ERROR_ABORT;
     }
 
-    if (this._settingsManager.hasReadWritePrivileges) {
+    if (this._settingsManager.hasPrivileges) {
       let req = Services.DOMRequest.createRequest(this._settingsManager._window);
       debug("send: " + JSON.stringify(aSettings));
       this._requests.enqueue({request: req, intent: "set", settings: aSettings});
       this.createTransactionAndProcess();
       return req;
     } else {
       debug("set not allowed");
       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@@ -174,17 +174,17 @@ SettingsLock.prototype = {
   },
 
   clear: function clear() {
     if (!this._open) {
       dump("Settings lock not open!\n");
       throw Components.results.NS_ERROR_ABORT;
     }
 
-    if (this._settingsManager.hasReadWritePrivileges) {
+    if (this._settingsManager.hasPrivileges) {
       let req = Services.DOMRequest.createRequest(this._settingsManager._window);
       this._requests.enqueue({ request: req, intent: "clear"});
       this.createTransactionAndProcess();
       return req;
     } else {
       debug("clear not allowed");
       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
     }
@@ -222,17 +222,17 @@ SettingsManager.prototype = {
   nextTick: function nextTick(aCallback, thisObj) {
     if (thisObj)
       aCallback = aCallback.bind(thisObj);
 
     Services.tm.currentThread.dispatch(aCallback, Ci.nsIThread.DISPATCH_NORMAL);
   },
 
   set onsettingchange(aCallback) {
-    if (this.hasReadPrivileges || this.hasReadWritePrivileges)
+    if (this.hasPrivileges)
       this._onsettingchange = aCallback;
     else
       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
   },
 
   get onsettingchange() {
     return this._onsettingchange;
   },
@@ -312,27 +312,19 @@ SettingsManager.prototype = {
       return null;
 
     cpmm.addMessageListener("Settings:Change:Return:OK", this);
     this._window = aWindow;
     Services.obs.addObserver(this, "inner-window-destroyed", false);
     let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     this.innerWindowID = util.currentInnerWindowID;
 
-    let principal = aWindow.document.nodePrincipal;
-    let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
-    let readPerm = principal == secMan.getSystemPrincipal()
-                     ? Ci.nsIPermissionManager.ALLOW_ACTION
-                     : Services.perms.testExactPermissionFromPrincipal(principal, "websettings-read");
-    let readwritePerm = principal == secMan.getSystemPrincipal()
-                          ? Ci.nsIPermissionManager.ALLOW_ACTION
-                          : Services.perms.testExactPermissionFromPrincipal(principal, "websettings-readwrite");
-    this.hasReadPrivileges = readPerm == Ci.nsIPermissionManager.ALLOW_ACTION;
-    this.hasReadWritePrivileges = readwritePerm == Ci.nsIPermissionManager.ALLOW_ACTION;
-    debug("has read privileges :" + this.hasReadPrivileges + ", has read-write privileges: " + this.hasReadWritePrivileges);
+    let perm = Services.perms.testExactPermissionFromPrincipal(aWindow.document.nodePrincipal, "settings");
+    this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
+    debug("has privileges :" + this.hasPrivileges);
   },
 
   observe: function(aSubject, aTopic, aData) {
     debug("Topic: " + aTopic);
     if (aTopic == "inner-window-destroyed") {
       let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
       if (wId == this.innerWindowID) {
         Services.obs.removeObserver(this, "inner-window-destroyed");
--- a/dom/settings/tests/test_settings_basics.html
+++ b/dom/settings/tests/test_settings_basics.html
@@ -19,18 +19,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 "use strict";
 
 var comp = SpecialPowers.wrap(Components);
 comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm");
 SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
-SpecialPowers.addPermission("websettings-read", true, document);
-SpecialPowers.addPermission("websettings-readwrite", true, document);
+SpecialPowers.addPermission("settings", true, document);
 
 function onUnwantedSuccess() {
   ok(false, "onUnwantedSuccess: shouldn't get here");
 }
 
 function onFailure() {
   ok(false, "in on Failure!");
 }
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -80,16 +80,17 @@ MobileConnectionInfo.prototype = {
     classDescription: "MobileConnectionInfo",
     flags:            Ci.nsIClassInfo.DOM_OBJECT,
     interfaces:       [Ci.nsIDOMMozMobileConnectionInfo]
   }),
 
   // nsIDOMMozMobileConnectionInfo
 
   connected: false,
+  state: null,
   emergencyCallsOnly: false,
   roaming: false,
   network: null,
   type: null,
   signalStrength: null,
   relSignalStrength: null
 };
 
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -441,148 +441,136 @@ RadioInterfaceLayer.prototype = {
 
   updateNetworkInfo: function updateNetworkInfo(message) {
     let voiceMessage = message[RIL.NETWORK_INFO_VOICE_REGISTRATION_STATE];
     let dataMessage = message[RIL.NETWORK_INFO_DATA_REGISTRATION_STATE];
     let operatorMessage = message[RIL.NETWORK_INFO_OPERATOR];
     let selectionMessage = message[RIL.NETWORK_INFO_NETWORK_SELECTION_MODE];
 
     // Batch the *InfoChanged messages together
-    let voiceInfoChanged = false;
     if (voiceMessage) {
       voiceMessage.batch = true;
-      voiceInfoChanged = this.updateVoiceConnection(voiceMessage);
+      this.updateVoiceConnection(voiceMessage);
     }
 
     let dataInfoChanged = false;
     if (dataMessage) {
       dataMessage.batch = true;
-      dataInfoChanged = this.updateDataConnection(dataMessage);
+      this.updateDataConnection(dataMessage);
     }
 
     let voice = this.rilContext.voice;
     let data = this.rilContext.data;
     if (operatorMessage) {
       if (this.networkChanged(operatorMessage, voice.network)) {
-        voiceInfoChanged = true;
         voice.network = operatorMessage;
       }
-
       if (this.networkChanged(operatorMessage, data.network)) {
-        dataInfoChanged = true;
         data.network = operatorMessage;
       }
     }
 
-    if (voiceInfoChanged) {
+    if (voiceMessage || operatorMessage) {
       ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voice);
     }
-    if (dataInfoChanged) {
+    if (dataMessage || operatorMessage) {
       ppmm.sendAsyncMessage("RIL:DataInfoChanged", data);
     }
 
     if (selectionMessage) {
       this.updateNetworkSelectionMode(selectionMessage);
     }
   },
 
   /**
    * Sends the RIL:VoiceInfoChanged message when the voice
    * connection's state has changed.
    *
-   * @param state The new voice connection state. When state.batch is true,
-   *              the RIL:VoiceInfoChanged message will not be sent.
-   * @return Whether or not this.radioState.voice was updated
+   * @param newInfo The new voice connection information. When newInfo.batch is true,
+   *                the RIL:VoiceInfoChanged message will not be sent.
    */
-  updateVoiceConnection: function updateVoiceConnection(state) {
+  updateVoiceConnection: function updateVoiceConnection(newInfo) {
     let voiceInfo = this.rilContext.voice;
-    let regState = state.regState;
-    voiceInfo.type = "gsm"; //TODO see bug 726098.
-    if (!state || regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
-      voiceInfo.connected = false;
-      voiceInfo.emergencyCallsOnly = false;
-      voiceInfo.roaming = false;
+    voiceInfo.state = newInfo.state;
+    voiceInfo.connected = newInfo.connected;
+    voiceInfo.roaming = newInfo.roaming;
+    voiceInfo.emergencyCallsOnly = newInfo.emergencyCallsOnly;
+    // Unlike the data registration info, the voice info typically contains
+    // no (useful) radio tech information, so we have to manually set
+    // this here. (TODO GSM only for now, see bug 726098.)
+    voiceInfo.type = "gsm";
+
+    // Make sure we also reset the operator and signal strength information
+    // if we drop off the network.
+    if (newInfo.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
       voiceInfo.network = null;
-      voiceInfo.type = null;
       voiceInfo.signalStrength = null;
       voiceInfo.relSignalStrength = null;
-      ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
-      return false;
     }
 
-    let isRoaming = regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING;
-    let isHome = regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME;
-    let isConnected = isRoaming || isHome;
-    let radioTech = RIL.GECKO_RADIO_TECH[state.radioTech] || null;
-
-    // Ensure that we check for changes before sending the message
-    if (voiceInfo.emergencyCallsOnly != state.emergencyCallsOnly ||
-        voiceInfo.connected != isConnected ||
-        voiceInfo.roaming != isRoaming ||
-        voiceInfo.type != radioTech) {
-
-      voiceInfo.emergencyCallsOnly = state.emergencyCallsOnly;
-      voiceInfo.connected = isConnected;
-      voiceInfo.roaming = isRoaming;
-      voiceInfo.type = radioTech;
-
-      // When batch is true, hold off on firing VoiceInfoChanged events
-      if (!state.batch) {
-        ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
-      }
-      return true;
+    if (!newInfo.batch) {
+      ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
     }
-    return false;
   },
 
-  updateDataConnection: function updateDataConnection(state) {
-    let data = this.rilContext.data;
-    if (!state || state.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
-      data.connected = false;
-      data.emergencyCallsOnly = false;
-      data.roaming = false;
-      data.network = null;
-      data.type = null;
-      data.signalStrength = null;
-      data.relSignalStrength = null;
-      ppmm.sendAsyncMessage("RIL:DataInfoChanged", data);
-      return false;
+  updateDataConnection: function updateDataConnection(newInfo) {
+    let dataInfo = this.rilContext.data;
+    dataInfo.state = newInfo.state;
+    dataInfo.roaming = newInfo.roaming;
+    dataInfo.emergencyCallsOnly = newInfo.emergencyCallsOnly;
+    dataInfo.type = newInfo.type;
+    // For the data connection, the `connected` flag indicates whether
+    // there's an active data call.
+    dataInfo.connected = RILNetworkInterface.connected;
+
+    // Make sure we also reset the operator and signal strength information
+    // if we drop off the network.
+    if (newInfo.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) {
+      dataInfo.network = null;
+      dataInfo.signalStrength = null;
+      dataInfo.relSignalStrength = null;
     }
-    data.roaming =
-      (state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING);
-    data.type = RIL.GECKO_RADIO_TECH[state.radioTech] || null;
-    ppmm.sendAsyncMessage("RIL:DataInfoChanged", data);
+
+    if (!newInfo.batch) {
+      ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo);
+    }
 
     if (!this.dataCallSettings["enabled"]) {
-      return false;
+      return;
     }
 
     let isRegistered =
-      state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME ||
-        (this.dataCallSettings["roaming_enabled"] &&
-         state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING);
+      newInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED &&
+      (!newInfo.roaming || this._isDataRoamingEnabled());
     let haveDataConnection =
-      state.radioTech != RIL.NETWORK_CREG_TECH_UNKNOWN;
+      newInfo.type != GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
 
     if (isRegistered && haveDataConnection) {
       debug("Radio is ready for data connection.");
       this.updateRILNetworkInterface();
     }
-    return false;
   },
 
   handleSignalStrengthChange: function handleSignalStrengthChange(message) {
+    let voiceInfo = this.rilContext.voice;
     // TODO CDMA, EVDO, LTE, etc. (see bug 726098)
-    this.rilContext.voice.signalStrength = message.gsmDBM;
-    this.rilContext.voice.relSignalStrength = message.gsmRelative;
-    ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", this.rilContext.voice);
+    if (voiceInfo.signalStrength != message.gsmDBM ||
+        voiceInfo.relSignalStrength != message.gsmRelative) {
+      voiceInfo.signalStrength = message.gsmDBM;
+      voiceInfo.relSignalStrength = message.gsmRelative;
+      ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
+    }
 
-    this.rilContext.data.signalStrength = message.gsmDBM;
-    this.rilContext.data.relSignalStrength = message.gsmRelative;
-    ppmm.sendAsyncMessage("RIL:DataInfoChanged", this.rilContext.data);
+    let dataInfo = this.rilContext.data;
+    if (dataInfo.signalStrength != message.gsmDBM ||
+        dataInfo.relSignalStrength != message.gsmRelative) {
+      dataInfo.signalStrength = message.gsmDBM;
+      dataInfo.relSignalStrength = message.gsmRelative;
+      ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo);
+    }
   },
 
   networkChanged: function networkChanged(srcNetwork, destNetwork) {
     return !destNetwork ||
       destNetwork.longName != srcNetwork.longName ||
       destNetwork.shortName != srcNetwork.shortName ||
       destNetwork.mnc != srcNetwork.mnc ||
       destNetwork.mcc != srcNetwork.mcc;
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -1444,16 +1444,35 @@ const GECKO_CARDSTATE_PUK_REQUIRED   = "
 const GECKO_CARDSTATE_NETWORK_LOCKED = "network_locked";
 const GECKO_CARDSTATE_NOT_READY      = null;
 const GECKO_CARDSTATE_READY          = "ready";
 
 const GECKO_NETWORK_SELECTION_UNKNOWN   = null;
 const GECKO_NETWORK_SELECTION_AUTOMATIC = "automatic";
 const GECKO_NETWORK_SELECTION_MANUAL    = "manual";
 
+const GECKO_MOBILE_CONNECTION_STATE_UNKNOWN = null;
+const GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING = "notSearching";
+const GECKO_MOBILE_CONNECTION_STATE_SEARCHING = "searching";
+const GECKO_MOBILE_CONNECTION_STATE_REGISTERED = "registered";
+const GECKO_MOBILE_CONNECTION_STATE_DENIED = "denied";
+
+const NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE = {};
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING;
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_HOME] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED] = GECKO_MOBILE_CONNECTION_STATE_DENIED;
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_ROAMING] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING;
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_SEARCHING;
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_DENIED;
+NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
+
+
 const GECKO_CALL_ERROR_BAD_NUMBER             = "BadNumberError";
 const GECKO_CALL_ERROR_NORMAL_CALL_CLEARING   = "NormalCallClearingError";
 const GECKO_CALL_ERROR_BUSY                   = "BusyError";
 const GECKO_CALL_ERROR_CONGESTION             = "CongestionError";
 const GECKO_CALL_ERROR_INCOMING_CALL_EXCEEDED = "IncomingCallExceededError";
 const GECKO_CALL_ERROR_BARRED                 = "BarredError";
 const GECKO_CALL_ERROR_FDN_BLOCKED            = "FDNBlockedError";
 const GECKO_CALL_ERROR_SUBSCRIBER_UNKNOWN     = "SubscriberUnknownError";
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -57,16 +57,19 @@ let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = f
 let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = false;
 // This flag defaults to true since on RIL v6 and later, we get the
 // version number via the UNSOLICITED_RIL_CONNECTED parcel.
 let RILQUIRKS_V5_LEGACY = true;
 let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = false;
 let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = false;
 let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = false;
 
+// Marker object.
+let PENDING_NETWORK_TYPE = {};
+
 /**
  * This object contains helpers buffering incoming data & deconstructing it
  * into parcels as well as buffering outgoing data & constructing parcels.
  * For that it maintains two buffers and corresponding uint8 views, indexes.
  *
  * The incoming buffer is a circular buffer where we store incoming data.
  * As soon as a complete parcel is received, it is processed right away, so
  * the buffer only needs to be large enough to hold one parcel.
@@ -610,16 +613,18 @@ let RIL = {
    */
   iccInfo: {},
 
   /**
    * Application identification for apps in ICC.
    */
   aid: null,
 
+  networkSelectionMode: null,
+
   voiceRegistrationState: {},
   dataRegistrationState: {},
 
   /**
    * The cell location on a phone, such as LAC, CID.
    */
   cellLocation: {},
 
@@ -1499,20 +1504,17 @@ let RIL = {
     Buf.sendParcel();
   },
 
   /**
    * Request various states about the network.
    */
   requestNetworkInfo: function requestNetworkInfo() {
     if (this._processingNetworkInfo) {
-      if (DEBUG) {
-        debug("Already requesting network info: " +
-              JSON.stringify(this._pendingNetworkInfo));
-      }
+      if (DEBUG) debug("Network info requested, but we're already requesting network info.");
       return;
     }
 
     if (DEBUG) debug("Requesting network info");
 
     this._processingNetworkInfo = true;
     this.getVoiceRegistrationState();
     this.getDataRegistrationState(); //TODO only GSM
@@ -2167,88 +2169,109 @@ let RIL = {
   _sendNetworkInfoMessage: function _sendNetworkInfoMessage(type, message) {
     if (!this._processingNetworkInfo) {
       // We only combine these messages in the case of the combined request
       // in requestNetworkInfo()
       this.sendDOMMessage(message);
       return;
     }
 
+    if (DEBUG) debug("Queuing " + type + " network info message: " + JSON.stringify(message));
     this._pendingNetworkInfo[type] = message;
   },
 
   _receivedNetworkInfo: function _receivedNetworkInfo(type) {
+    if (DEBUG) debug("Received " + type + " network info.");
     if (!this._processingNetworkInfo) {
       return;
     }
 
     let pending = this._pendingNetworkInfo;
 
-    // We still need to track states for events that aren't fired
+    // We still need to track states for events that aren't fired.
     if (!(type in pending)) {
-      pending[type] = true;
+      pending[type] = PENDING_NETWORK_TYPE;
     }
 
     // Pending network info is ready to be sent when no more messages
     // are waiting for responses, but the combined payload hasn't been sent.
     for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
       let type = NETWORK_INFO_MESSAGE_TYPES[i];
       if (!(type in pending)) {
+        if (DEBUG) debug("Still missing some more network info, not notifying main thread.");
         return;
       }
     }
 
     // Do a pass to clean up the processed messages that didn't create
     // a response message, so we don't have unused keys in the outbound
-    // networkinfochanged message
-    let keys = Object.keys(pending);
-    for (let i = 0; i < keys.length; i++) {
-      let key = keys[i];
-      if (pending[key] === true) {
+    // networkinfochanged message.
+    for (let key in pending) {
+      if (pending[key] == PENDING_NETWORK_TYPE) {
         delete pending[key];
       }
     }
 
+    if (DEBUG) debug("All pending network info has been received: " + JSON.stringify(pending));
+
     // Send the message on the next tick of the worker's loop, so we give the
     // last message a chance to call _sendNetworkInfoMessage first.
-    setTimeout(this._sendPendingNetworkInfo.bind(this), 0);
+    setTimeout(this._sendPendingNetworkInfo, 0);
   },
 
   _sendPendingNetworkInfo: function _sendPendingNetworkInfo() {
-    this.sendDOMMessage(this._pendingNetworkInfo);
-
-    this._processingNetworkInfo = false;
+    RIL.sendDOMMessage(RIL._pendingNetworkInfo);
+
+    RIL._processingNetworkInfo = false;
     for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
-      delete this._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]];
+      delete RIL._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]];
     }
   },
 
+  /**
+   * Process the network registration flags.
+   *
+   * @return true if the state changed, false otherwise.
+   */
+  _processCREG: function _processCREG(curState, newState) {
+    let changed = false;
+
+    let regState = RIL.parseInt(newState[0], NETWORK_CREG_STATE_UNKNOWN);
+    if (curState.regState != regState) {
+      changed = true;
+      curState.regState = regState;
+
+      curState.state = NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[regState];
+      curState.connected = regState == NETWORK_CREG_STATE_REGISTERED_HOME ||
+                           regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
+      curState.roaming = regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
+      curState.emergencyCallsOnly =
+        (regState >= NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS) &&
+        (regState <= NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS);
+      if (RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE) {
+        curState.emergencyCallsOnly = !curState.connected;
+      }
+    }
+
+    let radioTech = RIL.parseInt(newState[3], NETWORK_CREG_TECH_UNKNOWN);
+    if (curState.radioTech != radioTech) {
+      changed = true;
+      curState.radioTech = radioTech;
+      curState.type = GECKO_RADIO_TECH[radioTech] || null;
+    }
+    return changed;
+  },
+
   _processVoiceRegistrationState: function _processVoiceRegistrationState(state) {
     this.initRILQuirks();
 
     let rs = this.voiceRegistrationState;
-    let stateChanged = false;
-
-    let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN);
-    if (rs.regState != regState) {
-      rs.regState = regState;
-      if (RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE) {
-        rs.emergencyCallsOnly =
-          (regState != NETWORK_CREG_STATE_REGISTERED_HOME) &&
-          (regState != NETWORK_CREG_STATE_REGISTERED_ROAMING);
-      } else {
-        rs.emergencyCallsOnly =
-          (regState >= NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS) &&
-          (regState <= NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS);
-      }
-      stateChanged = true;
-      if (regState == NETWORK_CREG_STATE_REGISTERED_HOME ||
-          regState == NETWORK_CREG_STATE_REGISTERED_ROAMING) {
-        RIL.getSMSCAddress();
-      }
+    let stateChanged = this._processCREG(rs, state);
+    if (stateChanged && rs.connected) {
+      RIL.getSMSCAddress();
     }
 
     let cell = this.cellLocation;
     let cellChanged = false;
 
     // From TS 23.003, 0000 and 0xfffe are indicated that no valid LAI exists
     // in MS. So we still need to report the '0000' as well.
     let lac = parseInt(state[1], 16);
@@ -2263,22 +2286,16 @@ let RIL = {
       cellChanged = true;
     }
 
     if (cellChanged) {
       cell.rilMessageType = "celllocationchanged";
       this.sendDOMMessage(cell);
     }
 
-    let radioTech = RIL.parseInt(state[3], NETWORK_CREG_TECH_UNKNOWN);
-    if (rs.radioTech != radioTech) {
-      rs.radioTech = radioTech;
-      stateChanged = true;
-    }
-
     // TODO: This zombie code branch that will be raised from the dead once
     // we add explicit CDMA support everywhere (bug 726098).
     let cdma = false;
     if (cdma) {
       let baseStationId = RIL.parseInt(state[4]);
       let baseStationLatitude = RIL.parseInt(state[5]);
       let baseStationLongitude = RIL.parseInt(state[6]);
       if (!baseStationLatitude && !baseStationLongitude) {
@@ -2296,30 +2313,17 @@ let RIL = {
     if (stateChanged) {
       rs.rilMessageType = "voiceregistrationstatechange";
       this._sendNetworkInfoMessage(NETWORK_INFO_VOICE_REGISTRATION_STATE, rs);
     }
   },
 
   _processDataRegistrationState: function _processDataRegistrationState(state) {
     let rs = this.dataRegistrationState;
-    let stateChanged = false;
-
-    let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN);
-    if (rs.regState != regState) {
-      rs.regState = regState;
-      stateChanged = true;
-    }
-
-    let radioTech = RIL.parseInt(state[3], NETWORK_CREG_TECH_UNKNOWN);
-    if (rs.radioTech != radioTech) {
-      rs.radioTech = radioTech;
-      stateChanged = true;
-    }
-
+    let stateChanged = this._processCREG(rs, state);
     if (stateChanged) {
       rs.rilMessageType = "dataregistrationstatechange";
       this._sendNetworkInfoMessage(NETWORK_INFO_DATA_REGISTRATION_STATE, rs);
     }
   },
 
   _processOperator: function _processOperator(operatorData) {
     if (operatorData.length < 3) {
@@ -2328,17 +2332,17 @@ let RIL = {
       }
     }
 
     if (!this.operator) {
       this.operator = {rilMessageType: "operatorchange"};
     }
 
     let [longName, shortName, networkTuple] = operatorData;
-    let thisTuple = String(this.operator.mcc) + this.operator.mnc;
+    let thisTuple = "" + this.operator.mcc + this.operator.mnc;
 
     if (this.operator.longName !== longName ||
         this.operator.shortName !== shortName ||
         thisTuple !== networkTuple) {
 
       this.operator.longName = longName;
       this.operator.shortName = shortName;
       this.operator.mcc = 0;
@@ -3175,21 +3179,18 @@ RIL[REQUEST_DATA_REGISTRATION_STATE] = f
 RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_OPERATOR);
 
   if (options.rilRequestError) {
     return;
   }
 
   let operatorData = Buf.readStringList();
-  if (DEBUG) debug("operator: " + operatorData);
-
+  if (DEBUG) debug("Operator: " + operatorData);
   this._processOperator(operatorData);
-
-
 };
 RIL[REQUEST_RADIO_POWER] = null;
 RIL[REQUEST_DTMF] = null;
 RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) {
   if (options.rilRequestError) {
     switch (options.rilRequestError) {
       case ERROR_SMS_SEND_FAIL_RETRY:
         if (options.retryCount < SMS_RETRY_MAX) {
@@ -3378,18 +3379,18 @@ RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE
     case NETWORK_SELECTION_MODE_MANUAL:
       selectionMode = GECKO_NETWORK_SELECTION_MANUAL;
       break;
     default:
       selectionMode = GECKO_NETWORK_SELECTION_UNKNOWN;
       break;
   }
 
-  if (this.mode != selectionMode) {
-    this.mode = options.mode = selectionMode;
+  if (this.networkSelectionMode != selectionMode) {
+    this.networkSelectionMode = options.mode = selectionMode;
     options.rilMessageType = "networkselectionmodechange";
     this._sendNetworkInfoMessage(NETWORK_INFO_NETWORK_SELECTION_MODE, options);
   }
 };
 RIL[REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = function REQUEST_SET_NETWORK_SELECTION_AUTOMATIC(length, options) {
   if (options.rilRequestError) {
     options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendDOMMessage(options);
--- a/dom/tests/mochitest/geolocation/test_mozsettings.html
+++ b/dom/tests/mochitest/geolocation/test_mozsettings.html
@@ -34,18 +34,17 @@ function toggleGeolocationSetting(value,
 
 SimpleTest.waitForExplicitFinish();
 resume_geolocationProvider();
 force_prompt(true);
 
 
 var comp = SpecialPowers.wrap(Components);
 SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
-SpecialPowers.addPermission("websettings-read", true, document);
-SpecialPowers.addPermission("websettings-readwrite", true, document);
+SpecialPowers.addPermission("settings", true, document);
 comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm");
 
 toggleGeolocationSetting(false, function() {
     ok(true, "turned off geolocation via mozSettings");
     setTimeout(function() {
 	navigator.geolocation.getCurrentPosition(successCallbackAfterMozsetting, failureCallbackAfterMozsetting);
       }, 500); // need to wait a bit for all of these async callbacks to finish
   });
--- a/dom/tests/mochitest/geolocation/test_mozsettingsWatch.html
+++ b/dom/tests/mochitest/geolocation/test_mozsettingsWatch.html
@@ -34,18 +34,17 @@ function toggleGeolocationSetting(value,
 
 SimpleTest.waitForExplicitFinish();
 resume_geolocationProvider();
 force_prompt(true);
 
 
 var comp = SpecialPowers.wrap(Components);
 SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
-SpecialPowers.addPermission("websettings-read", true, document);
-SpecialPowers.addPermission("websettings-readwrite", true, document);
+SpecialPowers.addPermission("settings", true, document);
 comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm");
 
 toggleGeolocationSetting(false, function() {
     ok(true, "turned off geolocation via mozSettings");
     setTimeout(function() {
 	navigator.geolocation.watchPosition(successCallbackAfterMozsetting, failureCallbackAfterMozsetting);
       }, 500); // need to wait a bit for all of these async callbacks to finish
   });
--- a/dom/workers/Events.cpp
+++ b/dom/workers/Events.cpp
@@ -336,49 +336,52 @@ private:
   };
 
 DECL_EVENT_CLASS(Event::sClass, "Event")
 DECL_EVENT_CLASS(Event::sMainRuntimeClass, "WorkerEvent")
 
 #undef DECL_EVENT_CLASS
 
 JSPropertySpec Event::sProperties[] = {
-  { "type", SLOT_type, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
-  { "target", SLOT_target, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "currentTarget", SLOT_currentTarget, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "eventPhase", SLOT_eventPhase, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "bubbles", SLOT_bubbles, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "cancelable", SLOT_cancelable, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "timeStamp", SLOT_timeStamp, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "defaultPrevented", SLOT_defaultPrevented, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "isTrusted", SLOT_isTrusted, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+  { "type", SLOT_type, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "target", SLOT_target, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "currentTarget", SLOT_currentTarget, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "eventPhase", SLOT_eventPhase, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "bubbles", SLOT_bubbles, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "cancelable", SLOT_cancelable, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "timeStamp", SLOT_timeStamp, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "defaultPrevented", SLOT_defaultPrevented, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "isTrusted", SLOT_isTrusted, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec Event::sFunctions[] = {
   JS_FN("stopPropagation", StopPropagation, 0, FUNCTION_FLAGS),
   JS_FN("preventDefault", PreventDefault, 0, FUNCTION_FLAGS),
   JS_FN("initEvent", InitEvent, 3, FUNCTION_FLAGS),
   JS_FN("stopImmediatePropagation", StopImmediatePropagation, 0, FUNCTION_FLAGS),
   JS_FS_END
 };
 
 JSPropertySpec Event::sStaticProperties[] = {
-  { "CAPTURING_PHASE", CAPTURING_PHASE, CONSTANT_FLAGS, GetConstant, NULL },
-  { "AT_TARGET", AT_TARGET, CONSTANT_FLAGS, GetConstant, NULL },
-  { "BUBBLING_PHASE", BUBBLING_PHASE, CONSTANT_FLAGS, GetConstant, NULL },
-  { 0, 0, 0, NULL, NULL }
+  { "CAPTURING_PHASE", CAPTURING_PHASE, CONSTANT_FLAGS,
+    JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER },
+  { "AT_TARGET", AT_TARGET, CONSTANT_FLAGS, JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER },
+  { "BUBBLING_PHASE", BUBBLING_PHASE, CONSTANT_FLAGS,
+    JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 class MessageEvent : public Event
 {
   static JSClass sClass;
   static JSClass sMainRuntimeClass;
 
   static JSPropertySpec sProperties[];
@@ -588,22 +591,23 @@ private:
   };
 
 DECL_MESSAGEEVENT_CLASS(MessageEvent::sClass, "MessageEvent")
 DECL_MESSAGEEVENT_CLASS(MessageEvent::sMainRuntimeClass, "WorkerMessageEvent")
 
 #undef DECL_MESSAGEEVENT_CLASS
 
 JSPropertySpec MessageEvent::sProperties[] = {
-  { "data", SLOT_data, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
-  { "origin", SLOT_origin, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "source", SLOT_source, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+  { "data", SLOT_data, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "origin", SLOT_origin, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "source", SLOT_source, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec MessageEvent::sFunctions[] = {
   JS_FN("initMessageEvent", InitMessageEvent, 6, FUNCTION_FLAGS),
   JS_FS_END
 };
 
 class ErrorEvent : public Event
@@ -773,23 +777,23 @@ private:
   };
 
 DECL_ERROREVENT_CLASS(ErrorEvent::sClass, "ErrorEvent")
 DECL_ERROREVENT_CLASS(ErrorEvent::sMainRuntimeClass, "WorkerErrorEvent")
 
 #undef DECL_ERROREVENT_CLASS
 
 JSPropertySpec ErrorEvent::sProperties[] = {
-  { "message", SLOT_message, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "filename", SLOT_filename, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "lineno", SLOT_lineno, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+  { "message", SLOT_message, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "filename", SLOT_filename, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "lineno", SLOT_lineno, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec ErrorEvent::sFunctions[] = {
   JS_FN("initErrorEvent", InitErrorEvent, 6, FUNCTION_FLAGS),
   JS_FS_END
 };
 
 class ProgressEvent : public Event
@@ -947,23 +951,23 @@ private:
 JSClass ProgressEvent::sClass = {
   "ProgressEvent",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec ProgressEvent::sProperties[] = {
-  { "lengthComputable", SLOT_lengthComputable, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "loaded", SLOT_loaded, PROPERTY_FLAGS, GetProperty, 
-    js_GetterOnlyPropertyStub },
-  { "total", SLOT_total, PROPERTY_FLAGS, GetProperty, 
-    js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+  { "lengthComputable", SLOT_lengthComputable, PROPERTY_FLAGS,
+    JSOP_WRAPPER(GetProperty), JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "loaded", SLOT_loaded, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "total", SLOT_total, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec ProgressEvent::sFunctions[] = {
   JS_FN("initProgressEvent", InitProgressEvent, 6, FUNCTION_FLAGS),
   JS_FS_END
 };
 
 Event*
--- a/dom/workers/Exceptions.cpp
+++ b/dom/workers/Exceptions.cpp
@@ -157,31 +157,34 @@ private:
 JSClass DOMException::sClass = {
   "DOMException",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec DOMException::sProperties[] = {
-  { "code", SLOT_code, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
-  { "name", SLOT_name, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
-  { "message", SLOT_message, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+  { "code", SLOT_code, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "name", SLOT_name, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "message", SLOT_message, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec DOMException::sFunctions[] = {
   JS_FN("toString", ToString, 0, 0),
   JS_FS_END
 };
 
 JSPropertySpec DOMException::sStaticProperties[] = {
 
 #define EXCEPTION_ENTRY(_name) \
-  { #_name, _name, CONSTANT_FLAGS, GetConstant, NULL },
+  { #_name, _name, CONSTANT_FLAGS, JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER },
 
   EXCEPTION_ENTRY(INDEX_SIZE_ERR)
   EXCEPTION_ENTRY(DOMSTRING_SIZE_ERR)
   EXCEPTION_ENTRY(HIERARCHY_REQUEST_ERR)
   EXCEPTION_ENTRY(WRONG_DOCUMENT_ERR)
   EXCEPTION_ENTRY(INVALID_CHARACTER_ERR)
   EXCEPTION_ENTRY(NO_DATA_ALLOWED_ERR)
   EXCEPTION_ENTRY(NO_MODIFICATION_ALLOWED_ERR)
@@ -201,17 +204,17 @@ JSPropertySpec DOMException::sStaticProp
   EXCEPTION_ENTRY(URL_MISMATCH_ERR)
   EXCEPTION_ENTRY(QUOTA_EXCEEDED_ERR)
   EXCEPTION_ENTRY(TIMEOUT_ERR)
   EXCEPTION_ENTRY(INVALID_NODE_TYPE_ERR)
   EXCEPTION_ENTRY(DATA_CLONE_ERR)
 
 #undef EXCEPTION_ENTRY
 
-  { 0, 0, 0, NULL, NULL }
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 // static
 JSObject*
 DOMException::Create(JSContext* aCx, nsresult aNSResult)
 {
   JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
   if (!obj) {
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -205,19 +205,19 @@ private:
 JSClass Blob::sClass = {
   "Blob",
   JSCLASS_HAS_PRIVATE,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec Blob::sProperties[] = {
-  { "size", 0, PROPERTY_FLAGS, GetSize, js_GetterOnlyPropertyStub },
-  { "type", 0, PROPERTY_FLAGS, GetType, js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+  { "size", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetSize), JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "type", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetType), JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec Blob::sFunctions[] = {
   JS_FN("slice", Slice, 1, JSPROP_ENUMERATE),
   JS_FS_END
 };
 
 class File : public Blob
@@ -355,20 +355,21 @@ private:
 JSClass File::sClass = {
   "File",
   JSCLASS_HAS_PRIVATE,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec File::sProperties[] = {
-  { "name", 0, PROPERTY_FLAGS, GetName, js_GetterOnlyPropertyStub },
-  { "mozFullPath", 0, PROPERTY_FLAGS, GetMozFullPath,
-    js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+  { "name", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetName),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "mozFullPath", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetMozFullPath),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 nsIDOMBlob*
 Blob::GetPrivate(JSObject* aObj)
 {
   if (aObj) {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr == &sClass || classPtr == File::Class()) {
--- a/dom/workers/ImageData.cpp
+++ b/dom/workers/ImageData.cpp
@@ -143,20 +143,20 @@ JSPropertySpec ImageData::sProperties[] 
   // These properties are read-only per spec, which means that sets must throw
   // in strict mode and silently fail otherwise. This is a problem for workers
   // in general (because js_GetterOnlyPropertyStub throws unconditionally). The
   // general plan for fixing this involves the new DOM bindings. But Peace
   // Keeper breaks if we throw when setting these properties, so we need to do
   // something about it in the mean time. So we use NULL, which defaults to the
   // class setter (JS_StrictPropertyStub), which is always a silent no-op,
   // regardless of strict mode. Not ideal, but good enough for now.
-  { "width", SLOT_width, PROPERTY_FLAGS, GetProperty, NULL },
-  { "height", SLOT_height, PROPERTY_FLAGS, GetProperty, NULL },
-  { "data", SLOT_data, PROPERTY_FLAGS, GetProperty, NULL },
-  { 0, 0, 0, NULL, NULL }
+  { "width", SLOT_width, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), JSOP_NULLWRAPPER },
+  { "height", SLOT_height, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), JSOP_NULLWRAPPER },
+  { "data", SLOT_data, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), JSOP_NULLWRAPPER },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 } // anonymous namespace
 
 BEGIN_WORKERS_NAMESPACE
 
 namespace imagedata {
 
--- a/dom/workers/Location.cpp
+++ b/dom/workers/Location.cpp
@@ -149,29 +149,33 @@ private:
 JSClass Location::sClass = {
   "WorkerLocation",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec Location::sProperties[] = {
-  { "href", SLOT_href, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
-  { "protocol", SLOT_protocol, PROPERTY_FLAGS, GetProperty, 
-    js_GetterOnlyPropertyStub },
-  { "host", SLOT_host, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
-  { "hostname", SLOT_hostname, PROPERTY_FLAGS, GetProperty, 
-    js_GetterOnlyPropertyStub },
-  { "port", SLOT_port, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
-  { "pathname", SLOT_pathname, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "search", SLOT_search, PROPERTY_FLAGS, GetProperty,
-    js_GetterOnlyPropertyStub },
-  { "hash", SLOT_hash, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+  { "href", SLOT_href, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "protocol", SLOT_protocol, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "host", SLOT_host, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "hostname", SLOT_hostname, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "port", SLOT_port, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "pathname", SLOT_pathname, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "search", SLOT_search, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "hash", SLOT_hash, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec Location::sFunctions[] = {
   JS_FN("toString", ToString, 0, 0),
   JS_FS_END
 };
 
 } // anonymous namespace
--- a/dom/workers/Navigator.cpp
+++ b/dom/workers/Navigator.cpp
@@ -138,25 +138,25 @@ private:
 JSClass Navigator::sClass = {
   "WorkerNavigator",
   JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
 };
 
 JSPropertySpec Navigator::sProperties[] = {
-  { "appName", SLOT_appName, PROPERTY_FLAGS, GetProperty, 
-    js_GetterOnlyPropertyStub },
-  { "appVersion", SLOT_appVersion, PROPERTY_FLAGS, GetProperty, 
-    js_GetterOnlyPropertyStub },
-  { "platform", SLOT_platform, PROPERTY_FLAGS, GetProperty, 
-    js_GetterOnlyPropertyStub },
-  { "userAgent", SLOT_userAgent, PROPERTY_FLAGS, GetProperty, 
-    js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+  { "appName", SLOT_appName, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "appVersion", SLOT_appVersion, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "platform", SLOT_platform, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "userAgent", SLOT_userAgent, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 } // anonymous namespace
 
 BEGIN_WORKERS_NAMESPACE
 
 namespace navigator {
 
--- a/dom/workers/Worker.cpp
+++ b/dom/workers/Worker.cpp
@@ -287,20 +287,20 @@ DOMJSClass Worker::sClass = {
   },
   { prototypes::id::EventTarget_workers, prototypes::id::_ID_Count,
     prototypes::id::_ID_Count },
   -1, false, NULL
 };
 
 JSPropertySpec Worker::sProperties[] = {
   { sEventStrings[STRING_onerror], STRING_onerror, PROPERTY_FLAGS,
-    GetEventListener, SetEventListener },
+    JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) },
   { sEventStrings[STRING_onmessage], STRING_onmessage, PROPERTY_FLAGS,
-    GetEventListener, SetEventListener },
-  { 0, 0, 0, NULL, NULL }
+    JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec Worker::sFunctions[] = {
   JS_FN("terminate", Terminate, 0, FUNCTION_FLAGS),
   JS_FN("postMessage", PostMessage, 1, FUNCTION_FLAGS),
   JS_FS_END
 };
 
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -827,39 +827,33 @@ public:
     // Notify before WorkerRunnable::PostRun, since that can kill aWorkerPrivate
     NotifyScriptExecutedIfNeeded();
     WorkerRunnable::PostRun(aCx, aWorkerPrivate, aRunResult);
   }
 };
 
 class NotifyRunnable : public WorkerControlRunnable
 {
-  bool mFromJSObjectFinalizer;
   Status mStatus;
 
 public:
-  NotifyRunnable(WorkerPrivate* aWorkerPrivate, bool aFromJSObjectFinalizer,
-                 Status aStatus)
+  NotifyRunnable(WorkerPrivate* aWorkerPrivate, Status aStatus)
   : WorkerControlRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount),
-    mFromJSObjectFinalizer(aFromJSObjectFinalizer), mStatus(aStatus)
+    mStatus(aStatus)
   {
     NS_ASSERTION(aStatus == Terminating || aStatus == Canceling ||
                  aStatus == Killing, "Bad status!");
   }
 
   bool
   PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
   {
     // Modify here, but not in PostRun! This busy count addition will be matched
-    // by the CloseEventRunnable. If we're running from a finalizer there is no
-    // need to modify the count because future changes to the busy count will
-    // have no effect.
-    return mFromJSObjectFinalizer ?
-           true :
-           aWorkerPrivate->ModifyBusyCount(aCx, true);
+    // by the CloseEventRunnable.
+    return aWorkerPrivate->ModifyBusyCount(aCx, true);
   }
 
   bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
   {
     return aWorkerPrivate->NotifyInternal(aCx, mStatus);
   }
 };
@@ -2014,17 +2008,17 @@ WorkerPrivateParent<Derived>::NotifyPriv
 
   NS_ASSERTION(aStatus != Terminating || mQueuedRunnables.IsEmpty(),
                "Shouldn't have anything queued!");
 
   // Anything queued will be discarded.
   mQueuedRunnables.Clear();
 
   nsRefPtr<NotifyRunnable> runnable =
-    new NotifyRunnable(ParentAsWorkerPrivate(), !aCx, aStatus);
+    new NotifyRunnable(ParentAsWorkerPrivate(), aStatus);
   return runnable->Dispatch(aCx);
 }
 
 template <class Derived>
 bool
 WorkerPrivateParent<Derived>::Suspend(JSContext* aCx)
 {
   AssertIsOnParentThread();
@@ -2158,25 +2152,25 @@ template <class Derived>
 bool
 WorkerPrivateParent<Derived>::ModifyBusyCount(JSContext* aCx, bool aIncrease)
 {
   AssertIsOnParentThread();
 
   NS_ASSERTION(aIncrease || mBusyCount, "Mismatched busy count mods!");
 
   if (aIncrease) {
-    if (mBusyCount++ == 0) {
+    if (mBusyCount++ == 0 && mJSObject) {
       if (!RootJSObject(aCx, true)) {
         return false;
       }
     }
     return true;
   }
 
-  if (--mBusyCount == 0) {
+  if (--mBusyCount == 0 && mJSObject) {
     if (!RootJSObject(aCx, false)) {
       return false;
     }
 
     bool shouldCancel;
     {
       MutexAutoLock lock(mMutex);
       shouldCancel = mParentStatus == Terminating;
@@ -2193,16 +2187,17 @@ WorkerPrivateParent<Derived>::ModifyBusy
 template <class Derived>
 bool
 WorkerPrivateParent<Derived>::RootJSObject(JSContext* aCx, bool aRoot)
 {
   AssertIsOnParentThread();
 
   if (aRoot != mJSObjectRooted) {
     if (aRoot) {
+      NS_ASSERTION(mJSObject, "Nothing to root?");
       if (!JS_AddNamedObjectRoot(aCx, &mJSObject, "Worker root")) {
         NS_WARNING("JS_AddNamedObjectRoot failed!");
         return false;
       }
     }
     else {
       JS_RemoveObjectRoot(aCx, &mJSObject);
     }
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -607,26 +607,26 @@ private:
 JSClass WorkerGlobalScope::sClass = {
   "WorkerGlobalScope",
   0,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 JSPropertySpec WorkerGlobalScope::sProperties[] = {
-  { "location", SLOT_location, PROPERTY_FLAGS, GetLocation, 
-    js_GetterOnlyPropertyStub },
+  { "location", SLOT_location, PROPERTY_FLAGS, JSOP_WRAPPER(GetLocation),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
   { sEventStrings[STRING_onerror], STRING_onerror, PROPERTY_FLAGS,
-    GetOnErrorListener, SetOnErrorListener },
+    JSOP_WRAPPER(GetOnErrorListener), JSOP_WRAPPER(SetOnErrorListener) },
   { sEventStrings[STRING_onclose], STRING_onclose, PROPERTY_FLAGS,
-    GetEventListener, SetEventListener },
-  { "navigator", SLOT_navigator, PROPERTY_FLAGS, GetNavigator, 
-    js_GetterOnlyPropertyStub },
-  { "self", 0, PROPERTY_FLAGS, GetSelf, js_GetterOnlyPropertyStub },
-  { 0, 0, 0, NULL, NULL }
+    JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) },
+  { "navigator", SLOT_navigator, PROPERTY_FLAGS, JSOP_WRAPPER(GetNavigator),
+    JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { "self", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetSelf), JSOP_WRAPPER(js_GetterOnlyPropertyStub) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec WorkerGlobalScope::sFunctions[] = {
   JS_FN("close", Close, 0, FUNCTION_FLAGS),
   JS_FN("importScripts", ImportScripts, 1, FUNCTION_FLAGS),
   JS_FN("setTimeout", SetTimeout, 1, FUNCTION_FLAGS),
   JS_FN("clearTimeout", ClearTimeout, 1, FUNCTION_FLAGS),
   JS_FN("setInterval", SetInterval, 1, FUNCTION_FLAGS),
@@ -859,18 +859,18 @@ DOMJSClass DedicatedWorkerGlobalScope::s
   },
   { prototypes::id::EventTarget_workers, prototypes::id::_ID_Count,
     prototypes::id::_ID_Count },
   -1, false, NULL
 };
 
 JSPropertySpec DedicatedWorkerGlobalScope::sProperties[] = {
   { sEventStrings[STRING_onmessage], STRING_onmessage, PROPERTY_FLAGS,
-    GetEventListener, SetEventListener },
-  { 0, 0, 0, NULL, NULL }
+    JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 JSFunctionSpec DedicatedWorkerGlobalScope::sFunctions[] = {
   JS_FN("postMessage", PostMessage, 1, FUNCTION_FLAGS),
   JS_FS_END
 };
 
 const char* const DedicatedWorkerGlobalScope::sEventStrings[STRING_COUNT] = {
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -7620,17 +7620,17 @@ nsHTMLEditRules::RemoveEmptyNodes()
   nsCOMPtr<nsIContentIterator> iter =
                   do_CreateInstance("@mozilla.org/content/post-content-iterator;1");
   NS_ENSURE_TRUE(iter, NS_ERROR_NULL_POINTER);
   
   nsresult res = iter->Init(mDocChangeRange);
   NS_ENSURE_SUCCESS(res, res);
   
   nsCOMArray<nsINode> arrayOfEmptyNodes, arrayOfEmptyCites;
-  nsTArray<nsINode*> skipList;
+  nsTArray<nsCOMPtr<nsINode> > skipList;
 
   // check for empty nodes
   while (!iter->IsDone()) {
     nsINode* node = iter->GetCurrentNode();
     NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
     nsINode* parent = node->GetNodeParent();
     
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -3764,17 +3764,17 @@ nsHTMLEditor::GetEnclosingTable(nsIDOMNo
  * Uses nsEditor::JoinNodes so action is undoable. 
  * Should be called within the context of a batch transaction.
  */
 NS_IMETHODIMP
 nsHTMLEditor::CollapseAdjacentTextNodes(nsIDOMRange *aInRange)
 {
   NS_ENSURE_TRUE(aInRange, NS_ERROR_NULL_POINTER);
   nsAutoTxnsConserveSelection dontSpazMySelection(this);
-  nsTArray<nsIDOMNode*> textNodes;
+  nsTArray<nsCOMPtr<nsIDOMNode> > textNodes;
   // we can't actually do anything during iteration, so store the text nodes in an array
   // don't bother ref counting them because we know we can hold them for the 
   // lifetime of this method
 
 
   // build a list of editable text nodes
   nsresult result;
   nsCOMPtr<nsIContentIterator> iter =
--- a/editor/libeditor/html/nsTableEditor.cpp
+++ b/editor/libeditor/html/nsTableEditor.cpp
@@ -1301,17 +1301,17 @@ nsHTMLEditor::DeleteRow(nsIDOMElement *a
   PRInt32 colIndex = 0;
   nsresult res = NS_OK;
    
   // Prevent rules testing until we're done
   nsAutoRules beginRulesSniffing(this, kOpDeleteNode, nsIEditor::eNext);
 
   // The list of cells we will change rowspan in
   //  and the new rowspan values for each
-  nsTArray<nsIDOMElement*> spanCellList;
+  nsTArray<nsCOMPtr<nsIDOMElement> > spanCellList;
   nsTArray<PRInt32> newSpanList;
 
   // Scan through cells in row to do rowspan adjustments
   // Note that after we delete row, startRowIndex will point to the
   //   cells in the next row to be deleted
   do {
     res = GetCellDataAt(aTable, aRowIndex, colIndex, getter_AddRefs(cell),
                         &startRowIndex, &startColIndex, &rowSpan, &colSpan, 
@@ -2139,17 +2139,17 @@ nsHTMLEditor::JoinTableCells(bool aMerge
       {
         // No selected cells in this row -- stop at row above
         //  and leave last column at its previous value
         lastRowIndex = NS_MAX(0,rowIndex - 1);
       }
     }
   
     // The list of cells we will delete after joining
-    nsTArray<nsIDOMElement*> deleteList;
+    nsTArray<nsCOMPtr<nsIDOMElement> > deleteList;
 
     // 2nd pass: Do the joining and merging
     for (rowIndex = 0; rowIndex < rowCount; rowIndex++)
     {
       for (colIndex = 0; colIndex < colCount; colIndex += NS_MAX(actualColSpan2, 1))
       {
         res = GetCellDataAt(table, rowIndex, colIndex, getter_AddRefs(cell2),
                             &startRowIndex2, &startColIndex2,
--- a/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
@@ -132,17 +132,17 @@ NS_IMETHODIMP nsPrintProgress::RegisterL
   
   if (NS_SUCCEEDED(rv) && m_listenerList)
   {
     m_listenerList->AppendElement(listener);
     if (m_closeProgress || m_processCanceled)
       listener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
     else
     {
-      listener->OnStatusChange(nullptr, nullptr, 0, m_pendingStatus.get());
+      listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
       if (m_pendingStateFlags != -1)
         listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
     }
   }
     
   return NS_OK;
 }
 
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -866,45 +866,55 @@ void WriteSnapshotToDumpFile(Layer* aLay
 
 void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf)
 {
   WriteSnapshotToDumpFile_internal(aManager, aSurf);
 }
 #endif
 
 void
-Layer::Dump(FILE* aFile, const char* aPrefix)
+Layer::Dump(FILE* aFile, const char* aPrefix, bool aDumpHtml)
 {
-  fprintf(aFile, "<li><a id=\"%p\" ", this);
+  if (aDumpHtml) {
+    fprintf(aFile, "<li><a id=\"%p\" ", this);
 #ifdef MOZ_DUMP_PAINTING
-  if (GetType() == TYPE_CONTAINER || GetType() == TYPE_THEBES) {
-    WriteSnapshotLinkToDumpFile(this, aFile);
-  }
+    if (GetType() == TYPE_CONTAINER || GetType() == TYPE_THEBES) {
+      WriteSnapshotLinkToDumpFile(this, aFile);
+    }
 #endif
-  fprintf(aFile, ">");
+    fprintf(aFile, ">");
+  }
   DumpSelf(aFile, aPrefix);
-  fprintf(aFile, "</a>");
+  if (aDumpHtml) {
+    fprintf(aFile, "</a>");
+  }
 
   if (Layer* mask = GetMaskLayer()) {
     nsCAutoString pfx(aPrefix);
     pfx += "  Mask layer: ";
     mask->Dump(aFile, pfx.get());
   }
 
   if (Layer* kid = GetFirstChild()) {
     nsCAutoString pfx(aPrefix);
     pfx += "  ";
-    fprintf(aFile, "<ul>");
+    if (aDumpHtml) {
+      fprintf(aFile, "<ul>");
+    }
     kid->Dump(aFile, pfx.get());
-    fprintf(aFile, "</ul>");
+    if (aDumpHtml) {
+      fprintf(aFile, "</ul>");
+    }
   }
 
-  fprintf(aFile, "</li>");
+  if (aDumpHtml) {
+    fprintf(aFile, "</li>");
+  }
   if (Layer* next = GetNextSibling())
-    next->Dump(aFile, aPrefix);
+    next->Dump(aFile, aPrefix, aDumpHtml);
 }
 
 void
 Layer::DumpSelf(FILE* aFile, const char* aPrefix)
 {
   nsCAutoString str;
   PrintInfo(str, aPrefix);
   fprintf(FILEOrDefault(aFile), "%s\n", str.get());
@@ -1054,40 +1064,52 @@ ReadbackLayer::PrintInfo(nsACString& aTo
   }
   return aTo;
 }
 
 //--------------------------------------------------
 // LayerManager
 
 void
-LayerManager::Dump(FILE* aFile, const char* aPrefix)
+LayerManager::Dump(FILE* aFile, const char* aPrefix, bool aDumpHtml)
 {
   FILE* file = FILEOrDefault(aFile);
 
-  fprintf(file, "<ul><li><a ");
 #ifdef MOZ_DUMP_PAINTING
-  WriteSnapshotLinkToDumpFile(this, file);
+  if (aDumpHtml) {
+    fprintf(file, "<ul><li><a ");
+    WriteSnapshotLinkToDumpFile(this, file);
+    fprintf(file, ">");
+  }
 #endif
-  fprintf(file, ">");
   DumpSelf(file, aPrefix);
 #ifdef MOZ_DUMP_PAINTING
-  fprintf(file, "</a>");
+  if (aDumpHtml) {
+    fprintf(file, "</a>");
+  }
 #endif
 
   nsCAutoString pfx(aPrefix);
   pfx += "  ";
   if (!GetRoot()) {
-    fprintf(file, "%s(null)</li></ul>", pfx.get());
+    fprintf(file, "%s(null)", pfx.get());
+    if (aDumpHtml) {
+      fprintf(file, "</li></ul>");
+    }
     return;
   }
 
-  fprintf(file, "<ul>");
-  GetRoot()->Dump(file, pfx.get());
-  fprintf(file, "</ul></li></ul>");
+  if (aDumpHtml) {
+    fprintf(file, "<ul>");
+  }
+  GetRoot()->Dump(file, pfx.get(), aDumpHtml);
+  if (aDumpHtml) {
+    fprintf(file, "</ul></li></ul>");
+  }
+  fputc('\n', file);
 }
 
 void
 LayerManager::DumpSelf(FILE* aFile, const char* aPrefix)
 {
   nsCAutoString str;
   PrintInfo(str, aPrefix);
   fprintf(FILEOrDefault(aFile), "%s\n", str.get());
@@ -1156,17 +1178,17 @@ PrintInfo(nsACString& aTo, ShadowLayer* 
   if (!aShadowLayer->GetShadowVisibleRegion().IsEmpty()) {
     AppendToString(aTo, aShadowLayer->GetShadowVisibleRegion(), " [shadow-visible=", "]");
   }
   return aTo;
 }
 
 #else  // !MOZ_LAYERS_HAVE_LOG
 
-void Layer::Dump(FILE* aFile, const char* aPrefix) {}
+void Layer::Dump(FILE* aFile, const char* aPrefix, bool aDumpHtml) {}
 void Layer::DumpSelf(FILE* aFile, const char* aPrefix) {}
 void Layer::Log(const char* aPrefix) {}
 void Layer::LogSelf(const char* aPrefix) {}
 nsACString&
 Layer::PrintInfo(nsACString& aTo, const char* aPrefix)
 { return aTo; }
 
 nsACString&
@@ -1192,17 +1214,17 @@ ImageLayer::PrintInfo(nsACString& aTo, c
 nsACString&
 RefLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
 { return aTo; }
 
 nsACString&
 ReadbackLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
 { return aTo; }
 
-void LayerManager::Dump(FILE* aFile, const char* aPrefix) {}
+void LayerManager::Dump(FILE* aFile, const char* aPrefix, bool aDumpHtml) {}
 void LayerManager::DumpSelf(FILE* aFile, const char* aPrefix) {}
 void LayerManager::Log(const char* aPrefix) {}
 void LayerManager::LogSelf(const char* aPrefix) {}
 
 nsACString&
 LayerManager::PrintInfo(nsACString& aTo, const char* aPrefix)
 { return aTo; }
 
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -414,17 +414,17 @@ public:
   // ifndef MOZ_LAYERS_HAVE_LOG builds, they only have trivial
   // definitions in Layers.cpp.
   virtual const char* Name() const { return "???"; }
 
   /**
    * Dump information about this layer manager and its managed tree to
    * aFile, which defaults to stderr.
    */
-  void Dump(FILE* aFile=NULL, const char* aPrefix="");
+  void Dump(FILE* aFile=NULL, const char* aPrefix="", bool aDumpHtml=false);
   /**
    * Dump information about just this layer manager itself to aFile,
    * which defaults to stderr.
    */
   void DumpSelf(FILE* aFile=NULL, const char* aPrefix="");
 
   /**
    * Log information about this layer manager and its managed tree to
@@ -875,17 +875,17 @@ public:
   void SetParent(ContainerLayer* aParent) { mParent = aParent; }
   void SetNextSibling(Layer* aSibling) { mNextSibling = aSibling; }
   void SetPrevSibling(Layer* aSibling) { mPrevSibling = aSibling; }
 
   /**
    * Dump information about this layer manager and its managed tree to
    * aFile, which defaults to stderr.
    */
-  void Dump(FILE* aFile=NULL, const char* aPrefix="");
+  void Dump(FILE* aFile=NULL, const char* aPrefix="", bool aDumpHtml=false);
   /**
    * Dump information about just this layer manager itself to aFile,
    * which defaults to stderr.
    */
   void DumpSelf(FILE* aFile=NULL, const char* aPrefix="");
 
   /**
    * Log information about this layer manager and its managed tree to
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -4597,47 +4597,56 @@ ClipPartialLigature(gfxTextRun *aTextRun
         }
     }    
 }
 
 void
 gfxTextRun::DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx,
                                 PRUint32 aStart, PRUint32 aEnd,
                                 gfxPoint *aPt,
-                                PropertyProvider *aProvider)
+                                PropertyProvider *aProvider,
+                                gfxTextRun::DrawCallbacks *aCallbacks)
 {
     if (aStart >= aEnd)
         return;
 
-    // Need to preserve the path, otherwise this can break canvas text-on-path;
-    // in general it seems like a good thing, as naive callers probably won't
-    // expect gfxTextRun::Draw to implicitly destroy the current path.
-    gfxContextPathAutoSaveRestore savePath(aCtx);
-
     // Draw partial ligature. We hack this by clipping the ligature.
     LigatureData data = ComputeLigatureData(aStart, aEnd, aProvider);
     gfxRect clipExtents = aCtx->GetClipExtents();
     gfxFloat left = clipExtents.X()*mAppUnitsPerDevUnit;
     gfxFloat right = clipExtents.XMost()*mAppUnitsPerDevUnit;
     ClipPartialLigature(this, &left, &right, aPt->x, &data);
 
-    aCtx->Save();
-    aCtx->NewPath();
-    // use division here to ensure that when the rect is aligned on multiples
-    // of mAppUnitsPerDevUnit, we clip to true device unit boundaries.
-    // Also, make sure we snap the rectangle to device pixels.
-    aCtx->Rectangle(gfxRect(left/mAppUnitsPerDevUnit,
-                            clipExtents.Y(),
-                            (right - left)/mAppUnitsPerDevUnit,
-                            clipExtents.Height()), true);
-    aCtx->Clip();
+    {
+      // Need to preserve the path, otherwise this can break canvas text-on-path;
+      // in general it seems like a good thing, as naive callers probably won't
+      // expect gfxTextRun::Draw to implicitly destroy the current path.
+      gfxContextPathAutoSaveRestore savePath(aCtx);
+
+      // use division here to ensure that when the rect is aligned on multiples
+      // of mAppUnitsPerDevUnit, we clip to true device unit boundaries.
+      // Also, make sure we snap the rectangle to device pixels.
+      aCtx->Save();
+      aCtx->NewPath();
+      aCtx->Rectangle(gfxRect(left / mAppUnitsPerDevUnit,
+                              clipExtents.Y(),
+                              (right - left) / mAppUnitsPerDevUnit,
+                              clipExtents.Height()), true);
+      aCtx->Clip();
+    }
+
     gfxFloat direction = GetDirection();
     gfxPoint pt(aPt->x - direction*data.mPartAdvance, aPt->y);
-    DrawGlyphs(aFont, aCtx, gfxFont::GLYPH_FILL, &pt, nullptr, data.mLigatureStart,
-               data.mLigatureEnd, aProvider, aStart, aEnd);
+    DrawGlyphs(aFont, aCtx,
+               aCallbacks ? gfxFont::GLYPH_PATH : gfxFont::GLYPH_FILL, &pt,
+               nullptr, data.mLigatureStart, data.mLigatureEnd, aProvider,
+               aStart, aEnd);
+    if (aCallbacks) {
+      aCallbacks->NotifyGlyphPathEmitted();
+    }
     aCtx->Restore();
 
     aPt->x += direction*data.mPartWidth;
 }
 
 // returns true if a glyph run is using a font with synthetic bolding enabled, false otherwise
 static bool
 HasSyntheticBold(gfxTextRun *aRun, PRUint32 aStart, PRUint32 aLength)
@@ -4703,20 +4712,22 @@ struct BufferAlphaColor {
     gfxContext *mContext;
     gfxFloat mAlpha;
 };
 
 void
 gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, gfxFont::DrawMode aDrawMode,
                  PRUint32 aStart, PRUint32 aLength,
                  PropertyProvider *aProvider, gfxFloat *aAdvanceWidth,
-                 gfxPattern *aStrokePattern)
+                 gfxPattern *aStrokePattern,
+                 gfxTextRun::DrawCallbacks *aCallbacks)
 {
     NS_ASSERTION(aStart + aLength <= mCharacterCount, "Substring out of range");
     NS_ASSERTION(aDrawMode <= gfxFont::GLYPH_PATH, "GLYPH_PATH cannot be used with GLYPH_FILL or GLYPH_STROKE");
+    NS_ASSERTION(aDrawMode == gfxFont::GLYPH_PATH || !aCallbacks, "callback must not be specified unless using GLYPH_PATH");
 
     gfxFloat direction = GetDirection();
 
     if (mSkipDrawing) {
         // We're waiting for a user font to finish downloading;
         // but if the caller wants advance width, we need to compute it here
         if (aAdvanceWidth) {
             gfxTextRun::Metrics metrics = MeasureText(aStart, aLength,
@@ -4750,25 +4761,34 @@ gfxTextRun::Draw(gfxContext *aContext, g
     while (iter.NextRun()) {
         gfxFont *font = iter.GetGlyphRun()->mFont;
         PRUint32 start = iter.GetStringStart();
         PRUint32 end = iter.GetStringEnd();
         PRUint32 ligatureRunStart = start;
         PRUint32 ligatureRunEnd = end;
         ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
         
-        if (aDrawMode == gfxFont::GLYPH_FILL) {
-            DrawPartialLigature(font, aContext, start, ligatureRunStart, &pt, aProvider);
+        bool drawPartial = aDrawMode == gfxFont::GLYPH_FILL ||
+                           aDrawMode == gfxFont::GLYPH_PATH && aCallbacks;
+
+        if (drawPartial) {
+            DrawPartialLigature(font, aContext, start, ligatureRunStart, &pt,
+                                aProvider, aCallbacks);
         }
 
         DrawGlyphs(font, aContext, aDrawMode, &pt, aStrokePattern, ligatureRunStart,
                    ligatureRunEnd, aProvider, ligatureRunStart, ligatureRunEnd);
 
-        if (aDrawMode == gfxFont::GLYPH_FILL) {
-            DrawPartialLigature(font, aContext, ligatureRunEnd, end, &pt, aProvider);
+        if (aCallbacks) {
+          aCallbacks->NotifyGlyphPathEmitted();
+        }
+
+        if (drawPartial) {
+            DrawPartialLigature(font, aContext, ligatureRunEnd, end, &pt,
+                                aProvider, aCallbacks);
         }
     }
 
     // composite result when synthetic bolding used
     if (needToRestore) {
         syntheticBoldBuffer.PopAlpha();
     }
 
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -2467,16 +2467,32 @@ public:
         gfxFloat ClusterAdvance(PropertyProvider *aProvider) const;
 
     private:
         gfxTextRun *mTextRun;
         PRUint32    mCurrentChar;
     };
 
     /**
+     * Callback for Draw() to use when drawing text with mode
+     * gfxFont::GLYPH_PATH.
+     */
+    struct DrawCallbacks {
+
+        /**
+         * Called when a path has been emitted to the gfxContext when
+         * painting a text run.  This can be called up to three times:
+         * once for any partial ligature at the beginning of the text run,
+         * once for the main run of glyphs, and once for any partial ligature
+         * at the end of the text run.
+         */
+        virtual void NotifyGlyphPathEmitted() = 0;
+    };
+
+    /**
      * Draws a substring. Uses only GetSpacing from aBreakProvider.
      * The provided point is the baseline origin on the left of the string
      * for LTR, on the right of the string for RTL.
      * @param aAdvanceWidth if non-null, the advance width of the substring
      * is returned here.
      * 
      * Drawing should respect advance widths in the sense that for LTR runs,
      * Draw(ctx, pt, offset1, length1, dirty, &provider, &advance) followed by
@@ -2491,17 +2507,18 @@ public:
      * 
      * Glyphs should be drawn in logical content order, which can be significant
      * if they overlap (perhaps due to negative spacing).
      */
     void Draw(gfxContext *aContext, gfxPoint aPt,
               gfxFont::DrawMode aDrawMode,
               PRUint32 aStart, PRUint32 aLength,
               PropertyProvider *aProvider,
-              gfxFloat *aAdvanceWidth, gfxPattern *aStrokePattern);
+              gfxFloat *aAdvanceWidth, gfxPattern *aStrokePattern,
+              DrawCallbacks *aCallbacks = nullptr);
 
     /**
      * Computes the ReflowMetrics for a substring.
      * Uses GetSpacing from aBreakProvider.
      * @param aBoundingBoxType which kind of bounding box (loose/tight)
      */
     Metrics MeasureText(PRUint32 aStart, PRUint32 aLength,
                         gfxFont::BoundingBoxType aBoundingBoxType,
@@ -2913,17 +2930,18 @@ private:
 
     // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero
     LigatureData ComputeLigatureData(PRUint32 aPartStart, PRUint32 aPartEnd,
                                      PropertyProvider *aProvider);
     gfxFloat ComputePartialLigatureWidth(PRUint32 aPartStart, PRUint32 aPartEnd,
                                          PropertyProvider *aProvider);
     void DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx,
                              PRUint32 aStart, PRUint32 aEnd, gfxPoint *aPt,
-                             PropertyProvider *aProvider);
+                             PropertyProvider *aProvider,
+                             DrawCallbacks *aCallbacks);
     // Advance aStart to the start of the nearest ligature; back up aEnd
     // to the nearest ligature end; may result in *aStart == *aEnd
     void ShrinkToLigatureBoundaries(PRUint32 *aStart, PRUint32 *aEnd);
     // result in appunits
     gfxFloat GetPartialLigatureWidth(PRUint32 aStart, PRUint32 aEnd, PropertyProvider *aProvider);
     void AccumulatePartialLigatureMetrics(gfxFont *aFont,
                                           PRUint32 aStart, PRUint32 aEnd,
                                           gfxFont::BoundingBoxType aBoundingBoxType,
--- a/image/src/imgStatusTracker.h
+++ b/image/src/imgStatusTracker.h
@@ -146,13 +146,13 @@ private:
   friend class imgRequestNotifyRunnable;
 
   nsCOMPtr<nsIRunnable> mRequestRunnable;
 
   // A weak pointer to the Image, because it owns us, and we
   // can't create a cycle.
   mozilla::image::Image* mImage;
   PRUint32 mState;
-  nsresult mImageStatus;
+  PRUint32 mImageStatus;
   bool mHadLastPart;
 };
 
 #endif
--- a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
+++ b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
@@ -331,17 +331,19 @@ bool Channel::ChannelImpl::CreatePipe(co
         HANDLE_EINTR(close(pipe_fds[0]));
         HANDLE_EINTR(close(pipe_fds[1]));
         return false;
       }
 
       pipe_ = pipe_fds[0];
       client_pipe_ = pipe_fds[1];
 
-      Singleton<PipeMap>()->Insert(pipe_name_, client_pipe_);
+      if (pipe_name_.length()) {
+        Singleton<PipeMap>()->Insert(pipe_name_, client_pipe_);
+      }
     } else {
       pipe_ = ChannelNameToClientFD(pipe_name_);
       DCHECK(pipe_ > 0);
       waiting_connect_ = false;
     }
   }
 
   // Create the Hello message to be sent when Connect is called
--- a/ipc/dbus/DBusThread.cpp
+++ b/ipc/dbus/DBusThread.cpp
@@ -72,31 +72,16 @@
 // TODO Add Wakeup to this list once we've moved to ics
 
 enum {
   DBUS_EVENT_LOOP_EXIT = 1,
   DBUS_EVENT_LOOP_ADD = 2,
   DBUS_EVENT_LOOP_REMOVE = 3,
 } DBusEventTypes;
 
-// Signals that the DBus thread should listen for. Needs to include
-// all signals any DBus observer object may need.
-
-static const char* DBUS_SIGNALS[] =
-{
-  "type='signal',interface='org.bluez.Adapter'",
-  "type='signal',interface='org.bluez.Manager'",
-  "type='signal',interface='org.bluez.Device'",
-  "type='signal',interface='org.bluez.Input'",
-  "type='signal',interface='org.bluez.Network'",
-  "type='signal',interface='org.bluez.NetworkServer'",
-  "type='signal',interface='org.bluez.HealthDevice'",
-  "type='signal',interface='org.bluez.AudioSink'"
-};
-
 static unsigned int UnixEventsToDBusFlags(short events)
 {
   return (events & DBUS_WATCH_READABLE ? POLLIN : 0) |
     (events & DBUS_WATCH_WRITABLE ? POLLOUT : 0) |
     (events & DBUS_WATCH_ERROR ? POLLERR : 0) |
     (events & DBUS_WATCH_HANGUP ? POLLHUP : 0);
 }
 
@@ -145,17 +130,16 @@ struct DBusThread : public RawDBusConnec
   // Sockets for receiving dbus control information (watch
   // add/removes, loop shutdown, etc...)
   ScopedClose mControlFdR;
   ScopedClose mControlFdW;
 
 protected:
   bool SetUpEventLoop();
   bool TearDownData();
-  bool TearDownEventLoop();
 };
 
 static nsAutoPtr<DBusThread> sDBusThread;
 
 // DBus utility functions
 // Free statics, as they're used as function pointers in dbus setup
 
 static dbus_bool_t
@@ -317,29 +301,16 @@ DBusThread::SetUpEventLoop()
 
   // If we can't establish a connection to dbus, nothing else will work
   nsresult rv = EstablishDBusConnection();
   if (NS_FAILED(rv)) {
     NS_WARNING("Cannot create DBus Connection for DBus Thread!");
     return false;
   }
 
-  // Set which messages will be processed by this dbus connection.
-  // Since we are maintaining a single thread for all the DBus bluez
-  // signals we want, register all of them in this thread at startup.
-  // The event handler will sort the destinations out as needed.
-  for (uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) {
-    dbus_bus_add_match(mConnection,
-                       DBUS_SIGNALS[i],
-                       &err);
-    if (dbus_error_is_set(&err)) {
-      LOG_AND_FREE_DBUS_ERROR(&err);
-      return false;
-    }
-  }
   return true;
 }
 
 bool
 DBusThread::TearDownData()
 {
   LOG("Removing DBus Sockets\n");
   if (mControlFdW.get()) {
@@ -351,36 +322,16 @@ DBusThread::TearDownData()
   mPollData.Clear();
 
   // DBusWatch pointers are maintained by DBus, so we won't leak by
   // clearing.
   mWatchData.Clear();
   return true;
 }
 
-bool
-DBusThread::TearDownEventLoop()
-{
-  MOZ_ASSERT(mConnection);
-
-  DBusError err;
-  dbus_error_init(&err);
-
-  for (uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) {
-    dbus_bus_remove_match(mConnection,
-                          DBUS_SIGNALS[i],
-                          &err);
-    if (dbus_error_is_set(&err)) {
-      LOG_AND_FREE_DBUS_ERROR(&err);
-    }
-  }
-
-  return true;
-}
-
 void
 DBusThread::EventLoop()
 {
   dbus_connection_set_watch_functions(mConnection, AddWatch,
                                       RemoveWatch, ToggleWatch, this, NULL);
 
   LOG("DBus Event Loop Starting\n");
   while (1) {
@@ -395,17 +346,16 @@ DBusThread::EventLoop()
         char data;
         while (recv(mControlFdR.get(), &data, sizeof(char), MSG_DONTWAIT)
                != -1) {
           switch (data) {
             case DBUS_EVENT_LOOP_EXIT:
               LOG("DBus Event Loop Exiting\n");
               dbus_connection_set_watch_functions(mConnection,
                                                   NULL, NULL, NULL, NULL, NULL);
-              TearDownEventLoop();
               return;
             case DBUS_EVENT_LOOP_ADD:
               HandleWatchAdd(this);
               break;
             case DBUS_EVENT_LOOP_REMOVE:
               HandleWatchRemove(this);
               break;
           }
--- a/ipc/dbus/DBusUtils.cpp
+++ b/ipc/dbus/DBusUtils.cpp
@@ -255,10 +255,26 @@ DBusMessage * dbus_func_args_error(DBusC
   va_start(lst, first_arg_type);
   ret = dbus_func_args_timeout_valist(conn, -1, err,
                                       path, ifc, func,
                                       first_arg_type, lst);
   va_end(lst);
   return ret;
 }
 
+int dbus_returns_int32(DBusMessage *reply) 
+{
+  DBusError err;
+  int ret = -1;
+
+  dbus_error_init(&err);
+  if (!dbus_message_get_args(reply, &err,
+                             DBUS_TYPE_INT32, &ret,
+                             DBUS_TYPE_INVALID)) {
+    LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
+  }
+
+  dbus_message_unref(reply);
+  return ret;
+}
+
 }
 }
--- a/ipc/dbus/DBusUtils.h
+++ b/ipc/dbus/DBusUtils.h
@@ -100,14 +100,15 @@ DBusMessage*  dbus_func_args_timeout_val
                                             int timeout_ms,
                                             DBusError* err,
                                             const char* path,
                                             const char* ifc,
                                             const char* func,
                                             int first_arg_type,
                                             va_list args);
 
+int dbus_returns_int32(DBusMessage *reply);
 
 }
 }
 
 #endif
 
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -74,18 +74,17 @@ struct RunnableMethodTraits<GeckoChildPr
     static void ReleaseCallee(GeckoChildProcessHost* obj) { }
 };
 
 GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
                                              base::WaitableEventWatcher::Delegate* aDelegate)
   : ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum
     mProcessType(aProcessType),
     mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
-    mLaunched(false),
-    mChannelInitialized(false),
+    mProcessState(CREATING_CHANNEL),
     mDelegate(aDelegate),
     mChildProcessHandle(0)
 #if defined(MOZ_WIDGET_COCOA)
   , mChildTask(MACH_PORT_NULL)
 #endif
 {
     MOZ_COUNT_CTOR(GeckoChildProcessHost);
     
@@ -234,16 +233,30 @@ uint32 GeckoChildProcessHost::GetSupport
     }
     return pluginContainerArchs;
   }
 #endif
 
   return base::GetCurrentProcessArchitecture();
 }
 
+void
+GeckoChildProcessHost::PrepareLaunch()
+{
+#ifdef MOZ_CRASHREPORTER
+  if (CrashReporter::GetEnabled()) {
+    CrashReporter::OOPInit();
+  }
+#endif
+
+#ifdef XP_WIN
+  InitWindowsGroupID();
+#endif
+}
+
 #ifdef XP_WIN
 void GeckoChildProcessHost::InitWindowsGroupID()
 {
   // On Win7+, pass the application user model to the child, so it can
   // register with it. This insures windows created by the container
   // properly group with the parent app on the Win7 taskbar.
   nsCOMPtr<nsIWinTaskbar> taskbarInfo =
     do_GetService(NS_TASKBAR_CONTRACTID);
@@ -258,25 +271,17 @@ void GeckoChildProcessHost::InitWindowsG
     }
   }
 }
 #endif
 
 bool
 GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs, base::ProcessArchitecture arch)
 {
-#ifdef MOZ_CRASHREPORTER
-  if (CrashReporter::GetEnabled()) {
-    CrashReporter::OOPInit();
-  }
-#endif
-
-#ifdef XP_WIN
-  InitWindowsGroupID();
-#endif
+  PrepareLaunch();
 
   PRIntervalTime timeoutTicks = (aTimeoutMs > 0) ? 
     PR_MillisecondsToInterval(aTimeoutMs) : PR_INTERVAL_NO_TIMEOUT;
   MessageLoop* ioLoop = XRE_GetIOMessageLoop();
   NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI");
 
   ioLoop->PostTask(FROM_HERE,
                    NewRunnableMethod(this,
@@ -285,69 +290,81 @@ GeckoChildProcessHost::SyncLaunch(std::v
   // NB: this uses a different mechanism than the chromium parent
   // class.
   MonitorAutoLock lock(mMonitor);
   PRIntervalTime waitStart = PR_IntervalNow();
   PRIntervalTime current;
 
   // We'll receive several notifications, we need to exit when we
   // have either successfully launched or have timed out.
-  while (!mLaunched) {
+  while (mProcessState < PROCESS_CONNECTED) {
     lock.Wait(timeoutTicks);
 
     if (timeoutTicks != PR_INTERVAL_NO_TIMEOUT) {
       current = PR_IntervalNow();
       PRIntervalTime elapsed = current - waitStart;
       if (elapsed > timeoutTicks) {
         break;
       }
       timeoutTicks = timeoutTicks - elapsed;
       waitStart = current;
     }
   }
 
-  return mLaunched;
+  return mProcessState == PROCESS_CONNECTED;
 }
 
 bool
 GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts)
 {
-#ifdef MOZ_CRASHREPORTER
-  if (CrashReporter::GetEnabled()) {
-    CrashReporter::OOPInit();
-  }
-#endif
-
-#ifdef XP_WIN
-  InitWindowsGroupID();
-#endif
+  PrepareLaunch();
 
   MessageLoop* ioLoop = XRE_GetIOMessageLoop();
   ioLoop->PostTask(FROM_HERE,
                    NewRunnableMethod(this,
                                      &GeckoChildProcessHost::PerformAsyncLaunch,
                                      aExtraOpts, base::GetCurrentProcessArchitecture()));
 
   // This may look like the sync launch wait, but we only delay as
   // long as it takes to create the channel.
   MonitorAutoLock lock(mMonitor);
-  while (!mChannelInitialized) {
+  while (mProcessState < CHANNEL_INITIALIZED) {
     lock.Wait();
   }
 
   return true;
 }
 
+bool
+GeckoChildProcessHost::LaunchAndWaitForProcessHandle(StringVector aExtraOpts)
+{
+  PrepareLaunch();
+
+  MessageLoop* ioLoop = XRE_GetIOMessageLoop();
+  ioLoop->PostTask(FROM_HERE,
+                   NewRunnableMethod(this,
+                                     &GeckoChildProcessHost::PerformAsyncLaunch,
+                                     aExtraOpts, base::GetCurrentProcessArchitecture()));
+
+  MonitorAutoLock lock(mMonitor);
+  while (mProcessState < PROCESS_CREATED) {
+    lock.Wait();
+  }
+  MOZ_ASSERT(mProcessState == PROCESS_ERROR || mChildProcessHandle);
+
+  return mProcessState < PROCESS_ERROR;
+}
+
 void
 GeckoChildProcessHost::InitializeChannel()
 {
   CreateChannel();
 
   MonitorAutoLock lock(mMonitor);
-  mChannelInitialized = true;
+  mProcessState = CHANNEL_INITIALIZED;
   lock.Notify();
 }
 
 PRInt32 GeckoChildProcessHost::mChildCounter = 0;
 
 //
 // Wrapper function for handling GECKO_SEPARATE_NSPR_LOGS
 //
@@ -390,18 +407,16 @@ GeckoChildProcessHost::PerformAsyncLaunc
   PR_SetEnv(restoreOrigLogName);
 
   return retval;
 }
 
 bool
 GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExtraOpts, base::ProcessArchitecture arch)
 {
-  // FIXME/cjones: make this work from non-IO threads, too
-
   // We rely on the fact that InitializeChannel() has already been processed
   // on the IO thread before this point is reached.
   if (!GetChannel()) {
     return false;
   }
 
   base::ProcessHandle process;
 
@@ -679,36 +694,60 @@ GeckoChildProcessHost::PerformAsyncLaunc
 
   base::LaunchApp(cmdLine, false, false, &process);
 
 #else
 #  error Sorry
 #endif
 
   if (!process) {
+    MonitorAutoLock lock(mMonitor);
+    mProcessState = PROCESS_ERROR;
+    lock.Notify();
     return false;
   }
+  // NB: on OS X, we block much longer than we need to in order to
+  // reach this call, waiting for the child process's task_t.  The
+  // best way to fix that is to refactor this file, hard.
   SetHandle(process);
 #if defined(MOZ_WIDGET_COCOA)
   mChildTask = child_task;
 #endif
 
+  OpenPrivilegedHandle(base::GetProcId(process));
+  {
+    MonitorAutoLock lock(mMonitor);
+    mProcessState = PROCESS_CREATED;
+    lock.Notify();
+  }
+
   return true;
 }
 
 void
+GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid)
+{
+  if (mChildProcessHandle) {
+    MOZ_ASSERT(aPid == base::GetProcId(mChildProcessHandle));
+    return;
+  }
+  if (!base::OpenPrivilegedProcessHandle(aPid, &mChildProcessHandle)) {
+    NS_RUNTIMEABORT("can't open handle to child process");
+  }
+}
+
+void
 GeckoChildProcessHost::OnChannelConnected(int32 peer_pid)
 {
-  MonitorAutoLock lock(mMonitor);
-  mLaunched = true;
-
-  if (!base::OpenPrivilegedProcessHandle(peer_pid, &mChildProcessHandle))
-      NS_RUNTIMEABORT("can't open handle to child process");
-
-  lock.Notify();
+  OpenPrivilegedHandle(peer_pid);
+  {
+    MonitorAutoLock lock(mMonitor);
+    mProcessState = PROCESS_CONNECTED;
+    lock.Notify();
+  }
 }
 
 void
 GeckoChildProcessHost::OnMessageReceived(const IPC::Message& aMsg)
 {
   // We never process messages ourself, just save them up for the next
   // listener.
   mQueue.push(aMsg);
--- a/ipc/glue/GeckoChildProcessHost.h
+++ b/ipc/glue/GeckoChildProcessHost.h
@@ -18,34 +18,57 @@
 
 namespace mozilla {
 namespace ipc {
 
 class GeckoChildProcessHost : public ChildProcessHost
 {
 protected:
   typedef mozilla::Monitor Monitor;
+  typedef std::vector<std::string> StringVector;
 
 public:
   typedef base::ProcessHandle ProcessHandle;
 
   GeckoChildProcessHost(GeckoProcessType aProcessType=GeckoProcessType_Default,
                         base::WaitableEventWatcher::Delegate* aDelegate=nullptr);
 
   ~GeckoChildProcessHost();
 
   static nsresult GetArchitecturesForBinary(const char *path, uint32 *result);
 
   static uint32 GetSupportedArchitecturesForProcessType(GeckoProcessType type);
 
-  bool SyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>(),
+  // Block until the IPC channel for our subprocess is initialized,
+  // but no longer.  The child process may or may not have been
+  // created when this method returns.
+  bool AsyncLaunch(StringVector aExtraOpts=StringVector());
+
+  // Block until the IPC channel for our subprocess is initialized and
+  // the OS process is created.  The subprocess may or may not have
+  // connected back to us when this method returns.
+  //
+  // NB: on POSIX, this method is relatively cheap, and doesn't
+  // require disk IO.  On win32 however, it requires at least the
+  // analogue of stat().  This difference induces a semantic
+  // difference in this method: on POSIX, when we return, we know the
+  // subprocess has been created, but we don't know whether its
+  // executable image can be loaded.  On win32, we do know that when
+  // we return.  But we don't know if dynamic linking succeeded on
+  // either platform.
+  bool LaunchAndWaitForProcessHandle(StringVector aExtraOpts=StringVector());
+
+  // Block until the child process has been created and it connects to
+  // the IPC channel, meaning it's fully initialized.  (Or until an
+  // error occurs.)
+  bool SyncLaunch(StringVector aExtraOpts=StringVector(),
                   int32 timeoutMs=0,
                   base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture());
-  bool AsyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
-  bool PerformAsyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>(),
+
+  bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(),
                           base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture());
 
   virtual void OnChannelConnected(int32 peer_pid);
   virtual void OnMessageReceived(const IPC::Message& aMsg);
   virtual void OnChannelError();
   virtual void GetQueuedMessages(std::queue<IPC::Message>& queue);
 
   void InitializeChannel();
@@ -71,22 +94,38 @@ public:
     return mChildTask;
   }
 #endif
 
 
 protected:
   GeckoProcessType mProcessType;
   Monitor mMonitor;
-  bool mLaunched;
-  bool mChannelInitialized;
   FilePath mProcessPath;
+  // This value must be accessed while holding mMonitor.
+  enum {
+    // This object has been constructed, but the OS process has not
+    // yet.
+    CREATING_CHANNEL = 0,
+    // The IPC channel for our subprocess has been created, but the OS
+    // process has still not been created.
+    CHANNEL_INITIALIZED,
+    // The OS process has been created, but it hasn't yet connected to
+    // our IPC channel.
+    PROCESS_CREATED,
+    // The process is launched and connected to our IPC channel.  All
+    // is well.
+    PROCESS_CONNECTED,
+    PROCESS_ERROR
+  } mProcessState;
 
   static PRInt32 mChildCounter;
 
+  void PrepareLaunch();
+
 #ifdef XP_WIN
   void InitWindowsGroupID();
   nsString mGroupId;
 #endif
 
 #if defined(OS_POSIX)
   base::file_handle_mapping_vector mFileMap;
 #endif
@@ -100,16 +139,18 @@ protected:
 
 private:
   DISALLOW_EVIL_CONSTRUCTORS(GeckoChildProcessHost);
 
   // Does the actual work for AsyncLaunch, on the IO thread.
   bool PerformAsyncLaunchInternal(std::vector<std::string>& aExtraOpts,
                                   base::ProcessArchitecture arch);
 
+  void OpenPrivilegedHandle(base::ProcessId aPid);
+
   // In between launching the subprocess and handing off its IPC
   // channel, there's a small window of time in which *we* might still
   // be the channel listener, and receive messages.  That's bad
   // because we have no idea what to do with those messages.  So queue
   // them here until we hand off the eventual listener.
   //
   // FIXME/cjones: this strongly indicates bad design.  Shame on us.
   std::queue<IPC::Message> mQueue;
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -487,31 +487,31 @@ DumpHeap(JSContext *cx,
             (unsigned)(vp - argv));
     return JS_FALSE;
 }
 
 #endif /* DEBUG */
 
 JSFunctionSpec gGlobalFunctions[] =
 {
-    {"print",           Print,          0,0},
-    {"load",            Load,           1,0},
-    {"quit",            Quit,           0,0},
-    {"version",         Version,        1,0},
-    {"build",           BuildDate,      0,0},
-    {"dumpXPC",         DumpXPC,        1,0},
-    {"dump",            Dump,           1,0},
-    {"gc",              GC,             0,0},
-#ifdef JS_GC_ZEAL
-    {"gczeal",          GCZeal,         1,0},
-#endif
-#ifdef DEBUG
-    {"dumpHeap",        DumpHeap,       5,0},
-#endif
-    {nullptr,nullptr,0,0}
+    JS_FS("print",           Print,          0,0),
+    JS_FS("load",            Load,           1,0),
+    JS_FS("quit",            Quit,           0,0),
+    JS_FS("version",         Version,        1,0),
+    JS_FS("build",           BuildDate,      0,0),
+    JS_FS("dumpXPC",         DumpXPC,        1,0),
+    JS_FS("dump",            Dump,           1,0),
+    JS_FS("gc",              GC,             0,0),
+ #ifdef JS_GC_ZEAL
+    JS_FS("gczeal",          GCZeal,         1,0),
+ #endif
+ #ifdef DEBUG
+    JS_FS("dumpHeap",        DumpHeap,       5,0),
+ #endif
+    JS_FS_END
 };
 
 typedef enum JSShellErrNum
 {
 #define MSG_DEF(name, number, count, exception, format) \
     name = number,
 #include "jsshell.msg"
 #undef MSG_DEF
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -431,40 +431,59 @@ DEFINE_STATIC_SETTER(static_multiline_se
 
 const uint8_t REGEXP_STATIC_PROP_ATTRS    = JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE;
 const uint8_t RO_REGEXP_STATIC_PROP_ATTRS = REGEXP_STATIC_PROP_ATTRS | JSPROP_READONLY;
 
 const uint8_t HIDDEN_PROP_ATTRS = JSPROP_PERMANENT | JSPROP_SHARED;
 const uint8_t RO_HIDDEN_PROP_ATTRS = HIDDEN_PROP_ATTRS | JSPROP_READONLY;
 
 static JSPropertySpec regexp_static_props[] = {
-    {"input",        0, REGEXP_STATIC_PROP_ATTRS,    static_input_getter, static_input_setter},
-    {"multiline",    0, REGEXP_STATIC_PROP_ATTRS,    static_multiline_getter,
-                                                     static_multiline_setter},
-    {"lastMatch",    0, RO_REGEXP_STATIC_PROP_ATTRS, static_lastMatch_getter,    NULL},
-    {"lastParen",    0, RO_REGEXP_STATIC_PROP_ATTRS, static_lastParen_getter,    NULL},
-    {"leftContext",  0, RO_REGEXP_STATIC_PROP_ATTRS, static_leftContext_getter,  NULL},
-    {"rightContext", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_rightContext_getter, NULL},
-    {"$1",           0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren1_getter,       NULL},
-    {"$2",           0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren2_getter,       NULL},
-    {"$3",           0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren3_getter,       NULL},
-    {"$4",           0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren4_getter,       NULL},
-    {"$5",           0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren5_getter,       NULL},
-    {"$6",           0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren6_getter,       NULL},
-    {"$7",           0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren7_getter,       NULL},
-    {"$8",           0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren8_getter,       NULL},
-    {"$9",           0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren9_getter,       NULL},
-
-    {"$_",           0, HIDDEN_PROP_ATTRS,    static_input_getter, static_input_setter},
-    {"$*",           0, HIDDEN_PROP_ATTRS,    static_multiline_getter, static_multiline_setter},
-    {"$&",           0, RO_HIDDEN_PROP_ATTRS, static_lastMatch_getter, NULL},
-    {"$+",           0, RO_HIDDEN_PROP_ATTRS, static_lastParen_getter, NULL},
-    {"$`",           0, RO_HIDDEN_PROP_ATTRS, static_leftContext_getter, NULL},
-    {"$'",           0, RO_HIDDEN_PROP_ATTRS, static_rightContext_getter, NULL},
-    {0,0,0,0,0}
+    {"input",        0, REGEXP_STATIC_PROP_ATTRS,    JSOP_WRAPPER(static_input_getter),
+                                                     JSOP_WRAPPER(static_input_setter)},
+    {"multiline",    0, REGEXP_STATIC_PROP_ATTRS,    JSOP_WRAPPER(static_multiline_getter),
+                                                     JSOP_WRAPPER(static_multiline_setter)},
+    {"lastMatch",    0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_lastMatch_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"lastParen",    0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_lastParen_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"leftContext",  0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_leftContext_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"rightContext", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_rightContext_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$1",           0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren1_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$2",           0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren2_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$3",           0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren3_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$4",           0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren4_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$5",           0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren5_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$6",           0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren6_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$7",           0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren7_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$8",           0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren8_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$9",           0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren9_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$_",           0, HIDDEN_PROP_ATTRS,           JSOP_WRAPPER(static_input_getter),
+                                                     JSOP_WRAPPER(static_input_setter)},
+    {"$*",           0, HIDDEN_PROP_ATTRS,           JSOP_WRAPPER(static_multiline_getter),
+                                                     JSOP_WRAPPER(static_multiline_setter)},
+    {"$&",           0, RO_HIDDEN_PROP_ATTRS,        JSOP_WRAPPER(static_lastMatch_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$+",           0, RO_HIDDEN_PROP_ATTRS,        JSOP_WRAPPER(static_lastParen_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$`",           0, RO_HIDDEN_PROP_ATTRS,        JSOP_WRAPPER(static_leftContext_getter),
+                                                     JSOP_NULLWRAPPER},
+    {"$'",           0, RO_HIDDEN_PROP_ATTRS,        JSOP_WRAPPER(static_rightContext_getter),
+                                                     JSOP_NULLWRAPPER},
+    {0,0,0,JSOP_NULLWRAPPER,JSOP_NULLWRAPPER}
 };
 
 JSObject *
 js_InitRegExpClass(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj->isNative());
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -842,17 +842,17 @@ static JSFunctionSpecWithHelp TestingFun
 "  Terminate JavaScript execution, as if we had run out of\n"
 "  memory or been terminated by the slow script dialog."),
 
     JS_FN_HELP("enableSPSProfilingAssertions", EnableSPSProfilingAssertions, 1, 0,
 "enableSPSProfilingAssertions(enabled)",
 "  Enables or disables the assertions related to SPS profiling. This is fairly\n"
 "  expensive, so it shouldn't be enabled normally."),
 
-    JS_FS_END
+    JS_FS_HELP_END
 };
 
 namespace js {
 
 bool
 DefineTestingFunctions(JSContext *cx, HandleObject obj)
 {
     return JS_DefineFunctionsWithHelp(cx, obj, TestingFunctions);
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -115,16 +115,27 @@ OS_CONFIG	:= $(OS_ARCH)$(OS_RELEASE)
 
 FINAL_LINK_LIBS = $(DEPTH)/config/final-link-libs
 FINAL_LINK_COMPS = $(DEPTH)/config/final-link-comps
 FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names
 
 MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
 MOZ_WIDGET_SUPPORT_LIBS    = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
 
+ifdef _MSC_VER
+ifdef .PYMAKE
+PYCOMMANDPATH += $(topsrcdir)/build
+CC_WRAPPER ?= %cl InvokeClWithDependencyGeneration
+CXX_WRAPPER ?= %cl InvokeClWithDependencyGeneration
+else
+CC_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
+CXX_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
+endif # .PYMAKE
+endif # _MSC_VER
+
 CC := $(CC_WRAPPER) $(CC)
 CXX := $(CXX_WRAPPER) $(CXX)
 MKDIR ?= mkdir
 SLEEP ?= sleep
 TOUCH ?= touch
 
 ifdef .PYMAKE
 PYCOMMANDPATH += $(topsrcdir)/config
@@ -557,30 +568,29 @@ PBBUILD_SETTINGS = GCC_VERSION="$(GCC_VE
 ifdef MACOS_SDK_DIR
 PBBUILD_SETTINGS += SDKROOT="$(MACOS_SDK_DIR)"
 endif # MACOS_SDK_DIR
 ifdef MACOSX_DEPLOYMENT_TARGET
 export MACOSX_DEPLOYMENT_TARGET
 PBBUILD_SETTINGS += MACOSX_DEPLOYMENT_TARGET="$(MACOSX_DEPLOYMENT_TARGET)"
 endif # MACOSX_DEPLOYMENT_TARGET
 
-ifdef MOZ_USING_CCACHE
-ifdef CLANG_CXX
-export CCACHE_CPP2=1
-endif
-endif
-
 ifdef MOZ_OPTIMIZE
 ifeq (2,$(MOZ_OPTIMIZE))
 # Only override project defaults if the config specified explicit settings
 PBBUILD_SETTINGS += GCC_MODEL_TUNING= OPTIMIZATION_CFLAGS="$(MOZ_OPTIMIZE_FLAGS)"
 endif # MOZ_OPTIMIZE=2
 endif # MOZ_OPTIMIZE
 endif # OS_ARCH=Darwin
 
+ifdef MOZ_USING_CCACHE
+ifdef CLANG_CXX
+export CCACHE_CPP2=1
+endif
+endif
 
 ifdef MOZ_NATIVE_MAKEDEPEND
 MKDEPEND_DIR =
 MKDEPEND = $(MOZ_NATIVE_MAKEDEPEND)
 else
 MKDEPEND_DIR = $(CONFIG_TOOLS)/mkdepend
 MKDEPEND = $(MKDEPEND_DIR)/mkdepend$(BIN_SUFFIX)
 endif
--- a/js/src/config/makefiles/xpidl.mk
+++ b/js/src/config/makefiles/xpidl.mk
@@ -34,16 +34,18 @@ ifndef INCLUDED_XPIDL_MK #{
 endif #} INCLUDED_XPIDL_MK
 
 
 ###########################################################################
 ## processing targets
 ###########################################################################
 ifdef _xpidl-todo_ #{
 
+$(call requiredfunction,install_cmd)
+
 ## Logic batch #1
 xpidl-install-src-preqs=\
   $(XPIDLSRCS) \
   $(call mkdir_deps,$(IDL_DIR)) \
   $(NULL)
 
 xpidl-install-src: $(xpidl-install-src-preqs)
 	$(call install_cmd,$(IFLAGS1) $(foreach val,$^,$(call mkdir_stem,$(val))))
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1769,16 +1769,17 @@ CHECK_FROZEN_VARIABLES = $(foreach var,$
   $(if $(subst $($(var)_FROZEN),,'$($(var))'),$(error Makefile variable '$(var)' changed value after including rules.mk. Was $($(var)_FROZEN), now $($(var)).)))
 
 libs export::
 	$(CHECK_FROZEN_VARIABLES)
 
 default all::
 	if test -d $(DIST)/bin ; then touch $(DIST)/bin/.purgecaches ; fi
 
+.DEFAULT_GOAL ?= default
 
 #############################################################################
 # Derived targets and dependencies
 
 include $(topsrcdir)/config/makefiles/autotargets.mk
 ifneq ($(NULL),$(AUTO_DEPS))
   default all libs tools export:: $(AUTO_DEPS)
 endif
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -590,16 +590,17 @@ Processes.h
 process.h
 Process.h
 proto/dos.h
 proto/exec.h
 psap.h
 Pt.h
 pthread.h
 pthread_np.h
+pulse/pulseaudio.h
 pwd.h
 Python.h
 QDOffscreen.h
 queue
 Quickdraw.h
 QuickDraw.h
 QuickTimeComponents.h
 quipu/attr.h
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -177,17 +177,17 @@ if test -n "$gonkdir" ; then
         ;;
     i?86)
         ARCH_DIR=arch-x86
         ;;
     esac
 
     CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/system/core/include -isystem $gonkdir/bionic $CPPFLAGS"
     CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
-    CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS $STLPORT_CPPFLAGS"
+    CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS $STLPORT_CPPFLAGS"
     LIBS="$LIBS $STLPORT_LIBS"
 
     dnl Add -llog by default, since we use it all over the place.
     LDFLAGS="-mandroid -L$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib -Wl,-rpath-link=$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib --sysroot=$gonkdir/out/target/product/$GONK_PRODUCT/obj/ -llog $LDFLAGS"
 
     dnl prevent cross compile section from using these flags as host flags
     if test -z "$HOST_CPPFLAGS" ; then
         HOST_CPPFLAGS=" "
@@ -4131,31 +4131,24 @@ else
     changequote(,)
     CL_INCLUDES_PREFIX=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/^\([^:]*:[^:]*:\).*stdio.h$/\1/p'`
     changequote([,])
     if test -z "$CL_INCLUDES_PREFIX"; then
         AC_MSG_ERROR([Cannot find cl -showIncludes prefix.])
     fi
     AC_SUBST(CL_INCLUDES_PREFIX)
     rm -f dummy-hello.c
-    _topsrcdirwin=`cd \`dirname $0\`; pwd -W`
-    dnl cl.py provides dependency generation for MSVC
-    CC_WRAPPER="$PYTHON -O $_topsrcdirwin/build/cl.py"
-    CXX_WRAPPER="$PYTHON -O $_topsrcdirwin/build/cl.py"
     COMPILER_DEPEND=1
   fi
 fi
 fi # MOZ_AUTO_DEPS
 MDDEPDIR='.deps'
 AC_SUBST(MOZ_AUTO_DEPS)
 AC_SUBST(COMPILER_DEPEND)
 AC_SUBST(MDDEPDIR)
-AC_SUBST(CC_WRAPPER)
-AC_SUBST(CXX_WRAPPER)
-
 
 dnl ========================================================
 dnl = Link js shell to system readline
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(readline,
 [  --enable-readline       Link js shell to system readline library],
     JS_WANT_READLINE=1,
     JS_WANT_READLINE= )
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -430,21 +430,21 @@ static JSClass sCDataFinalizerClass = {
 
 #define CDATAFN_FLAGS \
   (JSPROP_READONLY | JSPROP_PERMANENT)
 
 #define CDATAFINALIZERFN_FLAGS \
   (JSPROP_READONLY | JSPROP_PERMANENT)
 
 static JSPropertySpec sCTypeProps[] = {
-  { "name", 0, CTYPESPROP_FLAGS, CType::NameGetter, NULL },
-  { "size", 0, CTYPESPROP_FLAGS, CType::SizeGetter, NULL },
-  { "ptr", 0, CTYPESPROP_FLAGS, CType::PtrGetter, NULL },
-  { "prototype", 0, CTYPESPROP_FLAGS, CType::PrototypeGetter, NULL },
-  { 0, 0, 0, NULL, NULL }
+  { "name", 0, CTYPESPROP_FLAGS, JSOP_WRAPPER(CType::NameGetter), JSOP_NULLWRAPPER },
+  { "size", 0, CTYPESPROP_FLAGS, JSOP_WRAPPER(CType::SizeGetter), JSOP_NULLWRAPPER },
+  { "ptr", 0, CTYPESPROP_FLAGS, JSOP_WRAPPER(CType::PtrGetter), JSOP_NULLWRAPPER },
+  { "prototype", 0, CTYPESPROP_FLAGS, JSOP_WRAPPER(CType::PrototypeGetter), JSOP_NULLWRAPPER },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sCTypeFunctions[] = {
   JS_FN("array", CType::CreateArray, 0, CTYPESFN_FLAGS),
   JS_FN("toString", CType::ToString, 0, CTYPESFN_FLAGS),
   JS_FN("toSource", CType::ToSource, 0, CTYPESFN_FLAGS),
   JS_FS_END
 };
@@ -452,109 +452,118 @@ static JSFunctionSpec sCTypeFunctions[] 
 static JSFunctionSpec sCABIFunctions[] = {
   JS_FN("toSource", ABI::ToSource, 0, CABIFN_FLAGS),
   JS_FN("toString", ABI::ToSource, 0, CABIFN_FLAGS),
   JS_FS_END
 };
 
 static JSPropertySpec sCDataProps[] = {
   { "value", 0, JSPROP_SHARED | JSPROP_PERMANENT,
-    CData::ValueGetter, CData::ValueSetter },
-  { 0, 0, 0, NULL, NULL }
+    JSOP_WRAPPER(CData::ValueGetter), JSOP_WRAPPER(CData::ValueSetter) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sCDataFunctions[] = {
   JS_FN("address", CData::Address, 0, CDATAFN_FLAGS),
   JS_FN("readString", CData::ReadString, 0, CDATAFN_FLAGS),
   JS_FN("toSource", CData::ToSource, 0, CDATAFN_FLAGS),
   JS_FN("toString", CData::ToSource, 0, CDATAFN_FLAGS),
   JS_FS_END
 };
 
 static JSPropertySpec sCDataFinalizerProps[] = {
-  { 0, 0, 0, NULL, NULL }
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sCDataFinalizerFunctions[] = {
   JS_FN("dispose",  CDataFinalizer::Methods::Dispose,  0, CDATAFINALIZERFN_FLAGS),
   JS_FN("forget",   CDataFinalizer::Methods::Forget,   0, CDATAFINALIZERFN_FLAGS),
   JS_FN("readString",CData::ReadString, 0, CDATAFINALIZERFN_FLAGS),
   JS_FN("toString", CDataFinalizer::Methods::ToString, 0, CDATAFINALIZERFN_FLAGS),
   JS_FN("toSource", CDataFinalizer::Methods::ToSource, 0, CDATAFINALIZERFN_FLAGS),
   JS_FS_END
 };
 
 static JSFunctionSpec sPointerFunction =
   JS_FN("PointerType", PointerType::Create, 1, CTYPESCTOR_FLAGS);
 
 static JSPropertySpec sPointerProps[] = {
-  { "targetType", 0, CTYPESPROP_FLAGS, PointerType::TargetTypeGetter, NULL },
-  { 0, 0, 0, NULL, NULL }
+  { "targetType", 0, CTYPESPROP_FLAGS,
+    JSOP_WRAPPER(PointerType::TargetTypeGetter), JSOP_NULLWRAPPER },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sPointerInstanceFunctions[] = {
   JS_FN("isNull", PointerType::IsNull, 0, CTYPESFN_FLAGS),
   JS_FN("increment", PointerType::Increment, 0, CTYPESFN_FLAGS),
   JS_FN("decrement", PointerType::Decrement, 0, CTYPESFN_FLAGS),
   JS_FS_END
 };
-  
+
 static JSPropertySpec sPointerInstanceProps[] = {
   { "contents", 0, JSPROP_SHARED | JSPROP_PERMANENT,
-    PointerType::ContentsGetter, PointerType::ContentsSetter },
-  { 0, 0, 0, NULL, NULL }
+    JSOP_WRAPPER(PointerType::ContentsGetter),
+    JSOP_WRAPPER(PointerType::ContentsSetter) },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sArrayFunction =
   JS_FN("ArrayType", ArrayType::Create, 1, CTYPESCTOR_FLAGS);
 
 static JSPropertySpec sArrayProps[] = {
-  { "elementType", 0, CTYPESPROP_FLAGS, ArrayType::ElementTypeGetter, NULL },
-  { "length", 0, CTYPESPROP_FLAGS, ArrayType::LengthGetter, NULL },
-  { 0, 0, 0, NULL, NULL }
+  { "elementType", 0, CTYPESPROP_FLAGS,
+    JSOP_WRAPPER(ArrayType::ElementTypeGetter), JSOP_NULLWRAPPER },
+  { "length", 0, CTYPESPROP_FLAGS,
+    JSOP_WRAPPER(ArrayType::LengthGetter), JSOP_NULLWRAPPER },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sArrayInstanceFunctions[] = {
   JS_FN("addressOfElement", ArrayType::AddressOfElement, 1, CDATAFN_FLAGS),
   JS_FS_END
 };
 
 static JSPropertySpec sArrayInstanceProps[] = {
   { "length", 0, JSPROP_SHARED | JSPROP_READONLY | JSPROP_PERMANENT,
-    ArrayType::LengthGetter, NULL },
-  { 0, 0, 0, NULL, NULL }
+    JSOP_WRAPPER(ArrayType::LengthGetter), JSOP_NULLWRAPPER },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sStructFunction =
   JS_FN("StructType", StructType::Create, 2, CTYPESCTOR_FLAGS);
 
 static JSPropertySpec sStructProps[] = {
-  { "fields", 0, CTYPESPROP_FLAGS, StructType::FieldsArrayGetter, NULL },
-  { 0, 0, 0, NULL, NULL }
+  { "fields", 0, CTYPESPROP_FLAGS,
+    JSOP_WRAPPER(StructType::FieldsArrayGetter), JSOP_NULLWRAPPER },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sStructFunctions[] = {
   JS_FN("define", StructType::Define, 1, CDATAFN_FLAGS),
   JS_FS_END
 };
 
 static JSFunctionSpec sStructInstanceFunctions[] = {
   JS_FN("addressOfField", StructType::AddressOfField, 1, CDATAFN_FLAGS),
   JS_FS_END
 };
 
 static JSFunctionSpec sFunctionFunction =
   JS_FN("FunctionType", FunctionType::Create, 2, CTYPESCTOR_FLAGS);
 
 static JSPropertySpec sFunctionProps[] = {
-  { "argTypes", 0, CTYPESPROP_FLAGS, FunctionType::ArgTypesGetter, NULL },
-  { "returnType", 0, CTYPESPROP_FLAGS, FunctionType::ReturnTypeGetter, NULL },
-  { "abi", 0, CTYPESPROP_FLAGS, FunctionType::ABIGetter, NULL },
-  { "isVariadic", 0, CTYPESPROP_FLAGS, FunctionType::IsVariadicGetter, NULL },
-  { 0, 0, 0, NULL, NULL }
+  { "argTypes", 0, CTYPESPROP_FLAGS,
+    JSOP_WRAPPER(FunctionType::ArgTypesGetter), JSOP_NULLWRAPPER },
+  { "returnType", 0, CTYPESPROP_FLAGS,
+    JSOP_WRAPPER(FunctionType::ReturnTypeGetter), JSOP_NULLWRAPPER },
+  { "abi", 0, CTYPESPROP_FLAGS,
+    JSOP_WRAPPER(FunctionType::ABIGetter), JSOP_NULLWRAPPER },
+  { "isVariadic", 0, CTYPESPROP_FLAGS,
+    JSOP_WRAPPER(FunctionType::IsVariadicGetter), JSOP_NULLWRAPPER },
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sFunctionInstanceFunctions[] = {
   JS_FN("call", js_fun_call, 1, CDATAFN_FLAGS),
   JS_FN("apply", js_fun_apply, 2, CDATAFN_FLAGS),
   JS_FS_END
 };
 
@@ -611,22 +620,22 @@ static JSFunctionSpec sInt64Functions[] 
 static JSFunctionSpec sUInt64Functions[] = {
   JS_FN("toString", UInt64::ToString, 0, CTYPESFN_FLAGS),
   JS_FN("toSource", UInt64::ToSource, 0, CTYPESFN_FLAGS),
   JS_FS_END
 };
 
 static JSPropertySpec sModuleProps[] = {
   { "errno", 0, JSPROP_SHARED | JSPROP_PERMANENT,
-    CData::ErrnoGetter, NULL },
+    JSOP_WRAPPER(CData::ErrnoGetter), JSOP_NULLWRAPPER },
 #if defined(XP_WIN)
   { "winLastError", 0, JSPROP_SHARED | JSPROP_PERMANENT,
-    CData::LastErrorGetter, NULL },
+    JSOP_WRAPPER(CData::LastErrorGetter), JSOP_NULLWRAPPER },
 #endif // defined(XP_WIN)
-  { 0, 0, 0, NULL, NULL }
+  { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }
 };
 
 static JSFunctionSpec sModuleFunctions[] = {
   JS_FN("CDataFinalizer", CDataFinalizer::Construct, 2, CTYPESFN_FLAGS),
   JS_FN("open", Library::Open, 1, CTYPESFN_FLAGS),
   JS_FN("cast", CData::Cast, 2, CTYPESFN_FLAGS),
   JS_FN("getRuntime", CData::GetRuntime, 1, CTYPESFN_FLAGS),
   JS_FN("libraryName", Library::Name, 1, CTYPESFN_FLAGS),
@@ -818,17 +827,17 @@ InitTypeConstructor(JSContext* cx,
                     JSFunctionSpec spec,
                     JSFunctionSpec* fns,
                     JSPropertySpec* props,
                     JSFunctionSpec* instanceFns,
                     JSPropertySpec* instanceProps,
                     MutableHandleObject typeProto,
                     MutableHandleObject dataProto)
 {
-  JSFunction* fun = js::DefineFunctionWithReserved(cx, parent, spec.name, spec.call, 
+  JSFunction* fun = js::DefineFunctionWithReserved(cx, parent, spec.name, spec.call.op,
                       spec.nargs, spec.flags);
   if (!fun)
     return false;
 
   RootedObject obj(cx, JS_GetFunctionObject(fun));
   if (!obj)
     return false;
 
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -60,24 +60,32 @@ frontend::CompileScript(JSContext *cx, H
      * The scripted callerFrame can only be given for compile-and-go scripts
      * and non-zero static level requires callerFrame.
      */
     JS_ASSERT_IF(callerFrame, options.compileAndGo);
     JS_ASSERT_IF(staticLevel != 0, callerFrame);
 
     if (!CheckLength(cx, length))
         return NULL;
+    JS_ASSERT_IF(staticLevel != 0, options.sourcePolicy != CompileOptions::LAZY_SOURCE);
     ScriptSource *ss = cx->new_<ScriptSource>();
     if (!ss)
         return NULL;
     ScriptSourceHolder ssh(cx->runtime, ss);
     SourceCompressionToken sct(cx);
-    if (!cx->hasRunOption(JSOPTION_ONLY_CNG_SOURCE) || options.compileAndGo) {
+    switch (options.sourcePolicy) {
+      case CompileOptions::SAVE_SOURCE:
         if (!ss->setSourceCopy(cx, chars, length, false, &sct))
             return NULL;
+        break;
+      case CompileOptions::LAZY_SOURCE:
+        ss->setSourceRetrievable();
+        break;
+      case CompileOptions::NO_SOURCE:
+        break;
     }
 
     Parser parser(cx, options, chars, length, /* foldConstants = */ true);
     if (!parser.init())
         return NULL;
     parser.sct = &sct;
 
     SharedContext sc(cx, scopeChain, /* fun = */ NULL, /* funbox = */ NULL, StrictModeFromContext(cx));
@@ -231,18 +239,21 @@ frontend::CompileFunctionBody(JSContext 
 {
     if (!CheckLength(cx, length))
         return NULL;
     ScriptSource *ss = cx->new_<ScriptSource>();
     if (!ss)
         return NULL;
     ScriptSourceHolder ssh(cx->runtime, ss);
     SourceCompressionToken sct(cx);
-    if (!ss->setSourceCopy(cx, chars, length, true, &sct))
-        return NULL;
+    JS_ASSERT(options.sourcePolicy != CompileOptions::LAZY_SOURCE);
+    if (options.sourcePolicy == CompileOptions::SAVE_SOURCE) {
+        if (!ss->setSourceCopy(cx, chars, length, true, &sct))
+            return NULL;
+    }
 
     options.setCompileAndGo(false);
     Parser parser(cx, options, chars, length, /* foldConstants = */ true);
     if (!parser.init())
         return false;
     parser.sct = &sct;
 
     JS_ASSERT(fun);
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1092,16 +1092,17 @@ LeaveFunction(ParseNode *fn, Parser *par
               FunctionSyntaxKind kind = Expression)
 {
     TreeContext *funtc = parser->tc;
     TreeContext *tc = funtc->parent;
     tc->blockidGen = funtc->blockidGen;
 
     FunctionBox *funbox = fn->pn_funbox;
     funbox->cxFlags = funtc->sc->cxFlags;   // copy all the flags
+    funbox->kids = funtc->functionList;
 
     if (!tc->topStmt || tc->topStmt->type == STMT_BLOCK)
         fn->pn_dflags |= PND_BLOCKCHILD;
 
     /*
      * Propagate unresolved lexical names up to tc->lexdeps, and save a copy
      * of funtc->lexdeps in a TOK_UPVARS node wrapping the function's formal
      * params and body. We do this only if there are lexical dependencies not
@@ -1722,18 +1723,16 @@ Parser::functionDef(HandlePropertyName f
                 if (!outertc->funcStmts || !outertc->funcStmts->init())
                     return NULL;
             }
             if (!outertc->funcStmts->put(funName))
                 return NULL;
         }
     }
 
-    funbox->kids = funtc.functionList;
-
     pn->pn_funbox = funbox;
     pn->setOp(op);
     pn->pn_body->append(body);
     pn->pn_body->pn_pos = body->pn_pos;
 
     JS_ASSERT_IF(!outertc->sc->inFunction() && bodyLevel && kind == Statement,
                  pn->pn_cookie.isFree());
 
--- a/js/src/jit-test/tests/arguments/defaults-strict-mode.js
+++ b/js/src/jit-test/tests/arguments/defaults-strict-mode.js
@@ -4,16 +4,17 @@ function f1(f=(function () { return type
 assertEq(f1()(), true);
 function f2(f=(function () { "use strict"; return (function () { return typeof this !== "object"; }) })) { assertEq(typeof this, "object"); return f; }
 assertEq(f2()()(), true);
 function f3(f=(function () { return (function () { return typeof this !== "object"; }) })) { "use strict"; return f; }
 assertEq(f3()()(), true);
 // These should be okay.
 function f4(f=(function () { with (Object) {} }), g=(function () { "use strict"; })) {}
 function f5(g=(function () { "use strict"; }), f=(function () { with (Object) {} })) {}
+function f6(f=(function () { return (x for (y in (function g() {}))); })) {}
 
 assertThrowsInstanceOf(function () {
     eval("function f(a=delete x) { 'use strict'; }");
 }, SyntaxError);
 assertThrowsInstanceOf(function () {
     Math.sin(4);
     eval("function f(a='\\251') { 'use strict'; }");
 }, SyntaxError);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testBug780712.js
@@ -0,0 +1,9 @@
+r = evalcx("/x/", undefined);
+s = "";
+gc()
+Function("\
+    s.match(r);\
+    schedulegc(__proto__);\
+    ({c:schedulegc(2)});\
+    s.match(r);\
+")()
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -829,16 +829,17 @@ JSRuntime::JSRuntime()
     gcLock(NULL),
     gcHelperThread(thisFromCtor()),
 #ifdef JS_THREADSAFE
     sourceCompressorThread(thisFromCtor()),
 #endif
     defaultFreeOp_(thisFromCtor(), false, false),
     debuggerMutations(0),
     securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)),
+    DOMcallbacks(NULL),
     destroyPrincipals(NULL),
     structuredCloneCallbacks(NULL),
     telemetryCallback(NULL),
     propertyRemovals(0),
     thousandsSeparator(0),
     decimalSeparator(0),
     numGrouping(0),
     waiveGCQuota(false),
@@ -3798,21 +3799,44 @@ JS_PUBLIC_API(JSBool)
 JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
                            JSBool *foundp)
 {
     RootedObject obj(cx, objArg);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     return atom && JS_AlreadyHasOwnPropertyById(cx, obj, AtomToId(atom), foundp);
 }
 
+/* Wrapper functions to create wrappers with no corresponding JSJitInfo from API
+ * function arguments.
+ */
+static JSPropertyOpWrapper
+GetterWrapper(JSPropertyOp getter)
+{
+    JSPropertyOpWrapper ret;
+    ret.op = getter;
+    ret.info = NULL;
+    return ret;
+}
+
+static JSStrictPropertyOpWrapper
+SetterWrapper(JSStrictPropertyOp setter)
+{
+    JSStrictPropertyOpWrapper ret;
+    ret.op = setter;
+    ret.info = NULL;
+    return ret;
+}
+
 static JSBool
 DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
-                   PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
-                   unsigned flags, int tinyid)
-{
+                   const JSPropertyOpWrapper &get, const JSStrictPropertyOpWrapper &set,
+                   unsigned attrs, unsigned flags, int tinyid)
+{
+    PropertyOp getter = get.op;
+    StrictPropertyOp setter = set.op;
     /*
      * JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
      * throw if this happens, but we've accepted it for long enough that it's
      * not worth trying to make callers change their ways. Just flip it off on
      * its way through the API layer so that we can enforce this internally.
      */
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
         attrs &= ~JSPROP_READONLY;
@@ -3823,29 +3847,37 @@ DefinePropertyById(JSContext *cx, Handle
      * of something with JSNative property descriptors. If we are, wrap them in
      * JS Function objects.
      */
     if (attrs & JSPROP_NATIVE_ACCESSORS) {
         JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
         attrs &= ~JSPROP_NATIVE_ACCESSORS;
         if (getter) {
             RootedObject global(cx, (JSObject*) &obj->global());
-            JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, global, NULL);
+            JSFunction *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, global, NULL);
             if (!getobj)
                 return false;
+
+            if (get.info)
+                getobj->setJitInfo(get.info);
+
             getter = JS_DATA_TO_FUNC_PTR(PropertyOp, getobj);
             attrs |= JSPROP_GETTER;
         }
         if (setter) {
             // Root just the getter, since the setter is not yet a JSObject.
             AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, NULL);
             RootedObject global(cx, (JSObject*) &obj->global());
-            JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, global, NULL);
+            JSFunction *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, global, NULL);
             if (!setobj)
                 return false;
+
+            if (set.info)
+                setobj->setJitInfo(set.info);
+
             setter = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setobj);
             attrs |= JSPROP_SETTER;
         }
     }
 
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -3867,41 +3899,44 @@ DefinePropertyById(JSContext *cx, Handle
 
 JS_PUBLIC_API(JSBool)
 JS_DefinePropertyById(JSContext *cx, JSObject *objArg, jsid idArg, jsval value_,
                       JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
     RootedId id(cx, idArg);
     RootedValue value(cx, value_);
-    return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
+    return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter),
+                              SetterWrapper(setter), attrs, 0, 0);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineElement(JSContext *cx, JSObject *objArg, uint32_t index, jsval valueArg,
                  JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
     RootedValue value(cx, valueArg);
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     RootedId id(cx);
     if (!IndexToId(cx, index, id.address()))
         return false;
-    return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
+    return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter),
+                              SetterWrapper(setter), attrs, 0, 0);
 }
 
 static JSBool
 DefineProperty(JSContext *cx, JSHandleObject obj, const char *name, const Value &value_,
-               PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
-               unsigned flags, int tinyid)
+               const JSPropertyOpWrapper &getter, const JSStrictPropertyOpWrapper &setter,
+               unsigned attrs, unsigned flags, int tinyid)
 {
     RootedValue value(cx, value_);
-    AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
+    AutoRooterGetterSetter gsRoot(cx, attrs, const_cast<JSPropertyOp *>(&getter.op),
+                                  const_cast<JSStrictPropertyOp *>(&setter.op));
     RootedId id(cx);
 
     if (attrs & JSPROP_INDEX) {
         id = INT_TO_JSID(intptr_t(name));
         attrs &= ~JSPROP_INDEX;
     } else {
         JSAtom *atom = js_Atomize(cx, name, strlen(name));
         if (!atom)
@@ -3912,39 +3947,42 @@ DefineProperty(JSContext *cx, JSHandleOb
     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineProperty(JSContext *cx, JSObject *objArg, const char *name, jsval value,
                   PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
-    return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
+    return DefineProperty(cx, obj, name, value, GetterWrapper(getter),
+                          SetterWrapper(setter), attrs, 0, 0);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *objArg, const char *name, int8_t tinyid,
                             jsval value, PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
-    return DefineProperty(cx, obj, name, value, getter, setter, attrs, Shape::HAS_SHORTID, tinyid);
+    return DefineProperty(cx, obj, name, value, GetterWrapper(getter),
+                          SetterWrapper(setter), attrs, Shape::HAS_SHORTID, tinyid);
 }
 
 static JSBool
 DefineUCProperty(JSContext *cx, JSHandleObject obj, const jschar *name, size_t namelen,
                  const Value &value_, PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                  unsigned flags, int tinyid)
 {
     RootedValue value(cx, value_);
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     if (!atom)
         return false;
     RootedId id(cx, AtomToId(atom));
-    return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid);
+    return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter),
+                              SetterWrapper(setter), attrs, flags, tinyid);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
                     jsval value, JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0, 0);
@@ -3985,37 +4023,42 @@ JS_DefineObject(JSContext *cx, JSObject 
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
     RootedObject nobj(cx, NewObjectWithClassProto(cx, clasp, proto, obj));
     if (!nobj)
         return NULL;
 
-    if (!DefineProperty(cx, obj, name, ObjectValue(*nobj), NULL, NULL, attrs, 0, 0))
+    if (!DefineProperty(cx, obj, name, ObjectValue(*nobj), GetterWrapper(NULL),
+                        SetterWrapper(NULL), attrs, 0, 0))
+    {
         return NULL;
+    }
 
     return nobj;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineConstDoubles(JSContext *cx, JSObject *objArg, JSConstDoubleSpec *cds)
 {
     RootedObject obj(cx, objArg);
     JSBool ok;
     unsigned attrs;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
+    JSPropertyOpWrapper noget = GetterWrapper(NULL);
+    JSStrictPropertyOpWrapper noset = SetterWrapper(NULL);
     for (ok = JS_TRUE; cds->name; cds++) {
         Value value = DoubleValue(cds->dval);
         attrs = cds->flags;
         if (!attrs)
             attrs = JSPROP_READONLY | JSPROP_PERMANENT;
-        ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, attrs, 0, 0);
+        ok = DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0, 0);
         if (!ok)
             break;
     }
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineProperties(JSContext *cx, JSObject *objArg, JSPropertySpec *ps)
@@ -4951,17 +4994,17 @@ js_generic_native_method_dispatcher(JSCo
      * call the corresponding prototype native method with our first argument
      * passed as |this|.
      */
     memmove(vp + 1, vp + 2, argc * sizeof(jsval));
 
     /* Clear the last parameter in case too few arguments were passed. */
     vp[2 + --argc].setUndefined();
 
-    return fs->call(cx, argc, vp);
+    return fs->call.op(cx, argc, vp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineFunctions(JSContext *cx, JSObject *objArg, JSFunctionSpec *fs)
 {
     RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     unsigned flags;
@@ -4999,19 +5042,21 @@ JS_DefineFunctions(JSContext *cx, JSObje
 
             /*
              * As jsapi.h notes, fs must point to storage that lives as long
              * as fun->object lives.
              */
             fun->setExtendedSlot(0, PrivateValue(fs));
         }
 
-        fun = js_DefineFunction(cx, obj, id, fs->call, fs->nargs, flags);
+        fun = js_DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags);
         if (!fun)
             return JS_FALSE;
+        if (fs->call.info)
+            fun->setJitInfo(fs->call.info);
     }
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_DefineFunction(JSContext *cx, JSObject *objArg, const char *name, JSNative call,
                   unsigned nargs, unsigned attrs)
 {
@@ -5163,17 +5208,18 @@ JS::CompileOptions::CompileOptions(JSCon
       originPrincipals(NULL),
       version(cx->findVersion()),
       versionSet(false),
       utf8(false),
       filename(NULL),
       lineno(1),
       compileAndGo(cx->hasRunOption(JSOPTION_COMPILE_N_GO)),
       noScriptRval(cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL)),
-      allowIntrinsicsCalls(false)
+      allowIntrinsicsCalls(false),
+      sourcePolicy(SAVE_SOURCE)
 {
 }
 
 JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options,
             const jschar *chars, size_t length)
 {
     Maybe<AutoVersionAPI> mava;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2864,17 +2864,17 @@ ToUint64(JSContext *cx, const js::Value 
 {
     AssertArgumentsAreSane(cx, v);
     {
         SkipRoot skip(cx, &v);
         MaybeCheckStackRoots(cx);
     }
 
     if (v.isInt32()) {
-        // Account for sign extension of negatives into the longer 64bit space.
+        /* Account for sign extension of negatives into the longer 64bit space. */
         *out = uint64_t(int64_t(v.toInt32()));
         return true;
     }
 
     return js::ToUint64Slow(cx, v, out);
 }
 
 
@@ -3217,24 +3217,23 @@ JS_StringToVersion(const char *string);
                                                    don't tune at run-time. */
 #define JSOPTION_PCCOUNT        JS_BIT(17)      /* Collect per-op execution counts */
 
 #define JSOPTION_TYPE_INFERENCE JS_BIT(18)      /* Perform type inference. */
 #define JSOPTION_STRICT_MODE    JS_BIT(19)      /* Provides a way to force
                                                    strict mode for all code
                                                    without requiring
                                                    "use strict" annotations. */
-/* JS_BIT(20) is taken in jsfriendapi.h! */
-
-#define JSOPTION_ION            JS_BIT(21)      /* IonMonkey */
+
+#define JSOPTION_ION            JS_BIT(20)      /* IonMonkey */
 
 /* Options which reflect compile-time properties of scripts. */
 #define JSCOMPILEOPTION_MASK    (JSOPTION_ALLOW_XML | JSOPTION_MOAR_XML)
 
-#define JSRUNOPTION_MASK        (JS_BITMASK(22) & ~JSCOMPILEOPTION_MASK)
+#define JSRUNOPTION_MASK        (JS_BITMASK(21) & ~JSCOMPILEOPTION_MASK)
 #define JSALLOPTION_MASK        (JSCOMPILEOPTION_MASK | JSRUNOPTION_MASK)
 
 extern JS_PUBLIC_API(uint32_t)
 JS_GetOptions(JSContext *cx);
 
 extern JS_PUBLIC_API(uint32_t)
 JS_SetOptions(JSContext *cx, uint32_t options);
 
@@ -4334,51 +4333,85 @@ JS_ConvertStub(JSContext *cx, JSHandleOb
 
 struct JSConstDoubleSpec {
     double          dval;
     const char      *name;
     uint8_t         flags;
     uint8_t         spare[3];
 };
 
+typedef struct JSJitInfo JSJitInfo;
+
+/*
+ * Wrappers to replace {Strict,}PropertyOp for JSPropertySpecs. This will allow
+ * us to pass one JSJitInfo per function with the property spec, without
+ * additional field overhead.
+ */
+typedef struct JSStrictPropertyOpWrapper {
+    JSStrictPropertyOp  op;
+    const JSJitInfo     *info;
+} JSStrictPropertyOpWrapper;
+
+typedef struct JSPropertyOpWrapper {
+    JSPropertyOp        op;
+    const JSJitInfo     *info;
+} JSPropertyOpWrapper;
+
+/*
+ * Wrapper to do as above, but for JSNatives for JSFunctionSpecs.
+ */
+typedef struct JSNativeWrapper {
+    JSNative        op;
+    const JSJitInfo *info;
+} JSNativeWrapper;
+
+/*
+ * Macro static initializers which make it easy to pass no JSJitInfo as part of a
+ * JSPropertySpec or JSFunctionSpec.
+ */
+#define JSOP_WRAPPER(op) {op, NULL}
+#define JSOP_NULLWRAPPER JSOP_WRAPPER(NULL)
+
 /*
  * To define an array element rather than a named property member, cast the
  * element's index to (const char *) and initialize name with it, and set the
  * JSPROP_INDEX bit in flags.
  */
 struct JSPropertySpec {
-    const char            *name;
-    int8_t                tinyid;
-    uint8_t               flags;
-    JSPropertyOp          getter;
-    JSStrictPropertyOp    setter;
+    const char                  *name;
+    int8_t                      tinyid;
+    uint8_t                     flags;
+    JSPropertyOpWrapper         getter;
+    JSStrictPropertyOpWrapper   setter;
 };
 
 struct JSFunctionSpec {
     const char      *name;
-    JSNative        call;
+    JSNativeWrapper call;
     uint16_t        nargs;
     uint16_t        flags;
 };
 
 /*
  * Terminating sentinel initializer to put at the end of a JSFunctionSpec array
  * that's passed to JS_DefineFunctions or JS_InitClass.
  */
 #define JS_FS_END JS_FS(NULL,NULL,0,0)
 
 /*
  * Initializer macros for a JSFunctionSpec array element. JS_FN (whose name
  * pays homage to the old JSNative/JSFastNative split) simply adds the flag
- * JSFUN_STUB_GSOPS.
+ * JSFUN_STUB_GSOPS. JS_FNINFO allows the simple adding of JSJitInfos.
  */
 #define JS_FS(name,call,nargs,flags)                                          \
-    {name, call, nargs, flags}
+    {name, JSOP_WRAPPER(call), nargs, flags}
 #define JS_FN(name,call,nargs,flags)                                          \
-    {name, call, nargs, (flags) | JSFUN_STUB_GSOPS}
+    {name, JSOP_WRAPPER(call), nargs, (flags) | JSFUN_STUB_GSOPS}
+#define JS_FNINFO(name,call,info,nargs,flags)                                 \
+    {name,{call,info},nargs,flags}
 
 extern JS_PUBLIC_API(JSObject *)
 JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
              JSClass *clasp, JSNative constructor, unsigned nargs,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
 
 /*
@@ -5079,28 +5112,34 @@ struct JS_PUBLIC_API(CompileOptions) {
     JSVersion version;
     bool versionSet;
     bool utf8;
     const char *filename;
     unsigned lineno;
     bool compileAndGo;
     bool noScriptRval;
     bool allowIntrinsicsCalls;
+    enum SourcePolicy {
+        NO_SOURCE,
+        LAZY_SOURCE,
+        SAVE_SOURCE
+    } sourcePolicy;
 
     CompileOptions(JSContext *cx);
     CompileOptions &setPrincipals(JSPrincipals *p) { principals = p; return *this; }
     CompileOptions &setOriginPrincipals(JSPrincipals *p) { originPrincipals = p; return *this; }
     CompileOptions &setVersion(JSVersion v) { version = v; versionSet = true; return *this; }
     CompileOptions &setUTF8(bool u) { utf8 = u; return *this; }
     CompileOptions &setFileAndLine(const char *f, unsigned l) {
         filename = f; lineno = l; return *this;
     }
     CompileOptions &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; }
     CompileOptions &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
     CompileOptions &setAllowIntrinsicsCalls(bool aic) { allowIntrinsicsCalls = aic; return *this; }
+    CompileOptions &setSourcePolicy(SourcePolicy sp) { sourcePolicy = sp; return *this; }
 };
 
 extern JS_PUBLIC_API(JSScript *)
 Compile(JSContext *cx, JSHandleObject obj, CompileOptions options,
         const char *bytes, size_t length);
 
 extern JS_PUBLIC_API(JSScript *)
 Compile(JSContext *cx, JSHandleObject obj, CompileOptions options,
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -790,16 +790,17 @@ struct JSRuntime : js::RuntimeFriendFiel
   public:
     js::FreeOp *defaultFreeOp() {
         return &defaultFreeOp_;
     }
 
     uint32_t            debuggerMutations;
 
     const JSSecurityCallbacks *securityCallbacks;
+    const js::DOMCallbacks *DOMcallbacks;
     JSDestroyPrincipalsOp destroyPrincipals;
 
     /* Structured data callbacks are runtime-wide. */
     const JSStructuredCloneCallbacks *structuredCloneCallbacks;
 
     /* Call this to accumulate telemetry data. */
     JSAccumulateTelemetryDataCallback telemetryCallback;
 
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -917,16 +917,28 @@ SetRuntimeProfilingStack(JSRuntime *rt, 
 }
 
 JS_FRIEND_API(void)
 EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled)
 {
     rt->spsProfiler.enable(enabled);
 }
 
+JS_FRIEND_API(void)
+SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks)
+{
+    rt->DOMcallbacks = callbacks;
+}
+
+JS_FRIEND_API(const DOMCallbacks *)
+GetDOMCallbacks(JSRuntime *rt)
+{
+    return rt->DOMcallbacks;
+}
+
 static void *gListBaseHandlerFamily = NULL;
 static uint32_t gListBaseExpandoSlot = 0;
 
 JS_FRIEND_API(void)
 SetListBaseInformation(void *listBaseHandlerFamily, uint32_t listBaseExpandoSlot)
 {
     gListBaseHandlerFamily = listBaseHandlerFamily;
     gListBaseExpandoSlot = listBaseExpandoSlot;
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -10,22 +10,16 @@
 #include "jsclass.h"
 #include "jspubtd.h"
 #include "jsprvtd.h"
 
 #include "mozilla/GuardObjects.h"
 
 JS_BEGIN_EXTERN_C
 
-/*
- * Only save the source of scripts that are compileAndGo or are created with
- * JS_CompileFunction*.
- */
-#define JSOPTION_ONLY_CNG_SOURCE JS_BIT(20)
-
 extern JS_FRIEND_API(void)
 JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
 
 extern JS_FRIEND_API(JSString *)
 JS_GetAnonymousString(JSRuntime *rt);
 
 extern JS_FRIEND_API(JSObject *)
 JS_FindCompilationScope(JSContext *cx, JSRawObject obj);
@@ -160,16 +154,18 @@ struct JSFunctionSpecWithHelp {
     uint16_t        nargs;
     uint16_t        flags;
     const char      *usage;
     const char      *help;
 };
 
 #define JS_FN_HELP(name,call,nargs,flags,usage,help)                          \
     {name, call, nargs, (flags) | JSPROP_ENUMERATE | JSFUN_STUB_GSOPS, usage, help}
+#define JS_FS_HELP_END                                                        \
+    {NULL, NULL, 0, 0, NULL, NULL}
 
 extern JS_FRIEND_API(bool)
 JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs);
 
 #endif
 
 JS_END_EXTERN_C
 
@@ -324,16 +320,26 @@ struct Object {
     js::Value &slotRef(size_t slot) const {
         size_t nfixed = numFixedSlots();
         if (slot < nfixed)
             return fixedSlots()[slot];
         return slots[slot - nfixed];
     }
 };
 
+struct Function {
+    Object base;
+    uint16_t nargs;
+    uint16_t flags;
+    /* Used only for natives */
+    Native native;
+    const JSJitInfo *jitinfo;
+    void *_1;
+};
+
 struct Atom {
     size_t _;
     const jschar *chars;
 };
 
 } /* namespace shadow */
 
 extern JS_FRIEND_DATA(js::Class) AnyNameClass;
@@ -737,16 +743,31 @@ typedef void
 
 extern JS_FRIEND_API(GCSliceCallback)
 SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback);
 
 /* Was the most recent GC run incrementally? */
 extern JS_FRIEND_API(bool)
 WasIncrementalGC(JSRuntime *rt);
 
+typedef JSBool
+(* DOMInstanceClassMatchesProto)(JSHandleObject protoObject, uint32_t protoID,
+                                 uint32_t depth);
+
+struct JSDOMCallbacks {
+    DOMInstanceClassMatchesProto instanceClassMatchesProto;
+};
+typedef struct JSDOMCallbacks DOMCallbacks;
+
+extern JS_FRIEND_API(void)
+SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks);
+
+extern JS_FRIEND_API(const DOMCallbacks *)
+GetDOMCallbacks(JSRuntime *rt);
+
 /*
  * Signals a good place to do an incremental slice, because the browser is
  * drawing a frame.
  */
 extern JS_FRIEND_API(void)
 NotifyDidPaint(JSRuntime *rt);
 
 extern JS_FRIEND_API(bool)
@@ -1293,9 +1314,47 @@ JS_GetDataViewByteLength(JSObject *obj, 
  * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
  * it would pass such a test: it is a data view or a wrapper of a data view,
  * and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
  * unable to assert when unwrapping should be disallowed.
  */
 JS_FRIEND_API(void *)
 JS_GetDataViewData(JSObject *obj, JSContext *cx);
 
+#ifdef __cplusplus
+/*
+ * This struct contains metadata passed from the DOM to the JS Engine for JIT
+ * optimizations on DOM property accessors. Eventually, this should be made
+ * available to general JSAPI users, but we are not currently ready to do so.
+ */
+typedef bool
+(* JSJitPropertyOp)(JSContext *cx, JSHandleObject thisObj,
+                    void *specializedThis, JS::Value *vp);
+typedef bool
+(* JSJitMethodOp)(JSContext *cx, JSHandleObject thisObj,
+                  void *specializedThis, unsigned argc, JS::Value *vp);
+
+struct JSJitInfo {
+    JSJitPropertyOp op;
+    uint32_t protoID;
+    uint32_t depth;
+    bool isInfallible;    /* Is op fallible? Getters only */
+    bool isConstant;      /* Getting a construction-time constant? */
+};
+
+static JS_ALWAYS_INLINE const JSJitInfo *
+FUNCTION_VALUE_TO_JITINFO(const JS::Value& v)
+{
+    JS_ASSERT(js::GetObjectClass(&v.toObject()) == &js::FunctionClass);
+    return reinterpret_cast<js::shadow::Function *>(&v.toObject())->jitinfo;
+}
+
+static JS_ALWAYS_INLINE void
+SET_JITINFO(JSFunction * func, const JSJitInfo *info)
+{
+    js::shadow::Function *fun = reinterpret_cast<js::shadow::Function *>(func);
+    /* JS_ASSERT(func->isNative()). 0x4000 is JSFUN_INTERPRETED */
+    JS_ASSERT(!(fun->flags & 0x4000));
+    fun->jitinfo = info;
+}
+#endif /* __cplusplus */
+
 #endif /* jsfriendapi_h___ */
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1429,18 +1429,18 @@ js_NewFunction(JSContext *cx, JSObject *
     /* Initialize all function members. */
     fun->nargs = uint16_t(nargs);
     fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED);
     if (flags & JSFUN_INTERPRETED) {
         JS_ASSERT(!native);
         fun->mutableScript().init(NULL);
         fun->initEnvironment(parent);
     } else {
-        fun->u.native = native;
-        JS_ASSERT(fun->u.native);
+        JS_ASSERT(native);
+        fun->initNative(native, NULL);
     }
     if (kind == JSFunction::ExtendedFinalizeKind) {
         fun->flags |= JSFUN_EXTENDED;
         fun->initializeExtended();
     }
     fun->atom.init(atom);
 
     if (native && !fun->setSingletonType(cx))
@@ -1463,17 +1463,17 @@ js_CloneFunctionObject(JSContext *cx, Ha
     RootedFunction clone(cx, static_cast<JSFunction *>(cloneobj));
 
     clone->nargs = fun->nargs;
     clone->flags = fun->flags & ~JSFUN_EXTENDED;
     if (fun->isInterpreted()) {
         clone->initScript(fun->script());
         clone->initEnvironment(parent);
     } else {
-        clone->u.native = fun->native();
+        clone->initNative(fun->native(), fun->jitInfo());
     }
     clone->atom.init(fun->atom);
 
     if (kind == JSFunction::ExtendedFinalizeKind) {
         clone->flags |= JSFUN_EXTENDED;
         clone->initializeExtended();
     }
 
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -34,27 +34,37 @@
  * move to u.i.script->flags. For now we use function flag bits to minimize
  * pointer-chasing.
  */
 #define JSFUN_PROTOTYPE     0x0800  /* function is Function.prototype for some
                                        global object */
 
 #define JSFUN_EXPR_CLOSURE  0x1000  /* expression closure: function(x) x*x */
 #define JSFUN_EXTENDED      0x2000  /* structure is FunctionExtended */
+/*
+ * NB: JSFUN_INTERPRETED is hardcode duplicated in SET_JITINFO() in
+ * jsfriendapi.h. If it changes, it must also be updated there.
+ */
 #define JSFUN_INTERPRETED   0x4000  /* use u.i if kind >= this value else u.native */
 
 namespace js { class FunctionExtended; }
 
 struct JSFunction : public JSObject
 {
     uint16_t        nargs;        /* maximum number of specified arguments,
                                      reflected as f.length/f.arity */
     uint16_t        flags;        /* flags, see JSFUN_* below and in jsapi.h */
     union U {
-        js::Native  native;       /* native method pointer or null */