Merge last PGO-green changeset of mozilla-inbound to mozilla-central
authorEd Morley <emorley@mozilla.com>
Thu, 18 Oct 2012 18:12:33 +0100
changeset 110790 3779eb3f036fd4d1e5b7d56d4bc430cb209b6fd7
parent 110742 28d5bb4008ec7d9c007ed4e8315fcc9758e2b0b9 (current diff)
parent 110789 d243048bc966c3657962ba32c93db77089667abc (diff)
child 110791 cf1bbed46731a5e9992805b931772be3ef3e31d6
child 110813 32ef5e90397832d437d448288eb91e30a68fd1ca
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone19.0a1
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
configure.in
dom/bindings/BindingGen.py
--- a/b2g/chrome/content/runapp.js
+++ b/b2g/chrome/content/runapp.js
@@ -1,44 +1,72 @@
+"use strict";
+
 // runapp.js:
 // Provide a --runapp APPNAME command-line option.
 
+let runAppObj;
 window.addEventListener('load', function() {
   // Get the command line arguments that were passed to the b2g client
   let args = window.arguments[0].QueryInterface(Ci.nsICommandLine);
   let appname;
 
   // - Check if the argument is present before doing any work.
   try {
     // Returns null if the argument was not specified.  Throws
     // NS_ERROR_INVALID_ARG if there is no parameter specified (because
     // it was the last argument or the next argument starts with '-').
     // However, someone could still explicitly pass an empty argument!
     appname = args.handleFlagWithParam('runapp', false);
-  }
-  catch(e) {
+  } catch(e) {
     // treat a missing parameter like an empty parameter (=> show usage)
     appname = '';
   }
 
   // not specified, bail.
-  if (appname === null)
+  if (appname === null) {
     return;
+  }
+
+  runAppObj = new AppRunner(appname);
+  Services.obs.addObserver(runAppObj, 'webapps-registry-ready', false);
+});
+
+window.addEventListener('unload', function() {
+  Services.obs.removeObserver(runAppObj, 'webapps-registry-ready');
+});
 
-  // - Get the list of apps since the parameter was specified
-  let appsReq = navigator.mozApps.mgmt.getAll();
-  appsReq.onsuccess = function() {
-    let apps = appsReq.result;
+function AppRunner(aName) {
+  this._req = null;
+  this._appName = aName;
+}
+AppRunner.prototype = {
+  observe: function(aSubject, aTopic, aData) {
+    if (aTopic == 'webapps-registry-ready') {
+      this.doRunApp();
+    }
+  },
+
+  doRunApp: function() {
+    // - Get the list of apps since the parameter was specified
+    this._req = navigator.mozApps.mgmt.getAll();
+    this._req.onsuccess = this.getAllSuccess.bind(this);
+    this._req.onerror = this.getAllError.bind(this);
+  },
+
+  getAllSuccess: function() {
+    let apps = this._req.result;
+
     function findAppWithName(name) {
       let normalizedSearchName = name.replace(/[- ]+/g, '').toLowerCase();
 
       for (let i = 0; i < apps.length; i++) {
         let app = apps[i];
         let normalizedAppName =
-              app.manifest.name.replace(/[- ]+/g, '').toLowerCase();
+          app.manifest.name.replace(/[- ]+/g, '').toLowerCase();
         if (normalizedSearchName === normalizedAppName) {
           return app;
         }
       }
       return null;
     }
 
     function usageAndDie(justApps) {
@@ -54,40 +82,41 @@ window.addEventListener('load', function
       for (let i = 0; i < apps.length; i++) {
         dump('  ' + apps[i].manifest.name + '\n');
       }
 
       // Exit the b2g client
       Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
     }
 
-    if (appname === '') {
+    if (this._appName === '') {
       usageAndDie();
       return;
     }
 
-    let app = findAppWithName(appname);
+    let app = findAppWithName(this._appName);
     if (!app) {
-      dump('Could not find app: "' + appname + '". Maybe you meant one of:\n');
+      dump('Could not find app: "' + this._appName + '". Maybe you meant one of:\n');
       usageAndDie(true);
       return;
     }
 
     let setReq =
       navigator.mozSettings.createLock().set({'lockscreen.enabled': false});
     setReq.onsuccess = function() {
-      // give the event loop another turn to disable the lock screen
+      // give the event loop 100ms to disable the lock screen
       window.setTimeout(function() {
         dump('--runapp launching app: ' + app.manifest.name + '\n');
         app.launch();
-      }, 0);
+      }, 100);
     };
     setReq.onerror = function() {
       dump('--runapp failed to disable lock-screen.  Giving up.\n');
     };
 
     dump('--runapp found app: ' + app.manifest.name +
          ', disabling lock screen...\n');
- };
- appsReq.onerror = function() {
-   dump('Problem getting the list of all apps!');
- };
-});
+  },
+
+  getAllError: function() {
+    dump('Problem getting the list of all apps!');
+  }
+};
\ No newline at end of file
--- a/b2g/chrome/content/shell.xul
+++ b/b2g/chrome/content/shell.xul
@@ -12,16 +12,16 @@
 #endif
         style="background: black; overflow: hidden; width:320px; height:480px"
         onload="shell.start();"
         onunload="shell.stop();">
 
   <script type="application/javascript" src="chrome://browser/content/settings.js"/>
   <script type="application/javascript" src="chrome://browser/content/shell.js"/>
 
-#ifndef ANDROID
+#ifndef MOZ_WIDGET_GONK
   <!-- this script handles the screen argument for desktop builds -->
   <script type="application/javascript" src="chrome://browser/content/screen.js"/>
   <!-- this script handles the "runapp" argument for desktop builds -->
   <script type="application/javascript" src="chrome://browser/content/runapp.js"/>
 #endif
   <!-- The html:iframe containing the UI is created here. -->
 </window>
--- a/browser/base/content/test/browser_minimize.js
+++ b/browser/base/content/test/browser_minimize.js
@@ -15,16 +15,20 @@ function waitForInactive() {
         return;
     }
     is(gBrowser.docShell.isActive, false, "Docshell should be inactive");
     window.restore();
     waitForActive();
 }
 
 function test() {
+    registerCleanupFunction(function() {
+      window.restore();
+    });
+
     waitForExplicitFinish();
     is(gBrowser.docShell.isActive, true, "Docshell should be active");
     window.minimize();
     // XXX On Linux minimize/restore seem to be very very async, but
     // our window.windowState changes sync.... so we can't rely on the
     // latter correctly reflecting the state of the former.  In
     // particular, a restore() call before minimizing is done will not
     // actually restore the window, but change the window state.  As a
--- a/build/autoconf/arch.m4
+++ b/build/autoconf/arch.m4
@@ -45,16 +45,20 @@ if test -z "$MOZ_ARCH"; then
         fi
         if test "$MOZ_PLATFORM_MAEMO" = 6; then
             MOZ_THUMB=yes
         fi
         ;;
     esac
 fi
 
+if test "$MOZ_ARCH" = "armv6" -a "$OS_TARGET" = "Android"; then
+   MOZ_FPU=vfp
+fi
+
 MOZ_ARG_WITH_STRING(thumb,
 [  --with-thumb[[=yes|no|toolchain-default]]]
 [                          Use Thumb instruction set (-mthumb)],
     if test -z "$GNU_CC"; then
         AC_MSG_ERROR([--with-thumb is not supported on non-GNU toolchains])
     fi
     MOZ_THUMB=$withval)
 
--- a/build/pymake/pymake/data.py
+++ b/build/pymake/pymake/data.py
@@ -1399,34 +1399,34 @@ class _CommandWrapper(object):
         self.usercb = cb
         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, 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:
             self.pycommandpath = None
-        self.module = parts[0]
-        self.method = parts[1]
-        self.cline_list = parts[2:]
 
     def __call__(self, cb):
+        # get the module and method to call
+        parts, badchar = process.clinetoargv(self.cline, self.kwargs['cwd'])
+        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)
+        module = parts[0]
+        method = parts[1]
+        cline_list = parts[2:]
         self.usercb = cb
-        process.call_native(self.module, self.method, self.cline_list,
+        process.call_native(module, method, cline_list,
                             loc=self.loc, cb=self._cb, context=self.context,
                             pycommandpath=self.pycommandpath, **self.kwargs)
 
 def getcommandsforrule(rule, target, makefile, prerequisites, stem):
     v = Variables(parent=target.variables)
     setautomaticvariables(v, makefile, target, prerequisites)
     if stem is not None:
         setautomatic(v, '*', [stem])
--- a/build/pymake/pymake/functions.py
+++ b/build/pymake/pymake/functions.py
@@ -1,14 +1,14 @@
 """
 Makefile functions.
 """
 
 import parser, util
-import subprocess, os, logging
+import subprocess, os, logging, sys
 from globrelative import glob
 from cStringIO import StringIO
 
 log = logging.getLogger('pymake.data')
 
 def emit_expansions(descend, *expansions):
     """Helper function to emit all expansions within an input set."""
     for expansion in expansions:
@@ -761,26 +761,38 @@ class FlavorFunction(Function):
 class ShellFunction(Function):
     name = 'shell'
     minargs = 1
     maxargs = 1
 
     __slots__ = Function.__slots__
 
     def resolve(self, makefile, variables, fd, setting):
-        #TODO: call this once up-front somewhere and save the result?
-        shell, msys = util.checkmsyscompat()
+        from process import prepare_command
         cline = self._arguments[0].resolvestr(makefile, variables, setting)
+        executable, cline = prepare_command(cline, makefile.workdir, self.loc)
+
+        # subprocess.Popen doesn't use the PATH set in the env argument for
+        # finding the executable on some platforms (but strangely it does on
+        # others!), so set os.environ['PATH'] explicitly.
+        oldpath = os.environ['PATH']
+        if makefile.env is not None and 'PATH' in makefile.env:
+            os.environ['PATH'] = makefile.env['PATH']
 
-        log.debug("%s: running shell command '%s'" % (self.loc, cline))
-        cline = [shell, "-c", cline]
-        p = subprocess.Popen(cline, env=makefile.env, shell=False,
-                             stdout=subprocess.PIPE, cwd=makefile.workdir)
+        log.debug("%s: running command '%s'" % (self.loc, ' '.join(cline)))
+        try:
+            p = subprocess.Popen(cline, executable=executable, env=makefile.env, shell=False,
+                                 stdout=subprocess.PIPE, cwd=makefile.workdir)
+        except OSError, e:
+            print >>sys.stderr, "Error executing command %s" % cline[0], e
+            return
+        finally:
+            os.environ['PATH'] = oldpath
+
         stdout, stderr = p.communicate()
-
         stdout = stdout.replace('\r\n', '\n')
         if stdout.endswith('\n'):
             stdout = stdout[:-1]
         stdout = stdout.replace('\n', ' ')
 
         fd.write(stdout)
 
 class ErrorFunction(Function):
--- a/build/pymake/pymake/process.py
+++ b/build/pymake/pymake/process.py
@@ -10,118 +10,267 @@ 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')
-# 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 tokens2re(tokens):
+    # Create a pattern for non-escaped tokens, in the form:
+    #   (?<!\\)(?:a|b|c...)
+    # This is meant to match patterns a, b, or c, or ... if they are not
+    # preceded by a backslash.
+    # where a, b, c... are in the form
+    #   (?P<name>pattern)
+    # which matches the pattern and captures it in a named match group.
+    # The group names and patterns come are given as a dict in the function
+    # argument.
+    nonescaped = r'(?<!\\)(?:%s)' % '|'.join('(?P<%s>%s)' % (name, value) for name, value in tokens.iteritems())
+    # The final pattern matches either the above pattern, or an escaped
+    # backslash, captured in the "escape" match group.
+    return re.compile('(?:%s|%s)' % (nonescaped, r'(?P<escape>\\\\)'))
+
+_unquoted_tokens = tokens2re({
+  'whitespace': r'[\t\r\n ]',
+  'quote': r'[\'"]',
+  'comment': '#',
+  'special': r'[<>&|`~(){}$;]',
+  'backslashed': r'\\[^\\]',
+  'glob': r'[\*\?]',
+})
+
+_doubly_quoted_tokens = tokens2re({
+  'quote': '"',
+  'backslashedquote': r'\\"',
+  'special': '\$',
+  'backslashed': r'\\[^\\"]',
+})
+
+class MetaCharacterException(Exception):
+    def __init__(self, char):
+        self.char = char
+
+class ClineSplitter(list):
+    """
+    Parses a given command line string and creates a list of command
+    and arguments, with wildcard expansion.
+    """
+    def __init__(self, cline, cwd):
+        self.cwd = cwd
+        self.arg = ''
+        self.cline = cline
+        self.glob = False
+        self._parse_unquoted()
+
+    def _push(self, str):
+        """
+        Push the given string as part of the current argument
+        """
+        self.arg += str
+
+    def _next(self):
+        """
+        Finalize current argument, effectively adding it to the list.
+        Perform globbing if needed.
+        """
+        if not self.arg:
+            return
+        if self.glob:
+            if os.path.isabs(self.arg):
+                path = self.arg
+            else:
+                path = os.path.join(self.cwd, self.arg)
+            globbed = glob.glob(path)
+            if not globbed:
+                # If globbing doesn't find anything, the literal string is
+                # used.
+                self.append(self.arg)
+            else:
+                self.extend(f[len(path)-len(self.arg):] for f in globbed)
+            self.glob = False
+        else:
+            self.append(self.arg)
+        self.arg = ''
 
-def clinetoargv(cline, blacklist_gray):
+    def _parse_unquoted(self):
+        """
+        Parse command line remainder in the context of an unquoted string.
+        """
+        while self.cline:
+            # Find the next token
+            m = _unquoted_tokens.search(self.cline)
+            # If we find none, the remainder of the string can be pushed to
+            # the current argument and the argument finalized
+            if not m:
+                self._push(self.cline)
+                break
+            # The beginning of the string, up to the found token, is part of
+            # the current argument
+            self._push(self.cline[:m.start()])
+            self.cline = self.cline[m.end():]
+
+            match = dict([(name, value) for name, value in m.groupdict().items() if value])
+            if 'quote' in match:
+                # " or ' start a quoted string
+                if match['quote'] == '"':
+                    self._parse_doubly_quoted()
+                else:
+                    self._parse_quoted()
+            elif 'comment' in match:
+                # Comments are ignored. The current argument can be finalized,
+                # and parsing stopped.
+                break
+            elif 'special' in match:
+                # Unquoted, non-escaped special characters need to be sent to a
+                # shell.
+                raise MetaCharacterException, match['special']
+            elif 'whitespace' in match:
+                # Whitespaces terminate current argument.
+                self._next()
+            elif 'escape' in match:
+                # Escaped backslashes turn into a single backslash
+                self._push('\\')
+            elif 'backslashed' in match:
+                # Backslashed characters are unbackslashed
+                # e.g. echo \a -> a
+                self._push(match['backslashed'][1])
+            elif 'glob' in match:
+                # ? or * will need globbing
+                self.glob = True
+                self._push(m.group(0))
+            else:
+                raise Exception, "Shouldn't reach here"
+        self._next()
+
+    def _parse_quoted(self):
+        # Single quoted strings are preserved, except for the final quote
+        index = self.cline.find("'")
+        if index == -1:
+            raise Exception, 'Unterminated quoted string in command'
+        self._push(self.cline[:index])
+        self.cline = self.cline[index+1:]
+
+    def _parse_doubly_quoted(self):
+        if not self.cline:
+            raise Exception, 'Unterminated quoted string in command'
+        while self.cline:
+            m = _doubly_quoted_tokens.search(self.cline)
+            if not m:
+                raise Exception, 'Unterminated quoted string in command'
+            self._push(self.cline[:m.start()])
+            self.cline = self.cline[m.end():]
+            match = dict([(name, value) for name, value in m.groupdict().items() if value])
+            if 'quote' in match:
+                # a double quote ends the quoted string, so go back to
+                # unquoted parsing
+                return
+            elif 'special' in match:
+                # Unquoted, non-escaped special characters in a doubly quoted
+                # string still have a special meaning and need to be sent to a
+                # shell.
+                raise MetaCharacterException, match['special']
+            elif 'escape' in match:
+                # Escaped backslashes turn into a single backslash
+                self._push('\\')
+            elif 'backslashedquote' in match:
+                # Backslashed double quotes are un-backslashed
+                self._push('"')
+            elif 'backslashed' in match:
+                # Backslashed characters are kept backslashed
+                self._push(match['backslashed'])
+
+def clinetoargv(cline, cwd):
     """
     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)
+    try:
+        args = ClineSplitter(str, cwd)
+    except MetaCharacterException, e:
+        return None, e.char
 
     if len(args) and args[0].find('=') != -1:
         return None, '='
 
     return args, None
 
-def doglobbing(args, cwd):
-    """
-    Perform any needed globbing on the argument list passed in
-    """
-    globbedargs = []
-    for arg in args:
-        if _needsglob.search(arg):
-            globbedargs.extend(glob.glob(os.path.join(cwd, arg)))
-        else:
-            globbedargs.append(arg)
-
-    return globbedargs
-
+# shellwords contains a set of shell builtin commands that need to be
+# executed within a shell. It also contains a set of commands that are known
+# to be giving problems when run directly instead of through the msys shell.
 shellwords = (':', '.', 'break', 'cd', 'continue', 'exec', 'exit', 'export',
               'getopts', 'hash', 'pwd', 'readonly', 'return', 'shift', 
               'test', 'times', 'trap', 'umask', 'unset', 'alias',
               'set', 'bind', 'builtin', 'caller', 'command', 'declare',
               'echo', 'enable', 'help', 'let', 'local', 'logout', 
               'printf', 'read', 'shopt', 'source', 'type', 'typeset',
-              'ulimit', 'unalias', 'set')
+              'ulimit', 'unalias', 'set', 'find')
 
-def call(cline, env, cwd, loc, cb, context, echo, justprint=False):
+def prepare_command(cline, cwd, loc):
+    """
+    Returns a list of command and arguments for the given command line string.
+    If the command needs to be run through a shell for some reason, the
+    returned list contains the shell invocation.
+    """
+
     #TODO: call this once up-front somewhere and save the result?
     shell, msys = util.checkmsyscompat()
 
     shellreason = None
+    executable = None
     if msys and cline.startswith('/'):
         shellreason = "command starts with /"
     else:
-        argv, badchar = clinetoargv(cline, blacklist_gray=True)
+        argv, badchar = clinetoargv(cline, cwd)
         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)
+        elif argv and (os.sep in argv[0] or os.altsep and os.altsep in argv[0]):
+            executable = util.normaljoin(cwd, argv[0])
+            # Avoid "%1 is not a valid Win32 application" errors, assuming
+            # that if the executable path is to be resolved with PATH, it will
+            # be a Win32 executable.
+            if sys.platform == 'win32' and os.path.isfile(executable) and open(executable, 'rb').read(2) == "#!":
+                shellreason = "command executable starts with a hashbang"
 
     if shellreason is not None:
         _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline)
         if msys:
             if len(cline) > 3 and cline[1] == ':' and cline[2] == '/':
                 cline = '/' + cline[0] + cline[2:]
-        cline = [shell, "-c", cline]
-        context.call(cline, shell=False, env=env, cwd=cwd, cb=cb, echo=echo,
-                     justprint=justprint)
-        return
+        argv = [shell, "-c", cline]
+        executable = None
+
+    return executable, argv
+
+def call(cline, env, cwd, loc, cb, context, echo, justprint=False):
+    executable, argv = prepare_command(cline, cwd, loc)
 
     if not len(argv):
         cb(res=0)
         return
 
     if argv[0] == command.makepypath:
         command.main(argv[1:], env, cwd, cb)
         return
 
     if argv[0:2] == [sys.executable.replace('\\', '/'),
                      command.makepypath.replace('\\', '/')]:
         command.main(argv[2:], env, cwd, cb)
         return
 
-    if argv[0].find('/') != -1:
-        executable = util.normaljoin(cwd, argv[0])
-    else:
-        executable = None
-
     context.call(argv, executable=executable, shell=False, env=env, cwd=cwd, cb=cb,
                  echo=echo, justprint=justprint)
 
 def call_native(module, method, argv, env, cwd, loc, cb, context, echo, justprint=False,
                 pycommandpath=None):
-    argv = doglobbing(argv, cwd)
     context.call_native(module, method, argv, env=env, cwd=cwd, cb=cb,
                         echo=echo, justprint=justprint, pycommandpath=pycommandpath)
 
 def statustoresult(status):
     """
     Convert the status returned from waitpid into a prettier numeric result.
     """
     sig = status & 0xFF
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1111,18 +1111,18 @@ Makefile: Makefile.in
 	@$(PYTHON) $(DEPTH)/config.status -n --file=Makefile
 	@$(TOUCH) $@
 endif
 
 ifndef NO_SUBMAKEFILES_RULE
 ifdef SUBMAKEFILES
 # VPATH does not work on some machines in this case, so add $(srcdir)
 $(SUBMAKEFILES): % : $(srcdir)/%.in
-	$(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file=$@
-	@$(TOUCH) $@
+	$(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file="$@"
+	@$(TOUCH) "$@"
 endif
 endif
 
 ifdef AUTOUPDATE_CONFIGURE
 $(topsrcdir)/configure: $(topsrcdir)/configure.in
 	(cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck
 endif
 
--- a/configure.in
+++ b/configure.in
@@ -5840,17 +5840,17 @@ if test -n "$MOZ_ANGLE_RENDERER" -a -z "
   if test -z "$MOZ_DIRECTX_SDK_REG_KEY" ; then
     # Otherwise just take whatever comes first
     MOZ_DIRECTX_SDK_REG_KEY=`reg query 'HKLM\Software\Microsoft\DirectX' //s | grep 'Microsoft DirectX SDK' | head -n 1`
   fi
 
   if test -n "`echo $MOZ_DIRECTX_SDK_REG_KEY | grep 'February 2010'`" ; then
     AC_MSG_ERROR([Found the February 2010 DirectX SDK. Need the June 2010 DirectX SDK, or newer.  Upgrade your SDK or reconfigure with --disable-webgl.])
   else
-    MOZ_DIRECTX_SDK_PATH=`reg query "$MOZ_DIRECTX_SDK_REG_KEY" //v InstallPath | grep REG_SZ | sed 's/.*\([[a-zA-Z]]\)\\:\\\\/\\1\\:\\\\/'`
+    MOZ_DIRECTX_SDK_PATH=`reg query "$MOZ_DIRECTX_SDK_REG_KEY" //v InstallPath | grep REG_SZ | sed 's/.*\([[a-zA-Z]]\)\\:\\\\/\\1\\:\\\\/' | sed 's,\\\\,/,g'`
   fi
 
   if test -n "$MOZ_DIRECTX_SDK_PATH" &&
      test -f "$MOZ_DIRECTX_SDK_PATH"/include/d3dx9.h &&
 	 test -f "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_DIRECTX_SDK_CPU_SUFFIX/dxguid.lib ; then
     AC_MSG_RESULT([Found DirectX SDK via registry, using $MOZ_DIRECTX_SDK_PATH])
   else
     AC_MSG_ERROR([Couldn't find the DirectX SDK, needed for WebGL. Either install it (June 2010 version or newer), or reconfigure with --disable-webgl.])
@@ -6082,16 +6082,22 @@ if test -z "$MOZ_ENABLE_GIO" -a `echo "$
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
 fi
 
 dnl Do not build gio with libxul based apps
 if test -n "$LIBXUL_SDK_DIR" -a `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
 fi
 
+if test `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
+    MOZ_GIO_COMPONENT=1
+    MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
+fi
+AC_SUBST(MOZ_GIO_COMPONENT)
+
 if test -z "$MOZ_JSDEBUGGER" -a `echo "$MOZ_EXTENSIONS" | grep -c venkman` -ne 0; then
     AC_MSG_WARN([Cannot build venkman without JavaScript debug library. Removing venkman from MOZ_EXTENSIONS.])
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|venkman||'`
 fi
 
 dnl xforms requires xtf
 if test -z "$MOZ_XTF" -a `echo "$MOZ_EXTENSIONS" | grep -c xforms` -ne 0; then
     AC_MSG_WARN([Cannot build XForms without XTF support.  Removing XForms from MOZ_EXTENSIONS.])
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6353,17 +6353,17 @@ public:
                                     nsCycleCollectionParticipant* helper)
   {
   }
 
   NS_IMETHOD_(void) NoteNextEdgeName(const char* name)
   {
   }
 
-  NS_IMETHOD_(void) NoteWeakMapping(void* map, void* key, void* val)
+  NS_IMETHOD_(void) NoteWeakMapping(void* map, void* key, void* kdelegate, void* val)
   {
   }
 
   bool mFound;
 
 private:
   void* mWrapper;
 };
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -308,45 +308,41 @@ nsHTMLDocument::CreateShell(nsPresContex
                             nsIViewManager* aViewManager,
                             nsStyleSet* aStyleSet,
                             nsIPresShell** aInstancePtrResult)
 {
   return doCreateShell(aContext, aViewManager, aStyleSet, mCompatMode,
                        aInstancePtrResult);
 }
 
-// The following Try*Charset will return false only if the charset source
-// should be considered (ie. aCharsetSource < thisCharsetSource) but we failed
-// to get the charset from this source.
-
-bool
+void
 nsHTMLDocument::TryHintCharset(nsIMarkupDocumentViewer* aMarkupDV,
                                int32_t& aCharsetSource, nsACString& aCharset)
 {
   if (aMarkupDV) {
     int32_t requestCharsetSource;
     nsresult rv = aMarkupDV->GetHintCharacterSetSource(&requestCharsetSource);
 
     if(NS_SUCCEEDED(rv) && kCharsetUninitialized != requestCharsetSource) {
       nsAutoCString requestCharset;
       rv = aMarkupDV->GetHintCharacterSet(requestCharset);
       aMarkupDV->SetHintCharacterSetSource((int32_t)(kCharsetUninitialized));
 
       if(requestCharsetSource <= aCharsetSource)
-        return true;
-
-      if(NS_SUCCEEDED(rv)) {
+        return;
+
+      if(NS_SUCCEEDED(rv) && IsAsciiCompatible(requestCharset)) {
         aCharsetSource = requestCharsetSource;
         aCharset = requestCharset;
 
-        return true;
+        return;
       }
     }
   }
-  return false;
+  return;
 }
 
 
 bool
 nsHTMLDocument::TryUserForcedCharset(nsIMarkupDocumentViewer* aMarkupDV,
                                      nsIDocShell*  aDocShell,
                                      int32_t& aCharsetSource,
                                      nsACString& aCharset)
@@ -356,16 +352,18 @@ nsHTMLDocument::TryUserForcedCharset(nsI
   if(kCharsetFromUserForced <= aCharsetSource)
     return true;
 
   nsAutoCString forceCharsetFromDocShell;
   if (aMarkupDV) {
     rv = aMarkupDV->GetForceCharacterSet(forceCharsetFromDocShell);
   }
 
+  // Not making the IsAsciiCompatible() check here to allow the user to
+  // force UTF-16 from the menu.
   if(NS_SUCCEEDED(rv) && !forceCharsetFromDocShell.IsEmpty()) {
     aCharset = forceCharsetFromDocShell;
     //TODO: we should define appropriate constant for force charset
     aCharsetSource = kCharsetFromUserForced;
   } else if (aDocShell) {
     nsCOMPtr<nsIAtom> csAtom;
     aDocShell->GetForcedCharset(getter_AddRefs(csAtom));
     if (csAtom) {
@@ -387,17 +385,22 @@ nsHTMLDocument::TryCacheCharset(nsICachi
   nsresult rv;
 
   if (kCharsetFromCache <= aCharsetSource) {
     return true;
   }
 
   nsCString cachedCharset;
   rv = aCachingChannel->GetCacheTokenCachedCharset(cachedCharset);
-  if (NS_SUCCEEDED(rv) && !cachedCharset.IsEmpty())
+  // Check IsAsciiCompatible() even in the cache case, because the value
+  // might be stale and in the case of a stale charset that is not a rough
+  // ASCII superset, the parser has no way to recover.
+  if (NS_SUCCEEDED(rv) &&
+      !cachedCharset.IsEmpty() &&
+      IsAsciiCompatible(cachedCharset))
   {
     aCharset = cachedCharset;
     aCharsetSource = kCharsetFromCache;
 
     return true;
   }
 
   return false;
@@ -412,93 +415,113 @@ CheckSameOrigin(nsINode* aNode1, nsINode
   bool equal;
   return
     NS_SUCCEEDED(aNode1->NodePrincipal()->
                    Equals(aNode2->NodePrincipal(), &equal)) &&
     equal;
 }
 
 bool
+nsHTMLDocument::IsAsciiCompatible(const nsACString& aPreferredName)
+{
+  return !(aPreferredName.LowerCaseEqualsLiteral("utf-16") ||
+           aPreferredName.LowerCaseEqualsLiteral("utf-16be") ||
+           aPreferredName.LowerCaseEqualsLiteral("utf-16le") ||
+           aPreferredName.LowerCaseEqualsLiteral("utf-7") ||
+           aPreferredName.LowerCaseEqualsLiteral("x-imap4-modified-utf7"));
+}
+
+void
 nsHTMLDocument::TryParentCharset(nsIDocShell*  aDocShell,
                                  nsIDocument* aParentDocument,
                                  int32_t& aCharsetSource,
                                  nsACString& aCharset)
 {
-  if (aDocShell) {
-    int32_t source;
-    nsCOMPtr<nsIAtom> csAtom;
-    int32_t parentSource;
-    aDocShell->GetParentCharsetSource(&parentSource);
-    if (kCharsetFromParentForced <= parentSource)
-      source = kCharsetFromParentForced;
-    else if (kCharsetFromHintPrevDoc == parentSource) {
-      // Make sure that's OK
-      if (!aParentDocument || !CheckSameOrigin(this, aParentDocument)) {
-        return false;
-      }
-      
-      // if parent is posted doc, set this prevent autodections
-      // I'm not sure this makes much sense... but whatever.
-      source = kCharsetFromHintPrevDoc;
+  if (!aDocShell) {
+    return;
+  }
+  int32_t source;
+  nsCOMPtr<nsIAtom> csAtom;
+  int32_t parentSource;
+  nsAutoCString parentCharset;
+  aDocShell->GetParentCharset(getter_AddRefs(csAtom));
+  if (!csAtom) {
+    return;
+  }
+  aDocShell->GetParentCharsetSource(&parentSource);
+  csAtom->ToUTF8String(parentCharset);
+  if (kCharsetFromParentForced <= parentSource) {
+    source = kCharsetFromParentForced;
+  } else if (kCharsetFromHintPrevDoc == parentSource) {
+    // Make sure that's OK
+    if (!aParentDocument ||
+        !CheckSameOrigin(this, aParentDocument) ||
+        !IsAsciiCompatible(parentCharset)) {
+      return;
     }
-    else if (kCharsetFromCache <= parentSource) {
-      // Make sure that's OK
-      if (!aParentDocument || !CheckSameOrigin(this, aParentDocument)) {
-        return false;
-      }
-
-      source = kCharsetFromParentFrame;
+
+    // if parent is posted doc, set this prevent autodetections
+    // I'm not sure this makes much sense... but whatever.
+    source = kCharsetFromHintPrevDoc;
+  } else if (kCharsetFromCache <= parentSource) {
+    // Make sure that's OK
+    if (!aParentDocument ||
+        !CheckSameOrigin(this, aParentDocument) ||
+        !IsAsciiCompatible(parentCharset)) {
+      return;
     }
-    else
-      return false;
-
-    if (source < aCharsetSource)
-      return true;
-
-    aDocShell->GetParentCharset(getter_AddRefs(csAtom));
-    if (csAtom) {
-      csAtom->ToUTF8String(aCharset);
-      aCharsetSource = source;
-      return true;
-    }
+
+    source = kCharsetFromParentFrame;
+  } else {
+    return;
   }
-  return false;
+
+  if (source < aCharsetSource) {
+    return;
+  }
+
+  aCharset.Assign(parentCharset);
+  aCharsetSource = source;
 }
 
-bool
+void
 nsHTMLDocument::UseWeakDocTypeDefault(int32_t& aCharsetSource,
                                       nsACString& aCharset)
 {
   if (kCharsetFromWeakDocTypeDefault <= aCharsetSource)
-    return true;
-  // fallback value in case docshell return error
-  aCharset.AssignLiteral("ISO-8859-1");
+    return;
 
   const nsAdoptingCString& defCharset =
     Preferences::GetLocalizedCString("intl.charset.default");
 
-  if (!defCharset.IsEmpty()) {
+  // Don't let the user break things by setting intl.charset.default to
+  // not a rough ASCII superset
+  if (!defCharset.IsEmpty() && IsAsciiCompatible(defCharset)) {
     aCharset = defCharset;
-    aCharsetSource = kCharsetFromWeakDocTypeDefault;
+  } else {
+    aCharset.AssignLiteral("ISO-8859-1");
   }
-  return true;
+  aCharsetSource = kCharsetFromWeakDocTypeDefault;
+  return;
 }
 
 bool
 nsHTMLDocument::TryDefaultCharset( nsIMarkupDocumentViewer* aMarkupDV,
                                    int32_t& aCharsetSource,
                                    nsACString& aCharset)
 {
   if(kCharsetFromUserDefault <= aCharsetSource)
     return true;
 
   nsAutoCString defaultCharsetFromDocShell;
   if (aMarkupDV) {
     nsresult rv =
       aMarkupDV->GetDefaultCharacterSet(defaultCharsetFromDocShell);
+    // Not making the IsAsciiCompatible() check here to allow the user to
+    // force UTF-16 from the menu.
     if(NS_SUCCEEDED(rv)) {
       aCharset = defaultCharsetFromDocShell;
 
       aCharsetSource = kCharsetFromUserDefault;
       return true;
     }
   }
   return false;
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -213,31 +213,33 @@ protected:
   nsRefPtr<nsContentList> mForms;
   nsRefPtr<nsContentList> mFormControls;
 
   /** # of forms in the document, synchronously set */
   int32_t mNumForms;
 
   static uint32_t gWyciwygSessionCnt;
 
-  static bool TryHintCharset(nsIMarkupDocumentViewer* aMarkupDV,
+  static bool IsAsciiCompatible(const nsACString& aPreferredName);
+
+  static void TryHintCharset(nsIMarkupDocumentViewer* aMarkupDV,
                                int32_t& aCharsetSource,
                                nsACString& aCharset);
   static bool TryUserForcedCharset(nsIMarkupDocumentViewer* aMarkupDV,
                                      nsIDocShell*  aDocShell,
                                      int32_t& aCharsetSource,
                                      nsACString& aCharset);
   static bool TryCacheCharset(nsICachingChannel* aCachingChannel,
                                 int32_t& aCharsetSource,
                                 nsACString& aCharset);
   // aParentDocument could be null.
-  bool TryParentCharset(nsIDocShell*  aDocShell,
+  void TryParentCharset(nsIDocShell*  aDocShell,
                           nsIDocument* aParentDocument,
                           int32_t& charsetSource, nsACString& aCharset);
-  static bool UseWeakDocTypeDefault(int32_t& aCharsetSource,
+  static void UseWeakDocTypeDefault(int32_t& aCharsetSource,
                                       nsACString& aCharset);
   static bool TryDefaultCharset(nsIMarkupDocumentViewer* aMarkupDV,
                                   int32_t& aCharsetSource,
                                   nsACString& aCharset);
 
   // Override so we can munge the charset on our wyciwyg channel as needed.
   virtual void SetDocumentCharacterSet(const nsACString& aCharSetID);
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -6420,21 +6420,24 @@ nsDocShell::OnRedirectStateChange(nsICha
         // here.  OnNewURI will do that, so we will cache it.
         SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
     }
 
     // check if the new load should go through the application cache.
     nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
         do_QueryInterface(aNewChannel);
     if (appCacheChannel) {
-        // Permission will be checked in the parent process.
-        if (GeckoProcessType_Default != XRE_GetProcessType())
+        if (GeckoProcessType_Default != XRE_GetProcessType()) {
+            // Permission will be checked in the parent process.
             appCacheChannel->SetChooseApplicationCache(true);
-        else
-            appCacheChannel->SetChooseApplicationCache(ShouldCheckAppCache(newURI));
+        } else {
+            appCacheChannel->SetChooseApplicationCache(
+                                NS_ShouldCheckAppCache(newURI,
+                                                       mInPrivateBrowsing));
+        }
     }
 
     if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) && 
         mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
         mLoadType = LOAD_NORMAL_REPLACE;
         SetHistoryEntry(&mLSHE, nullptr);
     }
 }
@@ -9164,36 +9167,16 @@ nsDocShell::GetInheritedPrincipal(bool a
         }
 
         return docPrincipal;
     }
 
     return nullptr;
 }
 
-bool
-nsDocShell::ShouldCheckAppCache(nsIURI *aURI)
-{
-    if (mInPrivateBrowsing) {
-        return false;
-    }
-
-    nsCOMPtr<nsIOfflineCacheUpdateService> offlineService =
-        do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
-    if (!offlineService) {
-        return false;
-    }
-
-    bool allowed;
-    nsresult rv = offlineService->OfflineAppAllowedForURI(aURI,
-                                                          nullptr,
-                                                          &allowed);
-    return NS_SUCCEEDED(rv) && allowed;
-}
-
 nsresult
 nsDocShell::DoURILoad(nsIURI * aURI,
                       nsIURI * aReferrerURI,
                       bool aSendReferrer,
                       nsISupports * aOwner,
                       const char * aTypeHint,
                       nsIInputStream * aPostData,
                       nsIInputStream * aHeadersData,
@@ -9271,22 +9254,23 @@ nsDocShell::DoURILoad(nsIURI * aURI,
     nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
         do_QueryInterface(channel);
     if (appCacheChannel) {
         // Any document load should not inherit application cache.
         appCacheChannel->SetInheritApplicationCache(false);
 
         // Loads with the correct permissions should check for a matching
         // application cache.
-        // Permission will be checked in the parent process
-        if (GeckoProcessType_Default != XRE_GetProcessType())
+        if (GeckoProcessType_Default != XRE_GetProcessType()) {
+            // Permission will be checked in the parent process
             appCacheChannel->SetChooseApplicationCache(true);
-        else
+        } else {
             appCacheChannel->SetChooseApplicationCache(
-                ShouldCheckAppCache(aURI));
+                NS_ShouldCheckAppCache(aURI, mInPrivateBrowsing));
+        }
     }
 
     // Make sure to give the caller a channel if we managed to create one
     // This is important for correct error page/session history interaction
     if (aRequest)
         NS_ADDREF(*aRequest = channel);
 
     channel->SetOriginalURI(aURI);
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -277,20 +277,16 @@ protected:
     // Get the principal that we'll set on the channel if we're inheriting.  If
     // aConsiderCurrentDocument is true, we try to use the current document if
     // at all possible.  If that fails, we fall back on the parent document.
     // If that fails too, we force creation of a content viewer and use the
     // resulting principal.  If aConsiderCurrentDocument is false, we just look
     // at the parent.
     nsIPrincipal* GetInheritedPrincipal(bool aConsiderCurrentDocument);
 
-    // True if when loading aURI into this docshell, the channel should look
-    // for an appropriate application cache.
-    bool ShouldCheckAppCache(nsIURI * aURI);
-
     // Actually open a channel and perform a URI load.  Note: whatever owner is
     // passed to this function will be set on the channel.  Callers who wish to
     // not have an owner on the channel should just pass null.
     virtual nsresult DoURILoad(nsIURI * aURI,
                                nsIURI * aReferrer,
                                bool aSendReferrer,
                                nsISupports * aOwner,
                                const char * aTypeHint,
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -746,16 +746,18 @@ let DOMApplicationRegistry = {
       if (aOfflineCacheObserver) {
         cacheUpdate.addObserver(aOfflineCacheObserver, false);
       }
     }
   },
 
   checkForUpdate: function(aData, aMm) {
     let app = this.getAppByManifestURL(aData.manifestURL);
+    let installOrigin = app.installOrigin;
+
     if (!app) {
       aData.error = "NO_SUCH_APP";
       aMm.sendAsyncMessage("Webapps:CheckForUpdate:Return:KO", aData);
       return;
     }
 
     function sendError(aError) {
       aData.error = aError;
@@ -845,17 +847,17 @@ let DOMApplicationRegistry = {
     if (aData.etag) {
       xhr.setRequestHeader("If-None-Match", aData.etag);
     }
 
     xhr.addEventListener("load", (function() {
       if (xhr.status == 200) {
         let manifest;
         try {
-          JSON.parse(xhr.responseText, installOrigin);
+          manifest = JSON.parse(xhr.responseText);
         } catch(e) {
           sendError("MANIFEST_PARSE_ERROR");
           return;
         }
         if (!AppsUtils.checkManifest(manifest, installOrigin)) {
           sendError("INVALID_MANIFEST");
         } else {
           app.etag = xhr.getResponseHeader("Etag");
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -494,16 +494,17 @@ DOMInterfaces = {
     'implicitJSContext': [ 'constructor' ]
 }],
 
 ####################################
 # Test Interfaces of various sorts #
 ####################################
 
 'TestInterface' : {
+        # Keep this in sync with TestExampleInterface
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'resultNotAddRefed': [ 'receiveWeakSelf', 'receiveWeakNullableSelf',
                                'receiveWeakOther', 'receiveWeakNullableOther',
                                'receiveWeakExternal', 'receiveWeakNullableExternal',
                                'ReceiveWeakCallbackInterface',
                                'ReceiveWeakNullableCallbackInterface',
                                'receiveWeakCastableObjectSequence',
@@ -582,16 +583,34 @@ DOMInterfaces = {
         'register': False
         },
 
 'TestIndexedAndNamedGetterAndSetterInterface' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'binaryNames': { '__stringifier': 'Stringify' }
         },
+
+'TestExampleInterface' : {
+        # Keep this in sync with TestInterface
+        'headerFile': 'TestExampleInterface-example.h',
+        'register': False,
+        'resultNotAddRefed': [ 'receiveWeakSelf', 'receiveWeakNullableSelf',
+                               'receiveWeakOther', 'receiveWeakNullableOther',
+                               'receiveWeakExternal', 'receiveWeakNullableExternal',
+                               'ReceiveWeakCallbackInterface',
+                               'ReceiveWeakNullableCallbackInterface',
+                               'receiveWeakCastableObjectSequence',
+                               'receiveWeakNullableCastableObjectSequence',
+                               'receiveWeakCastableObjectNullableSequence',
+                               'receiveWeakNullableCastableObjectNullableSequence' ],
+        'binaryNames': { 'methodRenamedFrom': 'methodRenamedTo',
+                         'attributeGetterRenamedFrom': 'attributeGetterRenamedTo',
+                         'attributeRenamedFrom': 'attributeRenamedTo' }
+        }
 }
 
 # These are temporary, until they've been converted to use new DOM bindings
 def addExternalIface(iface, nativeType=None, headerFile=None):
     if iface in DOMInterfaces:
         raise Exception('Interface declared both as WebIDL and External interface')
     domInterface = {
         'concrete': False
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5959,31 +5959,40 @@ class CGExampleMember(CGThing):
                     typeDecl = "%s&"
             return (typeDecl % iface.identifier.name), False, False
 
         if type.isSpiderMonkeyInterface():
             assert not isMember
             if type.nullable():
                 typeDecl = "%s*"
             else:
-                typeDecl = "%s&"
+                typeDecl = "%s"
+                if not optional:
+                    typeDecl += "&"
             return (typeDecl % type.name), False, False
 
         if type.isString():
             if isMember:
                 declType = "nsString"
             else:
                 declType = "nsAString"
             return declType, True, False
 
         if type.isEnum():
             return type.inner.identifier.name, False, True
 
         if type.isCallback():
-            return "JSObject*", False, False
+            if type.nullable():
+                declType = "JSObject*"
+            else:
+                if optional:
+                    declType = "NonNull<JSObject>"
+                else:
+                    declType = "JSObject&"
+            return declType, False, False
 
         if type.isAny():
             return "JS::Value", False, False
 
         if type.isObject():
             if type.nullable():
                 declType = "%s*"
             else:
@@ -6092,21 +6101,18 @@ class CGExampleClass(CGThing):
                     "{\n"
                     "public:\n"
                     "  ${ifaceName}();\n"
                     "  ~${ifaceName}();\n"
                     "\n"
                     "  NS_DECL_CYCLE_COLLECTING_ISUPPORTS\n"
                     "  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(${ifaceName})\n"
                     "\n"
-                    "  void* GetParentObject() const\n"
-                    "  {\n"
-                    "    // TODO: return something sensible here, and change the return type\n"
-                    "    return somethingSensible;\n"
-                    "  }\n"
+                    "  // TODO: return something sensible here, and change the return type\n"
+                    "  ${ifaceName}* GetParentObject() const;\n"
                     "\n" +
                     wrapFunc +
                     "\n").substitute({ "ifaceName": descriptor.name })),
             reindent=True)
 
         self.decl = CGWrapper(self.decl,
                               pre=("\n" + classDecl.define()),
                               post="\n};\n\n")
--- a/dom/bindings/test/Makefile.in
+++ b/dom/bindings/test/Makefile.in
@@ -70,19 +70,23 @@ MOCHITEST_CHROME_FILES = \
   $(NULL)
 
 # Include rules.mk before any of our targets so our first target is coming from
 # rules.mk and running make with no target in this dir does the right thing.
 include $(topsrcdir)/config/rules.mk
 
 $(CPPSRCS): ../%Binding.cpp: $(bindinggen_dependencies) \
                              ../%.webidl \
+                             TestExampleInterface-example \
                              $(NULL)
 	$(MAKE) -C .. $*Binding.h
 	$(MAKE) -C .. $*Binding.cpp
 
+TestExampleInterface-example:
+	$(MAKE) -C .. TestExampleInterface-example
+
 check::
 	PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py
 
 check-interactive:
 	PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py -q
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -29,17 +29,17 @@ callback TestCallback = void();
 TestInterface implements ImplementedInterface;
 
 // This interface is only for use in the constructor below
 interface OnlyForUseInConstructor {
 };
 
 [Constructor,
  Constructor(DOMString str),
- Constructor(unsigned long num, boolean? bool),
+ Constructor(unsigned long num, boolean? boolArg),
  Constructor(TestInterface? iface),
  Constructor(TestNonCastableInterface iface)
  // , Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3)
  ]
 interface TestInterface {
   // Integer types
   // XXXbz add tests for throwing versions of all the integer stuff
   readonly attribute byte readonlyByte;
@@ -327,16 +327,18 @@ interface TestInterface {
   // Typedefs
   const myLong myLongConstant = 5;
   void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg);
   AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
   void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
 
   // Miscellania
   [LenientThis] attribute long attrWithLenientThis;
+
+  // If you add things here, add them to TestExampleGen as well
 };
 
 interface TestNonWrapperCacheInterface {
 };
 
 interface ImplementedInterfaceParent {
   void implementedParentMethod();
   attribute boolean implementedParentProperty;
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -0,0 +1,308 @@
+/* -*- Mode: IDL; 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/.
+ */
+[Constructor,
+ Constructor(DOMString str),
+ Constructor(unsigned long num, boolean? boolArg),
+ Constructor(TestInterface? iface),
+ Constructor(TestNonCastableInterface iface)
+ // , Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3)
+ ]
+interface TestExampleInterface {
+  // Integer types
+  // XXXbz add tests for throwing versions of all the integer stuff
+  readonly attribute byte readonlyByte;
+  attribute byte writableByte;
+  void passByte(byte arg);
+  byte receiveByte();
+  void passOptionalByte(optional byte arg);
+  void passOptionalByteWithDefault(optional byte arg = 0);
+  void passNullableByte(byte? arg);
+  void passOptionalNullableByte(optional byte? arg);
+
+  readonly attribute short readonlyShort;
+  attribute short writableShort;
+  void passShort(short arg);
+  short receiveShort();
+  void passOptionalShort(optional short arg);
+  void passOptionalShortWithDefault(optional short arg = 5);
+
+  readonly attribute long readonlyLong;
+  attribute long writableLong;
+  void passLong(long arg);
+  long receiveLong();
+  void passOptionalLong(optional long arg);
+  void passOptionalLongWithDefault(optional long arg = 7);
+
+  readonly attribute long long readonlyLongLong;
+  attribute long long writableLongLong;
+  void passLongLong(long long arg);
+  long long receiveLongLong();
+  void passOptionalLongLong(optional long long arg);
+  void passOptionalLongLongWithDefault(optional long long arg = -12);
+
+  readonly attribute octet readonlyOctet;
+  attribute octet writableOctet;
+  void passOctet(octet arg);
+  octet receiveOctet();
+  void passOptionalOctet(optional octet arg);
+  void passOptionalOctetWithDefault(optional octet arg = 19);
+
+  readonly attribute unsigned short readonlyUnsignedShort;
+  attribute unsigned short writableUnsignedShort;
+  void passUnsignedShort(unsigned short arg);
+  unsigned short receiveUnsignedShort();
+  void passOptionalUnsignedShort(optional unsigned short arg);
+  void passOptionalUnsignedShortWithDefault(optional unsigned short arg = 2);
+
+  readonly attribute unsigned long readonlyUnsignedLong;
+  attribute unsigned long writableUnsignedLong;
+  void passUnsignedLong(unsigned long arg);
+  unsigned long receiveUnsignedLong();
+  void passOptionalUnsignedLong(optional unsigned long arg);
+  void passOptionalUnsignedLongWithDefault(optional unsigned long arg = 6);
+
+  readonly attribute unsigned long long readonlyUnsignedLongLong;
+  attribute unsigned long long  writableUnsignedLongLong;
+  void passUnsignedLongLong(unsigned long long arg);
+  unsigned long long receiveUnsignedLongLong();
+  void passOptionalUnsignedLongLong(optional unsigned long long arg);
+  void passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 17);
+
+  // Castable interface types
+  // XXXbz add tests for throwing versions of all the castable interface stuff
+  TestInterface receiveSelf();
+  TestInterface? receiveNullableSelf();
+  TestInterface receiveWeakSelf();
+  TestInterface? receiveWeakNullableSelf();
+  // A verstion to test for casting to TestInterface&
+  void passSelf(TestInterface arg);
+  // A version we can use to test for the exact type passed in
+  void passSelf2(TestInterface arg);
+  void passNullableSelf(TestInterface? arg);
+  attribute TestInterface nonNullSelf;
+  attribute TestInterface? nullableSelf;
+  // Optional arguments
+  void passOptionalSelf(optional TestInterface? arg);
+  void passOptionalNonNullSelf(optional TestInterface arg);
+  void passOptionalSelfWithDefault(optional TestInterface? arg = null);
+
+  // Non-wrapper-cache interface types
+  [Creator]
+  TestNonWrapperCacheInterface receiveNonWrapperCacheInterface();
+  [Creator]
+  TestNonWrapperCacheInterface? receiveNullableNonWrapperCacheInterface();
+  [Creator]
+  sequence<TestNonWrapperCacheInterface> receiveNonWrapperCacheInterfaceSequence();
+  [Creator]
+  sequence<TestNonWrapperCacheInterface?> receiveNullableNonWrapperCacheInterfaceSequence();
+  [Creator]
+  sequence<TestNonWrapperCacheInterface>? receiveNonWrapperCacheInterfaceNullableSequence();
+  [Creator]
+  sequence<TestNonWrapperCacheInterface?>? receiveNullableNonWrapperCacheInterfaceNullableSequence();
+
+  // Non-castable interface types
+  TestNonCastableInterface receiveOther();
+  TestNonCastableInterface? receiveNullableOther();
+  TestNonCastableInterface receiveWeakOther();
+  TestNonCastableInterface? receiveWeakNullableOther();
+  // A verstion to test for casting to TestNonCastableInterface&
+  void passOther(TestNonCastableInterface arg);
+  // A version we can use to test for the exact type passed in
+  void passOther2(TestNonCastableInterface arg);
+  void passNullableOther(TestNonCastableInterface? arg);
+  attribute TestNonCastableInterface nonNullOther;
+  attribute TestNonCastableInterface? nullableOther;
+  // Optional arguments
+  void passOptionalOther(optional TestNonCastableInterface? arg);
+  void passOptionalNonNullOther(optional TestNonCastableInterface arg);
+  void passOptionalOtherWithDefault(optional TestNonCastableInterface? arg = null);
+
+  // External interface types
+  TestExternalInterface receiveExternal();
+  TestExternalInterface? receiveNullableExternal();
+  TestExternalInterface receiveWeakExternal();
+  TestExternalInterface? receiveWeakNullableExternal();
+  // A verstion to test for casting to TestExternalInterface&
+  void passExternal(TestExternalInterface arg);
+  // A version we can use to test for the exact type passed in
+  void passExternal2(TestExternalInterface arg);
+  void passNullableExternal(TestExternalInterface? arg);
+  attribute TestExternalInterface nonNullExternal;
+  attribute TestExternalInterface? nullableExternal;
+  // Optional arguments
+  void passOptionalExternal(optional TestExternalInterface? arg);
+  void passOptionalNonNullExternal(optional TestExternalInterface arg);
+  void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null);
+
+  // Callback interface types
+  TestCallbackInterface receiveCallbackInterface();
+  TestCallbackInterface? receiveNullableCallbackInterface();
+  TestCallbackInterface receiveWeakCallbackInterface();
+  TestCallbackInterface? receiveWeakNullableCallbackInterface();
+  // A verstion to test for casting to TestCallbackInterface&
+  void passCallbackInterface(TestCallbackInterface arg);
+  // A version we can use to test for the exact type passed in
+  void passCallbackInterface2(TestCallbackInterface arg);
+  void passNullableCallbackInterface(TestCallbackInterface? arg);
+  attribute TestCallbackInterface nonNullCallbackInterface;
+  attribute TestCallbackInterface? nullableCallbackInterface;
+  // Optional arguments
+  void passOptionalCallbackInterface(optional TestCallbackInterface? arg);
+  void passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg);
+  void passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null);
+
+  // Miscellaneous interface tests
+  IndirectlyImplementedInterface receiveConsequentialInterface();
+  void passConsequentialInterface(IndirectlyImplementedInterface arg);
+
+  // Sequence types
+  sequence<long> receiveSequence();
+  sequence<long>? receiveNullableSequence();
+  sequence<long?> receiveSequenceOfNullableInts();
+  sequence<long?>? receiveNullableSequenceOfNullableInts();
+  void passSequence(sequence<long> arg);
+  void passNullableSequence(sequence<long>? arg);
+  void passSequenceOfNullableInts(sequence<long?> arg);
+  void passOptionalSequenceOfNullableInts(optional sequence<long?> arg);
+  void passOptionalNullableSequenceOfNullableInts(optional sequence<long?>? arg);
+  sequence<TestInterface> receiveCastableObjectSequence();
+  sequence<TestCallbackInterface> receiveCallbackObjectSequence();
+  sequence<TestInterface?> receiveNullableCastableObjectSequence();
+  sequence<TestCallbackInterface?> receiveNullableCallbackObjectSequence();
+  sequence<TestInterface>? receiveCastableObjectNullableSequence();
+  sequence<TestInterface?>? receiveNullableCastableObjectNullableSequence();
+  sequence<TestInterface> receiveWeakCastableObjectSequence();
+  sequence<TestInterface?> receiveWeakNullableCastableObjectSequence();
+  sequence<TestInterface>? receiveWeakCastableObjectNullableSequence();
+  sequence<TestInterface?>? receiveWeakNullableCastableObjectNullableSequence();
+  void passCastableObjectSequence(sequence<TestInterface> arg);
+  void passNullableCastableObjectSequence(sequence<TestInterface?> arg);
+  void passCastableObjectNullableSequence(sequence<TestInterface>? arg);
+  void passNullableCastableObjectNullableSequence(sequence<TestInterface?>? arg);
+  void passOptionalSequence(optional sequence<long> arg);
+  void passOptionalNullableSequence(optional sequence<long>? arg);
+  void passOptionalNullableSequenceWithDefaultValue(optional sequence<long>? arg = null);
+  void passOptionalObjectSequence(optional sequence<TestInterface> arg);
+
+  sequence<DOMString> receiveStringSequence();
+  void passStringSequence(sequence<DOMString> arg);
+
+  sequence<any> receiveAnySequence();
+  sequence<any>? receiveNullableAnySequence();
+
+  // Typed array types
+  void passArrayBuffer(ArrayBuffer arg);
+  void passNullableArrayBuffer(ArrayBuffer? arg);
+  void passOptionalArrayBuffer(optional ArrayBuffer arg);
+  void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg);
+  void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null);
+  void passArrayBufferView(ArrayBufferView arg);
+  void passInt8Array(Int8Array arg);
+  void passInt16Array(Int16Array arg);
+  void passInt32Array(Int32Array arg);
+  void passUint8Array(Uint8Array arg);
+  void passUint16Array(Uint16Array arg);
+  void passUint32Array(Uint32Array arg);
+  void passUint8ClampedArray(Uint8ClampedArray arg);
+  void passFloat32Array(Float32Array arg);
+  void passFloat64Array(Float64Array arg);
+  Uint8Array receiveUint8Array();
+
+  // String types
+  void passString(DOMString arg);
+  void passNullableString(DOMString? arg);
+  void passOptionalString(optional DOMString arg);
+  void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
+  void passOptionalNullableString(optional DOMString? arg);
+  void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
+
+  // Enumerated types
+  void passEnum(TestEnum arg);
+  // No support for nullable enums yet
+  // void passNullableEnum(TestEnum? arg);
+  void passOptionalEnum(optional TestEnum arg);
+  void passEnumWithDefault(optional TestEnum arg = "a");
+  // void passOptionalNullableEnum(optional TestEnum? arg);
+  // void passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null);
+  TestEnum receiveEnum();
+  attribute TestEnum enumAttribute;
+  readonly attribute TestEnum readonlyEnumAttribute;
+
+  // Callback types
+  void passCallback(TestCallback arg);
+  void passNullableCallback(TestCallback? arg);
+  void passOptionalCallback(optional TestCallback arg);
+  void passOptionalNullableCallback(optional TestCallback? arg);
+  void passOptionalNullableCallbackWithDefaultValue(optional TestCallback? arg = null);
+  TestCallback receiveCallback();
+  TestCallback? receiveNullableCallback();
+  void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg);
+  void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
+  void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
+
+  // Any types
+  void passAny(any arg);
+  void passOptionalAny(optional any arg);
+  void passAnyDefaultNull(optional any arg = null);
+  any receiveAny();
+
+  // object types
+  void passObject(object arg);
+  void passNullableObject(object? arg);
+  void passOptionalObject(optional object arg);
+  void passOptionalNullableObject(optional object? arg);
+  void passOptionalNullableObjectWithDefaultValue(optional object? arg = null);
+  object receiveObject();
+  object? receiveNullableObject();
+
+  // Union types
+  void passUnion((object or long) arg);
+  void passUnionWithNullable((object? or long) arg);
+  void passNullableUnion((object or long)? arg);
+  void passOptionalUnion(optional (object or long) arg);
+  void passOptionalNullableUnion(optional (object or long)? arg);
+  void passOptionalNullableUnionWithDefaultValue(optional (object or long)? arg = null);
+  //void passUnionWithInterfaces((TestInterface or TestExternalInterface) arg);
+  //void passUnionWithInterfacesAndNullable((TestInterface? or TestExternalInterface) arg);
+  //void passUnionWithSequence((sequence<object> or long) arg);
+  void passUnionWithArrayBuffer((ArrayBuffer or long) arg);
+  void passUnionWithString((DOMString or object) arg);
+  //void passUnionWithEnum((TestEnum or object) arg);
+  void passUnionWithCallback((TestCallback or long) arg);
+  void passUnionWithObject((object or long) arg);
+  //void passUnionWithDict((Dict or long) arg);
+
+  // binaryNames tests
+  void methodRenamedFrom();
+  void methodRenamedFrom(byte argument);
+  readonly attribute byte attributeGetterRenamedFrom;
+  attribute byte attributeRenamedFrom;
+
+  void passDictionary(optional Dict x);
+  void passOtherDictionary(optional GrandparentDict x);
+  void passSequenceOfDictionaries(sequence<Dict> x);
+  void passDictionaryOrLong(optional Dict x);
+  void passDictionaryOrLong(long x);
+
+  void passDictContainingDict(optional DictContainingDict arg);
+  void passDictContainingSequence(optional DictContainingSequence arg);
+
+  // EnforceRange/Clamp tests
+  void dontEnforceRangeOrClamp(byte arg);
+  void doEnforceRange([EnforceRange] byte arg);
+  void doClamp([Clamp] byte arg);
+
+  // Typedefs
+  const myLong myLongConstant = 5;
+  void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg);
+  AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
+  void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
+
+  // Miscellania
+  [LenientThis] attribute long attrWithLenientThis;
+
+  // If you add things here, add them to TestCodeGen as well
+};
--- a/dom/bluetooth/BluetoothUnixSocketConnector.cpp
+++ b/dom/bluetooth/BluetoothUnixSocketConnector.cpp
@@ -55,16 +55,23 @@ int get_bdaddr(const char *str, bdaddr_t
   for (int i = 0; i < 6; i++) {
     *d-- = strtol(str, &endp, 16);
     MOZ_ASSERT(!(*endp != ':' && i != 5));
     str = endp + 1;
   }
   return 0;
 }
 
+static
+void get_bdaddr_as_string(const bdaddr_t *ba, char *str) {
+    const uint8_t *b = (const uint8_t *)ba;
+    sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
+            b[5], b[4], b[3], b[2], b[1], b[0]);
+}
+
 BluetoothUnixSocketConnector::BluetoothUnixSocketConnector(
   BluetoothSocketType aType,
   int aChannel,
   bool aAuth,
   bool aEncrypt) : mType(aType)
                  , mChannel(aChannel)
                  , mAuth(aAuth)
                  , mEncrypt(aEncrypt)
@@ -174,8 +181,16 @@ BluetoothUnixSocketConnector::CreateAddr
     memcpy(&addr_sco.sco_bdaddr, &bd_address_obj, sizeof(bdaddr_t));
     memcpy(aAddr, &addr_sco, sizeof(addr_sco));
     break;
   default:
     NS_WARNING("Socket type unknown!");
   }
 }
 
+void
+BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr& aAddr,
+                                            nsAString& aAddrStr)
+{
+  char addr[18];
+  get_bdaddr_as_string((bdaddr_t*)&aAddr, addr);
+  aAddrStr.AssignASCII(addr);
+}
--- a/dom/bluetooth/BluetoothUnixSocketConnector.h
+++ b/dom/bluetooth/BluetoothUnixSocketConnector.h
@@ -21,16 +21,19 @@ public:
   virtual ~BluetoothUnixSocketConnector()
   {}
   virtual int Create() MOZ_OVERRIDE;
   virtual void CreateAddr(bool aIsServer,
                           socklen_t& aAddrSize,
                           struct sockaddr* aAddr,
                           const char* aAddress) MOZ_OVERRIDE;
   virtual bool SetUp(int aFd) MOZ_OVERRIDE;
+  virtual void GetSocketAddr(const sockaddr& aAddr,
+                             nsAString& aAddrStr) MOZ_OVERRIDE;
+
 private:
   BluetoothSocketType mType;
   int mChannel;
   bool mAuth;
   bool mEncrypt;
 };
 
 END_BLUETOOTH_NAMESPACE
--- a/dom/network/interfaces/nsIDOMTCPSocket.idl
+++ b/dom/network/interfaces/nsIDOMTCPSocket.idl
@@ -205,26 +205,26 @@ interface nsITCPSocketInternal : nsISupp
  * and the data associated with the event (if any).
  */
 
 [scriptable, uuid(0f2abcca-b483-4539-a3e8-345707f75c44)]
 interface nsITCPSocketEvent : nsISupports {
   /**
    * The socket object which produced this event.
    */
-  readonly attribute nsIDOMTCPSocket socket;
+  readonly attribute nsIDOMTCPSocket target;
 
   /**
    * The type of this event. One of:
    *
-   * onopen
-   * onerror
-   * ondata
-   * ondrain
-   * onclose
+   * open
+   * error
+   * data
+   * drain
+   * close
    */
   readonly attribute DOMString type;
 
   /**
    * The data related to this event, if any. In the ondata callback,
    * data will be the bytes read from the network; if the binaryType
    * of the socket was "arraybuffer", this value will be of type Uint8Array;
    * otherwise, it will be a normal JavaScript string.
--- a/dom/network/src/TCPSocket.js
+++ b/dom/network/src/TCPSocket.js
@@ -44,31 +44,31 @@ function LOG(msg) {
 }
 
 /*
  * nsITCPSocketEvent object
  */
 
 function TCPSocketEvent(type, sock, data) {
   this._type = type;
-  this._socket = sock;
+  this._target = sock;
   this._data = data;
 }
 
 TCPSocketEvent.prototype = {
   __exposedProps__: {
     type: 'r',
-    socket: 'r',
+    target: 'r',
     data: 'r'
   },
   get type() {
     return this._type;
   },
-  get socket() {
-    return this._socket;
+  get target() {
+    return this._target;
   },
   get data() {
     return this._data;
   }
 }
 
 /*
  * nsIDOMTCPSocket object
@@ -228,43 +228,43 @@ TCPSocket.prototype = {
       onStopRequest: function ts_output_onStopRequest(request, context, status) {
         self._asyncCopierActive = false;
         self._multiplexStream.removeStream(0);
 
         if (status) {
           self._readyState = kCLOSED;
           let err = new Error("Connection closed while writing: " + status);
           err.status = status;
-          self.callListener("onerror", err);
-          self.callListener("onclose");
+          self.callListener("error", err);
+          self.callListener("close");
           return;
         }
 
         if (self._multiplexStream.count) {
           self._ensureCopying();
         } else {
           if (self._waitingForDrain) {
             self._waitingForDrain = false;
-            self.callListener("ondrain");
+            self.callListener("drain");
           }
           if (self._readyState === kCLOSING) {
             self._socketOutputStream.close();
             self._readyState = kCLOSED;
-            self.callListener("onclose");
+            self.callListener("close");
           }
         }
       }
     }, null);
   },
 
   callListener: function ts_callListener(type, data) {
-    if (!this[type])
+    if (!this["on" + type])
       return;
 
-    this[type].call(null, new TCPSocketEvent(type, this, data || ""));
+    this["on" + type].call(null, new TCPSocketEvent(type, this, data || ""));
   },
 
   /* nsITCPSocketInternal methods */
   callListenerError: function ts_callListenerError(type, message, filename,
                                                    lineNumber, columnNumber) {
     this.callListener(type, new Error(message, filename, lineNumber, columnNumber));
   },
 
@@ -514,17 +514,17 @@ TCPSocket.prototype = {
     }
   },
 
   // nsITransportEventSink (Triggered by transport.setEventSink)
   onTransportStatus: function ts_onTransportStatus(
     transport, status, progress, max) {
     if (status === Ci.nsISocketTransport.STATUS_CONNECTED_TO) {
       this._readyState = kOPEN;
-      this.callListener("onopen");
+      this.callListener("open");
 
       this._inputStreamPump = new InputStreamPump(
         this._socketInputStream, -1, -1, 0, 0, false
       );
 
       while (this._suspendCount--) {
         this._inputStreamPump.suspend();
       }
@@ -534,17 +534,17 @@ TCPSocket.prototype = {
   },
 
   // nsIAsyncInputStream (Triggered by _socketInputStream.asyncWait)
   // Only used for detecting connection refused
   onInputStreamReady: function ts_onInputStreamReady(input) {
     try {
       input.available();
     } catch (e) {
-      this.callListener("onerror", new Error("Connection refused"));
+      this.callListener("error", new Error("Connection refused"));
     }
   },
 
   // nsIRequestObserver (Triggered by _inputStreamPump.asyncRead)
   onStartRequest: function ts_onStartRequest(request, context) {
   },
 
   // nsIRequestObserver (Triggered by _inputStreamPump.asyncRead)
@@ -562,31 +562,31 @@ TCPSocket.prototype = {
       return;
     }
 
     this._readyState = kCLOSED;
 
     if (status) {
       let err = new Error("Connection closed: " + status);
       err.status = status;
-      this.callListener("onerror", err);
+      this.callListener("error", err);
     }
 
-    this.callListener("onclose");
+    this.callListener("close");
   },
 
   // nsIStreamListener (Triggered by _inputStreamPump.asyncRead)
   onDataAvailable: function ts_onDataAvailable(request, context, inputStream, offset, count) {
     if (this._binaryType === "arraybuffer") {
       let ua = this.useWin ? new this.useWin.Uint8Array(count)
                            : new Uint8Array(count);
       ua.set(this._inputStreamBinary.readByteArray(count));
-      this.callListener("ondata", ua);
+      this.callListener("data", ua);
     } else {
-      this.callListener("ondata", this._inputStreamScriptable.read(count));
+      this.callListener("data", this._inputStreamScriptable.read(count));
     }
   },
 
   classID: Components.ID("{cda91b22-6472-11e1-aa11-834fec09cd0a}"),
 
   classInfo: XPCOMUtils.generateCI({
     classID: Components.ID("{cda91b22-6472-11e1-aa11-834fec09cd0a}"),
     contractID: "@mozilla.org/tcp-socket;1",
@@ -612,17 +612,17 @@ TCPSocket.prototype = {
 
 function SecurityCallbacks(socket) {
   this._socket = socket;
 }
 
 SecurityCallbacks.prototype = {
   notifyCertProblem: function sc_notifyCertProblem(socketInfo, status,
                                                    targetSite) {
-    this._socket.callListener("onerror", status);
+    this._socket.callListener("error", status);
     this._socket.close();
     return true;
   },
 
   getInterface: function sc_getInterface(iid) {
     return this.QueryInterface(iid);
   },
 
--- a/dom/network/src/TCPSocketParentIntermediary.js
+++ b/dom/network/src/TCPSocketParentIntermediary.js
@@ -21,19 +21,19 @@ TCPSocketParentIntermediary.prototype = 
     let socket = this._socket = baseSocket.open(aHost, aPort,
                                                 {useSSL: aUseSSL,
                                                 binaryType: aBinaryType});
     if (!socket)
       return null;
 
     // Create handlers for every possible callback that attempt to trigger
     // corresponding callbacks on the child object.
-    ["onopen", "ondrain", "ondata", "onerror", "onclose"].forEach(
+    ["open", "drain", "data", "error", "close"].forEach(
       function(p) {
-        socket[p] = function(data) {
+        socket["on" + p] = function(data) {
           aParentSide.sendCallback(p, data.data, socket.readyState,
                                    socket.bufferedAmount);
         };
       }
     );
 
     return socket;
   },
--- a/dom/tests/mochitest/chrome/file_bug799299.xul
+++ b/dom/tests/mochitest/chrome/file_bug799299.xul
@@ -26,32 +26,36 @@ https://bugzilla.mozilla.org/show_bug.cg
     wu.sendMouseEventToWindow("mousedown", 10, 10, 0, 0, 0);
     wu.sendMouseEventToWindow("mouseup", 10, 10, 0, 0, 0);
   }
 
   function runTests() {
     var b1 = document.getElementById("b1");
     var b2 = document.getElementById("b2");
     b1.contentWindow.focus();
-    opener.wrappedJSObject.is(document.activeElement, b1);
+    opener.wrappedJSObject.is(document.activeElement, b1,
+                              "Focused first iframe");
 
     var didCallDummy = false;
     b2.contentWindow.addEventListener("mousedown", function(e) { didCallDummy = true; });
     sendClick(b2.contentWindow);
-    opener.wrappedJSObject.ok(didCallDummy);
-    opener.wrappedJSObject.is(document.activeElement, b2);
+    opener.wrappedJSObject.ok(didCallDummy, "dummy mousedown handler should fire");
+    opener.wrappedJSObject.is(document.activeElement, b2,
+                              "Focus shifted to second iframe");
 
     b1.contentWindow.focus();
-    opener.wrappedJSObject.is(document.activeElement, b1);
+    opener.wrappedJSObject.is(document.activeElement, b1,
+                              "Re-focused first iframe for the first time");
 
     var didCallListener = false;
     b2.contentWindow.addEventListener("mousedown", function(e) { didCallListener = true; e.preventDefault(); });
     sendClick(b2.contentWindow);
-    opener.wrappedJSObject.ok(didCallListener);
-    opener.wrappedJSObject.is(document.activeElement, b2);
+    opener.wrappedJSObject.ok(didCallListener, "mousedown handler should fire");
+    opener.wrappedJSObject.is(document.activeElement, b2,
+                              "focus should move to the second iframe");
 
     window.close();
     opener.wrappedJSObject.SimpleTest.finish();
   }
 
   SimpleTest.waitForFocus(runTests);
   ]]>
   </script>
--- a/dom/tests/mochitest/chrome/file_bug800817.xul
+++ b/dom/tests/mochitest/chrome/file_bug800817.xul
@@ -26,41 +26,46 @@ https://bugzilla.mozilla.org/show_bug.cg
     wu.sendMouseEventToWindow("mousedown", 10, 10, 0, 0, 0);
     wu.sendMouseEventToWindow("mouseup", 10, 10, 0, 0, 0);
   }
 
   function runTests() {
     var b1 = document.getElementById("b1");
     var b2 = document.getElementById("b2");
 
-    var mozbrowserAttr = opener.wrappedJSObject.testMozBrowser ? "true" : "false";
-    b1.setAttribute("mozbrowser", mozbrowserAttr);
-    b2.setAttribute("mozbrowser", mozbrowserAttr);
+    var testMozBrowser = opener.wrappedJSObject.testMozBrowser;
+    if (testMozBrowser) {
+      b1.setAttribute("mozbrowser", "true");
+      b2.setAttribute("mozbrowser", "true");
+    }
 
-    opener.wrappedJSObject.ok(true, "Testing with mozbrowser="+ mozbrowserAttr);
+    if (testMozBrowser)
+      opener.wrappedJSObject.info("Testing with mozbrowser=true");
+    else
+      opener.wrappedJSObject.info("Testing without mozbrowser");
 
     b1.contentWindow.focus();
     opener.wrappedJSObject.is(document.activeElement, b1,
                               "Focused first iframe");
 
     var didCallDummy = false;
     b2.contentWindow.addEventListener("mousedown", function(e) { didCallDummy = true; });
     sendClick(b2.contentWindow);
-    opener.wrappedJSObject.ok(didCallDummy);
+    opener.wrappedJSObject.ok(didCallDummy, "dummy mousedown handler should fire");
     opener.wrappedJSObject.is(document.activeElement, b2,
                               "Focus shifted to second iframe");
 
     b1.contentWindow.focus();
     opener.wrappedJSObject.is(document.activeElement, b1,
                               "Re-focused first iframe for the first time");
 
     var didCallListener = false;
     b2.contentWindow.addEventListener("mousedown", function(e) { didCallListener = true; e.preventDefault(); });
     sendClick(b2.contentWindow);
-    opener.wrappedJSObject.ok(didCallListener);
+    opener.wrappedJSObject.ok(didCallListener, "mousedown handler should fire");
     opener.wrappedJSObject.is(document.activeElement, b1,
                               "Did not move focus to the second iframe");
 
     window.close();
     opener.wrappedJSObject.finishedTests();
   }
 
   SimpleTest.waitForFocus(runTests);
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -66,14 +66,15 @@ webidl_files += \
   USSDReceivedEvent.webidl \
   $(NULL)
 endif
 
 ifdef ENABLE_TESTS
 test_webidl_files := \
   TestCodeGen.webidl \
   TestDictionary.webidl \
+  TestExampleGen.webidl \
   TestTypedef.webidl \
   $(NULL)
 else
 test_webidl_files := $(NULL)
 endif
 
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -758,17 +758,21 @@ nsHTMLEditor::NodeIsBlockStatic(const do
       tagAtom==nsEditProperty::dt         ||
       tagAtom==nsEditProperty::dd         ||
       tagAtom==nsEditProperty::pre)
   {
     return true;
   }
 
   bool isBlock;
-  DebugOnly<nsresult> rv = nsContentUtils::GetParserService()->
+#ifdef DEBUG
+  // XXX we can't use DebugOnly here because VC++ is stupid (bug 802884)
+  nsresult rv =
+#endif
+    nsContentUtils::GetParserService()->
     IsBlock(nsContentUtils::GetParserService()->HTMLAtomTagToId(tagAtom),
             isBlock);
   MOZ_ASSERT(rv == NS_OK);
 
   AssertParserServiceIsCorrect(tagAtom, isBlock);
 
   return isBlock;
 }
--- a/extensions/gio/Makefile.in
+++ b/extensions/gio/Makefile.in
@@ -9,27 +9,19 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= nkgio
 LIBRARY_NAME	= nkgio
 SHORT_LIBNAME	= nkgio
 IS_COMPONENT	= 1
+EXPORT_LIBRARY	= 1
+MODULE_NAME	= nsGIOModule
+LIBXUL_LIBRARY	= 1
 
 CPPSRCS		= \
 		nsGIOProtocolHandler.cpp \
 		$(NULL)
 
 LOCAL_INCLUDES	= $(MOZ_GIO_CFLAGS)
 
-EXTRA_DSO_LDOPTS = \
-		   $(XPCOM_GLUE_LDOPTS) \
-		   $(MOZ_COMPONENT_LIBS) \
-		   $(MOZ_GIO_LIBS) \
-		   $(NULL)
-
-# make sure this component is never statically linked into the main
-# application.  this is necessary since we don't want to force users
-# to install gio in order to use the rest of mozilla ;-)
-FORCE_SHARED_LIB= 1
-
 include $(topsrcdir)/config/rules.mk
--- a/gfx/layers/ThebesLayerBuffer.cpp
+++ b/gfx/layers/ThebesLayerBuffer.cpp
@@ -307,17 +307,17 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
     if (!destBuffer)
       return result;
   }
   NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(),
                "If we're resampling, we need to validate the entire buffer");
 
   // If we have no buffered data already, then destBuffer will be a fresh buffer
   // and we do not need to clear it below.
-  bool isClear = mBuffer == nullptr;
+  bool isClear = !HaveBuffer();
 
   if (destBuffer) {
     if (HaveBuffer()) {
       // Copy the bits
       nsRefPtr<gfxContext> tmpCtx = new gfxContext(destBuffer);
       nsIntPoint offset = -destBufferRect.TopLeft();
       tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
       tmpCtx->Translate(gfxPoint(offset.x, offset.y));
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -411,16 +411,18 @@ BasicShadowableCanvasLayer::Paint(gfxCon
       handle = mGLContext->CreateSharedHandle(flags);
       if (handle) {
         mBackBuffer = SharedTextureDescriptor(flags, handle, mBounds.Size(), false);
       }
     }
     if (handle) {
       mGLContext->MakeCurrent();
       mGLContext->UpdateSharedHandle(flags, handle);
+      // call Painted() to reset our dirty 'bit'
+      Painted();
       FireDidTransactionCallback();
       BasicManager()->PaintedCanvas(BasicManager()->Hold(this),
                                     mNeedsYFlip,
                                     mBackBuffer);
       // Move SharedTextureHandle ownership to ShadowLayer
       mBackBuffer = SurfaceDescriptor();
       return;
     }
--- a/gfx/layers/opengl/ReusableTileStoreOGL.cpp
+++ b/gfx/layers/opengl/ReusableTileStoreOGL.cpp
@@ -213,25 +213,35 @@ ReusableTileStoreOGL::DrawTiles(TiledThe
   // rendered.
   gfxRect contentBounds, displayPort;
   ContainerLayer* scrollableLayer = nullptr;
   for (ContainerLayer* parent = aLayer->GetParent(); parent; parent = parent->GetParent()) {
       const FrameMetrics& parentMetrics = parent->GetFrameMetrics();
       if (parentMetrics.IsScrollable())
         scrollableLayer = parent;
       if (!parentMetrics.mDisplayPort.IsEmpty() && scrollableLayer) {
-          displayPort = parent->GetEffectiveTransform().
-            TransformBounds(gfxRect(
-              parentMetrics.mDisplayPort.x, parentMetrics.mDisplayPort.y,
-              parentMetrics.mDisplayPort.width, parentMetrics.mDisplayPort.height));
+          // Get the display-port bounds in screen-space.
+          displayPort = gfxRect(parentMetrics.mDisplayPort.x,
+                                parentMetrics.mDisplayPort.y,
+                                parentMetrics.mDisplayPort.width,
+                                parentMetrics.mDisplayPort.height);
+
+          // Calculate the scale transform applied to the root layer to determine
+          // the content resolution.
+          Layer* rootLayer = aLayer->Manager()->GetRoot();
+          const gfx3DMatrix& rootTransform = rootLayer->GetTransform();
+          float scaleX = rootTransform.GetXScale();
+          float scaleY = rootTransform.GetYScale();
+
+          // Get the content document bounds, in screen-space.
           const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics();
           const nsIntSize& contentSize = metrics.mContentRect.Size();
           gfx::Point scrollOffset =
-            gfx::Point(metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width,
-                       metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height);
+            gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scaleX,
+                       (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scaleY);
           const nsIntPoint& contentOrigin = metrics.mContentRect.TopLeft() -
             nsIntPoint(NS_lround(scrollOffset.x), NS_lround(scrollOffset.y));
           gfxRect contentRect = gfxRect(contentOrigin.x, contentOrigin.y,
                                         contentSize.width, contentSize.height);
           contentBounds = scrollableLayer->GetEffectiveTransform().TransformBounds(contentRect);
           break;
       }
   }
@@ -254,25 +264,27 @@ ReusableTileStoreOGL::DrawTiles(TiledThe
     if (aResolution != tile->mResolution)
       transformedValidRegion.ScaleRoundOut(1.0f/scaleFactor.width,
                                            1.0f/scaleFactor.height);
     nsIntRegion tileRegion;
     tileRegion.Sub(tile->mTileRegion, transformedValidRegion);
 
     // Subtract the display-port from the tile region.
     if (!displayPort.IsEmpty()) {
+      // Transform the display-port from screen space to layer space.
       gfxRect transformedRenderBounds = transform.Inverse().TransformBounds(displayPort);
       tileRegion.Sub(tileRegion, nsIntRect(transformedRenderBounds.x,
                                            transformedRenderBounds.y,
                                            transformedRenderBounds.width,
                                            transformedRenderBounds.height));
     }
 
     // Intersect the tile region with the content area.
     if (!contentBounds.IsEmpty()) {
+      // Transform the content bounds from screen space to layer space.
       gfxRect transformedRenderBounds = transform.Inverse().TransformBounds(contentBounds);
       tileRegion.And(tileRegion, nsIntRect(transformedRenderBounds.x,
                                            transformedRenderBounds.y,
                                            transformedRenderBounds.width,
                                            transformedRenderBounds.height));
     }
 
     // If the tile region is empty, skip drawing.
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -221,16 +221,17 @@ nsFontCache::Flush()
 
 nsDeviceContext::nsDeviceContext()
     : mWidth(0), mHeight(0), mDepth(0),
       mAppUnitsPerDevPixel(-1), mAppUnitsPerDevNotScaledPixel(-1),
       mAppUnitsPerPhysicalInch(-1),
       mPixelScale(1.0f), mPrintingScale(1.0f),
       mFontCache(nullptr)
 {
+    MOZ_ASSERT(NS_IsMainThread(), "nsDeviceContext created off main thread");
 }
 
 // Note: we use a bare pointer for mFontCache so that nsFontCache
 // can be an incomplete type in nsDeviceContext.h.
 // Therefore we have to do all the refcounting by hand.
 nsDeviceContext::~nsDeviceContext()
 {
     if (mFontCache) {
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -578,16 +578,18 @@ nsPNGDecoder::info_callback(png_structp 
    * members and whatnot, after which we can get channels, rowbytes, etc. */
   png_read_update_info(png_ptr, info_ptr);
   decoder->mChannels = channels = png_get_channels(png_ptr, info_ptr);
 
   /*---------------------------------------------------------------*/
   /* copy PNG info into imagelib structs (formerly png_set_dims()) */
   /*---------------------------------------------------------------*/
 
+  // This code is currently unused, but it will be needed for bug 517713.
+#if 0
   int32_t alpha_bits = 1;
 
   if (channels == 2 || channels == 4) {
     /* check if alpha is coming from a tRNS chunk and is binary */
     if (num_trans) {
       /* if it's not an indexed color image, tRNS means binary */
       if (color_type == PNG_COLOR_TYPE_PALETTE) {
         for (int i=0; i<num_trans; i++) {
@@ -596,16 +598,17 @@ nsPNGDecoder::info_callback(png_structp 
             break;
           }
         }
       }
     } else {
       alpha_bits = 8;
     }
   }
+#endif
 
   if (channels == 1 || channels == 3)
     decoder->format = gfxASurface::ImageFormatRGB24;
   else if (channels == 2 || channels == 4)
     decoder->format = gfxASurface::ImageFormatARGB32;
 
 #ifdef PNG_APNG_SUPPORTED
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL))
--- a/ipc/unixsocket/UnixSocket.cpp
+++ b/ipc/unixsocket/UnixSocket.cpp
@@ -146,16 +146,27 @@ public:
 
   /** 
    * Set up nonblocking flags on whatever our current file descriptor is.
    *
    * @return true if successful, false otherwise
    */
   bool SetNonblockFlags();
 
+  void GetSocketAddr(nsAString& aAddrStr)
+  {
+    if (!mConnector)
+    {
+      NS_WARNING("No connector to get socket address from!");
+      aAddrStr = nsString();
+      return;
+    }
+    mConnector->GetSocketAddr(mAddr, aAddrStr);
+  }
+
   /**
    * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
    * directly from main thread. All non-main-thread accesses should happen with
    * mImpl as container.
    */
   RefPtr<UnixSocketConsumer> mConsumer;
 
 private:
@@ -222,16 +233,27 @@ private:
    * will be taken care of by the IO loop. Just set to nullptr.
    */
   CancelableTask* mTask;
 
   /**
    * Address we are connecting to, assuming we are creating a client connection.
    */
   nsCString mAddress;
+
+  /**
+   * Size of the socket address struct
+   */
+  socklen_t mAddrSize;
+
+  /**
+   * Address struct of the socket currently in use
+   */
+  sockaddr mAddr;
+
 };
 
 static void
 DestroyImpl(UnixSocketImpl* impl)
 {
   MOZ_ASSERT(impl);
   delete impl;
 }
@@ -399,57 +421,55 @@ void SocketConnectTask::Run() {
     return;
   }
   mImpl->Connect();
 }
 
 void
 UnixSocketImpl::Accept()
 {
-  socklen_t addr_sz;
-  struct sockaddr addr;
 
   if (!mConnector) {
     NS_WARNING("No connector object available!");
     return;
   }
 
   // This will set things we don't particularly care about, but it will hand
   // back the correct structure size which is what we do care about.
-  mConnector->CreateAddr(true, addr_sz, &addr, nullptr);
+  mConnector->CreateAddr(true, mAddrSize, &mAddr, nullptr);
 
   if(mFd.get() < 0)
   {
     mFd = mConnector->Create();
     if (mFd.get() < 0) {
       return;
     }
 
     if (!SetNonblockFlags()) {
       return;
     }
 
-    if (bind(mFd.get(), &addr, addr_sz)) {
+    if (bind(mFd.get(), &mAddr, mAddrSize)) {
 #ifdef DEBUG
       LOG("...bind(%d) gave errno %d", mFd.get(), errno);
 #endif
       return;
     }
 
     if (listen(mFd.get(), 1)) {
 #ifdef DEBUG
       LOG("...listen(%d) gave errno %d", mFd.get(), errno);
 #endif
       return;
     }
 
   }
 
   int client_fd;
-  client_fd = accept(mFd.get(), &addr, &addr_sz);
+  client_fd = accept(mFd.get(), &mAddr, &mAddrSize);
   if (client_fd < 0) {
     EnqueueTask(SOCKET_RETRY_TIME_MS, new SocketAcceptTask(this));
     return;
   }
 
   if (!mConnector->SetUp(client_fd)) {
     NS_WARNING("Could not set up socket!");
     return;
@@ -474,22 +494,20 @@ UnixSocketImpl::Connect()
   {
     mFd = mConnector->Create();
     if (mFd.get() < 0) {
       return;
     }
   }
 
   int ret;
-  socklen_t addr_sz;
-  struct sockaddr addr;
 
-  mConnector->CreateAddr(false, addr_sz, &addr, mAddress.get());
+  mConnector->CreateAddr(false, mAddrSize, &mAddr, mAddress.get());
 
-  ret = connect(mFd.get(), &addr, addr_sz);
+  ret = connect(mFd.get(), &mAddr, mAddrSize);
 
   if (ret) {
 #if DEBUG
     LOG("Socket connect errno=%d\n", errno);
 #endif
     mFd.reset(-1);
     nsRefPtr<OnSocketEventTask> t =
       new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
@@ -689,16 +707,27 @@ UnixSocketImpl::OnFileCanWriteWithoutBlo
       return;
     }
     mOutgoingQ.RemoveElementAt(0);
     delete data;
   }
 }
 
 void
+UnixSocketConsumer::GetSocketAddr(nsAString& aAddrStr)
+{
+  if (!mImpl || mConnectionStatus != SOCKET_CONNECTED) {
+    NS_WARNING("No socket currently open!");
+    aAddrStr = nsString();
+    return;
+  }
+  mImpl->GetSocketAddr(aAddrStr);
+}
+
+void
 UnixSocketConsumer::NotifySuccess()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mConnectionStatus = SOCKET_CONNECTED;
   OnConnectSuccess();
 }
 
 void
--- a/ipc/unixsocket/UnixSocket.h
+++ b/ipc/unixsocket/UnixSocket.h
@@ -96,16 +96,27 @@ public:
   /** 
    * Does any socket type specific setup that may be needed
    *
    * @param aFd File descriptor for opened socket
    *
    * @return true is successful, false otherwise
    */
   virtual bool SetUp(int aFd) = 0;
+
+  /** 
+   * Get address of socket we're currently connected to. Return null string if
+   * not connected.
+   *
+   * @param aAddr Address struct
+   * @param aAddrStr String to store address to
+   */
+  virtual void GetSocketAddr(const sockaddr& aAddr,
+                             nsAString& aAddrStr) = 0;
+
 };
 
 enum SocketConnectionStatus {
   SOCKET_DISCONNECTED = 0,
   SOCKET_CONNECTING = 1,
   SOCKET_CONNECTED = 2
 };
 
@@ -207,16 +218,22 @@ public:
    * Called by implementation to notify consumer of error.
    */
   void NotifyError();
 
   /** 
    * Called by implementation to notify consumer of disconnect.
    */
   void NotifyDisconnect();
+
+  /**
+   * Get the current sockaddr for the socket
+   */
+  void GetSocketAddr(nsAString& aAddrStr);
+
 private:
   UnixSocketImpl* mImpl;
   SocketConnectionStatus mConnectionStatus;
 };
 
 } // namespace ipc
 } // namepsace mozilla
 
--- a/js/src/build/autoconf/arch.m4
+++ b/js/src/build/autoconf/arch.m4
@@ -45,16 +45,20 @@ if test -z "$MOZ_ARCH"; then
         fi
         if test "$MOZ_PLATFORM_MAEMO" = 6; then
             MOZ_THUMB=yes
         fi
         ;;
     esac
 fi
 
+if test "$MOZ_ARCH" = "armv6" -a "$OS_TARGET" = "Android"; then
+   MOZ_FPU=vfp
+fi
+
 MOZ_ARG_WITH_STRING(thumb,
 [  --with-thumb[[=yes|no|toolchain-default]]]
 [                          Use Thumb instruction set (-mthumb)],
     if test -z "$GNU_CC"; then
         AC_MSG_ERROR([--with-thumb is not supported on non-GNU toolchains])
     fi
     MOZ_THUMB=$withval)
 
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -162,18 +162,18 @@ GetBuildConfiguration(JSContext *cx, uns
 }
 
 static JSBool
 GC(JSContext *cx, unsigned argc, jsval *vp)
 {
     /*
      * If the first argument is 'compartment', we collect any compartments
      * previously scheduled for GC via schedulegc. If the first argument is an
-     * object, we collect the object's compartment (any any other compartments
-     * scheduled for GC). Otherwise, we collect call compartments.
+     * object, we collect the object's compartment (and any other compartments
+     * scheduled for GC). Otherwise, we collect all compartments.
      */
     JSBool compartment = false;
     if (argc == 1) {
         Value arg = vp[2];
         if (arg.isString()) {
             if (!JS_StringEqualsAscii(cx, arg.toString(), "compartment", &compartment))
                 return false;
         } else if (arg.isObject()) {
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1111,18 +1111,18 @@ Makefile: Makefile.in
 	@$(PYTHON) $(DEPTH)/config.status -n --file=Makefile
 	@$(TOUCH) $@
 endif
 
 ifndef NO_SUBMAKEFILES_RULE
 ifdef SUBMAKEFILES
 # VPATH does not work on some machines in this case, so add $(srcdir)
 $(SUBMAKEFILES): % : $(srcdir)/%.in
-	$(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file=$@
-	@$(TOUCH) $@
+	$(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file="$@"
+	@$(TOUCH) "$@"
 endif
 endif
 
 ifdef AUTOUPDATE_CONFIGURE
 $(topsrcdir)/configure: $(topsrcdir)/configure.in
 	(cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck
 endif
 
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -199,19 +199,19 @@ UpdateDepth(JSContext *cx, BytecodeEmitt
          */
         unsigned depth = (unsigned) bce->stackDepth +
                       ((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT);
         if (depth > bce->maxStackDepth)
             bce->maxStackDepth = depth;
     }
 
     /*
-     * Specially handle any case that would call js_GetIndexFromBytecode since
-     * it requires a well-formed script. This allows us to safely pass NULL as
-     * the 'script' parameter.
+     * Specially handle any case in which StackUses or StackDefs would call
+     * NumBlockSlots, since that requires a well-formed script. This allows us
+     * to safely pass NULL as the 'script' parameter to StackUses and StackDefs.
      */
     int nuses, ndefs;
     if (op == JSOP_ENTERBLOCK) {
         nuses = 0;
         ndefs = CurrentBlock(bce->topStmt).slotCount();
     } else if (op == JSOP_ENTERLET0) {
         nuses = ndefs = CurrentBlock(bce->topStmt).slotCount();
     } else if (op == JSOP_ENTERLET1) {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug673468.js
@@ -0,0 +1,8 @@
+var g = newGlobal();
+var k = g.eval('var u = new Object(); u');
+var m = new WeakMap();
+m.set(k, {});
+k = null;
+gc();
+k = g.eval('u');
+assertEq(m.has(k), true);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1878,16 +1878,19 @@ typedef void
  * a string describing the reference traced with JS_CallTracer.
  */
 typedef void
 (* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
 
 typedef JSBool
 (* JSEqualityOp)(JSContext *cx, JSHandleObject obj, JSHandleValue v, JSBool *bp);
 
+typedef JSRawObject
+(* JSWeakmapKeyDelegateOp)(JSRawObject obj);
+
 /*
  * Typedef for native functions called by the JS VM.
  *
  * See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros.
  */
 
 typedef JSBool
 (* JSNative)(JSContext *cx, unsigned argc, jsval *vp);
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -250,19 +250,32 @@ struct ClassExtension
     JSIteratorOp        iteratorObject;
     void               *unused;
 
     /*
      * isWrappedNative is true only if the class is an XPCWrappedNative.
      * WeakMaps use this to override the wrapper disposal optimization.
      */
     bool                isWrappedNative;
+
+    /*
+     * If an object is used as a key in a weakmap, it may be desirable for the
+     * garbage collector to keep that object around longer than it otherwise
+     * would. A common case is when the key is a wrapper around an object in
+     * another compartment, and we want to avoid collecting the wrapper (and
+     * removing the weakmap entry) as long as the wrapped object is alive. In
+     * that case, the wrapped object is returned by the wrapper's
+     * weakmapKeyDelegateOp hook. As long as the wrapper is used as a weakmap
+     * key, it will not be collected (and remain in the weakmap) until the
+     * wrapped object is collected.
+     */
+    JSWeakmapKeyDelegateOp weakmapKeyDelegateOp;
 };
 
-#define JS_NULL_CLASS_EXT   {NULL,NULL,NULL,NULL,NULL,false}
+#define JS_NULL_CLASS_EXT   {NULL,NULL,NULL,NULL,NULL,false,NULL}
 
 struct ObjectOps
 {
     LookupGenericOp     lookupGeneric;
     LookupPropOp        lookupProperty;
     LookupElementOp     lookupElement;
     LookupSpecialOp     lookupSpecial;
     DefineGenericOp     defineGeneric;
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -527,16 +527,24 @@ js::VisitGrayWrapperTargets(JSCompartmen
 {
     for (WrapperMap::Enum e(comp->crossCompartmentWrappers); !e.empty(); e.popFront()) {
         gc::Cell *thing = e.front().key.wrapped;
         if (thing->isMarked(gc::GRAY))
             callback(closure, thing);
     }
 }
 
+JS_FRIEND_API(JSObject *)
+js::GetWeakmapKeyDelegate(JSObject *key)
+{
+    if (JSWeakmapKeyDelegateOp op = key->getClass()->ext.weakmapKeyDelegateOp)
+        return op(key);
+    return NULL;
+}
+
 JS_FRIEND_API(void)
 JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback)
 {
     rt->telemetryCallback = callback;
 }
 
 JS_FRIEND_API(JSObject *)
 JS_CloneObject(JSContext *cx, JSObject *obj_, JSObject *proto_, JSObject *parent_)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -260,16 +260,19 @@ extern JS_FRIEND_API(bool)
 GCThingIsMarkedGray(void *thing);
 
 typedef void
 (GCThingCallback)(void *closure, void *gcthing);
 
 extern JS_FRIEND_API(void)
 VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure);
 
+extern JS_FRIEND_API(JSObject *)
+GetWeakmapKeyDelegate(JSObject *key);
+
 /*
  * Shadow declarations of JS internal structures, for access by inline access
  * functions below. Do not use these structures in any other way. When adding
  * new fields for access by inline methods, make sure to add static asserts to
  * the original header file to ensure that offsets are consistent.
  */
 namespace shadow {
 
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -348,16 +348,22 @@ BaseProxyHandler::objectClassIs(JSObject
     return false;
 }
 
 void
 BaseProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy)
 {
 }
 
+JSObject *
+BaseProxyHandler::weakmapKeyDelegate(JSObject *proxy)
+{
+    return NULL;
+}
+
 bool
 BaseProxyHandler::getPrototypeOf(JSContext *cx, JSObject *proxy, JSObject **proto)
 {
     // The default implementation here just uses proto of the proxy object.
     *proto = proxy->getTaggedProto().toObjectOrNull();
     return true;
 }
 
@@ -544,16 +550,22 @@ IndirectProxyHandler::iteratorNext(JSCon
         *vp = cx->iterValue;
         cx->iterValue = UndefinedValue();
     } else {
         *vp = MagicValue(JS_NO_ITER_VALUE);
     }
     return true;
 }
 
+JSObject *
+IndirectProxyHandler::weakmapKeyDelegate(JSObject *proxy)
+{
+    return UnwrapObject(proxy);
+}
+
 DirectProxyHandler::DirectProxyHandler(void *family)
   : IndirectProxyHandler(family)
 {
 }
 
 bool
 DirectProxyHandler::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
 {
@@ -2852,29 +2864,35 @@ proxy_TraceFunction(JSTracer *trc, RawOb
 {
     // NB: If you add new slots here, make sure to change
     // js::NukeChromeCrossCompartmentWrappers to cope.
     MarkCrossCompartmentSlot(trc, &GetCall(obj), "call");
     MarkSlot(trc, &GetFunctionProxyConstruct(obj), "construct");
     proxy_TraceObject(trc, obj);
 }
 
+static JSObject *
+proxy_WeakmapKeyDelegate(RawObject obj)
+{
+    JS_ASSERT(obj->isProxy());
+    return GetProxyHandler(obj)->weakmapKeyDelegate(obj);
+}
+
 static JSBool
 proxy_Convert(JSContext *cx, HandleObject proxy, JSType hint, MutableHandleValue vp)
 {
     JS_ASSERT(proxy->isProxy());
     return Proxy::defaultValue(cx, proxy, hint, vp.address());
 }
 
 static void
 proxy_Finalize(FreeOp *fop, RawObject obj)
 {
     JS_ASSERT(obj->isProxy());
-    if (!obj->getSlot(JSSLOT_PROXY_HANDLER).isUndefined())
-        GetProxyHandler(obj)->finalize(fop, obj);
+    GetProxyHandler(obj)->finalize(fop, obj);
 }
 
 static JSBool
 proxy_HasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, JSBool *bp)
 {
     bool b;
     if (!Proxy::hasInstance(cx, proxy, v, &b))
         return false;
@@ -2884,33 +2902,44 @@ proxy_HasInstance(JSContext *cx, HandleO
 
 static JSType
 proxy_TypeOf(JSContext *cx, HandleObject proxy)
 {
     JS_ASSERT(proxy->isProxy());
     return Proxy::typeOf(cx, proxy);
 }
 
+#define PROXY_CLASS_EXT                             \
+    {                                               \
+        NULL,                /* equality */         \
+        NULL,                /* outerObject */      \
+        NULL,                /* innerObject */      \
+        NULL,                /* iteratorObject */   \
+        NULL,                /* unused */           \
+        false,               /* isWrappedNative */  \
+        proxy_WeakmapKeyDelegate                    \
+    }
+
 JS_FRIEND_DATA(Class) js::ObjectProxyClass = {
     "Proxy",
     Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(4),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     proxy_Convert,
     proxy_Finalize,          /* finalize    */
     NULL,                    /* checkAccess */
     NULL,                    /* call        */
     proxy_HasInstance,       /* hasInstance */
     NULL,                    /* construct   */
     proxy_TraceObject,       /* trace       */
-    JS_NULL_CLASS_EXT,
+    PROXY_CLASS_EXT,
     {
         proxy_LookupGeneric,
         proxy_LookupProperty,
         proxy_LookupElement,
         proxy_LookupSpecial,
         proxy_DefineGeneric,
         proxy_DefineProperty,
         proxy_DefineElement,
@@ -2956,17 +2985,20 @@ JS_FRIEND_DATA(Class) js::OuterWindowPro
     NULL,                    /* call        */
     NULL,                    /* hasInstance */
     NULL,                    /* construct   */
     proxy_TraceObject,       /* trace       */
     {
         NULL,                /* equality    */
         NULL,                /* outerObject */
         proxy_innerObject,
-        NULL                 /* unused */
+        NULL,                /* iteratorObject */
+        NULL,                /* unused */
+        false,               /* isWrappedNative */
+        proxy_WeakmapKeyDelegate
     },
     {
         proxy_LookupGeneric,
         proxy_LookupProperty,
         proxy_LookupElement,
         proxy_LookupSpecial,
         proxy_DefineGeneric,
         proxy_DefineProperty,
@@ -3026,17 +3058,17 @@ JS_FRIEND_DATA(Class) js::FunctionProxyC
     JS_ResolveStub,
     JS_ConvertStub,
     proxy_Finalize,          /* finalize */
     NULL,                    /* checkAccess */
     proxy_Call,
     FunctionClass.hasInstance,
     proxy_Construct,
     proxy_TraceFunction,     /* trace       */
-    JS_NULL_CLASS_EXT,
+    PROXY_CLASS_EXT,
     {
         proxy_LookupGeneric,
         proxy_LookupProperty,
         proxy_LookupElement,
         proxy_LookupSpecial,
         proxy_DefineGeneric,
         proxy_DefineProperty,
         proxy_DefineElement,
--- a/js/src/jsproxy.h
+++ b/js/src/jsproxy.h
@@ -119,16 +119,19 @@ class JS_FRIEND_API(BaseProxyHandler) {
     virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, unsigned indent);
     virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g);
     virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
     virtual bool iteratorNext(JSContext *cx, JSObject *proxy, Value *vp);
     virtual void finalize(JSFreeOp *fop, JSObject *proxy);
     virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver,
                                      uint32_t index, Value *vp, bool *present);
     virtual bool getPrototypeOf(JSContext *cx, JSObject *proxy, JSObject **protop);
+
+    /* See comment for weakmapKeyDelegateOp in jsclass.h. */
+    virtual JSObject *weakmapKeyDelegate(JSObject *proxy);
 };
 
 /*
  * IndirectProxyHandler assumes that a target exists. Moreover, it assumes the
  * target is a JSObject. Consequently, it provides default implementations for
  * the fundamental traps that forward their behavior to the target. The derived
  * traps, however, are inherited from BaseProxyHandler, and therefore still
  * implemented in terms of the fundamental ones. This allows consumers of this
@@ -171,16 +174,17 @@ class JS_PUBLIC_API(IndirectProxyHandler
     virtual JSString *fun_toString(JSContext *cx, JSObject *proxy,
                                    unsigned indent) MOZ_OVERRIDE;
     virtual bool regexp_toShared(JSContext *cx, JSObject *proxy,
                                  RegExpGuard *g) MOZ_OVERRIDE;
     virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint,
                               Value *vp) MOZ_OVERRIDE;
     virtual bool iteratorNext(JSContext *cx, JSObject *proxy,
                               Value *vp) MOZ_OVERRIDE;
+    virtual JSObject *weakmapKeyDelegate(JSObject *proxy);
 };
 
 /*
  * DirectProxyHandler has the same assumptions about the target as its base,
  * IndirectProxyHandler. Its fundamental traps are inherited from this class,
  * and therefore forward their behavior to the target. The derived traps,
  * however, are overrided so that, they too, forward their behavior to the
  * target. This allows consumers of this class to forward to another object as
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -103,24 +103,17 @@ GetObjectMap(JSObject *obj)
 static JSObject *
 GetKeyArg(JSContext *cx, CallArgs &args)
 {
     Value *vp = &args[0];
     if (vp->isPrimitive()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_NONNULL_OBJECT);
         return NULL;
     }
-    JSObject &key = vp->toObject();
-
-    // If the key is from another compartment, and we store the wrapper as the key
-    // the wrapper might be GC-ed since it is not strong referenced (Bug 673468).
-    // To avoid this we always use the unwrapped object as the key instead of its
-    // security wrapper. This also means that if the keys are ever exposed they must
-    // be re-wrapped (see: JS_NondeterministicGetWeakMapKeys).
-    return JS_UnwrapObject(&key);
+    return &vp->toObject();
 }
 
 JS_ALWAYS_INLINE bool
 IsWeakMap(const Value &v)
 {
     return v.isObject() && v.toObject().hasClass(&WeakMapClass);
 }
 
@@ -246,17 +239,17 @@ WeakMap_set_impl(JSContext *cx, CallArgs
             JS_ReportOutOfMemory(cx);
             return false;
         }
         thisObj->setPrivate(map);
     }
 
     // Preserve wrapped native keys to prevent wrapper optimization.
     if (key->getClass()->ext.isWrappedNative) {
-        MOZ_ASSERT(cx->runtime->preserveWrapperCallback, "wrapped native weak map key needs preserveWrapperCallback");
+        JS_ASSERT(cx->runtime->preserveWrapperCallback);
         if (!cx->runtime->preserveWrapperCallback(cx, key)) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_WEAKMAP_KEY);
             return false;
         }
     }
 
     if (!map->put(key, value)) {
         JS_ReportOutOfMemory(cx);
@@ -273,31 +266,30 @@ WeakMap_set(JSContext *cx, unsigned argc
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsWeakMap, WeakMap_set_impl>(cx, args);
 }
 
 JS_FRIEND_API(JSBool)
 JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *obj, JSObject **ret)
 {
+    obj = UnwrapObject(obj);
     if (!obj || !obj->isWeakMap()) {
         *ret = NULL;
         return true;
     }
     RootedObject arr(cx, NewDenseEmptyArray(cx));
     if (!arr)
         return false;
     ObjectValueMap *map = GetObjectMap(obj);
     if (map) {
         for (ObjectValueMap::Base::Range r = map->all(); !r.empty(); r.popFront()) {
             RootedObject key(cx, r.front().key);
-            // Re-wrapping the key (see comment of GetKeyArg)
             if (!JS_WrapObject(cx, key.address()))
                 return false;
-
             if (!js_NewbornArrayPush(cx, arr, ObjectValue(*key)))
                 return false;
         }
     }
     *ret = arr;
     return true;
 }
 
--- a/js/src/jsweakmap.h
+++ b/js/src/jsweakmap.h
@@ -22,52 +22,20 @@ namespace js {
 // a key is collected, the table entry disappears, dropping its reference to the value.
 //
 // More precisely:
 //
 //     A WeakMap entry is collected if and only if either the WeakMap or the entry's key
 //     is collected. If an entry is not collected, it remains in the WeakMap and it has a
 //     strong reference to the value.
 //
-// You must call this table's 'mark' method when the object of which it is a part is
+// You must call this table's 'trace' method when the object of which it is a part is
 // reached by the garbage collection tracer. Once a table is known to be live, the
 // implementation takes care of the iterative marking needed for weak tables and removing
 // table entries when collection is complete.
-//
-// You may provide your own MarkPolicy class to specify how keys and values are marked; a
-// policy template provides default definitions for some common key/value type
-// combinations.
-//
-// Details:
-//
-// The interface is as for a js::HashMap, with the following additions:
-//
-// - You must call the WeakMap's 'trace' member function when you discover that the map is
-//   part of a live object. (You'll typically call this from the containing type's 'trace'
-//   function.)
-//
-// - There is no AllocPolicy parameter; these are used with our garbage collector, so
-//   RuntimeAllocPolicy is hard-wired.
-//
-// - Optional fourth and fifth parameters are the MarkPolicies for the key and value type.
-//   A MarkPolicy has the constructor:
-//
-//     MarkPolicy(JSTracer *)
-//
-//   and the following member functions:
-//
-//     bool isMarked(const Type &x)
-//        Return true if x has been marked as live by the garbage collector.
-//
-//     bool mark(Type &x)
-//        Return false if x is already marked. Otherwise, mark x and return true.
-//
-//   If omitted, the MarkPolicy parameter defaults to js::DefaultMarkPolicy<Type>,
-//   a policy template with the obvious definitions for some typical
-//   SpiderMonkey type combinations.
 
 // The value for the next pointer for maps not in the map list.
 static WeakMapBase * const WeakMapNotInList = reinterpret_cast<WeakMapBase *>(1);
 
 typedef Vector<WeakMapBase *, 0, SystemAllocPolicy> WeakMapVector;
 
 // Common base class for all WeakMap specializations. The collector uses this to call
 // their markIteratively and sweep methods.
@@ -165,26 +133,49 @@ class WeakMap : public HashMap<Key, Valu
         return true;
     }
 
     void nonMarkingTrace(JSTracer *trc) {
         for (Range r = Base::all(); !r.empty(); r.popFront())
             markValue(trc, &r.front().value);
     }
 
+    bool keyNeedsMark(JSObject *key) {
+        if (JSWeakmapKeyDelegateOp op = key->getClass()->ext.weakmapKeyDelegateOp) {
+            JSObject *delegate = op(key);
+            /*
+             * Check if the delegate is marked with any color to properly handle
+             * gray marking when the key's delegate is black and the map is
+             * gray.
+             */
+            return delegate && gc::IsObjectMarked(&delegate);
+        }
+        return false;
+    }
+
+    bool keyNeedsMark(gc::Cell *cell) {
+        return false;
+    }
+
     bool markIteratively(JSTracer *trc) {
         bool markedAny = false;
         for (Enum e(*this); !e.empty(); e.popFront()) {
             /* If the entry is live, ensure its key and value are marked. */
             Key prior(e.front().key);
             if (gc::IsMarked(const_cast<Key *>(&e.front().key))) {
                 if (markValue(trc, &e.front().value))
                     markedAny = true;
                 if (prior != e.front().key)
                     e.rekeyFront(e.front().key);
+            } else if (keyNeedsMark(e.front().key)) {
+                gc::Mark(trc, const_cast<Key *>(&e.front().key), "proxy-preserved WeakMap key");
+                if (prior != e.front().key)
+                    e.rekeyFront(e.front().key);
+                gc::Mark(trc, &e.front().value, "WeakMap entry");
+                markedAny = true;
             }
         }
         return markedAny;
     }
 
     void sweep(JSTracer *trc) {
         /* Remove all entries whose keys remain unmarked. */
         for (Enum e(*this); !e.empty(); e.popFront()) {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2518,16 +2518,23 @@ EvalInFrame(JSContext *cx, unsigned argc
     JSString *str = JSVAL_TO_STRING(argv[1]);
 
     bool saveCurrent = (argc >= 3 && JSVAL_IS_BOOLEAN(argv[2]))
                         ? !!(JSVAL_TO_BOOLEAN(argv[2]))
                         : false;
 
     JS_ASSERT(cx->hasfp());
 
+    /* This is a copy of CheckDebugMode. */
+    if (!JS_GetDebugMode(cx)) {
+        JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
+                                     NULL, JSMSG_NEED_DEBUG_MODE);
+        return false;
+    }
+
     /* Debug-mode currently disables Ion compilation. */
     ScriptFrameIter fi(cx);
     for (uint32_t i = 0; i < upCount; ++i, ++fi) {
         if (!fi.interpFrame()->prev())
             break;
     }
 
     bool saved = false;
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -393,31 +393,32 @@ struct NoteWeakMapChildrenTracer : publi
 {
     NoteWeakMapChildrenTracer(nsCycleCollectionTraversalCallback &cb)
         : mCb(cb)
     {
     }
     nsCycleCollectionTraversalCallback &mCb;
     JSObject *mMap;
     void *mKey;
+    void *mKeyDelegate;
 };
 
 static void
 TraceWeakMappingChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
 {
     MOZ_ASSERT(trc->callback == TraceWeakMappingChild);
     void *thing = *thingp;
     NoteWeakMapChildrenTracer *tracer =
         static_cast<NoteWeakMapChildrenTracer *>(trc);
     if (kind == JSTRACE_STRING)
         return;
     if (!xpc_IsGrayGCThing(thing) && !tracer->mCb.WantAllTraces())
         return;
     if (AddToCCKind(kind)) {
-        tracer->mCb.NoteWeakMapping(tracer->mMap, tracer->mKey, thing);
+        tracer->mCb.NoteWeakMapping(tracer->mMap, tracer->mKey, tracer->mKeyDelegate, thing);
     } else {
         JS_TraceChildren(trc, thing, kind);
     }
 }
 
 struct NoteWeakMapsTracer : public js::WeakMapTracer
 {
     NoteWeakMapsTracer(JSRuntime *rt, js::WeakMapTraceCallback cb,
@@ -450,21 +451,26 @@ TraceWeakMapping(js::WeakMapTracer *trc,
 
     // As an emergency fallback for non-debug builds, if the key is not
     // representable in the cycle collector graph, we treat it as marked.  This
     // can cause leaks, but is preferable to ignoring the binding, which could
     // cause the cycle collector to free live objects.
     if (!AddToCCKind(kkind))
         k = nullptr;
 
+    JSObject *kdelegate = NULL;
+    if (kkind == JSTRACE_OBJECT)
+        kdelegate = js::GetWeakmapKeyDelegate((JSObject *)k);
+
     if (AddToCCKind(vkind)) {
-        tracer->mCb.NoteWeakMapping(m, k, v);
+        tracer->mCb.NoteWeakMapping(m, k, kdelegate, v);
     } else {
         tracer->mChildTracer.mMap = m;
         tracer->mChildTracer.mKey = k;
+        tracer->mChildTracer.mKeyDelegate = kdelegate;
         JS_TraceChildren(&tracer->mChildTracer, v, vkind);
     }
 }
 
 nsresult
 nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb)
 {
     // It is important not to call GetSafeJSContext while on the
--- a/js/xpconnect/tests/chrome/Makefile.in
+++ b/js/xpconnect/tests/chrome/Makefile.in
@@ -57,16 +57,18 @@ MOCHITEST_CHROME_FILES = \
 		test_expandosharing.xul \
 		file_expandosharing.jsm \
 		test_getweakmapkeys.xul \
 		test_mozMatchesSelector.xul \
 		test_nodelists.xul \
 		test_precisegc.xul \
 		test_sandboxImport.xul \
 		test_weakmaps.xul \
+		test_weakmap_keys_preserved.xul \
+		test_weakmap_keys_preserved2.xul \
 		test_weakref.xul \
 		test_wrappers.xul \
 		$(NULL)
 
 # Disabled until this test gets updated to test the new proxy based
 # wrappers.
 #		test_wrappers-2.xul \
 
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_weakmap_keys_preserved.xul
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=673468
+-->
+<window title="Mozilla Bug "
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id="
+     target="_blank">Mozilla Bug 673468</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test for Bug 673468 **/
+
+  let Cc = Components.classes;
+  let Cu = Components.utils;
+  let Ci = Components.interfaces;
+
+  let system = Cc["@mozilla.org/systemprincipal;1"].createInstance();
+  let sandbox = Cu.Sandbox(system);
+  let map = sandbox.WeakMap();
+  let obj = {};
+  map.set(obj, {});
+
+  Cu.forceGC();
+
+  ok(map.has(obj), "Weakmap still contains our wrapper!");
+  ]]>
+  </script>
+</window>
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_weakmap_keys_preserved2.xul
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=673468
+-->
+<window title="Mozilla Bug "
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a id="testelem" href="https://bugzilla.mozilla.org/show_bug.cgi?id="
+     target="_blank">Mozilla Bug 673468</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test for Bug 673468 **/
+
+  let Cc = Components.classes;
+  let Cu = Components.utils;
+  let Ci = Components.interfaces;
+
+  SpecialPowers.DOMWindowUtils.garbageCollect();
+
+  let get_live_dom = function () {
+    return document.getElementById("testelem");
+  };
+
+  let wrappers_as_keys_test = function () {
+    let e = document.createEvent("MessageEvent");
+    e.initMessageEvent("foo", false, false, { dummy: document.createElement("foo") }, null, null, null);
+    window.eeeevent = e;
+
+    let live_dom = e.data.dummy;
+    let dead_dom = document.createElement("div");
+    let dead_child = document.createElement("div");
+    dead_dom.appendChild(dead_child);
+    is(dead_dom.children.length, 1, "children have wrong length");
+    let wrappee = new Object();
+
+    dead_dom.abcxyz = wrappee;
+
+    let system = Cc["@mozilla.org/systemprincipal;1"].createInstance();
+    let sandbox = Cu.Sandbox(system);
+
+    sandbox.wrapper = wrappee;
+    sandbox.value = dead_dom;
+    let map = Cu.evalInSandbox("wm = new WeakMap(); wm.set(wrapper, value); wm", sandbox);
+    sandbox.wrapper = null;
+    sandbox.value = null;
+
+    live_dom.xyzabc = {wrappee: wrappee, m: map, sb: sandbox};
+
+    let key = Cu.nondeterministicGetWeakMapKeys(map)[0];
+    let value = map.get(key);
+    is(value.children.length, 1, "children have wrong length");
+  }
+
+  wrappers_as_keys_test();
+
+  let check_wrappers_as_keys = function () {
+    let live_dom = window.eeeevent.data.dummy;
+    let live_map = live_dom.xyzabc.m;
+    let sandbox = live_dom.xyzabc.sb;
+    is(Cu.nondeterministicGetWeakMapKeys(live_map).length, 1,
+      "Map should not be empty.");
+    let key = Cu.nondeterministicGetWeakMapKeys(live_map)[0];
+    let value = live_map.get(key);
+    is(value.children.length, 1, "children have wrong length");
+  }
+
+  Cu.schedulePreciseGC(function () {
+    SpecialPowers.DOMWindowUtils.cycleCollect();
+    SpecialPowers.DOMWindowUtils.garbageCollect();
+
+    check_wrappers_as_keys();
+  });
+
+  ]]>
+  </script>
+</window>
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -443,17 +443,18 @@ nsDisplayListBuilder::nsDisplayListBuild
       mAllowMergingAndFlattening(true),
       mWillComputePluginGeometry(false),
       mInTransform(false),
       mSyncDecodeImages(false),
       mIsPaintingToWindow(false),
       mHasDisplayPort(false),
       mHasFixedItems(false),
       mIsInFixedPosition(false),
-      mIsCompositingCheap(false)
+      mIsCompositingCheap(false),
+      mContainsPluginItem(false)
 {
   MOZ_COUNT_CTOR(nsDisplayListBuilder);
   PL_InitArenaPool(&mPool, "displayListArena", 1024,
                    NS_MAX(NS_ALIGNMENT_OF(void*),NS_ALIGNMENT_OF(double))-1);
 
   nsPresContext* pc = aReferenceFrame->PresContext();
   nsIPresShell *shell = pc->PresShell();
   if (pc->IsRenderingOnlySelection()) {
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -577,16 +577,19 @@ public:
     } else {
       mGlassDisplayItem = aItem;
     }
   }
   bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem) {
     return aItem == mGlassDisplayItem;
   }
 
+  void SetContainsPluginItem() { mContainsPluginItem = true; }
+  bool ContainsPluginItem() { return mContainsPluginItem; }
+
 private:
   void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
                                     const nsRect& aDirtyRect);
 
   struct PresShellState {
     nsIPresShell* mPresShell;
     nsIFrame*     mCaretFrame;
     uint32_t      mFirstFrameMarkedForDisplay;
@@ -630,16 +633,17 @@ private:
   // under an nsDisplayTransform
   bool                           mInTransform;
   bool                           mSyncDecodeImages;
   bool                           mIsPaintingToWindow;
   bool                           mHasDisplayPort;
   bool                           mHasFixedItems;
   bool                           mIsInFixedPosition;
   bool                           mIsCompositingCheap;
+  bool                           mContainsPluginItem;
 };
 
 class nsDisplayItem;
 class nsDisplayList;
 /**
  * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
  * nsDisplayItemLink holds the link. The lists are linked from lowest to
  * highest in z-order.
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1297,17 +1297,21 @@ nsLayoutUtils::MatrixTransformPoint(cons
   return nsPoint(NSFloatPixelsToAppUnits(float(image.x), aFactor),
                  NSFloatPixelsToAppUnits(float(image.y), aFactor));
 }
 
 gfx3DMatrix
 nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor)
 {
   nsIFrame* parent;
-  gfx3DMatrix ctm = aFrame->GetTransformMatrix(aAncestor, &parent);
+  gfx3DMatrix ctm;
+  if (aFrame == aAncestor) {
+    return ctm;
+  }
+  ctm = aFrame->GetTransformMatrix(aAncestor, &parent);
   while (parent && parent != aAncestor) {
     if (!parent->Preserves3DChildren()) {
       ctm.ProjectTo2D();
     }
     ctm = ctm * parent->GetTransformMatrix(aAncestor, &parent);
   }
   return ctm;
 }
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2539,31 +2539,30 @@ nsRootPresContext::ComputePluginGeometry
   }
 
   // Initially make the next state for each plugin descendant of aFrame be
   // "hidden". Plugins that are visible will have their next state set to
   // unhidden by nsDisplayPlugin::ComputeVisibility.
   mRegisteredPlugins.EnumerateEntries(SetPluginHidden, aFrame);
 
   nsIFrame* rootFrame = FrameManager()->GetRootFrame();
-  if (!rootFrame) {
-    return;
+
+  if (rootFrame && aBuilder->ContainsPluginItem()) {
+    aBuilder->SetForPluginGeometry();
+    aBuilder->SetAccurateVisibleRegions();
+    // Merging and flattening has already been done and we should not do it
+    // again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
+    // again.
+    aBuilder->SetAllowMergingAndFlattening(false);
+    nsRegion region = rootFrame->GetVisualOverflowRectRelativeToSelf();
+    // nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
+    // widget configuration for the plugin, if it's visible.
+    aList->ComputeVisibilityForRoot(aBuilder, &region);
   }
 
-  aBuilder->SetForPluginGeometry();
-  aBuilder->SetAccurateVisibleRegions();
-  // Merging and flattening has already been done and we should not do it
-  // again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
-  // again.
-  aBuilder->SetAllowMergingAndFlattening(false);
-  nsRegion region = rootFrame->GetVisualOverflowRectRelativeToSelf();
-  // nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
-  // widget configuration for the plugin, if it's visible.
-  aList->ComputeVisibilityForRoot(aBuilder, &region);
-
   InitApplyPluginGeometryTimer();
 }
 
 static void
 ApplyPluginGeometryUpdatesCallback(nsITimer *aTimer, void *aClosure)
 {
   static_cast<nsRootPresContext*>(aClosure)->ApplyPluginGeometryUpdates();
 }
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -2993,36 +2993,35 @@ AccumulateFrameBounds(nsIFrame* aContain
                       nsIFrame* aFrame,
                       bool aUseWholeLineHeightForInlines,
                       nsRect& aRect,
                       bool& aHaveRect,
                       nsIFrame*& aPrevBlock,
                       nsAutoLineIterator& aLines,
                       int32_t& aCurLine)
 {
-  nsRect frameBounds = aFrame->GetRect() +
-    aFrame->GetParent()->GetOffsetTo(aContainerFrame);
+  nsIFrame* frame = aFrame;
+  nsRect frameBounds = nsRect(nsPoint(0, 0), aFrame->GetSize());
 
   // If this is an inline frame and either the bounds height is 0 (quirks
   // layout model) or aUseWholeLineHeightForInlines is set, we need to
   // change the top of the bounds to include the whole line.
   if (frameBounds.height == 0 || aUseWholeLineHeightForInlines) {
-    nsIAtom* frameType = NULL;
     nsIFrame *prevFrame = aFrame;
     nsIFrame *f = aFrame;
 
-    while (f &&
-           (frameType = f->GetType()) == nsGkAtoms::inlineFrame) {
+    while (f && f->IsFrameOfType(nsIFrame::eLineParticipant) &&
+           !f->IsTransformed() && !f->IsPositioned()) {
       prevFrame = f;
       f = prevFrame->GetParent();
     }
 
     if (f != aFrame &&
         f &&
-        frameType == nsGkAtoms::blockFrame) {
+        f->GetType() == nsGkAtoms::blockFrame) {
       // find the line containing aFrame and increase the top of |offset|.
       if (f != aPrevBlock) {
         aLines = f->GetLineIterator();
         aPrevBlock = f;
         aCurLine = 0;
       }
       if (aLines) {
         int32_t index = aLines->FindLineContaining(prevFrame, aCurLine);
@@ -3030,35 +3029,39 @@ AccumulateFrameBounds(nsIFrame* aContain
           aCurLine = index;
           nsIFrame *trash1;
           int32_t trash2;
           nsRect lineBounds;
           uint32_t trash3;
 
           if (NS_SUCCEEDED(aLines->GetLine(index, &trash1, &trash2,
                                            lineBounds, &trash3))) {
-            lineBounds += f->GetOffsetTo(aContainerFrame);
+            frameBounds += frame->GetOffsetTo(f);
+            frame = f;
             if (lineBounds.y < frameBounds.y) {
               frameBounds.height = frameBounds.YMost() - lineBounds.y;
               frameBounds.y = lineBounds.y;
             }
           }
         }
       }
     }
   }
 
+  nsRect transformedBounds = nsLayoutUtils::TransformFrameRectToAncestor(frame,
+    frameBounds, aContainerFrame);
+
   if (aHaveRect) {
     // We can't use nsRect::UnionRect since it drops empty rects on
     // the floor, and we need to include them.  (Thus we need
     // aHaveRect to know when to drop the initial value on the floor.)
-    aRect.UnionRectEdges(aRect, frameBounds);
+    aRect.UnionRectEdges(aRect, transformedBounds);
   } else {
     aHaveRect = true;
-    aRect = frameBounds;
+    aRect = transformedBounds;
   }
 }
 
 static bool
 ComputeNeedToScroll(nsIPresShell::WhenToScroll aWhenToScroll,
                     nscoord                    aLineSize,
                     nscoord                    aRectMin,
                     nscoord                    aRectMax,
@@ -3271,18 +3274,20 @@ PresShell::DoScrollContentIntoView()
 
   if (frame->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
     // The reflow flush before this scroll got interrupted, and this frame's
     // coords and size are all zero, and it has no content showing anyway.
     // Don't bother scrolling to it.  We'll try again when we finish up layout.
     return;
   }
 
+  // Make sure we skip 'frame' ... if it's scrollable, we should use its
+  // scrollable ancestor as the container.
   nsIFrame* container =
-    nsLayoutUtils::GetClosestFrameOfType(frame, nsGkAtoms::scrollFrame);
+    nsLayoutUtils::GetClosestFrameOfType(frame->GetParent(), nsGkAtoms::scrollFrame);
   if (!container) {
     // nothing can be scrolled
     return;
   }
 
   ScrollIntoViewData* data = static_cast<ScrollIntoViewData*>(
     mContentToScrollTo->GetProperty(nsGkAtoms::scrolling));
   if (NS_UNLIKELY(!data)) {
@@ -3349,18 +3354,24 @@ PresShell::ScrollFrameRectIntoView(nsIFr
         didScroll = true;
       }
 
       // only scroll one container when this flag is set
       if (aFlags & nsIPresShell::SCROLL_FIRST_ANCESTOR_ONLY) {
         break;
       }
     }
-    rect += container->GetPosition();
-    nsIFrame* parent = container->GetParent();
+    nsIFrame* parent;
+    if (container->IsTransformed()) {
+      container->GetTransformMatrix(nullptr, &parent);
+      rect = nsLayoutUtils::TransformFrameRectToAncestor(container, rect, parent);
+    } else {
+      rect += container->GetPosition();
+      parent = container->GetParent();
+    }
     if (!parent && !(aFlags & nsIPresShell::SCROLL_NO_PARENT_FRAMES)) {
       nsPoint extraOffset(0,0);
       parent = nsLayoutUtils::GetCrossDocParentFrame(container, &extraOffset);
       if (parent) {
         int32_t APD = container->PresContext()->AppUnitsPerDevPixel();        
         int32_t parentAPD = parent->PresContext()->AppUnitsPerDevPixel();
         rect = rect.ConvertAppUnitsRoundOut(APD, parentAPD);
         rect += extraOffset;
--- a/layout/base/tests/test_scroll_selection_into_view.html
+++ b/layout/base/tests/test_scroll_selection_into_view.html
@@ -35,16 +35,39 @@
                <body style='margin:0; overflow:hidden;'>
                  <div style='height:400px;'></div>
                  <div><span id='target4'
                             style='display:inline-block; vertical-align:top; height:300px;'>target4</span>
                  </div>
                  <div style='height:400px;'></div>">
   </iframe>
 </div>
+<div id="c5" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:0;">
+  <div style="-moz-transform:translateY(400px); transform:translateY(400px)">
+    <span id="target5" style="display:inline-block; vertical-align:top; height:20px;">target</span>
+  </div>
+  <div style="height:800px;"></div>
+</div>
+<div id="c6" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:200px;">
+  <div style="height:200px"></div>
+  <div style="height:100px; -moz-transform:scale(2); transform:scale(2)">
+    <span id="target6" style="display:inline-block; vertical-align:top; height:20px;">target</span>
+  </div>
+  <div style="height:800px;"></div>
+</div>
+<div id="c7" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:400px;">
+  <div style="overflow:auto; height:200px; -moz-transform:translateY(400px); transform:translateY(400px)">
+    <div style="height:200px;"></div>
+    <div>
+      <span id="target7" style="display:inline-block; vertical-align:top; height:20px;">target</span>
+    </div>
+    <div style="height:800px;"></div>
+  </div>
+  <div style="height:800px;"></div>
+</div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 var ANCHOR = 0;
 var FOCUS = 1;
 
 function testCollapsed(id, vPercent, startAt, expected) {
@@ -96,16 +119,28 @@ function doTest() {
   testCollapsed("4", 100, 0, 500);
   testCollapsed("4", -1, 0, 400);
   testCollapsed("4", 0, 1000, 400);
   testCollapsed("4", 100, 1000, 500);
   // If the element can't be completely visible, we make the top edge
   // visible.
   testCollapsed("4", -1, 1000, 400);
 
+  // Test that scrolling a translated element into view takes
+  // account of the transform.
+  testCollapsed("5", 0, 0, 400);
+
+  // Test that scrolling a scaled element into view takes
+  // account of the transform.
+  testCollapsed("6", 0, 0, 150);
+
+  // Test that scrolling an element with a translated, scrolling container
+  // into view takes account of the transform.
+  testCollapsed("7", 0, 0, 400);
+
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(doTest);
 </script>
 </pre>
 </body>
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -2047,17 +2047,21 @@ public:
    * Returns a transformation matrix that converts points in this frame's
    * coordinate space to points in some ancestor frame's coordinate space.
    * The frame decides which ancestor it will use as a reference point.
    * If this frame has no ancestor, aOutAncestor will be set to null.
    *
    * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
    *   all ancestors (including across documents) will be traversed.
    * @param aOutAncestor [out] The ancestor frame the frame has chosen.  If
-   *   this frame has no ancestor, *aOutAncestor will be set to null.
+   *   this frame has no ancestor, *aOutAncestor will be set to null. If
+   * this frame is not a root frame, then *aOutAncestor will be in the same
+   * document as this frame. If this frame IsTransformed(), then *aOutAncestor
+   * will be the parent frame (if not preserve-3d) or the nearest non-transformed
+   * ancestor (if preserve-3d).
    * @return A gfxMatrix that converts points in this frame's coordinate space
    *   into points in aOutAncestor's coordinate space.
    */
   gfx3DMatrix GetTransformMatrix(const nsIFrame* aStopAtAncestor,
                                  nsIFrame **aOutAncestor);
 
   /**
    * Bit-flags to pass to IsFrameOfType()
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -115,16 +115,24 @@ public:
     mNextConfigurationClipRegion.Clear();
   }
   /**
    * Append the desired widget configuration to aConfigurations.
    */
   void GetWidgetConfiguration(nsTArray<nsIWidget::Configuration>* aConfigurations)
   {
     if (mWidget) {
+      if (!mWidget->GetParent()) {
+        // Plugin widgets should not be toplevel except when they're out of the
+        // document, in which case the plugin should not be registered for
+        // geometry updates and this should not be called. But apparently we
+        // have bugs where mWidget sometimes is toplevel here. Bail out.
+        NS_ERROR("Plugin widgets registered for geometry updates should not be toplevel");
+        return;
+      }
       nsIWidget::Configuration* configuration = aConfigurations->AppendElement();
       configuration->mChild = mWidget;
       configuration->mBounds = mNextConfigurationBounds;
       configuration->mClipRegion = mNextConfigurationClipRegion;
     }
   }
   /**
    * Called after all widget position/size/clip regions have been changed
@@ -294,16 +302,17 @@ private:
 };
 
 class nsDisplayPlugin : public nsDisplayItem {
 public:
   nsDisplayPlugin(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame)
   {
     MOZ_COUNT_CTOR(nsDisplayPlugin);
+    aBuilder->SetContainsPluginItem();
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayPlugin() {
     MOZ_COUNT_DTOR(nsDisplayPlugin);
   }
 #endif
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
--- a/layout/generic/test/test_bug791616.html
+++ b/layout/generic/test/test_bug791616.html
@@ -30,17 +30,19 @@ var sel = window.getSelection();
 var smoothScrollPref = "general.smoothScroll";
 
 SimpleTest.waitForExplicitFinish();
 SpecialPowers.setBoolPref(smoothScrollPref, false);
 t.scrollTop = 0;
 var targetY = target.getBoundingClientRect().top;
 
 SimpleTest.waitForFocus(function() {
+  is(target.getBoundingClientRect().top, targetY, "Target should not have scrolled due to waitForFocus");
   t.focus();
+  is(target.getBoundingClientRect().top, targetY, "Target should not have scrolled due to focus change");
 
   // Move the caret to scroll it into view
   sel.collapse(target.firstChild, 2);
   synthesizeKey("VK_LEFT", {});
 
   // Delay until next repaint in case stuff is asynchronous. Also
   // take a trip through the event loop.
   setTimeout(function() {
--- a/mobile/android/base/Tabs.java
+++ b/mobile/android/base/Tabs.java
@@ -125,17 +125,17 @@ public class Tabs implements GeckoEventL
     public Tab selectTab(int id) {
         if (!mTabs.containsKey(id))
             return null;
 
         final Tab oldTab = getSelectedTab();
         final Tab tab = mTabs.get(id);
         // This avoids a NPE below, but callers need to be careful to
         // handle this case
-        if (tab == null)
+        if (tab == null || oldTab == tab)
             return null;
 
         mSelectedTab = tab;
         mActivity.runOnUiThread(new Runnable() { 
             public void run() {
                 mActivity.hideFormAssistPopup();
                 if (isSelectedTab(tab)) {
                     String url = tab.getURL();
--- a/mobile/android/base/gfx/BufferedCairoImage.java
+++ b/mobile/android/base/gfx/BufferedCairoImage.java
@@ -3,25 +3,28 @@
  * 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/. */
 
 package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.mozglue.DirectBufferAllocator;
 
 import android.graphics.Bitmap;
+import android.util.Log;
 
 import java.nio.ByteBuffer;
 
 /** A Cairo image that simply saves a buffer of pixel data. */
 public class BufferedCairoImage extends CairoImage {
     private ByteBuffer mBuffer;
     private IntSize mSize;
     private int mFormat;
 
+    private static String LOGTAG = "GeckoBufferedCairoImage";
+
     /** Creates a buffered Cairo image from a byte buffer. */
     public BufferedCairoImage(ByteBuffer inBuffer, int inWidth, int inHeight, int inFormat) {
         setBuffer(inBuffer, inWidth, inHeight, inFormat);
     }
 
     /** Creates a buffered Cairo image from an Android bitmap. */
     public BufferedCairoImage(Bitmap bitmap) {
         setBitmap(bitmap);
@@ -36,16 +39,25 @@ public class BufferedCairoImage extends 
         try {
             freeBuffer();
         } finally {
             super.finalize();
         }
     }
 
     @Override
+    public void destroy() {
+        try {
+            freeBuffer();
+        } catch (Exception ex) {
+            Log.e(LOGTAG, "error clearing buffer: ", ex);
+        }
+    }
+
+    @Override
     public ByteBuffer getBuffer() { return mBuffer; }
     @Override
     public IntSize getSize() { return mSize; }
     @Override
     public int getFormat() { return mFormat; }
 
 
     public void setBuffer(ByteBuffer buffer, int width, int height, int format) {
--- a/mobile/android/base/gfx/CairoImage.java
+++ b/mobile/android/base/gfx/CairoImage.java
@@ -8,16 +8,18 @@ package org.mozilla.gecko.gfx;
 import java.nio.ByteBuffer;
 
 /*
  * A bitmap with pixel data in one of the formats that Cairo understands.
  */
 public abstract class CairoImage {
     public abstract ByteBuffer getBuffer();
 
+    public abstract void destroy();
+
     public abstract IntSize getSize();
     public abstract int getFormat();
 
     public static final int FORMAT_INVALID = -1;
     public static final int FORMAT_ARGB32 = 0;
     public static final int FORMAT_RGB24 = 1;
     public static final int FORMAT_A8 = 2;
     public static final int FORMAT_A1 = 3;
--- a/mobile/android/base/gfx/CheckerboardImage.java
+++ b/mobile/android/base/gfx/CheckerboardImage.java
@@ -3,32 +3,35 @@
  * 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/. */
 
 package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.mozglue.DirectBufferAllocator;
 
 import android.graphics.Color;
+import android.util.Log;
 
 import java.nio.ByteBuffer;
 import java.nio.ShortBuffer;
 import java.util.Arrays;
 
 /** A Cairo image that displays a tinted checkerboard. */
 public class CheckerboardImage extends CairoImage {
     // The width and height of the checkerboard tile.
     private static final int SIZE = 16;
     // The pixel format of the checkerboard tile.
     private static final int FORMAT = CairoImage.FORMAT_RGB16_565;
     // The color to mix in to tint the background color.
     private static final int TINT_COLOR = Color.GRAY;
     // The amount to mix in.
     private static final float TINT_OPACITY = 0.4f;
 
+    private static String LOGTAG = "GeckoCheckerboardImage";
+
     private ByteBuffer mBuffer;
     private int mMainColor;
     private boolean mShowChecks;
 
     /** Creates a new checkerboard image. */
     public CheckerboardImage() {
         int bpp = CairoUtils.bitsPerPixelForCairoFormat(FORMAT);
         mBuffer = DirectBufferAllocator.allocate(SIZE * SIZE * bpp / 8);
@@ -117,16 +120,26 @@ public class CheckerboardImage extends C
             DirectBufferAllocator.free(mBuffer);
             mBuffer = null;
         } finally {
             super.finalize();
         }
     }
 
     @Override
+    public void destroy() {
+        try {
+            DirectBufferAllocator.free(mBuffer);
+            mBuffer = null;
+        } catch (Exception ex) {
+            Log.e(LOGTAG, "error clearing buffer: ", ex);
+        }
+    }
+
+    @Override
     public ByteBuffer getBuffer() {
         return mBuffer;
     }
 
     @Override
     public IntSize getSize() {
         return new IntSize(SIZE, SIZE);
     }
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -492,16 +492,22 @@ public class GeckoLayerClient
             // At this point, we have just switched to displaying a different document than we
             // we previously displaying. This means we need to abort any panning/zooming animations
             // that are in progress and send an updated display port request to browser.js as soon
             // as possible. We accomplish this by passing true to abortPanZoomAnimation, which
             // sends the request after aborting the animation. The display port request is actually
             // a full viewport update, which is fine because if browser.js has somehow moved to
             // be out of sync with this first-paint viewport, then we force them back in sync.
             abortPanZoomAnimation();
+
+            // Indicate that the document is about to be composited so the
+            // LayerView background can be removed.
+            if (mView.getPaintState() == LayerView.PAINT_START) {
+                mView.setPaintState(LayerView.PAINT_BEFORE_FIRST);
+            }
         }
         DisplayPortCalculator.resetPageState();
         mDrawTimingQueue.reset();
         mView.getRenderer().resetCheckerboard();
         ScreenshotHandler.screenshotWholePage(Tabs.getInstance().getSelectedTab());
     }
 
     /** This function is invoked by Gecko via JNI; be careful when modifying signature.
--- a/mobile/android/base/gfx/LayerRenderer.java
+++ b/mobile/android/base/gfx/LayerRenderer.java
@@ -1,16 +1,18 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.Tab;
+import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.gfx.Layer.RenderContext;
 import org.mozilla.gecko.mozglue.DirectBufferAllocator;
 
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -27,17 +29,17 @@ import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.microedition.khronos.egl.EGLConfig;
 
 /**
  * The layer renderer implements the rendering logic for a layer view.
  */
-public class LayerRenderer {
+public class LayerRenderer implements Tabs.OnTabsChangedListener {
     private static final String LOGTAG = "GeckoLayerRenderer";
     private static final String PROFTAG = "GeckoLayerRendererProf";
 
     /*
      * The amount of time a frame is allowed to take to render before we declare it a dropped
      * frame.
      */
     private static final int MAX_FRAME_TIME = 16;   /* 1000 ms / 60 FPS */
@@ -161,29 +163,45 @@ public class LayerRenderer {
         mFrameTimings = new int[60];
         mCurrentFrame = mFrameTimingsSum = mDroppedFrames = 0;
 
         // Initialize the FloatBuffer that will be used to store all vertices and texture
         // coordinates in draw() commands.
         mCoordByteBuffer = DirectBufferAllocator.allocate(COORD_BUFFER_SIZE * 4);
         mCoordByteBuffer.order(ByteOrder.nativeOrder());
         mCoordBuffer = mCoordByteBuffer.asFloatBuffer();
+
+        Tabs.registerOnTabsChangedListener(this);
     }
 
     @Override
     protected void finalize() throws Throwable {
         try {
             DirectBufferAllocator.free(mCoordByteBuffer);
             mCoordByteBuffer = null;
             mCoordBuffer = null;
         } finally {
             super.finalize();
         }
     }
 
+    public void destroy() {
+        DirectBufferAllocator.free(mCoordByteBuffer);
+        mCoordByteBuffer = null;
+        mCoordBuffer = null;
+        mScreenshotLayer.destroy();
+        mBackgroundLayer.destroy();
+        mShadowLayer.destroy();
+        mHorizScrollLayer.destroy();
+        mVertScrollLayer.destroy();
+        if (mFrameRateLayer != null) {
+            mFrameRateLayer.destroy();
+        }
+    }
+
     void onSurfaceCreated(EGLConfig config) {
         checkMonitoringEnabled();
         createDefaultProgram();
         activateDefaultProgram();
     }
 
     public void createDefaultProgram() {
         int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, DEFAULT_VERTEX_SHADER);
@@ -664,20 +682,34 @@ public class LayerRenderer {
                     pixelBuffer.position(0);
                     GLES20.glReadPixels(0, 0, (int)mScreenContext.viewport.width(),
                                         (int)mScreenContext.viewport.height(), GLES20.GL_RGBA,
                                         GLES20.GL_UNSIGNED_BYTE, pixelBuffer);
                     pixelBuffer.notify();
                 }
             }
 
-            // Remove white screen once we've painted
+            // Remove background color once we've painted. GeckoLayerClient is
+            // responsible for setting this flag before current document is
+            // composited.
             if (mView.getPaintState() == LayerView.PAINT_BEFORE_FIRST) {
                 mView.post(new Runnable() {
                     public void run() {
                         mView.getChildAt(0).setBackgroundColor(Color.TRANSPARENT);
                     }
                 });
                 mView.setPaintState(LayerView.PAINT_AFTER_FIRST);
             }
         }
     }
+
+    @Override
+    public void onTabChanged(final Tab tab, Tabs.TabEvents msg, Object data) {
+        // Sets the background of the newly selected tab. This background color
+        // gets cleared in endDrawing(). This function runs on the UI thread,
+        // but other code that touches the paint state is run on the compositor
+        // thread, so this may need to be changed if any problems appear.
+        if (msg == Tabs.TabEvents.SELECTED) {
+            mView.getChildAt(0).setBackgroundColor(tab.getCheckerboardColor());
+            mView.setPaintState(LayerView.PAINT_START);
+        }
+    }
 }
--- a/mobile/android/base/gfx/LayerView.java
+++ b/mobile/android/base/gfx/LayerView.java
@@ -55,18 +55,19 @@ public class LayerView extends FrameLayo
     private boolean mCheckerboardShouldShowChecks;
 
     private SurfaceView mSurfaceView;
     private TextureView mTextureView;
 
     private Listener mListener;
 
     /* Flags used to determine when to show the painted surface. */
-    public static final int PAINT_BEFORE_FIRST = 0;
-    public static final int PAINT_AFTER_FIRST = 1;
+    public static final int PAINT_START = 0;
+    public static final int PAINT_BEFORE_FIRST = 1;
+    public static final int PAINT_AFTER_FIRST = 2;
 
     public boolean shouldUseTextureView() {
         // Disable TextureView support for now as it causes panning/zooming
         // performance regressions (see bug 792259). Uncomment the code below
         // once this bug is fixed.
         return false;
 
         /*
@@ -85,17 +86,17 @@ public class LayerView extends FrameLayo
             return false;
         } */
     }
 
     public LayerView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
         mGLController = new GLController(this);
-        mPaintState = PAINT_BEFORE_FIRST;
+        mPaintState = PAINT_START;
         mCheckerboardColor = Color.WHITE;
         mCheckerboardShouldShowChecks = true;
     }
 
     public void initializeView(EventDispatcher eventDispatcher) {
         mLayerClient = new GeckoLayerClient(getContext(), this, eventDispatcher);
 
         mTouchEventHandler = new TouchEventHandler(getContext(), this, mLayerClient);
@@ -107,16 +108,19 @@ public class LayerView extends FrameLayo
 
         GeckoAccessibility.setDelegate(this);
     }
 
     public void destroy() {
         if (mLayerClient != null) {
             mLayerClient.destroy();
         }
+        if (mRenderer != null) {
+            mRenderer.destroy();
+        }
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN)
             requestFocus();
 
         /** We need to manually hide FormAssistPopup because it is not a regular PopupWindow. */
--- a/mobile/android/base/gfx/ScreenshotLayer.java
+++ b/mobile/android/base/gfx/ScreenshotLayer.java
@@ -110,16 +110,26 @@ public class ScreenshotLayer extends Sin
             try {
                 DirectBufferAllocator.free(mBuffer);
                 mBuffer = null;
             } finally {
                 super.finalize();
             }
         }
 
+        @Override
+        public void destroy() {
+            try {
+                DirectBufferAllocator.free(mBuffer);
+                mBuffer = null;
+            } catch (Exception ex) {
+                Log.e(LOGTAG, "error clearing buffers: ", ex);
+            }
+        }
+
         void copyBuffer(ByteBuffer src, ByteBuffer dst, Rect rect, int stride) {
             int start = (rect.top * stride) + (rect.left * BYTES_FOR_16BPP);
             int end = ((rect.bottom - 1) * stride) + (rect.right * BYTES_FOR_16BPP);
             // clamp stuff just to be safe
             start = Math.max(0, Math.min(dst.limit(), Math.min(src.limit(), start)));
             end = Math.max(start, Math.min(dst.limit(), Math.min(src.capacity(), end)));
             dst.position(start);
             src.position(start).limit(end);
--- a/mobile/android/base/gfx/TileLayer.java
+++ b/mobile/android/base/gfx/TileLayer.java
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
 import android.graphics.Rect;
 import android.opengl.GLES20;
+import android.util.Log;
 
 import java.nio.ByteBuffer;
 
 /**
  * Base class for tile layers, which encapsulate the logic needed to draw textured tiles in OpenGL
  * ES.
  */
 public abstract class TileLayer extends Layer {
@@ -45,16 +46,26 @@ public abstract class TileLayer extends 
         try {
             if (mTextureIDs != null)
                 TextureReaper.get().add(mTextureIDs);
         } finally {
             super.finalize();
         }
     }
 
+    public void destroy() {
+        try {
+            if (mImage != null) {
+                mImage.destroy();
+            }
+        } catch (Exception ex) {
+            Log.e(LOGTAG, "error clearing buffers: ", ex);
+        }
+    }
+
     public void setPaintMode(PaintMode mode) {
         mPaintMode = mode;
     }
 
     /**
      * Invalidates the entire buffer so that it will be uploaded again. Only valid inside a
      * transaction.
      */
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2795,22 +2795,19 @@ Tab.prototype = {
         if (target != this.browser.contentDocument)
           return;
 
         // Sample the background color of the page and pass it along. (This is used to draw the
         // checkerboard.) Right now we don't detect changes in the background color after this
         // event fires; it's not clear that doing so is worth the effort.
         var backgroundColor = null;
         try {
-          let browser = BrowserApp.selectedBrowser;
-          if (browser) {
-            let { contentDocument, contentWindow } = browser;
-            let computedStyle = contentWindow.getComputedStyle(contentDocument.body);
-            backgroundColor = computedStyle.backgroundColor;
-          }
+          let { contentDocument, contentWindow } = this.browser;
+          let computedStyle = contentWindow.getComputedStyle(contentDocument.body);
+          backgroundColor = computedStyle.backgroundColor;
         } catch (e) {
           // Ignore. Catching and ignoring exceptions here ensures that Talos succeeds.
         }
 
         sendMessageToJava({
           gecko: {
             type: "DOMContentLoaded",
             tabID: this.id,
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -73,16 +73,17 @@
 #include "nsISocketProviderService.h"
 #include "nsISocketProvider.h"
 #include "nsIRedirectChannelRegistrar.h"
 #include "nsIMIMEHeaderParam.h"
 #include "nsILoadContext.h"
 #include "mozilla/Services.h"
 #include "nsIPrivateBrowsingChannel.h"
 #include "mozIApplicationClearPrivateDataParams.h"
+#include "nsIOfflineCacheUpdate.h"
 
 #include <limits>
 
 #ifdef MOZILLA_INTERNAL_API
 
 inline already_AddRefed<nsIIOService>
 do_GetIOService(nsresult* error = 0)
 {
@@ -1371,16 +1372,39 @@ NS_GetAppInfoFromClearDataNotification(n
     NS_ENSURE_SUCCESS(rv, rv);
 
     *aAppID = appId;
     *aBrowserOnly = browserOnly;
     return NS_OK;
 }
 
 /**
+ * Determines whether appcache should be checked for a given URI.
+ */
+inline bool
+NS_ShouldCheckAppCache(nsIURI *aURI, bool usePrivateBrowsing)
+{
+    if (usePrivateBrowsing) {
+        return false;
+    }
+
+    nsCOMPtr<nsIOfflineCacheUpdateService> offlineService =
+        do_GetService("@mozilla.org/offlinecacheupdate-service;1");
+    if (!offlineService) {
+        return false;
+    }
+
+    bool allowed;
+    nsresult rv = offlineService->OfflineAppAllowedForURI(aURI,
+                                                          nullptr,
+                                                          &allowed);
+    return NS_SUCCEEDED(rv) && allowed;
+}
+
+/**
  * Wraps an nsIAuthPrompt so that it can be used as an nsIAuthPrompt2. This
  * method is provided mainly for use by other methods in this file.
  *
  * *aAuthPrompt2 should be set to null before calling this function.
  */
 inline void
 NS_WrapAuthPrompt(nsIAuthPrompt *aAuthPrompt, nsIAuthPrompt2** aAuthPrompt2)
 {
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -206,40 +206,34 @@ HttpChannelParent::RecvAsyncOpen(const U
   nsCOMPtr<nsIApplicationCacheChannel> appCacheChan =
     do_QueryInterface(mChannel);
   nsCOMPtr<nsIApplicationCacheService> appCacheService =
     do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
 
   bool setChooseApplicationCache = chooseApplicationCache;
   if (appCacheChan && appCacheService) {
     // We might potentially want to drop this flag (that is TRUE by default)
-    // after we succefully associate the channel with an application cache
+    // after we successfully associate the channel with an application cache
     // reported by the channel child.  Dropping it here may be too early.
     appCacheChan->SetInheritApplicationCache(false);
     if (!appCacheClientID.IsEmpty()) {
       nsCOMPtr<nsIApplicationCache> appCache;
       rv = appCacheService->GetApplicationCache(appCacheClientID,
                                                 getter_AddRefs(appCache));
       if (NS_SUCCEEDED(rv)) {
         appCacheChan->SetApplicationCache(appCache);
         setChooseApplicationCache = false;
       }
     }
 
     if (setChooseApplicationCache) {
-      nsCOMPtr<nsIOfflineCacheUpdateService> offlineUpdateService =
-        do_GetService("@mozilla.org/offlinecacheupdate-service;1", &rv);
-      if (NS_SUCCEEDED(rv)) {
-        rv = offlineUpdateService->OfflineAppAllowedForURI(uri,
-                                                           nullptr,
-                                                           &setChooseApplicationCache);
-
-        if (setChooseApplicationCache && NS_SUCCEEDED(rv))
-          appCacheChan->SetChooseApplicationCache(true);
-      }
+      // This works because we've already called SetNotificationCallbacks and
+      // done mPBOverride logic by this point.
+      appCacheChan->SetChooseApplicationCache(
+            NS_ShouldCheckAppCache(uri, NS_UsePrivateBrowsing(mChannel)));
     }
   }
 
   rv = httpChan->AsyncOpen(channelListener, nullptr);
   if (NS_FAILED(rv))
     return SendFailedAsyncOpen(rv);
 
   return true;
--- a/parser/html/nsHtml5MetaScannerCppSupplement.h
+++ b/parser/html/nsHtml5MetaScannerCppSupplement.h
@@ -51,20 +51,17 @@ nsHtml5MetaScanner::tryCharset(nsString*
   res = nsCharsetAlias::GetPreferred(encoding, preferred);
   if (NS_FAILED(res)) {
     return false;
   }
   if (preferred.LowerCaseEqualsLiteral("utf-16") ||
       preferred.LowerCaseEqualsLiteral("utf-16be") ||
       preferred.LowerCaseEqualsLiteral("utf-16le") ||
       preferred.LowerCaseEqualsLiteral("utf-7") ||
-      preferred.LowerCaseEqualsLiteral("jis_x0212-1990") ||
-      preferred.LowerCaseEqualsLiteral("x-jis0208") ||
-      preferred.LowerCaseEqualsLiteral("x-imap4-modified-utf7") ||
-      preferred.LowerCaseEqualsLiteral("x-user-defined")) {
+      preferred.LowerCaseEqualsLiteral("x-imap4-modified-utf7")) {
     return false;
   }
   res = convManager->GetUnicodeDecoderRaw(preferred.get(), getter_AddRefs(mUnicodeDecoder));
   if (res == NS_ERROR_UCONV_NOCONV) {
     return false;
   } else if (NS_FAILED(res)) {
     NS_ERROR("Getting an encoding decoder failed in a bad way.");
     mUnicodeDecoder = nullptr;
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -1208,20 +1208,17 @@ nsHtml5StreamParser::PreferredForInterna
   // ??? Explicit further blacklist of character sets that are not
   // "rough supersets" of ASCII.  Some of these are handled above (utf-16),
   // some by the XSS smuggling blacklist in charsetData.properties,
   // maybe all of the remainder should also be blacklisted there.
   if (preferred.LowerCaseEqualsLiteral("utf-16") ||
       preferred.LowerCaseEqualsLiteral("utf-16be") ||
       preferred.LowerCaseEqualsLiteral("utf-16le") ||
       preferred.LowerCaseEqualsLiteral("utf-7") ||
-      preferred.LowerCaseEqualsLiteral("jis_x0212-1990") ||
-      preferred.LowerCaseEqualsLiteral("x-jis0208") ||
-      preferred.LowerCaseEqualsLiteral("x-imap4-modified-utf7") ||
-      preferred.LowerCaseEqualsLiteral("x-user-defined")) {
+      preferred.LowerCaseEqualsLiteral("x-imap4-modified-utf7")) {
     // Not a rough ASCII superset
     mTreeBuilder->MaybeComplainAboutCharset("EncMetaNonRoughSuperset",
                                             true,
                                             mTokenizer->getLineNumber());
     return false;
   }
   aEncoding.Assign(preferred);
   return true;
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug599320-1-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset=utf-8>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>UTF-16 doc</title>
+</head>
+<body>
+<h1>UTF-16 doc</h1>
+
+<p>Euro sign: €</p>
+<p>iframe:</p>
+<iframe src=frame599320-1-ref.html width=300 height=400></iframe>
+
+</body>
+</html>
+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..590e9126c3fa1abdde37eca08dd8708c670da3b2
GIT binary patch
literal 616
zc$|HbK~IBF5QOK<uRzXLid7SvmW$S_9`xW*3l@^n5<naOlfO~@-iqYm!4SgE?Ck9B
z<9&TDbfjzD>Pq)|)SXreRj5;?tx^SA3@GG%(oP#K6)7i*;MT^rJdSPPU(n~^P7@u-
zl|<3tmBVB`sz4psx$N=l%(XM819cg30m|Utz-zt}FLO*~NrmfB;<F{&qH<AAU1AgN
zz?I?1Tyh+0`ZeBMoq4#bR1ciQ4Ni$JsLoKXQN$xnV9a=%XOx-VhfR}zyneEQDQlvY
zUYTc)rlre<ndihGq0`pAqx+VeZqx5Gm!I`B&ZVK#(&Nr`$urZbrZ&%s_h0?9o{^v0
b9ms8x!v4pZv8i?RJN@nu|Jgns-Jw9=rVnHN
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/frame599320-1-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset=utf-8>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>Non-UTF-16 doc</title>
+</head>
+<body>
+<h1>Non-UTF-16 doc</h1>
+
+<p>Euro sign: €</p>
+
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/frame599320-1.html
@@ -0,0 +1,1092 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<!-- More than 1 KB of space -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<meta charset=utf-8>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>Non-UTF-16 doc</title>
+</head>
+<body>
+<h1>Non-UTF-16 doc</h1>
+
+<p>Euro sign: €</p>
+<script>
+window.onload = function() {
+  window.mozRequestAnimationFrame(function() {
+    parent.document.documentElement.removeAttribute("class");
+  });
+}
+</script>
+</body>
+</html>
+
--- a/parser/htmlparser/tests/reftest/reftest.list
+++ b/parser/htmlparser/tests/reftest/reftest.list
@@ -1,15 +1,16 @@
 == bug535530-1.html bug535530-1-ref.html
 == view-source:bug535530-2.html bug535530-2-ref.html
 == bug566280-1.html bug566280-1-ref.html
 == bug577418-1.html bug577418-1-ref.html
 == bug582788-1.html bug582788-1-ref.html
 == bug582940-1.html bug582940-1-ref.html
 == bug592656-1.html bug592656-1-ref.html
+== bug599320-1.html bug599320-1-ref.html
 == bug608373-1.html bug608373-1-ref.html
 fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated&&!azureSkia) == view-source:bug482921-1.html bug482921-1-ref.html # bug 703201
 == view-source:bug482921-2.xhtml bug482921-2-ref.html
 == bug659763-1.html bug659763-1-ref.html
 == bug659763-2.html bug659763-2-ref.html
 == bug659763-3.html bug659763-3-ref.html
 == bug659763-4.html bug659763-4-ref.html
 == bug659763-5.html bug659763-5-ref.html
old mode 100644
new mode 100755
old mode 100644
new mode 100755
--- a/testing/xpcshell/Makefile.in
+++ b/testing/xpcshell/Makefile.in
@@ -17,30 +17,32 @@ MODULE		= testing_xpcshell
 TEST_DIRS += example
 
 include $(topsrcdir)/config/rules.mk
 
 # Harness files from the srcdir
 TEST_HARNESS_FILES := \
   runxpcshelltests.py \
   remotexpcshelltests.py \
+  runtestsb2g.py \
   head.js \
   node-spdy \
   moz-spdy \
   $(NULL)
 
 # Extra files needed from $(topsrcdir)/build
 EXTRA_BUILD_FILES := \
   automationutils.py \
   manifestparser.py \
   $(NULL)
 
-# And files for running xpcshell remotely from $(topsrcdir)/build/mobile
-MOBILE_BUILD_FILES := \
+MOZDEVICE_FILES := \
   devicemanager.py \
+  devicemanagerADB.py \
+  devicemanagerSUT.py \
   $(NULL)
 
 # Components / typelibs that don't get packaged with
 # the build, but that we need for the test harness.
 TEST_HARNESS_COMPONENTS := \
   httpd.js \
   httpd.manifest \
   $(NULL)
@@ -61,11 +63,11 @@ check::
 	  -I$(topsrcdir)/build -I$(topsrcdir)/testing/mozbase/mozinfo/mozinfo $(srcdir)/selftest.py
 
 stage-package:
 	$(NSINSTALL) -D $(PKG_STAGE)/xpcshell/tests
 	@(cd $(topsrcdir)/testing/mozbase/mozinfo/mozinfo && tar $(TAR_CREATE_FLAGS) - $(MOZINFO_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -)
 	@(cd $(srcdir) && tar $(TAR_CREATE_FLAGS) - $(TEST_HARNESS_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -)
 	@(cd $(topsrcdir)/build && tar $(TAR_CREATE_FLAGS) - $(EXTRA_BUILD_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -)
 	@cp $(DEPTH)/mozinfo.json $(PKG_STAGE)/xpcshell
-	@(cd $(topsrcdir)/build/mobile && tar $(TAR_CREATE_FLAGS) - $(MOBILE_BUILD_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -)
+	@(cd $(topsrcdir)/testing/mozbase/mozdevice/mozdevice && tar $(TAR_CREATE_FLAGS) - $(MOZDEVICE_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -)
 	(cd $(DEPTH)/_tests/xpcshell/ && tar $(TAR_CREATE_FLAGS_QUIET) - *) | (cd $(PKG_STAGE)/xpcshell/tests && tar -xf -)
 	@(cd $(DIST)/bin/components && tar $(TAR_CREATE_FLAGS) - $(TEST_HARNESS_COMPONENTS)) | (cd $(PKG_STAGE)/bin/components && tar -xf -)
--- a/toolkit/components/social/FrameWorker.jsm
+++ b/toolkit/components/social/FrameWorker.jsm
@@ -64,29 +64,30 @@ function getFrameWorkerHandle(url, clien
  * that has a select set of methods cloned from the URL's domain.
  */
 function FrameWorker(url, name) {
   this.url = url;
   this.name = name || url;
   this.ports = {};
   this.pendingPorts = [];
   this.loaded = false;
+  this.reloading = false;
 
   this.frame = makeHiddenFrame();
   this.load();
 }
 
 FrameWorker.prototype = {
   load: function FrameWorker_loadWorker() {
     var self = this;
     Services.obs.addObserver(function injectController(doc, topic, data) {
       if (!doc.defaultView || doc.defaultView != self.frame.contentWindow) {
         return;
       }
-      Services.obs.removeObserver(injectController, "document-element-inserted", false);
+      Services.obs.removeObserver(injectController, "document-element-inserted");
       try {
         self.createSandbox();
       } catch (e) {
         Cu.reportError("FrameWorker: failed to create sandbox for " + url + ". " + e);
       }
     }, "document-element-inserted", false);
 
     this.frame.setAttribute("src", this.url);
@@ -95,36 +96,44 @@ FrameWorker.prototype = {
   reload: function FrameWorker_reloadWorker() {
     // push all the ports into pending ports, they will be re-entangled
     // during the call to createSandbox after the document is reloaded
     for (let [portid, port] in Iterator(this.ports)) {
       port._window = null;
       this.pendingPorts.push(port);
     }
     this.ports = {};
-    this.loaded = false;
-    this.load();
+    // reset the iframe to about:blank - this will fire the unload event
+    // but not remove the iframe from the DOM.  Our unload handler will
+    // (a) set this.loaded to false then (b) see this.reloading is true and
+    // reload for us.
+    this.reloading = true;
+    this.frame.setAttribute("src", "about:blank");
   },
 
   createSandbox: function createSandbox() {
     let workerWindow = this.frame.contentWindow;
     let sandbox = new Cu.Sandbox(workerWindow);
 
     // copy the window apis onto the sandbox namespace only functions or
     // objects that are naturally a part of an iframe, I'm assuming they are
     // safe to import this way
     let workerAPI = ['WebSocket', 'localStorage', 'atob', 'btoa',
                      'clearInterval', 'clearTimeout', 'dump',
                      'setInterval', 'setTimeout', 'XMLHttpRequest',
                      'MozBlobBuilder', 'FileReader', 'Blob',
                      'location'];
     workerAPI.forEach(function(fn) {
       try {
-        // XXX Need to unwrap for this to work - find out why!
-        sandbox[fn] = XPCNativeWrapper.unwrap(workerWindow)[fn];
+        // Bug 798660 - XHR and WebSocket have issues in a sandbox and need
+        // to be unwrapped to work
+        if (fn == "XMLHttpRequest" || fn == "WebSocket")
+          sandbox[fn] = XPCNativeWrapper.unwrap(workerWindow)[fn];
+        else
+          sandbox[fn] = workerWindow[fn];
       }
       catch(e) {
         Cu.reportError("FrameWorker: failed to import API "+fn+"\n"+e+"\n");
       }
     });
     // the "navigator" object in a worker is a subset of the full navigator;
     // specifically, just the interfaces 'NavigatorID' and 'NavigatorOnLine'
     let navigator = {
@@ -163,18 +172,19 @@ FrameWorker.prototype = {
 
     sandbox._postMessage = function fw_postMessage(d, o) {
       workerWindow.postMessage(d, o)
     };
     sandbox._addEventListener = function fw_addEventListener(t, l, c) {
       workerWindow.addEventListener(t, l, c)
     };
 
-    this.sandbox = sandbox;
-
+    // Note we don't need to stash |sandbox| in |this| as the unload handler
+    // has a reference in its closure, so it can't die until that handler is
+    // removed - at which time we've explicitly killed it anyway.
     let worker = this;
 
     workerWindow.addEventListener("load", function loadListener() {
       workerWindow.removeEventListener("load", loadListener);
       // the iframe has loaded the js file as text - first inject the magic
       // port-handling code into the sandbox.
       try {
         Services.scriptloader.loadSubScript("resource://gre/modules/MessagePortBase.jsm", sandbox);
@@ -214,34 +224,75 @@ FrameWorker.prototype = {
             port._createWorkerAndEntangle(worker);
           }
           catch(e) {
             Cu.reportError("FrameWorker: Failed to create worker port: " + e + "\n" + e.stack);
           }
         }
       }
     });
+
+    // the 'unload' listener cleans up the worker and the sandbox.  This
+    // will be triggered via either our 'terminate' function or by the
+    // window unloading as part of shutdown.
+    workerWindow.addEventListener("unload", function unloadListener() {
+      workerWindow.removeEventListener("unload", unloadListener);
+      delete workerCache[worker.url];
+      // closing the port also removes it from this.ports via port-close
+      for (let [portid, port] in Iterator(worker.ports)) {
+        // port may have been closed as a side-effect from closing another port
+        if (!port)
+          continue;
+        try {
+          port.close();
+        } catch (ex) {
+          Cu.reportError("FrameWorker: failed to close port. " + ex);
+        }
+      }
+      // Must reset this to an array incase we are being reloaded.
+      worker.ports = [];
+      // The worker window may not have fired a load event yet, so pendingPorts
+      // might still have items in it - close them too.
+      worker.loaded = false;
+      // If the worker is reloading, when we don't actually close the pending
+      // ports as they are the ports which need to be re-entangled.
+      if (!worker.reloading) {
+        for (let port of worker.pendingPorts) {
+          try {
+            port.close();
+          } catch (ex) {
+            Cu.reportError("FrameWorker: failed to close pending port. " + ex);
+          }
+        }
+        worker.pendingPorts = [];
+      }
+
+      if (sandbox) {
+        Cu.nukeSandbox(sandbox);
+        sandbox = null;
+      }
+      if (worker.reloading) {
+        Services.tm.mainThread.dispatch(function doReload() {
+          worker.reloading = false;
+          worker.load();
+        }, Ci.nsIThread.DISPATCH_NORMAL);
+      }
+    });
   },
 
   terminate: function terminate() {
-    // closing the port also removes it from this.ports via port-close
-    for (let [portid, port] in Iterator(this.ports)) {
-      // port may have been closed as a side-effect from closing another port
-      if (!port)
-        continue;
-      try {
-        port.close();
-      } catch (ex) {
-        Cu.reportError("FrameWorker: failed to close port. " + ex);
-      }
+    if (!(this.url in workerCache)) {
+      // terminating an already terminated worker - ignore it
+      return;
     }
-
+    // we want to "forget" about this worker now even though the termination
+    // may not be complete for a little while...
     delete workerCache[this.url];
-
-    // let pending events get delivered before actually removing the frame
+    // let pending events get delivered before actually removing the frame,
+    // then we perform the actual cleanup in the unload handler.
     Services.tm.mainThread.dispatch(function deleteWorkerFrame() {
       // now nuke the iframe itself and forget everything about this worker.
       this.frame.parentNode.removeChild(this.frame);
     }.bind(this), Ci.nsIThread.DISPATCH_NORMAL);
   }
 };
 
 function makeHiddenFrame() {
--- a/toolkit/components/social/MessagePortBase.jsm
+++ b/toolkit/components/social/MessagePortBase.jsm
@@ -39,20 +39,20 @@ AbstractPort.prototype = {
   },
 
   _onmessage: function fw_AbstractPort_onmessage(data) {
     // See comments in postMessage below - we work around a cloning
     // issue by using JSON for these messages.
     // Further, we allow the workers to override exactly how the JSON parsing
     // is done - we try and do such parsing in the client window so things
     // like prototype overrides on Array work as expected.
-    data = this._JSONParse(data);
     if (!this._handler) {
       this._pendingMessagesIncoming.push(data);
     } else {
+      data = this._JSONParse(data);
       try {
         this._handler({
           data: data,
           __exposedProps__: {
             data: 'r'
           }
         });
       } catch (ex) {
--- a/toolkit/components/social/WorkerAPI.jsm
+++ b/toolkit/components/social/WorkerAPI.jsm
@@ -58,18 +58,17 @@ WorkerAPI.prototype = {
     },
     "social.user-profile": function (data) {
       this._provider.updateUserProfile(data);
     },
     "social.ambient-notification": function (data) {
       this._provider.setAmbientNotification(data);
     },
     "social.cookies-get": function(data) {
-      let document = getFrameWorkerHandle(this._provider.workerURL, null).
-                        _worker.frame.contentDocument;
+      let document = this._port._window.document;
       let cookies = document.cookie.split(";");
       let results = [];
       cookies.forEach(function(aCookie) {
         let [name, value] = aCookie.split("=");
         results.push({name: unescape(name.trim()),
                       value: unescape(value.trim())});
       });
       this._port.postMessage({topic: "social.cookies-get-response",
--- a/toolkit/components/social/test/browser/browser_workerAPI.js
+++ b/toolkit/components/social/test/browser/browser_workerAPI.js
@@ -109,36 +109,39 @@ let tests = {
     Cu.import("resource://gre/modules/FrameWorker.jsm", fw);
 
     // get a real handle to the worker so we can watch the unload event
     // we watch for the unload of the worker to know it is infact being
     // unloaded, after that if we get worker.connected we know that
     // the worker was loaded again and ports reconnected
     let reloading = false;
     let worker = fw.getFrameWorkerHandle(provider.workerURL, undefined, "testWorkerReload");
-    let win = worker._worker.frame.contentWindow;
+    let frame =  worker._worker.frame;
+    let win = frame.contentWindow;
+    let port = provider.getWorkerPort();
     win.addEventListener("unload", function workerUnload(e) {
       win.removeEventListener("unload", workerUnload);
       ok(true, "worker unload event has fired");
-      reloading = true;
+      is(port._pendingMessagesOutgoing.length, 0, "port has no pending outgoing message");
     });
-    let port = provider.getWorkerPort();
+    frame.addEventListener("DOMWindowCreated", function workerLoaded(e) {
+      frame.removeEventListener("DOMWindowCreated", workerLoaded);
+      // send a message which should end up pending
+      port.postMessage({topic: "test-pending-msg"});
+      ok(port._pendingMessagesOutgoing.length > 0, "port has pending outgoing message");
+    });
     ok(port, "provider has a port");
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "test-initialization-complete":
           // tell the worker to send the reload msg
           port.postMessage({topic: "test-reload-init"});
           break;
-        case "worker.connected":
-          // we'll get this message from the worker on every load of the worker,
-          // so we need to ignore it unless we have requested the reload.
-          if (reloading) {
-            ok(true, "worker reloaded and testPort was reconnected");
-            next();
-          }
+        case "test-pending-response":
+          ok(true, "worker reloaded and testPort was reconnected");
+          next();
           break;
       }
     }
     port.postMessage({topic: "test-initialization"});
   }
 };
--- a/toolkit/components/social/test/browser/worker_relative.js
+++ b/toolkit/components/social/test/browser/worker_relative.js
@@ -5,14 +5,15 @@ onconnect = function(e) {
   try {
     importScripts("relative_import.js");
     // the import should have exposed "testVar" and "testFunc" from the module.
     if (testVar == "oh hai" && testFunc() == "oh hai") {
       port.postMessage({topic: "done", result: "ok"});
     } else {
       port.postMessage({topic: "done", result: "import worked but global is not available"});
     }
+    return;
   } catch(e) {
     port.postMessage({topic: "done", result: "FAILED to importScripts, " + e.toString() });
     return;
   }
   port.postMessage({topic: "done", result: "FAILED to importScripts, no exception" });
 }
--- a/toolkit/components/social/test/browser/worker_social.js
+++ b/toolkit/components/social/test/browser/worker_social.js
@@ -20,16 +20,19 @@ onconnect = function(e) {
         break;
       case "test-initialization":
         testerPort = port;
         port.postMessage({topic: "test-initialization-complete"});
         break;
       case "test-profile":
         apiPort.postMessage({topic: "social.user-profile", data: data});
         break;
+      case "test-pending-msg":
+        port.postMessage({topic: "test-pending-response"})
+        break;
       case "test-ambient":
         apiPort.postMessage({topic: "social.ambient-notification", data: data});
         break;
       case "test.cookies-get":
         apiPort.postMessage({topic: "social.cookies-get"});
         break;
       case "social.cookies-get-response":
         testerPort.postMessage({topic: "test.cookies-get-response", data: data});
--- a/toolkit/components/url-classifier/nsUrlClassifierProxies.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierProxies.cpp
@@ -233,22 +233,28 @@ UrlClassifierUpdateObserverProxy::Update
 {
   mTarget->UpdateUrlRequested(mURL, mTable, mServerMAC);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 UrlClassifierUpdateObserverProxy::RekeyRequested()
 {
-  nsCOMPtr<nsIRunnable> r =
-    NS_NewRunnableMethod(mTarget, &nsIUrlClassifierUpdateObserver::RekeyRequested);
+  nsCOMPtr<nsIRunnable> r = new RekeyRequestedRunnable(mTarget);
   return NS_DispatchToMainThread(r);
 }
 
 NS_IMETHODIMP
+UrlClassifierUpdateObserverProxy::RekeyRequestedRunnable::Run()
+{
+  mTarget->RekeyRequested();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 UrlClassifierUpdateObserverProxy::StreamFinished(nsresult aStatus,
                                                  uint32_t aDelay)
 {
   nsCOMPtr<nsIRunnable> r =
     new StreamFinishedRunnable(mTarget, aStatus, aDelay);
   return NS_DispatchToMainThread(r);
 }
 
--- a/toolkit/components/url-classifier/nsUrlClassifierProxies.h
+++ b/toolkit/components/url-classifier/nsUrlClassifierProxies.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsUrlClassifierProxies_h
 #define nsUrlClassifierProxies_h
 
 #include "nsIUrlClassifierDBService.h"
+#include "nsProxyRelease.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Attributes.h"
 #include "nsIPrincipal.h"
 #include "LookupCache.h"
 
 using namespace mozilla::safebrowsing;
 
 /**
@@ -157,150 +158,163 @@ private:
 
 // The remaining classes here are all proxies to the main thread
 
 class UrlClassifierLookupCallbackProxy MOZ_FINAL :
   public nsIUrlClassifierLookupCallback
 {
 public:
   UrlClassifierLookupCallbackProxy(nsIUrlClassifierLookupCallback* aTarget)
-    : mTarget(aTarget)
+    : mTarget(new nsMainThreadPtrHolder<nsIUrlClassifierLookupCallback>(aTarget))
   { }
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIURLCLASSIFIERLOOKUPCALLBACK
 
   class LookupCompleteRunnable : public nsRunnable
   {
   public:
-    LookupCompleteRunnable(nsIUrlClassifierLookupCallback* aTarget,
+    LookupCompleteRunnable(nsMainThreadPtrHolder<nsIUrlClassifierLookupCallback>* aTarget,
                            LookupResultArray *aResults)
       : mTarget(aTarget)
       , mResults(aResults)
     { }
 
     NS_DECL_NSIRUNNABLE
 
   private:
-    nsCOMPtr<nsIUrlClassifierLookupCallback> mTarget;
+    nsMainThreadPtrHandle<nsIUrlClassifierLookupCallback> mTarget;
     LookupResultArray * mResults;
   };
 
 private:
-  nsCOMPtr<nsIUrlClassifierLookupCallback> mTarget;
+  nsMainThreadPtrHandle<nsIUrlClassifierLookupCallback> mTarget;
 };
 
 class UrlClassifierCallbackProxy MOZ_FINAL : public nsIUrlClassifierCallback
 {
 public:
   UrlClassifierCallbackProxy(nsIUrlClassifierCallback* aTarget)
-    : mTarget(aTarget)
+    : mTarget(new nsMainThreadPtrHolder<nsIUrlClassifierCallback>(aTarget))
   { }
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIURLCLASSIFIERCALLBACK
 
   class HandleEventRunnable : public nsRunnable
   {
   public:
-    HandleEventRunnable(nsIUrlClassifierCallback* aTarget,
+    HandleEventRunnable(nsMainThreadPtrHolder<nsIUrlClassifierCallback>* aTarget,
                         const nsACString& aValue)
       : mTarget(aTarget)
       , mValue(aValue)
     { }
 
     NS_DECL_NSIRUNNABLE
 
   private:
-    nsCOMPtr<nsIUrlClassifierCallback> mTarget;
+    nsMainThreadPtrHandle<nsIUrlClassifierCallback> mTarget;
     nsCString mValue;
   };
 
 private:
-  nsCOMPtr<nsIUrlClassifierCallback> mTarget;
+  nsMainThreadPtrHandle<nsIUrlClassifierCallback> mTarget;
 };
 
 class UrlClassifierUpdateObserverProxy MOZ_FINAL :
   public nsIUrlClassifierUpdateObserver
 {
 public:
   UrlClassifierUpdateObserverProxy(nsIUrlClassifierUpdateObserver* aTarget)
-    : mTarget(aTarget)
+    : mTarget(new nsMainThreadPtrHolder<nsIUrlClassifierUpdateObserver>(aTarget))
   { }
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIURLCLASSIFIERUPDATEOBSERVER
 
   class UpdateUrlRequestedRunnable : public nsRunnable
   {
   public:
-    UpdateUrlRequestedRunnable(nsIUrlClassifierUpdateObserver* aTarget,
+    UpdateUrlRequestedRunnable(nsMainThreadPtrHolder<nsIUrlClassifierUpdateObserver>* aTarget,
                                const nsACString& aURL,
                                const nsACString& aTable,
                                const nsACString& aServerMAC)
       : mTarget(aTarget)
       , mURL(aURL)
       , mTable(aTable)
       , mServerMAC(aServerMAC)
     { }
 
     NS_DECL_NSIRUNNABLE
 
   private:
-    nsCOMPtr<nsIUrlClassifierUpdateObserver> mTarget;
+    nsMainThreadPtrHandle<nsIUrlClassifierUpdateObserver> mTarget;
     nsCString mURL, mTable, mServerMAC;
   };
 
+  class RekeyRequestedRunnable : public nsRunnable
+  {
+  public:
+    RekeyRequestedRunnable(nsMainThreadPtrHolder<nsIUrlClassifierUpdateObserver>* aTarget)
+      : mTarget(aTarget)
+    { }
+
+    NS_DECL_NSIRUNNABLE
+
+  private:
+    nsMainThreadPtrHandle<nsIUrlClassifierUpdateObserver> mTarget;
+  };
+
   class StreamFinishedRunnable : public nsRunnable
   {
   public:
-    StreamFinishedRunnable(nsIUrlClassifierUpdateObserver* aTarget,
+    StreamFinishedRunnable(nsMainThreadPtrHolder<nsIUrlClassifierUpdateObserver>* aTarget,
                            nsresult aStatus, uint32_t aDelay)
       : mTarget(aTarget)
       , mStatus(aStatus)
       , mDelay(aDelay)
     { }
 
     NS_DECL_NSIRUNNABLE
 
   private:
-    nsCOMPtr<nsIUrlClassifierUpdateObserver> mTarget;
+    nsMainThreadPtrHandle<nsIUrlClassifierUpdateObserver> mTarget;
     nsresult mStatus;
     uint32_t mDelay;
   };
 
   class UpdateErrorRunnable : public nsRunnable
   {
   public:
-    UpdateErrorRunnable(nsIUrlClassifierUpdateObserver* aTarget,
+    UpdateErrorRunnable(nsMainThreadPtrHolder<nsIUrlClassifierUpdateObserver>* aTarget,
                         nsresult aError)
       : mTarget(aTarget)
       , mError(aError)
     { }
 
     NS_DECL_NSIRUNNABLE
 
   private:
-    nsCOMPtr<nsIUrlClassifierUpdateObserver> mTarget;
+    nsMainThreadPtrHandle<nsIUrlClassifierUpdateObserver> mTarget;
     nsresult mError;
   };
 
   class UpdateSuccessRunnable : public nsRunnable
   {
   public:
-    UpdateSuccessRunnable(nsIUrlClassifierUpdateObserver* aTarget,
+    UpdateSuccessRunnable(nsMainThreadPtrHolder<nsIUrlClassifierUpdateObserver>* aTarget,
                           uint32_t aRequestedTimeout)
       : mTarget(aTarget)
       , mRequestedTimeout(aRequestedTimeout)
     { }
 
     NS_DECL_NSIRUNNABLE
 
   private:
-    nsCOMPtr<nsIUrlClassifierUpdateObserver> mTarget;
+    nsMainThreadPtrHandle<nsIUrlClassifierUpdateObserver> mTarget;
     uint32_t mRequestedTimeout;
   };
 
 private:
-  nsCOMPtr<nsIUrlClassifierUpdateObserver> mTarget;
+  nsMainThreadPtrHandle<nsIUrlClassifierUpdateObserver> mTarget;
 };
 
 #endif // nsUrlClassifierProxies_h
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -328,16 +328,21 @@ endif
 COMPONENT_LIBS += services-crypto
 
 ifdef MOZ_DEBUG
 ifdef ENABLE_TESTS
 COMPONENT_LIBS += gkdebug
 endif
 endif
 
+ifdef MOZ_GIO_COMPONENT
+DEFINES += -DMOZ_GIO_COMPONENT
+COMPONENT_LIBS += nkgio
+endif
+
 ifdef MOZ_APP_COMPONENT_LIBS
 COMPONENT_LIBS += $(MOZ_APP_COMPONENT_LIBS)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 OS_LIBS += -framework OpenGL -lcups
 endif
 
--- a/toolkit/library/nsStaticXULComponents.cpp
+++ b/toolkit/library/nsStaticXULComponents.cpp
@@ -165,16 +165,22 @@
 #endif
 
 #if defined(MOZ_WEBRTC)
 #define PEERCONNECTION_MODULE MODULE(peerconnection)
 #else
 #define PEERCONNECTION_MODULE
 #endif
 
+#if defined(MOZ_GIO_COMPONENT)
+#define GIO_MODULE MODULE(nsGIOModule)
+#else
+#define GIO_MODULE
+#endif
+
 #define XUL_MODULES                          \
     MODULE(nsUConvModule)                    \
     MODULE(nsI18nModule)                     \
     MODULE(nsChardetModule)                  \
     UNIVERSALCHARDET_MODULE                  \
     MODULE(necko)                            \
     PERMISSIONS_MODULES                      \
     AUTH_MODULE                              \
@@ -223,16 +229,17 @@
     MODULE(jsperf)                           \
     MODULE(identity)                         \
     MODULE(nsServicesCryptoModule)           \
     MOZ_APP_COMPONENT_MODULES                \
     MODULE(nsTelemetryModule)                \
     MODULE(jsinspector)                      \
     MODULE(jsdebugger)                       \
     PEERCONNECTION_MODULE                    \
+    GIO_MODULE                               \
     /* end of list */
 
 #define MODULE(_name) \
   NSMODULE_DECL(_name);
 
 XUL_MODULES
 
 #undef MODULE
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -247,16 +247,20 @@ endif
 tier_platform_dirs += services/crypto/component
 
 tier_platform_dirs += startupcache
 
 tier_platform_dirs += js/ductwork/debugger
 
 tier_platform_dirs += other-licenses/snappy
 
+ifdef MOZ_GIO_COMPONENT
+tier_platform_dirs += extensions/gio
+endif
+
 ifdef APP_LIBXUL_STATICDIRS
 # Applications can cheat and ask for code to be
 # built before libxul so libxul can be linked against it.
 tier_platform_staticdirs += $(APP_LIBXUL_STATICDIRS)
 endif
 ifdef APP_LIBXUL_DIRS
 # Applications can cheat and ask for code to be
 # built before libxul so it can be linked into libxul.
--- a/toolkit/xre/Makefile.in
+++ b/toolkit/xre/Makefile.in
@@ -240,17 +240,17 @@ GRE_BUILDID   := $(strip $(firstword $(s
 DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) -DGRE_BUILDID=$(GRE_BUILDID)
 
 ifdef MOZILLA_OFFICIAL
 DEFINES += -DMOZILLA_OFFICIAL
 endif
 
 DEFINES += -DAPP_VERSION=$(MOZ_APP_VERSION)
 
-DEFINES += -DAPP_ID=$(MOZ_APP_ID)
+DEFINES += -DAPP_ID="$(MOZ_APP_ID)"
 
 $(srcdir)/nsAppRunner.cpp: $(DEPTH)/config/buildid $(milestone_txt)
 
 platform.ini: FORCE
 	$(PYTHON) $(srcdir)/make-platformini.py --buildid=$(GRE_BUILDID) $(INIARGS) $(milestone_txt) > $@
 
 GARBAGE += platform.ini
 
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -664,16 +664,17 @@ private:
 };
 
 
 struct WeakMapping
 {
     // map and key will be null if the corresponding objects are GC marked
     PtrInfo *mMap;
     PtrInfo *mKey;
+    PtrInfo *mKeyDelegate;
     PtrInfo *mVal;
 };
 
 class GCGraphBuilder;
 
 struct GCGraph
 {
     NodePool mNodes;
@@ -1673,17 +1674,17 @@ public:
     NS_IMETHOD_(void) NoteNativeRoot(void *root, nsCycleCollectionParticipant *participant);
 
     NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child);
     NS_IMETHOD_(void) NoteJSChild(void *child);
     NS_IMETHOD_(void) NoteNativeChild(void *child,
                                       nsCycleCollectionParticipant *participant);
 
     NS_IMETHOD_(void) NoteNextEdgeName(const char* name);
-    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val);
+    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *kdelegate, void *val);
 
 private:
     NS_IMETHOD_(void) NoteRoot(void *root,
                                nsCycleCollectionParticipant *participant)
     {
         MOZ_ASSERT(root);
         MOZ_ASSERT(participant);
 
@@ -1963,26 +1964,27 @@ GCGraphBuilder::AddWeakMapNode(void *nod
     if (JSCompartment *comp = MergeCompartment(node)) {
         return AddNode(comp, mJSCompParticipant);
     } else {
         return AddNode(node, mJSParticipant);
     }
 }
 
 NS_IMETHODIMP_(void)
-GCGraphBuilder::NoteWeakMapping(void *map, void *key, void *val)
+GCGraphBuilder::NoteWeakMapping(void *map, void *key, void *kdelegate, void *val)
 {
     PtrInfo *valNode = AddWeakMapNode(val);
 
     if (!valNode)
         return;
 
     WeakMapping *mapping = mWeakMaps.AppendElement();
     mapping->mMap = map ? AddWeakMapNode(map) : nullptr;
     mapping->mKey = key ? AddWeakMapNode(key) : nullptr;
+    mapping->mKeyDelegate = kdelegate ? AddWeakMapNode(kdelegate) : mapping->mKey;
     mapping->mVal = valNode;
 }
 
 static bool
 AddPurpleRoot(GCGraphBuilder &builder, void *root, nsCycleCollectionParticipant *cp)
 {
     CanonicalizeParticipant(&root, &cp);
 
@@ -2016,17 +2018,17 @@ public:
                                              const char *objname) {}
     NS_IMETHOD_(void) DescribeGCedNode(bool ismarked,
                                        const char *objname) {}
     NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root) {}
     NS_IMETHOD_(void) NoteJSRoot(void *root) {}
     NS_IMETHOD_(void) NoteNativeRoot(void *root,
                                      nsCycleCollectionParticipant *helper) {}
     NS_IMETHOD_(void) NoteNextEdgeName(const char* name) {}
-    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) {}
+    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *kdelegate, void *val) {}
     bool MayHaveChild() {
         return mMayHaveChild;
     }
 private:
     bool mMayHaveChild;
 };
 
 NS_IMETHODIMP_(void)
@@ -2201,25 +2203,32 @@ nsCycleCollector::ScanWeakMaps()
     do {
         anyChanged = false;
         for (uint32_t i = 0; i < mGraph.mWeakMaps.Length(); i++) {
             WeakMapping *wm = &mGraph.mWeakMaps[i];
 
             // If mMap or mKey are null, the original object was marked black.
             uint32_t mColor = wm->mMap ? wm->mMap->mColor : black;
             uint32_t kColor = wm->mKey ? wm->mKey->mColor : black;
+            uint32_t kdColor = wm->mKeyDelegate ? wm->mKeyDelegate->mColor : black;
             PtrInfo *v = wm->mVal;
 
             // All non-null weak mapping maps, keys and values are
             // roots (in the sense of WalkFromRoots) in the cycle
             // collector graph, and thus should have been colored
             // either black or white in ScanRoots().
-            NS_ASSERTION(mColor != grey, "Uncolored weak map");
-            NS_ASSERTION(kColor != grey, "Uncolored weak map key");
-            NS_ASSERTION(v->mColor != grey, "Uncolored weak map value");
+            MOZ_ASSERT(mColor != grey, "Uncolored weak map");
+            MOZ_ASSERT(kColor != grey, "Uncolored weak map key");
+            MOZ_ASSERT(kdColor != grey, "Uncolored weak map key delegate");
+            MOZ_ASSERT(v->mColor != grey, "Uncolored weak map value");
+
+            if (mColor == black && kColor != black && kdColor == black) {
+                GraphWalker<ScanBlackVisitor>(ScanBlackVisitor(mWhiteNodeCount)).Walk(wm->mKey);
+                anyChanged = true;
+            }
 
             if (mColor == black && kColor == black && v->mColor != black) {
                 GraphWalker<ScanBlackVisitor>(ScanBlackVisitor(mWhiteNodeCount)).Walk(v);
                 anyChanged = true;
             }
         }
     } while (anyChanged);
 }
@@ -2466,17 +2475,17 @@ public:
     NS_IMETHOD_(void) NoteJSRoot(void *root) {}
     NS_IMETHOD_(void) NoteNativeRoot(void *root,
                                      nsCycleCollectionParticipant *participant) {}
     NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child) {}
     NS_IMETHOD_(void) NoteJSChild(void *child) {}
     NS_IMETHOD_(void) NoteNativeChild(void *child,
                                      nsCycleCollectionParticipant *participant) {}
     NS_IMETHOD_(void) NoteNextEdgeName(const char* name) {}
-    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) {}
+    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *kdelegate, void *val) {}
 };
 
 char *Suppressor::sSuppressionList = nullptr;
 bool Suppressor::sInitialized = false;
 
 static bool
 nsCycleCollector_shouldSuppress(nsISupports *s)
 {
--- a/xpcom/base/nsError.h
+++ b/xpcom/base/nsError.h
@@ -141,30 +141,29 @@
 #endif
 
 #undef SUCCESS_OR_FAILURE
 #undef SUCCESS
 #undef FAILURE
 
 /**
  * @name Standard Error Handling Macros
- * @return 0 or 1
+ * @return 0 or 1 (false/true with bool type for C++)
  */
 
 #ifdef __cplusplus
-inline int NS_FAILED(nsresult _nsresult) {
+inline uint32_t NS_FAILED_impl(nsresult _nsresult) {
   return static_cast<uint32_t>(_nsresult) & 0x80000000;
 }
-
-inline int NS_SUCCEEDED(nsresult _nsresult) {
-  return !(static_cast<uint32_t>(_nsresult) & 0x80000000);
-}
+#define NS_FAILED(_nsresult)    ((bool)NS_UNLIKELY(NS_FAILED_impl(_nsresult)))
+#define NS_SUCCEEDED(_nsresult) ((bool)NS_LIKELY(!NS_FAILED_impl(_nsresult)))
 #else
-#define NS_FAILED(_nsresult)    (NS_UNLIKELY((_nsresult) & 0x80000000))
-#define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000)))
+#define NS_FAILED_impl(_nsresult) ((_nsresult) & 0x80000000)
+#define NS_FAILED(_nsresult)    (NS_UNLIKELY(NS_FAILED_impl(_nsresult)))
+#define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!NS_FAILED_impl(_nsresult)))
 #endif
 
 /**
  * @name Standard Error Generating Macros
  */
 
 #define NS_ERROR_GENERATE(sev, module, code) \
     (nsresult)(((uint32_t)(sev) << 31) | \
--- a/xpcom/glue/nsCycleCollectionParticipant.h
+++ b/xpcom/glue/nsCycleCollectionParticipant.h
@@ -79,17 +79,17 @@ public:
                                       nsCycleCollectionParticipant *helper) = 0;
 
     // Give a name to the edge associated with the next call to
     // NoteXPCOMChild, NoteJSChild, or NoteNativeChild.
     // Callbacks who care about this should set WANT_DEBUG_INFO in the
     // flags.
     NS_IMETHOD_(void) NoteNextEdgeName(const char* name) = 0;
 
-    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) = 0;
+    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *kdelegate, void *val) = 0;
 
     enum {
         // Values for flags:
 
         // Caller should call NoteNextEdgeName and pass useful objName
         // to DescribeRefCountedNode and DescribeGCedNode.
         WANT_DEBUG_INFO = (1<<0),