Merge mozilla-central to autoland. a=merge CLOSED TREE
authorBrindusan Cristian <cbrindusan@mozilla.com>
Thu, 15 Aug 2019 12:50:36 +0300
changeset 488210 caf7bd7998b21577f3ddce32f8d794d60e1ba203
parent 488209 ad04c84153da637000c7a472ccbc248116b5c330 (current diff)
parent 488153 0db07ff50ab5c9b655ba7e23788f68a2b9d66e71 (diff)
child 488211 a9bdb526a7a01e0984c2bf8c888e8d8ffc69c5c4
push id113904
push userncsoregi@mozilla.com
push dateThu, 15 Aug 2019 19:41:00 +0000
treeherdermozilla-inbound@b283a7ef186c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland. a=merge CLOSED TREE
docshell/base/BrowsingContext.cpp
dom/base/nsGlobalWindowOuter.cpp
taskcluster/taskgraph/transforms/use_toolchains.py
testing/specialpowers/content/SpecialPowersAPI.jsm
testing/web-platform/meta/console/idlharness.any.js.ini
testing/web-platform/meta/cookies/samesite/fetch.html.ini
testing/web-platform/meta/cookies/samesite/form-get-blank.html.ini
testing/web-platform/meta/cookies/samesite/form-post-blank-reload.html.ini
testing/web-platform/meta/cookies/samesite/form-post-blank.html.ini
testing/web-platform/meta/cookies/samesite/iframe-reload.html.ini
testing/web-platform/meta/cookies/samesite/iframe.html.ini
testing/web-platform/meta/cookies/samesite/img.html.ini
testing/web-platform/meta/cookies/samesite/setcookie-lax.html.ini
testing/web-platform/meta/css/css-variables/__dir__.ini
testing/web-platform/tests/.github/main.workflow
testing/web-platform/tests/2dcontext/clear-100x50.png
testing/web-platform/tests/2dcontext/drawing-rectangles-to-the-canvas/clear-100x50.png
testing/web-platform/tests/cookies/samesite/fetch.html
testing/web-platform/tests/cookies/samesite/form-get-blank-reload.html
testing/web-platform/tests/cookies/samesite/form-get-blank.html
testing/web-platform/tests/cookies/samesite/form-post-blank-reload.html
testing/web-platform/tests/cookies/samesite/form-post-blank.html
testing/web-platform/tests/cookies/samesite/iframe-reload.html
testing/web-platform/tests/cookies/samesite/iframe.html
testing/web-platform/tests/cookies/samesite/img.html
testing/web-platform/tests/cookies/samesite/setcookie-lax.html
testing/web-platform/tests/cookies/samesite/setcookie-navigation.html
testing/web-platform/tests/cookies/samesite/window-open-reload.html
testing/web-platform/tests/cookies/samesite/window-open.html
testing/web-platform/tests/css/css-animations/parsing/transition-timing-function-computed.html
testing/web-platform/tests/css/css-multicol/parsing/column-gap-computed.html
testing/web-platform/tests/css/css-multicol/parsing/column-gap-invalid.html
testing/web-platform/tests/css/css-multicol/parsing/column-gap-valid.html
testing/web-platform/tests/mathml/presentation-markup/direction/direction-006-ref.html
--- a/browser/config/mozconfigs/linux64/code-coverage
+++ b/browser/config/mozconfigs/linux64/code-coverage
@@ -7,11 +7,11 @@ TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
 ac_add_options --disable-install-strip
 ac_add_options --disable-elf-hack
 ac_add_options --disable-sandbox
 ac_add_options --disable-dmd
 ac_add_options --disable-profiling
 ac_add_options --disable-warnings-as-errors
 ac_add_options --enable-coverage
 
-export LDFLAGS="--coverage -L$topsrcdir/clang/lib/clang/8.0.0/lib/linux/"
+export LDFLAGS="--coverage -L$MOZ_FETCHES_DIR/clang/lib/clang/8.0.0/lib/linux/"
 export LIBS="-lclang_rt.profile-x86_64"
 export RUSTFLAGS="-Ccodegen-units=1 -Zprofile -Zno-landing-pads -Clink-dead-code -Coverflow-checks=off"
--- a/browser/config/mozconfigs/linux64/debug-searchfox-clang
+++ b/browser/config/mozconfigs/linux64/debug-searchfox-clang
@@ -4,18 +4,18 @@ MOZ_AUTOMATION_L10N_CHECK=0
 
 . "$topsrcdir/build/unix/mozconfig.unix"
 
 ac_add_options --enable-debug
 
 . $topsrcdir/build/mozconfig.stylo
 
 # Use Clang as specified in manifest
-export CC="$topsrcdir/clang/bin/clang"
-export CXX="$topsrcdir/clang/bin/clang++"
+export CC="$MOZ_FETCHES_DIR/clang/bin/clang"
+export CXX="$MOZ_FETCHES_DIR/clang/bin/clang++"
 
 # Save rust analysis (this requires unlocking the unstable features,
 # which is done in the taskcluster task definition via RUSTC_BOOTSTRAP)
 export RUSTFLAGS="-Zsave-analysis"
 
 # Add the static checker
 ac_add_options --enable-clang-plugin
 ac_add_options --enable-mozsearch-plugin
--- a/browser/config/mozconfigs/linux64/debug-static-analysis-clang
+++ b/browser/config/mozconfigs/linux64/debug-static-analysis-clang
@@ -4,17 +4,17 @@ MOZ_AUTOMATION_L10N_CHECK=0
 
 . "$topsrcdir/build/mozconfig.common"
 
 ac_add_options --enable-debug
 
 . $topsrcdir/build/mozconfig.stylo
 
 # Use Clang as specified in manifest
-export CC="$topsrcdir/clang/bin/clang"
-export CXX="$topsrcdir/clang/bin/clang++"
+export CC="$MOZ_FETCHES_DIR/clang/bin/clang"
+export CXX="$MOZ_FETCHES_DIR/clang/bin/clang++"
 
 # Add the static checker
 ac_add_options --enable-clang-plugin
 
 . "$topsrcdir/build/unix/mozconfig.stdcxx"
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/plain-opt
+++ b/browser/config/mozconfigs/linux64/plain-opt
@@ -1,14 +1,14 @@
 export TOOLTOOL_DIR="$topsrcdir"
-export LLVM_CONFIG="${TOOLTOOL_DIR}/clang/bin/llvm-config"
+export LLVM_CONFIG="${MOZ_FETCHES_DIR}/clang/bin/llvm-config"
 
-CARGO="${TOOLTOOL_DIR}/rustc/bin/cargo"
-RUSTC="${TOOLTOOL_DIR}/rustc/bin/rustc"
-RUSTDOC="${TOOLTOOL_DIR}/rustc/bin/rustdoc"
-RUSTFMT="${TOOLTOOL_DIR}/rustc/bin/rustfmt"
-CBINDGEN="${TOOLTOOL_DIR}/cbindgen/cbindgen"
+CARGO="${MOZ_FETCHES_DIR}/rustc/bin/cargo"
+RUSTC="${MOZ_FETCHES_DIR}/rustc/bin/rustc"
+RUSTDOC="${MOZ_FETCHES_DIR}/rustc/bin/rustdoc"
+RUSTFMT="${MOZ_FETCHES_DIR}/rustc/bin/rustfmt"
+CBINDGEN="${MOZ_FETCHES_DIR}/cbindgen/cbindgen"
 
-export NODEJS="${TOOLTOOL_DIR}/node/bin/node"
-NASM="${TOOLTOOL_DIR}/nasm/nasm"
+export NODEJS="${MOZ_FETCHES_DIR}/node/bin/node"
+NASM="${MOZ_FETCHES_DIR}/nasm/nasm"
 
-CC="${TOOLTOOL_DIR}/clang/bin/clang"
-CXX="${TOOLTOOL_DIR}/clang/bin/clang++"
+CC="${MOZ_FETCHES_DIR}/clang/bin/clang"
+CXX="${MOZ_FETCHES_DIR}/clang/bin/clang++"
--- a/browser/config/mozconfigs/linux64/tup
+++ b/browser/config/mozconfigs/linux64/tup
@@ -1,17 +1,17 @@
 MOZ_AUTOMATION_BUILD_SYMBOLS=0
 MOZ_AUTOMATION_L10N_CHECK=0
 MOZ_AUTOMATION_PACKAGE=0
 MOZ_AUTOMATION_PACKAGE_TESTS=0
 MOZ_AUTOMATION_UPLOAD=0
 MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
-export TUP=${TOOLTOOL_DIR}/tup/tup
+export TUP=${MOZ_FETCHES_DIR}/tup/tup
 
 . "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"
 . "$topsrcdir/build/mozconfig.common.override"
 
 ac_add_options --enable-build-backends=Tup
 unset ENABLE_CLANG_PLUGIN
 # To enable the option to upload the tup database, uncomment the line below
 # ac_add_options --upload-tup-db
--- a/browser/config/mozconfigs/macosx64/code-coverage
+++ b/browser/config/mozconfigs/macosx64/code-coverage
@@ -3,11 +3,11 @@
 unset MOZ_LTO
 
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
 
 ac_add_options --disable-sandbox
 ac_add_options --disable-warnings-as-errors
 ac_add_options --enable-coverage
 
-export LDFLAGS="-coverage -L$topsrcdir/clang/lib/clang/8.0.0/lib/darwin/"
+export LDFLAGS="-coverage -L$MOZ_FETCHES_DIR/clang/lib/clang/8.0.0/lib/darwin/"
 export LIBS="-lclang_rt.profile_osx"
 export RUSTFLAGS="-Ccodegen-units=1 -Zprofile -Zno-landing-pads -Clink-dead-code -Coverflow-checks=off"
--- a/browser/config/mozconfigs/macosx64/l10n-mozconfig
+++ b/browser/config/mozconfigs/macosx64/l10n-mozconfig
@@ -1,17 +1,17 @@
 . "$topsrcdir/browser/config/mozconfigs/common"
 . "$topsrcdir/build/mozconfig.no-compile"
 
 if test `uname -s` = "Linux"; then
   # We need to indicate the target for cross builds
   ac_add_options --target=x86_64-apple-darwin
-  export MKFSHFS=$topsrcdir/hfsplus-tools/newfs_hfs
-  export DMG_TOOL=$topsrcdir/dmg/dmg
-  export HFS_TOOL=$topsrcdir/dmg/hfsplus
+  export MKFSHFS=$MOZ_FETCHES_DIR/hfsplus-tools/newfs_hfs
+  export DMG_TOOL=$MOZ_FETCHES_DIR/dmg/dmg
+  export HFS_TOOL=$MOZ_FETCHES_DIR/dmg/hfsplus
 fi
 
 ac_add_options --with-l10n-base=../../l10n
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --with-branding=browser/branding/nightly
 
 ac_add_options --disable-nodejs
 unset NODEJS
--- a/browser/config/mozconfigs/macosx64/l10n-mozconfig-devedition
+++ b/browser/config/mozconfigs/macosx64/l10n-mozconfig-devedition
@@ -1,17 +1,17 @@
 . "$topsrcdir/browser/config/mozconfigs/common"
 . "$topsrcdir/build/mozconfig.no-compile"
 
 if test `uname -s` = "Linux"; then
   # We need to indicate the target for cross builds
   ac_add_options --target=x86_64-apple-darwin
-  export MKFSHFS=$topsrcdir/hfsplus-tools/newfs_hfs
-  export DMG_TOOL=$topsrcdir/dmg/dmg
-  export HFS_TOOL=$topsrcdir/dmg/hfsplus
+  export MKFSHFS=$MOZ_FETCHES_DIR/hfsplus-tools/newfs_hfs
+  export DMG_TOOL=$MOZ_FETCHES_DIR/dmg/dmg
+  export HFS_TOOL=$MOZ_FETCHES_DIR/dmg/hfsplus
 fi
 
 ac_add_options --with-l10n-base=../../l10n
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --with-branding=browser/branding/aurora
 
 ac_add_options --disable-nodejs
 unset NODEJS
--- a/browser/config/mozconfigs/macosx64/repack
+++ b/browser/config/mozconfigs/macosx64/repack
@@ -1,8 +1,8 @@
 # This mozconfig is responsible merely for getting the cross tools setup
 # for repacking a .tar into a .dmg as returned from signing.
 
-export MKFSHFS=$topsrcdir/hfsplus-tools/newfs_hfs
-export DMG_TOOL=$topsrcdir/dmg/dmg
-export HFS_TOOL=$topsrcdir/dmg/hfsplus
-export NODEJS=$topsrcdir/node/bin/node
+export MKFSHFS=$MOZ_FETCHES_DIR/hfsplus-tools/newfs_hfs
+export DMG_TOOL=$MOZ_FETCHES_DIR/dmg/dmg
+export HFS_TOOL=$MOZ_FETCHES_DIR/dmg/hfsplus
+export NODEJS=$MOZ_FETCHES_DIR/node/bin/node
 ac_add_options --disable-compile-environment
--- a/browser/config/mozconfigs/win32/mingwclang
+++ b/browser/config/mozconfigs/win32/mingwclang
@@ -41,34 +41,34 @@ ac_add_options --disable-jemalloc
 ac_add_options --enable-proxy-bypass-protection
 
 # These aren't supported on mingw at this time
 ac_add_options --disable-maintenance-service
 ac_add_options --disable-webrtc # Bug 1393901
 ac_add_options --disable-geckodriver # Bug 1489320
 
 # Find our toolchain
-HOST_CC="$TOOLTOOL_DIR/clang/bin/clang"
-HOST_CXX="$TOOLTOOL_DIR/clang/bin/clang++"
-CC="$TOOLTOOL_DIR/clang/bin/i686-w64-mingw32-clang"
-CXX="$TOOLTOOL_DIR/clang/bin/i686-w64-mingw32-clang++"
+HOST_CC="$MOZ_FETCHES_DIR/clang/bin/clang"
+HOST_CXX="$MOZ_FETCHES_DIR/clang/bin/clang++"
+CC="$MOZ_FETCHES_DIR/clang/bin/i686-w64-mingw32-clang"
+CXX="$MOZ_FETCHES_DIR/clang/bin/i686-w64-mingw32-clang++"
 ac_add_options --with-clang-path="$CC"
-ac_add_options --with-libclang-path="$TOOLTOOL_DIR/clang/lib"
+ac_add_options --with-libclang-path="$MOZ_FETCHES_DIR/clang/lib"
 CXXFLAGS="-fms-extensions"
 AR=llvm-ar
 RANLIB=llvm-ranlib
 
 # For Stylo
-BINDGEN_CFLAGS="-I$TOOLTOOL_DIR/clang/i686-w64-mingw32/include/c++/v1 -I$TOOLTOOL_DIR/clang/i686-w64-mingw32/include"
+BINDGEN_CFLAGS="-I$MOZ_FETCHES_DIR/clang/i686-w64-mingw32/include/c++/v1 -I$MOZ_FETCHES_DIR/clang/i686-w64-mingw32/include"
 
 # We want to make sure we use binutils and other binaries in the tooltool
 # package.
-mk_add_options "export PATH=$TOOLTOOL_DIR/clang/bin:$TOOLTOOL_DIR/mingw32/bin:$TOOLTOOL_DIR/wine/bin:$TOOLTOOL_DIR/upx/bin:$TOOLTOOL_DIR/fxc2/bin:$PATH"
+mk_add_options "export PATH=$MOZ_FETCHES_DIR/clang/bin:$MOZ_FETCHES_DIR/mingw32/bin:$MOZ_FETCHES_DIR/wine/bin:$MOZ_FETCHES_DIR/upx/bin:$MOZ_FETCHES_DIR/fxc2/bin:$PATH"
 
-LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOOLTOOL_DIR/mingw32/lib64:$TOOLTOOL_DIR/clang/lib
+LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$MOZ_FETCHES_DIR/mingw32/lib64:$MOZ_FETCHES_DIR/clang/lib
 mk_add_options "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
 
 # Do not include the visual studio related mozconfigs of course
 
 ac_add_options --with-branding=browser/branding/nightly
 
 . "$topsrcdir/build/mozconfig.common.override"
 . "$topsrcdir/build/mozconfig.cache"
--- a/browser/config/mozconfigs/win64/code-coverage
+++ b/browser/config/mozconfigs/win64/code-coverage
@@ -13,18 +13,18 @@ ac_add_options --enable-rust-tests
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 . $topsrcdir/build/win64/mozconfig.vs-latest
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
-if [ -d "$topsrcdir/clang" ]; then
-    CLANG_LIB_DIR="$(cd $topsrcdir/clang/lib/clang/* && cd lib/windows && pwd)"
+if [ -d "$MOZ_FETCHES_DIR/clang" ]; then
+    CLANG_LIB_DIR="$(cd $MOZ_FETCHES_DIR/clang/lib/clang/* && cd lib/windows && pwd)"
 
     export LIB=$LIB:$CLANG_LIB_DIR
     export LDFLAGS="clang_rt.profile-x86_64.lib"
 fi
 
 export RUSTFLAGS="-Ccodegen-units=1 -Zprofile -Zno-landing-pads -Clink-dead-code -Coverflow-checks=off"
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/mingwclang
+++ b/browser/config/mozconfigs/win64/mingwclang
@@ -41,34 +41,34 @@ ac_add_options --disable-jemalloc
 ac_add_options --enable-proxy-bypass-protection
 
 # These aren't supported on mingw at this time
 ac_add_options --disable-maintenance-service
 ac_add_options --disable-webrtc # Bug 1393901
 ac_add_options --disable-geckodriver # Bug 1489320
 
 # Find our toolchain
-HOST_CC="$TOOLTOOL_DIR/clang/bin/clang"
-HOST_CXX="$TOOLTOOL_DIR/clang/bin/clang++"
-CC="$TOOLTOOL_DIR/clang/bin/x86_64-w64-mingw32-clang"
-CXX="$TOOLTOOL_DIR/clang/bin/x86_64-w64-mingw32-clang++"
+HOST_CC="$MOZ_FETCHES_DIR/clang/bin/clang"
+HOST_CXX="$MOZ_FETCHES_DIR/clang/bin/clang++"
+CC="$MOZ_FETCHES_DIR/clang/bin/x86_64-w64-mingw32-clang"
+CXX="$MOZ_FETCHES_DIR/clang/bin/x86_64-w64-mingw32-clang++"
 ac_add_options --with-clang-path="$CC"
-ac_add_options --with-libclang-path="$TOOLTOOL_DIR/clang/lib"
+ac_add_options --with-libclang-path="$MOZ_FETCHES_DIR/clang/lib"
 CXXFLAGS="-fms-extensions"
 AR=llvm-ar
 RANLIB=llvm-ranlib
 
 # For Stylo
-BINDGEN_CFLAGS="-I$TOOLTOOL_DIR/clang/x86_64-w64-mingw32/include/c++/v1 -I$TOOLTOOL_DIR/clang/x86_64-w64-mingw32/include"
+BINDGEN_CFLAGS="-I$MOZ_FETCHES_DIR/clang/x86_64-w64-mingw32/include/c++/v1 -I$MOZ_FETCHES_DIR/clang/x86_64-w64-mingw32/include"
 
 # We want to make sure we use binutils and other binaries in the tooltool
 # package.
-mk_add_options "export PATH=$TOOLTOOL_DIR/clang/bin:$TOOLTOOL_DIR/mingw32/bin:$TOOLTOOL_DIR/wine/bin:$TOOLTOOL_DIR/upx/bin:$TOOLTOOL_DIR/fxc2/bin:$PATH"
+mk_add_options "export PATH=$MOZ_FETCHES_DIR/clang/bin:$MOZ_FETCHES_DIR/mingw32/bin:$MOZ_FETCHES_DIR/wine/bin:$MOZ_FETCHES_DIR/upx/bin:$MOZ_FETCHES_DIR/fxc2/bin:$PATH"
 
-LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOOLTOOL_DIR/mingw32/lib64:$TOOLTOOL_DIR/clang/lib
+LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$MOZ_FETCHES_DIR/mingw32/lib64:$MOZ_FETCHES_DIR/clang/lib
 mk_add_options "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
 
 # Do not include the visual studio related mozconfigs of course
 
 ac_add_options --with-branding=browser/branding/nightly
 
 . "$topsrcdir/build/mozconfig.common.override"
 . "$topsrcdir/build/mozconfig.cache"
--- a/browser/config/mozconfigs/win64/plain-opt
+++ b/browser/config/mozconfigs/win64/plain-opt
@@ -1,16 +1,16 @@
 TOOLTOOL_DIR=${topsrcdir}
 export MAKECAB=$TOOLTOOL_DIR/makecab.exe
-export LLVM_CONFIG="${TOOLTOOL_DIR}/clang/bin/llvm-config"
+export LLVM_CONFIG="${MOZ_FETCHES_DIR}/clang/bin/llvm-config"
 
-RUSTC="${TOOLTOOL_DIR}/rustc/bin/rustc"
-CARGO="${TOOLTOOL_DIR}/rustc/bin/cargo"
-RUSTDOC="${TOOLTOOL_DIR}/rustc/bin/rustdoc"
-RUSTFMT="${TOOLTOOL_DIR}/rustc/bin/rustfmt"
-CBINDGEN="${TOOLTOOL_DIR}/cbindgen/cbindgen"
+RUSTC="${MOZ_FETCHES_DIR}/rustc/bin/rustc"
+CARGO="${MOZ_FETCHES_DIR}/rustc/bin/cargo"
+RUSTDOC="${MOZ_FETCHES_DIR}/rustc/bin/rustdoc"
+RUSTFMT="${MOZ_FETCHES_DIR}/rustc/bin/rustfmt"
+CBINDGEN="${MOZ_FETCHES_DIR}/cbindgen/cbindgen"
 
-NASM="${TOOLTOOL_DIR}/nasm/nasm.exe"
-NODEJS="${TOOLTOOL_DIR}/node/node.exe"
+NASM="${MOZ_FETCHES_DIR}/nasm/nasm.exe"
+NODEJS="${MOZ_FETCHES_DIR}/node/node.exe"
 
 ac_add_options --target=x86_64-pc-mingw32
 
 . $topsrcdir/build/win64/mozconfig.vs-latest
--- a/browser/locales/l10n-changesets.json
+++ b/browser/locales/l10n-changesets.json
@@ -215,33 +215,16 @@
             "win32-devedition",
             "win64",
             "win64-aarch64",
             "win64-aarch64-devedition",
             "win64-devedition"
         ],
         "revision": "default"
     },
-    "crh": {
-        "platforms": [
-            "linux",
-            "linux-devedition",
-            "linux64",
-            "linux64-devedition",
-            "macosx64",
-            "macosx64-devedition",
-            "win32",
-            "win32-devedition",
-            "win64",
-            "win64-aarch64",
-            "win64-aarch64-devedition",
-            "win64-devedition"
-        ],
-        "revision": "default"
-    },
     "cs": {
         "platforms": [
             "linux",
             "linux-devedition",
             "linux64",
             "linux64-devedition",
             "macosx64",
             "macosx64-devedition",
--- a/build/build-clang/build-clang.py
+++ b/build/build-clang/build-clang.py
@@ -341,22 +341,23 @@ def build_one_stage(cc, cxx, asm, ld, ar
     if is_final_stage and android_targets:
         cmake_args += [
             "-DLLVM_LIBDIR_SUFFIX=64",
         ]
 
         android_link_flags = "-fuse-ld=lld"
 
         for target, cfg in android_targets.items():
-            sysroot_dir = cfg["ndk_sysroot"]
-            android_gcc_dir = cfg["ndk_toolchain"]
+            sysroot_dir = cfg["ndk_sysroot"].format(**os.environ)
+            android_gcc_dir = cfg["ndk_toolchain"].format(**os.environ)
             android_include_dirs = cfg["ndk_includes"]
             api_level = cfg["api_level"]
 
-            android_flags = ["-isystem %s" % d for d in android_include_dirs]
+            android_flags = ["-isystem %s" % d.format(**os.environ)
+                             for d in android_include_dirs]
             android_flags += ["--gcc-toolchain=%s" % android_gcc_dir]
             android_flags += ["-D__ANDROID_API__=%s" % api_level]
 
             # Our flags go last to override any --gcc-toolchain that may have
             # been set earlier.
             rt_c_flags = " ".join(cc[1:] + android_flags)
             rt_cxx_flags = " ".join(cxx[1:] + android_flags)
             rt_asm_flags = " ".join(asm[1:] + android_flags)
@@ -434,17 +435,17 @@ def build_one_stage(cc, cxx, asm, ld, ar
 # $PATH named "key".
 #
 # This expects the name of the key in the config file to match the name of
 # the tool in the default toolchain on the system (for example, "ld" on Unix
 # and "link" on Windows).
 def get_tool(config, key):
     f = None
     if key in config:
-        f = config[key]
+        f = config[key].format(**os.environ)
         if os.path.isabs(f):
             if not os.path.exists(f):
                 raise ValueError("%s must point to an existing path" % key)
             return f
 
     # Assume that we have the name of some program that should be on PATH.
     tool = which(f) if f else which(key)
     if not tool:
@@ -621,17 +622,17 @@ if __name__ == "__main__":
         if assertions not in (True, False):
             raise ValueError("Only boolean values are accepted for assertions.")
     python_path = None
     if "python_path" not in config:
         raise ValueError("Config file needs to set python_path")
     python_path = config["python_path"]
     gcc_dir = None
     if "gcc_dir" in config:
-        gcc_dir = config["gcc_dir"]
+        gcc_dir = config["gcc_dir"].format(**os.environ)
         if not os.path.exists(gcc_dir):
             raise ValueError("gcc_dir must point to an existing path")
     ndk_dir = None
     android_targets = None
     if "android_targets" in config:
         android_targets = config["android_targets"]
         for attr in ("ndk_toolchain", "ndk_sysroot", "ndk_includes", "api_level"):
             for target, cfg in android_targets.items():
--- a/build/build-clang/clang-4.0-linux64.json
+++ b/build/build-clang/clang-4.0-linux64.json
@@ -1,12 +1,12 @@
 {
     "stages": "3",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
     "python_path": "/usr/bin/python2.7",
-    "gcc_dir": "/builds/worker/workspace/build/gcc",
-    "cc": "/builds/worker/workspace/build/gcc/bin/gcc",
-    "cxx": "/builds/worker/workspace/build/gcc/bin/g++",
-    "as": "/builds/worker/workspace/build/gcc/bin/gcc",
+    "gcc_dir": "{MOZ_FETCHES_DIR}/gcc",
+    "cc": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
+    "cxx": "{MOZ_FETCHES_DIR}/gcc/bin/g++",
+    "as": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
     "patches": []
 }
--- a/build/build-clang/clang-7-linux64.json
+++ b/build/build-clang/clang-7-linux64.json
@@ -1,18 +1,18 @@
 {
     "stages": "3",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
     "python_path": "/usr/bin/python2.7",
-    "gcc_dir": "/builds/worker/workspace/build/gcc",
-    "cc": "/builds/worker/workspace/build/gcc/bin/gcc",
-    "cxx": "/builds/worker/workspace/build/gcc/bin/g++",
-    "as": "/builds/worker/workspace/build/gcc/bin/gcc",
+    "gcc_dir": "{MOZ_FETCHES_DIR}/gcc",
+    "cc": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
+    "cxx": "{MOZ_FETCHES_DIR}/gcc/bin/g++",
+    "as": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
     "patches": [
       "static-llvm-symbolizer.patch",
       "find_symbolizer_linux.patch",
       "rename_gcov_flush_7.patch",
       "r350774.patch",
       "android-mangling-error.patch"
     ]
 }
--- a/build/build-clang/clang-8-android.json
+++ b/build/build-clang/clang-8-android.json
@@ -1,52 +1,52 @@
 {
     "stages": "2",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
     "python_path": "/usr/bin/python2.7",
-    "gcc_dir": "/builds/worker/workspace/build/gcc",
-    "cc": "/builds/worker/workspace/build/gcc/bin/gcc",
-    "cxx": "/builds/worker/workspace/build/gcc/bin/g++",
-    "as": "/builds/worker/workspace/build/gcc/bin/gcc",
+    "gcc_dir": "{MOZ_FETCHES_DIR}/gcc",
+    "cc": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
+    "cxx": "{MOZ_FETCHES_DIR}/gcc/bin/g++",
+    "as": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
     "android_targets": {
       "armv7-linux-android": {
-        "ndk_toolchain": "/builds/worker/workspace/build/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64",
-        "ndk_sysroot": "/builds/worker/workspace/build/android-ndk/platforms/android-16/arch-arm",
+        "ndk_toolchain": "{MOZ_FETCHES_DIR}/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64",
+        "ndk_sysroot": "{MOZ_FETCHES_DIR}/android-ndk/platforms/android-16/arch-arm",
         "ndk_includes": [
-          "/builds/worker/workspace/build/android-ndk/sysroot/usr/include/arm-linux-androideabi",
-          "/builds/worker/workspace/build/android-ndk/sysroot/usr/include"
+          "{MOZ_FETCHES_DIR}/android-ndk/sysroot/usr/include/arm-linux-androideabi",
+          "{MOZ_FETCHES_DIR}/android-ndk/sysroot/usr/include"
         ],
         "api_level": 16
       },
       "i686-linux-android": {
-        "ndk_toolchain": "/builds/worker/workspace/build/android-ndk/toolchains/x86-4.9/prebuilt/linux-x86_64",
-        "ndk_sysroot": "/builds/worker/workspace/build/android-ndk/platforms/android-16/arch-x86",
+        "ndk_toolchain": "{MOZ_FETCHES_DIR}/android-ndk/toolchains/x86-4.9/prebuilt/linux-x86_64",
+        "ndk_sysroot": "{MOZ_FETCHES_DIR}/android-ndk/platforms/android-16/arch-x86",
         "ndk_includes": [
-          "/builds/worker/workspace/build/android-ndk/sysroot/usr/include/i686-linux-android",
-          "/builds/worker/workspace/build/android-ndk/sysroot/usr/include"
+          "{MOZ_FETCHES_DIR}/android-ndk/sysroot/usr/include/i686-linux-android",
+          "{MOZ_FETCHES_DIR}/android-ndk/sysroot/usr/include"
         ],
         "api_level": 16
       },
       "aarch64-linux-android": {
-        "ndk_toolchain": "/builds/worker/workspace/build/android-ndk/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64",
-        "ndk_sysroot": "/builds/worker/workspace/build/android-ndk/platforms/android-21/arch-arm64",
+        "ndk_toolchain": "{MOZ_FETCHES_DIR}/android-ndk/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64",
+        "ndk_sysroot": "{MOZ_FETCHES_DIR}/android-ndk/platforms/android-21/arch-arm64",
         "ndk_includes": [
-          "/builds/worker/workspace/build/android-ndk/sysroot/usr/include/aarch64-linux-android",
-          "/builds/worker/workspace/build/android-ndk/sysroot/usr/include"
+          "{MOZ_FETCHES_DIR}/android-ndk/sysroot/usr/include/aarch64-linux-android",
+          "{MOZ_FETCHES_DIR}/android-ndk/sysroot/usr/include"
         ],
         "api_level": 21
       },
       "x86_64-linux-android": {
-        "ndk_toolchain": "/builds/worker/workspace/build/android-ndk/toolchains/x86_64-4.9/prebuilt/linux-x86_64",
-        "ndk_sysroot": "/builds/worker/workspace/build/android-ndk/platforms/android-21/arch-x86_64",
+        "ndk_toolchain": "{MOZ_FETCHES_DIR}/android-ndk/toolchains/x86_64-4.9/prebuilt/linux-x86_64",
+        "ndk_sysroot": "{MOZ_FETCHES_DIR}/android-ndk/platforms/android-21/arch-x86_64",
         "ndk_includes": [
-          "/builds/worker/workspace/build/android-ndk/sysroot/usr/include/x86_64-linux-android",
-          "/builds/worker/workspace/build/android-ndk/sysroot/usr/include"
+          "{MOZ_FETCHES_DIR}/android-ndk/sysroot/usr/include/x86_64-linux-android",
+          "{MOZ_FETCHES_DIR}/android-ndk/sysroot/usr/include"
         ],
         "api_level": 21
       }
     },
     "patches": [
       "static-llvm-symbolizer.patch",
       "find_symbolizer_linux.patch",
       "rename_gcov_flush.patch"
--- a/build/build-clang/clang-8-linux64-aarch64-cross.json
+++ b/build/build-clang/clang-8-linux64-aarch64-cross.json
@@ -1,18 +1,18 @@
 {
     "stages": "3",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
     "python_path": "/usr/bin/python2.7",
-    "gcc_dir": "/builds/worker/workspace/build/gcc",
-    "cc": "/builds/worker/workspace/build/gcc/bin/gcc",
-    "cxx": "/builds/worker/workspace/build/gcc/bin/g++",
-    "as": "/builds/worker/workspace/build/gcc/bin/gcc",
+    "gcc_dir": "{MOZ_FETCHES_DIR}/gcc",
+    "cc": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
+    "cxx": "{MOZ_FETCHES_DIR}/gcc/bin/g++",
+    "as": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
     "extra_targets": [
       "aarch64-unknown-linux-gnu"
     ],
     "patches": [
       "static-llvm-symbolizer.patch",
       "find_symbolizer_linux.patch",
       "rename_gcov_flush.patch",
       "android-mangling-error.patch"
--- a/build/build-clang/clang-8-linux64.json
+++ b/build/build-clang/clang-8-linux64.json
@@ -1,17 +1,17 @@
 {
     "stages": "3",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
     "python_path": "/usr/bin/python2.7",
-    "gcc_dir": "/builds/worker/workspace/build/gcc",
-    "cc": "/builds/worker/workspace/build/gcc/bin/gcc",
-    "cxx": "/builds/worker/workspace/build/gcc/bin/g++",
-    "as": "/builds/worker/workspace/build/gcc/bin/gcc",
+    "gcc_dir": "{MOZ_FETCHES_DIR}/gcc",
+    "cc": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
+    "cxx": "{MOZ_FETCHES_DIR}/gcc/bin/g++",
+    "as": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
     "patches": [
       "static-llvm-symbolizer.patch",
       "find_symbolizer_linux.patch",
       "rename_gcov_flush.patch",
       "android-mangling-error.patch"
     ]
 }
--- a/build/build-clang/clang-8-macosx64.json
+++ b/build/build-clang/clang-8-macosx64.json
@@ -1,22 +1,22 @@
 {
     "stages": "1",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
     "osx_cross_compile": true,
     "python_path": "/usr/bin/python2.7",
-    "gcc_dir": "/builds/worker/workspace/build/gcc",
-    "cc": "/builds/worker/workspace/build/clang/bin/clang",
-    "cxx": "/builds/worker/workspace/build/clang/bin/clang++",
-    "as": "/builds/worker/workspace/build/clang/bin/clang",
-    "ar": "/builds/worker/workspace/build/cctools/bin/x86_64-apple-darwin-ar",
-    "ranlib": "/builds/worker/workspace/build/cctools/bin/x86_64-apple-darwin-ranlib",
-    "libtool": "/builds/worker/workspace/build/cctools/bin/x86_64-apple-darwin-libtool",
-    "ld": "/builds/worker/workspace/build/clang/bin/clang",
+    "gcc_dir": "{MOZ_FETCHES_DIR}/gcc",
+    "cc": "{MOZ_FETCHES_DIR}/clang/bin/clang",
+    "cxx": "{MOZ_FETCHES_DIR}/clang/bin/clang++",
+    "as": "{MOZ_FETCHES_DIR}/clang/bin/clang",
+    "ar": "{MOZ_FETCHES_DIR}/cctools/bin/x86_64-apple-darwin-ar",
+    "ranlib": "{MOZ_FETCHES_DIR}/cctools/bin/x86_64-apple-darwin-ranlib",
+    "libtool": "{MOZ_FETCHES_DIR}/cctools/bin/x86_64-apple-darwin-libtool",
+    "ld": "{MOZ_FETCHES_DIR}/clang/bin/clang",
     "patches": [
       "static-llvm-symbolizer.patch",
       "rename_gcov_flush.patch",
       "compiler-rt-cross-compile.patch",
       "compiler-rt-no-codesign.patch"
     ]
 }
--- a/build/build-clang/clang-8-mingw.json
+++ b/build/build-clang/clang-8-mingw.json
@@ -1,18 +1,18 @@
 {
     "stages": "3",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
     "python_path": "/usr/bin/python2.7",
-    "gcc_dir": "/builds/worker/workspace/build/gcc",
-    "cc": "/builds/worker/workspace/build/gcc/bin/gcc",
-    "cxx": "/builds/worker/workspace/build/gcc/bin/g++",
-    "as": "/builds/worker/workspace/build/gcc/bin/gcc",
+    "gcc_dir": "{MOZ_FETCHES_DIR}/gcc",
+    "cc": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
+    "cxx": "{MOZ_FETCHES_DIR}/gcc/bin/g++",
+    "as": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
     "patches": [
         "mingwclang-llvm-objcopy-COFF-Remove-a-superfluous-namespace-qua.patch",
         "mingwclang-llvm-objcopy-COFF-Add-support-for-removing-sections.patch",
         "mingwclang-llvm-objcopy-COFF-Implement-strip-debug.patch",
         "mingwclang-llvm-objcopy-COFF-Implement-only-keep-debug.patch",
         "mingwclang-llvm-objcopy-COFF-Implement-only-section.patch",
         "mingwclang-llvm-objcopy-Consistently-use-createStringError-inst.patch",
         "mingwclang-llvm-objcopy-COFF-Update-symbol-indices-in-weak-exte.patch",
--- a/build/build-clang/clang-tidy-linux64.json
+++ b/build/build-clang/clang-tidy-linux64.json
@@ -1,15 +1,15 @@
 {
     "stages": "1",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
     "build_clang_tidy": true,
     "python_path": "/usr/bin/python2.7",
-    "gcc_dir": "/builds/worker/workspace/build/gcc",
-    "cc": "/builds/worker/workspace/build/gcc/bin/gcc",
-    "cxx": "/builds/worker/workspace/build/gcc/bin/g++",
-    "as": "/builds/worker/workspace/build/gcc/bin/gcc",
+    "gcc_dir": "{MOZ_FETCHES_DIR}/gcc",
+    "cc": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
+    "cxx": "{MOZ_FETCHES_DIR}/gcc/bin/g++",
+    "as": "{MOZ_FETCHES_DIR}/gcc/bin/gcc",
     "patches": [
       "clang-tidy-8.patch"
     ]
 }
--- a/build/build-clang/clang-tidy-macosx64.json
+++ b/build/build-clang/clang-tidy-macosx64.json
@@ -1,21 +1,21 @@
 {
     "stages": "1",
     "build_libcxx": true,
     "build_type": "Release",
     "assertions": false,
     "build_clang_tidy": true,
     "osx_cross_compile": true,
     "python_path": "/usr/bin/python2.7",
-    "gcc_dir": "/builds/worker/workspace/build/gcc",
-    "cc": "/builds/worker/workspace/build/clang/bin/clang",
-    "cxx": "/builds/worker/workspace/build/clang/bin/clang++",
-    "as": "/builds/worker/workspace/build/clang/bin/clang",
-    "ar": "/builds/worker/workspace/build/cctools/bin/x86_64-apple-darwin-ar",
-    "ranlib": "/builds/worker/workspace/build/cctools/bin/x86_64-apple-darwin-ranlib",
-    "libtool": "/builds/worker/workspace/build/cctools/bin/x86_64-apple-darwin-libtool",
-    "ld": "/builds/worker/workspace/build/clang/bin/clang",
+    "gcc_dir": "{MOZ_FETCHES_DIR}/gcc",
+    "cc": "{MOZ_FETCHES_DIR}/clang/bin/clang",
+    "cxx": "{MOZ_FETCHES_DIR}/clang/bin/clang++",
+    "as": "{MOZ_FETCHES_DIR}/clang/bin/clang",
+    "ar": "{MOZ_FETCHES_DIR}/cctools/bin/x86_64-apple-darwin-ar",
+    "ranlib": "{MOZ_FETCHES_DIR}/cctools/bin/x86_64-apple-darwin-ranlib",
+    "libtool": "{MOZ_FETCHES_DIR}/cctools/bin/x86_64-apple-darwin-libtool",
+    "ld": "{MOZ_FETCHES_DIR}/clang/bin/clang",
     "patches": [
       "clang-tidy-8.patch",
       "compiler-rt-no-codesign.patch"
     ]
 }
--- a/build/macosx/cross-mozconfig.common
+++ b/build/macosx/cross-mozconfig.common
@@ -2,41 +2,41 @@
 # 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/.
 
 MOZ_AUTOMATION_L10N_CHECK=0
 
 . "$topsrcdir/build/mozconfig.common"
 
 # cctools for ld, ar, and other related tools ; dsymutil for rust.
-mk_add_options "export PATH=$topsrcdir/cctools/bin:$topsrcdir/binutils/bin:$topsrcdir/llvm-dsymutil/bin:$PATH"
+mk_add_options "export PATH=$MOZ_FETCHES_DIR/cctools/bin:$MOZ_FETCHES_DIR/binutils/bin:$MOZ_FETCHES_DIR/llvm-dsymutil/bin:$PATH"
 
 # dsymutil needs a libstdc++ more recent than what's on the system.
-mk_add_options "export LD_LIBRARY_PATH=$topsrcdir/clang/lib"
+mk_add_options "export LD_LIBRARY_PATH=$MOZ_FETCHES_DIR/clang/lib"
 
 # This SDK was copied from a local XCode install and uploaded to tooltool.
 # Generate the tarball by running this command with the proper SDK version:
 #   sdk_path=$(xcrun --sdk macosx10.12 --show-sdk-path)
 #   tar -C $(dirname ${sdk_path}) -cHjf /tmp/$(basename ${sdk_path}).tar.bz2 $(basename ${sdk_path})
 # Upload the resulting tarball from /tmp to tooltool, and change the entry in
 # `browser/config/tooltool-manifests/macosx64/cross-releng.manifest`.
 CROSS_SYSROOT=$topsrcdir/MacOSX10.11.sdk
 CROSS_PRIVATE_FRAMEWORKS=$CROSS_SYSROOT/System/Library/PrivateFrameworks
 
-export CC="$topsrcdir/clang/bin/clang"
-export CXX="$topsrcdir/clang/bin/clang++"
+export CC="$MOZ_FETCHES_DIR/clang/bin/clang"
+export CXX="$MOZ_FETCHES_DIR/clang/bin/clang++"
 export CFLAGS="$CFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}"
 export CXXFLAGS="$CXXFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}"
-export LLVMCONFIG=$topsrcdir/clang/bin/llvm-config
+export LLVMCONFIG=$MOZ_FETCHES_DIR/clang/bin/llvm-config
 export BINDGEN_CFLAGS="-isysroot $CROSS_SYSROOT"
 export DSYMUTIL=$topsrcdir/build/macosx/llvm-dsymutil
-mk_add_options "export REAL_DSYMUTIL=$topsrcdir/llvm-dsymutil/bin/dsymutil"
-export MKFSHFS=$topsrcdir/hfsplus-tools/newfs_hfs
-export DMG_TOOL=$topsrcdir/dmg/dmg
-export HFS_TOOL=$topsrcdir/dmg/hfsplus
+mk_add_options "export REAL_DSYMUTIL=$MOZ_FETCHES_DIR/llvm-dsymutil/bin/dsymutil"
+export MKFSHFS=$MOZ_FETCHES_DIR/hfsplus-tools/newfs_hfs
+export DMG_TOOL=$MOZ_FETCHES_DIR/dmg/dmg
+export HFS_TOOL=$MOZ_FETCHES_DIR/dmg/hfsplus
 
 export HOST_CFLAGS="-g"
 export HOST_CXXFLAGS="-g"
 export HOST_LDFLAGS="-g"
 
 ac_add_options --target=x86_64-apple-darwin
 export MACOS_SDK_DIR=$CROSS_SYSROOT
 export MACOS_PRIVATE_FRAMEWORKS_DIR=$CROSS_PRIVATE_FRAMEWORKS
--- a/build/macosx/local-mozconfig.common
+++ b/build/macosx/local-mozconfig.common
@@ -1,34 +1,24 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 . "$topsrcdir/build/mozconfig.common"
 
-if [ -d "$topsrcdir/clang" ]; then
+if [ -d "$MOZ_FETCHES_DIR/clang" ]; then
     # mozilla-central based build
-    export CC=$topsrcdir/clang/bin/clang
-    export CXX=$topsrcdir/clang/bin/clang++
-    export LLVMCONFIG=$topsrcdir/clang/bin/llvm-config
-    export DSYMUTIL=$topsrcdir/clang/bin/llvm-dsymutil
+    export CC=$MOZ_FETCHES_DIR/clang/bin/clang
+    export CXX=$MOZ_FETCHES_DIR/clang/bin/clang++
+    export LLVMCONFIG=$MOZ_FETCHES_DIR/clang/bin/llvm-config
+    export DSYMUTIL=$MOZ_FETCHES_DIR/clang/bin/llvm-dsymutil
     # Use an updated linker.
-    ldflags="-B$topsrcdir/cctools/bin"
-    export AR=$topsrcdir/cctools/bin/ar
-    export RANLIB=$topsrcdir/cctools/bin/ranlib
-elif [ -d "$topsrcdir/../clang" ]; then
-    # comm-central based build
-    export CC=$topsrcdir/../clang/bin/clang
-    export CXX=$topsrcdir/../clang/bin/clang++
-    export LLVMCONFIG=$topsrcdir/../clang/bin/llvm-config
-    export DSYMUTIL=$topsrcdir/../clang/bin/llvm-dsymutil
-    # Use an updated linker.
-    ldflags="-B$topsrcdir/../cctools/bin"
-    export AR=$topsrcdir/../cctools/bin/ar
-    export RANLIB=$topsrcdir/../cctools/bin/ranlib
+    ldflags="-B$MOZ_FETCHES_DIR/cctools/bin"
+    export AR=$MOZ_FETCHES_DIR/cctools/bin/ar
+    export RANLIB=$MOZ_FETCHES_DIR/cctools/bin/ranlib
 fi
 
 # Ensure the updated linker doesn't generate things our older build tools
 # don't understand.
 ldflags="$ldflags -Wl,-no_data_in_code_info"
 export LDFLAGS="$ldflags"
 
 # If not set use the system default clang
--- a/build/mozconfig.cache
+++ b/build/mozconfig.cache
@@ -53,12 +53,12 @@ if test -z "$bucket" -a -z "$SCCACHE_DIS
 fi
 
 if test -n "$bucket"; then
     if [ -n "${SCCACHE_GCS_KEY_PATH}" ]; then
         mk_add_options "export SCCACHE_GCS_BUCKET=$bucket"
     else
         mk_add_options "export SCCACHE_BUCKET=$bucket"
     fi
-    export CCACHE="$topsrcdir/sccache/sccache"
+    export CCACHE="$MOZ_FETCHES_DIR/sccache/sccache"
     export SCCACHE_VERBOSE_STATS=1
-    mk_add_options MOZBUILD_MANAGE_SCCACHE_DAEMON=${topsrcdir}/sccache/sccache
+    mk_add_options MOZBUILD_MANAGE_SCCACHE_DAEMON=${MOZ_FETCHES_DIR}/sccache/sccache
 fi
--- a/build/mozconfig.clang-cl
+++ b/build/mozconfig.clang-cl
@@ -1,14 +1,14 @@
-if test -d "$topsrcdir/clang/bin"; then
-    CLANG_DIR=`cd "$topsrcdir/clang/bin" ; pwd`
+if test -d "$MOZ_FETCHES_DIR/clang/bin"; then
+    CLANG_DIR=`cd "$MOZ_FETCHES_DIR/clang/bin" ; pwd`
     export PATH="${CLANG_DIR}:${PATH}"
 
-    if $(cd $topsrcdir/clang/lib/clang/* && test -d lib/windows); then
-        CLANG_LIB_DIR="$(cd $topsrcdir/clang/lib/clang/* && cd lib/windows && pwd)"
+    if $(cd $MOZ_FETCHES_DIR/clang/lib/clang/* && test -d lib/windows); then
+        CLANG_LIB_DIR="$(cd $MOZ_FETCHES_DIR/clang/lib/clang/* && cd lib/windows && pwd)"
         export LIB=$LIB:$CLANG_LIB_DIR
     fi
 fi
 
 export CC=clang-cl
 export CXX=clang-cl
 export ENABLE_CLANG_PLUGIN=1
 
--- a/build/mozconfig.lld-link
+++ b/build/mozconfig.lld-link
@@ -1,6 +1,6 @@
-if test -d "$topsrcdir/clang/bin"; then
-    CLANG_DIR=`cd "$topsrcdir/clang/bin" ; pwd`
+if test -d "$MOZ_FETCHES_DIR/clang/bin"; then
+    CLANG_DIR=`cd "$MOZ_FETCHES_DIR/clang/bin" ; pwd`
     export PATH="${CLANG_DIR}:${PATH}"
 fi
 
 export LINKER=lld-link
--- a/build/mozconfig.nasm
+++ b/build/mozconfig.nasm
@@ -1,12 +1,12 @@
 # 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/.
 
 case "$(uname -s)" in
 MINGW*)
-    export NASM=$topsrcdir/nasm/nasm.exe
+    export NASM=$MOZ_FETCHES_DIR/nasm/nasm.exe
     ;;
 *)
-    export NASM=$topsrcdir/nasm/nasm
+    export NASM=$MOZ_FETCHES_DIR/nasm/nasm
     ;;
 esac
--- a/build/mozconfig.node
+++ b/build/mozconfig.node
@@ -1,12 +1,12 @@
 # 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/.
 
 case "$(uname -s)" in
 MINGW*)
-    export NODEJS=$topsrcdir/node/node.exe
+    export NODEJS=$MOZ_FETCHES_DIR/node/node.exe
     ;;
 *)
-    export NODEJS=$topsrcdir/node/bin/node
+    export NODEJS=$MOZ_FETCHES_DIR/node/bin/node
     ;;
 esac
--- a/build/mozconfig.rust
+++ b/build/mozconfig.rust
@@ -1,12 +1,12 @@
 # Options to enable rust in automation builds.
 
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
 
 # Tell configure to use the tooltool rustc.
-RUSTC="$TOOLTOOL_DIR/rustc/bin/rustc"
-CARGO="$TOOLTOOL_DIR/rustc/bin/cargo"
-RUSTDOC="$TOOLTOOL_DIR/rustc/bin/rustdoc"
-RUSTFMT="$TOOLTOOL_DIR/rustc/bin/rustfmt"
-CBINDGEN="$TOOLTOOL_DIR/cbindgen/cbindgen"
+RUSTC="$MOZ_FETCHES_DIR/rustc/bin/rustc"
+CARGO="$MOZ_FETCHES_DIR/rustc/bin/cargo"
+RUSTDOC="$MOZ_FETCHES_DIR/rustc/bin/rustdoc"
+RUSTFMT="$MOZ_FETCHES_DIR/rustc/bin/rustfmt"
+CBINDGEN="$MOZ_FETCHES_DIR/cbindgen/cbindgen"
 
 ac_add_options --enable-rust-simd
--- a/build/mozconfig.stylo
+++ b/build/mozconfig.stylo
@@ -1,2 +1,2 @@
 # Tell the build system where to find llvm-config for builds on automation.
-export LLVM_CONFIG="${TOOLTOOL_DIR:-$topsrcdir}/clang/bin/llvm-config"
+export LLVM_CONFIG="${MOZ_FETCHES_DIR}/clang/bin/llvm-config"
--- a/build/unix/mozconfig.asan
+++ b/build/unix/mozconfig.asan
@@ -1,13 +1,13 @@
 MOZ_AUTOMATION_L10N_CHECK=0
 
 . "$topsrcdir/build/unix/mozconfig.unix"
 
-export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
+export LLVM_SYMBOLIZER="$MOZ_FETCHES_DIR/clang/bin/llvm-symbolizer"
 #
 # Enable ASan specific code and build workarounds
 ac_add_options --enable-address-sanitizer
 
 # Mandatory options required for ASan builds (both on Linux and Mac)
 export MOZ_DEBUG_SYMBOLS=1
 ac_add_options --enable-debug-symbols
 ac_add_options --disable-install-strip
--- a/build/unix/mozconfig.stdcxx
+++ b/build/unix/mozconfig.stdcxx
@@ -1,19 +1,19 @@
 # Avoid dependency on libstdc++ 4.7
 export MOZ_STDCXX_COMPAT=1
 
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
 
 # Depending whether GCC was built on a RedHat-based or a Debian-based system,
 # the directory containing 32-bits libraries can be either (respectively)
 # lib or lib32. The directory for 64-bits libraries is always lib64.
-if [ -f "$TOOLTOOL_DIR/gcc/lib64/libstdc++.so" ]; then
+if [ -f "$MOZ_FETCHES_DIR/gcc/lib64/libstdc++.so" ]; then
   # We put both 32-bits and 64-bits library path in LD_LIBRARY_PATH: ld.so
   # will prefer the files in the 32-bits path when loading 32-bits executables,
   # and the files in the 64-bits path when loading 64-bits executables.
   # We also put both possible 32-bits library paths.
-  LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOOLTOOL_DIR/gcc/lib64:$TOOLTOOL_DIR/gcc/lib32:$TOOLTOOL_DIR/gcc/lib
-elif [ -f "$TOOLTOOL_DIR/clang/lib/libstdc++.so" ]; then
-  LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOOLTOOL_DIR/clang/lib:$TOOLTOOL_DIR/clang/lib32
+  LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$MOZ_FETCHES_DIR/gcc/lib64:$MOZ_FETCHES_DIR/gcc/lib32:$MOZ_FETCHES_DIR/gcc/lib
+elif [ -f "$MOZ_FETCHES_DIR/clang/lib/libstdc++.so" ]; then
+  LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$MOZ_FETCHES_DIR/clang/lib:$MOZ_FETCHES_DIR/clang/lib32
 fi
 
 mk_add_options "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
--- a/build/unix/mozconfig.tsan
+++ b/build/unix/mozconfig.tsan
@@ -1,13 +1,13 @@
 MOZ_AUTOMATION_L10N_CHECK=0
 
 . "$topsrcdir/build/unix/mozconfig.unix"
 
-export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
+export LLVM_SYMBOLIZER="$MOZ_FETCHES_DIR/clang/bin/llvm-symbolizer"
 
 # Enable TSan specific code and build workarounds
 ac_add_options --enable-thread-sanitizer
 
 # The ThreadSanitizer is not compatible with sandboxing
 # (see bug 1182565)
 ac_add_options --disable-sandbox
 
--- a/build/unix/mozconfig.unix
+++ b/build/unix/mozconfig.unix
@@ -1,23 +1,23 @@
 . "$topsrcdir/build/mozconfig.common"
 
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
 
 if [ -n "$FORCE_GCC" ]; then
-    CC="$TOOLTOOL_DIR/gcc/bin/gcc"
-    CXX="$TOOLTOOL_DIR/gcc/bin/g++"
+    CC="$MOZ_FETCHES_DIR/gcc/bin/gcc"
+    CXX="$MOZ_FETCHES_DIR/gcc/bin/g++"
 
     # We want to make sure we use binutils and other binaries in the tooltool
     # package.
-    mk_add_options "export PATH=$TOOLTOOL_DIR/gcc/bin:$PATH"
-    ac_add_options --with-clang-path=$TOOLTOOL_DIR/clang/bin/clang
+    mk_add_options "export PATH=$MOZ_FETCHES_DIR/gcc/bin:$PATH"
+    ac_add_options --with-clang-path=$MOZ_FETCHES_DIR/clang/bin/clang
 else
-    CC="$TOOLTOOL_DIR/clang/bin/clang"
-    CXX="$TOOLTOOL_DIR/clang/bin/clang++"
+    CC="$MOZ_FETCHES_DIR/clang/bin/clang"
+    CXX="$MOZ_FETCHES_DIR/clang/bin/clang++"
     export ENABLE_CLANG_PLUGIN=1
     case "$PERFHERDER_EXTRA_OPTIONS" in
     base-toolchains*)
       # Clang versions < 7.0 don't support the -fcrash-diagnostics-dir flag.
       ;;
     *)
       export CFLAGS="$CFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}"
       export CXXFLAGS="$CXXFLAGS -fcrash-diagnostics-dir=${UPLOAD_PATH}"
@@ -28,18 +28,18 @@ else
         if [ -z "$USE_ARTIFACT" ]; then
             export MOZ_LTO=cross
             if [ -n "$MOZ_PGO_PROFILE_USE" ]; then
                 ac_add_options --enable-profile-use=cross
                 ac_add_options --with-pgo-jarlog=/builds/worker/fetches/en-US.log
                 ac_add_options --with-pgo-profile-path=/builds/worker/fetches
             fi
         fi
-        export LLVM_PROFDATA="$TOOLTOOL_DIR/clang/bin/llvm-profdata"
-        export AR="$topsrcdir/clang/bin/llvm-ar"
-        export NM="$topsrcdir/clang/bin/llvm-nm"
-        export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+        export LLVM_PROFDATA="$MOZ_FETCHES_DIR/clang/bin/llvm-profdata"
+        export AR="$MOZ_FETCHES_DIR/clang/bin/llvm-ar"
+        export NM="$MOZ_FETCHES_DIR/clang/bin/llvm-nm"
+        export RANLIB="$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib"
     fi
 
-    mk_add_options "export PATH=$TOOLTOOL_DIR/binutils/bin:$PATH"
+    mk_add_options "export PATH=$MOZ_FETCHES_DIR/binutils/bin:$PATH"
 fi
 
 . "$topsrcdir/build/unix/mozconfig.stdcxx"
--- a/build/win64/mozconfig.asan
+++ b/build/win64/mozconfig.asan
@@ -1,18 +1,18 @@
 . "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
 
-if [ -d "$topsrcdir/clang" ]; then
-    CLANG_LIB_DIR="$(cd $topsrcdir/clang/lib/clang/* && cd lib/windows && pwd)"
+if [ -d "$MOZ_FETCHES_DIR/clang" ]; then
+    CLANG_LIB_DIR="$(cd $MOZ_FETCHES_DIR/clang/lib/clang/* && cd lib/windows && pwd)"
 
     export LIB=$LIB:$CLANG_LIB_DIR
     export LDFLAGS="clang_rt.asan_dynamic-x86_64.lib clang_rt.asan_dynamic_runtime_thunk-x86_64.lib"
 
     export MOZ_COPY_PDBS=1
-    export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer.exe"
+    export LLVM_SYMBOLIZER="$MOZ_FETCHES_DIR/clang/bin/llvm-symbolizer.exe"
     export MOZ_CLANG_RT_ASAN_LIB_PATH="${CLANG_LIB_DIR}/clang_rt.asan_dynamic-x86_64.dll"
 fi
 
 # Enable ASan specific code and build workarounds
 ac_add_options --enable-address-sanitizer
 
 # Mandatory options required for ASan builds
 ac_add_options --enable-debug-symbols
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -457,114 +457,131 @@ void BrowsingContext::GetChildren(Childr
 // 4) Siblings and their children, both in insertion order
 // 5) After this we iteratively follow the parent chain, repeating 3
 //    and 4 until
 // 6) If there is no parent, consider all other top level browsing
 //    contexts and their children, both in insertion order
 //
 // See
 // https://html.spec.whatwg.org/multipage/browsers.html#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name
-BrowsingContext* BrowsingContext::FindWithName(const nsAString& aName) {
+BrowsingContext* BrowsingContext::FindWithName(
+    const nsAString& aName, BrowsingContext& aRequestingContext) {
   BrowsingContext* found = nullptr;
   if (aName.IsEmpty()) {
     // You can't find a browsing context with an empty name.
     found = nullptr;
-  } else if (BrowsingContext* special = FindWithSpecialName(aName)) {
-    found = special;
   } else if (aName.LowerCaseEqualsLiteral("_blank")) {
     // Just return null. Caller must handle creating a new window with
     // a blank name.
     found = nullptr;
-  } else if (BrowsingContext* child = FindWithNameInSubtree(aName, this)) {
+  } else if (IsSpecialName(aName)) {
+    found = FindWithSpecialName(aName, aRequestingContext);
+  } else if (BrowsingContext* child =
+                 FindWithNameInSubtree(aName, aRequestingContext)) {
     found = child;
   } else {
     BrowsingContext* current = this;
 
     do {
       Children* siblings;
       BrowsingContext* parent = current->mParent;
 
       if (!parent) {
         // We've reached the root of the tree, consider browsing
         // contexts in the same browsing context group.
         siblings = &mGroup->Toplevels();
-      } else if (parent->NameEquals(aName) && CanAccess(parent) &&
+      } else if (parent->NameEquals(aName) &&
+                 aRequestingContext.CanAccess(parent) &&
                  parent->IsTargetable()) {
         found = parent;
         break;
       } else {
         siblings = &parent->mChildren;
       }
 
       for (BrowsingContext* sibling : *siblings) {
         if (sibling == current) {
           continue;
         }
 
         if (BrowsingContext* relative =
-                sibling->FindWithNameInSubtree(aName, this)) {
+                sibling->FindWithNameInSubtree(aName, aRequestingContext)) {
           found = relative;
           // Breaks the outer loop
           parent = nullptr;
           break;
         }
       }
 
       current = parent;
     } while (current);
   }
 
   // Helpers should perform access control checks, which means that we
   // only need to assert that we can access found.
-  MOZ_DIAGNOSTIC_ASSERT(!found || CanAccess(found));
+  MOZ_DIAGNOSTIC_ASSERT(!found || aRequestingContext.CanAccess(found));
 
   return found;
 }
 
-BrowsingContext* BrowsingContext::FindChildWithName(const nsAString& aName) {
+BrowsingContext* BrowsingContext::FindChildWithName(
+    const nsAString& aName, BrowsingContext& aRequestingContext) {
   if (aName.IsEmpty()) {
     // You can't find a browsing context with the empty name.
     return nullptr;
   }
 
   for (BrowsingContext* child : mChildren) {
-    if (child->NameEquals(aName) && CanAccess(child) && child->IsTargetable()) {
+    if (child->NameEquals(aName) && aRequestingContext.CanAccess(child) &&
+        child->IsTargetable()) {
       return child;
     }
   }
 
   return nullptr;
 }
 
-BrowsingContext* BrowsingContext::FindWithSpecialName(const nsAString& aName) {
+/* static */
+bool BrowsingContext::IsSpecialName(const nsAString& aName) {
+  return (aName.LowerCaseEqualsLiteral("_self") ||
+          aName.LowerCaseEqualsLiteral("_parent") ||
+          aName.LowerCaseEqualsLiteral("_top") ||
+          aName.LowerCaseEqualsLiteral("_blank"));
+}
+
+BrowsingContext* BrowsingContext::FindWithSpecialName(
+    const nsAString& aName, BrowsingContext& aRequestingContext) {
   // TODO(farre): Neither BrowsingContext nor nsDocShell checks if the
   // browsing context pointed to by a special name is active. Should
   // it be? See Bug 1527913.
   if (aName.LowerCaseEqualsLiteral("_self")) {
     return this;
   }
 
   if (aName.LowerCaseEqualsLiteral("_parent")) {
-    return mParent && CanAccess(mParent.get()) ? mParent.get() : this;
+    if (mParent) {
+      return aRequestingContext.CanAccess(mParent) ? mParent.get() : nullptr;
+    }
+    return this;
   }
 
   if (aName.LowerCaseEqualsLiteral("_top")) {
     BrowsingContext* top = Top();
 
-    return CanAccess(top) ? top : nullptr;
+    return aRequestingContext.CanAccess(top) ? top : nullptr;
   }
 
   return nullptr;
 }
 
 BrowsingContext* BrowsingContext::FindWithNameInSubtree(
-    const nsAString& aName, BrowsingContext* aRequestingContext) {
+    const nsAString& aName, BrowsingContext& aRequestingContext) {
   MOZ_DIAGNOSTIC_ASSERT(!aName.IsEmpty());
 
-  if (NameEquals(aName) && aRequestingContext->CanAccess(this) &&
+  if (NameEquals(aName) && aRequestingContext.CanAccess(this) &&
       IsTargetable()) {
     return this;
   }
 
   for (BrowsingContext* child : mChildren) {
     if (BrowsingContext* found =
             child->FindWithNameInSubtree(aName, aRequestingContext)) {
       return found;
@@ -761,16 +778,39 @@ void BrowsingContext::Location(JSContext
   aError.MightThrowJSException();
   sSingleton.GetProxyObject(aCx, &mLocation, /* aTransplantTo = */ nullptr,
                             aLocation);
   if (!aLocation) {
     aError.StealExceptionFromJSContext(aCx);
   }
 }
 
+void BrowsingContext::LoadURI(BrowsingContext* aAccessor,
+                              nsDocShellLoadState* aLoadState) {
+  MOZ_DIAGNOSTIC_ASSERT(!IsDiscarded());
+  MOZ_DIAGNOSTIC_ASSERT(!aAccessor || !aAccessor->IsDiscarded());
+
+  if (mDocShell) {
+    mDocShell->LoadURI(aLoadState);
+  } else if (!aAccessor && XRE_IsParentProcess()) {
+    Unused << Canonical()->GetCurrentWindowGlobal()->SendLoadURIInChild(
+        aLoadState);
+  } else {
+    MOZ_DIAGNOSTIC_ASSERT(aAccessor);
+    MOZ_DIAGNOSTIC_ASSERT(aAccessor->Group() == Group());
+
+    nsCOMPtr<nsPIDOMWindowOuter> win(aAccessor->GetDOMWindow());
+    MOZ_DIAGNOSTIC_ASSERT(win);
+    if (WindowGlobalChild* wgc =
+            win->GetCurrentInnerWindow()->GetWindowGlobalChild()) {
+      wgc->SendLoadURI(this, aLoadState);
+    }
+  }
+}
+
 void BrowsingContext::Close(CallerType aCallerType, ErrorResult& aError) {
   // FIXME We need to set mClosed, but only once we're sending the
   //       DOMWindowClose event (which happens in the process where the
   //       document for this browsing context is loaded).
   //       See https://bugzilla.mozilla.org/show_bug.cgi?id=1516343.
   if (ContentChild* cc = ContentChild::GetSingleton()) {
     cc->SendWindowClose(this, aCallerType == CallerType::System);
   } else if (ContentParent* cp = Canonical()->GetContentParent()) {
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -15,16 +15,17 @@
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDocShell.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 #include "nsILoadInfo.h"
 
+class nsDocShellLoadState;
 class nsGlobalWindowOuter;
 class nsIPrincipal;
 class nsOuterWindowProxy;
 class PickleIterator;
 
 namespace IPC {
 class Message;
 }  // namespace IPC
@@ -174,16 +175,21 @@ class BrowsingContext : public nsWrapper
 
   // Remove all children from the current BrowsingContext and cache
   // them to allow them to be attached again.
   void CacheChildren(bool aFromIPC = false);
 
   // Restore cached browsing contexts.
   void RestoreChildren(Children&& aChildren, bool aFromIPC = false);
 
+  // Triggers a load in the process which currently owns this BrowsingContext.
+  // aAccessor is the context which initiated the load, and may be null only for
+  // in-process BrowsingContexts.
+  void LoadURI(BrowsingContext* aAccessor, nsDocShellLoadState* aLoadState);
+
   // Determine if the current BrowsingContext was 'cached' by the logic in
   // CacheChildren.
   bool IsCached();
 
   // Check that this browsing context is targetable for navigations (i.e. that
   // it is neither closed, cached, nor discarded).
   bool IsTargetable();
 
@@ -204,37 +210,58 @@ class BrowsingContext : public nsWrapper
 
   already_AddRefed<BrowsingContext> GetOpener() const { return Get(mOpenerId); }
   void SetOpener(BrowsingContext* aOpener) {
     SetOpenerId(aOpener ? aOpener->Id() : 0);
   }
 
   bool HasOpener() const;
 
+  /**
+   * When a new browsing context is opened by a sandboxed document, it needs to
+   * keep track of the browsing context that opened it, so that it can be
+   * navigated by it.  This is the "one permitted sandboxed navigator".
+   */
+  already_AddRefed<BrowsingContext> GetOnePermittedSandboxedNavigator() const {
+    return Get(mOnePermittedSandboxedNavigatorId);
+  }
+  void SetOnePermittedSandboxedNavigator(BrowsingContext* aNavigator) {
+    if (mOnePermittedSandboxedNavigatorId) {
+      MOZ_ASSERT(false,
+                 "One Permitted Sandboxed Navigator should only be set once.");
+    } else {
+      SetOnePermittedSandboxedNavigatorId(aNavigator ? aNavigator->Id() : 0);
+    }
+  }
+
   void GetChildren(Children& aChildren);
 
   BrowsingContextGroup* Group() { return mGroup; }
 
   // Using the rules for choosing a browsing context we try to find
   // the browsing context with the given name in the set of
   // transitively reachable browsing contexts. Performs access control
   // with regards to this.
   // See
   // https://html.spec.whatwg.org/multipage/browsers.html#the-rules-for-choosing-a-browsing-context-given-a-browsing-context-name.
   //
   // BrowsingContext::FindWithName(const nsAString&) is equivalent to
   // calling nsIDocShellTreeItem::FindItemWithName(aName, nullptr,
   // nullptr, false, <return value>).
-  BrowsingContext* FindWithName(const nsAString& aName);
+  BrowsingContext* FindWithName(const nsAString& aName,
+                                BrowsingContext& aRequestingContext);
+
 
   // Find a browsing context in this context's list of
   // children. Doesn't consider the special names, '_self', '_parent',
   // '_top', or '_blank'. Performs access control with regard to
   // 'this'.
-  BrowsingContext* FindChildWithName(const nsAString& aName);
+  BrowsingContext* FindChildWithName(const nsAString& aName,
+                                     BrowsingContext& aRequestingContext);
+
 
   nsISupports* GetParentObject() const;
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
   // This function would be called when its corresponding document is activated
   // by user gesture, and we would set the flag in the top level browsing
   // context.
@@ -385,26 +412,31 @@ class BrowsingContext : public nsWrapper
   bool CanAccess(BrowsingContext* aTarget, bool aConsiderOpener = true);
 
  protected:
   virtual ~BrowsingContext();
   BrowsingContext(BrowsingContext* aParent, BrowsingContextGroup* aGroup,
                   uint64_t aBrowsingContextId, Type aType);
 
  private:
+  // Returns true if the given name is one of the "special" names, currently:
+  // "_self", "_parent", "_top", or "_blank".
+  static bool IsSpecialName(const nsAString& aName);
+
   // Find the special browsing context if aName is '_self', '_parent',
   // '_top', but not '_blank'. The latter is handled in FindWithName
-  BrowsingContext* FindWithSpecialName(const nsAString& aName);
+  BrowsingContext* FindWithSpecialName(const nsAString& aName,
+                                       BrowsingContext& aRequestingContext);
 
   // Find a browsing context in the subtree rooted at 'this' Doesn't
   // consider the special names, '_self', '_parent', '_top', or
   // '_blank'. Performs access control with regard to
   // 'aRequestingContext'.
   BrowsingContext* FindWithNameInSubtree(const nsAString& aName,
-                                         BrowsingContext* aRequestingContext);
+                                         BrowsingContext& aRequestingContext);
 
   // Removes the context from its group and sets mIsDetached to true.
   void Unregister();
 
   friend class ::nsOuterWindowProxy;
   friend class ::nsGlobalWindowOuter;
   // Update the window proxy object that corresponds to this browsing context.
   // This should be called from the window proxy object's objectMoved hook, if
--- a/docshell/base/BrowsingContextFieldList.h
+++ b/docshell/base/BrowsingContextFieldList.h
@@ -14,13 +14,15 @@ MOZ_BC_FIELD(Name, nsString)
 MOZ_BC_FIELD(Closed, bool)
 MOZ_BC_FIELD(EmbedderPolicy, nsILoadInfo::CrossOriginEmbedderPolicy)
 MOZ_BC_FIELD(OpenerPolicy, nsILoadInfo::CrossOriginOpenerPolicy)
 
 // The current opener for this BrowsingContext. This is a weak reference, and
 // stored as the opener ID.
 MOZ_BC_FIELD(OpenerId, uint64_t)
 
+MOZ_BC_FIELD(OnePermittedSandboxedNavigatorId, uint64_t)
+
 // Toplevel browsing contexts only. This field controls whether the browsing
 // context is currently considered to be activated by a gesture.
 MOZ_BC_FIELD(IsActivatedByUserGesture, bool)
 
 #undef MOZ_BC_FIELD
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3002,24 +3002,24 @@ nsresult nsDocShell::DoFindItemWithName(
   if (window && !aSkipTabGroup) {
     RefPtr<mozilla::dom::TabGroup> tabGroup = window->TabGroup();
     tabGroup->FindItemWithName(aName, this, aOriginalRequestor, aResult);
   }
 
   return NS_OK;
 }
 
-bool nsDocShell::IsSandboxedFrom(nsIDocShell* aTargetDocShell) {
+bool nsDocShell::IsSandboxedFrom(BrowsingContext* aTargetBC) {
   // If no target then not sandboxed.
-  if (!aTargetDocShell) {
+  if (!aTargetBC) {
     return false;
   }
 
   // We cannot be sandboxed from ourselves.
-  if (aTargetDocShell == this) {
+  if (aTargetBC == mBrowsingContext) {
     return false;
   }
 
   // Default the sandbox flags to our flags, so that if we can't retrieve the
   // active document, we will still enforce our own.
   uint32_t sandboxFlags = mSandboxFlags;
   if (mContentViewer) {
     RefPtr<Document> doc = mContentViewer->GetDocument();
@@ -3028,55 +3028,47 @@ bool nsDocShell::IsSandboxedFrom(nsIDocS
     }
   }
 
   // If no flags, we are not sandboxed at all.
   if (!sandboxFlags) {
     return false;
   }
 
-  // If aTargetDocShell has an ancestor, it is not top level.
-  nsCOMPtr<nsIDocShellTreeItem> ancestorOfTarget;
-  aTargetDocShell->GetInProcessSameTypeParent(getter_AddRefs(ancestorOfTarget));
+  // If aTargetBC has an ancestor, it is not top level.
+  RefPtr<BrowsingContext> ancestorOfTarget(aTargetBC->GetParent());
   if (ancestorOfTarget) {
     do {
       // We are not sandboxed if we are an ancestor of target.
-      if (ancestorOfTarget == this) {
+      if (ancestorOfTarget == mBrowsingContext) {
         return false;
       }
-      nsCOMPtr<nsIDocShellTreeItem> tempTreeItem;
-      ancestorOfTarget->GetInProcessSameTypeParent(
-          getter_AddRefs(tempTreeItem));
-      tempTreeItem.swap(ancestorOfTarget);
+      ancestorOfTarget = ancestorOfTarget->GetParent();
     } while (ancestorOfTarget);
 
-    // Otherwise, we are sandboxed from aTargetDocShell.
+    // Otherwise, we are sandboxed from aTargetBC.
     return true;
   }
 
-  // aTargetDocShell is top level, are we the "one permitted sandboxed
-  // navigator", i.e. did we open aTargetDocShell?
-  nsCOMPtr<nsIDocShell> permittedNavigator;
-  aTargetDocShell->GetOnePermittedSandboxedNavigator(
-      getter_AddRefs(permittedNavigator));
-  if (permittedNavigator == this) {
+  // aTargetBC is top level, are we the "one permitted sandboxed
+  // navigator", i.e. did we open aTargetBC?
+  RefPtr<BrowsingContext> permittedNavigator(
+      aTargetBC->GetOnePermittedSandboxedNavigator());
+  if (permittedNavigator == mBrowsingContext) {
     return false;
   }
 
   // If SANDBOXED_TOPLEVEL_NAVIGATION flag is not on, we are not sandboxed
   // from our top.
-  if (!(sandboxFlags & SANDBOXED_TOPLEVEL_NAVIGATION)) {
-    nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
-    GetInProcessSameTypeRootTreeItem(getter_AddRefs(rootTreeItem));
-    if (SameCOMIdentity(aTargetDocShell, rootTreeItem)) {
-      return false;
-    }
-  }
-
-  // Otherwise, we are sandboxed from aTargetDocShell.
+  if (!(sandboxFlags & SANDBOXED_TOPLEVEL_NAVIGATION) &&
+      aTargetBC == mBrowsingContext->Top()) {
+    return false;
+  }
+
+  // Otherwise, we are sandboxed from aTargetBC.
   return true;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
   NS_ENSURE_ARG_POINTER(aTreeOwner);
 
   *aTreeOwner = mTreeOwner;
@@ -4962,18 +4954,16 @@ nsDocShell::Destroy() {
   }
 
   SetTreeOwner(nullptr);
 
   mBrowserChild = nullptr;
 
   mChromeEventHandler = nullptr;
 
-  mOnePermittedSandboxedNavigator = nullptr;
-
   // required to break ref cycle
   mSecurityUI = nullptr;
 
   // Cancel any timers that were set for this docshell; this is needed
   // to break the cycle between us and the timers.
   CancelRefreshURITimers();
 
   if (UsePrivateBrowsing()) {
@@ -5260,21 +5250,16 @@ nsDocShell::SetIsOffScreenBrowser(bool a
 NS_IMETHODIMP
 nsDocShell::GetIsOffScreenBrowser(bool* aIsOffScreen) {
   *aIsOffScreen = mIsOffScreenBrowser;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetIsActive(bool aIsActive) {
-  // We disallow setting active on chrome docshells.
-  if (mItemType == nsIDocShellTreeItem::typeChrome) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
   // Keep track ourselves.
   mIsActive = aIsActive;
 
   // Tell the PresShell about it.
   if (RefPtr<PresShell> presShell = GetPresShell()) {
     presShell->SetIsActive(aIsActive);
   }
 
@@ -5363,44 +5348,16 @@ nsDocShell::SetSandboxFlags(uint32_t aSa
 
 NS_IMETHODIMP
 nsDocShell::GetSandboxFlags(uint32_t* aSandboxFlags) {
   *aSandboxFlags = mSandboxFlags;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocShell::SetOnePermittedSandboxedNavigator(
-    nsIDocShell* aSandboxedNavigator) {
-  if (mOnePermittedSandboxedNavigator) {
-    NS_ERROR("One Permitted Sandboxed Navigator should only be set once.");
-    return NS_OK;
-  }
-
-  MOZ_ASSERT(!mIsBeingDestroyed);
-
-  mOnePermittedSandboxedNavigator = do_GetWeakReference(aSandboxedNavigator);
-  NS_ASSERTION(
-      mOnePermittedSandboxedNavigator,
-      "One Permitted Sandboxed Navigator must support weak references.");
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocShell::GetOnePermittedSandboxedNavigator(
-    nsIDocShell** aSandboxedNavigator) {
-  NS_ENSURE_ARG_POINTER(aSandboxedNavigator);
-  nsCOMPtr<nsIDocShell> permittedNavigator =
-      do_QueryReferent(mOnePermittedSandboxedNavigator);
-  permittedNavigator.forget(aSandboxedNavigator);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) {
   mDefaultLoadFlags = aDefaultLoadFlags;
 
   // Tell the load group to set these flags all requests in the group
   if (mLoadGroup) {
     mLoadGroup->SetDefaultLoadFlags(aDefaultLoadFlags);
   } else {
     NS_WARNING(
@@ -9295,17 +9252,17 @@ nsresult nsDocShell::InternalLoad(nsDocS
     if (handled) {
       return NS_OK;
     }
   }
 
   // If a source docshell has been passed, check to see if we are sandboxed
   // from it as the result of an iframe or CSP sandbox.
   if (aLoadState->SourceDocShell() &&
-      aLoadState->SourceDocShell()->IsSandboxedFrom(this)) {
+      aLoadState->SourceDocShell()->IsSandboxedFrom(mBrowsingContext)) {
     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   }
 
   NS_ENSURE_STATE(!HasUnloadedParent());
 
   rv = CheckLoadingPermissions();
   if (NS_FAILED(rv)) {
     return rv;
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -1061,17 +1061,16 @@ class nsDocShell final : public nsDocLoa
   // We're counting the number of |nsDocShells| to help find leaks
   static unsigned long gNumberOfDocShells;
 #endif /* DEBUG */
 
   nsID mHistoryID;
   nsString mTitle;
   nsString mCustomUserAgent;
   nsCString mOriginalUriString;
-  nsWeakPtr mOnePermittedSandboxedNavigator;
   nsWeakPtr mOpener;
   nsTObserverArray<nsWeakPtr> mPrivacyObservers;
   nsTObserverArray<nsWeakPtr> mReflowObservers;
   nsTObserverArray<nsWeakPtr> mScrollObservers;
   mozilla::OriginAttributes mOriginAttributes;
   mozilla::UniquePtr<mozilla::dom::ClientSource> mInitialClientSource;
   nsCOMPtr<nsINetworkInterceptController> mInterceptController;
   RefPtr<nsDOMNavigationTiming> mTiming;
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -780,27 +780,20 @@ interface nsIDocShell : nsIDocShellTreeI
    * loaded.
    * The sandbox flags of a document depend on the sandbox flags on its
    * docshell and of its parent document, if any.
    * See nsSandboxFlags.h for the possible flags.
    */
   attribute unsigned long sandboxFlags;
 
   /**
-   * When a new browsing context is opened by a sandboxed document, it needs to
-   * keep track of the browsing context that opened it, so that it can be
-   * navigated by it.  This is the "one permitted sandboxed navigator".
-   */
-  attribute nsIDocShell onePermittedSandboxedNavigator;
-
-  /**
    * Returns true if we are sandboxed from aTargetDocShell.
    * aTargetDocShell - the browsing context we are attempting to navigate.
    */
-  [noscript,notxpcom,nostdcall] bool isSandboxedFrom(in nsIDocShell aTargetDocShell);
+  [noscript,notxpcom,nostdcall] bool isSandboxedFrom(in BrowsingContext aTargetBC);
 
   /**
    * This member variable determines whether a document has Mixed Active Content that
    * was initially blocked from loading, but the user has choosen to override the
    * block and allow the content to load. mMixedContentChannel is set to the document's
    * channel when the user allows mixed content. The nsMixedContentBlocker content policy
    * checks if the document's root channel matches the mMixedContentChannel.  If it matches,
    * then Mixed Content is loaded.  If it does match, mixed content is blocked.
--- a/docshell/test/browser/browser.ini
+++ b/docshell/test/browser/browser.ini
@@ -129,19 +129,19 @@ skip-if = true # Bug 1220415
 [browser_timelineMarkers-03.js]
 [browser_timelineMarkers-04.js]
 [browser_timelineMarkers-05.js]
 [browser_ua_emulation.js]
 [browser_history_triggeringprincipal_viewsource.js]
 [browser_click_link_within_view_source.js]
 [browser_browsingContext-01.js]
 [browser_browsingContext-02.js]
-fail-if = fission
+skip-if = fission # Cross-process postMessage
 [browser_browsingContext-03.js]
-fail-if = fission
+skip-if = fission # Cross-process postMessage
 [browser_browsingContext-embedder.js]
 [browser_csp_uir.js]
 support-files =
   file_csp_uir.html
   file_csp_uir_dummy.html
 [browser_cross_process_csp_inheritance.js]
 fail-if = fission
 skip-if = !e10s # e10s specific test.
--- a/docshell/test/browser/browser_browsingContext-02.js
+++ b/docshell/test/browser/browser_browsingContext-02.js
@@ -27,54 +27,66 @@ add_task(async function() {
         URL + "#seventh",
         true,
         true
       );
       await ContentTask.spawn(
         browser,
         { base1: BASE1, base2: BASE2 },
         async function({ base1, base2 }) {
-          let top = content.window;
+          let top = content;
           top.name = "top";
           top.location.href += "#top";
 
           let contexts = {
             top: top.location.href,
             first: base1 + "dummy_page.html#first",
             third: base2 + "dummy_page.html#third",
             second: base1 + "dummy_page.html#second",
             fourth: base2 + "dummy_page.html#fourth",
             fifth: base1 + "dummy_page.html#fifth",
             sixth: base1 + "onload_message.html#sixth",
             seventh: base1 + "onload_message.html#seventh",
           };
 
           function addFrame(target, name) {
-            let doc = (target.contentWindow || target).document;
-            let frame = doc.createElement("iframe");
-            let p = new Promise(
-              resolve => (frame.onload = () => resolve(frame))
+            return content.SpecialPowers.spawn(
+              target,
+              [name, contexts[name]],
+              async (name, context) => {
+                let doc = this.content.document;
+
+                let frame = doc.createElement("iframe");
+                doc.body.appendChild(frame);
+                frame.name = name;
+                frame.src = context;
+                await new Promise(resolve => {
+                  frame.addEventListener("load", resolve, { once: true });
+                });
+                return frame.browsingContext;
+              }
             );
-            doc.body.appendChild(frame);
-            frame.name = name;
-            frame.src = contexts[name];
-            return p;
           }
 
           function addWindow(target, name, { options, resolve }) {
-            var win = target.contentWindow.open(contexts[name], name, options);
+            return content.SpecialPowers.spawn(
+              target,
+              [name, contexts[name], options, resolve],
+              (name, context, options, resolve) => {
+                let win = this.content.open(context, name, options);
+                let bc = win && win.docShell.browsingContext;
 
-            if (resolve) {
-              return new Promise(resolve =>
-                target.contentWindow.addEventListener("message", () =>
-                  resolve(win)
-                )
-              );
-            }
-            return Promise.resolve({ name });
+                if (resolve) {
+                  return new Promise(resolve =>
+                    this.content.addEventListener("message", () => resolve(bc))
+                  );
+                }
+                return Promise.resolve({ name });
+              }
+            );
           }
 
           // We're going to create a tree that looks like the
           // following.
           //
           //           top          sixth    seventh
           //          /   \
           //         /     \        /
@@ -88,35 +100,31 @@ add_task(async function() {
           //
           // The idea is to have one top level non-auxiliary browsing
           // context, five nested, one top level auxiliary with an
           // opener, and one top level without an opener. Given that
           // set of related and one unrelated browsing contexts we
           // wish to confirm that targeting is able to find
           // appropriate browsing contexts.
 
-          function bc(frame) {
-            return (frame.contentWindow || frame).docShell.browsingContext;
-          }
-
           function reachable(start, targets) {
             for (let target of targets) {
               is(
-                bc(start).findWithName(target.name),
-                bc(target),
-                [bc(start).name, "can reach", target.name].join(" ")
+                start.findWithName(target.name, start),
+                target,
+                [start.name, "can reach", target.name].join(" ")
               );
             }
           }
 
           function unreachable(start, target) {
             is(
-              bc(start).findWithName(target.name),
+              start.findWithName(target.name, start),
               null,
-              [bc(start).name, "can't reach", target.name].join(" ")
+              [start.name, "can't reach", target.name].join(" ")
             );
           }
 
           let first = await addFrame(top, "first");
           info("first");
           let second = await addFrame(top, "second");
           info("second");
           let third = await addFrame(first, "third");
@@ -127,17 +135,25 @@ add_task(async function() {
           info("fifth");
           let sixth = await addWindow(fourth, "sixth", { resolve: true });
           info("sixth");
           let seventh = await addWindow(fourth, "seventh", {
             options: ["noopener"],
           });
           info("seventh");
 
-          let frames = [top, first, second, third, fourth, fifth, sixth];
+          let frames = [
+            BrowsingContext.getFromWindow(top),
+            first,
+            second,
+            third,
+            fourth,
+            fifth,
+            sixth,
+          ];
           for (let start of frames) {
             reachable(start, frames);
             unreachable(start, seventh);
           }
         }
       );
 
       for (let tab of await Promise.all([sixth, seventh])) {
--- a/docshell/test/browser/browser_browsingContext-03.js
+++ b/docshell/test/browser/browser_browsingContext-03.js
@@ -21,49 +21,61 @@ add_task(async function() {
         URL + "#sixth",
         true,
         true
       );
       await ContentTask.spawn(
         browser,
         { base1: BASE1, base2: BASE2 },
         async function({ base1, base2 }) {
-          let top = content.window;
+          let top = content;
           top.name = "top";
           top.location.href += "#top";
 
           let contexts = {
             top: top.location.href,
             first: base1 + "dummy_page.html#first",
             third: base2 + "dummy_page.html#third",
             second: base1 + "dummy_page.html#second",
             fourth: base2 + "dummy_page.html#fourth",
             fifth: base1 + "dummy_page.html#fifth",
             sixth: base1 + "onload_message.html#sixth",
           };
 
           function addFrame(target, name) {
-            let doc = (target.contentWindow || target).document;
-            let frame = doc.createElement("iframe");
-            let p = new Promise(
-              resolve => (frame.onload = () => resolve(frame))
+            return content.SpecialPowers.spawn(
+              target,
+              [name, contexts[name]],
+              async (name, context) => {
+                let doc = this.content.document;
+
+                let frame = doc.createElement("iframe");
+                doc.body.appendChild(frame);
+                frame.name = name;
+                frame.src = context;
+                await new Promise(resolve => {
+                  frame.addEventListener("load", resolve, { once: true });
+                });
+                return frame.browsingContext;
+              }
             );
-            doc.body.appendChild(frame);
-            frame.name = name;
-            frame.src = contexts[name];
-            return p;
           }
 
           function addWindow(target, name) {
-            var win = target.contentWindow.open(contexts[name], name);
+            return content.SpecialPowers.spawn(
+              target,
+              [name, contexts[name]],
+              (name, context) => {
+                let win = this.content.open(context, name);
+                let bc = win && win.docShell.browsingContext;
 
-            return new Promise(resolve =>
-              target.contentWindow.addEventListener("message", () =>
-                resolve(win)
-              )
+                return new Promise(resolve =>
+                  this.content.addEventListener("message", () => resolve(bc))
+                );
+              }
             );
           }
 
           // Generate all lists of length length with every combination of
           // values in input
           function* generate(input, length) {
             let list = new Array(length);
 
@@ -98,29 +110,32 @@ add_task(async function() {
           // context, five nested, one top level auxiliary with an
           // opener. Given that set of related browsing contexts we
           // wish to confirm that targeting is semantically equivalent
           // with how nsIDocShellTreeItem.findItemWithName works. The
           // trick to ensure that is to give all frames the same name!
           // and ensure that the find algorithms return the same nodes
           // in the same order.
 
-          function bc(frame) {
-            return (frame.contentWindow || frame).docShell.browsingContext;
-          }
-
           let first = await addFrame(top, "first");
           let second = await addFrame(top, "second");
           let third = await addFrame(first, "third");
           let fourth = await addFrame(first, "fourth");
           let fifth = await addFrame(fourth, "fifth");
           let sixth = await addWindow(fourth, "sixth");
 
-          let frames = [top, first, second, third, fourth, fifth, sixth];
-          let browsingContexts = frames.map(bc);
+          let browsingContexts = [
+            BrowsingContext.getFromWindow(top),
+            first,
+            second,
+            third,
+            fourth,
+            fifth,
+            sixth,
+          ];
           let docShells = browsingContexts.map(context => context.docShell);
 
           ok(
             top.docShell instanceof Ci.nsIDocShellTreeItem,
             "When we remove nsIDocShellTreeItem this test should be removed"
           );
 
           // For every browsing context we generate all possible
@@ -133,34 +148,40 @@ add_task(async function() {
 
             for (let i = 0; i < docShells.length; ++i) {
               let docShell = docShells[i].findItemWithName(
                 "target",
                 null,
                 null,
                 false
               );
-              let browsingContext = browsingContexts[i].findWithName("target");
+              let browsingContext = browsingContexts[i].findWithName(
+                "target",
+                browsingContexts[i]
+              );
               is(
                 docShell ? docShell.browsingContext : null,
                 browsingContext,
                 "findItemWithName should find same browsing context as findWithName"
               );
             }
           }
 
           for (let target of ["_self", "_top", "_parent", "_blank"]) {
             for (let i = 0; i < docShells.length; ++i) {
               let docShell = docShells[i].findItemWithName(
                 target,
                 null,
                 null,
                 false
               );
-              let browsingContext = browsingContexts[i].findWithName(target);
+              let browsingContext = browsingContexts[i].findWithName(
+                target,
+                browsingContexts[i]
+              );
               is(
                 docShell ? docShell.browsingContext : null,
                 browsingContext,
                 "findItemWithName should find same browsing context as findWithName for " +
                   target
               );
             }
           }
--- a/docshell/test/chrome/bug113934_window.xul
+++ b/docshell/test/chrome/bug113934_window.xul
@@ -43,20 +43,20 @@
     "data:text/html,<html><body onbeforeunload='document.documentElement.textContent = \"\"' onunload='document.documentElement.textContent = \"\"' onpagehide='document.documentElement.textContent = \"\"'>This is a test</body></html>";
     var doc2 = "data:text/html,<html><head></head><body>This is a second test</body></html>";
 
 
     $("f1").setAttribute("src", doc1);
     $("f2").setAttribute("src", doc2);
     $("f3").setAttribute("src", doc2);
 
-    function doTheTest() {
-      var s1 = snapshotWindow($("f1").contentWindow);
-      var s2 = snapshotWindow($("f2").contentWindow);
-      var s3 = snapshotWindow($("f3").contentWindow);
+    async function doTheTest() {
+      var s1 = await snapshotWindow($("f1").contentWindow);
+      var s2 = await snapshotWindow($("f2").contentWindow);
+      var s3 = await snapshotWindow($("f3").contentWindow);
 
       // This test is broken - see bug 1090274
       //ok(!compareSnapshots(s2, s3, true)[0],
       //   "Should look different due to different sizing");
 
       function getDOM(id) {
         return $(id).contentDocument.documentElement.innerHTML;
       }
@@ -81,17 +81,17 @@
       // first DOMLinkAdded event (which is a result of the actual addition)
       // is dispatched, the docshells are swapped and the pageshow and pagehide
       // events are tested. Only then, we wait for the DOMLink* events,
       // which are a result of swapping the docshells.
       var DOMLinkListener = {
         _afterFirst: false,
         _removedDispatched: false,
         _addedDispatched: false,
-        handleEvent: function(aEvent) {
+        handleEvent: async function(aEvent) {
           if (!this._afterFirst) {
             is(aEvent.type, "DOMLinkAdded");
 
             var strs = { "f1": "", "f3" : "" };
             function attachListener(node, type) {
               var listener = function(e) {
                 if (strs[node.id]) strs[node.id] += " ";
                 strs[node.id] += node.id + ".page" + type;
@@ -115,17 +115,17 @@
             l1.detach();
             l2.detach();
             l3.detach();
             l4.detach();
 
             // swapDocShells reflows asynchronously, ensure layout is
             // clean so that the viewport of f1 is the right size.
             $("f1").getBoundingClientRect();
-            var s1_new = snapshotWindow($("f1").contentWindow);
+            var s1_new = await snapshotWindow($("f1").contentWindow);
             var [same, first, second] = compareSnapshots(s1_new, s2, true);
             ok(same, "Should reflow on swap. Expected " + second + " but got " + first);
 
             is(strs["f1"], "f1.pagehide f1.pageshow");
             is(strs["f3"], "f3.pagehide f3.pageshow");
             this._afterFirst = true;
             return;
           }
--- a/docshell/test/chrome/bug293235_window.xul
+++ b/docshell/test/chrome/bug293235_window.xul
@@ -1,47 +1,36 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 
 <window id="293235Test"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         width="600"
         height="600"
-        onload="setTimeout(nextTest, 0);"
+        onload="setTimeout(runTests, 0);"
         title="bug 293235 test">
 
   <script src="chrome://mochikit/content/tests/SimpleTest/ChromePowers.js"/>
   <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
   <script type="application/javascript" src="docshell_helpers.js" />
   <script src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
 
   <script type="application/javascript"><![CDATA[
     var {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
 
-    // Define the generator-iterator for the tests.
-    var tests = testIterator();
-
-    ////
-    // Execute the next test in the generator function.
-    //
-    function nextTest() {
-      tests.next();
-    }
-
     // Return the Element object for the specified element id
     function $(id) { return TestWindow.getDocument().getElementById(id); }
 
     ////
     // Generator function for test steps for bug 293235:
     // A visited link should have the :visited style applied
     // to it when displayed on a page which was fetched from
     // the bfcache.
     //
-    function* testIterator()
-    {
+    async function runTests() {
       // Register our observer to know when the link lookup is complete.
       let testURI = NetUtil.newURI(getHttpUrl("bug293235_p2.html"));
       let os = Cc["@mozilla.org/observer-service;1"].
                getService(Ci.nsIObserverService);
       const URI_VISITED_RESOLUTION_TOPIC = "visited-status-resolution";
       let observer = {
         notified: false,
         observe: function(aSubject, aTopic, aData)
@@ -58,94 +47,97 @@
       };
       os.addObserver(observer, URI_VISITED_RESOLUTION_TOPIC);
       function notified() {
         return observer.notified;
       }
 
       // Load a test page containing a link that should be initially
       // blue, per the :link style.
-      doPageNavigation({
-        uri: getHttpUrl("bug293235.html"),
-        onNavComplete: nextTest
+      await new Promise(resolve => {
+        doPageNavigation({
+          uri: getHttpUrl("bug293235.html"),
+          onNavComplete: resolve,
+        });
       });
-      yield undefined;
 
       // Before we go any further, make sure our link has been notified.
-      waitForTrue(notified, nextTest);
-      yield undefined;
+      await new Promise(resolve => {
+        waitForTrue(notified, resolve);
+      });
 
       // Now that we've been notified, we can check our link color.
       // Since we can't use getComputedStyle() for this because
       // getComputedStyle lies about styles that result from :visited,
       // we have to take snapshots.
       // First, take two reference snapshots.
       var link1 = $("link1");
       link1.className = "forcelink";
-      var refLink = snapshotWindow(TestWindow.getWindow());
+      var refLink = await snapshotWindow(TestWindow.getWindow());
       link1.className = "forcevisited";
-      var refVisited = snapshotWindow(TestWindow.getWindow());
+      var refVisited = await snapshotWindow(TestWindow.getWindow());
       link1.className = "";
       function snapshotsEqual(snap1, snap2) {
         return compareSnapshots(snap1, snap2, true)[0];
       }
       ok(!snapshotsEqual(refLink, refVisited), "references should not match");
-      ok(snapshotsEqual(refLink, snapshotWindow(TestWindow.getWindow())),
+      ok(snapshotsEqual(refLink, await snapshotWindow(TestWindow.getWindow())),
          "link should initially be blue");
 
       let observedVisit = false, observedPageShow = false;
-      function maybeRunNextTest() {
-        ok(true, "maybe run next test? visited: " + observedVisit + " pageShow: " + observedPageShow);
-        if (observedVisit && observedPageShow)
-          nextTest();
-      }
+      await new Promise(resolve => {
+        function maybeResolve() {
+          ok(true, "maybe run next test? visited: " + observedVisit + " pageShow: " + observedPageShow);
+          if (observedVisit && observedPageShow)
+            resolve();
+        }
 
-      // Because adding visits is async, we will not be notified imemdiately.
-      let visitObserver = {
-        observe: function(aSubject, aTopic, aData)
-        {
-          if (!testURI.equals(aSubject.QueryInterface(Ci.nsIURI))) {
-            return;
+        // Because adding visits is async, we will not be notified imemdiately.
+        let visitObserver = {
+          observe: function(aSubject, aTopic, aData)
+          {
+            if (!testURI.equals(aSubject.QueryInterface(Ci.nsIURI))) {
+              return;
+            }
+            os.removeObserver(this, aTopic);
+            observedVisit = true;
+            maybeResolve();
+          },
+        };
+        os.addObserver(visitObserver, "uri-visit-saved");
+        // Load the page that the link on the previous page points to.
+        doPageNavigation({
+          uri: getHttpUrl("bug293235_p2.html"),
+          onNavComplete: function() {
+            observedPageShow = true;
+            maybeResolve();
           }
-          os.removeObserver(this, aTopic);
-          observedVisit = true;
-          maybeRunNextTest();
-        },
-      };
-      os.addObserver(visitObserver, "uri-visit-saved");
-      // Load the page that the link on the previous page points to.
-      doPageNavigation({
-        uri: getHttpUrl("bug293235_p2.html"),
-        onNavComplete: function() {
-          observedPageShow = true;
-          maybeRunNextTest();
-        }
-      });
-      yield undefined;
+        });
+      })
 
       // And the nodes get notified after the "uri-visit-saved" topic, so
       // we need to execute soon...
-      SimpleTest.executeSoon(nextTest);
-      yield undefined;
+      await new Promise(SimpleTest.executeSoon);
 
       // Go back, verify the original page was loaded from the bfcache,
       // and verify that the link is now purple, per the
       // :visited style.
-      doPageNavigation({
-        back: true,
-        eventsToListenFor: ["pageshow"],
-        expectedEvents: [ { type: "pageshow",
-                            persisted: true,
-                            title: "Bug 293235 page1" } ],
-        onNavComplete: nextTest
-      });
-      yield undefined;
+      await new Promise(resolve => {
+        doPageNavigation({
+          back: true,
+          eventsToListenFor: ["pageshow"],
+          expectedEvents: [ { type: "pageshow",
+                              persisted: true,
+                              title: "Bug 293235 page1" } ],
+          onNavComplete: resolve,
+        });
+      })
 
       // Now we can test the link color.
-      ok(snapshotsEqual(refVisited, snapshotWindow(TestWindow.getWindow())),
+      ok(snapshotsEqual(refVisited, await snapshotWindow(TestWindow.getWindow())),
          "visited link should be purple");
 
       // Tell the framework the test is finished.
       finish();
     }
 
   ]]></script>
 
--- a/docshell/test/chrome/bug89419_window.xul
+++ b/docshell/test/chrome/bug89419_window.xul
@@ -1,77 +1,67 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 
 <window id="89419Test"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         width="600"
         height="600"
-        onload="setTimeout(nextTest, 0);"
+        onload="setTimeout(runTests, 0);"
         title="bug 89419 test">
 
   <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
   <script src="chrome://mochikit/content/tests/SimpleTest/ChromePowers.js"/>
   <script type="application/javascript" src="docshell_helpers.js" />
   <script src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
 
   <script type="application/javascript"><![CDATA[
-    // Define the generator-iterator for the tests.
-    var tests = testIterator();
-
     ////
-    // Execute the next test in the generator function.
-    //
-    function nextTest() {
-      tests.next();
-    }
-
-    ////
-    // Generator function for test steps for bug 89419:
     // A visited link should have the :visited style applied
     // to it when displayed on a page which was fetched from
     // the bfcache.
     //
-    function* testIterator()
-    {
+    async function runTests() {
       // Disable rcwn to make cache behavior deterministic.
-      var SpecialPowers = window.opener.wrappedJSObject.SpecialPowers;
-      SpecialPowers.pushPrefEnv({"set":[["network.http.rcwn.enabled", false]]}, nextTest);
-      yield undefined;
+      var {SpecialPowers} = opener;
+      await SpecialPowers.pushPrefEnv({"set":[["network.http.rcwn.enabled", false]]});
 
       // Load a test page containing an image referring to the sjs that returns
       // a different redirect every time it's loaded.
-      doPageNavigation({
-        uri: getHttpUrl("89419.html"),
-        onNavComplete: nextTest,
-        preventBFCache: true
-      });
-      yield undefined;
+      await new Promise(resolve => {
+        doPageNavigation({
+          uri: getHttpUrl("89419.html"),
+          onNavComplete: resolve,
+          preventBFCache: true,
+        });
+      })
 
-      var first = snapshotWindow(TestWindow.getWindow());
+      var first = await snapshotWindow(TestWindow.getWindow());
 
-      doPageNavigation({
-        uri: "about:blank",
-        onNavComplete: nextTest
+      await new Promise(resolve => {
+        doPageNavigation({
+          uri: "about:blank",
+          onNavComplete: resolve,
+        });
       });
-      yield undefined;
 
-      var second = snapshotWindow(TestWindow.getWindow());
+      var second = await snapshotWindow(TestWindow.getWindow());
       function snapshotsEqual(snap1, snap2) {
         return compareSnapshots(snap1, snap2, true)[0];
       }
       ok(!snapshotsEqual(first, second), "about:blank should not be the same as the image web page");
 
-      doPageNavigation({
-        back: true,
-        onNavComplete: nextTest
+      await new Promise(resolve => {
+        doPageNavigation({
+          back: true,
+          onNavComplete: resolve,
+        });
       });
-      yield undefined;
 
-      var third = snapshotWindow(TestWindow.getWindow());
+      var third = await snapshotWindow(TestWindow.getWindow());
       ok(!snapshotsEqual(third, second), "going back should not be the same as about:blank");
       ok(snapshotsEqual(first, third), "going back should be the same as the initial load");
 
       // Tell the framework the test is finished.
       finish();
     }
 
   ]]></script>
--- a/docshell/test/mochitest/mochitest.ini
+++ b/docshell/test/mochitest/mochitest.ini
@@ -69,19 +69,19 @@ support-files =
 skip-if = true
 # Disabled for too many intermittent failures (bug 719186)
 [test_bug475636.html]
 [test_bug509055.html]
 [test_bug511449.html]
 skip-if = toolkit != "cocoa" || headless # Headless: bug 1410525
 support-files = file_bug511449.html
 [test_bug529119-1.html]
-fail-if = fission
+skip-if = fission # Times out in weird ways.
 [test_bug529119-2.html]
-fail-if = fission
+skip-if = fission # Times out in weird ways.
 [test_bug530396.html]
 support-files = bug530396-noref.sjs bug530396-subframe.html
 [test_bug540462.html]
 skip-if = toolkit == 'android' && debug && !is_fennec
 [test_bug551225.html]
 [test_bug570341.html]
 skip-if = (verify && !debug && (os == 'win'))
 [test_bug580069.html]
--- a/docshell/test/mochitest/test_bug598895.html
+++ b/docshell/test/mochitest/test_bug598895.html
@@ -22,22 +22,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(function() {
 var win1 = window.open();
 win1.document.body.textContent = "Should show";
 
 var windowsLoaded = 0;
 
-window.onmessage = function(ev) {
+window.onmessage = async function(ev) {
   is(ev.data, "loaded", "Message should be 'loaded'");
   if (++windowsLoaded == 2) {
-    var one = snapshotWindow(win1);
-    var two = snapshotWindow(win2);
-    var three = snapshotWindow(win3);
+    var one = await snapshotWindow(win1);
+    var two = await snapshotWindow(win2);
+    var three = await snapshotWindow(win3);
     win1.close();
     win2.close();
     win3.close();
     ok(compareSnapshots(one, two, true)[0], "Popups should look identical");
     ok(compareSnapshots(one, three, false)[0], "Popups should not look identical");
 
     SimpleTest.finish();
   }
--- a/docshell/test/mochitest/test_bug637644.html
+++ b/docshell/test/mochitest/test_bug637644.html
@@ -22,22 +22,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(function() {
 var win1 = window.open("", "", "height=500,width=500");
 win1.document.body.textContent = "Should show";
 
 var windowsLoaded = 0;
 
-window.onmessage = function(ev) {
+window.onmessage = async function(ev) {
   is(ev.data, "loaded", "Message should be 'loaded'");
   if (++windowsLoaded == 2) {
-    var one = snapshotWindow(win1);
-    var two = snapshotWindow(win2);
-    var three = snapshotWindow(win3);
+    var one = await snapshotWindow(win1);
+    var two = await snapshotWindow(win2);
+    var three = await snapshotWindow(win3);
     win1.close();
     win2.close();
     win3.close();
     ok(compareSnapshots(one, two, true)[0], "Popups should look identical");
     ok(compareSnapshots(one, three, false)[0], "Popups should not look identical");
 
     SimpleTest.finish();
   }
--- a/docshell/test/navigation/mochitest.ini
+++ b/docshell/test/navigation/mochitest.ini
@@ -52,54 +52,54 @@ support-files =
   file_bug1364364-1.html
   file_bug1364364-2.html
   file_bug1375833.html
   file_bug1375833-frame1.html
   file_bug1375833-frame2.html
   test_bug145971.html
 
 [test_bug13871.html]
-fail-if = fission
-skip-if = fission && debug # Times out.
+skip-if = fission # Times out.
 [test_bug270414.html]
-fail-if = fission
+skip-if =
+  fission || # Times out.
+  fission && debug # Crashes in automation: @ mozilla::dom::ContentProcessManager::GetContentProcessById(mozilla::dom::IdType<mozilla::dom::ContentParent> const&)
 [test_bug278916.html]
 [test_bug279495.html]
 [test_bug344861.html]
 skip-if = toolkit == "android" || toolkit == "windows" # disabled on Windows because of bug 1234520
 [test_bug386782.html]
 [test_bug430624.html]
 [test_bug430723.html]
 skip-if = (toolkit == 'android') || (!debug && (os == 'mac' || os == 'win')) # Bug 874423
 [test_bug1364364.html]
 [test_bug1375833.html]
 [test_child.html]
-fail-if = fission
+skip-if = fission # Times out.
 [test_grandchild.html]
-fail-if = fission
 skip-if = fission && (debug || asan) # Causes shutdown leaks under Fission.
+fail-if = fission
 [test_not-opener.html]
-fail-if = fission
-skip-if = fission && debug # Times out
+skip-if = fission # Times out.
 [test_opener.html]
-skip-if = fission && debug # Times out
+skip-if = fission # Times out.
 [test_popup-navigates-children.html]
-fail-if = fission
+skip-if = fission # Times out.
 [test_reserved.html]
-skip-if = 
+skip-if =
   (toolkit == 'android') || (debug && e10s) || (os == 'mac' && os_version == '10.14') || #too slow on Android 4.3 aws only; bug 1030403; bug 1263213 for debug e10s, macosx1014 due to 1548821
-  (fission && !debug) #Bug 1570953
+  fission # Times out.
 [test_performance_navigation.html]
 [test_sessionhistory.html]
 skip-if =
   toolkit == 'android' || # RANDOM on android
   (fission && debug) # Intermittent timeouts
 support-files = file_bug1379762-1.html
 [test_sibling-matching-parent.html]
-fail-if = fission
+skip-if = fission # Times out.
 [test_sibling-off-domain.html]
 skip-if =
   fission || # Times out.
   fission && debug # Crashes: @ mozilla::dom::ContentParent::CommonCreateWindow(mozilla::dom::PBrowserParent*, bool, unsigned int const&, bool const&, bool const&, bool const&, nsIURI*, nsTString<char> const&, float const&, unsigned long, nsTString<char16_t> const&, nsresult&, nsCOMPtr<nsIRemoteTab>&, bool*, int&, nsIPrincipal*, nsIReferrerInfo*, bool, nsIContentSecurityPolicy*)
 [test_triggeringprincipal_frame_nav.html]
 [test_triggeringprincipal_window_open.html]
 [test_triggeringprincipal_parent_iframe_window_open.html]
 [test_triggeringprincipal_iframe_iframe_window_open.html]
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -4034,17 +4034,17 @@ Nullable<WindowProxyHolder> nsGlobalWind
   BrowsingContext* bc = GetBrowsingContext();
   return bc ? bc->GetTop(IgnoreErrors()) : nullptr;
 }
 
 already_AddRefed<BrowsingContext> nsGlobalWindowOuter::GetChildWindow(
     const nsAString& aName) {
   NS_ENSURE_TRUE(mBrowsingContext, nullptr);
 
-  return do_AddRef(mBrowsingContext->FindChildWithName(aName));
+  return do_AddRef(mBrowsingContext->FindChildWithName(aName, *mBrowsingContext));
 }
 
 bool nsGlobalWindowOuter::DispatchCustomEvent(const nsAString& aEventName) {
   bool defaultActionEnabled = true;
   nsContentUtils::DispatchTrustedEvent(mDoc, ToSupports(this), aEventName,
                                        CanBubble::eYes, Cancelable::eYes,
                                        &defaultActionEnabled);
 
@@ -6327,16 +6327,18 @@ void nsGlobalWindowOuter::ForceClose() {
 
   FinalClose();
 }
 
 void nsGlobalWindowOuter::FinalClose() {
   // Flag that we were closed.
   mIsClosed = true;
 
+  GetBrowsingContext()->SetClosed(true);
+
   // If we get here from CloseOuter then it means that the parent process is
   // going to close our window for us. It's just important to set mIsClosed.
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     return;
   }
 
   // This stuff is non-sensical but incredibly fragile. The reasons for the
   // behavior here don't make sense today and may not have ever made sense,
--- a/dom/base/test/file_bug326337_inner.html
+++ b/dom/base/test/file_bug326337_inner.html
@@ -16,25 +16,29 @@ runTest();
 var xhr;
 
 function runTest() {
   xhr = new XMLHttpRequest();
   xhr.open("GET", "file_bug326337.xml", true);
   xhr.onreadystatechange = function() {
     if (xhr.readyState == 4) {
       check(xhr.responseXML.documentElement.getAttribute("root"));
-      SpecialPowers.wrap(parent).location.hash = "#done";
+      SpecialPowers.spawn(parent, [], () => {
+        content.location.hash = "#done";
+      });
     }
   }
   xhr.send(null);
 }
 
 function check(attr) {
   if (attr != "yes") {
-    SpeciaPowers.wrap(parent).location.hash = "#fail";
+    SpecialPowers.spawn(parent, [], () => {
+      content.location.hash = "#fail";
+    });
     throw 1;
   }
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -305,23 +305,21 @@ skip-if = toolkit == 'android' || headle
 [test_bug282547.html]
 [test_bug298064.html]
 [test_bug300992.html]
 [test_bug311681.xml]
 [test_bug313646.html]
 [test_bug320799.html]
 [test_bug322317.html]
 [test_bug326337.html]
-fail-if = fission
 skip-if = fission && debug # Crashes: @ std::_Function_handler<void (mozilla::Tuple<nsresult, mozilla::dom::PBrowserBridgeParent*>&&), mozilla::dom::WindowGlobalParent::ChangeFrameRemoteness(mozilla::dom::BrowsingContext*, nsTSubstring<char16_t> const&, unsigned long, mozilla::ErrorResult&)::$_2>::_M_invoke(std::_Any_data const&, mozilla::Tuple<nsresult, mozilla::dom::PBrowserBridgeParent*>&&)
 [test_bug330925.xhtml]
 [test_bug331959.html]
-skip-if = fission
 [test_bug333064.html]
-skip-if = fission || toolkit == 'android' || headless # Headless: Bug 1405868
+skip-if = toolkit == 'android' || headless # Headless: Bug 1405868
 [test_bug333198.html]
 [test_bug333673.html]
 [test_bug337631.html]
 [test_bug338541.xhtml]
 [test_bug338583.html]
 skip-if = toolkit == 'android'
 [test_bug338679.html]
 [test_bug339494.html]
@@ -486,17 +484,16 @@ skip-if = (os == "android") # Failure wi
 [test_bug574596.html]
 skip-if = toolkit == 'android'
 [test_bug578096.html]
 skip-if = (verify && (os == 'win'))
 [test_bug585978.html]
 [test_bug587931.html]
 [test_bug588990.html]
 [test_bug590812.html]
-fail-if = fission
 skip-if = toolkit == 'android' || (verify && !debug && (os == 'linux')) #bug 687032
 [test_bug590870.html]
 skip-if = fission # Crashes: @ mozilla::dom::ContentParent::RecvDetachBrowsingContext(unsigned long, std::function<void (bool const&)>&&)
 [test_bug592366.html]
 [test_bug592829.html]
 [test_bug597345.html]
 [test_bug599295.html]
 [test_bug599588.html]
@@ -588,17 +585,17 @@ skip-if = fission # Crashes: @ mozilla::
 [test_bug902847.html]
 [test_bug907892.html]
 fail-if = fission
 [test_bug913761.html]
 [test_bug922681.html]
 [test_bug927196.html]
 [test_bug962251.html]
 [test_bug976673.html]
-fail-if = fission
+skip-if = fission # Times out in weird ways.
 [test_bug982153.html]
 [test_bug999456.html]
 [test_bug1022229.html]
 [test_bug1025933.html]
 [test_bug1037687.html]
 support-files = test_bug1037687_subframe.html
 [test_bug1043106.html]
 [test_bug1057176.html]
@@ -831,17 +828,16 @@ support-files =
 [test_setInterval_from_start.html]
 [test_setInterval_uncatchable_exception.html]
 skip-if = debug == false
 [test_settimeout_extra_arguments.html]
 [test_settimeout_inner.html]
 [test_setTimeoutWith0.html]
 [test_setting_opener.html]
 [test_shared_compartment1.html]
-fail-if = fission
 [test_shared_compartment2.html]
 fail-if = fission
 [test_structuredclone_backref.html]
 [test_style_cssText.html]
 [test_text_wholeText.html]
 [test_textnode_normalize_in_selection.html]
 [test_textnode_split_in_selection.html]
 [test_timeout_clamp.html]
@@ -877,12 +873,12 @@ fail-if = fission
 [test_window_extensible.html]
 [test_window_indexing.html]
 [test_window_keys.html]
 [test_window_named_frame_enumeration.html]
 [test_window_own_props.html]
 [test_window_proto.html]
 [test_writable-replaceable.html]
 [test_x-frame-options.html]
-fail-if = fission
+fail-if = fission # Cross-origin X-Frame-Options
 skip-if = toolkit == 'android' && debug && !is_fennec
 [test_youtube_flash_embed.html]
 # Please keep alphabetical order.
--- a/dom/base/test/test_bug1101364.html
+++ b/dom/base/test/test_bug1101364.html
@@ -21,46 +21,46 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body id='body'>
 
 <iframe id="test1" srcdoc="<h1 id='test1' style='-moz-user-select:none'>Header</h1><div id='testDiv'>test1</div>"></iframe>
 <iframe id="test2" srcdoc="<div contenteditable id='test2'>AAA<span id='test2Inner'>BBB</span></div>"></iframe>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-function test()
+async function test()
 {
   var iframe1 = document.getElementById('test1');
   iframe1.focus();
   var docShell = SpecialPowers.wrap(iframe1.contentWindow).docShell;
 
   // test1
   docShell.doCommand("cmd_selectAll");
-  var withoutContenteditable = snapshotWindow(iframe1.contentWindow);
+  var withoutContenteditable = await snapshotWindow(iframe1.contentWindow);
 
   iframe1.contentDocument.getElementById('testDiv').setAttribute('contentEditable', true);
   docShell.doCommand("cmd_selectAll");
-  var withContenteditable = snapshotWindow(iframe1.contentWindow);
+  var withContenteditable = await snapshotWindow(iframe1.contentWindow);
   dump(withoutContenteditable.toDataURL());
   dump(withContenteditable.toDataURL());
 
   ok(compareSnapshots(withoutContenteditable, withContenteditable, true)[0], 'Select all should look identical');
 
   // test2
   var iframe2 = document.getElementById('test2');
   iframe2.focus();
   var docShell = SpecialPowers.wrap(iframe2.contentWindow).docShell;
   var test2Inner = iframe2.contentDocument.getElementById('test2Inner');
   test2Inner.style.MozUserSelect = 'text';
   docShell.doCommand("cmd_selectAll");
-  var withoutUserSelect = snapshotWindow(iframe2.contentWindow);
+  var withoutUserSelect = await snapshotWindow(iframe2.contentWindow);
 
   test2Inner.style.MozUserSelect = 'none';
   docShell.doCommand("cmd_selectAll");
-  var withUserSelect = snapshotWindow(iframe2.contentWindow);
+  var withUserSelect = await snapshotWindow(iframe2.contentWindow);
   ok(compareSnapshots(withoutUserSelect, withUserSelect, true)[0], 'Editable fields should ignore user select style');
 
   SimpleTest.finish();
 }
 window.onload = function() { setTimeout(test, 0); };
 SimpleTest.waitForExplicitFinish();
 </script>
 </pre>
--- a/dom/base/test/test_bug590812.html
+++ b/dom/base/test/test_bug590812.html
@@ -12,20 +12,28 @@
 <iframe src="http://noxul.example.com/tests/dom/base/test/file_bug590812.xml"></iframe>
 <iframe src="file_bug590812.xml"></iframe>
 <iframe src="file_bug590812-ref.xhtml"></iframe>
 <pre id="test">
 <script class="testbody" type="application/javascript">
 
 SimpleTest.waitForExplicitFinish();
 
-function runTest() {
-  sNoXUL = snapshotWindow(window.frames[0], false);
-  sWithXUL = snapshotWindow(window.frames[1], false);
-  sRef = snapshotWindow(window.frames[2], false);
+async function runTest() {
+  // FIXME(Fission): The load event fires before cross-origin iframes have
+  // loaded (bug 1559841).
+  if (SpecialPowers.useRemoteSubframes) {
+    for (let i = 0; i < 100; i++) {
+      await new Promise(resolve => setTimeout(resolve, 0));
+    }
+  }
+
+  let sNoXUL = await snapshotWindow(window.frames[0], false);
+  let sWithXUL = await snapshotWindow(window.frames[1], false);
+  let sRef = await snapshotWindow(window.frames[2], false);
   let res;
   ok(compareSnapshots(sNoXUL, sRef, true)[0],
      "noxul domain same as ref");
   ok(compareSnapshots(sWithXUL, sRef, true)[0],
      "xul supporting domain same as ref");
 
   SimpleTest.finish();
 }
--- a/dom/base/test/test_bug682592.html
+++ b/dom/base/test/test_bug682592.html
@@ -45,21 +45,21 @@ if (navigator.platform.startsWith("Linux
 }
 
 var page = `<!DOCTYPE html>
 <html><meta charset='UTF-8'><body><p id="content"></p></body></html>`;
 var refFrame = document.getElementById("iframe-ref")
 var testFrame = document.getElementById("iframe-test");
 
 refFrame.addEventListener("load", function() {
-  testFrame.addEventListener("load", function() {
+  testFrame.addEventListener("load", async function() {
     let {done} = tests.next();
     if (!done) {
-      ok(compareSnapshots(snapshotWindow(testFrame.contentWindow), 
-                          snapshotWindow(refFrame.contentWindow), true)[0], 
+      ok(compareSnapshots(await snapshotWindow(testFrame.contentWindow), 
+                          await snapshotWindow(refFrame.contentWindow), true)[0], 
          "bidi is not detected correctly");
 
       testFrame.contentWindow.location.reload();
     } else {
       SimpleTest.finish();
     }
   });
   testFrame.srcdoc = page;
--- a/dom/base/test/test_x-frame-options.html
+++ b/dom/base/test/test_x-frame-options.html
@@ -12,102 +12,138 @@
 </div>
 
 <iframe style="width:100%;height:300px;" id="harness"></iframe>
 <script class="testbody" type="text/javascript">
 
 var path = "/tests/dom/base/test/";
 var isUnique = SpecialPowers.getBoolPref("security.data_uri.unique_opaque_origin");
 
-var testFramesLoaded = function() {
-  var harness = SpecialPowers.wrap(document).getElementById("harness");
+var testFramesLoaded = async function() {
+  var harness = document.getElementById("harness").contentDocument;
+
+  // FIXME(Fission): The load event fires before cross-origin iframes have
+  // loaded (bug 1559841).
+  if (SpecialPowers.useRemoteSubframes) {
+    for (let i = 0; i < 100; i++) {
+      await new Promise(resolve => setTimeout(resolve, 0));
+    }
+  }
 
   // iframe from same origin, no X-F-O header - should load
-  var frame = harness.contentDocument.getElementById("control1");
-  var test1 = frame.contentDocument.getElementById("test").textContent;
-  is(test1, "control1", "test control1");
+  var frame = harness.getElementById("control1");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test1 = this.content.document.getElementById("test").textContent;
+    Assert.equal(test1, "control1", "test control1");
+  });
 
   // iframe from different origin, no X-F-O header - should load
-  frame = harness.contentDocument.getElementById("control2");
-  var test2 = frame.contentDocument.getElementById("test").textContent;
-  is(test2, "control2", "test control2");
+  frame = harness.getElementById("control2");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test2 = this.content.document.getElementById("test").textContent;
+    Assert.equal(test2, "control2", "test control2");
+  });
 
   // iframe from same origin, X-F-O: DENY - should not load
-  frame = harness.contentDocument.getElementById("deny");
-  var test3 = frame.contentDocument.getElementById("test");
-  is(test3, null, "test deny");
+  frame = harness.getElementById("deny");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test3 = this.content.document.getElementById("test");
+    Assert.equal(test3, null, "test deny");
+  });
 
   // iframe from same origin, X-F-O: SAMEORIGIN - should load
-  frame = harness.contentDocument.getElementById("sameorigin1");
-  var test4 = frame.contentDocument.getElementById("test").textContent;
-  is(test4, "sameorigin1", "test sameorigin1");
+  frame = harness.getElementById("sameorigin1");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test4 = this.content.document.getElementById("test").textContent;
+    Assert.equal(test4, "sameorigin1", "test sameorigin1");
+  });
 
   // iframe from different origin, X-F-O: SAMEORIGIN - should not load
-  frame = harness.contentDocument.getElementById("sameorigin2");
-  var test5 = frame.contentDocument.getElementById("test");
-  is(test5, null, "test sameorigin2");
+  frame = harness.getElementById("sameorigin2");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test5 = this.content.document.getElementById("test");
+    Assert.equal(test5, null, "test sameorigin2");
+  });
 
   // iframe from different origin, X-F-O: SAMEORIGIN, SAMEORIGIN - should not load
-  frame = harness.contentDocument.getElementById("sameorigin5");
-  var test6 = frame.contentDocument.getElementById("test");
-  is(test6, null, "test sameorigin5");
+  frame = harness.getElementById("sameorigin5");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test6 = this.content.document.getElementById("test");
+    Assert.equal(test6, null, "test sameorigin5");
+  });
 
   // iframe from same origin, X-F-O: SAMEORIGIN, SAMEORIGIN - should load
-  frame = harness.contentDocument.getElementById("sameorigin6");
-  var test7 = frame.contentDocument.getElementById("test").textContent;
-  is(test7, "sameorigin6", "test sameorigin6");
+  frame = harness.getElementById("sameorigin6");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test7 = this.content.document.getElementById("test").textContent;
+    Assert.equal(test7, "sameorigin6", "test sameorigin6");
+  });
 
   // iframe from same origin, X-F-O: SAMEORIGIN,SAMEORIGIN, SAMEORIGIN - should load
-  frame = harness.contentDocument.getElementById("sameorigin7");
-  var test8 = frame.contentDocument.getElementById("test").textContent;
-  is(test8, "sameorigin7", "test sameorigin7");
+  frame = harness.getElementById("sameorigin7");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test8 = this.content.document.getElementById("test").textContent;
+    Assert.equal(test8, "sameorigin7", "test sameorigin7");
+  });
 
   // iframe from same origin, X-F-O: SAMEORIGIN,SAMEORIGIN, SAMEORIGIN - should not load
-  frame = harness.contentDocument.getElementById("sameorigin8");
-  var test9 = frame.contentDocument.getElementById("test");
-  is(test9, null, "test sameorigin8");
+  frame = harness.getElementById("sameorigin8");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test9 = this.content.document.getElementById("test");
+    Assert.equal(test9, null, "test sameorigin8");
+  });
 
   // iframe from same origin, X-F-O: DENY,SAMEORIGIN - should not load
-  frame = harness.contentDocument.getElementById("mixedpolicy");
-  var test10 = frame.contentDocument.getElementById("test");
-  is(test10, null, "test mixedpolicy");
+  frame = harness.getElementById("mixedpolicy");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test10 = this.content.document.getElementById("test");
+    Assert.equal(test10, null, "test mixedpolicy");
+  });
 
   // iframe from different origin, allow-from: this origin - should load
-  frame = harness.contentDocument.getElementById("allow-from-allow");
-  var test11 = frame.contentDocument.getElementById("test").textContent;
-  is(test11, "allow-from-allow", "test allow-from-allow");
+  frame = harness.getElementById("allow-from-allow");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test11 = this.content.document.getElementById("test").textContent;
+    Assert.equal(test11, "allow-from-allow", "test allow-from-allow");
+  });
 
   // iframe from different origin, with allow-from: other - should load as we no longer support allow-from (Bug 1301529)
-  frame = harness.contentDocument.getElementById("allow-from-deny");
-  var test12 = frame.contentDocument.getElementById("test");
-  isnot(test12, null, "test allow-from-deny");
+  frame = harness.getElementById("allow-from-deny");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test12 = this.content.document.getElementById("test");
+    Assert.notEqual(test12, null, "test allow-from-deny");
+  });
 
   // iframe from different origin, X-F-O: SAMEORIGIN, multipart - should not load
-  frame = harness.contentDocument.getElementById("sameorigin-multipart");
-  var test13 = frame.contentDocument.getElementById("test");
-  is(test13, null, "test sameorigin-multipart");
+  frame = harness.getElementById("sameorigin-multipart");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test13 = this.content.document.getElementById("test");
+    Assert.equal(test13, null, "test sameorigin-multipart");
+  });
 
   // iframe from same origin, X-F-O: SAMEORIGIN, multipart - should load
-  frame = harness.contentDocument.getElementById("sameorigin-multipart2");
-  var test14 = frame.contentDocument.getElementById("test").textContent;
-  is(test14, "sameorigin-multipart2", "test sameorigin-multipart2");
+  frame = harness.getElementById("sameorigin-multipart2");
+  await SpecialPowers.spawn(frame, [], () => {
+    var test14 = this.content.document.getElementById("test").textContent;
+    Assert.equal(test14, "sameorigin-multipart2", "test sameorigin-multipart2");
+  });
 
 
   // frames from bug 836132 tests, no longer supported allow-from
   {
-    frame = harness.contentDocument.getElementById("allow-from-allow-1");
+    frame = harness.getElementById("allow-from-allow-1");
     var theTestResult = frame.contentDocument.getElementById("test");
     isnot(theTestResult, null, "test afa1 should have been allowed");
     if(theTestResult) {
       is(theTestResult.textContent, "allow-from-allow-1", "test allow-from-allow-1");
     }
   }
   // Verify allow-from no longer works
   for (var i = 1; i<=14; i++) {
-    frame = harness.contentDocument.getElementById("allow-from-deny-" + i);
+    frame = harness.getElementById("allow-from-deny-" + i);
     var theTestResult = frame.contentDocument.getElementById("test");
     isnot(theTestResult, null, "test allow-from-deny-" + i);
   }
 
   // call tests to check principal comparison, e.g. a document can open a window
   // to a data: or javascript: document which frames an
   // X-Frame-Options: SAMEORIGIN document and the frame should load
   testFrameInJSURI();
--- a/dom/browser-element/mochitest/browserElement_XFrameOptionsDeny.js
+++ b/dom/browser-element/mochitest/browserElement_XFrameOptionsDeny.js
@@ -34,25 +34,25 @@ function runTest() {
   iframe.setAttribute("mozbrowser", "true");
 
   // Our child will create two iframes, so make sure this iframe is big enough
   // to show both of them without scrolling, so taking a screenshot gets both
   // frames.
   iframe.height = "1000px";
 
   var step1, stepfinish;
-  iframe.addEventListener("mozbrowsershowmodalprompt", function(e) {
+  iframe.addEventListener("mozbrowsershowmodalprompt", async function(e) {
     switch (e.detail.message) {
       case "step 1":
-        step1 = SpecialPowers.snapshotWindow(iframe.contentWindow);
+        step1 = await SpecialPowers.snapshotWindow(iframe.contentWindow);
         break;
       case "step 2":
         // The page has now attempted to load the X-Frame-Options page; take
         // another screenshot.
-        stepfinish = SpecialPowers.snapshotWindow(iframe.contentWindow);
+        stepfinish = await SpecialPowers.snapshotWindow(iframe.contentWindow);
         ok(
           step1.toDataURL() == stepfinish.toDataURL(),
           "Screenshots should be identical"
         );
         SimpleTest.finish();
         break;
     }
   });
--- a/dom/canvas/test/test_bitmaprenderer.html
+++ b/dom/canvas/test/test_bitmaprenderer.html
@@ -47,33 +47,33 @@ function runTest(canvasWidth, canvasHeig
   var ctx = canvasRef.getContext("2d");
   // Clear with black transparent first
   ctx.fillStyle = "rgba(0, 0, 0, 0)";
   ctx.fillRect(0, 0, 90, 90);
 
   ctx.fillStyle = "#00FF00";
   ctx.fillRect(0, 0, canvasWidth, canvasHeight);
 
-  createImageBitmap(canvas1).then(function(bmp) {
+  createImageBitmap(canvas1).then(async function(bmp) {
     document.body.removeChild(canvas1);
 
     var canvas2 = createCanvas(90, 90);
     var ctx2 = canvas2.getContext("bitmaprenderer");
     ctx2.transferFromImageBitmap(bmp);
 
     ok(canvasRef.toDataURL() == canvas2.toDataURL(), "toDataURL should return same result.");
 
     // Exam render result
     canvasRef.style.display = "none";
     canvas2.style.display = "block";
-    var snapshot = snapshotWindow(window);
+    var snapshot = await snapshotWindow(window);
 
     canvasRef.style.display = "block";
     canvas2.style.display = "none";
-    var snapshotRef = snapshotWindow(window);
+    var snapshotRef = await snapshotWindow(window);
 
     // bitmaprenderers use an ImageLayer whereas a normal 2d canvas uses a canvas layer. This
     // can result in some anti-aliasing differences on the edge. We consider slight AA differences
     // to be reasonable when using different codepaths so fuzz a little bit.
     var fuzz = { numDifferentPixels:  0,
                  maxDifference: 0 };
     if (SpecialPowers.Services.appinfo.widgetToolkit == "android") {
       fuzz.maxDifference = 2;
@@ -97,40 +97,40 @@ function scaleTest() {
 
   var canvas2 = createCanvas(64, 64);
   var ctx2 = canvas2.getContext("2d");
   ctx2.fillStyle = "#00FF00";
   ctx2.fillRect(0, 0, 64, 64);
 
   var p1 = createImageBitmap(canvas1);
   var p2 = createImageBitmap(canvas2);
-  Promise.all([p1, p2]).then(function(bitmaps) {
+  Promise.all([p1, p2]).then(async function(bitmaps) {
     document.body.removeChild(canvas1);
     document.body.removeChild(canvas2);
 
     // Create a large canvas then shrink.
     var canvas3 = createCanvas(128, 128);
     var ctx3 = canvas3.getContext("bitmaprenderer");
     ctx3.transferFromImageBitmap(bitmaps[0]);
-    var snapshotLargeRef = snapshotWindow(window);
+    var snapshotLargeRef = await snapshotWindow(window);
 
     canvas3.width = 32;
     canvas3.height = 32;
-    var snapshotSmall = snapshotWindow(window);
+    var snapshotSmall = await snapshotWindow(window);
     document.body.removeChild(canvas3);
 
     // Create a small canvas then grow.
     var canvas4 = createCanvas(32, 32);
     var ctx4 = canvas4.getContext("bitmaprenderer");
     ctx4.transferFromImageBitmap(bitmaps[1]);
-    var snapshotSmallRef = snapshotWindow(window);
+    var snapshotSmallRef = await snapshotWindow(window);
 
     canvas4.width = 128;
     canvas4.height = 128;
-    var snapshotLarge = snapshotWindow(window);
+    var snapshotLarge = await snapshotWindow(window);
     document.body.removeChild(canvas4);
 
     var resultsLarge = compareSnapshots(snapshotLarge, snapshotLargeRef, true);
     ok(resultsLarge[0], "Screenshots should be the same");
 
     var resultsSmall = compareSnapshots(snapshotSmall, snapshotSmallRef, true);
     ok(resultsSmall[0], "Screenshots should be the same");
     runTestOnWorker();
--- a/dom/canvas/test/test_offscreencanvas_dynamic_fallback.html
+++ b/dom/canvas/test/test_offscreencanvas_dynamic_fallback.html
@@ -18,47 +18,47 @@ function createCanvas(initWithMask) {
   document.body.appendChild(canvas);
   if (initWithMask) {
     canvas.style.mask = "url('offscreencanvas_mask.svg#fade_mask_both')";
   }
 
   return canvas;
 }
 
-function getRefSnapshot(initWithMask) {
+async function getRefSnapshot(initWithMask) {
   var refCanvas = createCanvas(!initWithMask);
   var ctx = refCanvas.getContext("2d");
   ctx.rect(0, 0, 64, 64);
   ctx.fillStyle = "#00FF00";
   ctx.fill();
-  var result = snapshotWindow(window);
+  var result = await snapshotWindow(window);
   document.body.removeChild(refCanvas);
   return result;
 }
 
 function runTest(initWithMask) {
   var htmlCanvas = createCanvas(initWithMask);
   var worker = new Worker("offscreencanvas.js");
 
-  worker.onmessage = function(evt) {
+  worker.onmessage = async function(evt) {
     var msg = evt.data || {};
     if (msg.type == "draw") {
       if (msg.count === 10) {
         // Change the fallback state dynamically when drawing count reaches 10.
         if (initWithMask) {
           htmlCanvas.style.mask = "";
         } else {
           htmlCanvas.style.mask = "url('offscreencanvas_mask.svg#fade_mask_both')";
         }
       } else if (msg.count === 20) {
-        var snapshotFallback = snapshotWindow(window);
         worker.terminate();
+        var snapshotFallback = await snapshotWindow(window);
         document.body.removeChild(htmlCanvas);
 
-        var results = compareSnapshots(snapshotFallback, getRefSnapshot(initWithMask), true);
+        var results = compareSnapshots(snapshotFallback, await getRefSnapshot(initWithMask), true);
         ok(results[0], "after dynamic fallback, screenshots should be the same");
 
         if (initWithMask) {
           SimpleTest.finish();
         } else {
           runTest(true);
         }
       }
--- a/dom/chrome-webidl/BrowsingContext.webidl
+++ b/dom/chrome-webidl/BrowsingContext.webidl
@@ -6,18 +6,18 @@
 interface nsIDocShell;
 
 [Exposed=Window, ChromeOnly]
 interface BrowsingContext {
   static BrowsingContext? get(unsigned long long aId);
 
   static BrowsingContext? getFromWindow(WindowProxy window);
 
-  BrowsingContext? findChildWithName(DOMString name);
-  BrowsingContext? findWithName(DOMString name);
+  BrowsingContext? findChildWithName(DOMString name, BrowsingContext accessor);
+  BrowsingContext? findWithName(DOMString name, BrowsingContext accessor);
 
   readonly attribute DOMString name;
 
   readonly attribute BrowsingContext? parent;
 
   readonly attribute BrowsingContext top;
 
   sequence<BrowsingContext> getChildren();
--- a/dom/events/test/test_bug864040.html
+++ b/dom/events/test/test_bug864040.html
@@ -24,62 +24,62 @@ https://bugzilla.mozilla.org/show_bug.cg
     /**
     * Test for Bug 864040
     *
     * We use a selection event to set the selection to the end of an editor
     * containing an ending newline. Then we test to see that the caret is
     * actually drawn on the newline.
     */
 
-    function testSelectEndOfText(elem) {
+    async function testSelectEndOfText(elem) {
       var tn = elem.tagName;
       elem.focus();
 
       // Enter test string into editor
       var test_string = 'test\n';
       sendString(test_string);
 
       // Get the caret position after what we entered
       var result = synthesizeQuerySelectedText();
       ok(result, tn + ': failed to query selection (1)');
       var refoffset = result.offset;
 
       // Take a snapshot of where the caret is (on the new line)
-      referenceSnapshot = snapshotWindow(window, true /* withCaret */);
+      referenceSnapshot = await snapshotWindow(window, true /* withCaret */);
       ok(referenceSnapshot, tn + ': failed to take snapshot (1)');
 
       // Set selection to the same spot through a selection event
       ok(synthesizeSelectionSet(refoffset, 0, false), tn + ': failed to set selection');
 
       // Make sure new selection is the same
       result = synthesizeQuerySelectedText();
       ok(result, tn + ': failed to query selection (2)');
       is(result.offset, refoffset, tn + ': caret is not at the right position');
 
       // Take a snapshot of where the new caret is (shoud still be on the new line)
-      testSnapshot = snapshotWindow(window, true /* withCaret */);
+      testSnapshot = await snapshotWindow(window, true /* withCaret */);
       ok(testSnapshot, tn + ': failed to take snapshot (2)');
 
       // Compare snapshot (should be the same)
       result = compareSnapshots(referenceSnapshot, testSnapshot, true /* expected */)
       ok(result, tn + ': failed to compare snapshots');
       // result = [correct, s1data, s2data]
       ok(result[0], tn + ': caret is not on new line');
       if (!result[0]) {
         dump('Ref: ' + result[1] + '\n');
         dump('Res: ' + result[2] + '\n');
       }
     }
 
-    function runTests() {
+    async function runTests() {
       // we don't test regular <input> because this test is about multiline support
       // test textarea
-      testSelectEndOfText(document.getElementById('ta'));
+      await testSelectEndOfText(document.getElementById('ta'));
       // test contentEditable
-      testSelectEndOfText(document.getElementById('ce'));
+      await testSelectEndOfText(document.getElementById('ce'));
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
 
     SimpleTest.waitForFocus(runTests);
   </script>
 </pre>
--- a/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html
+++ b/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html
@@ -17,40 +17,40 @@ https://bugzilla.mozilla.org/show_bug.cg
    * This test checks that setting .value on an text field (input or textarea)
    * doesn't scroll the field to its beginning.
    */
 
   SimpleTest.waitForExplicitFinish();
 
   var gTestRunner = null;
 
-  function test(aElementName)
+  async function test(aElementName)
   {
     var element = document.getElementsByTagName(aElementName)[0];
     element.focus();
 
-    var baseSnapshot = snapshotWindow(window);
+    var baseSnapshot = await snapshotWindow(window);
 
     // This is a sanity check.
-    var s2 = snapshotWindow(window);
-    var results = compareSnapshots(baseSnapshot, snapshotWindow(window), true);
+    var s2 = await snapshotWindow(window);
+    var results = compareSnapshots(baseSnapshot, await snapshotWindow(window), true);
     ok(results[0], "sanity check: screenshots should be the same");
 
     element.selectionStart = element.selectionEnd = element.value.length;
 
     setTimeout(function() {
       sendString('f');
 
-      requestAnimationFrame(function() {
-        var selectionAtTheEndSnapshot = snapshotWindow(window);
+      requestAnimationFrame(async function() {
+        var selectionAtTheEndSnapshot = await snapshotWindow(window);
         results = compareSnapshots(baseSnapshot, selectionAtTheEndSnapshot, false);
         ok(results[0], "after appending a character, string should have changed");
 
         element.value = element.value;
-        var tmpSnapshot = snapshotWindow(window);
+        var tmpSnapshot = await snapshotWindow(window);
 
         results = compareSnapshots(baseSnapshot, tmpSnapshot, false);
         ok(results[0], "re-settig the value should change nothing");
 
         results = compareSnapshots(selectionAtTheEndSnapshot, tmpSnapshot, true);
         ok(results[0], "re-settig the value should change nothing");
 
         element.selectionStart = element.selectionEnd = 0;
@@ -58,36 +58,36 @@ https://bugzilla.mozilla.org/show_bug.cg
 
         gTestRunner.next();
       });
     }, 0);
   }
 
   // This test checks that when a textarea has a long list of values and the
   // textarea's value is then changed, the values are shown correctly.
-  function testCorrectUpdateOnScroll()
+  async function testCorrectUpdateOnScroll()
   {
     var textarea = document.createElement('textarea');
     textarea.rows = 5;
     textarea.cols = 10;
     textarea.value = 'a\nb\nc\nd';
     document.getElementById('content').appendChild(textarea);
 
-    var baseSnapshot = snapshotWindow(window);
+    var baseSnapshot = await snapshotWindow(window);
 
     textarea.value = '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n';
     textarea.selectionStart = textarea.selectionEnd = textarea.value.length;
 
-    var fullSnapshot = snapshotWindow(window);
+    var fullSnapshot = await snapshotWindow(window);
     var results = compareSnapshots(baseSnapshot, fullSnapshot, false);
     ok(results[0], "sanity check: screenshots should not be the same");
 
     textarea.value = 'a\nb\nc\nd';
 
-    var tmpSnapshot = snapshotWindow(window);
+    var tmpSnapshot = await snapshotWindow(window);
     results = compareSnapshots(baseSnapshot, tmpSnapshot, true);
     ok(results[0], "textarea view should look like the beginning");
 
     setTimeout(function() {
       gTestRunner.next();
     }, 0);
   }
 
--- a/dom/html/test/test_bug611189.html
+++ b/dom/html/test/test_bug611189.html
@@ -15,31 +15,31 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 611189 **/
 SimpleTest.waitForExplicitFinish();
-addLoadEvent(function() {
+addLoadEvent(async function() {
   var i = document.createElement("input");
   var b = document.getElementById("content");
   b.appendChild(i);
   b.clientWidth; // bind to frame
   i.focus(); // initialize editor
-  var before = snapshotWindow(window, true);
+  var before = await snapshotWindow(window, true);
   i.value = "L"; // set the value
   i.style.display = "none";
   b.clientWidth; // unbind from frame
   i.value = ""; // set the value without a frame
   i.style.display = "";
   b.clientWidth; // rebind to frame
   is(i.value, "", "Input's value should be correctly updated");
-  var after = snapshotWindow(window, true);
+  var after = await snapshotWindow(window, true);
   ok(compareSnapshots(before, after, true), "The correct value should be rendered inside the control");
   SimpleTest.finish();
 });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/ipc/DOMTypes.ipdlh
+++ b/dom/ipc/DOMTypes.ipdlh
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
 /* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include "mozilla/GfxMessageUtils.h";
+include "mozilla/dom/DocShellMessageUtils.h";
 include "mozilla/layers/LayersMessageUtils.h";
 
 include IPCBlob;
 include IPCStream;
 include ProtocolTypes;
 
 using struct mozilla::void_t
   from "ipc/IPCMessageUtils.h";
--- a/dom/ipc/PWindowGlobal.ipdl
+++ b/dom/ipc/PWindowGlobal.ipdl
@@ -1,24 +1,27 @@
 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
 /* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+include "mozilla/dom/DocShellMessageUtils.h";
+
 include protocol PBrowser;
 include protocol PInProcess;
 include protocol PBrowserBridge;
 
 include DOMTypes;
 
 using JSWindowActorMessageKind from "mozilla/dom/JSWindowActor.h";
 using mozilla::gfx::IntRect from "mozilla/gfx/Rect.h";
 using moveonly mozilla::gfx::PaintFragment from "mozilla/gfx/CrossProcessPaint.h";
 using nscolor from "nsColor.h";
+using refcounted class nsDocShellLoadState from "nsDocShellLoadState.h";
 
 namespace mozilla {
 namespace dom {
 
 struct JSWindowActorMessageMeta {
   nsString actorName;
   nsString messageName;
   uint64_t queryId;
@@ -45,20 +48,27 @@ child:
 
   async DrawSnapshot(IntRect? aRect, float aScale, nscolor aBackgroundColor, uint32_t aFlags) returns (PaintFragment retval);
 
   /**
    * Returns the serialized security info associated with this window.
    */
   async GetSecurityInfo() returns(nsCString? serializedSecInfo);
 
+  async LoadURIInChild(nsDocShellLoadState aLoadState);
+
 both:
   async RawMessage(JSWindowActorMessageMeta aMetadata, ClonedMessageData aData);
 
 parent:
+  // Load the given URI load state into the current owner process of the given
+  // BrowsingContext. aTargetBC must be in the same BrowsingContextGroup as this
+  // window global.
+  async LoadURI(BrowsingContext aTargetBC, nsDocShellLoadState aLoadState);
+
   /// Update the URI of the document in this WindowGlobal.
   async UpdateDocumentURI(nsIURI aUri);
 
   /// Send down initial document bit to the parent.
   async SetIsInitialDocument(bool aIsInitialDocument);
 
   /// Tell the parent if this WindowGlobal has any "beforeunload" event
   /// listeners.
--- a/dom/ipc/WindowGlobalChild.cpp
+++ b/dom/ipc/WindowGlobalChild.cpp
@@ -223,16 +223,22 @@ void WindowGlobalChild::Destroy() {
 
     for (auto& windowActor : windowActors) {
       windowActor->StartDestroy();
     }
     SendDestroy();
   }
 }
 
+mozilla::ipc::IPCResult WindowGlobalChild::RecvLoadURIInChild(
+    nsDocShellLoadState* aLoadState) {
+  mWindowGlobal->GetDocShell()->LoadURI(aLoadState);
+  return IPC_OK();
+}
+
 static nsresult ChangeFrameRemoteness(WindowGlobalChild* aWgc,
                                       BrowsingContext* aBc,
                                       const nsString& aRemoteType,
                                       uint64_t aPendingSwitchId,
                                       BrowserBridgeChild** aBridge) {
   MOZ_ASSERT(XRE_IsContentProcess(), "This doesn't make sense in the parent");
 
   // Get the target embedder's FrameLoaderOwner, and make sure we're in the
--- a/dom/ipc/WindowGlobalChild.h
+++ b/dom/ipc/WindowGlobalChild.h
@@ -109,16 +109,18 @@ class WindowGlobalChild final : public W
  protected:
   const nsAString& GetRemoteType() override;
   JSWindowActor::Type GetSide() override { return JSWindowActor::Type::Child; }
 
   // IPC messages
   mozilla::ipc::IPCResult RecvRawMessage(const JSWindowActorMessageMeta& aMeta,
                                          const ClonedMessageData& aData);
 
+  mozilla::ipc::IPCResult RecvLoadURIInChild(nsDocShellLoadState* aLoadState);
+
   mozilla::ipc::IPCResult RecvChangeFrameRemoteness(
       dom::BrowsingContext* aBc, const nsString& aRemoteType,
       uint64_t aPendingSwitchId, ChangeFrameRemotenessResolver&& aResolver);
 
   mozilla::ipc::IPCResult RecvDrawSnapshot(const Maybe<IntRect>& aRect,
                                            const float& aScale,
                                            const nscolor& aBackgroundColor,
                                            const uint32_t& aFlags,
--- a/dom/ipc/WindowGlobalParent.cpp
+++ b/dom/ipc/WindowGlobalParent.cpp
@@ -168,16 +168,48 @@ bool WindowGlobalParent::IsProcessRoot()
   auto* embedder = BrowsingContext()->GetEmbedderWindowGlobal();
   if (NS_WARN_IF(!embedder)) {
     return false;
   }
 
   return ContentParentId() != embedder->ContentParentId();
 }
 
+mozilla::ipc::IPCResult WindowGlobalParent::RecvLoadURI(
+    dom::BrowsingContext* aTargetBC,
+    nsDocShellLoadState* aLoadState) {
+  if (!aTargetBC || aTargetBC->IsDiscarded()) {
+    MOZ_LOG(
+        BrowsingContext::GetLog(), LogLevel::Debug,
+        ("ParentIPC: Trying to send a message with dead or detached context"));
+    return IPC_OK();
+  }
+
+  // FIXME: For cross-process loads, we should double check CanAccess() for the
+  // source browsing context in the parent process.
+
+  if (aTargetBC->Group() != BrowsingContext()->Group()) {
+    return IPC_FAIL(this, "Illegal cross-group BrowsingContext load");
+  }
+
+  // FIXME: We should really initiate the load in the parent before bouncing
+  // back down to the child.
+
+  WindowGlobalParent* wgp = aTargetBC->Canonical()->GetCurrentWindowGlobal();
+  if (!wgp) {
+    MOZ_LOG(
+        BrowsingContext::GetLog(), LogLevel::Debug,
+        ("ParentIPC: Target BrowsingContext has no WindowGlobalParent"));
+    return IPC_OK();
+  }
+
+  Unused << wgp->SendLoadURIInChild(aLoadState);
+  return IPC_OK();
+}
+
 IPCResult WindowGlobalParent::RecvUpdateDocumentURI(nsIURI* aURI) {
   // XXX(nika): Assert that the URI change was one which makes sense (either
   // about:blank -> a real URI, or a legal push/popstate URI change?)
   mDocumentURI = aURI;
   return IPC_OK();
 }
 
 IPCResult WindowGlobalParent::RecvSetHasBeforeUnload(bool aHasBeforeUnload) {
--- a/dom/ipc/WindowGlobalParent.h
+++ b/dom/ipc/WindowGlobalParent.h
@@ -134,16 +134,18 @@ class WindowGlobalParent final : public 
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
  protected:
   const nsAString& GetRemoteType() override;
   JSWindowActor::Type GetSide() override { return JSWindowActor::Type::Parent; }
 
   // IPC messages
+  mozilla::ipc::IPCResult RecvLoadURI(dom::BrowsingContext* aTargetBC,
+                                      nsDocShellLoadState* aLoadState);
   mozilla::ipc::IPCResult RecvUpdateDocumentURI(nsIURI* aURI);
   mozilla::ipc::IPCResult RecvSetIsInitialDocument(bool aIsInitialDocument) {
     mIsInitialDocument = aIsInitialDocument;
     return IPC_OK();
   }
   mozilla::ipc::IPCResult RecvSetHasBeforeUnload(bool aHasBeforeUnload);
   mozilla::ipc::IPCResult RecvBecomeCurrentWindowGlobal();
   mozilla::ipc::IPCResult RecvDestroy();
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -304,17 +304,16 @@ skip-if = toolkit == 'android'
 [test_child-src_worker_data.html]
 [test_child-src_worker-redirect.html]
 [test_child-src_iframe.html]
 [test_meta_element.html]
 [test_meta_header_dual.html]
 [test_docwrite_meta.html]
 [test_multipartchannel.html]
 [test_fontloader.html]
-fail-if = fission
 [test_block_all_mixed_content.html]
 tags = mcb
 [test_block_all_mixed_content_frame_navigation.html]
 tags = mcb
 [test_form_action_blocks_url.html]
 [test_meta_whitespace_skipping.html]
 [test_iframe_sandbox.html]
 [test_iframe_sandbox_top_1.html]
--- a/dom/security/test/csp/test_fontloader.html
+++ b/dom/security/test/csp/test_fontloader.html
@@ -52,21 +52,21 @@ const tests = [
   }
 ];
 
 var curTest;
 var counter = -1;
 var baselineframe = document.getElementById("baselineframe");
 var testframe = document.getElementById("testframe");
 
-function checkResult() {
+async function checkResult() {
   testframe.removeEventListener('load', checkResult);
   try {
-    ok(compareSnapshots(snapshotWindow(baselineframe.contentWindow),
-                        snapshotWindow(testframe.contentWindow),
+    ok(compareSnapshots(await snapshotWindow(baselineframe.contentWindow),
+                        await snapshotWindow(testframe.contentWindow),
                         curTest.expected)[0],
                         curTest.description);
   } catch(err) {
     ok(false, "error: " + err.message);
   }
   loadNextTest();
 }
 
--- a/dom/svg/test/mochitest.ini
+++ b/dom/svg/test/mochitest.ini
@@ -96,15 +96,14 @@ support-files = tearoff_with_cc_helper.h
 [test_text.html]
 [test_text_lengthAdjust.html]
 [test_text_scaled.html]
 [test_text_selection.html]
 [test_text_update.html]
 [test_transform.xhtml]
 [test_transformParsing.html]
 [test_use_with_hsts.html]
-skip-if = fission
 support-files = use-with-hsts-helper.html use-with-hsts-helper.html^headers^
 [test_valueAsString.xhtml]
 [test_valueLeaks.xhtml]
 [test_viewBox.html]
 [test_viewport.html]
 
--- a/dom/svg/test/test_text_dirty.html
+++ b/dom/svg/test/test_text_dirty.html
@@ -18,26 +18,26 @@ https://bugzilla.mozilla.org/show_bug.cg
     <mask id="m"><text id="t">x</text></mask>
     <rect width="600" height="400" mask="url(#m)"/>
   </svg>
 </p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
-function runTest() {
+async function runTest() {
   var svgText = document.getElementById("t");
 
   // Dirty the frames.
   document.getElementById("display").style.width = "700px";
   svgText.firstChild.remove();
 
   // Paint without flushing layout.  If the test fails, we'll trigger
   // an assertion.
-  SpecialPowers.snapshotWindowWithOptions(window, undefined, undefined, { DRAWWINDOW_DO_NOT_FLUSH: true });
+  await SpecialPowers.snapshotWindowWithOptions(window, undefined, undefined, { DRAWWINDOW_DO_NOT_FLUSH: true });
 
   ok(true);
   SimpleTest.finish();
 }
 
 window.addEventListener("load", runTest);
 
 SimpleTest.waitForExplicitFinish();
--- a/dom/svg/test/test_use_with_hsts.html
+++ b/dom/svg/test/test_use_with_hsts.html
@@ -68,52 +68,52 @@ https://bugzilla.mozilla.org/show_bug.cg
     });
   }
 
   // MAIN TEST CODE BEGINS HERE.
   async function runTest() {
     // Capture a snapshot with nothing in the iframe, so we can do a
     // sanity-check not-equal comparison against our reference case, to be
     // sure we're rendering anything at all:
-    let blankSnapshot = snapshotWindow(iframeWin);
+    let blankSnapshot = await snapshotWindow(iframeWin);
 
     // Load & snapshot a reference case (fully lime):
     await LoadIframeAsync("data:text/html,<body style='background:lime'>");
-    let refSnapshot = snapshotWindow(iframeWin);
+    let refSnapshot = await snapshotWindow(iframeWin);
 
     // Ensure reference snapshot looks different from blank snapshot:
     assertSnapshots(refSnapshot, blankSnapshot,
                     false /* not equal*/, null /* no fuzz*/,
                     "refSnapshot", "blankSnapshot");
 
     // OK, assuming we've got a valid refSnapshot, we can now proceed to
     // capture test screenshots.
 
     // Register a postMessage handler, so that iframe can report its location:
     window.addEventListener("message", receiveMessage);
 
     // Load & snapshot secure (HTTPS) version of testcase, & check against ref:
     await LoadIframeAsync(secureURI);
-    let secureSnapshot = snapshotWindow(iframeWin);
+    let secureSnapshot = await snapshotWindow(iframeWin);
     assertSnapshots(secureSnapshot, refSnapshot,
                     true /* equal*/, null /* no fuzz*/,
                     "secureSnapshot", "refSnapshot");
 
     // Load insecure (HTTP) version of testcase (which should get
     // automatically upgraded to secure (HTTPS) under the hood):
     await LoadIframeAsync(insecureURI);
 
     // Double-check that iframe is really pointed at insecure URI, to be sure
     // we're actually exercising HSTS. (Note that receiveMessage() will make
     // sure it's been upgraded to a secure HTTPS URI under the hood.)
     is(iframe.src, insecureURI,
        "test should've attempted to load insecure HTTP URI, to exercise HSTS");
 
     // Capture snapshot of iframe showing upgraded-to-HTTPS version of testcase:
-    let upgradedSnapshot = snapshotWindow(iframeWin);
+    let upgradedSnapshot = await snapshotWindow(iframeWin);
     assertSnapshots(upgradedSnapshot, refSnapshot,
                     true /* equal*/, null /* no fuzz*/,
                     "upgradedSnapshot", "refSnapshot");
 
     // Check that the iframe did actually invoke our postMessage handler (which
     // is where we verify that the HSTS upgrade actually happened):
     is(numPostMessageCalls, expectedNumPostMessageCalls,
       "didn't receive as many messages from child iframe as expected");
--- a/dom/xul/test/test_bug398289.html
+++ b/dom/xul/test/test_bug398289.html
@@ -10,28 +10,28 @@
   <iframe id="test" src="398289-resource.xul" width="100%" height="100%">
   </iframe>
 
   <script class="testbody" type="text/javascript">
     var snap1, snap2;
   
     SimpleTest.waitForExplicitFinish();
   
-    function onBodyLoad() {
+    async function onBodyLoad() {
       window.frames[0].document.getElementById("test").selectedIndex = 0;
       window.frames[0].document.getElementById("test").selectedIndex = 1;
       
-      snap1 = snapshotWindow(window);
+      snap1 = await snapshotWindow(window);
       
       document.getElementById("test").onload = onFrameLoad;
       window.frames[0].location.reload();
     }
     
-    function onFrameLoad() {
-      snap2 = snapshotWindow(window);
+    async function onFrameLoad() {
+      snap2 = await snapshotWindow(window);
 
       var equal, str1, str2;
       [equal, str1, str2] = compareSnapshots(snap1, snap2, true);
 
       ok(equal, "persistent attribute in tab box broken, expected: "+str1+" got: "+str2);
           
       SimpleTest.finish();
     }
--- a/image/test/mochitest/mochitest.ini
+++ b/image/test/mochitest/mochitest.ini
@@ -118,17 +118,16 @@ skip-if = verify
 [test_bug497665.html]
 [test_bug552605-1.html]
 [test_bug552605-2.html]
 [test_bug553982.html]
 [test_bug601470.html]
 [test_bug614392.html]
 [test_bug657191.html]
 [test_bug671906.html]
-fail-if = fission
 [test_bug733553.html]
 skip-if = verify
 [test_bug767779.html]
 [test_bug865919.html]
 [test_bug89419-1.html]
 [test_bug89419-2.html]
 [test_bug1132427.html]
 skip-if = os == 'android'
--- a/image/test/mochitest/test_bug671906.html
+++ b/image/test/mochitest/test_bug671906.html
@@ -16,43 +16,43 @@ https://bugzilla.mozilla.org/show_bug.cg
 <pre id="test">
 <script type="application/javascript">
 
 var first, second, third;
 var correct, val1, val2;
 
 SimpleTest.waitForExplicitFinish();
 
-function snapshotFirst()
+async function snapshotFirst()
 {
   var iframeelem = document.getElementById('test-iframe');
-  first = snapshotWindow(iframeelem.contentWindow, false);
+  first = await snapshotWindow(iframeelem, false);
 
   iframeelem.onload = snapshotSecond;
   iframeelem.src = "http://example.com/tests/image/test/mochitest/bug671906-iframe.html";
 }
 
-function snapshotSecond()
+async function snapshotSecond()
 {
   var iframeelem = document.getElementById('test-iframe');
-  second = snapshotWindow(iframeelem.contentWindow, false);
+  second = await snapshotWindow(iframeelem, false);
 
   // We must have loaded the image again, because the principals for the
   // loading document are different.
   [correct, val1, val2] = compareSnapshots(first, second, false);
   ok(correct, "Image should have changed after changing the iframe's src.");
 
   iframeelem.onload = snapshotThird;
   iframeelem.src = "http://mochi.test:8888/tests/image/test/mochitest/bug671906-iframe.html";
 }
 
-function snapshotThird()
+async function snapshotThird()
 {
   var iframeelem = document.getElementById('test-iframe');
-  third = snapshotWindow(iframeelem.contentWindow, false);
+  third = await snapshotWindow(iframeelem, false);
 
   // We must have loaded the image again, because the principals for the
   // loading document are different.
   [correct, val1, val2] = compareSnapshots(second, third, false);
   ok(correct, "Image should have changed after changing the iframe's src.");
 
   // We must have looped back to the first image, because the sjs only sends
   // one of two images.
--- a/js/src/devtools/automation/autospider.py
+++ b/js/src/devtools/automation/autospider.py
@@ -16,26 +16,28 @@ import subprocess
 import sys
 
 from collections import Counter, namedtuple
 from logging import info
 from os import environ as env
 from subprocess import Popen
 from threading import Timer
 
-Dirs = namedtuple('Dirs', ['scripts', 'js_src', 'source', 'tooltool'])
+Dirs = namedtuple('Dirs', ['scripts', 'js_src', 'source', 'tooltool', 'fetches'])
 
 
 def directories(pathmodule, cwd, fixup=lambda s: s):
     scripts = pathmodule.join(fixup(cwd), fixup(pathmodule.dirname(__file__)))
     js_src = pathmodule.abspath(pathmodule.join(scripts, "..", ".."))
     source = pathmodule.abspath(pathmodule.join(js_src, "..", ".."))
     tooltool = pathmodule.abspath(env.get('TOOLTOOL_CHECKOUT',
                                           pathmodule.join(source, "..", "..")))
-    return Dirs(scripts, js_src, source, tooltool)
+    fetches = pathmodule.abspath(env.get('MOZ_FETCHES_DIR',
+                                         pathmodule.join(source, "..", "..")))
+    return Dirs(scripts, js_src, source, tooltool, fetches)
 
 
 # Some scripts will be called with sh, which cannot use backslashed
 # paths. So for direct subprocess.* invocation, use normal paths from
 # DIR, but when running under the shell, use POSIX style paths.
 DIR = directories(os.path, os.getcwd())
 PDIR = directories(posixpath, os.environ["PWD"],
                    fixup=lambda s: re.sub(r'^(\w):', r'/\1', s))
@@ -104,17 +106,17 @@ args = parser.parse_args()
 logging.basicConfig(level=logging.INFO, format='%(message)s')
 
 OBJDIR = args.objdir
 OUTDIR = os.path.join(OBJDIR, "out")
 POBJDIR = posixpath.join(PDIR.source, args.objdir)
 MAKE = env.get('MAKE', 'make')
 MAKEFLAGS = env.get('MAKEFLAGS', '-j6' + ('' if AUTOMATION else ' -s'))
 
-for d in ('scripts', 'js_src', 'source', 'tooltool'):
+for d in ('scripts', 'js_src', 'source', 'tooltool', 'fetches'):
     info("DIR.{name} = {dir}".format(name=d, dir=getattr(DIR, d)))
 
 
 def set_vars_from_script(script, vars):
     '''Run a shell script, then dump out chosen environment variables. The build
        system uses shell scripts to do some configuration that we need to
        borrow. On Windows, the script itself must output the variable settings
        (in the form "export FOO=<value>"), since otherwise there will be
@@ -223,17 +225,17 @@ elif platform.system() == 'Windows':
     compiler = 'cl'
 else:
     compiler = 'gcc'
 
 info("using compiler '{}'".format(compiler))
 
 cxx = {'clang': 'clang++', 'gcc': 'g++', 'cl': 'cl'}.get(compiler)
 
-compiler_dir = env.get('GCCDIR', os.path.join(DIR.tooltool, compiler))
+compiler_dir = env.get('GCCDIR', os.path.join(DIR.fetches, compiler))
 info("looking for compiler under {}/".format(compiler_dir))
 if os.path.exists(os.path.join(compiler_dir, 'bin', compiler)):
     env.setdefault('CC', os.path.join(compiler_dir, 'bin', compiler))
     env.setdefault('CXX', os.path.join(compiler_dir, 'bin', cxx))
     if compiler == 'clang':
         platlib = 'lib'
     else:
         platlib = 'lib64' if word_bits == 64 else 'lib'
@@ -244,17 +246,17 @@ else:
 
 bindir = os.path.join(OBJDIR, 'dist', 'bin')
 env['LD_LIBRARY_PATH'] = ':'.join(
     p for p in (bindir, env.get('LD_LIBRARY_PATH')) if p)
 
 for v in ('CC', 'CXX', 'LD_LIBRARY_PATH'):
     info("default {name} = {value}".format(name=v, value=env[v]))
 
-rust_dir = os.path.join(DIR.tooltool, 'rustc')
+rust_dir = os.path.join(DIR.fetches, 'rustc')
 if os.path.exists(os.path.join(rust_dir, 'bin', 'rustc')):
     env.setdefault('RUSTC', os.path.join(rust_dir, 'bin', 'rustc'))
     env.setdefault('CARGO', os.path.join(rust_dir, 'bin', 'cargo'))
 else:
     env.setdefault('RUSTC', 'rustc')
     env.setdefault('CARGO', 'cargo')
 
 if platform.system() == 'Darwin':
@@ -332,16 +334,17 @@ def run_command(command, check=False, **
         raise subprocess.CalledProcessError(status, command, output=stderr)
     return stdout, stderr, status
 
 
 # Replacement strings in environment variables.
 REPLACEMENTS = {
     'DIR': DIR.scripts,
     'TOOLTOOL_CHECKOUT': DIR.tooltool,
+    'MOZ_FETCHES_DIR': DIR.fetches,
     'MOZ_UPLOAD_DIR': env['MOZ_UPLOAD_DIR'],
     'OUTDIR': OUTDIR,
 }
 
 # Add in environment variable settings for this variant. Normally used to
 # modify the flags passed to the shell or to set the GC zeal mode.
 for k, v in variant.get('env', {}).items():
     env[k.encode('ascii')] = v.encode('ascii').format(**REPLACEMENTS)
--- a/js/src/devtools/automation/variants/asan
+++ b/js/src/devtools/automation/variants/asan
@@ -1,10 +1,10 @@
 {
     "configure-args": "--enable-debug-symbols='-gline-tables-only' --enable-gczeal --disable-jemalloc --enable-address-sanitizer",
     "optimize": true,
     "debug": false,
     "compiler": "clang",
     "env": {
-        "LLVM_SYMBOLIZER": "{TOOLTOOL_CHECKOUT}/clang/bin/llvm-symbolizer"
+        "LLVM_SYMBOLIZER": "{MOZ_FETCHES_DIR}/clang/bin/llvm-symbolizer"
     },
     "use_minidump": false
 }
--- a/js/src/devtools/automation/variants/fuzzing
+++ b/js/src/devtools/automation/variants/fuzzing
@@ -1,13 +1,13 @@
 {
     "configure-args": "--enable-fuzzing --enable-gczeal --enable-debug-symbols='-gline-tables-only -gdwarf-2' --disable-jemalloc --disable-stdcxx-compat --enable-address-sanitizer --enable-ctypes --enable-nspr-build",
     "optimize": true,
     "debug": false,
     "compiler": "clang",
     "env": {
         "JITTEST_EXTRA_ARGS": "--jitflags=none",
         "JSTESTS_EXTRA_ARGS": "--jitflags=none",
-        "LLVM_SYMBOLIZER": "{TOOLTOOL_CHECKOUT}/clang/bin/llvm-symbolizer",
-        "ASAN_SYMBOLIZER_PATH": "{TOOLTOOL_CHECKOUT}/clang/bin/llvm-symbolizer"
+        "LLVM_SYMBOLIZER": "{MOZ_FETCHES_DIR}/clang/bin/llvm-symbolizer",
+        "ASAN_SYMBOLIZER_PATH": "{MOZ_FETCHES_DIR}/clang/bin/llvm-symbolizer"
     },
     "use_minidump": false
 }
--- a/js/src/devtools/automation/variants/msan
+++ b/js/src/devtools/automation/variants/msan
@@ -1,14 +1,14 @@
 {
     "configure-args": "--enable-debug-symbols='-gline-tables-only' --disable-jemalloc --enable-memory-sanitizer --without-system-zlib",
     "optimize": true,
     "debug": false,
     "compiler": "clang",
     "env": {
         "JITTEST_EXTRA_ARGS": "--jitflags=interp --ignore-timeouts={DIR}/cgc-jittest-timeouts.txt",
         "JSTESTS_EXTRA_ARGS": "--jitflags=interp --exclude-file={DIR}/cgc-jstests-slow.txt",
-        "MSAN_OPTIONS": "external_symbolizer_path={TOOLTOOL_CHECKOUT}/clang/bin/llvm-symbolizer:log_path={OUTDIR}/sanitize_log"
+        "MSAN_OPTIONS": "external_symbolizer_path={MOZ_FETCHES_DIR}/clang/bin/llvm-symbolizer:log_path={OUTDIR}/sanitize_log"
     },
     "ignore-test-failures": "true",
     "max-errors": 7,
     "use_minidump": false
 }
--- a/js/src/devtools/automation/variants/tsan
+++ b/js/src/devtools/automation/variants/tsan
@@ -1,12 +1,12 @@
 {
     "configure-args": "--enable-debug-symbols='-gline-tables-only' --disable-jemalloc --enable-thread-sanitizer",
     "optimize": true,
     "debug": false,
     "compiler": "clang",
     "env": {
-        "LLVM_SYMBOLIZER": "{TOOLTOOL_CHECKOUT}/clang/bin/llvm-symbolizer",
+        "LLVM_SYMBOLIZER": "{MOZ_FETCHES_DIR}/clang/bin/llvm-symbolizer",
         "JITTEST_EXTRA_ARGS": "--jitflags=tsan --ignore-timeouts={DIR}/cgc-jittest-timeouts.txt --unusable-error-status --exclude-from={DIR}/tsan-slow.txt",
         "JSTESTS_EXTRA_ARGS": "--exclude-file={DIR}/cgc-jstests-slow.txt"
     },
     "use_minidump": false
 }
--- a/js/src/devtools/rootAnalysis/README.md
+++ b/js/src/devtools/rootAnalysis/README.md
@@ -71,30 +71,30 @@ 3.  Install taskcluster-vcs, eg by doing
         npm install taskcluster-vcs
         export PATH="$PATH:$(pwd)/node_modules/.bin"
 
 4. In some directory, using $SRCDIR as the top of your Gecko source checkout,
     run these commands:
 
         mkdir work
         cd work
-        ( export GECKO_DIR=$SRCDIR; $GECKO_DIR/taskcluster/scripts/builder/build-haz-linux.sh $(pwd) --dep )
+        ( export GECKO_PATH=$SRCDIR; $GECKO_PATH/taskcluster/scripts/builder/build-haz-linux.sh $(pwd) --dep )
 
 The `--dep` is optional, and will avoid rebuilding the JS shell used to run the
 analysis later.
 
 If you see the error ``/lib/../lib64/crti.o: unrecognized relocation (0x2a) in section .init`` then have a version mismatch between the precompiled gcc used in automation and your installed glibc. The easiest way to fix this is to delete the ld provided with the precompiled gcc (it will be in two places, one given in the first part of the error message), which will cause gcc to fall back to your system ld. But you will need to additionally pass ``--no-tooltool`` to build-haz-linux.sh. With the current package, you could do the deletion with
 
     rm gcc/bin/ld
     rm gcc/x86_64-unknown-linux-gnu/bin/ld
 
 Output goes to `analysis/hazards.txt`. This will run the
 analysis on the js/src tree only; if you wish to analyze the full browser, use
 
-    ( export GECKO_DIR=$SRCDIR; $GECKO_DIR/taskcluster/scripts/builder/build-haz-linux.sh --project browser $(pwd) )
+    ( export GECKO_PATH=$SRCDIR; $GECKO_PATH/taskcluster/scripts/builder/build-haz-linux.sh --project browser $(pwd) )
 
 After running the analysis once, you can reuse the `*.xdb` database files
 generated, using modified analysis scripts, by running
 `analysis/run-analysis.sh` (or pass `--list` to see ways to select even more
 restrictive parts of the overall analysis; the default is `gcTypes` which will
 do everything but regenerate the xdb files).
 
 Also, you can pass `-v` to get exact command lines to cut & paste for running the
--- a/js/src/devtools/rootAnalysis/mozconfig.haz
+++ b/js/src/devtools/rootAnalysis/mozconfig.haz
@@ -17,31 +17,31 @@ MOZ_AUTOMATION_PACKAGE_TESTS=0
 MOZ_AUTOMATION_UPLOAD=0
 
 ac_add_options --enable-js-shell
 
 # The objdir must be at a known location so its path can be stripped from the
 # filenames stored by the analysis
 mk_add_options MOZ_OBJDIR=obj-analyzed
 
-export LLVM_CONFIG=$TOOLTOOL_DIR/clang/bin/llvm-config
-export CBINDGEN="${TOOLTOOL_DIR}/cbindgen/cbindgen"
+export LLVM_CONFIG=$MOZ_FETCHES_DIR/clang/bin/llvm-config
+export CBINDGEN="${MOZ_FETCHES_DIR}/cbindgen/cbindgen"
 
 # The configuration options are chosen to compile the most code
 # (--enable-debug, --enable-tests) in the trickiest way possible
 # (--enable-optimize) to maximize the chance of seeing tricky static orderings.
 ac_add_options --enable-debug
 ac_add_options --enable-tests
 ac_add_options --enable-optimize
-ac_add_options --with-compiler-wrapper=$TOOLTOOL_DIR/sixgill/usr/libexec/sixgill/scripts/wrap_gcc/basecc
+ac_add_options --with-compiler-wrapper=$MOZ_FETCHES_DIR/sixgill/usr/libexec/sixgill/scripts/wrap_gcc/basecc
 ac_add_options --without-ccache
 
 ac_add_options --disable-replace-malloc
 
 # -Wattributes is very verbose due to attributes being ignored on template
 # instantiations. -Wignored-attributes is very verbose due to attributes being
 # ignored on template parameters.
 CFLAGS="$CFLAGS -Wno-attributes -Wno-ignored-attributes"
 CPPFLAGS="$CPPFLAGS -Wno-attributes -Wno-ignored-attributes"
 CXXFLAGS="$CXXFLAGS -Wno-attributes -Wno-ignored-attributes"
 
-NODEJS="$TOOLTOOL_DIR/node/bin/node"
-NASM="$TOOLTOOL_DIR/nasm/nasm"
+NODEJS="$MOZ_FETCHES_DIR/node/bin/node"
+NASM="$MOZ_FETCHES_DIR/nasm/nasm"
--- a/js/src/devtools/rootAnalysis/run-analysis.sh
+++ b/js/src/devtools/rootAnalysis/run-analysis.sh
@@ -1,4 +1,4 @@
 #!/bin/sh
 
 SRCDIR=$(cd $(dirname $0)/../../../..; pwd)
-GECKO_DIR=$SRCDIR $SRCDIR/taskcluster/scripts/builder/build-haz-linux.sh $(pwd) "$@"
+GECKO_PATH=$SRCDIR $SRCDIR/taskcluster/scripts/builder/build-haz-linux.sh $(pwd) "$@"
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -411,16 +411,31 @@ interface nsIXPCComponents_Utils : nsISu
      *
      * Dead-wrapper objects hold no other objects alive (they have no outgoing
      * reference edges) and will throw if you touch them (e.g. by
      * reading/writing a property).
      */
     bool isDeadWrapper(in jsval obj);
 
     /**
+     * Determines whether this value is a remote object proxy, such as
+     * RemoteWindowProxy or RemoteLocationProxy, for an out-of-process frame.
+     *
+     * Remote object proxies do not grant chrome callers the same exemptions
+     * to the same-origin-policy that in-process wrappers typically do, so
+     * this can be used to determine whether access to cross-origin proxies is
+     * safe:
+     *
+     *   if (!Cu.isRemoteProxy(frame.contentWindow)) {
+     *     frame.contentWindow.doCrossOriginThing();
+     *   }
+     */
+    bool isRemoteProxy(in jsval val);
+
+    /**
      * Determines whether this object is a cross-process wrapper.
      */
     bool isCrossProcessWrapper(in jsval obj);
 
     /**
      * CPOWs can have user data attached to them. This data originates
      * in the local process via the
      * nsIRemoteTagService.getRemoteObjectTag method. It's sent along
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -25,16 +25,17 @@
 #include "mozilla/Preferences.h"
 #include "nsJSEnvironment.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/URLPreloader.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/RemoteObjectProxy.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "nsZipArchive.h"
 #include "nsWindowMemoryReporter.h"
 #include "nsICycleCollectorListener.h"
 #include "nsIException.h"
 #include "nsIScriptError.h"
 #include "nsISimpleEnumerator.h"
@@ -1909,16 +1910,27 @@ nsXPCComponents_Utils::IsDeadWrapper(Han
   MOZ_ASSERT_IF(js::IsCrossCompartmentWrapper(&obj.toObject()),
                 !JS_IsDeadWrapper(js::UncheckedUnwrap(&obj.toObject())));
 
   *out = JS_IsDeadWrapper(&obj.toObject());
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsXPCComponents_Utils::IsRemoteProxy(HandleValue val, bool* out) {
+  if (val.isObject()) {
+    *out = dom::IsRemoteObjectProxy(UncheckedUnwrap(&val.toObject()));
+    ;
+  } else {
+    *out = false;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsXPCComponents_Utils::IsCrossProcessWrapper(HandleValue obj, bool* out) {
   *out = false;
   if (obj.isPrimitive()) {
     return NS_ERROR_INVALID_ARG;
   }
 
   *out = jsipc::IsWrappedCPOW(&obj.toObject());
   return NS_OK;
--- a/js/xpconnect/tests/mochitest/mochitest.ini
+++ b/js/xpconnect/tests/mochitest/mochitest.ini
@@ -38,72 +38,69 @@ support-files =
   inner.html
   test1_bug629331.html
   test2_bug629331.html
 
 [test_bug384632.html]
 [test_bug390488.html]
 [test_bug393269.html]
 [test_bug396851.html]
-fail-if = fission
 [test_bug428021.html]
 [test_bug446584.html]
 [test_bug462428.html]
 [test_bug478438.html]
 fail-if = fission
 [test_bug500691.html]
 [test_bug504877.html]
 fail-if = fission
 [test_bug505915.html]
-fail-if = fission
 [test_bug560351.html]
 [test_bug585745.html]
 [test_bug589028.html]
 [test_bug601299.html]
 [test_bug605167.html]
 [test_bug618017.html]
 [test_bug623437.html]
 [test_bug628410.html]
 [test_bug628794.html]
 [test_bug629227.html]
-fail-if = fission
+skip-if = fission # Times out.
 [test_bug629331.html]
 [test_bug636097.html]
-fail-if = fission
+fail-if = fission # Bug 1573621: window.location access after cross-origin navigation.
 [test_bug650273.html]
 [test_bug655297-1.html]
 [test_bug655297-2.html]
 [test_bug661980.html]
 [test_bug691059.html]
 [test_bug720619.html]
 [test_bug731471.html]
 skip-if = toolkit == "android" && debug && !is_fennec
 [test_bug764389.html]
 [test_bug772288.html]
 [test_bug781476.html]
 [test_bug789713.html]
 [test_bug790732.html]
 [test_bug793969.html]
 [test_bug800864.html]
-fail-if = fission
+fail-if = fission # Bug 1573621: window.location access after cross-origin navigation.
 [test_bug802557.html]
 skip-if = fission # Crashes: @ mozilla::dom::ContentParent::RecvDetachBrowsingContext(unsigned long, std::function<void (bool const&)>&&)
-fail-if = fission
+fail-if = fission # Bug 1573621: window.location access after cross-origin navigation.
 [test_bug803730.html]
 [test_bug809547.html]
 [test_bug829872.html]
-fail-if = fission
 [test_bug862380.html]
 [test_bug865260.html]
 [test_bug870423.html]
-fail-if = fission
+fail-if = fission # isinstance hooks for remote object proxies.
 [test_bug871887.html]
 [test_bug912322.html]
 [test_bug916945.html]
-fail-if = fission
+fail-if = fission # "name" attribute on cross-origin frames
 [test_bug92773.html]
 [test_bug940783.html]
 fail-if = fission
 [test_bug965082.html]
 fail-if = fission
 skip-if = fission && webrender && debug # Crashes intermittently: @ nsDocShell::SetParentWidget(nsIWidget*)
 [test_bug960820.html]
 [test_bug986542.html]
@@ -113,18 +110,17 @@ skip-if = fission && webrender && debug 
 [test_bug1158558.html]
 [test_bug1448048.html]
 [test_crosscompartment_weakmap.html]
 [test_frameWrapping.html]
 # The JS test component we use below is only available in debug builds.
 [test_getWebIDLCaller.html]
 skip-if = (debug == false)
 [test_getweakmapkeys.html]
+[test_isRemoteProxy.html]
 [test_paris_weakmap_keys.html]
 skip-if = (debug == false)
 [test_nukeContentWindow.html]
 [test_sameOriginPolicy.html]
-skip-if = fission # Crashes: @ nsOuterWindowProxy::GetSubframeWindow(JSContext*, JS::Handle<JSObject*>, JS::Handle<JS::PropertyKey>) const
-fail-if = fission
 [test_sandbox_fetch.html]
   support-files =
     ../../../../dom/tests/mochitest/fetch/test_fetch_basic.js
 [test_weakmaps.html]
--- a/js/xpconnect/tests/mochitest/test_bug396851.html
+++ b/js/xpconnect/tests/mochitest/test_bug396851.html
@@ -4,28 +4,40 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=396851
 -->
 <head>
   <title>Test for Bug 396851</title>
   <script src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 
   <script type="text/javascript">
+  function throws(func, pattern, msg) {
+    try {
+      func();
+      ok(false, msg);
+    } catch (e) {
+      ok(pattern.test(e), `${msg}: Expect exception mathing ${pattern}`);
+    }
+  }
+
   function go() {
     var iframe = $("ifr");
     var win = iframe.contentWindow;
-    try {
-      var doc = win.document;
-      fail("Allowed cross-origin access to the document");
-    } catch (e) {
-      ok(e.toString().match("Permission denied") != null, "Weird exception thrown");
+    throws(() => win.document,
+           /Permission denied/,
+           "Unprivileged code should not be able to access cross-origin document");
+
+    if (SpecialPowers.useRemoteSubframes) {
+      throws(() => win.document,
+             /Permission denied/,
+             "Privileged code should not be able to access cross-process document");
+    } else {
+      ok(SpecialPowers.wrap(win).document != null,
+         "Able to access the cross-origin document");
     }
-
-    doc = SpecialPowers.wrap(win).document;
-    ok(doc != null, "Able to access the cross-origin document");
     SimpleTest.finish();
   }
   </script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=396851">Mozilla Bug 396851</a>
 <p id="display"></p>
 <div id="content" style="display: none">
--- a/js/xpconnect/tests/mochitest/test_bug505915.html
+++ b/js/xpconnect/tests/mochitest/test_bug505915.html
@@ -40,12 +40,12 @@ function go() {
     SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 
 </script>
 </pre>
 
-<iframe id="ifr" onload="go();" src="http://example.org/"></iframe>
+<iframe id="ifr" onload="go();" src="http://test1.mochi.test:8888/"></iframe>
 
 </body>
 </html>
--- a/js/xpconnect/tests/mochitest/test_bug829872.html
+++ b/js/xpconnect/tests/mochitest/test_bug829872.html
@@ -14,29 +14,29 @@ https://bugzilla.mozilla.org/show_bug.cg
   SimpleTest.waitForExplicitFinish();
 
   var gLoadCount = 0;
   function loaded() {
     if (++gLoadCount == 3)
       go();
   }
 
-  function check(elem, desc) {
+  async function check(elem, desc) {
     is(elem.contentDocument, null, "null cross-origin contentDocument for " + desc);
-    ok(SpecialPowers.wrap(elem).contentWindow.eval('frameElement === null;'),
+    ok(await SpecialPowers.spawn(elem, [], () => this.content.eval('frameElement === null;')),
        "null cross-origin frameElement for " + desc);
     if (!(elem instanceof HTMLFrameElement))
       is(elem.getSVGDocument(), null, "null cross-origin getSVGDocument() for " + desc);
   }
 
-  function go() {
+  async function go() {
     ok(true, "Starting test");
-    check($('ifr'), "iframe element");
-    check($('obj'), "object element");
-    check($('framesetholder').contentDocument.getElementById('fr'), "frameset frame");
+    await check($('ifr'), "iframe element");
+    await check($('obj'), "object element");
+    await check($('framesetholder').contentDocument.getElementById('fr'), "frameset frame");
     SimpleTest.finish();
   }
 
   </script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=829872">Mozilla Bug 829872</a>
 <p id="display"></p>
--- a/js/xpconnect/tests/mochitest/test_bug916945.html
+++ b/js/xpconnect/tests/mochitest/test_bug916945.html
@@ -13,35 +13,40 @@ https://bugzilla.mozilla.org/show_bug.cg
   /** Test for Bug 916945 **/
   SimpleTest.waitForExplicitFinish();
 
   var gLoadCount = 0;
   function loaded() {
     if (++gLoadCount == 2)
       go();
   }
-  function go() {
+  async function go() {
     // Both same-origin and cross-origin names should be visible if they're set
     // on the iframe element.
     ok('winA' in window, "same-origin named access works");
     ok(winA instanceof Window, "same-origin named access works");
     ok('winB' in window, "cross-origin named access works when iframe name matches");
     // XXXbholley - flip me when Window moves to new bindings.
     todo_is(winB instanceof Window, "cross-origin named access works when iframe name matches");
 
     // Setting the 'name' attribute should propagate to the docshell.
     var ifrB = document.getElementById('ifrB');
     ifrB.setAttribute('name', 'foo');
-    is(SpecialPowers.wrap(ifrB).contentWindow.name, 'foo', 'attribute sets propagate to the docshell');
+    await SpecialPowers.spawn(ifrB, [], () => {
+      Assert.equal(this.content.name, 'foo',
+                   'attribute sets propagate to the docshell');
+    });
     ok('foo' in window, "names are dynamic if updated via setAttribute");
     // XXXbholley - flip me when Window moves to new bindings.
     todo('foo' instanceof Window, "names are dynamic if updated via setAttribute");
 
     // Setting window.name on the subframe should not propagate to the attribute.
-    SpecialPowers.wrap(ifrB).contentWindow.name = 'bar';
+    await SpecialPowers.spawn(ifrB, [], () => {
+      this.content.name = "bar";
+    });
     is(ifrB.getAttribute('name'), 'foo', 'docshell updates dont propagate to the attribute');
 
     // When the frame element attribute and docshell name don't match, nothing is returned.
     ok(!('foo' in window), "frame element name not resolved if it doesn't match the docshell");
     ok(!('bar' in window), "docshell name not resolved if it doesn't match the frame element");
 
     SimpleTest.finish();
   }
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/mochitest/test_isRemoteProxy.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Tests for Cu.isRemoteProxy</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script>
+/* eslint-disable prettier/prettier */
+
+async function addFrame(url) {
+  let frame = document.createElement("iframe");
+  frame.src = url;
+  document.body.appendChild(frame);
+
+  await new Promise(resolve => {
+    frame.addEventListener("load", resolve, { once: true });
+  });
+
+  return frame;
+}
+
+add_task(async function() {
+  const { Cu } = SpecialPowers;
+
+  let localFrame = await addFrame("file_empty.html");
+  let remoteFrame = await addFrame(
+    SimpleTest.getTestFileURL("file_empty.html")
+              .replace("mochi.test:8888", "example.com"));
+
+  ok(frames[0] === localFrame.contentWindow, "frames[0] is localFrame");
+  ok(frames[1] === remoteFrame.contentWindow, "frames[1] is remoteFrame");
+
+  ok(!Cu.isRemoteProxy(window), "window is not a remote proxy");
+  ok(!Cu.isRemoteProxy(location), "location is not a remote proxy");
+
+  ok(!Cu.isRemoteProxy(frames[0]), "frames[0] is not a remote proxy");
+  ok(
+    !Cu.isRemoteProxy(frames[0].location),
+    "frames[0].location is not a remote proxy"
+  );
+
+  const { useRemoteSubframes } = SpecialPowers;
+  is(Cu.isRemoteProxy(frames[1]), useRemoteSubframes,
+     "frames[1] is a remote proxy if Fission is enabled");
+  is(Cu.isRemoteProxy(frames[1].location), useRemoteSubframes,
+    "frames[1].location is a remote proxy if Fission is enabled");
+});
+
+</script>
+</body>
+</html>
--- a/layout/svg/tests/mochitest.ini
+++ b/layout/svg/tests/mochitest.ini
@@ -1,15 +1,14 @@
 [DEFAULT]
 support-files =
   file_disabled_iframe.html
 
 [test_disabled.html]
 [test_filter_crossorigin.html]
-fail-if = fission
 support-files =
   filters.svg
   file_filter_crossorigin.svg
   file_black_yellow.svg
   file_yellow_black.svg
 
 [test_hover_near_text.html]
 [test_multiple_font_size.html]
--- a/layout/svg/tests/test_filter_crossorigin.html
+++ b/layout/svg/tests/test_filter_crossorigin.html
@@ -19,21 +19,30 @@ https://bugzilla.mozilla.org/show_bug.cg
 <br>
 <!-- These iframes' renderings are expected to match: -->
 <iframe src="http://example.org/tests/layout/svg/tests/file_filter_crossorigin.svg"></iframe>
 <iframe src="file_yellow_black.svg"></iframe>
 
 <pre id="test">
 <script type="application/javascript">
 // Main Function
-function run() {
+async function run() {
   SimpleTest.waitForExplicitFinish();
+
+  // FIXME(Fission): The load event fires before cross-origin iframes have
+  // loaded (bug 1559841).
+  if (SpecialPowers.useRemoteSubframes) {
+    for (let i = 0; i < 100; i++) {
+      await new Promise(resolve => setTimeout(resolve, 0));
+    }
+  }
+
   let snapshots = new Array(4);
   for (let i = 0; i < snapshots.length; i++) {
-    snapshots[i] = snapshotWindow(frames[i].window, false);
+    snapshots[i] = await snapshotWindow(frames[i], false);
   }
 
   // Compare mochi.test iframe against its reference:
   assertSnapshots(snapshots[0], snapshots[1], true, null,
                   "Testcase loaded from mochi.test", "Reference: black/yellow");
 
   // Compare example.org iframe against its reference:
   assertSnapshots(snapshots[2], snapshots[3], true, null,
--- a/mobile/android/config/mozconfigs/android-aarch64/beta
+++ b/mobile/android/config/mozconfigs/android-aarch64/beta
@@ -1,18 +1,18 @@
 . "$topsrcdir/mobile/android/config/mozconfigs/common"
 
 # Android
 ac_add_options --with-android-min-sdk=21
 ac_add_options --target=aarch64-linux-android
 
 ac_add_options --with-branding=mobile/android/branding/beta
 
-export AR="$topsrcdir/clang/bin/llvm-ar"
-export NM="$topsrcdir/clang/bin/llvm-nm"
-export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+export AR="$MOZ_FETCHES_DIR/clang/bin/llvm-ar"
+export NM="$MOZ_FETCHES_DIR/clang/bin/llvm-nm"
+export RANLIB="$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib"
 
 export MOZ_LTO=cross
 
 export MOZILLA_OFFICIAL=1
 export MOZ_ANDROID_POCKET=1
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-aarch64/nightly
+++ b/mobile/android/config/mozconfigs/android-aarch64/nightly
@@ -3,18 +3,18 @@
 # Android
 ac_add_options --with-android-min-sdk=21
 ac_add_options --target=aarch64-linux-android
 
 ac_add_options --with-branding=mobile/android/branding/nightly
 
 export FENNEC_NIGHTLY=1
 
-export AR="$topsrcdir/clang/bin/llvm-ar"
-export NM="$topsrcdir/clang/bin/llvm-nm"
-export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+export AR="$MOZ_FETCHES_DIR/clang/bin/llvm-ar"
+export NM="$MOZ_FETCHES_DIR/clang/bin/llvm-nm"
+export RANLIB="$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib"
 
 export MOZ_LTO=cross
 
 export MOZILLA_OFFICIAL=1
 export MOZ_ANDROID_POCKET=1
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-api-16-gradle-dependencies/nightly
+++ b/mobile/android/config/mozconfigs/android-api-16-gradle-dependencies/nightly
@@ -6,20 +6,16 @@ MOZ_AUTOMATION_PACKAGE_TESTS=0
 MOZ_AUTOMATION_UPLOAD=0
 MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES=0
 
 NO_CACHE=1
 NO_NDK=1
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common"
 
-# Until normal mozconfigs also use MOZ_FETCHES_DIR
-ac_add_options --with-android-sdk="$MOZ_FETCHES_DIR/android-sdk-linux"
-export NODEJS=$MOZ_FETCHES_DIR/node/bin/node
-
 # We want to download Gradle.
 ac_add_options --with-gradle
 # We want to use (and populate!) the local Nexus repositories.
 export GRADLE_MAVEN_REPOSITORIES="http://localhost:8081/nexus/content/repositories/google/","http://localhost:8081/nexus/content/repositories/jcenter/","http://localhost:8081/nexus/content/repositories/gradle-plugins/"
 
 # From here on, just like ../android-api-16-frontend/nightly.
 
 . "$topsrcdir/build/mozconfig.no-compile"
--- a/mobile/android/config/mozconfigs/android-api-16/beta
+++ b/mobile/android/config/mozconfigs/android-api-16/beta
@@ -10,15 +10,15 @@ ac_add_options --with-android-min-sdk=16
 ac_add_options --target=arm-linux-androideabi
 
 ac_add_options --with-branding=mobile/android/branding/beta
 
 export MOZILLA_OFFICIAL=1
 export MOZ_ANDROID_MMA=1
 export MOZ_ANDROID_POCKET=1
 
-export AR="$topsrcdir/clang/bin/llvm-ar"
-export NM="$topsrcdir/clang/bin/llvm-nm"
-export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+export AR="$MOZ_FETCHES_DIR/clang/bin/llvm-ar"
+export NM="$MOZ_FETCHES_DIR/clang/bin/llvm-nm"
+export RANLIB="$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib"
 
 export MOZ_LTO=cross
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-api-16/nightly
+++ b/mobile/android/config/mozconfigs/android-api-16/nightly
@@ -12,15 +12,15 @@ ac_add_options --target=arm-linux-androi
 ac_add_options --with-branding=mobile/android/branding/nightly
 
 export FENNEC_NIGHTLY=1
 
 export MOZILLA_OFFICIAL=1
 export MOZ_ANDROID_MMA=1
 export MOZ_ANDROID_POCKET=1
 
-export AR="$topsrcdir/clang/bin/llvm-ar"
-export NM="$topsrcdir/clang/bin/llvm-nm"
-export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+export AR="$MOZ_FETCHES_DIR/clang/bin/llvm-ar"
+export NM="$MOZ_FETCHES_DIR/clang/bin/llvm-nm"
+export RANLIB="$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib"
 
 export MOZ_LTO=cross
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-x86/beta
+++ b/mobile/android/config/mozconfigs/android-x86/beta
@@ -8,15 +8,15 @@
 ac_add_options --target=i686-linux-android
 ac_add_options --with-android-min-sdk=16
 
 ac_add_options --with-branding=mobile/android/branding/beta
 
 export MOZILLA_OFFICIAL=1
 export MOZ_ANDROID_POCKET=1
 
-export AR="$topsrcdir/clang/bin/llvm-ar"
-export NM="$topsrcdir/clang/bin/llvm-nm"
-export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+export AR="$MOZ_FETCHES_DIR/clang/bin/llvm-ar"
+export NM="$MOZ_FETCHES_DIR/clang/bin/llvm-nm"
+export RANLIB="$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib"
 
 export MOZ_LTO=cross
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-x86/nightly
+++ b/mobile/android/config/mozconfigs/android-x86/nightly
@@ -10,15 +10,15 @@ ac_add_options --with-android-min-sdk=16
 
 ac_add_options --with-branding=mobile/android/branding/nightly
 
 export FENNEC_NIGHTLY=1
 
 export MOZILLA_OFFICIAL=1
 export MOZ_ANDROID_POCKET=1
 
-export AR="$topsrcdir/clang/bin/llvm-ar"
-export NM="$topsrcdir/clang/bin/llvm-nm"
-export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+export AR="$MOZ_FETCHES_DIR/clang/bin/llvm-ar"
+export NM="$MOZ_FETCHES_DIR/clang/bin/llvm-nm"
+export RANLIB="$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib"
 
 export MOZ_LTO=cross
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-x86_64/beta
+++ b/mobile/android/config/mozconfigs/android-x86_64/beta
@@ -1,18 +1,18 @@
 . "$topsrcdir/mobile/android/config/mozconfigs/common"
 
 # Android
 ac_add_options --with-android-min-sdk=21
 ac_add_options --target=x86_64-linux-android
 
 ac_add_options --with-branding=mobile/android/branding/beta
 
-export AR="$topsrcdir/clang/bin/llvm-ar"
-export NM="$topsrcdir/clang/bin/llvm-nm"
-export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+export AR="$MOZ_FETCHES_DIR/clang/bin/llvm-ar"
+export NM="$MOZ_FETCHES_DIR/clang/bin/llvm-nm"
+export RANLIB="$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib"
 
 export MOZ_LTO=cross
 
 export MOZILLA_OFFICIAL=1
 export MOZ_ANDROID_POCKET=1
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-x86_64/nightly
+++ b/mobile/android/config/mozconfigs/android-x86_64/nightly
@@ -3,18 +3,18 @@
 # Android
 ac_add_options --with-android-min-sdk=21
 ac_add_options --target=x86_64-linux-android
 
 ac_add_options --with-branding=mobile/android/branding/nightly
 
 export FENNEC_NIGHTLY=1
 
-export AR="$topsrcdir/clang/bin/llvm-ar"
-export NM="$topsrcdir/clang/bin/llvm-nm"
-export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
+export AR="$MOZ_FETCHES_DIR/clang/bin/llvm-ar"
+export NM="$MOZ_FETCHES_DIR/clang/bin/llvm-nm"
+export RANLIB="$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib"
 
 export MOZ_LTO=cross
 
 export MOZILLA_OFFICIAL=1
 export MOZ_ANDROID_POCKET=1
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/common
+++ b/mobile/android/config/mozconfigs/common
@@ -10,31 +10,31 @@ fi
 MOZ_AUTOMATION_L10N_CHECK=0
 . "$topsrcdir/build/mozconfig.common"
 
 # For Android builds in TaskCluster, the system image is Debian, and
 # we use the Java JRE/JDK from the system.  We use a custom clang for
 # the host compiler. Make sure clang uses the c++ headers included with
 # clang, rather than the system headers which leads to incompatibility
 # later (when linking against the clang-provided libstdc++).
-HOST_CC="$topsrcdir/clang/bin/clang --gcc-toolchain=$topsrcdir/clang"
-HOST_CXX="$topsrcdir/clang/bin/clang++ --gcc-toolchain=$topsrcdir/clang"
+HOST_CC="$MOZ_FETCHES_DIR/clang/bin/clang --gcc-toolchain=$MOZ_FETCHES_DIR/clang"
+HOST_CXX="$MOZ_FETCHES_DIR/clang/bin/clang++ --gcc-toolchain=$MOZ_FETCHES_DIR/clang"
 
 # Build Fennec
 ac_add_options --enable-application=mobile/android
-ac_add_options --with-android-sdk="$topsrcdir/android-sdk-linux"
+ac_add_options --with-android-sdk="$MOZ_FETCHES_DIR/android-sdk-linux"
 
-ac_add_options --with-gradle="$topsrcdir/android-gradle-dependencies/gradle-dist/bin/gradle"
-export GRADLE_MAVEN_REPOSITORIES="file://$topsrcdir/android-gradle-dependencies/google","file://$topsrcdir/android-gradle-dependencies/jcenter","file://$topsrcdir/android-gradle-dependencies/gradle-plugins"
+ac_add_options --with-gradle="$MOZ_FETCHES_DIR/android-gradle-dependencies/gradle-dist/bin/gradle"
+export GRADLE_MAVEN_REPOSITORIES="file://$MOZ_FETCHES_DIR/android-gradle-dependencies/google","file://$MOZ_FETCHES_DIR/android-gradle-dependencies/jcenter","file://$MOZ_FETCHES_DIR/android-gradle-dependencies/gradle-plugins"
 
 if [ -z "$NO_NDK" -a -z "$USE_ARTIFACT" ]; then
     # We use our own clang instead of the NDK's clang.
-    CC="$topsrcdir/clang/bin/clang"
-    CXX="$topsrcdir/clang/bin/clang++"
-    ac_add_options --with-android-ndk="$topsrcdir/android-ndk"
+    CC="$MOZ_FETCHES_DIR/clang/bin/clang"
+    CXX="$MOZ_FETCHES_DIR/clang/bin/clang++"
+    ac_add_options --with-android-ndk="$MOZ_FETCHES_DIR/android-ndk"
     # Enable static analysis plugin
     export ENABLE_CLANG_PLUGIN=1
 fi
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 
 ac_add_options --with-google-safebrowsing-api-keyfile=/builds/sb-gapi.data
 ac_add_options --with-google-location-service-api-keyfile=/builds/gls-gapi.data
@@ -85,17 +85,17 @@ elif test "$MOZ_UPDATE_CHANNEL" = "beta"
     ac_add_options --with-pocket-api-keyfile=/builds/pocket-api-beta.token
 elif test "$MOZ_UPDATE_CHANNEL" = "nightly" ; then
     ac_add_options --with-pocket-api-keyfile=/builds/pocket-api-nightly.token
 else
     ac_add_options --with-pocket-api-keyfile="$topsrcdir/mobile/android/base/pocket-api-sandbox.token"
 fi
 
 if [ -n "$MOZ_PGO_PROFILE_USE" ]; then
-    export LLVM_PROFDATA="$topsrcdir/clang/bin/llvm-profdata"
+    export LLVM_PROFDATA="$MOZ_FETCHES_DIR/clang/bin/llvm-profdata"
 
     ac_add_options --enable-profile-use
 
     # This is disabled because jarlog re-ordering breaks apk publishing tasks,
     # see bug 1539933.
     # ac_add_options --with-pgo-jarlog=/builds/worker/fetches/en-US.log
     ac_add_options --with-pgo-profile-path=/builds/worker/fetches
 fi
--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
@@ -925,17 +925,17 @@ class StaticAnalysis(MachCommandBase):
         self.TOOLS_CHECKER_NOT_FOUND = 7
         self.TOOLS_CHECKER_FAILED_FILE = 8
         self.TOOLS_CHECKER_LIST_EMPTY = 9
         self.TOOLS_GRADLE_FAILED = 10
 
         # Configure the tree or download clang-tidy package, depending on the option that we choose
         if intree_tool:
             _, config, _ = self._get_config_environment()
-            clang_tools_path = self.topsrcdir
+            clang_tools_path = os.environ['MOZ_FETCHES_DIR']
             self._clang_tidy_path = mozpath.join(
                 clang_tools_path, "clang-tidy", "bin",
                 "clang-tidy" + config.substs.get('BIN_SUFFIX', ''))
             self._clang_format_path = mozpath.join(
                 clang_tools_path, "clang-tidy", "bin",
                 "clang-format" + config.substs.get('BIN_SUFFIX', ''))
             self._clang_apply_replacements = mozpath.join(
                 clang_tools_path, "clang-tidy", "bin",
@@ -1808,17 +1808,17 @@ class StaticAnalysis(MachCommandBase):
                     args += [':({0}){1}'.format(','.join(magics), pattern)]
         return args
 
     def _get_infer(self, force=False, skip_cache=False, download_if_needed=True,
                    verbose=False, intree_tool=False):
         rc, config, _ = self._get_config_environment()
         if rc != 0:
             return rc
-        infer_path = self.topsrcdir if intree_tool else \
+        infer_path = os.environ['MOZ_FETCHES_DIR'] if intree_tool else \
             mozpath.join(self._mach_context.state_dir, 'infer')
         self._infer_path = mozpath.join(infer_path, 'infer', 'bin', 'infer' +
                                         config.substs.get('BIN_SUFFIX', ''))
         if intree_tool:
             return not os.path.exists(self._infer_path)
         if os.path.exists(self._infer_path) and not force:
             return 0
 
--- a/remote/doc/Debugging.md
+++ b/remote/doc/Debugging.md
@@ -6,9 +6,9 @@ Increasing the logging verbosity
 
 To increase the internal logging verbosity you can use the
 `remote.log.level` [preference].
 
 If you use mach to start the Firefox:
 
 	./mach run --setpref "remote.enabled=true" --setpref "remote.log.level=Debug" --remote-debugger
 
-[preference]: ./Prefs.md
+[preference]: ./Prefs.html
--- a/taskcluster/ci/artifact-build/kind.yml
+++ b/taskcluster/ci/artifact-build/kind.yml
@@ -5,17 +5,16 @@
 loader: taskgraph.loader.transform:loader
 
 kind-dependencies:
     - toolchain
 
 transforms:
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 jobs:
     linux64-artifact/opt:
         description: "Linux64 Opt Artifact Build"
         index:
             product: firefox
@@ -41,10 +40,11 @@ jobs:
                 - builds/releng_base_linux_64_builds.py
             script: "mozharness/scripts/fx_desktop_build.py"
             secrets: true
             tooltool-downloads: public
             need-xvfb: true
             keep-artifacts: false
         dependencies:
             linux64-opt: build-linux64/opt
-        toolchains:
-            - linux64-node
+        fetches:
+            toolchain:
+                - linux64-node
--- a/taskcluster/ci/build-fat-aar/kind.yml
+++ b/taskcluster/ci/build-fat-aar/kind.yml
@@ -8,26 +8,24 @@ kind-dependencies:
     - build
     - toolchain
 
 transforms:
     - taskgraph.transforms.build:transforms
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
     - taskgraph.transforms.build_fat_aar:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 job-defaults:
     attributes:
         artifact_map: taskcluster/taskgraph/manifests/fennec_geckoview.yml
     index:
         product: mobile
-    fetches: {}   # See build_fat_aar transform
     worker-type: b-linux
     worker:
         docker-image: {in-tree: android-build}
         max-run-time: 7200
         env:
             # Online in order to download the per-architecture AARs.
             GRADLE_USER_HOME: "/builds/worker/workspace/build/src/mobile/android/gradle/dotgradle-online"
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
@@ -53,26 +51,27 @@ job-defaults:
                 nightly-oak: nightly-oak
                 beta:
                     by-shipping-product:
                         devedition: aurora
                         default: beta
                 release.*: release
                 esr.*: esr
                 default: null
-    toolchains:
-        - android-gradle-dependencies
-        - android-ndk-linux
-        - android-sdk-linux
-        - linux64-clang
-        - linux64-rust-android
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - android-gradle-dependencies
+            - android-ndk-linux
+            - android-sdk-linux
+            - linux64-clang
+            - linux64-rust-android
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
 
 jobs:
     android-geckoview-fat-aar/opt:
         description: "Android GeckoView multi-architecture fat AAR Opt"
         index:
             job-name: android-geckoview-fat-aar-opt
         treeherder:
             platform: android-4-0-geckoview-fat-aar/opt
@@ -85,18 +84,19 @@ jobs:
         worker:
             env:
                 PERFHERDER_EXTRA_OPTIONS: android-geckoview-fat-aar-opt
                 USE_ARTIFACT: '1'
                 MOZ_ARTIFACT_TASK: {task-reference: '<android-api-16-opt>'}
         run:
             actions: [get-secrets, build]
             config: ["builds/releng_base_android_64_builds.py"]
-        toolchains:
-            - linux64-sccache
+        fetches:
+            toolchain:
+                - linux64-sccache
 
     android-geckoview-fat-aar-nightly/opt:
         description: "Android GeckoView multi-architecture fat AAR Nightly"
         attributes:
             nightly: true
             enable-full-crashsymbols: true
             disable-push-apk: true
         shipping-phase: build
--- a/taskcluster/ci/build/android-stuff.yml
+++ b/taskcluster/ci/build/android-stuff.yml
@@ -35,17 +35,18 @@ android-geckoview-docs/opt:
         using: mozharness
         actions: [get-secrets, build]
         config:
             - builds/releng_base_android_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: android-geckoview-docs
         tooltool-downloads: internal
-    toolchains:
-        - android-gradle-dependencies
-        - android-sdk-linux
-        - linux64-node
+    fetches:
+        toolchain:
+            - android-gradle-dependencies
+            - android-sdk-linux
+            - linux64-node
     optimization:
         skip-unless-changed:
             - "mobile/android/**/*.java"
             - "mobile/android/gradle.configure"
             - "**/*.gradle"
--- a/taskcluster/ci/build/android.yml
+++ b/taskcluster/ci/build/android.yml
@@ -26,26 +26,27 @@ job-defaults:
               path: /builds/worker/artifacts/
               type: directory
     run:
         using: mozharness
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         mozconfig-variant: null
         tooltool-downloads: internal
-    toolchains:
-        - android-gradle-dependencies
-        - android-ndk-linux
-        - android-sdk-linux
-        - linux64-clang
-        - linux64-rust-android
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - android-gradle-dependencies
+            - android-ndk-linux
+            - android-sdk-linux
+            - linux64-clang
+            - linux64-rust-android
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
 
 android-api-16/debug:
     description: "Android 4.0 api-16+ Debug"
     index:
         job-name: android-api-16-debug
     attributes:
         enable-full-crashsymbols: true
     treeherder:
@@ -54,18 +55,19 @@ android-api-16/debug:
     worker-type: b-linux
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: api-16-debug
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-x86/opt:
     description: "Android 4.2 x86 Opt"
     index:
         job-name: android-x86-opt
     attributes:
         enable-full-crashsymbols: true
     treeherder:
@@ -74,36 +76,38 @@ android-x86/opt:
     worker-type: b-linux
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android-x86/releng.manifest"
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: x86
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-x86-fuzzing/debug:
     description: "Android x86 Fuzzing Debug"
     index:
         job-name: android-x86-fuzzing-debug
     treeherder:
         platform: android-4-2-x86/debug
         symbol: Bf
     worker-type: b-linux
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android-x86/releng.manifest"
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: x86-fuzzing-debug
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-x86-nightly/opt:
     description: "Android 4.2 x86 Nightly"
     attributes:
         enable-full-crashsymbols: true
         nightly: true
     shipping-phase: build
     shipping-product: fennec
@@ -136,18 +140,19 @@ android-api-16/opt:
     worker-type: b-linux
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: api-16
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-api-16/pgo:
     description: "Android 4.0 api-16+ PGO"
     use-pgo: true
     index:
         job-name: android-api-16-pgo
     attributes:
         enable-full-crashsymbols: true
@@ -175,18 +180,19 @@ android-api-16-without-google-play-servi
         env:
             PERFHERDER_EXTRA_OPTIONS: android-api-16-without-google-play-services
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: api-16-without-google-play-services
     run-on-projects: ['mozilla-central']
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-api-16-nightly/opt:
     description: "Android 4.0 api-16+ Nightly"
     use-pgo: android-api-16/pgo
     attributes:
         enable-full-crashsymbols: true
         nightly: true
     shipping-phase: build
@@ -220,18 +226,19 @@ android-aarch64/opt:
     worker-type: b-linux
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: aarch64
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-aarch64/pgo:
     description: "Android 5.0 AArch64 PGO"
     use-pgo: android-api-16/pgo
     index:
         job-name: android-aarch64-pgo
     attributes:
         enable-full-crashsymbols: true
@@ -259,18 +266,19 @@ android-aarch64/debug:
     worker-type: b-linux
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: aarch64-debug
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-aarch64-nightly/opt:
     description: "Android 5.0 AArch64 Nightly"
     use-pgo: android-api-16/pgo
     attributes:
         enable-full-crashsymbols: true
         nightly: true
     shipping-phase: build
@@ -304,18 +312,19 @@ android-x86_64/opt:
     worker-type: b-linux
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android-x86/releng.manifest"
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: x86_64
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-x86_64-nightly/opt:
     description: "Android 5.0 x86-64 Nightly"
     attributes:
         enable-full-crashsymbols: true
         nightly: true
     shipping-phase: build
     shipping-product: fennec
@@ -348,18 +357,19 @@ android-x86_64/debug:
     worker-type: b-linux
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android-x86/releng.manifest"
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: x86_64-debug
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 
 android-api-16-gcp/debug:
     description: "Android 4.0 api-16+ Debug - built on GCP"
     index:
         job-name: android-api-16-gcp-debug
     attributes:
         enable-full-crashsymbols: true
@@ -371,18 +381,19 @@ android-api-16-gcp/debug:
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
             PERFHERDER_EXTRA_OPTIONS: gcp
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: api-16-debug
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 
 android-x86-gcp/opt:
     description: "Android 4.2 x86 Opt - built on GCP"
     index:
         job-name: android-x86-gcp-opt
     attributes:
         enable-full-crashsymbols: true
@@ -394,18 +405,19 @@ android-x86-gcp/opt:
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android-x86/releng.manifest"
             PERFHERDER_EXTRA_OPTIONS: gcp
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: x86
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-api-16-gcp/opt:
     description: "Android 4.0 api-16+ Opt - built on GCP"
     index:
         job-name: android-api-16-gcp-opt
     attributes:
         enable-full-crashsymbols: true
     treeherder:
@@ -416,18 +428,19 @@ android-api-16-gcp/opt:
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
             PERFHERDER_EXTRA_OPTIONS: gcp
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: api-16
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-aarch64-gcp/opt:
     description: "Android 5.0 AArch64 Opt - built on GCP"
     index:
         job-name: android-aarch64-gcp-opt
     attributes:
         enable-full-crashsymbols: true
     treeherder:
@@ -438,18 +451,19 @@ android-aarch64-gcp/opt:
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
             PERFHERDER_EXTRA_OPTIONS: gcp
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: aarch64
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-aarch64-gcp/debug:
     description: "Android 5.0 AArch64 Debug - built on GCP"
     index:
         job-name: android-aarch64-gcp-debug
     attributes:
         enable-full-crashsymbols: true
     treeherder:
@@ -460,18 +474,19 @@ android-aarch64-gcp/debug:
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
             PERFHERDER_EXTRA_OPTIONS: gcp
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: aarch64-debug
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-x86_64-gcp/opt:
     description: "Android 5.0 x86-64 Opt - built on GCP"
     index:
         job-name: android-x86_64-gcp-opt
     attributes:
         enable-full-crashsymbols: true
     treeherder:
@@ -482,18 +497,19 @@ android-x86_64-gcp/opt:
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android-x86/releng.manifest"
             PERFHERDER_EXTRA_OPTIONS: gcp
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: x86_64
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
 
 android-x86_64-gcp/debug:
     description: "Android 5.0 x86-64 Debug - built on GCP"
     index:
         job-name: android-x86_64-gcp-debug
     attributes:
         enable-full-crashsymbols: true
     treeherder:
@@ -504,10 +520,11 @@ android-x86_64-gcp/debug:
     worker:
         env:
             TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android-x86/releng.manifest"
             PERFHERDER_EXTRA_OPTIONS: gcp
     run:
         actions: [get-secrets, build]
         config: ["builds/releng_base_android_64_builds.py"]
         custom-build-variant-cfg: x86_64-debug
-    toolchains:
-        - linux64-sccache
+    fetches:
+        toolchain:
+            - linux64-sccache
--- a/taskcluster/ci/build/kind.yml
+++ b/taskcluster/ci/build/kind.yml
@@ -8,17 +8,16 @@ kind-dependencies:
     - toolchain
     - fetch
     - generate-profile
 
 transforms:
     - taskgraph.transforms.build:transforms
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 jobs-from:
     - android.yml
     - android-stuff.yml
     - linux.yml
     - macosx.yml
--- a/taskcluster/ci/build/linux.yml
+++ b/taskcluster/ci/build/linux.yml
@@ -21,25 +21,26 @@ linux64/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-plain/opt:
     description: "Linux64 Opt Plain"
     index:
         product: firefox
         job-name: linux64-plain-opt
     treeherder:
         platform: linux64/opt
@@ -58,23 +59,24 @@ linux64-plain/opt:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: mozharness/scripts/fx_desktop_build.py
         tooltool-downloads: public
         extra-config:
             disable_package_metrics: true
         mozconfig-variant: plain-opt
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-nasm
-        - linux64-node
-        - linux64-cbindgen
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-nasm
+            - linux64-node
+            - linux64-cbindgen
 
 linux64-fuzzing/debug:
     description: "Linux64 Fuzzing Debug"
     index:
         product: firefox
         job-name: linux64-fuzzing-debug
     treeherder:
         platform: linux64/debug
@@ -92,25 +94,26 @@ linux64-fuzzing/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: fuzzing-debug
         mozconfig-variant: debug-fuzzing
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-clang
-        - linux64-gcc
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-clang
+            - linux64-gcc
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-nasm
+            - linux64-node
 
 linux64/debug:
     description: "Linux64 Debug"
     index:
         product: firefox
         job-name: linux64-debug
     attributes:
         enable-full-crashsymbols: true
@@ -127,25 +130,26 @@ linux64/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-nasm
+            - linux64-node
 
 linux64-plain/debug:
     description: "Linux64 Debug Plain"
     index:
         product: firefox
         job-name: linux64-plain-debug
     treeherder:
         platform: linux64/debug
@@ -164,23 +168,24 @@ linux64-plain/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         extra-config:
             disable_package_metrics: true
         mozconfig-variant: plain-debug
         script: mozharness/scripts/fx_desktop_build.py
         tooltool-downloads: public
     run-on-projects: [trunk]
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-nasm
-        - linux64-node
-        - linux64-cbindgen
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-nasm
+            - linux64-node
+            - linux64-cbindgen
 
 linux64-devedition-nightly/opt:
     description: "Linux64 devedition Nightly"
     use-pgo: linux64-shippable/opt
     attributes:
         nightly: true
         enable-full-crashsymbols: true
     shipping-phase: build
@@ -205,24 +210,25 @@ linux64-devedition-nightly/opt:
         extra-config:
             stage_platform: 'linux64-devedition'
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
         mozconfig-variant: devedition
     run-on-projects: ['mozilla-beta']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
 
 linux64-base-toolchains/opt:
     description: "Linux64 base toolchains Opt"
     index:
         product: firefox
         job-name: linux64-base-toolchains-opt
     treeherder:
         platform: linux64/opt
@@ -239,24 +245,25 @@ linux64-base-toolchains/opt:
         actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-clang-4.0
-        - linux64-gcc-6
-        - linux64-rust-1.36
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm-2.13.02
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-clang-4.0
+            - linux64-gcc-6
+            - linux64-rust-1.36
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm-2.13.02
+            - linux64-node
 
 linux64-base-toolchains/debug:
     description: "Linux64 base toolchains Debug"
     index:
         product: firefox
         job-name: linux64-base-toolchains-debug
     treeherder:
         platform: linux64/debug
@@ -275,24 +282,25 @@ linux64-base-toolchains/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-clang-4.0
-        - linux64-gcc-6
-        - linux64-rust-1.36
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm-2.13.02
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-clang-4.0
+            - linux64-gcc-6
+            - linux64-rust-1.36
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm-2.13.02
+            - linux64-node
 
 linux64-base-toolchains-clang/opt:
     description: "Linux64 base toolchains clang Opt"
     index:
         product: firefox
         job-name: linux64-base-toolchains-clang-opt
     treeherder:
         platform: linux64/opt
@@ -308,23 +316,24 @@ linux64-base-toolchains-clang/opt:
         actions: [get-secrets, build, check-test]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang-4.0
-        - linux64-rust-1.36
-        - linux64-cbindgen
-        - linux64-nasm-2.13.02
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang-4.0
+            - linux64-rust-1.36
+            - linux64-cbindgen
+            - linux64-nasm-2.13.02
+            - linux64-node
 
 linux64-base-toolchains-clang/debug:
     description: "Linux64 base toolchains clang Debug"
     index:
         product: firefox
         job-name: linux64-base-toolchains-clang-debug
     treeherder:
         platform: linux64/debug
@@ -342,23 +351,24 @@ linux64-base-toolchains-clang/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang-4.0
-        - linux64-rust-1.36
-        - linux64-cbindgen
-        - linux64-nasm-2.13.02
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang-4.0
+            - linux64-rust-1.36
+            - linux64-cbindgen
+            - linux64-nasm-2.13.02
+            - linux64-node
 
 linux/opt:
     description: "Linux32 Opt"
     index:
         product: firefox
         job-name: linux-opt
     attributes:
         enable-full-crashsymbols: true
@@ -375,25 +385,26 @@ linux/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux/debug:
     description: "Linux32 Debug"
     index:
         product: firefox
         job-name: linux-debug
     attributes:
         enable-full-crashsymbols: true
@@ -411,25 +422,26 @@ linux/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux-rusttests/opt:
     description: "Linux32 Rust Tests Opt"
     index:
         product: firefox
         job-name: linux-rusttests-opt
     treeherder:
         platform: linux32/opt
@@ -450,24 +462,25 @@ linux-rusttests/opt:
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: rusttests
         mozconfig-variant: rusttests
         tooltool-downloads: public
         keep-artifacts: false
         need-xvfb: true
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux-rusttests/debug:
     description: "Linux32 Rust Tests Debug"
     index:
         product: firefox
         job-name: linux-rusttests-debug
     treeherder:
         platform: linux32/debug
@@ -488,24 +501,25 @@ linux-rusttests/debug:
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: rusttests-debug
         mozconfig-variant: rusttests-debug
         tooltool-downloads: public
         keep-artifacts: false
         need-xvfb: true
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux-devedition-nightly/opt:
     description: "Linux32 devedition Nightly"
     use-pgo: linux-shippable/opt
     attributes:
         nightly: true
         enable-full-crashsymbols: true
     shipping-phase: build
@@ -531,24 +545,25 @@ linux-devedition-nightly/opt:
         extra-config:
             stage_platform: linux-devedition
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
         mozconfig-variant: devedition
     run-on-projects: ['mozilla-beta']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
 
 linux-shippable/opt:
     description: "Linux32 Shippable"
     use-pgo: true
     attributes:
         shippable: true
         enable-full-crashsymbols: true
     shipping-phase: build
@@ -570,24 +585,25 @@ linux-shippable/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
 
 linux64-asan/opt:
     description: "Linux64 Opt ASAN"
     index:
         product: firefox
         job-name: linux64-asan-opt
     treeherder:
         platform: linux64/asan
@@ -605,25 +621,26 @@ linux64-asan/opt:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: asan-tc
         mozconfig-variant: nightly-asan
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-asan-fuzzing/opt:
     description: "Linux64 Fuzzing Opt ASAN"
     index:
         product: firefox
         job-name: linux64-fuzzing-asan-opt
     treeherder:
         platform: linux64/asan
@@ -641,25 +658,26 @@ linux64-asan-fuzzing/opt:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: fuzzing-asan-tc
         mozconfig-variant: nightly-fuzzing-asan
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-asan-fuzzing-ccov/opt:
     description: "Linux64 Fuzzing Opt ASAN w/ Coverage"
     index:
         product: firefox
         job-name: linux64-ccov-fuzzing-asan-opt
     treeherder:
         platform: linux64/asan
@@ -677,25 +695,26 @@ linux64-asan-fuzzing-ccov/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         mozconfig-variant: asan-fuzzing-ccov
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-fuzzing-ccov/opt:
     description: "Linux64 Fuzzing Opt w/ Coverage"
     index:
         product: firefox
         job-name: linux64-ccov-fuzzing-opt
     treeherder:
         platform: linux64/opt
@@ -714,25 +733,26 @@ linux64-fuzzing-ccov/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         mozconfig-variant: fuzzing-ccov
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-clang
-        - linux64-gcc
-        - linux64-cbindgen
-        - linux64-rust-nightly
-        - linux64-rust-size
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-clang
+            - linux64-gcc
+            - linux64-cbindgen
+            - linux64-rust-nightly
+            - linux64-rust-size
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-asan-reporter-nightly/opt:
     description: "Linux64 Opt ASAN Reporter Nightly"
     attributes:
         nightly: true
     shipping-product:
         by-release-type:
             nightly: firefox
@@ -761,24 +781,25 @@ linux64-asan-reporter-nightly/opt:
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: asan-reporter-tc
         mozconfig-variant: nightly-asan-reporter
         tooltool-downloads: public
         need-xvfb: true
         mar-channel-id:
             firefox-mozilla-central-asan
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
 
 linux64-asan/debug:
     description: "Linux64 Debug ASAN"
     index:
         product: firefox
         job-name: linux64-asan-debug
     treeherder:
         platform: linux64/asan
@@ -796,25 +817,26 @@ linux64-asan/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: asan-tc-and-debug
         mozconfig-variant: debug-asan
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-shippable/opt:
     description: "Linux64 Shippable"
     use-pgo: true
     attributes:
         shippable: true
         enable-full-crashsymbols: true
     shipping-phase: build
@@ -835,24 +857,25 @@ linux64-shippable/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
 
 linux64-noopt/debug:
     description: "Linux64 No-optimize Debug"
     index:
         product: firefox
         job-name: linux64-noopt-debug
     treeherder:
         platform: linux64-noopt/debug
@@ -872,25 +895,26 @@ linux64-noopt/debug:
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: noopt-debug
         mozconfig-variant: noopt-debug
         tooltool-downloads: public
         keep-artifacts: false
         need-xvfb: true
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-rusttests/opt:
     description: "Linux64 Rust Tests Opt"
     index:
         product: firefox
         job-name: linux64-rusttests-opt
     treeherder:
         platform: linux64/opt
@@ -910,24 +934,25 @@ linux64-rusttests/opt:
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: rusttests
         mozconfig-variant: rusttests
         tooltool-downloads: public
         keep-artifacts: false
         need-xvfb: true
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-rusttests/debug:
     description: "Linux64 Rust Tests Debug"
     index:
         product: firefox
         job-name: linux64-rusttests-debug
     treeherder:
         platform: linux64/debug
@@ -947,24 +972,25 @@ linux64-rusttests/debug:
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: rusttests-debug
         mozconfig-variant: rusttests-debug
         tooltool-downloads: public
         keep-artifacts: false
         need-xvfb: true
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-tup/opt:
     description: "Linux64 Tup"
     index:
         product: firefox
         job-name: linux64-tup-opt
     treeherder:
         platform: linux64/opt
@@ -983,25 +1009,26 @@ linux64-tup/opt:
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: tup
         mozconfig-variant: tup
         tooltool-downloads: public
         need-xvfb: true
     run-on-projects: []
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust-nightly
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-tup
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust-nightly
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-tup
+            - linux64-nasm
+            - linux64-node
 
 linux64-ccov/debug:
     description: "Linux64-CCov Debug"
     index:
         product: firefox
         job-name: linux64-ccov-debug
     treeherder:
         platform: linux64-ccov/debug
@@ -1024,27 +1051,26 @@ linux64-ccov/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage-debug
         mozconfig-variant: code-coverage-debug
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-clang-8
-        - linux64-rust-nightly
-        - linux64-gcc
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
     fetches:
         toolchain:
+            - linux64-clang-8
+            - linux64-rust-nightly
+            - linux64-gcc
             - linux64-grcov
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-ccov/opt:
     description: "Linux64-CCov Opt"
     index:
         product: firefox
         job-name: linux64-ccov-opt
     treeherder:
         platform: linux64-ccov/opt
@@ -1063,24 +1089,25 @@ linux64-ccov/opt:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage-opt
         mozconfig-variant: code-coverage-opt
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-clang-8
-        - linux64-rust-nightly
-        - linux64-gcc
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-clang-8
+            - linux64-rust-nightly
+            - linux64-gcc
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-add-on-devel/opt:
     description: "Linux64 add-on-devel"
     index:
         product: firefox
         job-name: linux64-add-on-devel
     treeherder:
         platform: linux64-add-on-devel/opt
@@ -1097,25 +1124,26 @@ linux64-add-on-devel/opt:
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: add-on-devel
         mozconfig-variant: add-on-devel
         tooltool-downloads: public
         need-xvfb: true
     run-on-projects: ['mozilla-beta', 'mozilla-release', 'mozilla-esr45']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-aarch64/opt:
     description: "Linux64 aarch64 Opt"
     index:
         product: firefox
         job-name: linux64-aarch64-opt
     attributes:
         enable-full-crashsymbols: true
@@ -1135,24 +1163,25 @@ linux64-aarch64/opt:
             - builds/releng_base_linux_64_builds.py
         extra-config:
             mozconfig_platform: linux64-aarch64
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         mozconfig-variant: opt
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-node
 
 linux-gcp/debug:
     description: "Linux32 Debug - built on GCP"
     index:
         product: firefox
         job-name: linux-gcp-debug
     attributes:
         enable-full-crashsymbols: true
@@ -1173,25 +1202,26 @@ linux-gcp/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux-gcp/opt:
     description: "Linux32 Opt - built on GCP"
     index:
         product: firefox
         job-name: linux-gcp-opt
     attributes:
         enable-full-crashsymbols: true
@@ -1211,25 +1241,26 @@ linux-gcp/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_32_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 linux64-gcp/debug:
     description: "Linux64 Debug - built on GCP"
     index:
         product: firefox
         job-name: linux64-gcp-debug
     attributes:
         enable-full-crashsymbols: true
@@ -1249,25 +1280,26 @@ linux64-gcp/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
         need-xvfb: true
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-nasm
+            - linux64-node
 
 linux64-gcp/opt:
     description: "Linux64 Opt - built on GCP"
     index:
         product: firefox
         job-name: linux64-gcp-opt
     attributes:
         enable-full-crashsymbols: true
@@ -1286,17 +1318,18 @@ linux64-gcp/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
--- a/taskcluster/ci/build/macosx.yml
+++ b/taskcluster/ci/build/macosx.yml
@@ -24,29 +24,30 @@ macosx64/debug:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-debug
         mozconfig-variant: debug
         tooltool-downloads: internal
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 macosx64/opt:
     description: "MacOS X x64 Cross-compile"
     index:
         product: firefox
         job-name: macosx64-opt
     attributes:
         enable-full-crashsymbols: true
@@ -64,29 +65,30 @@ macosx64/opt:
         actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: internal
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 macosx64-asan-fuzzing/opt:
     description: "MacOS X x64 Cross-compile Fuzzing ASAN"
     index:
         product: firefox
         job-name: macosx64-fuzzing-asan-opt
     treeherder:
         platform: osx-cross/asan
@@ -103,29 +105,30 @@ macosx64-asan-fuzzing/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-fuzzing-asan
         mozconfig-variant: nightly-fuzzing-asan
         tooltool-downloads: internal
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 macosx64-fuzzing/debug:
     description: "MacOS X x64 Cross-compile Fuzzing Debug"
     index:
         product: firefox
         job-name: macosx64-fuzzing-debug
     attributes:
         enable-full-crashsymbols: true
@@ -144,29 +147,30 @@ macosx64-fuzzing/debug:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-fuzzing-debug
         mozconfig-variant: debug-fuzzing
         tooltool-downloads: internal
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 macosx64-devedition-nightly/opt:
     description: "MacOS X Dev Edition x64 Nightly"
     attributes:
         nightly: true
         enable-full-crashsymbols: true
     shipping-phase: build
     shipping-product: devedition
@@ -192,28 +196,29 @@ macosx64-devedition-nightly/opt:
             - taskcluster_nightly.py
         extra-config:
             stage_platform: macosx64-devedition
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: internal
         mozconfig-variant: devedition
     run-on-projects: ['mozilla-beta']
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
 
 macosx64-noopt/debug:
     description: "MacOS X x64 No-optimize Debug"
     index:
         product: firefox
         job-name: macosx64-noopt-debug
     treeherder:
         platform: osx-cross-noopt/debug
@@ -232,29 +237,30 @@ macosx64-noopt/debug:
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-noopt-debug
         mozconfig-variant: cross-noopt-debug
         tooltool-downloads: internal
         keep-artifacts: false
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 macosx64-add-on-devel/opt:
     description: "MacOS X x64 add-on-devel"
     index:
         product: firefox
         job-name: macosx64-add-on-devel
     treeherder:
         platform: osx-cross-add-on-devel/opt
@@ -272,29 +278,30 @@ macosx64-add-on-devel/opt:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: add-on-devel
         mozconfig-variant: add-on-devel
         tooltool-downloads: internal
     run-on-projects: ['mozilla-beta', 'mozilla-release', 'mozilla-esr45']
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 macosx64-shippable/opt:
     description: "MacOS X x64 Cross-compile"
     attributes:
         shippable: true
         enable-full-crashsymbols: true
     shipping-phase: build
     shipping-product: firefox
@@ -316,28 +323,29 @@ macosx64-shippable/opt:
         actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: internal
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
 
 macosx64-ccov/debug:
     description: "MacOS X x64 Cross-compile Code Coverage"
     index:
         product: firefox
         job-name: macosx64-ccov-debug
     treeherder:
         platform: osx-cross-ccov/debug
@@ -355,29 +363,30 @@ macosx64-ccov/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage-debug
         mozconfig-variant: code-coverage-debug
         tooltool-downloads: internal
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-nightly-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-nightly-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 macosx64-gcp/debug:
     description: "MacOS X x64 Cross-compile - built on GCP"
     index:
         product: firefox
         job-name: macosx64-gcp-debug
     attributes:
         enable-full-crashsymbols: true
@@ -397,29 +406,30 @@ macosx64-gcp/debug:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-debug
         mozconfig-variant: debug
         tooltool-downloads: internal
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
 
 macosx64-gcp/opt:
     description: "MacOS X x64 Cross-compile - built on GCP"
     index:
         product: firefox
         job-name: macosx64-gcp-opt
     attributes:
         enable-full-crashsymbols: true
@@ -438,21 +448,22 @@ macosx64-gcp/opt:
         actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: internal
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - linux64-binutils
-        - linux64-cctools-port
-        - linux64-clang-macosx-cross
-        - linux64-hfsplus
-        - linux64-libdmg
-        - linux64-llvm-dsymutil
-        - linux64-rust-macos
-        - linux64-rust-size
-        - linux64-cbindgen
-        - linux64-sccache
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-cctools-port
+            - linux64-clang-macosx-cross
+            - linux64-hfsplus
+            - linux64-libdmg
+            - linux64-llvm-dsymutil
+            - linux64-rust-macos
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-nasm
+            - linux64-node
--- a/taskcluster/ci/build/windows-mingw.yml
+++ b/taskcluster/ci/build/windows-mingw.yml
@@ -26,27 +26,28 @@ win32-mingwclang/opt:
         env:
             PERFHERDER_EXTRA_OPTIONS: "opt 32 clang"
     run:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_windows_32_mingw_builds.py
             - builds/releng_sub_windows_configs/32_mingwclang.py
         mozconfig-variant: mingwclang
-    toolchains:
-        - mingw32-rust
-        - linux64-upx
-        - linux64-wine
-        - linux64-sccache
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
-        - linux64-clang-mingw-x86
-        - linux64-mingw32-nsis
-        - linux64-mingw-fxc2-x86
+    fetches:
+        toolchain:
+            - mingw32-rust
+            - linux64-upx
+            - linux64-wine
+            - linux64-sccache
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
+            - linux64-clang-mingw-x86
+            - linux64-mingw32-nsis
+            - linux64-mingw-fxc2-x86
 
 win32-mingwclang/debug:
     description: "Win32 MinGW-Clang Debug"
     index:
         product: firefox
         job-name: win32-mingwclang-debug
     treeherder:
         platform: windows-mingw32/all
@@ -56,27 +57,28 @@ win32-mingwclang/debug:
         env:
             PERFHERDER_EXTRA_OPTIONS: "debug 32 clang"
     run:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_windows_32_mingw_builds.py
             - builds/releng_sub_windows_configs/32_mingwclang.py
         mozconfig-variant: mingwclang-debug
-    toolchains:
-        - mingw32-rust
-        - linux64-upx
-        - linux64-wine
-        - linux64-sccache
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
-        - linux64-clang-mingw-x86
-        - linux64-mingw32-nsis
-        - linux64-mingw-fxc2-x86
+    fetches:
+        toolchain:
+            - mingw32-rust
+            - linux64-upx
+            - linux64-wine
+            - linux64-sccache
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
+            - linux64-clang-mingw-x86
+            - linux64-mingw32-nsis
+            - linux64-mingw-fxc2-x86
 
 win64-mingwclang/opt:
     description: "Win64 MinGW-Clang Opt"
     index:
         product: firefox
         job-name: win64-mingwclang-opt
     treeherder:
         platform: windows-mingw32/all
@@ -86,27 +88,28 @@ win64-mingwclang/opt:
         env:
             PERFHERDER_EXTRA_OPTIONS: "opt 64 clang"
     run:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_windows_64_mingw_builds.py
             - builds/releng_sub_windows_configs/64_mingwclang.py
         mozconfig-variant: mingwclang
-    toolchains:
-        - mingw32-rust
-        - linux64-upx
-        - linux64-wine
-        - linux64-sccache
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
-        - linux64-clang-mingw-x64
-        - linux64-mingw32-nsis
-        - linux64-mingw-fxc2-x86
+    fetches:
+        toolchain:
+            - mingw32-rust
+            - linux64-upx
+            - linux64-wine
+            - linux64-sccache
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
+            - linux64-clang-mingw-x64
+            - linux64-mingw32-nsis
+            - linux64-mingw-fxc2-x86
 
 win64-mingwclang/debug:
     description: "Win64 MinGW-Clang Debug"
     index:
         product: firefox
         job-name: win64-mingwclang-debug
     treeherder:
         platform: windows-mingw32/all
@@ -116,19 +119,20 @@ win64-mingwclang/debug:
         env:
             PERFHERDER_EXTRA_OPTIONS: "debug 64 clang"
     run:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_windows_64_mingw_builds.py
             - builds/releng_sub_windows_configs/64_mingwclang.py
         mozconfig-variant: mingwclang-debug
-    toolchains:
-        - mingw32-rust
-        - linux64-upx
-        - linux64-wine
-        - linux64-sccache
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
-        - linux64-clang-mingw-x64
-        - linux64-mingw32-nsis
-        - linux64-mingw-fxc2-x86
+    fetches:
+        toolchain:
+            - mingw32-rust
+            - linux64-upx
+            - linux64-wine
+            - linux64-sccache
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
+            - linux64-clang-mingw-x64
+            - linux64-mingw32-nsis
+            - linux64-mingw-fxc2-x86
--- a/taskcluster/ci/build/windows.yml
+++ b/taskcluster/ci/build/windows.yml
@@ -28,24 +28,25 @@ win32/debug:
         script: mozharness/scripts/fx_desktop_build.py
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win32.py
             - builds/taskcluster_sub_win32/debug.py
         mozconfig-variant: debug
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win32/opt:
     description: "Win32 Opt"
     index:
         product: firefox
         job-name: win32-opt
     attributes:
         enable-full-crashsymbols: true
@@ -64,24 +65,25 @@ win32/opt:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win32.py
         extra-config:
             stage_platform: win32
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64/debug:
     description: "Win64 Debug"
     index:
         product: firefox
         job-name: win64-debug
     attributes:
         enable-full-crashsymbols: true
@@ -99,24 +101,25 @@ win64/debug:
         script: mozharness/scripts/fx_desktop_build.py
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - builds/taskcluster_sub_win64/debug.py
         mozconfig-variant: debug
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-fuzzing/debug:
     description: "Win64 Fuzzing Debug"
     index:
         product: firefox
         job-name: win64-fuzzing-debug
     attributes:
         enable-full-crashsymbols: true
@@ -136,24 +139,25 @@ win64-fuzzing/debug:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - builds/taskcluster_sub_win64/debug.py
         mozconfig-variant: debug-fuzzing
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-plain/debug:
     description: "Win64 Debug Plain"
     index:
         product: firefox
         job-name: win64-plain-debug
     treeherder:
         platform: windows2012-64/debug
@@ -173,22 +177,23 @@ win64-plain/debug:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
         extra-config:
             disable_package_metrics: true
             stage_platform: win64
         mozconfig-variant: plain-debug
     run-on-projects: ['trunk']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-node
-        - win64-nasm
-        - win64-cbindgen
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-node
+            - win64-nasm
+            - win64-cbindgen
 
 win64/opt:
     description: "Win64 Opt"
     index:
         product: firefox
         job-name: win64-opt
     attributes:
         enable-full-crashsymbols: true
@@ -207,24 +212,25 @@ win64/opt:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
         extra-config:
             stage_platform: win64
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-plain/opt:
     description: "Win64 Opt Plain"
     index:
         product: firefox
         job-name: win64-plain-opt
     treeherder:
         platform: windows2012-64/opt
@@ -244,22 +250,23 @@ win64-plain/opt:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
         extra-config:
             disable_package_metrics: true
             stage_platform: win64
         mozconfig-variant: plain-opt
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-nasm
-        - win64-node
-        - win64-cbindgen
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-nasm
+            - win64-node
+            - win64-cbindgen
 
 win32-shippable/opt:
     description: "Win32 Opt Shippable"
     use-pgo: true
     index:
         product: firefox
         job-name: win32-opt
         type: shippable
@@ -294,23 +301,24 @@ win32-shippable/opt:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win32.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: win32
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-nasm
+            - win64-node
 
 win64-shippable/opt:
     description: "Win64 Shippable"
     use-pgo: true
     index:
         product: firefox
         job-name: win64-opt
         type: shippable
@@ -334,23 +342,24 @@ win64-shippable/opt:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: win64
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-nasm
+            - win64-node
 
 win32-add-on-devel/opt:
     description: "Windows32 add-on-devel"
     index:
         product: firefox
         job-name: win32-add-on-devel
     treeherder:
         platform: windows2012-32-add-on-devel/opt
@@ -368,24 +377,25 @@ win32-add-on-devel/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win32.py
         extra-config:
             stage_platform: win32-add-on-devel
         mozconfig-variant: add-on-devel
     run-on-projects: ['mozilla-beta', 'mozilla-release']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-add-on-devel/opt:
     description: "Windows64 add-on-devel"
     index:
         product: firefox
         job-name: win64-add-on-devel
     treeherder:
         platform: windows2012-64-add-on-devel/opt
@@ -403,24 +413,25 @@ win64-add-on-devel/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
         extra-config:
             stage_platform: win64-on-devel
         mozconfig-variant: add-on-devel
     run-on-projects: ['mozilla-beta', 'mozilla-release']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-noopt/debug:
     description: "Win64 No-optimize Debug"
     index:
         product: firefox
         job-name: win64-noopt-debug
     treeherder:
         platform: windows2012-64-noopt/debug
@@ -437,24 +448,25 @@ win64-noopt/debug:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - builds/taskcluster_sub_win64/noopt_debug.py
         mozconfig-variant: noopt-debug
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win32-noopt/debug:
     description: "Win32 No-optimize Debug"
     index:
         product: firefox
         job-name: win32-noopt-debug
     treeherder:
         platform: windows2012-32-noopt/debug
@@ -471,24 +483,25 @@ win32-noopt/debug:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win32.py
             - builds/taskcluster_sub_win32/noopt_debug.py
         mozconfig-variant: noopt-debug
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win32-rusttests/opt:
     description: "Win32 Rust Tests Opt"
     index:
         product: firefox
         job-name: win32-rusttests-opt
     treeherder:
         platform: windows2012-32/opt
@@ -510,23 +523,24 @@ win32-rusttests/opt:
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win32.py
         extra-config:
             stage_platform: win32-rusttests
             build_targets: ['pre-export', 'export', 'recurse_rusttests']
             disable_package_metrics: true
         mozconfig-variant: rusttests
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win32-rusttests/debug:
     description: "Win32 Rust Tests Debug"
     index:
         product: firefox
         job-name: win32-rusttests-debug
     treeherder:
         platform: windows2012-32/debug
@@ -548,23 +562,24 @@ win32-rusttests/debug:
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win32.py
         extra-config:
             stage_platform: win32-rusttests
             build_targets: ['pre-export', 'export', 'recurse_rusttests']
             disable_package_metrics: true
         mozconfig-variant: rusttests-debug
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-rusttests/opt:
     description: "Win64 Rust Tests Opt"
     index:
         product: firefox
         job-name: win64-rusttests-opt
     treeherder:
         platform: windows2012-64/opt
@@ -583,23 +598,24 @@ win64-rusttests/opt:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - builds/taskcluster_sub_win64/rusttests_opt.py
         mozconfig-variant: rusttests
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-rusttests/debug:
     description: "Win64 Rust Tests Debug"
     index:
         product: firefox
         job-name: win64-rusttests-debug
     treeherder:
         platform: windows2012-64/debug
@@ -618,23 +634,24 @@ win64-rusttests/debug:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - builds/taskcluster_sub_win64/rusttests_opt.py
         mozconfig-variant: rusttests-debug
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-ccov/debug:
     description: "Win64 Debug Code Coverage"
     index:
         product: firefox
         job-name: win64-ccov-debug
     treeherder:
         platform: windows2012-64/ccov
@@ -655,27 +672,26 @@ win64-ccov/debug:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - builds/taskcluster_sub_win64/ccov_debug.py
         mozconfig-variant: code-coverage
     run-on-projects: ['mozilla-central', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust-nightly
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
     fetches:
         toolchain:
+            - win64-clang-cl
+            - win64-rust-nightly
+            - win64-rust-size
+            - win64-cbindgen
             - win64-grcov
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-asan/debug:
     description: "Win64 Debug ASAN"
     index:
         product: firefox
         job-name: win64-asan-debug
     treeherder:
         platform: windows2012-64/asan
@@ -693,24 +709,25 @@ win64-asan/debug:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - builds/taskcluster_sub_win64/asan_debug.py
         mozconfig-variant: debug-asan
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-asan/opt:
     description: "Win64 Opt ASAN"
     index:
         product: firefox
         job-name: win64-asan-opt
     treeherder:
         platform: windows2012-64/asan
@@ -729,24 +746,25 @@ win64-asan/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
         extra-config:
             stage_platform: win64-asan
         mozconfig-variant: nightly-asan
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-asan-reporter-nightly/opt:
     description: "Win64 Opt ASAN Reporter Nightly"
     attributes:
         nightly: true
     shipping-product:
         by-release-type:
             nightly: firefox
@@ -775,23 +793,24 @@ win64-asan-reporter-nightly/opt:
             - builds/taskcluster_sub_win64/asan_reporter_opt.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: win64-asan-reporter
         mozconfig-variant: nightly-asan-reporter
         mar-channel-id:
             firefox-mozilla-central-asan
     run-on-projects: ['mozilla-central']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-nasm
+            - win64-node
 
 win64-asan-fuzzing/opt:
     description: "Win64 Fuzzing Opt ASAN"
     index:
         product: firefox
         job-name: win64-fuzzing-asan-opt
     treeherder:
         platform: windows2012-64/asan
@@ -809,24 +828,25 @@ win64-asan-fuzzing/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
         extra-config:
             stage_platform: win64-fuzzing-asan
         mozconfig-variant: nightly-fuzzing-asan
     run-on-projects: ['trunk', 'try']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win32-devedition-nightly/opt:
     description: "Win32 Dev Edition Nightly"
     use-pgo: win32-shippable/opt
     index:
         product: devedition
         job-name: win32-opt
         type: nightly
@@ -862,23 +882,24 @@ win32-devedition-nightly/opt:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win32.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: win32-devedition
         mozconfig-variant: devedition
     run-on-projects: ['mozilla-beta']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-nasm
+            - win64-node
 
 win64-devedition-nightly/opt:
     description: "Win64 Dev Edition Nightly"
     use-pgo: win64-shippable/opt
     index:
         product: devedition
         job-name: win64-opt
         type: nightly
@@ -904,23 +925,24 @@ win64-devedition-nightly/opt:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: win64-devedition
         mozconfig-variant: devedition
     run-on-projects: ['mozilla-beta']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-nasm
+            - win64-node
 
 win64-aarch64/debug:
     description: "AArch64 Win64 Debug"
     index:
         product: firefox
         job-name: win64-aarch64-debug
     attributes:
         enable-full-crashsymbols: true
@@ -941,24 +963,25 @@ win64-aarch64/debug:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_sub_win64/debug.py
         extra-config:
             mozconfig_platform: win64-aarch64
         mozconfig-variant: debug
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-aarch64/opt:
     description: "AArch64 Win64 Opt"
     index:
         product: firefox
         job-name: win64-aarch64-opt
     attributes:
         enable-full-crashsymbols: true
@@ -979,24 +1002,25 @@ win64-aarch64/opt:
         secrets: true
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
         extra-config:
             stage_platform: win64-aarch64
             mozconfig_platform: win64-aarch64
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-sccache
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-sccache
+            - win64-nasm
+            - win64-node
 
 win64-aarch64-eme/opt:
     description: "AArch64 Win64 Opt w/ EME"
     index:
         product: firefox
         job-name: win64-aarch64-eme-opt
     treeherder:
         platform: windows2012-aarch64/opt
@@ -1021,18 +1045,19 @@ win64-aarch64-eme/opt:
             - builds/taskcluster_base_windows.py
             - builds/taskcluster_base_win64.py
         extra-config:
             stage_platform: win64-aarch64
             mozconfig_platform: win64-aarch64
     dependencies:
         win32-opt: build-win32/opt
         win64-aarch64-opt: build-win64-aarch64/opt
-    toolchains:
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-node
 
 win64-aarch64-shippable/opt:
     description: "AArch64 Win64 Shippable"
     index:
         product: firefox
         job-name: win64-aarch64-opt
         type: shippable
     attributes:
@@ -1109,18 +1134,18 @@ win64-aarch64-shippable/opt:
               extract: false
               dest: ../public/build
             - artifact: target.generated-files.tar.gz
               extract: false
               dest: ../public/build
             - artifact: target.langpack.xpi
               extract: false
               dest: ../public/build
-    toolchains:
-        - win64-node
+        toolchain:
+            - win64-node
 
 win64-aarch64-shippable-no-eme/opt:
     description: "AArch64 Win64 Shippable w/o EME"
     use-pgo: win64-shippable/opt
     index:
         product: firefox
         job-name: win64-aarch64-no-eme-opt
         type: shippable
@@ -1146,23 +1171,24 @@ win64-aarch64-shippable-no-eme/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: win64-aarch64
             mozconfig_platform: win64-aarch64
     run-on-projects: []
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-nasm
+            - win64-node
 
 
 win64-aarch64-devedition-nightly/opt:
     description: "AArch64 Win64 MSVC Devedition Nightly"
     index:
         product: devedition
         job-name: win64-aarch64-opt
         type: nightly
@@ -1190,15 +1216,16 @@ win64-aarch64-devedition-nightly/opt:
             - builds/releng_base_firefox.py
             - builds/taskcluster_base_windows.py
             - taskcluster_nightly.py
         extra-config:
             stage_platform: win64-aarch64
             mozconfig_platform: win64-aarch64
         mozconfig-variant: devedition
     run-on-projects: ['mozilla-beta']
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
-        - win64-rust-size
-        - win64-cbindgen
-        - win64-nasm
-        - win64-node
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
+            - win64-rust-size
+            - win64-cbindgen
+            - win64-nasm
+            - win64-node
--- a/taskcluster/ci/diffoscope/kind.yml
+++ b/taskcluster/ci/diffoscope/kind.yml
@@ -5,17 +5,16 @@
 loader: taskgraph.loader.transform:loader
 
 kind-dependencies:
     - build
     - toolchain
 
 transforms:
     - taskgraph.transforms.diffoscope:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 # Note: --exclude-command .--line-numbers is because of
 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=879003
 # That skips `objdump --disassemble --line-numbers` and falls back to
 # `objdump --disassemble`
 # Note: the .chk excludes are for files that are known to differ between
--- a/taskcluster/ci/generate-profile/kind.yml
+++ b/taskcluster/ci/generate-profile/kind.yml
@@ -7,17 +7,16 @@ loader: taskgraph.loader.transform:loade
 kind-dependencies:
     - toolchain
     - instrumented-build
 
 transforms:
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.release_deps:transforms
     - taskgraph.transforms.run_pgo_profile:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 
 job-defaults:
     treeherder:
         symbol: Bpgo(run)
         kind: build
@@ -122,18 +121,19 @@ jobs:
             job-script: taskcluster/scripts/tester/test-linux.sh
             script: android_emulator_pgo.py
             tooltool-downloads: internal
             options: [installer-path=/builds/worker/fetches/target.apk]
             config:
                 - android/android_common.py
                 - android/androidarm_4_3.py
                 - android/android_pgo.py
-        toolchains:
-            - linux64-clang
+        fetches:
+            toolchain:
+                - linux64-clang
 
     win32-shippable/opt:
         description: "Win32 Profile Generation"
         shipping-phase: build
         shipping-product: firefox
         index:
             product: firefox
             job-name: win32-profile
--- a/taskcluster/ci/hazard/kind.yml
+++ b/taskcluster/ci/hazard/kind.yml
@@ -5,17 +5,16 @@
 loader: taskgraph.loader.transform:loader
 
 kind-dependencies:
     - toolchain
 
 transforms:
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 job-defaults:
     attributes:
         retrigger: true
     treeherder:
         kind: build
@@ -38,38 +37,40 @@ jobs:
             using: hazard
             command: >
                 cd /builds/worker/checkouts/gecko/taskcluster/scripts/builder
                 && ./build-haz-linux.sh --project shell $HOME/workspace
         when:
             files-changed:
                 - js/public/**
                 - js/src/**
-        toolchains:
-            - linux64-clang
-            - linux64-gcc-6
-            - linux64-gcc-sixgill
-            - linux64-rust
-            - linux64-cbindgen
-            - linux64-node
+        fetches:
+            toolchain:
+                - linux64-clang
+                - linux64-gcc-6
+                - linux64-gcc-sixgill
+                - linux64-rust
+                - linux64-cbindgen
+                - linux64-node
 
     linux64-haz/debug:
         description: "Browser Hazard Analysis Linux"
         index:
             product: firefox
             job-name: browser-haz-debug
         treeherder:
             platform: linux64/debug
             symbol: H
         run:
             using: hazard
             mozconfig: "browser/config/mozconfigs/linux64/hazards"
             command: >
                 cd /builds/worker/checkouts/gecko/taskcluster/scripts/builder
                 && ./build-haz-linux.sh --project browser $HOME/workspace
-        toolchains:
-            - linux64-clang
-            - linux64-gcc-6
-            - linux64-gcc-sixgill
-            - linux64-rust
-            - linux64-cbindgen
-            - linux64-nasm
-            - linux64-node
+        fetches:
+            toolchain:
+                - linux64-clang
+                - linux64-gcc-6
+                - linux64-gcc-sixgill
+                - linux64-rust
+                - linux64-cbindgen
+                - linux64-nasm
+                - linux64-node
--- a/taskcluster/ci/instrumented-build/kind.yml
+++ b/taskcluster/ci/instrumented-build/kind.yml
@@ -7,17 +7,16 @@ loader: taskgraph.loader.transform:loade
 kind-dependencies:
     - toolchain
     - fetch
 
 transforms:
     - taskgraph.transforms.build:transforms
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 job-defaults:
     shipping-phase: build
     treeherder:
         symbol: Bpgo(instr)
         tier: 1
@@ -42,48 +41,50 @@ jobs:
             docker-image: {in-tree: debian7-i386-build}
         run:
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_base_linux_32_builds.py
             mozconfig-variant: profile-generate
             tooltool-downloads: public
             need-xvfb: true
-        toolchains:
-            - linux64-binutils
-            - linux64-clang
-            - linux64-rust
-            - linux64-rust-size
-            - linux64-cbindgen
-            - linux64-sccache
-            - linux64-nasm
-            - linux64-node
+        fetches:
+            toolchain:
+                - linux64-binutils
+                - linux64-clang
+                - linux64-rust
+                - linux64-rust-size
+                - linux64-cbindgen
+                - linux64-sccache
+                - linux64-nasm
+                - linux64-node
 
     linux64-shippable/opt:
         description: "Linux64 Instrumented"
         shipping-product: firefox
         treeherder:
             platform: linux64-shippable/opt
         worker-type: b-linux
         run:
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_base_linux_64_builds.py
             mozconfig-variant: profile-generate
             tooltool-downloads: public
             need-xvfb: true
-        toolchains:
-            - linux64-binutils
-            - linux64-clang
-            - linux64-rust
-            - linux64-rust-size
-            - linux64-cbindgen
-            - linux64-sccache
-            - linux64-nasm
-            - linux64-node
+        fetches:
+            toolchain:
+                - linux64-binutils
+                - linux64-clang
+                - linux64-rust
+                - linux64-rust-size
+                - linux64-cbindgen
+                - linux64-sccache
+                - linux64-nasm
+                - linux64-node
 
     android-api-16/pgo:
         description: "Android 4.0 api-16+ PGO instrumented"
         shipping-product: fennec
         treeherder:
             platform: android-4-0-armv7-api16/pgo
         worker-type: b-linux
         worker:
@@ -101,27 +102,28 @@ jobs:
                 - name: public/build/geckoview_example.apk
                   path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/withGeckoBinaries/debug/geckoview_example-withGeckoBinaries-debug.apk
                   type: file
         run:
             config:
                 - builds/releng_base_android_64_builds.py
             custom-build-variant-cfg: api-16-profile-generate
             tooltool-downloads: internal
-        toolchains:
-            - android-gradle-dependencies
-            - android-ndk-linux
-            - android-sdk-linux
-            - linux64-clang-android-cross
-            - linux64-rust-android
-            - linux64-rust-size
-            - linux64-cbindgen
-            - linux64-sccache
-            - linux64-nasm
-            - linux64-node
+        fetches:
+            toolchain:
+                - android-gradle-dependencies
+                - android-ndk-linux
+                - android-sdk-linux
+                - linux64-clang-android-cross
+                - linux64-rust-android
+                - linux64-rust-size
+                - linux64-cbindgen
+                - linux64-sccache
+                - linux64-nasm
+                - linux64-node
 
     win32-shippable/opt:
         description: "Win32 Shippable PGO Instrumented"
         shipping-product: firefox
         treeherder:
             platform: windows2012-32-shippable/opt
         worker-type: b-win2012
         worker:
@@ -132,23 +134,24 @@ jobs:
             options: [append-env-variables-from-configs]
             mozconfig-variant: profile-generate
             config:
                 - builds/releng_base_firefox.py
                 - builds/taskcluster_base_windows.py
                 - builds/taskcluster_base_win32.py
             extra-config:
                 stage_platform: win32
-        toolchains:
-            - win64-clang-cl
-            - win64-rust
-            - win64-rust-size
-            - win64-cbindgen
-            - win64-nasm
-            - win64-node
+        fetches:
+            toolchain:
+                - win64-clang-cl
+                - win64-rust
+                - win64-rust-size
+                - win64-cbindgen
+                - win64-nasm
+                - win64-node
 
     win64-shippable/opt:
         description: "Win64 Shippable PGO Instrumented"
         shipping-product: firefox
         treeherder:
             platform: windows2012-64-shippable/opt
         worker-type: b-win2012
         worker:
@@ -159,15 +162,16 @@ jobs:
             options: [append-env-variables-from-configs]
             mozconfig-variant: profile-generate
             config:
                 - builds/releng_base_firefox.py
                 - builds/taskcluster_base_windows.py
                 - builds/taskcluster_base_win64.py
             extra-config:
                 stage_platform: win64
-        toolchains:
-            - win64-clang-cl
-            - win64-rust
-            - win64-rust-size
-            - win64-cbindgen
-            - win64-nasm
-            - win64-node
+        fetches:
+            toolchain:
+                - win64-clang-cl
+                - win64-rust
+                - win64-rust-size
+                - win64-cbindgen
+                - win64-nasm
+                - win64-node
--- a/taskcluster/ci/l10n/kind.yml
+++ b/taskcluster/ci/l10n/kind.yml
@@ -3,17 +3,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 ---
 loader: taskgraph.loader.multi_dep:loader
 
 group-by: platform
 
 transforms:
     - taskgraph.transforms.l10n:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 kind-dependencies:
     - build
     - build-signing
     - repackage
     - toolchain
@@ -47,25 +46,26 @@ job-template:
         by-build-platform:
             android-api-16:
                 in-tree: android-build
             default: null
     secrets:
         by-build-platform:
             default: false
             android-api-16: true
-    toolchains:
-        by-build-platform:
-            default: []
-            macosx64.*:
-                - linux64-libdmg
-                - linux64-hfsplus
-            android-api-16:
-                - android-gradle-dependencies
-                - android-sdk-linux
+    fetches:
+        toolchain:
+            by-build-platform:
+                default: []
+                macosx64.*:
+                    - linux64-libdmg
+                    - linux64-hfsplus
+                android-api-16:
+                    - android-gradle-dependencies
+                    - android-sdk-linux
     tooltool:
         by-build-platform:
             default: internal
             linux.*: public
     index:
         type: l10n
         product:
             by-build-platform:
--- a/taskcluster/ci/nightly-l10n/kind.yml
+++ b/taskcluster/ci/nightly-l10n/kind.yml
@@ -3,17 +3,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 ---
 loader: taskgraph.loader.multi_dep:loader
 
 group-by: platform
 
 transforms:
     - taskgraph.transforms.l10n:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 kind-dependencies:
     - build
     - build-signing
     - repackage
     - toolchain
@@ -64,25 +63,26 @@ job-template:
         by-build-platform:
             android-api-16-nightly:
                 in-tree: android-build
             default: null
     secrets:
         by-build-platform:
             default: false
             android-api-16-nightly: true
-    toolchains:
-        by-build-platform:
-            default: []
-            macosx64.*:
-                - linux64-libdmg
-                - linux64-hfsplus
-            android-api-16-nightly:
-                - android-gradle-dependencies
-                - android-sdk-linux
+    fetches:
+        toolchain:
+            by-build-platform:
+                default: []
+                macosx64.*:
+                    - linux64-libdmg
+                    - linux64-hfsplus
+                android-api-16-nightly:
+                    - android-gradle-dependencies
+                    - android-sdk-linux
     tooltool:
         by-build-platform:
             default: internal
             linux.*: public
     index:
         type:
             by-build-platform:
                 .*nightly.*: nightly-l10n
--- a/taskcluster/ci/openh264-plugin/kind.yml
+++ b/taskcluster/ci/openh264-plugin/kind.yml
@@ -4,17 +4,16 @@
 ---
 loader: taskgraph.loader.transform:loader
 
 kind-dependencies:
     - toolchain
 
 transforms:
     - taskgraph.transforms.openh264:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 job-defaults:
     description: "Build OpenH264 plugin"
     treeherder:
         kind: build
         symbol: h264
@@ -40,20 +39,21 @@ jobs:
                   path: /builds/worker/workspace/build/openh264/artifacts
                   type: directory
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/linux32.py
             tooltool-downloads: public
-        toolchains:
-            - linux64-binutils
-            - linux64-clang
-            - linux64-nasm
+        fetches:
+            toolchain:
+                - linux64-binutils
+                - linux64-clang
+                - linux64-nasm
     linux64/opt:
         attributes:
             build_platform: linux64
             build_type: opt
         treeherder:
             platform: linux64/opt
         worker-type: b-linux
         worker:
@@ -63,20 +63,21 @@ jobs:
                   path: /builds/worker/workspace/build/openh264/artifacts
                   type: directory
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/linux64.py
             tooltool-downloads: public
-        toolchains:
-            - linux64-binutils
-            - linux64-clang
-            - linux64-nasm
+        fetches:
+            toolchain:
+                - linux64-binutils
+                - linux64-clang
+                - linux64-nasm
     macosx64/opt:
         attributes:
             build_platform: macosx64
             build_type: opt
         treeherder:
             platform: macosx64/opt
         worker-type: b-linux
         worker:
@@ -86,19 +87,20 @@ jobs:
                   path: /builds/worker/workspace/build/openh264/artifacts
                   type: directory
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/macosx64.py
             tooltool-downloads: internal
-        toolchains:
-            - linux64-cctools-port
-            - linux64-clang
+        fetches:
+            toolchain:
+                - linux64-cctools-port
+                - linux64-clang
     win32/opt:
         attributes:
             build_platform: win32
             build_type: opt
         treeherder:
             platform: win32/opt
         worker-type: b-win2012
         worker:
@@ -107,18 +109,19 @@ jobs:
                 - name: private/openh264
                   path: build/openh264/artifacts
                   type: directory
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/win32.py
-        toolchains:
-            - win64-clang-cl
+        fetches:
+            toolchain:
+                - win64-clang-cl
     win64/opt:
         attributes:
             build_platform: win64
             build_type: opt
         treeherder:
             platform: win64/opt
         worker-type: b-win2012
         worker:
@@ -127,18 +130,19 @@ jobs:
                 - name: private/openh264
                   path: build/openh264/artifacts
                   type: directory
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/win64.py
-        toolchains:
-            - win64-clang-cl
+        fetches:
+            toolchain:
+                - win64-clang-cl
     win64-aarch64/opt:
         attributes:
             build_platform: win64-aarch64
             build_type: opt
         treeherder:
             platform: win64-aarch64/opt
         worker-type: b-win2012
         worker:
@@ -147,18 +151,19 @@ jobs:
                 - name: private/openh264
                   path: build/openh264/artifacts
                   type: directory
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/win64-aarch64.py
-        toolchains:
-            - win64-clang-cl
+        fetches:
+            toolchain:
+                - win64-clang-cl
     android-api-16/opt:
         attributes:
             build_platform: android-arm
             build_type: opt
         treeherder:
             platform: android-api-16/opt
         worker-type: b-linux
         worker:
@@ -172,21 +177,22 @@ jobs:
         repo: https://github.com/dminor/openh264.git
         revision: 42954cf0fe8a2bdc97fdc180462a3eaefceb035f
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/android-arm.py
             tooltool-downloads: internal
-        toolchains:
-            - android-ndk-linux
-            - android-sdk-linux
-            - linux64-clang
-            - linux64-nasm
+        fetches:
+            toolchain:
+                - android-ndk-linux
+                - android-sdk-linux
+                - linux64-clang
+                - linux64-nasm
     android-aarch64/opt:
         attributes:
             build_platform: android-aarch64
             build_type: opt
         treeherder:
             platform: android-5-0-aarch64/opt
         worker-type: b-linux
         worker:
@@ -200,21 +206,22 @@ jobs:
         repo: https://github.com/dminor/openh264.git
         revision: 42954cf0fe8a2bdc97fdc180462a3eaefceb035f
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/android-aarch64.py
             tooltool-downloads: internal
-        toolchains:
-            - android-ndk-linux
-            - android-sdk-linux
-            - linux64-clang
-            - linux64-nasm
+        fetches:
+            toolchain:
+                - android-ndk-linux
+                - android-sdk-linux
+                - linux64-clang
+                - linux64-nasm
     android-x86/opt:
         attributes:
             build_platform: android-x86
             build_type: opt
         treeherder:
             platform: android-4-2-x86/opt
         worker-type: b-linux
         worker:
@@ -228,21 +235,22 @@ jobs:
         repo: https://github.com/dminor/openh264.git
         revision: 42954cf0fe8a2bdc97fdc180462a3eaefceb035f
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/android-x86.py
             tooltool-downloads: internal
-        toolchains:
-            - android-ndk-linux
-            - android-sdk-linux
-            - linux64-clang
-            - linux64-nasm
+        fetches:
+            toolchain:
+                - android-ndk-linux
+                - android-sdk-linux
+                - linux64-clang
+                - linux64-nasm
     android-x86_64/opt:
         attributes:
             build_platform: android-x86_64
             build_type: opt
         treeherder:
             platform: android-5-0-x86_64/opt
         worker-type: b-linux
         worker:
@@ -256,13 +264,14 @@ jobs:
         repo: https://github.com/dminor/openh264.git
         revision: 42954cf0fe8a2bdc97fdc180462a3eaefceb035f
         run:
             using: mozharness
             script: mozharness/scripts/openh264_build.py
             config:
                 - openh264/android-x86_64.py
             tooltool-downloads: internal
-        toolchains:
-            - android-ndk-linux
-            - android-sdk-linux
-            - linux64-clang
-            - linux64-nasm
+        fetches:
+            toolchain:
+                - android-ndk-linux
+                - android-sdk-linux
+                - linux64-clang
+                - linux64-nasm
--- a/taskcluster/ci/release-eme-free-repack-repackage/kind.yml
+++ b/taskcluster/ci/release-eme-free-repack-repackage/kind.yml
@@ -3,17 +3,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 ---
 loader: taskgraph.loader.single_dep:loader
 
 transforms:
     - taskgraph.transforms.chunk_partners:transforms
     - taskgraph.transforms.name_sanity:transforms
     - taskgraph.transforms.repackage_partner:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 kind-dependencies:
     - release-eme-free-repack
     - release-eme-free-repack-signing
     - toolchain
 
--- a/taskcluster/ci/release-partner-repack-repackage/kind.yml
+++ b/taskcluster/ci/release-partner-repack-repackage/kind.yml
@@ -3,17 +3,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 ---
 loader: taskgraph.loader.single_dep:loader
 
 transforms:
     - taskgraph.transforms.chunk_partners:transforms
     - taskgraph.transforms.name_sanity:transforms
     - taskgraph.transforms.repackage_partner:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 kind-dependencies:
     - release-partner-repack
     - release-partner-repack-signing
     - toolchain
 
--- a/taskcluster/ci/release-source/kind.yml
+++ b/taskcluster/ci/release-source/kind.yml
@@ -6,17 +6,16 @@ loader: taskgraph.loader.transform:loade
 
 kind-dependencies:
     - toolchain
 
 transforms:
     - taskgraph.transforms.build:transforms
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 
 job-defaults:
     shipping-phase: promote
     treeherder:
         symbol: Src
--- a/taskcluster/ci/repackage-l10n/kind.yml
+++ b/taskcluster/ci/repackage-l10n/kind.yml
@@ -3,17 +3,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 ---
 loader: taskgraph.loader.single_dep:loader
 
 transforms:
     - taskgraph.transforms.repackage_l10n:transforms
     - taskgraph.transforms.name_sanity:transforms
     - taskgraph.transforms.repackage:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 kind-dependencies:
     - nightly-l10n-signing
     - toolchain
 
 only-for-build-platforms:
--- a/taskcluster/ci/repackage-msi/kind.yml
+++ b/taskcluster/ci/repackage-msi/kind.yml
@@ -2,17 +2,16 @@
 # 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/.
 ---
 loader: taskgraph.loader.single_dep:loader
 
 transforms:
     - taskgraph.transforms.name_sanity:transforms
     - taskgraph.transforms.repackage:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 kind-dependencies:
     - repackage-signing
     - repackage-signing-l10n
     - fetch
 
--- a/taskcluster/ci/repackage/kind.yml
+++ b/taskcluster/ci/repackage/kind.yml
@@ -2,17 +2,16 @@
 # 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/.
 ---
 loader: taskgraph.loader.single_dep:loader
 
 transforms:
     - taskgraph.transforms.name_sanity:transforms
     - taskgraph.transforms.repackage:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.repackage_routes:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 kind-dependencies:
     - build-signing
     - toolchain
 
--- a/taskcluster/ci/searchfox/kind.yml
+++ b/taskcluster/ci/searchfox/kind.yml
@@ -5,17 +5,16 @@
 loader: taskgraph.loader.transform:loader
 
 kind-dependencies:
     - toolchain
 
 transforms:
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 job-defaults:
     index:
         product: firefox
     treeherder:
         symbol: Searchfox(idx)
@@ -42,23 +41,24 @@ jobs:
             using: mozharness
             actions: [build]
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_sub_linux_configs/64_searchfox_and_debug.py
             script: "mozharness/scripts/fx_desktop_build.py"
             tooltool-downloads: public
             keep-artifacts: false
-        toolchains:
-            - linux64-binutils
-            - linux64-clang
-            - linux64-nasm
-            - linux64-node
-            - linux64-rust
-            - linux64-cbindgen
+        fetches:
+            toolchain:
+                - linux64-binutils
+                - linux64-clang
+                - linux64-nasm
+                - linux64-node
+                - linux64-rust
+                - linux64-cbindgen
 
     macosx64-searchfox/debug:
         description: "MacOS X x64 Debug Cross-compile Searchfox"
         index:
             job-name: macosx64-searchfox-debug
         treeherder:
             platform: osx-cross/debug
         worker-type: b-linux
@@ -75,27 +75,28 @@ jobs:
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_base_mac_64_cross_builds.py
             script: "mozharness/scripts/fx_desktop_build.py"
             custom-build-variant-cfg: cross-debug-searchfox
             secrets: true
             tooltool-downloads: internal
             keep-artifacts: false
-        toolchains:
-            - linux64-binutils
-            - linux64-cctools-port
-            - linux64-clang-macosx-cross
-            - linux64-hfsplus
-            - linux64-libdmg
-            - linux64-llvm-dsymutil
-            - linux64-nasm
-            - linux64-node
-            - linux64-rust-macos
-            - linux64-cbindgen
+        fetches:
+            toolchain:
+                - linux64-binutils
+                - linux64-cctools-port
+                - linux64-clang-macosx-cross
+                - linux64-hfsplus
+                - linux64-libdmg
+                - linux64-llvm-dsymutil
+                - linux64-nasm
+                - linux64-node
+                - linux64-rust-macos
+                - linux64-cbindgen
 
     win64-searchfox/debug:
         description: "Win64 Searchfox Debug (clang-cl)"
         index:
             product: firefox
             job-name: win64-searchfox-debug
         treeherder:
             platform: windows2012-64/debug
@@ -113,22 +114,23 @@ jobs:
             use-caches: false
             options: [append-env-variables-from-configs]
             script: mozharness/scripts/fx_desktop_build.py
             config:
                 - builds/releng_base_firefox.py
                 - builds/taskcluster_base_windows.py
                 - builds/taskcluster_base_win64.py
                 - builds/taskcluster_sub_win64/searchfox_debug.py
-        toolchains:
-            - win64-clang-cl
-            - win64-node
-            - win64-rust
-            - win64-cbindgen
-            - win64-nasm
+        fetches:
+            toolchain:
+                - win64-clang-cl
+                - win64-node
+                - win64-rust
+                - win64-cbindgen
+                - win64-nasm
 
     android-armv7-searchfox/debug:
         description: "Android ARMv7 Debug Searchfox"
         index:
             job-name: android-armv7-searchfox-debug
         treeherder:
             platform: android-4-0-armv7-api16/debug
         worker-type: b-linux
@@ -145,19 +147,20 @@ jobs:
             using: mozharness
             actions: [get-secrets, build]
             config:
                 - builds/releng_base_android_64_builds.py
             script: "mozharness/scripts/fx_desktop_build.py"
             secrets: true
             custom-build-variant-cfg: api-16-debug-searchfox
             tooltool-downloads: internal
-        toolchains:
-            - android-gradle-dependencies
-            - android-ndk-linux
-            - android-sdk-linux
-            - linux64-clang
-            - linux64-rust-android
-            - linux64-rust-size
-            - linux64-cbindgen
-            - linux64-sccache
-            - linux64-nasm
-            - linux64-node
+        fetches:
+            toolchain:
+                - android-gradle-dependencies
+                - android-ndk-linux
+                - android-sdk-linux
+                - linux64-clang
+                - linux64-rust-android
+                - linux64-rust-size
+                - linux64-cbindgen
+                - linux64-sccache
+                - linux64-nasm
+                - linux64-node
--- a/taskcluster/ci/source-test/clang.yml
+++ b/taskcluster/ci/source-test/clang.yml
@@ -18,23 +18,24 @@ job-defaults:
         docker-image: {in-tree: debian7-amd64-build}
         max-run-time: 5400
     treeherder:
         kind: other
         tier: 2
     run:
         using: run-task
         tooltool-downloads: public
-    toolchains:
-        - linux64-clang
-        - linux64-clang-tidy
-        - linux64-rust
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-clang
+            - linux64-clang-tidy
+            - linux64-rust
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
     when:
         # Extension list from https://hg.mozilla.org/mozilla-central/file/tip/python/mozbuild/mozbuild/mach_commands.py#l1664
         files-changed:
             - '**/*.c'
             - '**/*.cpp'
             - '**/*.cc'
             - '**/*.cxx'
             - '**/*.m'
--- a/taskcluster/ci/source-test/coverity.yml
+++ b/taskcluster/ci/source-test/coverity.yml
@@ -17,22 +17,23 @@ job-defaults:
         docker-image: {in-tree: debian7-amd64-build}
         max-run-time: 5400
     treeherder:
         kind: other
         tier: 2
     run:
         using: run-task
         tooltool-downloads: public
-    toolchains:
-        - linux64-clang-7
-        - linux64-rust
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-clang-7
+            - linux64-rust
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
     when:
         # Extension list from https://hg.mozilla.org/mozilla-central/file/tip/python/mozbuild/mozbuild/mach_commands.py#l1664
         files-changed:
             - '**/*.c'
             - '**/*.cpp'
             - '**/*.cc'
             - '**/*.cxx'
             - '**/*.m'
--- a/taskcluster/ci/source-test/infer.yml
+++ b/taskcluster/ci/source-test/infer.yml
@@ -18,25 +18,26 @@ job-defaults:
         docker-image: {in-tree: android-build}
         max-run-time: 5400
     treeherder:
         kind: other
         tier: 2
     run:
         using: run-task
         tooltool-downloads: public
-    toolchains:
-        - linux64-infer
-        - linux64-android-sdk-linux-repack
-        - linux64-android-ndk-linux-repack
-        - linux64-rust-android
-        - linux64-clang
-        - linux64-cbindgen
-        - linux64-nasm
-        - linux64-node
+    fetches:
+        toolchain:
+            - linux64-infer
+            - linux64-android-sdk-linux-repack
+            - linux64-android-ndk-linux-repack
+            - linux64-rust-android
+            - linux64-clang
+            - linux64-cbindgen
+            - linux64-nasm
+            - linux64-node
     when:
         files-changed:
             - 'mobile/**/*.java'
 
 infer:
     description: Run static-analysis (infer) on Java patches
     treeherder:
         symbol: infer
--- a/taskcluster/ci/source-test/kind.yml
+++ b/taskcluster/ci/source-test/kind.yml
@@ -2,17 +2,16 @@
 # 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/.
 ---
 loader: taskgraph.loader.transform:loader
 
 transforms:
     - taskgraph.transforms.try_job:transforms
     - taskgraph.transforms.source_test:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 kind-dependencies:
     - fetch
     - toolchain
 
 jobs-from:
--- a/taskcluster/ci/spidermonkey/kind.yml
+++ b/taskcluster/ci/spidermonkey/kind.yml
@@ -6,17 +6,16 @@ loader: taskgraph.loader.transform:loade
 
 kind-dependencies:
     - toolchain
 
 transforms:
     - taskgraph.transforms.spidermonkey:transforms
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 job-defaults:
     attributes:
         retrigger: true
     treeherder:
         kind: build
@@ -53,21 +52,22 @@ job-defaults:
             - python/**
             - taskcluster/moz.build
             - taskcluster/ci/spidermonkey/kind.yml
             - testing/mozbase/**
             - testing/web-platform/**
             - test.mozbuild
             - toolkit/mozapps/installer/package-name.mk
             - toolkit/mozapps/installer/upload-files.mk
-    toolchains:
-        by-worker-type:
-            .*-b-win2012:
-                - win64-clang-cl
-                - win64-rust
-            default:
-                - linux64-clang
-                - linux64-gcc
-                - linux64-rust
+    fetches:
+        toolchain:
+            by-worker-type:
+                .*-b-win2012:
+                    - win64-clang-cl
+                    - win64-rust
+                default:
+                    - linux64-clang
+                    - linux64-gcc
+                    - linux64-rust
 
 jobs-from:
     - linux.yml
     - windows.yml
--- a/taskcluster/ci/spidermonkey/linux.yml
+++ b/taskcluster/ci/spidermonkey/linux.yml
@@ -136,20 +136,21 @@ sm-tsan-linux64/opt:
     description: "Spidermonkey Thread Sanitizer"
     index:
         job-name: sm-tsan-linux64-opt
     treeherder:
         symbol: SM(tsan)
         platform: linux64/opt
     run:
         spidermonkey-variant: tsan
-    toolchains:
-        - linux64-binutils
-        - linux64-clang
-        - linux64-rust
+    fetches:
+        toolchain:
+            - linux64-binutils
+            - linux64-clang
+            - linux64-rust
 
 sm-rootanalysis-linux64/debug:
     description: "Spidermonkey Root Analysis"
     index:
         job-name: sm-rootanalysis-linux64-debug
     treeherder:
         platform: linux64/debug
         symbol: SM(r)
--- a/taskcluster/ci/spidermonkey/windows.yml
+++ b/taskcluster/ci/spidermonkey/windows.yml
@@ -14,106 +14,113 @@ sm-plain-win64/debug:
     index:
         job-name: sm-plain-win64-debug
     treeherder:
         platform: windows2012-64/debug
         symbol: SM(p)
     run:
         spidermonkey-variant: plaindebug
         spidermonkey-platform: win64
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
 
 sm-plain-win32/debug:
     description: "Spidermonkey Plain win32 debug"
     index:
         job-name: sm-plain-win32-debug
     treeherder:
         platform: windows2012-32/debug
         symbol: SM(p)
     run:
         spidermonkey-variant: plaindebug
         spidermonkey-platform: win32
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
     worker:
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win32/releng.manifest"
 
 sm-plain-win64/opt:
     description: "Spidermonkey Plain win64 opt"
     index:
         job-name: sm-plain-win64-opt
     treeherder:
         platform: windows2012-64/opt
         symbol: SM(p)
     run:
         spidermonkey-variant: plain
         spidermonkey-platform: win64
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
 
 sm-plain-win32/opt:
     description: "Spidermonkey Plain win32 opt"
     index:
         job-name: sm-plain-win32-opt
     treeherder:
         platform: windows2012-32/opt
         symbol: SM(p)
     run:
         spidermonkey-variant: plain
         spidermonkey-platform: win32
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
     worker:
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win32/releng.manifest"
 
 sm-compacting-win64/debug:
     description: "Spidermonkey Compacting win64 debug"
     index:
         job-name: sm-compacting-win64-debug
     treeherder:
         platform: windows2012-64/debug
         symbol: SM(cgc)
     run:
         spidermonkey-variant: compacting
         spidermonkey-platform: win64
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
 
 sm-compacting-win32/debug:
     description: "Spidermonkey Compacting win32 debug"
     index:
         job-name: sm-compacting-win32-debug
     treeherder:
         platform: windows2012-32/debug
         symbol: SM(cgc)
     run:
         spidermonkey-variant: compacting
         spidermonkey-platform: win32
     run-on-projects: []
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
     worker:
         env:
             TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win32/releng.manifest"
 
 sm-plain-win64-aarch64/opt:
     description: "Spidermonkey Plain win64-aarch64 opt"
     index:
         job-name: sm-plain-win64-aarch64-opt
     treeherder:
         platform: windows2012-aarch64/opt
         symbol: SM(p)
         tier: 2
     run:
         spidermonkey-variant: plain
         spidermonkey-platform: win64
-    toolchains:
-        - win64-clang-cl
-        - win64-rust
+    fetches:
+        toolchain:
+            - win64-clang-cl
+            - win64-rust
--- a/taskcluster/ci/static-analysis-autotest/kind.yml
+++ b/taskcluster/ci/static-analysis-autotest/kind.yml
@@ -5,17 +5,16 @@
 loader: taskgraph.loader.transform:loader
 
 kind-dependencies:
     - toolchain
 
 transforms:
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 job-defaults:
     attributes:
         retrigger: true
     index:
         product: firefox
@@ -49,25 +48,26 @@ jobs:
                 LD_LIBRARY_PATH: /builds/worker/workspace/build/src/clang/lib
                 PERFHERDER_EXTRA_OPTIONS: static-analysis-autotest
         run:
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_sub_linux_configs/64_stat_and_debug.py
             tooltool-downloads: public
             keep-artifacts: false
-        toolchains:
-            - linux64-clang
-            - linux64-clang-tidy
-            - linux64-infer
-            - linux64-rust
-            - linux64-sccache
-            - linux64-cbindgen
-            - linux64-nasm
-            - linux64-node
+        fetches:
+            toolchain:
+                - linux64-clang
+                - linux64-clang-tidy
+                - linux64-infer
+                - linux64-rust
+                - linux64-sccache
+                - linux64-cbindgen
+                - linux64-nasm
+                - linux64-node
 
     win64-st-autotest/debug:
         description: "Win64 Debug Static Analysis Autotest"
         index:
             job-name: win64-st-autotest-debug
         treeherder:
             platform: windows2012-64/debug
             tier: 2
@@ -78,16 +78,17 @@ jobs:
         run:
             config:
                 - builds/releng_base_firefox.py
                 - builds/taskcluster_base_windows.py
                 - builds/taskcluster_base_win64.py
                 - builds/taskcluster_sub_win64/debug.py
             extra-config:
                 mozconfig_variant: debug
-        toolchains:
-            - win64-clang-cl
-            - win64-rust
-            - win64-sccache
-            - win64-cbindgen
-            - win64-clang-tidy
-            - win64-nasm
-            - win64-node
+        fetches:
+            toolchain:
+                - win64-clang-cl
+                - win64-rust
+                - win64-sccache
+                - win64-cbindgen
+                - win64-clang-tidy
+                - win64-nasm
+                - win64-node
--- a/taskcluster/ci/valgrind/kind.yml
+++ b/taskcluster/ci/valgrind/kind.yml
@@ -5,17 +5,16 @@
 loader: taskgraph.loader.transform:loader
 
 kind-dependencies:
     - toolchain
 
 transforms:
     - taskgraph.transforms.build_attrs:transforms
     - taskgraph.transforms.build_lints:transforms
-    - taskgraph.transforms.use_toolchains:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 job-defaults:
     attributes:
         retrigger: true
 
 jobs:
@@ -41,16 +40,17 @@ jobs:
             custom-build-variant-cfg: valgrind
             config:
                 - builds/releng_base_firefox.py
                 - builds/releng_base_linux_64_builds.py
             script: "mozharness/scripts/fx_desktop_build.py"
             secrets: true
             tooltool-downloads: public
             need-xvfb: true
-        toolchains:
-            - linux64-binutils
-            - linux64-clang
-            - linux64-rust
-            - linux64-cbindgen
-            - linux64-sccache
-            - linux64-nasm
-            - linux64-node
+        fetches:
+            toolchain:
+                - linux64-binutils
+                - linux64-clang
+                - linux64-rust
+                - linux64-cbindgen
+                - linux64-sccache
+                - linux64-nasm
+                - linux64-node
--- a/taskcluster/docker/diffoscope/get_and_diffoscope
+++ b/taskcluster/docker/diffoscope/get_and_diffoscope
@@ -6,49 +6,37 @@ set -x
 cd /builds/worker
 
 mkdir a b
 
 # Until https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=879010 is
 # implemented, it's better to first manually extract the data.
 # Plus dmg files are not supported yet.
 
-# duplicate the functionality of taskcluster-lib-urls, but in bash..
-if [ "$TASKCLUSTER_ROOT_URL" = "https://taskcluster.net" ]; then
-    queue_base='https://queue.taskcluster.net/v1'
-else
-    queue_base="$TASKCLUSTER_ROOT_URL/api/queue/v1"
-fi
-
 case "$ORIG_URL" in
 */target.zip|*/target.apk)
 	curl -L "$ORIG_URL" > a.zip
 	curl -L "$NEW_URL" > b.zip
 	unzip -d a a.zip
 	unzip -d b b.zip
 	;;
 */target.tar.bz2)
 	curl -L "$ORIG_URL" | tar -C a -jxf -
 	curl -L "$NEW_URL" | tar -C b -jxf -
 	;;
 */target.dmg)
-	# We don't have mach available to call mach artifact toolchain.
-	# This is the trivial equivalent for those toolchains we use here.
-	for t in $MOZ_TOOLCHAINS; do
-		curl -L $queue_base/task/${t#*@}/artifacts/${t%@*} | tar -Jxf -
-	done
 	for tool in lipo otool; do
-		ln -s /builds/worker/cctools/bin/x86_64-apple-darwin*-$tool bin/$tool
+		ln -s $MOZ_FETCHES_DIR/cctools/bin/x86_64-apple-darwin*-$tool bin/$tool
 	done
 	export PATH=$PATH:/builds/worker/bin
 	curl -L "$ORIG_URL" > a.dmg
 	curl -L "$NEW_URL" > b.dmg
 	for i in a b; do
-		dmg/dmg extract $i.dmg $i.hfs
-		dmg/hfsplus $i.hfs extractall / $i
+		$MOZ_FETCHES_DIR/dmg/dmg extract $i.dmg $i.hfs
+		$MOZ_FETCHES_DIR/dmg/hfsplus $i.hfs extractall / $i
 	done
 	;;
 esac
 
 case "$ORIG_URL" in
 */target.apk)
 	OMNIJAR=assets/omni.ja
 	;;
--- a/taskcluster/scripts/builder/build-haz-linux.sh
+++ b/taskcluster/scripts/builder/build-haz-linux.sh
@@ -3,68 +3,53 @@
 function usage() {
     echo "Usage: $0 [--project <shell|browser>] <workspace-dir> flags..."
     echo "flags are treated the same way as a commit message would be"
     echo "(as in, they are scanned for directives just like a try: ... line)"
 }
 
 PROJECT=shell
 WORKSPACE=
-DO_TOOLTOOL=1
 while [[ $# -gt 0 ]]; do
     if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
         usage
         exit 0
     elif [[ "$1" == "--project" ]]; then
         shift
         PROJECT="$1"
         shift
     elif [[ "$1" == "--no-tooltool" ]]; then
         shift
-        DO_TOOLTOOL=
     elif [[ -z "$WORKSPACE" ]]; then
         WORKSPACE=$( cd "$1" && pwd )
         shift
         break
     fi
 done
 
 SCRIPT_FLAGS=$*
 
 # Ensure all the scripts in this dir are on the path....
 DIRNAME=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
 PATH=$DIRNAME:$PATH
 
 # Use GECKO_BASE_REPOSITORY as a signal for whether we are running in automation.
 export AUTOMATION=${GECKO_BASE_REPOSITORY:+1}
 
-: "${GECKO_DIR:="$DIRNAME"/../../..}"
-: "${TOOLTOOL_CACHE:=$WORKSPACE/tt-cache}"
+: "${GECKO_PATH:="$DIRNAME"/../../..}"
 
-if ! [ -d "$GECKO_DIR" ]; then
-    echo "GECKO_DIR must be set to a directory containing a gecko source checkout" >&2
+if ! [ -d "$GECKO_PATH" ]; then
+    echo "GECKO_PATH must be set to a directory containing a gecko source checkout" >&2
     exit 1
 fi
-GECKO_DIR="$( cd "$GECKO_DIR" && pwd )"
-
-# Directory to populate with tooltool-installed tools
-export TOOLTOOL_DIR="$WORKSPACE"
 
 # Directory to hold the (useless) object files generated by the analysis.
 export MOZ_OBJDIR="$WORKSPACE/obj-analyzed"
 mkdir -p "$MOZ_OBJDIR"
 
-if [ -n "$DO_TOOLTOOL" ]; then (
-    cd "$TOOLTOOL_DIR"
-    "$GECKO_DIR"/mach artifact toolchain -v\
-                ${TOOLTOOL_MANIFEST:+ --tooltool-url https://tooltool.mozilla-releng.net/ \
-                                      --tooltool-manifest "$GECKO_DIR/$TOOLTOOL_MANIFEST"} \
-                --cache-dir "$TOOLTOOL_CACHE"${MOZ_TOOLCHAINS:+ ${MOZ_TOOLCHAINS}}
-) fi
-
 export NO_MERCURIAL_SETUP_CHECK=1
 
 if [[ "$PROJECT" = "browser" ]]; then (
     cd "$WORKSPACE"
     set "$WORKSPACE"
     # Mozbuild config:
     export MOZBUILD_STATE_PATH=$WORKSPACE/mozbuild/
     # Create .mozbuild so mach doesn't complain about this
--- a/taskcluster/scripts/builder/build-sm-mozjs-crate.sh
+++ b/taskcluster/scripts/builder/build-sm-mozjs-crate.sh
@@ -6,14 +6,14 @@ source $(dirname $0)/sm-tooltool-config.
 
 # Ensure that we have a .config/cargo that points us to our vendored crates
 # rather than to crates.io.
 cd "$SRCDIR/.cargo"
 sed -e "s|@top_srcdir@|$SRCDIR|" -e 's|@[^@]*@||g' < config.in > config
 
 cd "$SRCDIR/js/src"
 
-export PATH="$PATH:$TOOLTOOL_CHECKOUT/cargo/bin:$TOOLTOOL_CHECKOUT/rustc/bin"
+export PATH="$PATH:$MOZ_FETCHES_DIR/cargo/bin:$MOZ_FETCHES_DIR/rustc/bin"
 export RUST_BACKTRACE=1
 export AUTOMATION=1
 
 cargo build --verbose --frozen --features debugmozjs
 cargo build --verbose --frozen
--- a/taskcluster/scripts/builder/build-sm-rust-bindings.sh
+++ b/taskcluster/scripts/builder/build-sm-rust-bindings.sh
@@ -6,14 +6,14 @@ source $(dirname $0)/sm-tooltool-config.
 
 # Ensure that we have a .config/cargo that points us to our vendored crates
 # rather than to crates.io.
 cd "$SRCDIR/.cargo"
 sed -e "s|@top_srcdir@|$SRCDIR|" -e 's|@[^@]*@||g' < config.in > config
 
 cd "$SRCDIR/js/rust"
 
-export LD_LIBRARY_PATH="$TOOLTOOL_CHECKOUT/gcc/lib64"
+export LD_LIBRARY_PATH="$MOZ_FETCHES_DIR/gcc/lib64"
 # Enable backtraces if we panic.
 export RUST_BACKTRACE=1
 
 cargo test --verbose --frozen --features debugmozjs
 cargo test --verbose --frozen
--- a/taskcluster/scripts/builder/build-sm.sh
+++ b/taskcluster/scripts/builder/build-sm.sh
@@ -14,11 +14,11 @@ BUILD_STATUS=$?
 # Ensure upload dir exists
 mkdir -p $UPLOAD_DIR
 
 # Copy artifacts for upload by TaskCluster
 cp -rL $SRCDIR/obj-spider/dist/bin/{js,jsapi-tests,js-gdb.py} $UPLOAD_DIR
 
 # Fuzzing users would really like to have llvm-symbolizer available in the same
 # directory as the built output.
-gzip -c $TOOLTOOL_CHECKOUT/clang/bin/llvm-symbolizer > $UPLOAD_DIR/llvm-symbolizer.gz || true
+gzip -c $MOZ_FETCHES_DIR/clang/bin/llvm-symbolizer > $UPLOAD_DIR/llvm-symbolizer.gz || true
 
 exit $BUILD_STATUS
--- a/taskcluster/scripts/builder/hazard-analysis.sh
+++ b/taskcluster/scripts/builder/hazard-analysis.sh
@@ -1,36 +1,36 @@
 #!/bin/bash -ex
 
 [ -n "$WORKSPACE" ]
 [ -n "$MOZ_OBJDIR" ]
-[ -n "$GECKO_DIR" ]
+[ -n "$GECKO_PATH" ]
 
 HAZARD_SHELL_OBJDIR=$WORKSPACE/obj-haz-shell
 JSBIN="$HAZARD_SHELL_OBJDIR/dist/bin/js"
-JS_SRCDIR=$GECKO_DIR/js/src
+JS_SRCDIR=$GECKO_PATH/js/src
 ANALYSIS_SRCDIR=$JS_SRCDIR/devtools/rootAnalysis
-GCCDIR="$TOOLTOOL_DIR/gcc"
+GCCDIR="$MOZ_FETCHES_DIR/gcc"
 
 export CC="$GCCDIR/bin/gcc"
 export CXX="$GCCDIR/bin/g++"
-export PATH="$GCCDIR/bin:$TOOLTOOL_DIR/clang/bin:$PATH"
+export PATH="$GCCDIR/bin:$MOZ_FETCHES_DIR/clang/bin:$PATH"
 export LD_LIBRARY_PATH="$GCCDIR/lib64"
-export RUSTC="$TOOLTOOL_DIR/rustc/bin/rustc"
-export CARGO="$TOOLTOOL_DIR/rustc/bin/cargo"
+export RUSTC="$MOZ_FETCHES_DIR/rustc/bin/rustc"
+export CARGO="$MOZ_FETCHES_DIR/rustc/bin/cargo"
 
 PYTHON=python2.7
 if ! which $PYTHON; then
     PYTHON=python
 fi
 
 function check_commit_msg () {
     ( set +e;
     if [[ -n "$AUTOMATION" ]]; then
-        hg --cwd "$GECKO_DIR" log -r. --template '{desc}\n' | grep -F -q -- "$1"
+        hg --cwd "$GECKO_PATH" log -r. --template '{desc}\n' | grep -F -q -- "$1"
     else
         echo -- "$SCRIPT_FLAGS" | grep -F -q -- "$1"
     fi
     )
 }
 
 if check_commit_msg "--dep"; then
     HAZ_DEP=1
@@ -66,23 +66,23 @@ function configure_analysis () {
 
     mkdir -p "$analysis_dir" || true
     (
         cd "$analysis_dir"
         cat > defaults.py <<EOF
 js = "$JSBIN"
 analysis_scriptdir = "$ANALYSIS_SRCDIR"
 objdir = "$MOZ_OBJDIR"
-source = "$GECKO_DIR"
-sixgill = "$TOOLTOOL_DIR/sixgill/usr/libexec/sixgill"
-sixgill_bin = "$TOOLTOOL_DIR/sixgill/usr/bin"
+source = "$GECKO_PATH"
+sixgill = "$MOZ_FETCHES_DIR/sixgill/usr/libexec/sixgill"
+sixgill_bin = "$MOZ_FETCHES_DIR/sixgill/usr/bin"
 EOF
 
         local rev
-        rev=$(cd $GECKO_DIR && hg log -r . -T '{node|short}')
+        rev=$(cd $GECKO_PATH && hg log -r . -T '{node|short}')
         cat > run-analysis.sh <<EOF
 #!/bin/sh
 if [ \$# -eq 0 ]; then
   set gcTypes
 fi
 export ANALYSIS_SCRIPTDIR="$ANALYSIS_SRCDIR"
 export URLPREFIX="https://hg.mozilla.org/mozilla-unified/file/$rev/"
 exec "$ANALYSIS_SRCDIR/analyze.py" "\$@"
@@ -98,22 +98,22 @@ function run_analysis () {
     build_type="$2"
 
     if [[ -z "$HAZ_DEP" ]]; then
         [ -d $MOZ_OBJDIR ] && rm -rf $MOZ_OBJDIR
     fi
 
     (
         cd "$analysis_dir"
-        $PYTHON "$ANALYSIS_SRCDIR/analyze.py" -v --buildcommand="$GECKO_DIR/taskcluster/scripts/builder/hazard-${build_type}.sh"
+        $PYTHON "$ANALYSIS_SRCDIR/analyze.py" -v --buildcommand="$GECKO_PATH/taskcluster/scripts/builder/hazard-${build_type}.sh"
     )
 }
 
 function analysis_self_test () {
-    LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$(dirname "$JSBIN")" $PYTHON "$ANALYSIS_SRCDIR/run-test.py" -v --js "$JSBIN" --sixgill "$TOOLTOOL_DIR/sixgill" --gccdir "$GCCDIR"
+    LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$(dirname "$JSBIN")" $PYTHON "$ANALYSIS_SRCDIR/run-test.py" -v --js "$JSBIN" --sixgill "$MOZ_FETCHES_DIR/sixgill" --gccdir "$GCCDIR"
 }
 
 function grab_artifacts () {
     local analysis_dir
     analysis_dir="$1"
     local artifacts
     artifacts="$2"
 
--- a/taskcluster/scripts/builder/sm-tooltool-config.sh
+++ b/taskcluster/scripts/builder/sm-tooltool-config.sh
@@ -1,17 +1,17 @@
 #!/bin/bash
 
 set -x
 
 TOOLTOOL_SERVER=${TOOLTOOL_SERVER:-https://tooltool.mozilla-releng.net/}
 SPIDERMONKEY_VARIANT=${SPIDERMONKEY_VARIANT:-plain}
 UPLOAD_DIR=${UPLOAD_DIR:-$HOME/artifacts/}
 WORK=${WORK:-$HOME/workspace}
-SRCDIR=${SRCDIR:-$WORK/build/src}
+SRCDIR=${SRCDIR:-$GECKO_PATH}
 
 export TOOLTOOL_CHECKOUT=${TOOLTOOL_CHECKOUT:-$WORK}
 
 ( # Create scope for set -e
 set -e
 mkdir -p $WORK
 cd $WORK
 
@@ -56,16 +56,16 @@ fi
 # necessary for the JS shell, but it's less duplication to share tooltool
 # manifests.
 BROWSER_PLATFORM=$PLATFORM_OS$BITS
 
 (cd $TOOLTOOL_CHECKOUT && ${SRCDIR}/mach artifact toolchain${TOOLTOOL_MANIFEST:+ -v $TOOLTOOL_AUTH_FLAGS --tooltool-url $TOOLTOOL_SERVER --tooltool-manifest $SRCDIR/$TOOLTOOL_MANIFEST}${TOOLTOOL_CACHE:+ --cache-dir $TOOLTOOL_CACHE}${MOZ_TOOLCHAINS:+ ${MOZ_TOOLCHAINS}})
 
 ) || exit 1 # end of set -e scope
 
-# Add all the tooltool binaries to our $PATH.
-for bin in $TOOLTOOL_CHECKOUT/*/bin $TOOLTOOL_CHECKOUT/VC/bin/Hostx64/x86; do
+# Add all the fetches and tooltool binaries to our $PATH.
+for bin in $MOZ_FETCHES_DIR/*/bin $TOOLTOOL_CHECKOUT/VC/bin/Hostx64/x86; do
     if [ ! -d "$bin" ]; then
         continue
     fi
     absbin=$(cd "$bin" && pwd)
     export PATH="$absbin:$PATH"
 done
--- a/taskcluster/scripts/misc/build-gn-win32.sh
+++ b/taskcluster/scripts/misc/build-gn-win32.sh
@@ -1,18 +1,18 @@
 #!/bin/bash
-set -e -v
+set -e -v -x
 
 # This script is for building GN on Windows.
 
 UPLOAD_DIR=$PWD/public/build
 COMPRESS_EXT=bz2
 
 cd $GECKO_PATH
 
-export PATH="$MOZ_FETCHES_DIR/ninja/bin:$PATH"
-export PATH="$MOZ_FETCHES_DIR/mingw64/bin:$PATH"
+export PATH="$(cd $MOZ_FETCHES_DIR && pwd)/ninja/bin:$PATH"
+export PATH="$(cd $MOZ_FETCHES_DIR && pwd)/mingw64/bin:$PATH"
 
 . taskcluster/scripts/misc/vs-setup.sh
 . taskcluster/scripts/misc/tooltool-download.sh
 . taskcluster/scripts/misc/build-gn-common.sh
 
 . $GECKO_PATH/taskcluster/scripts/misc/vs-cleanup.sh
--- a/taskcluster/scripts/misc/build-mingw32-nsis.sh
+++ b/taskcluster/scripts/misc/build-mingw32-nsis.sh
@@ -6,40 +6,41 @@ set -x -e -v
 #   checking for NSIS version...
 #   DEBUG: Executing: `/home/worker/workspace/build/src/mingw32/
 #   DEBUG: The command returned non-zero exit status 1.
 #   DEBUG: Its error output was:
 #   DEBUG: | Error: opening stub "/home/worker/workspace/mingw32/
 #   DEBUG: | Error initalizing CEXEBuild: error setting
 #   ERROR: Failed to get nsis version.
 
-INSTALL_DIR=$GECKO_PATH/mingw32
+INSTALL_DIR=$MOZ_FETCHES_DIR/mingw32
 
 mkdir -p $INSTALL_DIR
 
+cd $MOZ_FETCHES_DIR
+
 # As explained above, we have to build nsis to the directory it
 # will eventually be run from, which is the same place we just
 # installed our compiler. But at the end of the script we want
 # to package up what we just built. If we don't move the compiler,
 # we will package up the compiler we downloaded along with the
 # stuff we just built.
-mv $MOZ_FETCHES_DIR/mingw32 $GECKO_PATH/mingw32-gcc
-export PATH="$GECKO_PATH/mingw32-gcc/bin:$PATH"
-
-cd $MOZ_FETCHES_DIR
+mv mingw32 mingw32-gcc
+export PATH="$MOZ_FETCHES_DIR/mingw32-gcc/bin:$PATH"
 
 # --------------
 
 cd zlib-1.2.11
 make -f win32/Makefile.gcc PREFIX=i686-w64-mingw32-
 
 cd ../nsis-3.01-src
 # I don't know how to make the version work with the environment variables/config flags the way the author appears to
 sed -i "s/'VERSION', 'Version of NSIS', cvs_version/'VERSION', 'Version of NSIS', '3.01'/" SConstruct
 scons XGCC_W32_PREFIX=i686-w64-mingw32- ZLIB_W32=../zlib-1.2.11 SKIPUTILS="NSIS Menu" PREFIX=$INSTALL_DIR/ install
 
 # --------------
 
-cd $GECKO_PATH
+cd $MOZ_FETCHES_DIR
+
 tar caf nsis.tar.xz mingw32
 
 mkdir -p $UPLOAD_DIR
 cp nsis.tar.* $UPLOAD_DIR
--- a/taskcluster/scripts/misc/source-test-clang-setup.sh
+++ b/taskcluster/scripts/misc/source-test-clang-setup.sh
@@ -1,19 +1,19 @@
 #!/bin/bash
 source $HOME/checkouts/gecko/taskcluster/scripts/misc/source-test-common.sh
 
 # Add clang-tidy to PATH
-export PATH=$MOZBUILD_STATE_PATH/clang-tidy/bin:$PATH
+export PATH=$MOZ_FETCHES_DIR/clang-tidy/bin:$PATH
 
 # Use toolchain clang
-export LD_LIBRARY_PATH=$MOZBUILD_STATE_PATH/clang/lib
+export LD_LIBRARY_PATH=$MOZ_FETCHES_DIR/clang/lib
 
 # Write custom mozconfig
-export MOZCONFIG=$HOME/checkouts/gecko/mozconfig
+export MOZCONFIG=$GECKO_PATH/mozconfig
 # Enable debug mode
 echo "ac_add_options --enable-debug"  > $MOZCONFIG
 # Enable GC zeal, a testing and debugging feature that helps find GC-related bugs in JSAPI applications.
 echo "ac_add_options --enable-gczeal" > $MOZCONFIG
 
 # Mach lookup clang-tidy in clang-tools
 mkdir -p $MOZBUILD_STATE_PATH/clang-tools
-ln -s $MOZBUILD_STATE_PATH/clang-tidy $MOZBUILD_STATE_PATH/clang-tools/clang-tidy
+ln -s $MOZ_FETCHES_DIR/clang-tidy $MOZBUILD_STATE_PATH/clang-tools/clang-tidy
--- a/taskcluster/scripts/misc/source-test-common.sh
+++ b/taskcluster/scripts/misc/source-test-common.sh
@@ -1,22 +1,16 @@
 #! /bin/bash -vex
 
 set -x -e
 
 export MOZBUILD_STATE_PATH=$HOME/workspace
 
-# Setup toolchains
-pushd $MOZBUILD_STATE_PATH
-$HOME/checkouts/gecko/mach artifact toolchain -v $MOZ_TOOLCHAINS
-
 # Add toolchain binaries to PATH to run ./mach configure
-export PATH=$MOZBUILD_STATE_PATH/clang/bin:$PATH
-export PATH=$MOZBUILD_STATE_PATH/rustc/bin:$PATH
-export PATH=$MOZBUILD_STATE_PATH/cbindgen:$PATH
-export PATH=$MOZBUILD_STATE_PATH/nasm:$PATH
-export PATH=$MOZBUILD_STATE_PATH/node/bin:$PATH
+export PATH=$MOZ_FETCHES_DIR/clang/bin:$PATH
+export PATH=$MOZ_FETCHES_DIR/rustc/bin:$PATH
+export PATH=$MOZ_FETCHES_DIR/cbindgen:$PATH
+export PATH=$MOZ_FETCHES_DIR/nasm:$PATH
+export PATH=$MOZ_FETCHES_DIR/node/bin:$PATH
 
 # Use clang as host compiler
-export CC=$MOZBUILD_STATE_PATH/clang/bin/clang
-export CXX=$MOZBUILD_STATE_PATH/clang/bin/clang++
-
-popd
+export CC=$MOZ_FETCHES_DIR/clang/bin/clang
+export CXX=$MOZ_FETCHES_DIR/clang/bin/clang++
--- a/taskcluster/scripts/misc/source-test-infer-setup.sh
+++ b/taskcluster/scripts/misc/source-test-infer-setup.sh
@@ -1,18 +1,18 @@
 #!/bin/bash
-source $HOME/checkouts/gecko/taskcluster/scripts/misc/source-test-common.sh
+source $GECKO_PATH/taskcluster/scripts/misc/source-test-common.sh
 
 # Write custom mozconfig
-MOZCONFIG=$HOME/checkouts/gecko/mozconfig
+MOZCONFIG=$GECKO_PATH/mozconfig
 echo "ac_add_options --enable-application=mobile/android" > $MOZCONFIG
 echo "ac_add_options --target=arm-linux-androideabi" >> $MOZCONFIG
-echo "ac_add_options --with-android-sdk=${MOZBUILD_STATE_PATH}/android-sdk-linux" >> $MOZCONFIG
-echo "ac_add_options --with-android-ndk=${MOZBUILD_STATE_PATH}/android-ndk" >> $MOZCONFIG
+echo "ac_add_options --with-android-sdk=${MOZ_FETCHES_DIR}/android-sdk-linux" >> $MOZCONFIG
+echo "ac_add_options --with-android-ndk=${MOZ_FETCHES_DIR}/android-ndk" >> $MOZCONFIG
 
 # Write custom grade properties
 export GRADLE_USER_HOME=$HOME/workspace/gradle
 mkdir -p $GRADLE_USER_HOME
 echo "org.gradle.daemon=false" >> ${GRADLE_USER_HOME}/gradle.properties
 
 # Mach lookup infer in infer...
 mkdir -p $MOZBUILD_STATE_PATH/infer/infer
-mv $MOZBUILD_STATE_PATH/infer/{bin,lib} $MOZBUILD_STATE_PATH/infer/infer
+mv $MOZ_FETCHES_DIR/infer/{bin,lib} $MOZBUILD_STATE_PATH/infer/infer
--- a/taskcluster/scripts/run-task
+++ b/taskcluster/scripts/run-task
@@ -507,18 +507,20 @@ def fetch_artifacts():
         fetch_content = os.path.join(os.path.dirname(__file__),
                                      'fetch-content')
 
     if not os.path.isfile(fetch_content):
         print(FETCH_CONTENT_NOT_FOUND)
         sys.exit(1)
 
     cmd = [sys.executable, '-u', fetch_content, 'task-artifacts']
-    print_line(b'fetches', b'executing %r\n' % cmd)
-    subprocess.run(cmd, check=True, env=os.environ)
+    res = run_and_prefix_output(b'fetches', cmd)
+    if res:
+        sys.exit(res)
+
     print_line(b'fetches', b'finished fetching artifacts\n')
 
 
 def add_vcs_arguments(parser, project, name):
     """Adds arguments to ArgumentParser to control VCS options for a project."""
 
     parser.add_argument('--%s-checkout' % project,
                         help='Directory where %s checkout should be created' %
@@ -831,17 +833,19 @@ def main(args):
         os.setresuid(uid, uid, uid)
 
     vcs_checkout_from_args(args, 'gecko')
     vcs_checkout_from_args(args, 'comm')
 
     try:
         for k in ('GECKO_PATH', 'MOZ_FETCHES_DIR', 'UPLOAD_DIR'):
             if k in os.environ:
-                os.environ[k] = os.path.abspath(os.environ[k])
+                # Normalize paths to use forward slashes. Some shell scripts
+                # tolerate that better on Windows.
+                os.environ[k] = os.path.abspath(os.environ[k]).replace(os.sep, '/')
                 print_line(b'setup', b'%s is %s\n' % (
                     k.encode('utf-8'),
                     os.environ[k].encode('utf-8')))
 
         if 'MOZ_FETCHES' in os.environ:
             fetch_artifacts()
 
         return run_and_prefix_output(b'task', task_args, cwd=args.task_cwd)
--- a/taskcluster/taskgraph/transforms/build_fat_aar.py
+++ b/taskcluster/taskgraph/transforms/build_fat_aar.py
@@ -38,20 +38,20 @@ def set_fetches_and_locations(config, jo
 
             aar_location = _get_aar_location(config, job, platform)
             prefix = get_artifact_prefix(job)
             if not prefix.endswith('/'):
                 prefix = prefix + '/'
             if aar_location.startswith(prefix):
                 aar_location = aar_location[len(prefix):]
 
-            job['fetches'][platform] = [{
+            job.setdefault('fetches', {}).setdefault(platform, []).append({
                 'artifact': aar_location,
                 'extract': False,
-            }]
+            })
 
             aar_file_name = aar_location.split('/')[-1]
             env_var = MOZ_ANDROID_FAT_AAR_ENV_MAP[platform]
             job['worker']['env'][env_var] = aar_file_name
 
         job['dependencies'] = dependencies
 
         yield job
--- a/taskcluster/taskgraph/transforms/diffoscope.py
+++ b/taskcluster/taskgraph/transforms/diffoscope.py
@@ -152,14 +152,14 @@ def fill_template(config, tasks):
                     ' --unpack' if task.get('unpack') else '',
                     ' --fail' if task.get('fail-on-diff') else '',
                 ),
             },
             'dependencies': deps,
         }
 
         if artifact.endswith('.dmg'):
-            taskdesc['toolchains'] = [
+            taskdesc.setdefault('fetches', {}).setdefault('toolchain', []).extend([
                 'linux64-cctools-port',
                 'linux64-libdmg',
-            ]
+            ])
 
         yield taskdesc
--- a/taskcluster/taskgraph/transforms/job/__init__.py
+++ b/taskcluster/taskgraph/transforms/job/__init__.py
@@ -213,16 +213,19 @@ def use_fetches(config, jobs):
                             job['scopes'].append(scope)
 
                     dependencies[label] = label
                     job_fetches.append({
                         'artifact': path,
                         'task': '<{label}>'.format(label=label),
                         'extract': True,
                     })
+
+                    if kind == 'toolchain' and fetch_name.endswith('-sccache'):
+                        job['needs-sccache'] = True
             else:
                 if kind not in dependencies:
                     raise Exception("{name} can't fetch {kind} artifacts because "
                                     "it has no {kind} dependencies!".format(name=name, kind=kind))
 
                 for artifact in artifacts:
                     if isinstance(artifact, basestring):
                         path = artifact
--- a/taskcluster/taskgraph/transforms/job/hazard.py
+++ b/taskcluster/taskgraph/transforms/job/hazard.py
@@ -5,23 +5,25 @@
 Support for running hazard jobs via dedicated scripts
 """
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 from taskgraph.util.schema import Schema
 from voluptuous import Required, Optional, Any
 
-from taskgraph.transforms.job import run_job_using
+from taskgraph.transforms.job import (
+    run_job_using,
+    configure_taskdesc_for_run,
+)
 from taskgraph.transforms.job.common import (
     docker_worker_add_workspace_cache,
     setup_secrets,
     docker_worker_add_artifacts,
     docker_worker_add_tooltool,
-    support_vcs_checkout,
 )
 
 haz_run_schema = Schema({
     Required('using'): 'hazard',
 
     # The command to run within the task image (passed through to the worker)
     Required('command'): basestring,
 
@@ -39,37 +41,29 @@ haz_run_schema = Schema({
     Required('workdir'): basestring,
 })
 
 
 @run_job_using("docker-worker", "hazard", schema=haz_run_schema)
 def docker_worker_hazard(config, job, taskdesc):
     run = job['run']
 
-    worker = taskdesc['worker']
+    worker = taskdesc['worker'] = job['worker']
     worker['artifacts'] = []
 
     docker_worker_add_artifacts(config, job, taskdesc)
     docker_worker_add_workspace_cache(config, job, taskdesc)
     docker_worker_add_tooltool(config, job, taskdesc)
     setup_secrets(config, job, taskdesc)
-    support_vcs_checkout(config, job, taskdesc)
 
     env = worker['env']
     env.update({
         'MOZ_BUILD_DATE': config.params['moz_build_date'],
         'MOZ_SCM_LEVEL': config.params['level'],
     })
 
     # script parameters
     if run.get('mozconfig'):
-        env['MOZCONFIG'] = run['mozconfig']
-
-    # build-haz-linux.sh needs this otherwise it assumes the checkout is in
-    # the workspace.
-    env['GECKO_DIR'] = '{workdir}/checkouts/gecko'.format(**run)
+        env['MOZCONFIG'] = run.pop('mozconfig')
 
-    worker['command'] = [
-        '{workdir}/bin/run-task'.format(**run),
-        '--gecko-checkout', '{workdir}/checkouts/gecko'.format(**run),
-        '--',
-        '/bin/bash', '-c', run['command']
-    ]
+    run['using'] = 'run-task'
+    run['cwd'] = run['workdir']
+    configure_taskdesc_for_run(config, job, taskdesc, worker['implementation'])
--- a/taskcluster/taskgraph/transforms/job/spidermonkey.py
+++ b/taskcluster/taskgraph/transforms/job/spidermonkey.py
@@ -5,23 +5,24 @@
 Support for running spidermonkey jobs via dedicated scripts
 """
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 from taskgraph.util.schema import Schema
 from voluptuous import Required, Any, Optional
 
-from taskgraph.transforms.job import run_job_using
+from taskgraph.transforms.job import (
+    run_job_using,
+    configure_taskdesc_for_run,
+)
 from taskgraph.transforms.job.common import (
     docker_worker_add_artifacts,
     generic_worker_add_artifacts,
-    generic_worker_hg_commands,
     docker_worker_add_tooltool,
-    support_vcs_checkout,
 )
 
 sm_run_schema = Schema({
     Required('using'): Any('spidermonkey', 'spidermonkey-package', 'spidermonkey-mozjs-crate',
                            'spidermonkey-rust-bindings'),
 
     # SPIDERMONKEY_VARIANT and SPIDERMONKEY_PLATFORM
     Required('spidermonkey-variant'): basestring,
@@ -36,104 +37,92 @@ sm_run_schema = Schema({
 @run_job_using("docker-worker", "spidermonkey-package", schema=sm_run_schema)
 @run_job_using("docker-worker", "spidermonkey-mozjs-crate",
                schema=sm_run_schema)
 @run_job_using("docker-worker", "spidermonkey-rust-bindings",
                schema=sm_run_schema)
 def docker_worker_spidermonkey(config, job, taskdesc):
     run = job['run']
 
-    worker = taskdesc['worker']
+    worker = taskdesc['worker'] = job['worker']
     worker['artifacts'] = []
     worker.setdefault('caches', []).append({
         'type': 'persistent',
         'name': '{}-build-spidermonkey-workspace'.format(config.params['project']),
         'mount-point': "{workdir}/workspace".format(**run),
         'skip-untrusted': True,
     })
 
     docker_worker_add_artifacts(config, job, taskdesc)
     docker_worker_add_tooltool(config, job, taskdesc)
 
     env = worker.setdefault('env', {})
     env.update({
         'MOZHARNESS_DISABLE': 'true',
-        'SPIDERMONKEY_VARIANT': run['spidermonkey-variant'],
+        'SPIDERMONKEY_VARIANT': run.pop('spidermonkey-variant'),
         'MOZ_BUILD_DATE': config.params['moz_build_date'],
         'MOZ_SCM_LEVEL': config.params['level'],
+        'GECKO_PATH': '{}/workspace/build/src'.format(run['workdir'])
     })
     if 'spidermonkey-platform' in run:
-        env['SPIDERMONKEY_PLATFORM'] = run['spidermonkey-platform']
-
-    support_vcs_checkout(config, job, taskdesc)
+        env['SPIDERMONKEY_PLATFORM'] = run.pop('spidermonkey-platform')
 
     script = "build-sm.sh"
     if run['using'] == 'spidermonkey-package':
         script = "build-sm-package.sh"
     elif run['using'] == 'spidermonkey-mozjs-crate':
         script = "build-sm-mozjs-crate.sh"
     elif run['using'] == 'spidermonkey-rust-bindings':
         script = "build-sm-rust-bindings.sh"
 
-    worker['command'] = [
-        '{workdir}/bin/run-task'.format(**run),
-        '--gecko-checkout', '{workdir}/workspace/build/src'.format(**run),
-        '--',
-        '/bin/bash',
-        '-c',
-        'cd {workdir} && workspace/build/src/taskcluster/scripts/builder/{script}'.format(
-            workdir=run['workdir'], script=script)
+    run['using'] = 'run-task'
+    run['cwd'] = run['workdir']
+    run['command'] = [
+        'workspace/build/src/taskcluster/scripts/builder/{script}'.format(
+            script=script)
     ]
 
+    configure_taskdesc_for_run(config, job, taskdesc, worker['implementation'])
+
 
 @run_job_using("generic-worker", "spidermonkey", schema=sm_run_schema)
 def generic_worker_spidermonkey(config, job, taskdesc):
     assert job['worker']['os'] == 'windows', 'only supports windows right now'
 
     run = job['run']
 
-    worker = taskdesc['worker']
+    worker = taskdesc['worker'] = job['worker']
 
     generic_worker_add_artifacts(config, job, taskdesc)
-    support_vcs_checkout(config, job, taskdesc)
 
     env = worker.setdefault('env', {})
     env.update({
         'MOZHARNESS_DISABLE': 'true',
-        'SPIDERMONKEY_VARIANT': run['spidermonkey-variant'],
+        'SPIDERMONKEY_VARIANT': run.pop('spidermonkey-variant'),
         'MOZ_BUILD_DATE': config.params['moz_build_date'],
         'MOZ_SCM_LEVEL': config.params['level'],
         'SCCACHE_DISABLE': "1",
         'WORK': ".",  # Override the defaults in build scripts
-        'SRCDIR': "./src",  # with values suiteable for windows generic worker
+        'GECKO_PATH': "./src",  # with values suiteable for windows generic worker
         'UPLOAD_DIR': "./public/build"
     })
     if 'spidermonkey-platform' in run:
-        env['SPIDERMONKEY_PLATFORM'] = run['spidermonkey-platform']
+        env['SPIDERMONKEY_PLATFORM'] = run.pop('spidermonkey-platform')
 
     script = "build-sm.sh"
     if run['using'] == 'spidermonkey-package':
         script = "build-sm-package.sh"
         # Don't allow untested configurations yet
         raise Exception("spidermonkey-package is not a supported configuration")
     elif run['using'] == 'spidermonkey-mozjs-crate':
         script = "build-sm-mozjs-crate.sh"
         # Don't allow untested configurations yet
         raise Exception("spidermonkey-mozjs-crate is not a supported configuration")
     elif run['using'] == 'spidermonkey-rust-bindings':
         script = "build-sm-rust-bindings.sh"
         # Don't allow untested configurations yet
         raise Exception("spidermonkey-rust-bindings is not a supported configuration")
 
-    hg_command = generic_worker_hg_commands(
-        'https://hg.mozilla.org/mozilla-unified',
-        env['GECKO_HEAD_REPOSITORY'],
-        env['GECKO_HEAD_REV'],
-        r'.\src',
-    )[0]
+    run['using'] = 'run-task'
+    run['command'] = ['c:\\mozilla-build\\msys\\bin\\bash.exe '  # string concat
+                      '"./src/taskcluster/scripts/builder/%s"' % script]
 
-    command = ['c:\\mozilla-build\\msys\\bin\\bash.exe '  # string concat
-               '"./src/taskcluster/scripts/builder/%s"' % script]
-
-    worker['command'] = [
-        hg_command,
-        ' '.join(command),
-    ]
+    configure_taskdesc_for_run(config, job, taskdesc, worker['implementation'])
--- a/taskcluster/taskgraph/transforms/job/toolchain.py
+++ b/taskcluster/taskgraph/transforms/job/toolchain.py
@@ -127,17 +127,16 @@ def docker_worker_toolchain(config, job,
     # Toolchain checkouts don't live under {workdir}/checkouts
     workspace = '{workdir}/workspace/build'.format(**run)
     gecko_path = '{}/src'.format(workspace)
 
     env = worker['env']
     env.update({
         'MOZ_BUILD_DATE': config.params['moz_build_date'],
         'MOZ_SCM_LEVEL': config.params['level'],
-        'MOZ_FETCHES_DIR': workspace,
         'GECKO_PATH': gecko_path,
     })
 
     attributes = taskdesc.setdefault('attributes', {})
     attributes['toolchain-artifact'] = run.pop('toolchain-artifact')
     if 'toolchain-alias' in run:
         attributes['toolchain-alias'] = run.pop('toolchain-alias')
 
--- a/taskcluster/taskgraph/transforms/l10n.py
+++ b/taskcluster/taskgraph/transforms/l10n.py
@@ -99,17 +99,19 @@ l10n_description_schema = schema.extend(
     # Docker image required for task.  We accept only in-tree images
     # -- generally desktop-build or android-build -- for now.
     Required('docker-image'): _by_platform(Any(
         # an in-tree generated docker image (from `taskcluster/docker/<name>`)
         {'in-tree': basestring},
         None,
     )),
 
-    Optional('toolchains'): _by_platform([basestring]),
+    Optional('fetches'): {
+        basestring: _by_platform([basestring]),
+    },
 
     # The set of secret names to which the task has access; these are prefixed
     # with `project/releng/gecko/{treeherder.kind}/level-{level}/`.  Setting
     # this will enable any worker features required and set the task's scopes
     # appropriately.  `true` here means ['*'], all secrets.  Not supported on
     # Windows
     Required('secrets', default=False): _by_platform(Any(bool, [basestring])),
 
@@ -229,17 +231,17 @@ def handle_keyed_by(config, jobs):
     fields = [
         "locales-file",
         "locales-per-chunk",
         "worker-type",
         "description",
         "run-time",
         "docker-image",
         "secrets",
-        "toolchains",
+        "fetches.toolchain",
         "tooltool",
         "env",
         "ignore-locales",
         "mozharness.config",
         "mozharness.options",
         "mozharness.actions",
         "mozharness.script",
         "treeherder.tier",
@@ -397,18 +399,18 @@ def make_job_description(config, jobs):
                 'chain-of-trust': True,
             }
             job_description['run']['tooltool-downloads'] = job['tooltool']
             job_description['run']['need-xvfb'] = True
 
         if job.get('docker-image'):
             job_description['worker']['docker-image'] = job['docker-image']
 
-        if job.get('toolchains'):
-            job_description['toolchains'] = job['toolchains']
+        if job.get('fetches'):
+            job_description['fetches'] = job['fetches']
 
         if job.get('index'):
             job_description['index'] = {
                 'product': job['index']['product'],
                 'job-name': job['index']['job-name'],
                 'type': job['index'].get('type', 'generic'),
             }
 
--- a/taskcluster/taskgraph/transforms/repackage.py
+++ b/taskcluster/taskgraph/transforms/repackage.py
@@ -333,21 +333,21 @@ def make_job_description(config, jobs):
                                                  signing_task, repackage_signing_task,
                                                  locale=locale,
                                                  project=config.params["project"],
                                                  existing_fetch=job.get('fetches')),
             'release-artifacts': [artifact['name'] for artifact in worker['artifacts']]
         }
 
         if build_platform.startswith('macosx'):
-            task['toolchains'] = [
+            task.setdefault('fetches', {}).setdefault('toolchain', []).extend([