Project import generated by Copybara.

GitOrigin-RevId: abea2b04eba80feee70a464607bdb5645564eaa4
diff --git a/nss-3.88/nss/automation/taskcluster/docker-aarch64/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-aarch64/Dockerfile
new file mode 100644
index 0000000..aca173c
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-aarch64/Dockerfile
@@ -0,0 +1,29 @@
+FROM franziskus/xenial:aarch64
+MAINTAINER Franziskus Kiefer <franziskuskiefer@gmail.com>
+
+RUN useradd -d /home/worker -s /bin/bash -m worker
+WORKDIR /home/worker
+
+# Add build and test scripts.
+ADD bin /home/worker/bin
+RUN chmod +x /home/worker/bin/*
+
+# Install dependencies.
+ADD setup.sh /tmp/setup.sh
+RUN bash /tmp/setup.sh
+
+# Change user.
+# USER worker # See bug 1347473.
+
+# Env variables.
+ENV HOME /home/worker
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME worker
+ENV LANG en_US.UTF-8
+ENV LC_ALL en_US.UTF-8
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-aarch64/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-aarch64/bin/checkout.sh
new file mode 100755
index 0000000..9167f6b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-aarch64/bin/checkout.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/docker-aarch64/setup.sh b/nss-3.88/nss/automation/taskcluster/docker-aarch64/setup.sh
new file mode 100755
index 0000000..b76514a
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-aarch64/setup.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+export DEBIAN_FRONTEND=noninteractive
+
+apt-get -y update
+apt-get -y install software-properties-common
+
+# Add more repos
+add-apt-repository "deb http://ports.ubuntu.com/ xenial main restricted universe multiverse"
+add-apt-repository "deb http://ports.ubuntu.com/ xenial-security main restricted universe multiverse"
+add-apt-repository "deb http://ports.ubuntu.com/ xenial-updates main restricted universe multiverse"
+add-apt-repository "deb http://ports.ubuntu.com/ xenial-backports main restricted universe multiverse"
+
+# Update.
+apt-get -y update
+apt-get -y dist-upgrade
+
+apt_packages=()
+apt_packages+=('build-essential')
+apt_packages+=('ca-certificates')
+apt_packages+=('curl')
+apt_packages+=('libxml2-utils')
+apt_packages+=('zlib1g-dev')
+apt_packages+=('ninja-build')
+apt_packages+=('gyp')
+apt_packages+=('mercurial')
+apt_packages+=('locales')
+
+# Install packages.
+apt-get install -y --no-install-recommends ${apt_packages[@]}
+
+locale-gen en_US.UTF-8
+dpkg-reconfigure locales
+
+# Cleanup.
+rm -rf ~/.ccache ~/.cache
+apt-get autoremove -y
+apt-get clean
+apt-get autoclean
+rm $0
diff --git a/nss-3.88/nss/automation/taskcluster/docker-acvp/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-acvp/Dockerfile
new file mode 100644
index 0000000..78f0ce9
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-acvp/Dockerfile
@@ -0,0 +1,49 @@
+# Minimal image with clang-format 3.9.
+FROM rust:1.64
+LABEL maintainer="iaroslav.gridin@tuni.fi"
+
+# for new clang/llvm
+RUN echo "deb http://ftp.debian.org/debian/ sid main" > /etc/apt/sources.list.d/sid.list \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends \
+    ca-certificates \
+    locales \
+    python-dev-is-python3 \
+    mercurial \
+    python3-pip \
+    python-setuptools \
+    build-essential \
+    cargo \
+    rustc \
+    git \
+    gyp \
+    clang-15 \
+    llvm-15 \
+    ninja-build \
+    binutils \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y
+
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME $USER
+ENV HOME /home/$USER
+ENV HOSTNAME taskcluster-worker
+ENV LANG en_US.UTF-8
+ENV LC_ALL $LANG
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+RUN locale-gen $LANG \
+ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
+
+RUN useradd -d $HOME -s $SHELL -m $USER
+WORKDIR $HOME
+
+ADD bin $HOME/bin
+RUN chmod +x $HOME/bin/*
+
+USER $USER
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-acvp/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-acvp/bin/checkout.sh
new file mode 100755
index 0000000..2a7d32c
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-acvp/bin/checkout.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+hg clone -r $REVISION $REPOSITORY nss
+
+# Clone NSPR if needed.
+hg clone -r default https://hg.mozilla.org/projects/nspr
+
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
diff --git a/nss-3.88/nss/automation/taskcluster/docker-acvp/bin/run.sh b/nss-3.88/nss/automation/taskcluster/docker-acvp/bin/run.sh
new file mode 100755
index 0000000..a523785
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-acvp/bin/run.sh
@@ -0,0 +1,26 @@
+#!/bin/bash -eu
+#
+# 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/.
+#
+################################################################################
+export NSS_PATH=$PWD NSS_SOURCES_PATH=$PWD/nss
+export LD_LIBRARY_PATH=$PWD/dist/Debug/lib/
+export RUST_LOG=warn
+export RUSTFLAGS="-C instrument-coverage"
+cd nss
+CC=clang-15 CXX=clang++-15 ./build.sh -g -v --sourcecov --static --disable-tests
+
+git clone --depth=1 https://gitlab.com/nisec/nss-project/acvp-rust.git
+cd acvp-rust
+cargo build
+TESTRUN="cargo run --bin test -- --profdata-command llvm-profdata-15"
+echo "AES-GCM:"
+$TESTRUN acvp-rust/samples/aes-gcm.json symmetric nss
+echo "ECDSA:"
+$TESTRUN acvp-rust/samples/ecdsa.json ecdsa nss
+echo "RSA:"
+$TESTRUN acvp-rust/samples/rsa.json rsa nss
+echo "SHA-256:"
+$TESTRUN acvp-rust/samples/sha256.json sha nss
diff --git a/nss-3.88/nss/automation/taskcluster/docker-arm/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-arm/Dockerfile
new file mode 100644
index 0000000..5b8cfca
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-arm/Dockerfile
@@ -0,0 +1,26 @@
+FROM armv7/armhf-ubuntu:16.04
+MAINTAINER Franziskus Kiefer <franziskuskiefer@gmail.com>
+
+RUN useradd -d /home/worker -s /bin/bash -m worker
+WORKDIR /home/worker
+
+# Add build and test scripts.
+ADD bin /home/worker/bin
+RUN chmod +x /home/worker/bin/*
+
+# Install dependencies.
+ADD setup.sh /tmp/setup.sh
+RUN bash /tmp/setup.sh
+
+# Env variables.
+ENV HOME /home/worker
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME worker
+ENV LANG en_US.UTF-8
+ENV LC_ALL en_US.UTF-8
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-arm/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-arm/bin/checkout.sh
new file mode 100755
index 0000000..4b89128
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-arm/bin/checkout.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # set up fake uname
+    if [ ! -f /bin/uname-real ]; then
+        mv /bin/uname /bin/uname-real
+        ln -s /home/worker/bin/uname.sh /bin/uname
+    fi
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/docker-arm/bin/uname.sh b/nss-3.88/nss/automation/taskcluster/docker-arm/bin/uname.sh
new file mode 100755
index 0000000..61ad13c
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-arm/bin/uname.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+args=`getopt rmvs $*`
+set -- $args
+for i
+do
+  if [ "$i" == "-v" ]; then
+    /bin/uname-real -v
+  fi
+  if [ "$i" == "-r" ]; then
+    echo "4.4.16-v7+"
+  fi
+  if [ "$i" == "-m" ]; then
+    echo "armv7l"
+  fi
+  if [ "$i" == "-s" ]; then
+    echo "Linux"
+  fi
+done
\ No newline at end of file
diff --git a/nss-3.88/nss/automation/taskcluster/docker-arm/setup.sh b/nss-3.88/nss/automation/taskcluster/docker-arm/setup.sh
new file mode 100755
index 0000000..78c6392
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-arm/setup.sh
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+export DEBIAN_FRONTEND=noninteractive
+
+# Update.
+apt-get -y update
+apt-get -y dist-upgrade
+
+apt_packages=()
+apt_packages+=('build-essential')
+apt_packages+=('ca-certificates')
+apt_packages+=('curl')
+apt_packages+=('locales')
+apt_packages+=('python-dev')
+apt_packages+=('python-pip')
+apt_packages+=('python-setuptools')
+apt_packages+=('zlib1g-dev')
+
+# Install packages.
+apt-get install -y --no-install-recommends ${apt_packages[@]}
+
+# Latest Mercurial.
+pip install --upgrade pip
+pip install Mercurial
+
+locale-gen en_US.UTF-8
+dpkg-reconfigure locales
+
+# Cleanup.
+rm -rf ~/.ccache ~/.cache
+apt-get autoremove -y
+apt-get clean
+apt-get autoclean
+rm $0
diff --git a/nss-3.88/nss/automation/taskcluster/docker-builds/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-builds/Dockerfile
new file mode 100644
index 0000000..6ea2543
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-builds/Dockerfile
@@ -0,0 +1,75 @@
+# Dockerfile for building extra builds.  This includes more tools than the
+# default image, so it's a fair bit bigger.  Only use this for builds where
+# the smaller docker image is missing something.  These builds will run on
+# the leaner configuration.
+FROM ubuntu:18.04
+LABEL maintainer="Martin Thomson <martin.thomson@gmail.com>"
+
+RUN dpkg --add-architecture i386
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+    build-essential \
+    ca-certificates \
+    clang-4.0 \
+    clang-10 \
+    clang \
+    cmake \
+    curl \
+    g++-4.8-multilib \
+    g++-5-multilib \
+    g++-multilib \
+    git \
+    gyp \
+    libelf-dev \
+    libdw-dev \
+    libssl-dev \
+    libssl-dev:i386 \
+    libxml2-utils \
+    lib32z1-dev \
+    linux-libc-dev:i386 \
+    llvm-dev \
+    locales \
+    mercurial \
+    ninja-build \
+    pkg-config \
+    valgrind \
+    zlib1g-dev \
+    clang-format-10 \
+    sqlite3 \ 
+    libabigail-dev \
+    abigail-tools \
+    software-properties-common \ 
+ && add-apt-repository ppa:ubuntu-toolchain-r/test -y \ 
+ && apt-get update \
+ && apt-get install --no-install-recommends -y \ 
+    gcc-11-multilib \
+    g++-11-multilib \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y
+
+RUN update-alternatives --install /usr/bin/clang-format \
+    clang-format $(which clang-format-10) 10
+
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME $USER
+ENV HOME /home/$USER
+ENV LANG en_US.UTF-8
+ENV LC_ALL $LANG
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+RUN locale-gen $LANG \
+ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
+
+RUN useradd -d $HOME -s $SHELL -m $USER
+WORKDIR $HOME
+
+# Add build and test scripts.
+ADD bin $HOME/bin
+RUN chmod +x $HOME/bin/*
+
+USER $USER
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-builds/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-builds/bin/checkout.sh
new file mode 100644
index 0000000..9167f6b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-builds/bin/checkout.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/docker-clang-format/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-clang-format/Dockerfile
new file mode 100644
index 0000000..8ef4bb0
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-clang-format/Dockerfile
@@ -0,0 +1,38 @@
+# Minimal image with clang-format 10
+FROM ubuntu:18.04
+LABEL maintainer="Martin Thomson <martin.thomson@gmail.com>"
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+    ca-certificates \
+    clang-format-10 \
+    locales \
+    mercurial \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y
+
+RUN update-alternatives --install /usr/bin/clang-format \
+    clang-format $(which clang-format-10) 10
+
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME $USER
+ENV HOME /home/$USER
+ENV LANG en_US.UTF-8
+ENV LC_ALL $LANG
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+RUN locale-gen $LANG \
+ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
+
+RUN useradd -d $HOME -s $SHELL -m $USER
+WORKDIR $HOME
+
+ADD bin $HOME/bin
+RUN chmod +x $HOME/bin/*
+
+USER $USER
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-clang-format/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-clang-format/bin/checkout.sh
new file mode 100644
index 0000000..9167f6b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-clang-format/bin/checkout.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/docker-decision/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-decision/Dockerfile
new file mode 100644
index 0000000..8ce08a8
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-decision/Dockerfile
@@ -0,0 +1,38 @@
+# Minimal image for running the decision task.
+FROM ubuntu:18.04
+LABEL maintainer="Martin Thomson <martin.thomson@gmail.com>"
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+    ca-certificates \
+    curl \
+    locales \
+    mercurial \
+    nodejs \
+    npm \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y
+
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME $USER
+ENV HOME /home/$USER
+ENV LANG en_US.UTF-8
+ENV LC_ALL $LANG
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+RUN locale-gen $LANG \
+ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
+
+RUN useradd -d $HOME -s $SHELL -m $USER
+WORKDIR $HOME
+
+# Add build and test scripts.
+ADD bin $HOME/bin
+RUN chmod +x $HOME/bin/*
+
+USER $USER
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-decision/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-decision/bin/checkout.sh
new file mode 100644
index 0000000..0cdd2ac
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-decision/bin/checkout.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/docker-fuzz/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-fuzz/Dockerfile
new file mode 100644
index 0000000..d7e7fa9
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-fuzz/Dockerfile
@@ -0,0 +1,61 @@
+# Dockerfile for running fuzzing tests.
+# Used for ASAN.
+# Note that when running this, you need to add `--cap-add SYS_PTRACE` to the
+# docker invocation or ASAN won't work.
+# On taskcluster for ASAN use `features: ["allowPtrace"]`.
+# See https://github.com/google/sanitizers/issues/764#issuecomment-276700920
+FROM ubuntu:18.04
+LABEL maintainer="Martin Thomson <martin.thomson@gmail.com>"
+
+RUN dpkg --add-architecture i386
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+    build-essential \
+    ca-certificates \
+    clang \
+    clang-tools \
+    curl \
+    g++-multilib \
+    git \
+    gyp \
+    libssl-dev \
+    libssl-dev:i386 \
+    libxml2-utils \
+    lib32z1-dev \
+    linux-libc-dev:i386 \
+    llvm-dev \
+    locales \
+    mercurial \
+    ninja-build \
+    pkg-config \
+    python-pip \
+    valgrind \
+    zlib1g-dev \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y \
+ && pip install requests
+
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME $USER
+ENV HOME /home/$USER
+ENV LANG en_US.UTF-8
+ENV LC_ALL $LANG
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+RUN locale-gen $LANG \
+ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
+
+RUN useradd -d $HOME -s $SHELL -m $USER
+WORKDIR $HOME
+
+# Add build and test scripts.
+ADD bin $HOME/bin
+RUN chmod +x $HOME/bin/*
+
+# Change user.
+USER $USER
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-fuzz/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-fuzz/bin/checkout.sh
new file mode 100644
index 0000000..9167f6b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-fuzz/bin/checkout.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/docker-fuzz32/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-fuzz32/Dockerfile
new file mode 100644
index 0000000..e80b94d
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-fuzz32/Dockerfile
@@ -0,0 +1,75 @@
+# Dockerfile for running fuzzing tests on linux32.
+#
+# This is a temporary workaround for bugs in clang that make it incompatible
+# with Ubuntu 18.04 (see bug 1488148). This image can be removed once a new
+# release of LLVM includes the necessary fixes.
+
+FROM ubuntu:16.04
+LABEL maintainer="Martin Thomson <martin.thomson@gmail.com>"
+
+RUN dpkg --add-architecture i386
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+    apt-transport-https \
+    apt-utils \
+    build-essential \
+    ca-certificates \
+    curl \
+    g++-multilib \
+    git \
+    gyp \
+    libssl-dev \
+    libssl-dev:i386 \
+    libxml2-utils \
+    lib32z1-dev \
+    linux-libc-dev:i386 \
+    locales \
+    mercurial \
+    ninja-build \
+    pkg-config \
+    software-properties-common \
+    valgrind \
+    zlib1g-dev \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y
+
+# Install clang and tools from the LLVM PPA.
+RUN curl -sf https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - \
+ && apt-add-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-6.0 main" \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends \
+    clang-6.0 \
+    clang-tools-6.0 \
+    llvm-6.0-dev \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y
+
+# Alias all the clang commands.
+RUN for i in $(dpkg -L clang-6.0 clang-tools-6.0 | grep '^/usr/bin/' | xargs -i basename {} -6.0); do \
+      update-alternatives --install "/usr/bin/$i" "$i" "/usr/bin/${i}-6.0" 10; \
+    done
+
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME $USER
+ENV HOME /home/$USER
+ENV LANG en_US.UTF-8
+ENV LC_ALL $LANG
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+RUN locale-gen $LANG \
+ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
+
+RUN useradd -d $HOME -s $SHELL -m $USER
+WORKDIR $HOME
+
+# Add build and test scripts.
+ADD bin $HOME/bin
+RUN chmod +x $HOME/bin/*
+
+# Change user.
+USER $USER
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-fuzz32/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-fuzz32/bin/checkout.sh
new file mode 100644
index 0000000..9167f6b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-fuzz32/bin/checkout.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/docker-gcc-4.4/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-gcc-4.4/Dockerfile
new file mode 100644
index 0000000..866e806
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-gcc-4.4/Dockerfile
@@ -0,0 +1,41 @@
+FROM ubuntu:14.04
+LABEL maintainer="Martin Thomson <martin.thomson@gmail.com>"
+
+RUN dpkg --add-architecture i386
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+    ca-certificates \
+    g++-4.4 \
+    gcc-4.4 \
+    locales \
+    make \
+    patch \
+    mercurial \
+    sqlite3 \
+    zlib1g-dev \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y
+
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME $USER
+ENV HOME /home/$USER
+ENV LANG en_US.UTF-8
+ENV LC_ALL $LANG
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+RUN locale-gen $LANG \
+ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
+
+RUN useradd -d $HOME -s $SHELL -m $USER
+WORKDIR $HOME
+
+# Add build and test scripts.
+ADD bin $HOME/bin
+RUN chmod +x $HOME/bin/*
+
+USER $USER
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-gcc-4.4/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-gcc-4.4/bin/checkout.sh
new file mode 100644
index 0000000..9167f6b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-gcc-4.4/bin/checkout.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/docker-interop/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker-interop/Dockerfile
new file mode 100644
index 0000000..ff5f33c
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-interop/Dockerfile
@@ -0,0 +1,57 @@
+# Dockerfile for running interop tests.
+# This includes Rust, golang, and nodejs.
+FROM ubuntu:20.04
+LABEL maintainer="Martin Thomson <martin.thomson@gmail.com>"
+
+RUN dpkg --add-architecture i386
+RUN apt-get update && \
+   DEBIAN_FRONTEND=noninteractive \
+   apt-get install -y --no-install-recommends \
+    build-essential \
+    ca-certificates \
+    clang \
+    cmake \
+    curl \
+    g++-multilib \
+    git \
+    golang \
+    gyp \
+    libxml2-utils \
+    lib32z1-dev \
+    linux-libc-dev:i386 \
+    llvm-dev \
+    locales \
+    mercurial \
+    ninja-build \
+    npm \
+    pkg-config \
+    zlib1g-dev \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y
+
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME $USER
+ENV HOME /home/$USER
+ENV LANG en_US.UTF-8
+ENV LC_ALL $LANG
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+RUN locale-gen $LANG \
+ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
+
+RUN useradd -d $HOME -s $SHELL -m $USER
+WORKDIR $HOME
+
+# Add build and test scripts.
+ADD bin $HOME/bin
+RUN chmod +x $HOME/bin/*
+
+USER $USER
+
+# Install Rust stable as $USER.
+RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker-interop/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker-interop/bin/checkout.sh
new file mode 100644
index 0000000..9167f6b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker-interop/bin/checkout.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/docker/Dockerfile b/nss-3.88/nss/automation/taskcluster/docker/Dockerfile
new file mode 100644
index 0000000..859b5bd
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker/Dockerfile
@@ -0,0 +1,50 @@
+# Lean image for running the bulk of the NSS CI tests on taskcluster.
+FROM ubuntu:18.04
+LABEL maintainer="Martin Thomson <martin.thomson@gmail.com>"
+
+RUN dpkg --add-architecture i386
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+    build-essential \
+    ca-certificates \
+    clang \
+    curl \
+    g++-multilib \
+    git \
+    gyp \
+    libxml2-utils \
+    lib32z1-dev \
+    linux-libc-dev:i386 \
+    llvm-dev \
+    locales \
+    mercurial \
+    ninja-build \
+    pkg-config \
+    sqlite3 \
+    zlib1g-dev \
+ && rm -rf /var/lib/apt/lists/* \
+ && apt-get autoremove -y && apt-get clean -y
+
+ENV SHELL /bin/bash
+ENV USER worker
+ENV LOGNAME $USER
+ENV HOME /home/$USER
+ENV LANG en_US.UTF-8
+ENV LC_ALL $LANG
+ENV HOST localhost
+ENV DOMSUF localdomain
+
+RUN locale-gen $LANG \
+ && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales
+
+RUN useradd -d $HOME -s $SHELL -m $USER
+WORKDIR $HOME
+
+# Add build and test scripts.
+ADD bin $HOME/bin
+RUN chmod +x $HOME/bin/*
+
+USER $USER
+
+# Set a default command for debugging.
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/docker/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/docker/bin/checkout.sh
new file mode 100644
index 0000000..9167f6b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/docker/bin/checkout.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    # Drop privileges by re-running this script.
+    exec su worker $0
+fi
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/graph/npm-shrinkwrap.json b/nss-3.88/nss/automation/taskcluster/graph/npm-shrinkwrap.json
new file mode 100644
index 0000000..7071843
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/graph/npm-shrinkwrap.json
@@ -0,0 +1,2963 @@
+{
+  "name": "decision-task",
+  "version": "0.0.1",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "ansi-regex": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+      "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc="
+    },
+    "ansi-styles": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+      "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+    },
+    "anymatch": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz",
+      "integrity": "sha1-o+Uvo5FoyCX/V7AkgSbOWo/5VQc=",
+      "optional": true,
+      "requires": {
+        "arrify": "1.0.1",
+        "micromatch": "2.3.11"
+      }
+    },
+    "argparse": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+      "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+      "requires": {
+        "sprintf-js": "1.0.3"
+      }
+    },
+    "arr-diff": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+      "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+      "optional": true,
+      "requires": {
+        "arr-flatten": "1.0.1"
+      }
+    },
+    "arr-flatten": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz",
+      "integrity": "sha1-5f/lTUXhnzLyFukeuZyM6JK7YEs=",
+      "optional": true
+    },
+    "array-find-index": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
+    },
+    "array-uniq": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
+    },
+    "array-unique": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+      "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+      "optional": true
+    },
+    "arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+      "optional": true
+    },
+    "asn1": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+      "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
+    },
+    "assert-plus": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+      "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
+    },
+    "async": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.1.1.tgz",
+      "integrity": "sha1-4RttEAQ/IlTvthohFj2EDM3bjSg=",
+      "requires": {
+        "lodash": "4.16.4"
+      }
+    },
+    "async-each": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+      "optional": true
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+    },
+    "aws-sign2": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+      "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8="
+    },
+    "aws4": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.5.0.tgz",
+      "integrity": "sha1-Cin/t5wxyecS7rCH6OemS0pW11U="
+    },
+    "b64": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/b64/-/b64-4.1.2.tgz",
+      "integrity": "sha512-+GUspBxlH3CJaxMUGUE1EBoWM6RKgWiYwUDal0qdf8m3ArnXNN1KzKVo5HOnE/FSq4HHyWf3TlHLsZI8PKQgrQ==",
+      "requires": {
+        "hoek": "6.1.3"
+      },
+      "dependencies": {
+        "hoek": {
+          "version": "6.1.3",
+          "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
+          "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ=="
+        }
+      }
+    },
+    "babel-cli": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.16.0.tgz",
+      "integrity": "sha1-Tg0c9ARC73gzD3/viOs6ChsWvTc=",
+      "requires": {
+        "babel-core": "6.17.0",
+        "babel-polyfill": "6.16.0",
+        "babel-register": "6.16.3",
+        "babel-runtime": "6.11.6",
+        "bin-version-check": "2.1.0",
+        "chalk": "1.1.1",
+        "chokidar": "1.6.0",
+        "commander": "2.9.0",
+        "convert-source-map": "1.3.0",
+        "fs-readdir-recursive": "0.1.2",
+        "glob": "5.0.15",
+        "lodash": "4.16.4",
+        "log-symbols": "1.0.2",
+        "output-file-sync": "1.1.2",
+        "path-exists": "1.0.0",
+        "path-is-absolute": "1.0.1",
+        "request": "2.75.0",
+        "slash": "1.0.0",
+        "source-map": "0.5.6",
+        "v8flags": "2.0.11"
+      }
+    },
+    "babel-code-frame": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.16.0.tgz",
+      "integrity": "sha1-+Q5g2ghikJ084JhzO105h8l8uN4=",
+      "requires": {
+        "chalk": "1.1.1",
+        "esutils": "2.0.2",
+        "js-tokens": "2.0.0"
+      }
+    },
+    "babel-compile": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/babel-compile/-/babel-compile-2.0.0.tgz",
+      "integrity": "sha1-JwRg2Fzah1iqXGMWWzZaa8RMmXY=",
+      "requires": {
+        "babel-core": "6.17.0",
+        "commander": "2.9.0",
+        "fs-walk": "0.0.1",
+        "lodash": "4.16.4",
+        "mkdirp": "0.5.1",
+        "rimraf": "2.5.4"
+      }
+    },
+    "babel-core": {
+      "version": "6.17.0",
+      "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.17.0.tgz",
+      "integrity": "sha1-bEV2RH30eeJB5YyAfkvH2k239CU=",
+      "requires": {
+        "babel-code-frame": "6.16.0",
+        "babel-generator": "6.17.0",
+        "babel-helpers": "6.16.0",
+        "babel-messages": "6.8.0",
+        "babel-register": "6.16.3",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0",
+        "babel-traverse": "6.16.0",
+        "babel-types": "6.16.0",
+        "babylon": "6.11.6",
+        "convert-source-map": "1.3.0",
+        "debug": "2.2.0",
+        "json5": "0.4.0",
+        "lodash": "4.16.4",
+        "minimatch": "3.0.3",
+        "path-exists": "1.0.0",
+        "path-is-absolute": "1.0.1",
+        "private": "0.1.6",
+        "shebang-regex": "1.0.0",
+        "slash": "1.0.0",
+        "source-map": "0.5.6"
+      }
+    },
+    "babel-generator": {
+      "version": "6.17.0",
+      "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.17.0.tgz",
+      "integrity": "sha1-uJTjgIvu94APJVBjW/4CS2ImzzM=",
+      "requires": {
+        "babel-messages": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0",
+        "detect-indent": "3.0.1",
+        "jsesc": "1.3.0",
+        "lodash": "4.16.4",
+        "source-map": "0.5.6"
+      }
+    },
+    "babel-helper-call-delegate": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.8.0.tgz",
+      "integrity": "sha1-nSg+dIZ3m2sEgYZKEbNx6lwB+mQ=",
+      "requires": {
+        "babel-helper-hoist-variables": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-traverse": "6.16.0",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-helper-define-map": {
+      "version": "6.9.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.9.0.tgz",
+      "integrity": "sha1-Zin5sqfljhjoN5pX0eb7spaZAvs=",
+      "requires": {
+        "babel-helper-function-name": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0",
+        "lodash": "4.16.4"
+      }
+    },
+    "babel-helper-function-name": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.8.0.tgz",
+      "integrity": "sha1-oDNroUUmoHXN9QL8UtP+hLEvejQ=",
+      "requires": {
+        "babel-helper-get-function-arity": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0",
+        "babel-traverse": "6.16.0",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-helper-get-function-arity": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.8.0.tgz",
+      "integrity": "sha1-iCdsJL0lHN9vYbb4n3RfSGztkq8=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-helper-hoist-variables": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.8.0.tgz",
+      "integrity": "sha1-iwdm3AJuqepCO8KzTmZaTac3Oq8=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-helper-optimise-call-expression": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.8.0.tgz",
+      "integrity": "sha1-QXVijpyJ/DYXSQTycHDynThWfwY=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-helper-regex": {
+      "version": "6.9.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.9.0.tgz",
+      "integrity": "sha1-x0Jl/eGA/5oWc1/uBeY8rbngsFc=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0",
+        "lodash": "4.16.4"
+      }
+    },
+    "babel-helper-remap-async-to-generator": {
+      "version": "6.16.2",
+      "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.16.2.tgz",
+      "integrity": "sha1-JDFb3oMmxgAi3AU8zoTP441yS4I=",
+      "requires": {
+        "babel-helper-function-name": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0",
+        "babel-traverse": "6.16.0",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-helper-replace-supers": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.16.0.tgz",
+      "integrity": "sha1-Icl2I8x+QwhVdT8lJ0ASJiajnms=",
+      "requires": {
+        "babel-helper-optimise-call-expression": "6.8.0",
+        "babel-messages": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0",
+        "babel-traverse": "6.16.0",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-helpers": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.16.0.tgz",
+      "integrity": "sha1-EJXsENmSeUYFU+Z+s+7plz04Z+M=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0"
+      }
+    },
+    "babel-messages": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz",
+      "integrity": "sha1-v1BHNsqWfm1l7wrbWipflHyODrk=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-check-es2015-constants": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz",
+      "integrity": "sha1-2/Akwy7Te/2o3uHnbaAjhqjSb+c=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-syntax-async-functions": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+      "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU="
+    },
+    "babel-plugin-transform-async-to-generator": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.16.0.tgz",
+      "integrity": "sha1-Gew2yxSGtZ+fRorfpCzhOQjKKZk=",
+      "requires": {
+        "babel-helper-remap-async-to-generator": "6.16.2",
+        "babel-plugin-syntax-async-functions": "6.13.0",
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-arrow-functions": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.8.0.tgz",
+      "integrity": "sha1-W2Ovwxgb3JqMTUgbWk8/fX/vPZ0=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-block-scoped-functions": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.8.0.tgz",
+      "integrity": "sha1-7ZXWKcS1pxriloK5mPcNmDPrNm0=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-block-scoping": {
+      "version": "6.15.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.15.0.tgz",
+      "integrity": "sha1-W0Q8oUK+jR22qMKuQvUZWLZrcPY=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0",
+        "babel-traverse": "6.16.0",
+        "babel-types": "6.16.0",
+        "lodash": "4.16.4"
+      }
+    },
+    "babel-plugin-transform-es2015-classes": {
+      "version": "6.14.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.14.0.tgz",
+      "integrity": "sha1-h9UUnukftHWSJAn5r1srpdHjkoc=",
+      "requires": {
+        "babel-helper-define-map": "6.9.0",
+        "babel-helper-function-name": "6.8.0",
+        "babel-helper-optimise-call-expression": "6.8.0",
+        "babel-helper-replace-supers": "6.16.0",
+        "babel-messages": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0",
+        "babel-traverse": "6.16.0",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-computed-properties": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.8.0.tgz",
+      "integrity": "sha1-9RAQ/WGzvXtrYKX9/TB7t6UnmHA=",
+      "requires": {
+        "babel-helper-define-map": "6.9.0",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-destructuring": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.16.0.tgz",
+      "integrity": "sha1-BQ/ghm9dU7NgYu4QzfW/5k+Slic=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-duplicate-keys": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.8.0.tgz",
+      "integrity": "sha1-/Y9/cXH8EIzBxwwxZLnxWoHCX30=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-for-of": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.8.0.tgz",
+      "integrity": "sha1-gu2hObpCcN2hNcPsGx8oE/pi8jw=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-function-name": {
+      "version": "6.9.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.9.0.tgz",
+      "integrity": "sha1-jBNbF9vQZOW7pW7FEbqu4vyoJxk=",
+      "requires": {
+        "babel-helper-function-name": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-literals": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.8.0.tgz",
+      "integrity": "sha1-UKouXHlY/CqyXXTsEX4MyY8EZGg=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-amd": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.8.0.tgz",
+      "integrity": "sha1-JdlUqgvwQDH8RtKo5iMLsau95KM=",
+      "requires": {
+        "babel-plugin-transform-es2015-modules-commonjs": "6.16.0",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-commonjs": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.16.0.tgz",
+      "integrity": "sha1-CjS0R7yIrRpwmIttGZzKbQuWyJI=",
+      "requires": {
+        "babel-plugin-transform-strict-mode": "6.11.3",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-systemjs": {
+      "version": "6.14.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.14.0.tgz",
+      "integrity": "sha1-xRm1xz4yOI5nnJse30Gy/CPcMwM=",
+      "requires": {
+        "babel-helper-hoist-variables": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-modules-umd": {
+      "version": "6.12.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.12.0.tgz",
+      "integrity": "sha1-XXNVnrSSZnde0oHEC+iKQhvTcaM=",
+      "requires": {
+        "babel-plugin-transform-es2015-modules-amd": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-object-super": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.8.0.tgz",
+      "integrity": "sha1-G4WHQKWkQAiHwj3P9vTVbupKJMU=",
+      "requires": {
+        "babel-helper-replace-supers": "6.16.0",
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-parameters": {
+      "version": "6.17.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.17.0.tgz",
+      "integrity": "sha1-4G0wzviX9GrbRzRwe74Sig1CfVg=",
+      "requires": {
+        "babel-helper-call-delegate": "6.8.0",
+        "babel-helper-get-function-arity": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-template": "6.16.0",
+        "babel-traverse": "6.16.0",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-shorthand-properties": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.8.0.tgz",
+      "integrity": "sha1-8KTF/UcWMKzzM8LZnD1ne/CVIUk=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-spread": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.8.0.tgz",
+      "integrity": "sha1-Ahf3N+O4IfpaZp8YfG7VkgXwXpw=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-sticky-regex": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.8.0.tgz",
+      "integrity": "sha1-5z0wCkQKNdXGT1wqNE3CNuPfR74=",
+      "requires": {
+        "babel-helper-regex": "6.9.0",
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-plugin-transform-es2015-template-literals": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.8.0.tgz",
+      "integrity": "sha1-huuHbQosY12k7ASLT33p38iX5ms=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-typeof-symbol": {
+      "version": "6.8.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.8.0.tgz",
+      "integrity": "sha1-hMKesSGTckgJVaAg/vemXETzBTM=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-es2015-unicode-regex": {
+      "version": "6.11.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.11.0.tgz",
+      "integrity": "sha1-YpjOq6rYjVCj9POS2N6ZcmD27yw=",
+      "requires": {
+        "babel-helper-regex": "6.9.0",
+        "babel-runtime": "6.11.6",
+        "regexpu-core": "2.0.0"
+      }
+    },
+    "babel-plugin-transform-regenerator": {
+      "version": "6.16.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.16.1.tgz",
+      "integrity": "sha1-p13msEihQVSq4UsBInVsW+05L1k=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0",
+        "private": "0.1.6"
+      }
+    },
+    "babel-plugin-transform-runtime": {
+      "version": "6.15.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.15.0.tgz",
+      "integrity": "sha1-PXW02Umtga8VdXAnOEb7Wa6w1Xw=",
+      "requires": {
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-plugin-transform-strict-mode": {
+      "version": "6.11.3",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.11.3.tgz",
+      "integrity": "sha1-GDdBMlEmvH7Jz0wPwlfT58pa/UA=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0"
+      }
+    },
+    "babel-polyfill": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.16.0.tgz",
+      "integrity": "sha1-LUUCHfh+JqN0ttTRqcZZZNF/JCI=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "core-js": "2.4.1",
+        "regenerator-runtime": "0.9.5"
+      }
+    },
+    "babel-preset-es2015": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.16.0.tgz",
+      "integrity": "sha1-Wazs0e++uvSPiUBIQPL+eMTSrVw=",
+      "requires": {
+        "babel-plugin-check-es2015-constants": "6.8.0",
+        "babel-plugin-transform-es2015-arrow-functions": "6.8.0",
+        "babel-plugin-transform-es2015-block-scoped-functions": "6.8.0",
+        "babel-plugin-transform-es2015-block-scoping": "6.15.0",
+        "babel-plugin-transform-es2015-classes": "6.14.0",
+        "babel-plugin-transform-es2015-computed-properties": "6.8.0",
+        "babel-plugin-transform-es2015-destructuring": "6.16.0",
+        "babel-plugin-transform-es2015-duplicate-keys": "6.8.0",
+        "babel-plugin-transform-es2015-for-of": "6.8.0",
+        "babel-plugin-transform-es2015-function-name": "6.9.0",
+        "babel-plugin-transform-es2015-literals": "6.8.0",
+        "babel-plugin-transform-es2015-modules-amd": "6.8.0",
+        "babel-plugin-transform-es2015-modules-commonjs": "6.16.0",
+        "babel-plugin-transform-es2015-modules-systemjs": "6.14.0",
+        "babel-plugin-transform-es2015-modules-umd": "6.12.0",
+        "babel-plugin-transform-es2015-object-super": "6.8.0",
+        "babel-plugin-transform-es2015-parameters": "6.17.0",
+        "babel-plugin-transform-es2015-shorthand-properties": "6.8.0",
+        "babel-plugin-transform-es2015-spread": "6.8.0",
+        "babel-plugin-transform-es2015-sticky-regex": "6.8.0",
+        "babel-plugin-transform-es2015-template-literals": "6.8.0",
+        "babel-plugin-transform-es2015-typeof-symbol": "6.8.0",
+        "babel-plugin-transform-es2015-unicode-regex": "6.11.0",
+        "babel-plugin-transform-regenerator": "6.16.1"
+      }
+    },
+    "babel-preset-taskcluster": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/babel-preset-taskcluster/-/babel-preset-taskcluster-3.0.0.tgz",
+      "integrity": "sha1-QEfdaJJzFmGkjgRVHMBazTp3TFc=",
+      "requires": {
+        "babel-plugin-syntax-async-functions": "6.13.0",
+        "babel-plugin-transform-async-to-generator": "6.16.0",
+        "babel-plugin-transform-runtime": "6.15.0",
+        "babel-plugin-transform-strict-mode": "6.11.3",
+        "babel-preset-es2015": "6.16.0",
+        "babel-runtime": "6.11.6"
+      }
+    },
+    "babel-register": {
+      "version": "6.16.3",
+      "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.16.3.tgz",
+      "integrity": "sha1-ewwMp7/euRiLpMJ+X8t1maSXxiQ=",
+      "requires": {
+        "babel-core": "6.17.0",
+        "babel-runtime": "6.11.6",
+        "core-js": "2.4.1",
+        "home-or-tmp": "1.0.0",
+        "lodash": "4.16.4",
+        "mkdirp": "0.5.1",
+        "path-exists": "1.0.0",
+        "source-map-support": "0.4.3"
+      }
+    },
+    "babel-runtime": {
+      "version": "6.11.6",
+      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.11.6.tgz",
+      "integrity": "sha1-bbcH/vLUnEm/o8tk79tDa1GLgiI=",
+      "requires": {
+        "core-js": "2.4.1",
+        "regenerator-runtime": "0.9.5"
+      }
+    },
+    "babel-template": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.16.0.tgz",
+      "integrity": "sha1-4UndGp8Do1+BfdvE0EgZiOfryMo=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "babel-traverse": "6.16.0",
+        "babel-types": "6.16.0",
+        "babylon": "6.11.6",
+        "lodash": "4.16.4"
+      }
+    },
+    "babel-traverse": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.16.0.tgz",
+      "integrity": "sha1-+6ha4f1NEH3pzgAxScxX9TvvDE8=",
+      "requires": {
+        "babel-code-frame": "6.16.0",
+        "babel-messages": "6.8.0",
+        "babel-runtime": "6.11.6",
+        "babel-types": "6.16.0",
+        "babylon": "6.11.6",
+        "debug": "2.2.0",
+        "globals": "8.18.0",
+        "invariant": "2.2.1",
+        "lodash": "4.16.4"
+      }
+    },
+    "babel-types": {
+      "version": "6.16.0",
+      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.16.0.tgz",
+      "integrity": "sha1-ccyh2+Uzd2YiXFwZMHHo68vP/P4=",
+      "requires": {
+        "babel-runtime": "6.11.6",
+        "esutils": "2.0.2",
+        "lodash": "4.16.4",
+        "to-fast-properties": "1.0.2"
+      }
+    },
+    "babylon": {
+      "version": "6.11.6",
+      "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.11.6.tgz",
+      "integrity": "sha1-VtxS5iSIKEHH/glSV/vLSlu2GuE="
+    },
+    "balanced-match": {
+      "version": "0.4.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+      "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+    },
+    "bcrypt-pbkdf": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz",
+      "integrity": "sha1-PKdrhSQccXC/fZcD57mqdGMAQNQ=",
+      "optional": true,
+      "requires": {
+        "tweetnacl": "0.14.3"
+      }
+    },
+    "bin-version": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz",
+      "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=",
+      "requires": {
+        "find-versions": "1.2.1"
+      }
+    },
+    "bin-version-check": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz",
+      "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=",
+      "requires": {
+        "bin-version": "1.0.4",
+        "minimist": "1.2.0",
+        "semver": "4.3.6",
+        "semver-truncate": "1.1.2"
+      }
+    },
+    "binary-extensions": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.7.0.tgz",
+      "integrity": "sha1-bBYQ2xY6v7NO3+QvpCM0Oh4BGF0=",
+      "optional": true
+    },
+    "bl": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz",
+      "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=",
+      "requires": {
+        "readable-stream": "2.0.6"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.0.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+          "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "1.0.0",
+            "process-nextick-args": "1.0.7",
+            "string_decoder": "0.10.31",
+            "util-deprecate": "1.0.2"
+          }
+        }
+      }
+    },
+    "boom": {
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+      "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
+      "requires": {
+        "hoek": "2.16.3"
+      }
+    },
+    "bounce": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/bounce/-/bounce-1.2.3.tgz",
+      "integrity": "sha512-3G7B8CyBnip5EahCZJjnvQ1HLyArC6P5e+xcolo13BVI9ogFaDOsNMAE7FIWliHtIkYI8/nTRCvCY9tZa3Mu4g==",
+      "requires": {
+        "boom": "7.3.0",
+        "hoek": "6.1.3"
+      },
+      "dependencies": {
+        "boom": {
+          "version": "7.3.0",
+          "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz",
+          "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==",
+          "requires": {
+            "hoek": "6.1.3"
+          }
+        },
+        "hoek": {
+          "version": "6.1.3",
+          "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
+          "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ=="
+        }
+      }
+    },
+    "brace-expansion": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
+      "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=",
+      "requires": {
+        "balanced-match": "0.4.2",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+      "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+      "optional": true,
+      "requires": {
+        "expand-range": "1.8.2",
+        "preserve": "0.2.0",
+        "repeat-element": "1.1.2"
+      }
+    },
+    "buffer-shims": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
+      "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=",
+      "optional": true
+    },
+    "builtin-modules": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="
+    },
+    "camelcase": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+      "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
+    },
+    "camelcase-keys": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+      "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+      "requires": {
+        "camelcase": "2.1.1",
+        "map-obj": "1.0.1"
+      }
+    },
+    "caseless": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
+      "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c="
+    },
+    "chalk": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz",
+      "integrity": "sha1-UJr7ZwZudJn36zU1x3RFdyri0Bk=",
+      "requires": {
+        "ansi-styles": "2.2.1",
+        "escape-string-regexp": "1.0.5",
+        "has-ansi": "2.0.0",
+        "strip-ansi": "3.0.1",
+        "supports-color": "2.0.0"
+      }
+    },
+    "chokidar": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.0.tgz",
+      "integrity": "sha1-kMMq1IApAddxPeUy3ChOlqY60Fg=",
+      "optional": true,
+      "requires": {
+        "anymatch": "1.3.0",
+        "async-each": "1.0.1",
+        "fsevents": "1.2.7",
+        "glob-parent": "2.0.0",
+        "inherits": "2.0.3",
+        "is-binary-path": "1.0.1",
+        "is-glob": "2.0.1",
+        "path-is-absolute": "1.0.1",
+        "readdirp": "2.1.0"
+      }
+    },
+    "combined-stream": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
+      "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
+      "requires": {
+        "delayed-stream": "1.0.0"
+      }
+    },
+    "commander": {
+      "version": "2.9.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+      "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
+      "requires": {
+        "graceful-readlink": "1.0.1"
+      }
+    },
+    "component-emitter": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+    },
+    "convert-source-map": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.3.0.tgz",
+      "integrity": "sha1-6fPpxuJyjvwmdmlqcOs4L3MQamc="
+    },
+    "cookiejar": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
+      "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
+    },
+    "core-js": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
+      "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4="
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+    },
+    "cryptiles": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+      "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
+      "requires": {
+        "boom": "2.10.1"
+      }
+    },
+    "currently-unhandled": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+      "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+      "requires": {
+        "array-find-index": "1.0.2"
+      }
+    },
+    "dashdash": {
+      "version": "1.14.0",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz",
+      "integrity": "sha1-KeSGxUGL8PNWA0qZPVFoajPoQUE=",
+      "requires": {
+        "assert-plus": "1.0.0"
+      },
+      "dependencies": {
+        "assert-plus": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+          "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+        }
+      }
+    },
+    "debug": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+      "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+      "requires": {
+        "ms": "0.7.1"
+      }
+    },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+    },
+    "detect-indent": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz",
+      "integrity": "sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U=",
+      "requires": {
+        "get-stdin": "4.0.1",
+        "minimist": "1.2.0",
+        "repeating": "1.1.3"
+      }
+    },
+    "ecc-jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+      "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+      "optional": true,
+      "requires": {
+        "jsbn": "0.1.0"
+      }
+    },
+    "error-ex": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz",
+      "integrity": "sha1-5ntD8+gsluo6WE/+4Ln8MyXYAtk=",
+      "requires": {
+        "is-arrayish": "0.2.1"
+      }
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+    },
+    "esprima": {
+      "version": "2.7.3",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+      "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE="
+    },
+    "esutils": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
+    },
+    "expand-brackets": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+      "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+      "optional": true,
+      "requires": {
+        "is-posix-bracket": "0.1.1"
+      }
+    },
+    "expand-range": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+      "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+      "optional": true,
+      "requires": {
+        "fill-range": "2.2.3"
+      }
+    },
+    "extend": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz",
+      "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ="
+    },
+    "extglob": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+      "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+      "optional": true,
+      "requires": {
+        "is-extglob": "1.0.0"
+      }
+    },
+    "extsprintf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz",
+      "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA="
+    },
+    "fast-safe-stringify": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
+      "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
+    },
+    "filename-regex": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz",
+      "integrity": "sha1-mW4+gEebmLmJfxWopYs9CE6SZ3U=",
+      "optional": true
+    },
+    "fill-range": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
+      "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+      "optional": true,
+      "requires": {
+        "is-number": "2.1.0",
+        "isobject": "2.1.0",
+        "randomatic": "1.1.5",
+        "repeat-element": "1.1.2",
+        "repeat-string": "1.5.4"
+      }
+    },
+    "find-up": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+      "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+      "requires": {
+        "path-exists": "2.1.0",
+        "pinkie-promise": "2.0.1"
+      },
+      "dependencies": {
+        "path-exists": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+          "requires": {
+            "pinkie-promise": "2.0.1"
+          }
+        }
+      }
+    },
+    "find-versions": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz",
+      "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=",
+      "requires": {
+        "array-uniq": "1.0.3",
+        "get-stdin": "4.0.1",
+        "meow": "3.7.0",
+        "semver-regex": "1.0.0"
+      }
+    },
+    "flatmap": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/flatmap/-/flatmap-0.0.3.tgz",
+      "integrity": "sha1-Hxik2TgVLUlZZfnJWNkjqy3WabQ="
+    },
+    "for-in": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.6.tgz",
+      "integrity": "sha1-yfluib+tGKVFr17D7TUqHZ5bTcg=",
+      "optional": true
+    },
+    "for-own": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.4.tgz",
+      "integrity": "sha1-AUm0GjkIjHUV9R6+HBOG1F+TUHI=",
+      "optional": true,
+      "requires": {
+        "for-in": "0.1.6"
+      }
+    },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+    },
+    "form-data": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz",
+      "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=",
+      "requires": {
+        "asynckit": "0.4.0",
+        "combined-stream": "1.0.5",
+        "mime-types": "2.1.12"
+      }
+    },
+    "formidable": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
+      "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
+    },
+    "fs-readdir-recursive": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz",
+      "integrity": "sha1-MVtPuMHKW4xH3v7zGdBz2tNWgFk="
+    },
+    "fs-walk": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/fs-walk/-/fs-walk-0.0.1.tgz",
+      "integrity": "sha1-9/yRw64e6tB8mYvF0N1B8tvr0zU=",
+      "requires": {
+        "async": "2.1.1"
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+    },
+    "fsevents": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz",
+      "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==",
+      "optional": true,
+      "requires": {
+        "nan": "2.12.1",
+        "node-pre-gyp": "0.10.3"
+      },
+      "dependencies": {
+        "abbrev": {
+          "version": "1.1.1",
+          "bundled": true,
+          "optional": true
+        },
+        "ansi-regex": {
+          "version": "2.1.1",
+          "bundled": true,
+          "optional": true
+        },
+        "aproba": {
+          "version": "1.2.0",
+          "bundled": true,
+          "optional": true
+        },
+        "are-we-there-yet": {
+          "version": "1.1.5",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "delegates": "^1.0.0",
+            "readable-stream": "^2.0.6"
+          }
+        },
+        "balanced-match": {
+          "version": "1.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "brace-expansion": {
+          "version": "1.1.11",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "chownr": {
+          "version": "1.1.1",
+          "bundled": true,
+          "optional": true
+        },
+        "code-point-at": {
+          "version": "1.1.0",
+          "bundled": true,
+          "optional": true
+        },
+        "concat-map": {
+          "version": "0.0.1",
+          "bundled": true,
+          "optional": true
+        },
+        "console-control-strings": {
+          "version": "1.1.0",
+          "bundled": true,
+          "optional": true
+        },
+        "core-util-is": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "debug": {
+          "version": "2.6.9",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "deep-extend": {
+          "version": "0.6.0",
+          "bundled": true,
+          "optional": true
+        },
+        "delegates": {
+          "version": "1.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "detect-libc": {
+          "version": "1.0.3",
+          "bundled": true,
+          "optional": true
+        },
+        "fs-minipass": {
+          "version": "1.2.5",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "minipass": "^2.2.1"
+          }
+        },
+        "fs.realpath": {
+          "version": "1.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "gauge": {
+          "version": "2.7.4",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "aproba": "^1.0.3",
+            "console-control-strings": "^1.0.0",
+            "has-unicode": "^2.0.0",
+            "object-assign": "^4.1.0",
+            "signal-exit": "^3.0.0",
+            "string-width": "^1.0.1",
+            "strip-ansi": "^3.0.1",
+            "wide-align": "^1.1.0"
+          }
+        },
+        "glob": {
+          "version": "7.1.3",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^3.0.4",
+            "once": "^1.3.0",
+            "path-is-absolute": "^1.0.0"
+          }
+        },
+        "has-unicode": {
+          "version": "2.0.1",
+          "bundled": true,
+          "optional": true
+        },
+        "iconv-lite": {
+          "version": "0.4.24",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "safer-buffer": ">= 2.1.2 < 3"
+          }
+        },
+        "ignore-walk": {
+          "version": "3.0.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "minimatch": "^3.0.4"
+          }
+        },
+        "inflight": {
+          "version": "1.0.6",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "once": "^1.3.0",
+            "wrappy": "1"
+          }
+        },
+        "inherits": {
+          "version": "2.0.3",
+          "bundled": true,
+          "optional": true
+        },
+        "ini": {
+          "version": "1.3.5",
+          "bundled": true,
+          "optional": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "number-is-nan": "^1.0.0"
+          }
+        },
+        "isarray": {
+          "version": "1.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "minimatch": {
+          "version": "3.0.4",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
+        "minimist": {
+          "version": "0.0.8",
+          "bundled": true,
+          "optional": true
+        },
+        "minipass": {
+          "version": "2.3.5",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.0"
+          }
+        },
+        "minizlib": {
+          "version": "1.2.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "minipass": "^2.2.1"
+          }
+        },
+        "mkdirp": {
+          "version": "0.5.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "minimist": "0.0.8"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "needle": {
+          "version": "2.2.4",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "debug": "^2.1.2",
+            "iconv-lite": "^0.4.4",
+            "sax": "^1.2.4"
+          }
+        },
+        "node-pre-gyp": {
+          "version": "0.10.3",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "detect-libc": "^1.0.2",
+            "mkdirp": "^0.5.1",
+            "needle": "^2.2.1",
+            "nopt": "^4.0.1",
+            "npm-packlist": "^1.1.6",
+            "npmlog": "^4.0.2",
+            "rc": "^1.2.7",
+            "rimraf": "^2.6.1",
+            "semver": "^5.3.0",
+            "tar": "^4"
+          }
+        },
+        "nopt": {
+          "version": "4.0.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "abbrev": "1",
+            "osenv": "^0.1.4"
+          }
+        },
+        "npm-bundled": {
+          "version": "1.0.5",
+          "bundled": true,
+          "optional": true
+        },
+        "npm-packlist": {
+          "version": "1.2.0",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "ignore-walk": "^3.0.1",
+            "npm-bundled": "^1.0.1"
+          }
+        },
+        "npmlog": {
+          "version": "4.1.2",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "are-we-there-yet": "~1.1.2",
+            "console-control-strings": "~1.1.0",
+            "gauge": "~2.7.3",
+            "set-blocking": "~2.0.0"
+          }
+        },
+        "number-is-nan": {
+          "version": "1.0.1",
+          "bundled": true,
+          "optional": true
+        },
+        "object-assign": {
+          "version": "4.1.1",
+          "bundled": true,
+          "optional": true
+        },
+        "once": {
+          "version": "1.4.0",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "wrappy": "1"
+          }
+        },
+        "os-homedir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "os-tmpdir": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "osenv": {
+          "version": "0.1.5",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "os-homedir": "^1.0.0",
+            "os-tmpdir": "^1.0.0"
+          }
+        },
+        "path-is-absolute": {
+          "version": "1.0.1",
+          "bundled": true,
+          "optional": true
+        },
+        "process-nextick-args": {
+          "version": "2.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "rc": {
+          "version": "1.2.8",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "deep-extend": "^0.6.0",
+            "ini": "~1.3.0",
+            "minimist": "^1.2.0",
+            "strip-json-comments": "~2.0.1"
+          },
+          "dependencies": {
+            "minimist": {
+              "version": "1.2.0",
+              "bundled": true,
+              "optional": true
+            }
+          }
+        },
+        "readable-stream": {
+          "version": "2.3.6",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "rimraf": {
+          "version": "2.6.3",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
+        "safe-buffer": {
+          "version": "5.1.2",
+          "bundled": true,
+          "optional": true
+        },
+        "safer-buffer": {
+          "version": "2.1.2",
+          "bundled": true,
+          "optional": true
+        },
+        "sax": {
+          "version": "1.2.4",
+          "bundled": true,
+          "optional": true
+        },
+        "semver": {
+          "version": "5.6.0",
+          "bundled": true,
+          "optional": true
+        },
+        "set-blocking": {
+          "version": "2.0.0",
+          "bundled": true,
+          "optional": true
+        },
+        "signal-exit": {
+          "version": "3.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "code-point-at": "^1.0.0",
+            "is-fullwidth-code-point": "^1.0.0",
+            "strip-ansi": "^3.0.0"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        },
+        "strip-json-comments": {
+          "version": "2.0.1",
+          "bundled": true,
+          "optional": true
+        },
+        "tar": {
+          "version": "4.4.8",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "chownr": "^1.1.1",
+            "fs-minipass": "^1.2.5",
+            "minipass": "^2.3.4",
+            "minizlib": "^1.1.1",
+            "mkdirp": "^0.5.0",
+            "safe-buffer": "^5.1.2",
+            "yallist": "^3.0.2"
+          }
+        },
+        "util-deprecate": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "wide-align": {
+          "version": "1.1.3",
+          "bundled": true,
+          "optional": true,
+          "requires": {
+            "string-width": "^1.0.2 || 2"
+          }
+        },
+        "wrappy": {
+          "version": "1.0.2",
+          "bundled": true,
+          "optional": true
+        },
+        "yallist": {
+          "version": "3.0.3",
+          "bundled": true,
+          "optional": true
+        }
+      }
+    },
+    "generate-function": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
+      "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ="
+    },
+    "generate-object-property": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
+      "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
+      "requires": {
+        "is-property": "1.0.2"
+      }
+    },
+    "get-stdin": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+      "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
+    },
+    "getpass": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz",
+      "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=",
+      "requires": {
+        "assert-plus": "1.0.0"
+      },
+      "dependencies": {
+        "assert-plus": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+          "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+        }
+      }
+    },
+    "glob": {
+      "version": "5.0.15",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+      "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+      "requires": {
+        "inflight": "1.0.6",
+        "inherits": "2.0.3",
+        "minimatch": "3.0.3",
+        "once": "1.4.0",
+        "path-is-absolute": "1.0.1"
+      }
+    },
+    "glob-base": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+      "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+      "optional": true,
+      "requires": {
+        "glob-parent": "2.0.0",
+        "is-glob": "2.0.1"
+      }
+    },
+    "glob-parent": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+      "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+      "requires": {
+        "is-glob": "2.0.1"
+      }
+    },
+    "globals": {
+      "version": "8.18.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz",
+      "integrity": "sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ="
+    },
+    "graceful-fs": {
+      "version": "4.1.9",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz",
+      "integrity": "sha1-uqy6N9GdEfnRRtNXi8mZWMN4fik="
+    },
+    "graceful-readlink": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+      "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU="
+    },
+    "har-validator": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
+      "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
+      "requires": {
+        "chalk": "1.1.1",
+        "commander": "2.9.0",
+        "is-my-json-valid": "2.15.0",
+        "pinkie-promise": "2.0.1"
+      }
+    },
+    "has-ansi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+      "requires": {
+        "ansi-regex": "2.0.0"
+      }
+    },
+    "hawk": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+      "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
+      "requires": {
+        "boom": "2.10.1",
+        "cryptiles": "2.0.5",
+        "hoek": "2.16.3",
+        "sntp": "1.0.9"
+      }
+    },
+    "hoek": {
+      "version": "2.16.3",
+      "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+      "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
+    },
+    "home-or-tmp": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-1.0.0.tgz",
+      "integrity": "sha1-S58eQIAMPlDGwn94FnavzOcfOYU=",
+      "requires": {
+        "os-tmpdir": "1.0.2",
+        "user-home": "1.1.1"
+      }
+    },
+    "hosted-git-info": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz",
+      "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs="
+    },
+    "http-signature": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+      "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
+      "requires": {
+        "assert-plus": "0.2.0",
+        "jsprim": "1.3.1",
+        "sshpk": "1.10.1"
+      }
+    },
+    "indent-string": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+      "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+      "requires": {
+        "repeating": "2.0.1"
+      },
+      "dependencies": {
+        "repeating": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+          "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+          "requires": {
+            "is-finite": "1.0.2"
+          }
+        }
+      }
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "requires": {
+        "once": "1.4.0",
+        "wrappy": "1.0.2"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+    },
+    "intersect": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/intersect/-/intersect-1.0.1.tgz",
+      "integrity": "sha1-MyZQ4QhU2MCsWMGSvcJ6i/fnoww="
+    },
+    "invariant": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz",
+      "integrity": "sha1-sJcBBUdmjH4zcCjr6Bbr42yKjVQ=",
+      "requires": {
+        "loose-envify": "1.2.0"
+      }
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+    },
+    "is-binary-path": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+      "optional": true,
+      "requires": {
+        "binary-extensions": "1.7.0"
+      }
+    },
+    "is-buffer": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz",
+      "integrity": "sha1-z8hszV3FpS+oBIkRHGkgxFfi2Ys="
+    },
+    "is-builtin-module": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+      "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+      "requires": {
+        "builtin-modules": "1.1.1"
+      }
+    },
+    "is-dotfile": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz",
+      "integrity": "sha1-LBMjg/ORmfjtwmjKAbmwB9IFzE0=",
+      "optional": true
+    },
+    "is-equal-shallow": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+      "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+      "optional": true,
+      "requires": {
+        "is-primitive": "2.0.0"
+      }
+    },
+    "is-extendable": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+      "optional": true
+    },
+    "is-extglob": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+      "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
+    },
+    "is-finite": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+      "requires": {
+        "number-is-nan": "1.0.1"
+      }
+    },
+    "is-glob": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+      "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+      "requires": {
+        "is-extglob": "1.0.0"
+      }
+    },
+    "is-my-json-valid": {
+      "version": "2.15.0",
+      "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz",
+      "integrity": "sha1-k27do8o8IR/ZjzstPgjaQ/eykVs=",
+      "requires": {
+        "generate-function": "2.0.0",
+        "generate-object-property": "1.2.0",
+        "jsonpointer": "4.0.0",
+        "xtend": "4.0.1"
+      }
+    },
+    "is-number": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+      "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+      "requires": {
+        "kind-of": "3.0.4"
+      }
+    },
+    "is-posix-bracket": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+      "optional": true
+    },
+    "is-primitive": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU="
+    },
+    "is-property": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+      "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
+    },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+    },
+    "is-utf8": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
+    },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+    },
+    "isobject": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+      "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+      "optional": true,
+      "requires": {
+        "isarray": "1.0.0"
+      }
+    },
+    "isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+    },
+    "jodid25519": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz",
+      "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=",
+      "optional": true,
+      "requires": {
+        "jsbn": "0.1.0"
+      }
+    },
+    "js-tokens": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz",
+      "integrity": "sha1-eZA/VWPud4zBFi5tzxoAJ8l/nLU="
+    },
+    "js-yaml": {
+      "version": "3.6.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz",
+      "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=",
+      "requires": {
+        "argparse": "1.0.9",
+        "esprima": "2.7.3"
+      }
+    },
+    "jsbn": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz",
+      "integrity": "sha1-ZQmH2g3XT06/WhE3eiqi0nPpff0=",
+      "optional": true
+    },
+    "jsesc": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+      "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s="
+    },
+    "json-schema": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
+    },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+    },
+    "json5": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz",
+      "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0="
+    },
+    "jsonpointer": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz",
+      "integrity": "sha1-ZmHhYdL8RF8Z+YQwIxNDci4fy9U="
+    },
+    "jsprim": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz",
+      "integrity": "sha1-KnJW9wQSop7jZwqspiWZTE3P8lI=",
+      "requires": {
+        "extsprintf": "1.0.2",
+        "json-schema": "0.2.3",
+        "verror": "1.3.6"
+      }
+    },
+    "kind-of": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz",
+      "integrity": "sha1-e47PGKThf4Jp1ztQHJ8jLJaIenQ=",
+      "requires": {
+        "is-buffer": "1.1.4"
+      }
+    },
+    "load-json-file": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+      "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+      "requires": {
+        "graceful-fs": "4.1.9",
+        "parse-json": "2.2.0",
+        "pify": "2.3.0",
+        "pinkie-promise": "2.0.1",
+        "strip-bom": "2.0.0"
+      }
+    },
+    "lodash": {
+      "version": "4.16.4",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.4.tgz",
+      "integrity": "sha1-Ac4wa5utExnypVKGdPiCl663ASc="
+    },
+    "log-symbols": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
+      "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
+      "requires": {
+        "chalk": "1.1.1"
+      }
+    },
+    "loose-envify": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz",
+      "integrity": "sha1-aaZarT3lQs9O4PT+dOjjPHCcyw8=",
+      "requires": {
+        "js-tokens": "1.0.3"
+      },
+      "dependencies": {
+        "js-tokens": {
+          "version": "1.0.3",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz",
+          "integrity": "sha1-FOVutoyPGpLEPVn1AU7CncIPKuE="
+        }
+      }
+    },
+    "loud-rejection": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+      "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+      "requires": {
+        "currently-unhandled": "0.4.1",
+        "signal-exit": "3.0.1"
+      }
+    },
+    "map-obj": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+      "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
+    },
+    "meow": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+      "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+      "requires": {
+        "camelcase-keys": "2.1.0",
+        "decamelize": "1.2.0",
+        "loud-rejection": "1.6.0",
+        "map-obj": "1.0.1",
+        "minimist": "1.2.0",
+        "normalize-package-data": "2.3.5",
+        "object-assign": "4.1.0",
+        "read-pkg-up": "1.0.1",
+        "redent": "1.0.0",
+        "trim-newlines": "1.0.0"
+      }
+    },
+    "merge": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz",
+      "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo="
+    },
+    "methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+    },
+    "micromatch": {
+      "version": "2.3.11",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+      "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+      "optional": true,
+      "requires": {
+        "arr-diff": "2.0.0",
+        "array-unique": "0.2.1",
+        "braces": "1.8.5",
+        "expand-brackets": "0.1.5",
+        "extglob": "0.3.2",
+        "filename-regex": "2.0.0",
+        "is-extglob": "1.0.0",
+        "is-glob": "2.0.1",
+        "kind-of": "3.0.4",
+        "normalize-path": "2.0.1",
+        "object.omit": "2.0.0",
+        "parse-glob": "3.0.4",
+        "regex-cache": "0.4.3"
+      }
+    },
+    "mime": {
+      "version": "2.4.4",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+      "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
+    },
+    "mime-db": {
+      "version": "1.24.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz",
+      "integrity": "sha1-4tE/k58AFsbk6a0lqGUvEmxGfww="
+    },
+    "mime-types": {
+      "version": "2.1.12",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz",
+      "integrity": "sha1-FSuiVndwIN1GY/VMLnvCY4HnFyk=",
+      "requires": {
+        "mime-db": "1.24.0"
+      }
+    },
+    "minimatch": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
+      "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=",
+      "requires": {
+        "brace-expansion": "1.1.6"
+      }
+    },
+    "minimist": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "requires": {
+        "minimist": "0.0.8"
+      },
+      "dependencies": {
+        "minimist": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+        }
+      }
+    },
+    "ms": {
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+      "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg="
+    },
+    "nan": {
+      "version": "2.12.1",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
+      "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==",
+      "optional": true
+    },
+    "node-uuid": {
+      "version": "1.4.7",
+      "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz",
+      "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8="
+    },
+    "normalize-package-data": {
+      "version": "2.3.5",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz",
+      "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=",
+      "requires": {
+        "hosted-git-info": "2.1.5",
+        "is-builtin-module": "1.0.0",
+        "semver": "4.3.6",
+        "validate-npm-package-license": "3.0.1"
+      }
+    },
+    "normalize-path": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz",
+      "integrity": "sha1-R4hqwWYnYNQmG32XnSQXCdPOP3o=",
+      "optional": true
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+    },
+    "oauth-sign": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+      "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
+    },
+    "object-assign": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
+      "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A="
+    },
+    "object.omit": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.0.tgz",
+      "integrity": "sha1-hoWXMz1U5gZilAu0WGBd1q4S/pQ=",
+      "optional": true,
+      "requires": {
+        "for-own": "0.1.4",
+        "is-extendable": "0.1.1"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "requires": {
+        "wrappy": "1.0.2"
+      }
+    },
+    "os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+    },
+    "output-file-sync": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz",
+      "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=",
+      "requires": {
+        "graceful-fs": "4.1.9",
+        "mkdirp": "0.5.1",
+        "object-assign": "4.1.0"
+      }
+    },
+    "parse-glob": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+      "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+      "optional": true,
+      "requires": {
+        "glob-base": "0.3.0",
+        "is-dotfile": "1.0.2",
+        "is-extglob": "1.0.0",
+        "is-glob": "2.0.1"
+      }
+    },
+    "parse-json": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+      "requires": {
+        "error-ex": "1.3.0"
+      }
+    },
+    "path-exists": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz",
+      "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE="
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+    },
+    "path-type": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+      "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+      "requires": {
+        "graceful-fs": "4.1.9",
+        "pify": "2.3.0",
+        "pinkie-promise": "2.0.1"
+      }
+    },
+    "pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+    },
+    "pinkie": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+    },
+    "pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+      "requires": {
+        "pinkie": "2.0.4"
+      }
+    },
+    "preserve": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+      "optional": true
+    },
+    "private": {
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/private/-/private-0.1.6.tgz",
+      "integrity": "sha1-VcapdtD5uvuZJIUTUP5HubX7t8E="
+    },
+    "process-nextick-args": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+      "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+    },
+    "qs": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz",
+      "integrity": "sha1-zgPF/wk1vB2daanxTL0Y5WjWdiU="
+    },
+    "randomatic": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.5.tgz",
+      "integrity": "sha1-Xp718tVzxnvSuBJK6QtRVuRXhAs=",
+      "optional": true,
+      "requires": {
+        "is-number": "2.1.0",
+        "kind-of": "3.0.4"
+      }
+    },
+    "read-pkg": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+      "requires": {
+        "load-json-file": "1.1.0",
+        "normalize-package-data": "2.3.5",
+        "path-type": "1.1.0"
+      }
+    },
+    "read-pkg-up": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+      "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+      "requires": {
+        "find-up": "1.1.2",
+        "read-pkg": "1.1.0"
+      }
+    },
+    "readable-stream": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz",
+      "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=",
+      "optional": true,
+      "requires": {
+        "buffer-shims": "1.0.0",
+        "core-util-is": "1.0.2",
+        "inherits": "2.0.3",
+        "isarray": "1.0.0",
+        "process-nextick-args": "1.0.7",
+        "string_decoder": "0.10.31",
+        "util-deprecate": "1.0.2"
+      }
+    },
+    "readdirp": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
+      "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+      "optional": true,
+      "requires": {
+        "graceful-fs": "4.1.9",
+        "minimatch": "3.0.3",
+        "readable-stream": "2.1.5",
+        "set-immediate-shim": "1.0.1"
+      }
+    },
+    "redent": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+      "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+      "requires": {
+        "indent-string": "2.1.0",
+        "strip-indent": "1.0.1"
+      }
+    },
+    "regenerate": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.1.tgz",
+      "integrity": "sha1-AwAgOl0v3PiRFtzoQnXQEfWQPzM="
+    },
+    "regenerator-runtime": {
+      "version": "0.9.5",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz",
+      "integrity": "sha1-QD1tQKS9/5wzDdk5Lcuy2ai7ofw="
+    },
+    "regex-cache": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz",
+      "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=",
+      "optional": true,
+      "requires": {
+        "is-equal-shallow": "0.1.3",
+        "is-primitive": "2.0.0"
+      }
+    },
+    "regexpu-core": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+      "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+      "requires": {
+        "regenerate": "1.3.1",
+        "regjsgen": "0.2.0",
+        "regjsparser": "0.1.5"
+      }
+    },
+    "regjsgen": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+      "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc="
+    },
+    "regjsparser": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+      "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+      "requires": {
+        "jsesc": "0.5.0"
+      },
+      "dependencies": {
+        "jsesc": {
+          "version": "0.5.0",
+          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+          "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+        }
+      }
+    },
+    "repeat-element": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+      "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo="
+    },
+    "repeat-string": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.5.4.tgz",
+      "integrity": "sha1-ZOwMkeD0tHX5DVtkNlHj5uW2wtU=",
+      "optional": true
+    },
+    "repeating": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz",
+      "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=",
+      "requires": {
+        "is-finite": "1.0.2"
+      }
+    },
+    "request": {
+      "version": "2.75.0",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz",
+      "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=",
+      "requires": {
+        "aws-sign2": "0.6.0",
+        "aws4": "1.5.0",
+        "bl": "1.1.2",
+        "caseless": "0.11.0",
+        "combined-stream": "1.0.5",
+        "extend": "3.0.0",
+        "forever-agent": "0.6.1",
+        "form-data": "2.0.0",
+        "har-validator": "2.0.6",
+        "hawk": "3.1.3",
+        "http-signature": "1.1.1",
+        "is-typedarray": "1.0.0",
+        "isstream": "0.1.2",
+        "json-stringify-safe": "5.0.1",
+        "mime-types": "2.1.12",
+        "node-uuid": "1.4.7",
+        "oauth-sign": "0.8.2",
+        "qs": "6.2.1",
+        "stringstream": "0.0.5",
+        "tough-cookie": "2.3.1",
+        "tunnel-agent": "0.4.3"
+      }
+    },
+    "rimraf": {
+      "version": "2.5.4",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz",
+      "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=",
+      "requires": {
+        "glob": "7.1.1"
+      },
+      "dependencies": {
+        "glob": {
+          "version": "7.1.1",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+          "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
+          "requires": {
+            "fs.realpath": "1.0.0",
+            "inflight": "1.0.6",
+            "inherits": "2.0.3",
+            "minimatch": "3.0.3",
+            "once": "1.4.0",
+            "path-is-absolute": "1.0.1"
+          }
+        }
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+      "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
+    },
+    "semver": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
+      "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto="
+    },
+    "semver-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz",
+      "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk="
+    },
+    "semver-truncate": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz",
+      "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=",
+      "requires": {
+        "semver": "5.3.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+          "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
+        }
+      }
+    },
+    "set-immediate-shim": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
+      "optional": true
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+    },
+    "signal-exit": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.1.tgz",
+      "integrity": "sha1-WkyISZK2OnrNm623iUw+6c/MrYE="
+    },
+    "slash": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="
+    },
+    "slugid": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/slugid/-/slugid-1.1.0.tgz",
+      "integrity": "sha1-4J8AiZwJ9acFjtw23UnwRv1QqCo=",
+      "requires": {
+        "uuid": "2.0.3"
+      }
+    },
+    "sntp": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+      "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
+      "requires": {
+        "hoek": "2.16.3"
+      }
+    },
+    "source-map": {
+      "version": "0.5.6",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+      "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
+    },
+    "source-map-support": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.3.tgz",
+      "integrity": "sha1-aTyDg9Q4mkVpSGmHwhl0TfxgFoU=",
+      "requires": {
+        "source-map": "0.5.6"
+      }
+    },
+    "spdx-correct": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
+      "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
+      "requires": {
+        "spdx-license-ids": "1.2.2"
+      }
+    },
+    "spdx-expression-parse": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
+      "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw="
+    },
+    "spdx-license-ids": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
+      "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc="
+    },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+    },
+    "sshpk": {
+      "version": "1.10.1",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.1.tgz",
+      "integrity": "sha1-MOGl0ykkSXShr2FREznVla9mOLA=",
+      "requires": {
+        "asn1": "0.2.3",
+        "assert-plus": "1.0.0",
+        "bcrypt-pbkdf": "1.0.0",
+        "dashdash": "1.14.0",
+        "ecc-jsbn": "0.1.1",
+        "getpass": "0.1.6",
+        "jodid25519": "1.0.2",
+        "jsbn": "0.1.0",
+        "tweetnacl": "0.14.3"
+      },
+      "dependencies": {
+        "assert-plus": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+          "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+        }
+      }
+    },
+    "string_decoder": {
+      "version": "0.10.31",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+      "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+    },
+    "stringstream": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+      "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
+    },
+    "strip-ansi": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+      "requires": {
+        "ansi-regex": "2.0.0"
+      }
+    },
+    "strip-bom": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+      "requires": {
+        "is-utf8": "0.2.1"
+      }
+    },
+    "strip-indent": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+      "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+      "requires": {
+        "get-stdin": "4.0.1"
+      }
+    },
+    "superagent": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.1.0.tgz",
+      "integrity": "sha512-7V6JVx5N+eTL1MMqRBX0v0bG04UjrjAvvZJTF/VDH/SH2GjSLqlrcYepFlpTrXpm37aSY6h3GGVWGxXl/98TKA==",
+      "requires": {
+        "component-emitter": "1.3.0",
+        "cookiejar": "2.1.2",
+        "debug": "4.1.1",
+        "fast-safe-stringify": "2.0.7",
+        "form-data": "2.5.1",
+        "formidable": "1.2.1",
+        "methods": "1.1.2",
+        "mime": "2.4.4",
+        "qs": "6.9.0",
+        "readable-stream": "3.4.0",
+        "semver": "6.3.0"
+      },
+      "dependencies": {
+        "combined-stream": {
+          "version": "1.0.8",
+          "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+          "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+          "requires": {
+            "delayed-stream": "1.0.0"
+          }
+        },
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "form-data": {
+          "version": "2.5.1",
+          "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
+          "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
+          "requires": {
+            "asynckit": "0.4.0",
+            "combined-stream": "1.0.8",
+            "mime-types": "2.1.12"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+        },
+        "qs": {
+          "version": "6.9.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.0.tgz",
+          "integrity": "sha512-27RP4UotQORTpmNQDX8BHPukOnBP3p1uUJY5UnDhaJB+rMt9iMsok724XL+UHU23bEFOHRMQ2ZhI99qOWUMGFA=="
+        },
+        "readable-stream": {
+          "version": "3.4.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
+          "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
+          "requires": {
+            "inherits": "2.0.3",
+            "string_decoder": "1.3.0",
+            "util-deprecate": "1.0.2"
+          }
+        },
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+        },
+        "string_decoder": {
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+          "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+          "requires": {
+            "safe-buffer": "5.2.0"
+          }
+        }
+      }
+    },
+    "supports-color": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+      "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+    },
+    "taskcluster-client": {
+      "version": "22.0.0",
+      "resolved": "https://registry.npmjs.org/taskcluster-client/-/taskcluster-client-22.0.0.tgz",
+      "integrity": "sha512-L9Z84WXWVLkCYlcxNl6TAXBqoERyB0iavNgsymQqu9TGMLh3Acl7J55PzthZr/o1F3sVfHwRgDnxM1CidaYbEQ==",
+      "requires": {
+        "debug": "4.1.1",
+        "hawk": "7.0.10",
+        "lodash": "4.17.15",
+        "slugid": "2.0.0",
+        "superagent": "5.1.0",
+        "taskcluster-lib-urls": "12.0.0"
+      },
+      "dependencies": {
+        "boom": {
+          "version": "7.3.0",
+          "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz",
+          "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==",
+          "requires": {
+            "hoek": "6.1.3"
+          }
+        },
+        "cryptiles": {
+          "version": "4.1.3",
+          "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-4.1.3.tgz",
+          "integrity": "sha512-gT9nyTMSUC1JnziQpPbxKGBbUg8VL7Zn2NB4E1cJYvuXdElHrwxrV9bmltZGDzet45zSDGyYceueke1TjynGzw==",
+          "requires": {
+            "boom": "7.3.0"
+          }
+        },
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "hawk": {
+          "version": "7.0.10",
+          "resolved": "https://registry.npmjs.org/hawk/-/hawk-7.0.10.tgz",
+          "integrity": "sha512-3RWF4SXN9CdZ1VDAe6Pn3Rd0tC3Lw+GV+esX5oKCrXoScZK3Ri6dl5Wt986M/hlzU+GuapTGiB0rBhGeRIBQsw==",
+          "requires": {
+            "b64": "4.1.2",
+            "boom": "7.3.0",
+            "cryptiles": "4.1.3",
+            "hoek": "6.1.3",
+            "sntp": "3.0.2"
+          }
+        },
+        "hoek": {
+          "version": "6.1.3",
+          "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
+          "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ=="
+        },
+        "lodash": {
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+        },
+        "slugid": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/slugid/-/slugid-2.0.0.tgz",
+          "integrity": "sha512-zTCivUfTk2GC6MU4Fjcz0iXwAjhe0NweMJqpfWcGrBbrm2dWtVAUupAonfsc7ysw4M0kZ934Nle5ljwM2dR+/g==",
+          "requires": {
+            "uuid": "3.3.3",
+            "uuid-parse": "1.1.0"
+          }
+        },
+        "sntp": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/sntp/-/sntp-3.0.2.tgz",
+          "integrity": "sha512-MCAPpBPFjNp1fwDVCLSRuWuH9gONtb2R+lS1esC6Mp8lP6jy60FVUtP/Qr0jBvcWAVbhzx06y1b6ptXiy32dug==",
+          "requires": {
+            "boom": "7.3.0",
+            "bounce": "1.2.3",
+            "hoek": "6.1.3",
+            "teamwork": "3.2.0"
+          }
+        },
+        "uuid": {
+          "version": "3.3.3",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
+          "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
+        }
+      }
+    },
+    "taskcluster-lib-urls": {
+      "version": "12.0.0",
+      "resolved": "https://registry.npmjs.org/taskcluster-lib-urls/-/taskcluster-lib-urls-12.0.0.tgz",
+      "integrity": "sha512-OrEFE0m3p/+mGsmIwjttLhSKg3io6MpJLhYtPNjVSZA9Ix8Y5tprN3vM6a3MjWt5asPF6AKZsfT43cgpGwJB0g=="
+    },
+    "teamwork": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/teamwork/-/teamwork-3.2.0.tgz",
+      "integrity": "sha512-xAmJ8PIVjRZMXAHgUuOP8ITsv0SedyWAit2UWiNImXgg/F+BxrsG46ZegElNBM0Dwp+iMfbigg/Ll/M2oDRYww=="
+    },
+    "to-fast-properties": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz",
+      "integrity": "sha1-8/XAw7pymafvmUJ+RGMyV63kMyA="
+    },
+    "tough-cookie": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.1.tgz",
+      "integrity": "sha1-mcd9+7fYBCSeiimdTLD9gf7wg/0="
+    },
+    "trim-newlines": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+      "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM="
+    },
+    "tunnel-agent": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
+      "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us="
+    },
+    "tweetnacl": {
+      "version": "0.14.3",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz",
+      "integrity": "sha1-PaOC9nDyXe1417PReSEZvKC3Ey0=",
+      "optional": true
+    },
+    "user-home": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz",
+      "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA="
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+    },
+    "uuid": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
+      "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho="
+    },
+    "uuid-parse": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.1.0.tgz",
+      "integrity": "sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A=="
+    },
+    "v8flags": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.11.tgz",
+      "integrity": "sha1-vKjzDw1tYGEswsAGQeaWLUKuaIE=",
+      "requires": {
+        "user-home": "1.1.1"
+      }
+    },
+    "validate-npm-package-license": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
+      "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
+      "requires": {
+        "spdx-correct": "1.0.2",
+        "spdx-expression-parse": "1.0.4"
+      }
+    },
+    "verror": {
+      "version": "1.3.6",
+      "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz",
+      "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=",
+      "requires": {
+        "extsprintf": "1.0.2"
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+    },
+    "xtend": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
+    }
+  }
+}
diff --git a/nss-3.88/nss/automation/taskcluster/graph/package.json b/nss-3.88/nss/automation/taskcluster/graph/package.json
new file mode 100644
index 0000000..7bf52b9
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/graph/package.json
@@ -0,0 +1,24 @@
+{
+  "name": "decision-task",
+  "version": "0.0.1",
+  "private": true,
+  "author": "Tim Taubert <ttaubert@mozilla.com>",
+  "description": "Decision Task for NSS",
+  "scripts": {
+    "compile": "babel-compile -p taskcluster src:lib",
+    "install": "npm run compile"
+  },
+  "dependencies": {
+    "babel-cli": "^6.14.0",
+    "babel-compile": "^2.0.0",
+    "babel-preset-taskcluster": "^3.0.0",
+    "babel-runtime": "^6.11.6",
+    "flatmap": "0.0.3",
+    "intersect": "^1.0.1",
+    "js-yaml": "^3.6.1",
+    "merge": "^1.2.0",
+    "minimist": "^1.2.0",
+    "slugid": "^1.1.0",
+    "taskcluster-client": "^22.0.0"
+  }
+}
diff --git a/nss-3.88/nss/automation/taskcluster/graph/src/context_hash.js b/nss-3.88/nss/automation/taskcluster/graph/src/context_hash.js
new file mode 100644
index 0000000..0699a05
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/graph/src/context_hash.js
@@ -0,0 +1,53 @@
+/* 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/. */
+
+import fs from "fs";
+import path from "path";
+import crypto from "crypto";
+import flatmap from "flatmap";
+
+// Compute the SHA-256 digest.
+function sha256(data) {
+  let hash = crypto.createHash("sha256");
+  hash.update(data);
+  return hash.digest("hex");
+}
+
+// Recursively collect a list of all files of a given directory.
+function collectFilesInDirectory(dir) {
+  return flatmap(fs.readdirSync(dir), entry => {
+    let entry_path = path.join(dir, entry);
+
+    if (fs.lstatSync(entry_path).isDirectory()) {
+      return collectFilesInDirectory(entry_path);
+    }
+
+    return [entry_path];
+  });
+}
+
+// A list of hashes for each file in the given path.
+function collectFileHashes(context_path) {
+  let root = path.join(__dirname, "../../../..");
+  let dir = path.join(root, context_path);
+  let files = collectFilesInDirectory(dir).sort();
+
+  return files.map(file => {
+    return sha256(file + "|" + fs.readFileSync(file, "utf-8"));
+  });
+}
+
+// Compute a context hash for the given context path.
+export default function (context_path) {
+  // Regenerate all images when the image_builder changes.
+  let hashes = collectFileHashes("automation/taskcluster/image_builder");
+
+  // Regenerate images when the image itself changes.
+  hashes = hashes.concat(collectFileHashes(context_path));
+
+  // Generate a new prefix every month to ensure the image stays buildable.
+  let now = new Date();
+  let prefix = `${now.getUTCFullYear()}-${now.getUTCMonth() + 1}:`;
+  return sha256(prefix + hashes.join(","));
+}
diff --git a/nss-3.88/nss/automation/taskcluster/graph/src/extend.js b/nss-3.88/nss/automation/taskcluster/graph/src/extend.js
new file mode 100644
index 0000000..7ef79fb
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/graph/src/extend.js
@@ -0,0 +1,1247 @@
+/* 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/. */
+
+import merge from "./merge";
+import * as queue from "./queue";
+
+const LINUX_IMAGE = {
+  name: "linux",
+  path: "automation/taskcluster/docker"
+};
+
+const LINUX_BUILDS_IMAGE = {
+  name: "linux-builds",
+  path: "automation/taskcluster/docker-builds"
+};
+
+const LINUX_INTEROP_IMAGE = {
+  name: "linux-interop",
+  path: "automation/taskcluster/docker-interop"
+};
+
+const ACVP_IMAGE = {
+  name: "acvp",
+  path: "automation/taskcluster/docker-acvp"
+};
+
+
+const CLANG_FORMAT_IMAGE = {
+  name: "clang-format",
+  path: "automation/taskcluster/docker-clang-format"
+};
+
+const LINUX_GCC44_IMAGE = {
+  name: "linux-gcc-4.4",
+  path: "automation/taskcluster/docker-gcc-4.4"
+};
+
+const FUZZ_IMAGE = {
+  name: "fuzz",
+  path: "automation/taskcluster/docker-fuzz"
+};
+
+// Bug 1488148 - temporary image for fuzzing 32-bit builds.
+const FUZZ_IMAGE_32 = {
+  name: "fuzz32",
+  path: "automation/taskcluster/docker-fuzz32"
+};
+
+const WINDOWS_CHECKOUT_CMD =
+  "bash -c \"hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss || " +
+    "(sleep 2; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss) || " +
+    "(sleep 5; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss)\"";
+const MAC_CHECKOUT_CMD = ["bash", "-c",
+            "hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss || " +
+            "(sleep 2; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss) || " +
+            "(sleep 5; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss)"];
+
+/*****************************************************************************/
+
+queue.filter(task => {
+  if (task.group == "Builds") {
+    // Remove extra builds on {A,UB}San and ARM.
+    if (task.collection == "asan" || task.platform == "aarch64") {
+      return false;
+    }
+
+    // Make modular builds only on Linux make.
+    if (task.symbol == "modular" && task.collection != "make") {
+      return false;
+    }
+  }
+
+  if (task.tests == "bogo" || task.tests == "interop" || task.tests == "tlsfuzzer") {
+    // No windows
+    if (task.platform == "windows2012-64" ||
+        task.platform == "windows2012-32") {
+      return false;
+    }
+
+    // No ARM; TODO: enable
+    if (task.platform == "aarch64") {
+      return false;
+    }
+
+    // No mac
+    if (task.platform == "mac") {
+      return false;
+    }
+  }
+
+  if (task.tests == "fips" &&
+     (task.platform == "mac" || task.platform == "aarch64")) {
+    return false;
+  }
+
+  // Only old make builds have -Ddisable_libpkix=0 and can run chain tests.
+  if (task.tests == "chains" && task.collection != "make") {
+    return false;
+  }
+
+  // Don't run all additional hardware tests on ARM.
+  if (task.group == "Cipher" && task.platform == "aarch64" && task.env &&
+      (task.env.NSS_DISABLE_PCLMUL == "1" || task.env.NSS_DISABLE_SSE4_1 == "1"
+       || task.env.NSS_DISABLE_AVX == "1" || task.env.NSS_DISABLE_AVX2 == "1")) {
+    return false;
+  }
+
+  // Don't run ARM specific hardware tests on non-ARM.
+  // TODO: our server that runs task cluster doesn't support Intel SHA extensions.
+  if (task.group == "Cipher" && task.platform != "aarch64" && task.env &&
+      (task.env.NSS_DISABLE_HW_SHA1 == "1" || task.env.NSS_DISABLE_HW_SHA2 == "1")) {
+    return false;
+  }
+
+  // Don't run DBM builds on aarch64.
+  if (task.group == "DBM" && task.platform == "aarch64") {
+    return false;
+  }
+
+  return true;
+});
+
+queue.map(task => {
+  if (task.collection == "asan") {
+    // CRMF and FIPS tests still leak, unfortunately.
+    if (task.tests == "crmf") {
+      task.env.ASAN_OPTIONS = "detect_leaks=0";
+    }
+  }
+
+  if (task.tests == "ssl") {
+    if (!task.env) {
+      task.env = {};
+    }
+
+    // Stress tests to not include other SSL tests
+    if (task.symbol == "stress") {
+      task.env.NSS_SSL_TESTS = "normal_normal";
+    } else {
+      task.env.NSS_SSL_TESTS = "crl iopr policy normal_normal";
+    }
+
+    // FIPS runs
+    if (task.collection == "fips") {
+      task.env.NSS_SSL_TESTS += " fips_fips fips_normal normal_fips";
+    }
+
+    if (task.platform == "mac") {
+      task.maxRunTime = 7200;
+    }
+  }
+
+  // Windows is slow.
+  if ((task.platform == "windows2012-32" || task.platform == "windows2012-64") &&
+      task.tests == "chains") {
+    task.maxRunTime = 7200;
+  }
+
+  if (task.platform == "mac" && task.tests == "tools") {
+      task.maxRunTime = 7200;
+  }
+  return task;
+});
+
+/*****************************************************************************/
+
+export default async function main() {
+  await scheduleLinux("Linux 32 (opt)", {
+    platform: "linux32",
+    image: LINUX_IMAGE
+  }, "-t ia32 --opt");
+
+  await scheduleLinux("Linux 32 (debug)", {
+    platform: "linux32",
+    collection: "debug",
+    image: LINUX_IMAGE
+  }, "-t ia32");
+
+  await scheduleLinux("Linux 64 (opt)", {
+    platform: "linux64",
+    image: LINUX_IMAGE
+  }, "--opt");
+
+  await scheduleLinux("Linux 64 (debug)", {
+    platform: "linux64",
+    collection: "debug",
+    image: LINUX_IMAGE
+  });
+
+  await scheduleLinux("Linux 64 (debug, make)", {
+    env: {USE_64: "1"},
+    platform: "linux64",
+    image: LINUX_IMAGE,
+    collection: "make",
+    command: [
+       "/bin/bash",
+       "-c",
+       "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
+    ],
+  });
+
+  await scheduleLinux("Linux 64 (opt, make)", {
+    env: {USE_64: "1", BUILD_OPT: "1"},
+    platform: "linux64",
+    image: LINUX_IMAGE,
+    collection: "make",
+    command: [
+       "/bin/bash",
+       "-c",
+       "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
+    ],
+  });
+
+  await scheduleLinux("Linux 32 (debug, make)", {
+    platform: "linux32",
+    image: LINUX_IMAGE,
+    collection: "make",
+    command: [
+       "/bin/bash",
+       "-c",
+       "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
+    ],
+  });
+
+  await scheduleLinux("Linux 64 (ASan, debug)", {
+    env: {
+      UBSAN_OPTIONS: "print_stacktrace=1",
+      NSS_DISABLE_ARENA_FREE_LIST: "1",
+      NSS_DISABLE_UNLOAD: "1",
+      CC: "clang",
+      CCC: "clang++",
+    },
+    platform: "linux64",
+    collection: "asan",
+    image: LINUX_IMAGE,
+    features: ["allowPtrace"],
+  }, "--ubsan --asan");
+
+  await scheduleLinux("Linux 64 (FIPS opt)", {
+    platform: "linux64",
+    collection: "fips",
+    image: LINUX_IMAGE,
+  }, "--enable-fips --opt");
+
+  await scheduleWindows("Windows 2012 64 (debug, make)", {
+    platform: "windows2012-64",
+    collection: "make",
+    env: {USE_64: "1"}
+  }, "build.sh");
+
+  await scheduleWindows("Windows 2012 32 (debug, make)", {
+    platform: "windows2012-32",
+    collection: "make"
+  }, "build.sh");
+
+  await scheduleWindows("Windows 2012 64 (opt)", {
+    platform: "windows2012-64",
+  }, "build_gyp.sh --opt");
+
+  await scheduleWindows("Windows 2012 64 (debug)", {
+    platform: "windows2012-64",
+    collection: "debug"
+  }, "build_gyp.sh");
+
+  await scheduleWindows("Windows 2012 64 Static (opt)", {
+    platform: "windows2012-64",
+    collection: "opt-static"
+  }, "build_gyp.sh --opt --static");
+
+  await scheduleWindows("Windows 2012 32 (opt)", {
+    platform: "windows2012-32",
+  }, "build_gyp.sh --opt -t ia32");
+
+  await scheduleWindows("Windows 2012 32 (debug)", {
+    platform: "windows2012-32",
+    collection: "debug"
+  }, "build_gyp.sh -t ia32");
+
+  await scheduleFuzzing();
+  await scheduleFuzzing32();
+
+  await scheduleTools();
+
+  let aarch64_base = {
+    image: "franziskus/nss-aarch64-ci",
+    provisioner: "localprovisioner",
+    workerType: "nss-aarch64",
+    platform: "aarch64",
+    maxRunTime: 7200
+  };
+
+  await scheduleLinux("Linux AArch64 (debug)",
+    merge(aarch64_base, {
+      command: [
+        "/bin/bash",
+        "-c",
+        "bin/checkout.sh && nss/automation/taskcluster/scripts/build_gyp.sh"
+      ],
+      collection: "debug",
+    })
+  );
+
+  await scheduleLinux("Linux AArch64 (opt)",
+    merge(aarch64_base, {
+      command: [
+        "/bin/bash",
+        "-c",
+        "bin/checkout.sh && nss/automation/taskcluster/scripts/build_gyp.sh --opt"
+      ],
+      collection: "opt",
+    })
+  );
+
+  await scheduleLinux("Linux AArch64 (debug, make)",
+    merge(aarch64_base, {
+      env: {USE_64: "1"},
+      command: [
+         "/bin/bash",
+         "-c",
+         "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
+      ],
+      collection: "make",
+    })
+  );
+
+  await scheduleMac("Mac (opt)", {collection: "opt"}, "--opt");
+  await scheduleMac("Mac Static (opt)", {collection: "opt-static"}, "--opt --static -Ddisable_libpkix=1");
+  await scheduleMac("Mac (debug)", {collection: "debug"});
+
+  // Must be executed after all other tasks are scheduled
+  queue.clearFilters();
+  await scheduleCodeReview();
+}
+
+
+async function scheduleMac(name, base, args = "") {
+  let mac_base = merge(base, {
+    env: {
+      PATH: "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin",
+      NSS_TASKCLUSTER_MAC: "1",
+      DOMSUF: "localdomain",
+      HOST: "localhost",
+    },
+    provisioner: "localprovisioner",
+    workerType: "nss-macos-10-12",
+    platform: "mac"
+  });
+
+  // Build base definition.
+  let build_base_without_command_symbol = merge(mac_base, {
+    provisioner: "localprovisioner",
+    workerType: "nss-macos-10-12",
+    platform: "mac",
+    maxRunTime: 7200,
+    artifacts: [{
+      expires: 24 * 7,
+      type: "directory",
+      path: "public"
+    }],
+    kind: "build",
+  });
+
+  let gyp_cmd = "nss/automation/taskcluster/scripts/build_gyp.sh ";
+
+  if (!("collection" in base) ||
+      (base.collection != "make" &&
+       base.collection != "asan" &&
+       base.collection != "fips" &&
+       base.collection != "fuzz")) {
+    let nspr_gyp = gyp_cmd + "--nspr-only --nspr-test-build --nspr-test-run ";
+    let nspr_build = merge(build_base_without_command_symbol, {
+      command: [
+        MAC_CHECKOUT_CMD,
+        ["bash", "-c",
+         nspr_gyp + args]
+      ],
+      symbol: "NSPR"
+    });
+    // The task that tests NSPR.
+    let nspr_task_build = queue.scheduleTask(merge(nspr_build, {name}));
+  }
+
+  let build_base = merge(build_base_without_command_symbol, {
+    command: [
+      MAC_CHECKOUT_CMD,
+      ["bash", "-c",
+       gyp_cmd + args]
+    ],
+    symbol: "B"
+  });
+
+  // The task that builds NSPR+NSS.
+  let task_build = queue.scheduleTask(merge(build_base, {name}));
+
+  // The task that generates certificates.
+  let task_cert = queue.scheduleTask(merge(build_base, {
+    name: "Certificates",
+    command: [
+      MAC_CHECKOUT_CMD,
+      ["bash", "-c",
+       "nss/automation/taskcluster/scripts/gen_certs.sh"]
+    ],
+    parent: task_build,
+    symbol: "Certs"
+  }));
+
+  // Schedule tests.
+  scheduleTests(task_build, task_cert, merge(mac_base, {
+    command: [
+      MAC_CHECKOUT_CMD,
+      ["bash", "-c",
+       "nss/automation/taskcluster/scripts/run_tests.sh"]
+    ]
+  }));
+
+  return queue.submit();
+}
+
+/*****************************************************************************/
+
+async function scheduleLinux(name, overrides, args = "") {
+  let checkout_and_gyp = "bin/checkout.sh && nss/automation/taskcluster/scripts/build_gyp.sh ";
+  let artifacts_and_kind = {
+    artifacts: {
+      public: {
+        expires: 24 * 7,
+        type: "directory",
+        path: "/home/worker/artifacts"
+      }
+    },
+    kind: "build",
+  };
+
+  if (!("collection" in overrides) ||
+       (overrides.collection != "make" &&
+        overrides.collection != "asan" &&
+        overrides.collection != "fips" &&
+        overrides.collection != "fuzz")) {
+    let nspr_gyp = checkout_and_gyp + "--nspr-only --nspr-test-build --nspr-test-run ";
+
+    let nspr_base = merge({
+      command: [
+        "/bin/bash",
+        "-c",
+        nspr_gyp + args
+      ],
+    }, overrides);
+    let nspr_without_symbol = merge(nspr_base, artifacts_and_kind);
+    let nspr_build = merge(nspr_without_symbol, {
+      symbol: "NSPR",
+    });
+    // The task that tests NSPR.
+    let nspr_task_build = queue.scheduleTask(merge(nspr_build, {name}));
+  }
+
+  // Construct a base definition.  This takes |overrides| second because
+  // callers expect to be able to overwrite the |command| key.
+  let base = merge({
+    command: [
+      "/bin/bash",
+      "-c",
+      checkout_and_gyp + args
+    ],
+  }, overrides);
+
+  let base_without_symbol = merge(base, artifacts_and_kind);
+
+  // The base for building.
+  let build_base = merge(base_without_symbol, {
+    symbol: "B",
+  });
+
+  // The task that builds NSPR+NSS.
+  let task_build = queue.scheduleTask(merge(build_base, {name}));
+
+  // Make builds run FIPS tests, which need an extra FIPS build.
+  if (base.collection == "make") {
+    let extra_build = queue.scheduleTask(merge(build_base, {
+      env: { NSS_FORCE_FIPS: "1" },
+      group: "FIPS",
+      name: `${name} w/ NSS_FORCE_FIPS`
+    }));
+
+    // The task that generates certificates.
+    let task_cert = queue.scheduleTask(merge(build_base, {
+      name: "Certificates",
+      command: [
+        "/bin/bash",
+        "-c",
+        "bin/checkout.sh && nss/automation/taskcluster/scripts/gen_certs.sh"
+      ],
+      parent: extra_build,
+      symbol: "Certs-F",
+      group: "FIPS",
+    }));
+
+    // Schedule FIPS tests.
+    queue.scheduleTask(merge(base, {
+      parent: task_cert,
+      name: "FIPS",
+      command: [
+        "/bin/bash",
+        "-c",
+        "bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
+      ],
+      cycle: "standard",
+      kind: "test",
+      name: "FIPS tests",
+      symbol: "Tests-F",
+      tests: "fips",
+      group: "FIPS"
+    }));
+  }
+
+  // The task that generates certificates.
+  let cert_base = merge(build_base, {
+    name: "Certificates",
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/gen_certs.sh"
+    ],
+    parent: task_build,
+    symbol: "Certs"
+  });
+  let task_cert = queue.scheduleTask(cert_base);
+
+  // Schedule tests.
+  scheduleTests(task_build, task_cert, merge(base, {
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
+    ]
+  }));
+
+  // Extra builds.
+  let extra_base = merge(build_base, {
+    group: "Builds",
+    image: LINUX_BUILDS_IMAGE,
+  });
+  queue.scheduleTask(merge(extra_base, {
+    name: `${name} w/ clang-4`,
+    env: {
+      CC: "clang-4.0",
+      CCC: "clang++-4.0",
+    },
+    symbol: "clang-4"
+  }));
+  queue.scheduleTask(merge(extra_base, {
+    name: `${name} w/ clang-10`,
+    env: {
+      CC: "clang-10",
+      CCC: "clang++-10",
+    },
+    symbol: "clang-10"
+  }));
+  queue.scheduleTask(merge(extra_base, {
+    name: `${name} w/ gcc-4.4`,
+    image: LINUX_GCC44_IMAGE,
+    env: {
+      USE_64: "1",
+      CC: "gcc-4.4",
+      CCC: "g++-4.4",
+      // gcc-4.6 introduced nullptr.
+      NSS_DISABLE_GTESTS: "1",
+    },
+    // Use the old Makefile-based build system, GYP doesn't have a proper GCC
+    // version check for __int128 support. It's mainly meant to cover RHEL6.
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh",
+    ],
+    symbol: "gcc-4.4"
+  }));
+
+  queue.scheduleTask(merge(extra_base, {
+    name: `${name} w/ gcc-4.8`,
+    env: {
+      CC: "gcc-4.8",
+      CCC: "g++-4.8",
+      // gcc-4.8 has incomplete c++11 support
+      NSS_DISABLE_GTESTS: "1",
+    },
+    // Use -Ddisable-intelhw_sha=1, GYP doesn't have a proper GCC version
+    // check for Intel SHA support.
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh",
+    ],
+    symbol: "gcc-4.8"
+  }));
+
+  queue.scheduleTask(merge(extra_base, {
+    name: `${name} w/ gcc-5`,
+    env: {
+      CC: "gcc-5",
+      CCC: "g++-5"
+    },
+    symbol: "gcc-5"
+  }));
+
+  queue.scheduleTask(merge(extra_base, {
+    name: `${name} w/ gcc-11`,
+    env: {
+      CC: "gcc-11",
+      CCC: "g++-11",
+    },
+    symbol: "gcc-11"
+  }));
+
+  queue.scheduleTask(merge(extra_base, {
+    name: `${name} w/ modular builds`,
+    image: LINUX_IMAGE,
+    env: {NSS_BUILD_MODULAR: "1"},
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh",
+    ],
+    symbol: "modular"
+  }));
+
+  if (base.collection != "make") {
+    let task_build_dbm = queue.scheduleTask(merge(extra_base, {
+      name: `${name} w/ legacy-db`,
+      command: [
+        "/bin/bash",
+        "-c",
+        checkout_and_gyp + "--enable-legacy-db"
+      ],
+      symbol: "B",
+      group: "DBM",
+    }));
+
+    let task_cert_dbm = queue.scheduleTask(merge(cert_base, {
+      parent: task_build_dbm,
+      group: "DBM",
+      symbol: "Certs"
+    }));
+  }
+
+  return queue.submit();
+}
+
+/*****************************************************************************/
+
+function scheduleFuzzingRun(base, name, target, max_len, symbol = null, corpus = null) {
+  const MAX_FUZZ_TIME = 300;
+
+  queue.scheduleTask(merge(base, {
+    name,
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/fuzz.sh " +
+        `${target} nss/fuzz/corpus/${corpus || target} ` +
+        `-max_total_time=${MAX_FUZZ_TIME} ` +
+        `-max_len=${max_len}`
+    ],
+    symbol: symbol || name
+  }));
+}
+
+async function scheduleFuzzing() {
+  let base = {
+    env: {
+      ASAN_OPTIONS: "allocator_may_return_null=1:detect_stack_use_after_return=1",
+      UBSAN_OPTIONS: "print_stacktrace=1",
+      NSS_DISABLE_ARENA_FREE_LIST: "1",
+      NSS_DISABLE_UNLOAD: "1",
+      CC: "clang",
+      CCC: "clang++"
+    },
+    features: ["allowPtrace"],
+    platform: "linux64",
+    collection: "fuzz",
+    image: FUZZ_IMAGE
+  };
+
+  // Build base definition.
+  let build_base = merge(base, {
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && " +
+      "nss/automation/taskcluster/scripts/build_gyp.sh --fuzz"
+    ],
+    artifacts: {
+      public: {
+        expires: 24 * 7,
+        type: "directory",
+        path: "/home/worker/artifacts"
+      }
+    },
+    kind: "build",
+    symbol: "B"
+  });
+
+  // The task that builds NSPR+NSS.
+  let task_build = queue.scheduleTask(merge(build_base, {
+    name: "Linux x64 (debug, fuzz)"
+  }));
+
+  // The task that builds NSPR+NSS (TLS fuzzing mode).
+  let task_build_tls = queue.scheduleTask(merge(build_base, {
+    name: "Linux x64 (debug, TLS fuzz)",
+    symbol: "B",
+    group: "TLS",
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && " +
+      "nss/automation/taskcluster/scripts/build_gyp.sh --fuzz=tls"
+    ],
+  }));
+
+  // Schedule tests.
+  queue.scheduleTask(merge(base, {
+    parent: task_build_tls,
+    name: "Gtests",
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
+    ],
+    env: {GTESTFILTER: "*Fuzz*"},
+    tests: "ssl_gtests gtests",
+    cycle: "standard",
+    symbol: "Gtest",
+    kind: "test"
+  }));
+
+  // Schedule fuzzing runs.
+  let run_base = merge(base, {parent: task_build, kind: "test"});
+  scheduleFuzzingRun(run_base, "CertDN", "certDN", 4096);
+  scheduleFuzzingRun(run_base, "QuickDER", "quickder", 10000);
+
+  // Schedule MPI fuzzing runs.
+  let mpi_base = merge(run_base, {group: "MPI"});
+  let mpi_names = ["add", "addmod", "div", "mod", "mulmod", "sqr",
+                   "sqrmod", "sub", "submod"];
+  for (let name of mpi_names) {
+    scheduleFuzzingRun(mpi_base, `MPI (${name})`, `mpi-${name}`, 4096, name);
+  }
+  scheduleFuzzingRun(mpi_base, `MPI (invmod)`, `mpi-invmod`, 256, "invmod");
+  scheduleFuzzingRun(mpi_base, `MPI (expmod)`, `mpi-expmod`, 2048, "expmod");
+
+  // Schedule TLS fuzzing runs (non-fuzzing mode).
+  let tls_base = merge(run_base, {group: "TLS"});
+  scheduleFuzzingRun(tls_base, "TLS Client", "tls-client", 20000, "client-nfm",
+                     "tls-client-no_fuzzer_mode");
+  scheduleFuzzingRun(tls_base, "TLS Server", "tls-server", 20000, "server-nfm",
+                     "tls-server-no_fuzzer_mode");
+  scheduleFuzzingRun(tls_base, "DTLS Client", "dtls-client", 20000,
+                     "dtls-client-nfm", "dtls-client-no_fuzzer_mode");
+  scheduleFuzzingRun(tls_base, "DTLS Server", "dtls-server", 20000,
+                     "dtls-server-nfm", "dtls-server-no_fuzzer_mode");
+
+  // Schedule TLS fuzzing runs (fuzzing mode).
+  let tls_fm_base = merge(tls_base, {parent: task_build_tls});
+  scheduleFuzzingRun(tls_fm_base, "TLS Client", "tls-client", 20000, "client");
+  scheduleFuzzingRun(tls_fm_base, "TLS Server", "tls-server", 20000, "server");
+  scheduleFuzzingRun(tls_fm_base, "DTLS Client", "dtls-client", 20000, "dtls-client");
+  scheduleFuzzingRun(tls_fm_base, "DTLS Server", "dtls-server", 20000, "dtls-server");
+
+  return queue.submit();
+}
+
+async function scheduleFuzzing32() {
+  let base = {
+    env: {
+      ASAN_OPTIONS: "allocator_may_return_null=1:detect_stack_use_after_return=1",
+      UBSAN_OPTIONS: "print_stacktrace=1",
+      NSS_DISABLE_ARENA_FREE_LIST: "1",
+      NSS_DISABLE_UNLOAD: "1",
+      CC: "clang",
+      CCC: "clang++"
+    },
+    features: ["allowPtrace"],
+    platform: "linux32",
+    collection: "fuzz",
+    image: FUZZ_IMAGE_32
+  };
+
+  // Build base definition.
+  let build_base = merge(base, {
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && " +
+      "nss/automation/taskcluster/scripts/build_gyp.sh --fuzz -t ia32"
+    ],
+    artifacts: {
+      public: {
+        expires: 24 * 7,
+        type: "directory",
+        path: "/home/worker/artifacts"
+      }
+    },
+    kind: "build",
+    symbol: "B"
+  });
+
+  // The task that builds NSPR+NSS.
+  let task_build = queue.scheduleTask(merge(build_base, {
+    name: "Linux 32 (debug, fuzz)"
+  }));
+
+  // The task that builds NSPR+NSS (TLS fuzzing mode).
+  let task_build_tls = queue.scheduleTask(merge(build_base, {
+    name: "Linux 32 (debug, TLS fuzz)",
+    symbol: "B",
+    group: "TLS",
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && " +
+      "nss/automation/taskcluster/scripts/build_gyp.sh --fuzz=tls -t ia32"
+    ],
+  }));
+
+  // Schedule tests.
+  queue.scheduleTask(merge(base, {
+    parent: task_build_tls,
+    name: "Gtests",
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
+    ],
+    env: {GTESTFILTER: "*Fuzz*"},
+    tests: "ssl_gtests gtests",
+    cycle: "standard",
+    symbol: "Gtest",
+    kind: "test"
+  }));
+
+  // Schedule fuzzing runs.
+  let run_base = merge(base, {parent: task_build, kind: "test"});
+  scheduleFuzzingRun(run_base, "CertDN", "certDN", 4096);
+  scheduleFuzzingRun(run_base, "QuickDER", "quickder", 10000);
+
+  // Schedule MPI fuzzing runs.
+  let mpi_base = merge(run_base, {group: "MPI"});
+  let mpi_names = ["add", "addmod", "div", "expmod", "mod", "mulmod", "sqr",
+                   "sqrmod", "sub", "submod"];
+  for (let name of mpi_names) {
+    scheduleFuzzingRun(mpi_base, `MPI (${name})`, `mpi-${name}`, 4096, name);
+  }
+  scheduleFuzzingRun(mpi_base, `MPI (invmod)`, `mpi-invmod`, 256, "invmod");
+
+  // Schedule TLS fuzzing runs (non-fuzzing mode).
+  let tls_base = merge(run_base, {group: "TLS"});
+  scheduleFuzzingRun(tls_base, "TLS Client", "tls-client", 20000, "client-nfm",
+                     "tls-client-no_fuzzer_mode");
+  scheduleFuzzingRun(tls_base, "TLS Server", "tls-server", 20000, "server-nfm",
+                     "tls-server-no_fuzzer_mode");
+  scheduleFuzzingRun(tls_base, "DTLS Client", "dtls-client", 20000,
+                     "dtls-client-nfm", "dtls-client-no_fuzzer_mode");
+  scheduleFuzzingRun(tls_base, "DTLS Server", "dtls-server", 20000,
+                     "dtls-server-nfm", "dtls-server-no_fuzzer_mode");
+
+  // Schedule TLS fuzzing runs (fuzzing mode).
+  let tls_fm_base = merge(tls_base, {parent: task_build_tls});
+  scheduleFuzzingRun(tls_fm_base, "TLS Client", "tls-client", 20000, "client");
+  scheduleFuzzingRun(tls_fm_base, "TLS Server", "tls-server", 20000, "server");
+  scheduleFuzzingRun(tls_fm_base, "DTLS Client", "dtls-client", 20000, "dtls-client");
+  scheduleFuzzingRun(tls_fm_base, "DTLS Server", "dtls-server", 20000, "dtls-server");
+
+  return queue.submit();
+}
+
+/*****************************************************************************/
+
+async function scheduleWindows(name, base, build_script) {
+  base = merge(base, {
+    workerType: "win2012r2",
+    env: {
+      PATH: "c:\\mozilla-build\\bin;c:\\mozilla-build\\python;" +
+           "c:\\mozilla-build\\msys\\local\\bin;c:\\mozilla-build\\7zip;" +
+           "c:\\mozilla-build\\info-zip;c:\\mozilla-build\\python\\Scripts;" +
+           "c:\\mozilla-build\\yasm;c:\\mozilla-build\\msys\\bin;" +
+           "c:\\Windows\\system32;c:\\mozilla-build\\upx391w;" +
+           "c:\\mozilla-build\\moztools-x64\\bin;c:\\mozilla-build\\wget",
+      DOMSUF: "localdomain",
+      HOST: "localhost",
+    },
+    features: ["taskclusterProxy"],
+    scopes: ["project:releng:services/tooltool/api/download/internal"],
+  });
+
+  let artifacts_and_kind = {
+    artifacts: [{
+      expires: 24 * 7,
+      type: "directory",
+      path: "public\\build"
+    }],
+    kind: "build",
+  };
+
+  let build_without_command_symbol = merge(base, artifacts_and_kind);
+
+  // Build base definition.
+  let build_base = merge(build_without_command_symbol, {
+    command: [
+      WINDOWS_CHECKOUT_CMD,
+      `bash -c 'nss/automation/taskcluster/windows/${build_script}'`
+    ],
+    symbol: "B"
+  });
+
+  if (!("collection" in base) ||
+      (base.collection != "make" &&
+       base.collection != "asan" &&
+       base.collection != "fips" &&
+       base.collection != "fuzz")) {
+    let nspr_gyp =
+      `bash -c 'nss/automation/taskcluster/windows/${build_script} --nspr-only --nspr-test-build --nspr-test-run'`;
+    let nspr_build = merge(build_without_command_symbol, {
+      command: [
+        WINDOWS_CHECKOUT_CMD,
+        nspr_gyp
+      ],
+      symbol: "NSPR"
+    });
+    // The task that tests NSPR.
+    let task_build = queue.scheduleTask(merge(nspr_build, {name}));
+  }
+
+  // Make builds run FIPS tests, which need an extra FIPS build.
+  if (base.collection == "make") {
+    let extra_build = queue.scheduleTask(merge(build_base, {
+      env: { NSS_FORCE_FIPS: "1" },
+      group: "FIPS",
+      name: `${name} w/ NSS_FORCE_FIPS`
+    }));
+
+    // The task that generates certificates.
+    let task_cert = queue.scheduleTask(merge(build_base, {
+      name: "Certificates",
+      command: [
+        WINDOWS_CHECKOUT_CMD,
+        "bash -c nss/automation/taskcluster/windows/gen_certs.sh"
+      ],
+      parent: extra_build,
+      symbol: "Certs-F",
+      group: "FIPS",
+    }));
+
+    // Schedule FIPS tests.
+    queue.scheduleTask(merge(base, {
+      parent: task_cert,
+      name: "FIPS",
+      command: [
+        WINDOWS_CHECKOUT_CMD,
+        "bash -c nss/automation/taskcluster/windows/run_tests.sh"
+      ],
+      cycle: "standard",
+      kind: "test",
+      name: "FIPS tests",
+      symbol: "Tests-F",
+      tests: "fips",
+      group: "FIPS"
+    }));
+  }
+
+  // The task that builds NSPR+NSS.
+  let task_build = queue.scheduleTask(merge(build_base, {name}));
+
+  // The task that generates certificates.
+  let task_cert = queue.scheduleTask(merge(build_base, {
+    name: "Certificates",
+    command: [
+      WINDOWS_CHECKOUT_CMD,
+      "bash -c nss/automation/taskcluster/windows/gen_certs.sh"
+    ],
+    parent: task_build,
+    symbol: "Certs"
+  }));
+
+  // Schedule tests.
+  scheduleTests(task_build, task_cert, merge(base, {
+    command: [
+      WINDOWS_CHECKOUT_CMD,
+      "bash -c nss/automation/taskcluster/windows/run_tests.sh"
+    ]
+  }));
+
+  return queue.submit();
+}
+
+/*****************************************************************************/
+
+function scheduleTests(task_build, task_cert, test_base) {
+  test_base = merge(test_base, {kind: "test"});
+  let no_cert_base = merge(test_base, {parent: task_build});
+  let cert_base = merge(test_base, {parent: task_cert});
+  let cert_base_long = merge(cert_base, {maxRunTime: 7200});
+
+  // Schedule tests that do NOT need certificates. This is defined as
+  // the test itself not needing certs AND not running under the upgradedb
+  // cycle (which itself needs certs). If cycle is not defined, default is all.
+  queue.scheduleTask(merge(no_cert_base, {
+    name: "Gtests", symbol: "Gtest", tests: "ssl_gtests gtests", cycle: "standard"
+  }));
+  queue.scheduleTask(merge(no_cert_base, {
+    name: "Bogo tests",
+    symbol: "Bogo",
+    tests: "bogo",
+    cycle: "standard",
+    image: LINUX_INTEROP_IMAGE,
+  }));
+  queue.scheduleTask(merge(no_cert_base, {
+    name: "Interop tests",
+    symbol: "Interop",
+    tests: "interop",
+    cycle: "standard",
+    image: LINUX_INTEROP_IMAGE,
+  }));
+  queue.scheduleTask(merge(no_cert_base, {
+    name: "tlsfuzzer tests", symbol: "tlsfuzzer", tests: "tlsfuzzer", cycle: "standard"
+  }));
+  queue.scheduleTask(merge(no_cert_base, {
+    name: "MPI tests", symbol: "MPI", tests: "mpi", cycle: "standard"
+  }));
+  queue.scheduleTask(merge(cert_base, {
+    name: "Chains tests", symbol: "Chains", tests: "chains"
+  }));
+  queue.scheduleTask(merge(cert_base_long, {
+    name: "Cipher tests", symbol: "Default", tests: "cipher", group: "Cipher"
+  }));
+  queue.scheduleTask(merge(cert_base_long, {
+    name: "Cipher tests", symbol: "NoAES", tests: "cipher",
+    env: {NSS_DISABLE_HW_AES: "1"}, group: "Cipher"
+  }));
+  queue.scheduleTask(merge(cert_base_long, {
+    name: "Cipher tests", symbol: "NoSHA", tests: "cipher",
+    env: {
+      NSS_DISABLE_HW_SHA1: "1",
+      NSS_DISABLE_HW_SHA2: "1"
+    }, group: "Cipher"
+  }));
+  queue.scheduleTask(merge(cert_base_long, {
+    name: "Cipher tests", symbol: "NoPCLMUL", tests: "cipher",
+    env: {NSS_DISABLE_PCLMUL: "1"}, group: "Cipher"
+  }));
+  queue.scheduleTask(merge(cert_base_long, {
+    name: "Cipher tests", symbol: "NoAVX", tests: "cipher",
+    env: {NSS_DISABLE_AVX: "1"}, group: "Cipher"
+  }));
+  queue.scheduleTask(merge(cert_base_long, {
+    name: "Cipher tests", symbol: "NoAVX2", tests: "cipher",
+    env: {NSS_DISABLE_AVX2: "1"}, group: "Cipher"
+  }));
+  queue.scheduleTask(merge(cert_base_long, {
+    name: "Cipher tests", symbol: "NoSSSE3|NEON", tests: "cipher",
+    env: {
+      NSS_DISABLE_ARM_NEON: "1",
+      NSS_DISABLE_SSSE3: "1"
+    }, group: "Cipher"
+  }));
+  queue.scheduleTask(merge(cert_base_long, {
+    name: "Cipher tests", symbol: "NoSSE4.1", tests: "cipher",
+    env: {NSS_DISABLE_SSE4_1: "1"}, group: "Cipher"
+  }));
+  queue.scheduleTask(merge(cert_base, {
+    name: "EC tests", symbol: "EC", tests: "ec"
+  }));
+  queue.scheduleTask(merge(cert_base, {
+    name: "Lowhash tests", symbol: "Lowhash", tests: "lowhash"
+  }));
+  queue.scheduleTask(merge(cert_base, {
+    name: "SDR tests", symbol: "SDR", tests: "sdr"
+  }));
+  queue.scheduleTask(merge(cert_base, {
+    name: "Policy tests", symbol: "Policy", tests: "policy"
+  }));
+
+  // Schedule tests that need certificates.
+  queue.scheduleTask(merge(cert_base, {
+    name: "CRMF tests", symbol: "CRMF", tests: "crmf"
+  }));
+  queue.scheduleTask(merge(cert_base, {
+    name: "DB tests", symbol: "DB", tests: "dbtests"
+  }));
+  queue.scheduleTask(merge(cert_base, {
+    name: "Merge tests", symbol: "Merge", tests: "merge"
+  }));
+  queue.scheduleTask(merge(cert_base, {
+    name: "S/MIME tests", symbol: "SMIME", tests: "smime"
+  }));
+  queue.scheduleTask(merge(cert_base, {
+    name: "Tools tests", symbol: "Tools", tests: "tools"
+  }));
+
+  // SSL tests, need certificates too.
+  let ssl_base = merge(cert_base, {tests: "ssl", group: "SSL"});
+  queue.scheduleTask(merge(ssl_base, {
+    name: "SSL tests (standard)", symbol: "standard", cycle: "standard"
+  }));
+  queue.scheduleTask(merge(ssl_base, {
+    name: "SSL tests (pkix)", symbol: "pkix", cycle: "pkix"
+  }));
+  queue.scheduleTask(merge(ssl_base, {
+    name: "SSL tests (stress)", symbol: "stress", cycle: "sharedb",
+    env: {NSS_SSL_RUN: "stress"}
+  }));
+}
+
+/*****************************************************************************/
+
+async function scheduleTools() {
+  let base = {
+    platform: "nss-tools",
+    kind: "test"
+  };
+
+  // ABI check task
+  queue.scheduleTask(merge(base, {
+    symbol: "abi",
+    name: "abi",
+    image: LINUX_BUILDS_IMAGE,
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/check_abi.sh"
+    ],
+  }));
+
+  queue.scheduleTask(merge(base, {
+    symbol: "clang-format",
+    name: "clang-format",
+    image: CLANG_FORMAT_IMAGE,
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/clang-format/run_clang_format.sh"
+    ]
+  }));
+
+  queue.scheduleTask(merge(base, {
+    symbol: "acvp",
+    name: "acvp",
+    image: ACVP_IMAGE,
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && bin/run.sh"
+    ]
+  }));
+
+
+  queue.scheduleTask(merge(base, {
+    symbol: "scan-build",
+    name: "scan-build",
+    image: FUZZ_IMAGE,
+    env: {
+      USE_64: "1",
+      CC: "clang",
+      CCC: "clang++",
+    },
+    artifacts: {
+      public: {
+        expires: 24 * 7,
+        type: "directory",
+        path: "/home/worker/artifacts"
+      }
+    },
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/run_scan_build.sh"
+    ]
+  }));
+
+  queue.scheduleTask(merge(base, {
+    symbol: "hacl",
+    name: "hacl",
+    image: LINUX_BUILDS_IMAGE,
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/run_hacl.sh"
+    ]
+  }));
+
+  queue.scheduleTask(merge(base, {
+    symbol: "Coverage",
+    name: "Coverage",
+    image: FUZZ_IMAGE,
+    type: "other",
+    features: ["allowPtrace"],
+    artifacts: {
+      public: {
+        expires: 24 * 7,
+        type: "directory",
+        path: "/home/worker/artifacts"
+      }
+    },
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/gen_coverage_report.sh"
+    ]
+  }));
+
+  return queue.submit();
+}
+
+async function scheduleCodeReview() {
+  let tasks = queue.taggedTasks("code-review");
+  if(! tasks) {
+    console.debug("No code review tasks, skipping ending task");
+    return
+  }
+
+  // From https://hg.mozilla.org/mozilla-central/file/tip/taskcluster/ci/code-review/kind.yml
+  queue.scheduleTask({
+    platform: "nss-tools",
+    name: "code-review-issues",
+    description: "List all issues found in static analysis and linting tasks",
+
+    // No logic on that task
+    image: LINUX_IMAGE,
+    command: ["/bin/true"],
+
+    // This task must run after all analyzer tasks are completed
+    parents: tasks,
+
+    // This option permits to run the task
+    // regardless of the analyzers tasks exit status
+    // as we are interested in the task failures
+    requires: "all-resolved",
+
+    // Publish code review trigger on pulse
+    routes: ["project.relman.codereview.v1.try_ending"],
+
+    kind: "code-review",
+    symbol: "E"
+  });
+
+  return queue.submit();
+};
diff --git a/nss-3.88/nss/automation/taskcluster/graph/src/image_builder.js b/nss-3.88/nss/automation/taskcluster/graph/src/image_builder.js
new file mode 100644
index 0000000..7bf632d
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/graph/src/image_builder.js
@@ -0,0 +1,61 @@
+/* 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/. */
+
+import * as queue from "./queue";
+import context_hash from "./context_hash";
+import taskcluster from "taskcluster-client";
+
+async function taskHasImageArtifact(taskId) {
+  let queue = new taskcluster.Queue(taskcluster.fromEnvVars());
+  let {artifacts} = await queue.listLatestArtifacts(taskId);
+  return artifacts.some(artifact => artifact.name == "public/image.tar.zst");
+}
+
+async function findTaskWithImageArtifact(ns) {
+  let index = new taskcluster.Index(taskcluster.fromEnvVars());
+  let {taskId} = await index.findTask(ns);
+  let has_image = await taskHasImageArtifact(taskId);
+  return has_image ? taskId : null;
+}
+
+export async function findTask({name, path}) {
+  let hash = await context_hash(path);
+  let ns = `docker.images.v1.${process.env.TC_PROJECT}.${name}.hash.${hash}`;
+  return findTaskWithImageArtifact(ns).catch(() => null);
+}
+
+export async function buildTask({name, path}) {
+  let hash = await context_hash(path);
+  let ns = `docker.images.v1.${process.env.TC_PROJECT}.${name}.hash.${hash}`;
+
+  return {
+    name: `Image Builder (${name})`,
+    image: "nssdev/image_builder:0.1.5",
+    routes: ["index." + ns],
+    env: {
+      NSS_HEAD_REPOSITORY: process.env.NSS_HEAD_REPOSITORY,
+      NSS_HEAD_REVISION: process.env.NSS_HEAD_REVISION,
+      PROJECT: process.env.TC_PROJECT,
+      CONTEXT_PATH: path,
+      HASH: hash
+    },
+    artifacts: {
+      "public/image.tar.zst": {
+        type: "file",
+        expires: 24 * 90,
+        path: "/artifacts/image.tar.zst"
+      }
+    },
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/build_image.sh"
+    ],
+    platform: "nss-decision",
+    features: ["dind"],
+    maxRunTime: 7200,
+    kind: "build",
+    symbol: "I"
+  };
+}
diff --git a/nss-3.88/nss/automation/taskcluster/graph/src/index.js b/nss-3.88/nss/automation/taskcluster/graph/src/index.js
new file mode 100644
index 0000000..78f4af8
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/graph/src/index.js
@@ -0,0 +1,22 @@
+/* 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/. */
+
+import * as try_syntax from "./try_syntax";
+import * as queue from "./queue";
+import extend from "./extend";
+
+const main = async () => {
+  // Init try syntax filter.
+  if (process.env.TC_PROJECT == "nss-try") {
+    await try_syntax.initFilter();
+  }
+
+  // Extend the task graph.
+  await extend();
+};
+
+main().catch(err => {
+  console.error(err);
+  process.exit(1);
+});
diff --git a/nss-3.88/nss/automation/taskcluster/graph/src/merge.js b/nss-3.88/nss/automation/taskcluster/graph/src/merge.js
new file mode 100644
index 0000000..17043dd
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/graph/src/merge.js
@@ -0,0 +1,10 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import {recursive as merge} from "merge";
+
+// We always want to clone.
+export default function (...args) {
+  return merge(true, ...args);
+}
diff --git a/nss-3.88/nss/automation/taskcluster/graph/src/queue.js b/nss-3.88/nss/automation/taskcluster/graph/src/queue.js
new file mode 100644
index 0000000..1baa604
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/graph/src/queue.js
@@ -0,0 +1,304 @@
+/* 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/. */
+
+import {clone} from "merge";
+import merge from "./merge";
+import slugid from "slugid";
+import taskcluster from "taskcluster-client";
+import * as image_builder from "./image_builder";
+
+let maps = [];
+let filters = [];
+
+let tasks = new Map();
+let tags = new Map();
+let image_tasks = new Map();
+let parameters = {};
+
+let queue = new taskcluster.Queue({
+  rootUrl: process.env.TASKCLUSTER_PROXY_URL,
+});
+
+function fromNow(hours) {
+  let d = new Date();
+  d.setHours(d.getHours() + (hours|0));
+  return d.toJSON();
+}
+
+function parseRoutes(routes) {
+  let rv = [
+    `tc-treeherder.v2.${process.env.TC_PROJECT}.${process.env.NSS_HEAD_REVISION}.${process.env.NSS_PUSHLOG_ID}`,
+    ...routes
+  ];
+
+  // Notify about failures (except on try).
+  // Turned off, too noisy.
+  /*if (process.env.TC_PROJECT != "nss-try") {
+    rv.push(`notify.email.${process.env.TC_OWNER}.on-failed`,
+            `notify.email.${process.env.TC_OWNER}.on-exception`);
+  }*/
+
+  return rv;
+}
+
+function parseFeatures(list) {
+  return list.reduce((map, feature) => {
+    map[feature] = true;
+    return map;
+  }, {});
+}
+
+function parseArtifacts(artifacts) {
+  let copy = clone(artifacts);
+  Object.keys(copy).forEach(key => {
+    copy[key].expires = fromNow(copy[key].expires);
+  });
+  return copy;
+}
+
+function parseCollection(name) {
+  let collection = {};
+  collection[name] = true;
+  return collection;
+}
+
+function parseTreeherder(def) {
+  let treeherder = {
+    build: {
+      platform: def.platform
+    },
+    machine: {
+      platform: def.platform
+    },
+    symbol: def.symbol,
+    jobKind: def.kind
+  };
+
+  if (def.group) {
+    treeherder.groupSymbol = def.group;
+  }
+
+  if (def.collection) {
+    treeherder.collection = parseCollection(def.collection);
+  }
+
+  if (def.tier) {
+    treeherder.tier = def.tier;
+  }
+
+  return treeherder;
+}
+
+function convertTask(def) {
+  let scopes = [];
+  let dependencies = [];
+
+  let env = merge({
+    NSS_HEAD_REPOSITORY: process.env.NSS_HEAD_REPOSITORY,
+    NSS_HEAD_REVISION: process.env.NSS_HEAD_REVISION,
+    NSS_MAX_MP_PBE_ITERATION_COUNT: "100",
+  }, def.env || {});
+
+  if (def.parent) {
+    dependencies.push(def.parent);
+    env.TC_PARENT_TASK_ID = def.parent;
+  }
+  if (def.parents) {
+    dependencies = dependencies.concat(def.parents);
+  }
+
+  if (def.tests) {
+    env.NSS_TESTS = def.tests;
+  }
+
+  if (def.cycle) {
+    env.NSS_CYCLES = def.cycle;
+  }
+  if (def.kind === "build") {
+    // Disable leak checking during builds (bug 1579290).
+    if (env.ASAN_OPTIONS) {
+      env.ASAN_OPTIONS += ":detect_leaks=0";
+    } else {
+      env.ASAN_OPTIONS = "detect_leaks=0";
+    }
+  }
+
+  let payload = {
+    env,
+    command: def.command,
+    maxRunTime: def.maxRunTime || 3600
+  };
+
+  if (def.image) {
+    payload.image = def.image;
+  }
+
+  if (def.artifacts) {
+    payload.artifacts = parseArtifacts(def.artifacts);
+  }
+
+  if (def.features) {
+    payload.features = parseFeatures(def.features);
+
+    if (payload.features.allowPtrace) {
+      scopes.push("docker-worker:feature:allowPtrace");
+    }
+  }
+
+  if (def.scopes) {
+    // Need to add existing scopes in the task definition
+    scopes.push.apply(scopes, def.scopes)
+  }
+
+  let extra = Object.assign({
+    treeherder: parseTreeherder(def)
+  }, parameters);
+
+  return {
+    provisionerId: def.provisioner || `nss-${process.env.MOZ_SCM_LEVEL}`,
+    workerType: def.workerType || "linux-gcp",
+    schedulerId: process.env.TC_SCHEDULER_ID,
+    taskGroupId: process.env.TASK_ID,
+
+    scopes,
+    created: fromNow(0),
+    deadline: fromNow(24),
+
+    dependencies,
+    requires: def.requires || "all-completed",
+    routes: parseRoutes(def.routes || []),
+
+    metadata: {
+      name: def.name,
+      description: def.name,
+      owner: process.env.TC_OWNER,
+      source: process.env.TC_SOURCE
+    },
+
+    payload,
+    extra,
+  };
+}
+
+export function map(fun) {
+  maps.push(fun);
+}
+
+export function filter(fun) {
+  filters.push(fun);
+}
+
+export function addParameters(params) {
+  parameters = Object.assign(parameters, params);
+}
+
+export function clearFilters(fun) {
+  filters = [];
+}
+
+export function taggedTasks(tag) {
+  return tags[tag];
+}
+
+export function scheduleTask(def) {
+  let taskId = slugid.v4();
+  tasks.set(taskId, merge({}, def));
+  return taskId;
+}
+
+export async function submit() {
+  let promises = new Map();
+
+  for (let [taskId, task] of tasks) {
+    // Allow filtering tasks before we schedule them.
+    if (!filters.every(filter => filter(task))) {
+      continue;
+    }
+
+    // Allow changing tasks before we schedule them.
+    maps.forEach(map => { task = map(merge({}, task)) });
+
+    let log_id = `${task.name} @ ${task.platform}[${task.collection || "opt"}]`;
+    if (task.group) {
+      log_id = `${task.group}::${log_id}`;
+    }
+    console.log(`+ Submitting ${log_id}.`);
+
+    // Index that task for each tag specified
+    if(task.tags) {
+      task.tags.map(tag => {
+        if(!tags[tag]) {
+          tags[tag] = [];
+        }
+        tags[tag].push(taskId);
+      });
+    }
+
+    let parent = task.parent;
+
+    // Convert the task definition.
+    task = await convertTask(task);
+
+    // Convert the docker image definition.
+    let image_def = task.payload.image;
+    if (image_def && image_def.hasOwnProperty("path")) {
+      let key = `${image_def.name}:${image_def.path}`;
+      let data = {};
+
+      // Check the cache first.
+      if (image_tasks.has(key)) {
+        data = image_tasks.get(key);
+      } else {
+        data.taskId = await image_builder.findTask(image_def);
+        data.isPending = !data.taskId;
+
+        // No task found.
+        if (data.isPending) {
+          let image_task = await image_builder.buildTask(image_def);
+
+          // Schedule a new image builder task immediately.
+          data.taskId = slugid.v4();
+
+          try {
+            await queue.createTask(data.taskId, convertTask(image_task));
+          } catch (e) {
+            console.error("! FAIL: Scheduling image builder task failed.");
+            continue; /* Skip this task on failure. */
+          }
+        }
+
+        // Store in cache.
+        image_tasks.set(key, data);
+      }
+
+      if (data.isPending) {
+        task.dependencies.push(data.taskId);
+      }
+
+      task.payload.image = {
+        path: "public/image.tar.zst",
+        taskId: data.taskId,
+        type: "task-image"
+      };
+    }
+
+    // Wait for the parent task to be created before scheduling dependants.
+    let predecessor = parent ? promises.get(parent) : Promise.resolve();
+
+    promises.set(taskId, predecessor.then(() => {
+      // Schedule the task.
+      return queue.createTask(taskId, task).catch(err => {
+        console.error(`! FAIL: Scheduling ${log_id} failed.`, err);
+      });
+    }));
+  }
+
+  // Wait for all requests to finish.
+  if (promises.length) {
+    await Promise.all([...promises.values()]);
+    console.log("=== Total:", promises.length, "tasks. ===");
+  }
+
+  tasks.clear();
+}
diff --git a/nss-3.88/nss/automation/taskcluster/graph/src/try_syntax.js b/nss-3.88/nss/automation/taskcluster/graph/src/try_syntax.js
new file mode 100644
index 0000000..4629ff4
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/graph/src/try_syntax.js
@@ -0,0 +1,201 @@
+/* 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/. */
+
+import * as queue from "./queue";
+import path from 'path'
+import fs from 'fs'
+import intersect from "intersect";
+import parse_args from "minimist";
+import util from "util";
+import child_process from 'child_process';
+
+let execFile = util.promisify(child_process.execFile);
+
+function parseOptions(opts) {
+  opts = parse_args(opts.split(/\s+/), {
+    default: {build: "do", platform: "all", unittests: "none", tools: "none"},
+    alias: {b: "build", p: "platform", u: "unittests", t: "tools", e: "extra-builds"},
+    string: ["build", "platform", "unittests", "tools", "extra-builds"]
+  });
+
+  // Parse build types (d=debug, o=opt).
+  let builds = intersect(opts.build.split(""), ["d", "o"]);
+
+  // If the given value is nonsense default to debug and opt builds.
+  if (builds.length == 0) {
+    builds = ["d", "o"];
+  }
+
+  // Parse platforms.
+  let allPlatforms = ["linux", "linux64", "linux64-asan", "linux64-fips",
+                      "win", "win64", "win-make", "win64-make",
+                      "linux64-make", "linux-make", "linux-fuzz",
+                      "linux64-fuzz", "aarch64", "aarch64-make", "mac"];
+  let platforms = intersect(opts.platform.split(/\s*,\s*/), allPlatforms);
+
+  // If the given value is nonsense or "none" default to all platforms.
+  if (platforms.length == 0 && opts.platform != "none") {
+    platforms = allPlatforms;
+  }
+
+  // Parse unit tests.
+  let aliases = {"gtests": "gtest"};
+  let allUnitTests = ["bogo", "crmf", "chains", "cipher", "db", "ec", "fips",
+                      "gtest", "interop", "lowhash", "merge", "sdr", "smime", "tools",
+                      "ssl", "mpi", "scert", "spki", "policy", "tlsfuzzer"];
+  let unittests = intersect(opts.unittests.split(/\s*,\s*/).map(t => {
+    return aliases[t] || t;
+  }), allUnitTests);
+
+  // If the given value is "all" run all tests.
+  // If it's nonsense then don't run any tests.
+  if (opts.unittests == "all") {
+    unittests = allUnitTests;
+  } else if (unittests.length == 0) {
+    unittests = [];
+  }
+
+  // Parse tools.
+  let allTools = ["clang-format", "scan-build", "hacl", "saw", "abi", "coverage"];
+  let tools = intersect(opts.tools.split(/\s*,\s*/), allTools);
+
+  // If the given value is "all" run all tools.
+  // If it's nonsense then don't run any tools.
+  if (opts.tools == "all") {
+    tools = allTools;
+  } else if (tools.length == 0) {
+    tools = [];
+  }
+
+  return {
+    builds: builds,
+    platforms: platforms,
+    unittests: unittests,
+    extra: (opts.e == "all"),
+    tools: tools
+  };
+}
+
+function filter(opts) {
+  return function (task) {
+    // Filter tools. We can immediately return here as those
+    // are not affected by platform or build type selectors.
+    if (task.platform == "nss-tools") {
+      return opts.tools.some(tool => {
+        return task.symbol.toLowerCase().startsWith(tool) ||
+               (task.group && task.group.toLowerCase().startsWith(tool));
+      });
+    }
+
+    // Filter unit tests.
+    if (task.tests) {
+      let found = opts.unittests.some(test => {
+        if (task.group && task.group.toLowerCase() == "ssl" && test == "ssl") {
+          return true;
+        }
+        if (task.group && task.group.toLowerCase() == "cipher" && test == "cipher") {
+          return true;
+        }
+        return task.symbol.toLowerCase().startsWith(test);
+      });
+
+      if (!found) {
+        return false;
+      }
+    }
+
+    // Filter extra builds.
+    if (task.group == "Builds" && !opts.extra) {
+      return false;
+    }
+
+    let coll = name => name == (task.collection || "opt");
+
+    // Filter by platform.
+    let found = opts.platforms.some(platform => {
+      let aliases = {
+        "aarch64-make": "aarch64",
+        "linux": "linux32",
+        "linux-fuzz": "linux32",
+        "linux64-asan": "linux64",
+        "linux64-fips": "linux64",
+        "linux64-fuzz": "linux64",
+        "linux64-make": "linux64",
+        "linux-make": "linux32",
+        "win64-make": "windows2012-64",
+        "win-make": "windows2012-32",
+        "win64": "windows2012-64",
+        "win": "windows2012-32"
+      };
+
+      // Check the platform name.
+      let keep = (task.platform == (aliases[platform] || platform));
+
+      // Additional checks.
+      if (platform == "linux64-asan") {
+        keep &= coll("asan");
+      } else if (platform == "linux64-fips") {
+        keep &= coll("fips");
+      } else if (platform == "linux64-make" || platform == "linux-make" ||
+                 platform == "win64-make" || platform == "win-make" ||
+                 platform == "aarch64-make") {
+        keep &= coll("make");
+      } else if (platform == "linux64-fuzz" || platform == "linux-fuzz") {
+        keep &= coll("fuzz");
+      } else {
+        keep &= coll("opt") || coll("debug");
+      }
+
+      return keep;
+    });
+
+    if (!found) {
+      return false;
+    }
+
+    // Finally, filter by build type.
+    let isDebug = coll("debug") || coll("asan") || coll("make") ||
+                  coll("fuzz");
+    return (isDebug && opts.builds.includes("d")) ||
+           (!isDebug && opts.builds.includes("o"));
+  }
+}
+
+async function getCommitComment() {
+  const res = await execFile('hg', ['log', '-r', '.', '-T', '{desc}']);
+  return res.stdout;
+};
+
+export async function initFilter() {
+  let comment = await getCommitComment();
+
+  // Load try_task_config.json
+  // Add parameters to queue for created tasks
+  let config_path = path.normalize(path.join(__dirname, '../../../../try_task_config.json'))
+  if (fs.existsSync(config_path)) {
+    var payload = JSON.parse(fs.readFileSync(config_path));
+    if (payload['version'] == 2) {
+      queue.addParameters(payload['parameters']);
+    }
+  }
+
+  // Check for try syntax in changeset comment.
+  let match = comment.match(/\btry:\s*(.*)\s*$/m);
+
+  // Add try syntax filter.
+  if (match) {
+    let match1 = match[1];
+    queue.filter(filter(parseOptions(match1)));
+
+    if (match1.includes("--nspr-patch")) {
+      queue.map(task => {
+        if (!task.env) {
+          task.env = {};
+        }
+        task.env.ALLOW_NSPR_PATCH = "1";
+        return task;
+      });
+    }
+  }
+}
diff --git a/nss-3.88/nss/automation/taskcluster/image_builder/Dockerfile b/nss-3.88/nss/automation/taskcluster/image_builder/Dockerfile
new file mode 100644
index 0000000..f8b4edc
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/image_builder/Dockerfile
@@ -0,0 +1,23 @@
+FROM ubuntu:16.04
+MAINTAINER Tim Taubert <ttaubert@mozilla.com>
+
+WORKDIR /home/worker
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt-get update && apt-get install -y apt-transport-https apt-utils
+RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 && \
+    sh -c "echo deb https://get.docker.io/ubuntu docker main \
+    > /etc/apt/sources.list.d/docker.list"
+RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 41BD8711B1F0EC2B0D85B91CF59CE3A8323293EE && \
+    sh -c "echo deb http://ppa.launchpad.net/mercurial-ppa/releases/ubuntu xenial main \
+    > /etc/apt/sources.list.d/mercurial.list"
+RUN apt-get update && apt-get install -y \
+    lxc-docker-1.6.1 \
+    mercurial
+
+ADD bin /home/worker/bin
+RUN chmod +x /home/worker/bin/*
+
+# Set a default command useful for debugging
+CMD ["/bin/bash", "--login"]
diff --git a/nss-3.88/nss/automation/taskcluster/image_builder/VERSION b/nss-3.88/nss/automation/taskcluster/image_builder/VERSION
new file mode 100644
index 0000000..9faa1b7
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/image_builder/VERSION
@@ -0,0 +1 @@
+0.1.5
diff --git a/nss-3.88/nss/automation/taskcluster/image_builder/bin/checkout.sh b/nss-3.88/nss/automation/taskcluster/image_builder/bin/checkout.sh
new file mode 100644
index 0000000..0cdd2ac
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/image_builder/bin/checkout.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+# Default values for testing.
+REVISION=${NSS_HEAD_REVISION:-default}
+REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
+
+# Clone NSS.
+for i in 0 2 5; do
+    sleep $i
+    hg clone -r $REVISION $REPOSITORY nss && exit 0
+    rm -rf nss
+done
+exit 1
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/build.sh b/nss-3.88/nss/automation/taskcluster/scripts/build.sh
new file mode 100755
index 0000000..42ac822
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/build.sh
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+
+source $(dirname "$0")/tools.sh
+
+if [ -n "$NSS_BUILD_MODULAR" ]; then
+    $(dirname "$0")/build_nspr.sh || exit $?
+    $(dirname "$0")/build_util.sh || exit $?
+    $(dirname "$0")/build_softoken.sh || exit $?
+    $(dirname "$0")/build_nss.sh || exit $?
+    exit
+fi
+
+# Clone NSPR if needed.
+hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
+
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
+# Build.
+make -C nss nss_build_all
+
+# Package.
+mkdir artifacts
+tar cvfjh artifacts/dist.tar.bz2 dist
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/build_gyp.sh b/nss-3.88/nss/automation/taskcluster/scripts/build_gyp.sh
new file mode 100755
index 0000000..2cb0deb
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/build_gyp.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+source $(dirname "$0")/tools.sh
+
+# Clone NSPR if needed.
+hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
+
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
+# Build.
+nss/build.sh -g -v --enable-libpkix -Denable_draft_hpke=1 "$@"
+
+# Package.
+if [[ $(uname) = "Darwin" ]]; then
+  mkdir -p public
+  tar cvfjh public/dist.tar.bz2 dist
+else
+  mkdir artifacts
+  tar cvfjh artifacts/dist.tar.bz2 dist
+fi
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/build_image.sh b/nss-3.88/nss/automation/taskcluster/scripts/build_image.sh
new file mode 100755
index 0000000..3a469cf
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/build_image.sh
@@ -0,0 +1,27 @@
+#!/bin/bash -vex
+
+set -x -e -v
+
+# Prefix errors with taskcluster error prefix so that they are parsed by Treeherder
+raise_error() {
+   echo
+   echo "[taskcluster-image-build:error] $1"
+   exit 1
+}
+
+# Ensure that the PROJECT is specified so the image can be indexed
+test -n "$PROJECT" || raise_error "Project must be provided."
+test -n "$HASH" || raise_error "Context Hash must be provided."
+
+CONTEXT_PATH="/home/worker/nss/$CONTEXT_PATH"
+
+test -d "$CONTEXT_PATH" || raise_error "Context Path $CONTEXT_PATH does not exist."
+test -f "$CONTEXT_PATH/Dockerfile" || raise_error "Dockerfile must be present in $CONTEXT_PATH."
+
+apt-get update
+apt-get -y install zstd
+
+docker build -t "$PROJECT:$HASH" "$CONTEXT_PATH"
+
+mkdir /artifacts
+docker save "$PROJECT:$HASH" | zstd > /artifacts/image.tar.zst
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/build_nspr.sh b/nss-3.88/nss/automation/taskcluster/scripts/build_nspr.sh
new file mode 100755
index 0000000..b104e43
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/build_nspr.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+source $(dirname $0)/tools.sh
+
+# Clone NSPR if needed.
+hg_clone https://hg.mozilla.org/projects/nspr nspr default
+
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
+# Build.
+rm -rf dist
+make -C nss build_nspr
+
+# Package.
+test -d artifacts || mkdir artifacts
+rm -rf dist-nspr
+mv dist dist-nspr
+tar cvfjh artifacts/dist-nspr.tar.bz2 dist-nspr
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/build_nss.sh b/nss-3.88/nss/automation/taskcluster/scripts/build_nss.sh
new file mode 100755
index 0000000..b909bc3
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/build_nss.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+source $(dirname $0)/tools.sh
+source $(dirname $0)/split.sh
+
+test -d dist-softoken || { echo "run build_softoken.sh first" 1>&2; exit 1; }
+
+rm -rf nss-nss
+split_nss nss nss-nss
+
+# Build.
+export NSS_BUILD_WITHOUT_SOFTOKEN=1
+export NSS_USE_SYSTEM_FREEBL=1
+
+platform=`make -s -C nss platform`
+
+export NSPR_LIB_DIR="$PWD/dist-nspr/$platform/lib"
+export NSSUTIL_LIB_DIR="$PWD/dist-util/$platform/lib"
+export FREEBL_LIB_DIR="$PWD/dist-softoken/$platform/lib"
+export SOFTOKEN_LIB_DIR="$PWD/dist-softoken/$platform/lib"
+export FREEBL_LIBS=-lfreebl
+
+export NSS_NO_PKCS11_BYPASS=1
+export FREEBL_NO_DEPEND=1
+
+export LIBRARY_PATH="$PWD/dist-nspr/$platform/lib:$PWD/dist-util/$platform/lib:$PWD/dist-softoken/$platform/lib"
+export LD_LIBRARY_PATH="$LIBRARY_PATH:$LD_LIBRARY_PATH"
+export INCLUDES="-I$PWD/dist-nspr/$platform/include -I$PWD/dist-util/public/nss -I$PWD/dist-softoken/public/nss"
+
+rm -rf dist
+make -C nss-nss nss_build_all
+
+# Package.
+test -d artifacts || mkdir artifacts
+rm -rf dist-nss
+mv dist dist-nss
+tar cvfjh artifacts/dist-nss.tar.bz2 dist-nss
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/build_softoken.sh b/nss-3.88/nss/automation/taskcluster/scripts/build_softoken.sh
new file mode 100755
index 0000000..5f60456
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/build_softoken.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+source $(dirname $0)/tools.sh
+source $(dirname $0)/split.sh
+
+test -d dist-util || { echo "run build_util.sh first" 1>&2; exit 1; }
+
+rm -rf nss-softoken
+split_softoken nss nss-softoken
+
+# Build.
+platform=`make -s -C nss platform`
+export LIBRARY_PATH="$PWD/dist-nspr/$platform/lib:$PWD/dist-util/$platform/lib"
+export LD_LIBRARY_PATH="$LIBRARY_PATH:$LD_LIBRARY_PATH"
+export INCLUDES="-I$PWD/dist-nspr/$platform/include -I$PWD/dist-util/public/nss"
+export NSS_BUILD_SOFTOKEN_ONLY=1
+
+rm -rf dist
+make -C nss-softoken nss_build_all
+
+for i in blapi alghmac cmac; do
+    mv "dist/private/nss/${i}.h" dist/public/nss
+done
+
+# Package.
+test -d artifacts || mkdir artifacts
+rm -rf dist-softoken
+mv dist dist-softoken
+tar cvfjh artifacts/dist-softoken.tar.bz2 dist-softoken
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/build_util.sh b/nss-3.88/nss/automation/taskcluster/scripts/build_util.sh
new file mode 100755
index 0000000..0d2ecc5
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/build_util.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+source $(dirname $0)/tools.sh
+source $(dirname $0)/split.sh
+
+rm -rf nss-util
+split_util nss nss-util
+
+# Build.
+platform=`make -s -C nss platform`
+export LIBRARY_PATH="$PWD/dist-nspr/$platform/lib"
+export LD_LIBRARY_PATH="$LIBRARY_PATH:$LD_LIBRARY_PATH"
+export INCLUDES="-I$PWD/dist-nspr/$platform/include"
+export NSS_BUILD_UTIL_ONLY=1
+
+rm -rf dist
+make -C nss-util nss_build_all
+
+# Package.
+test -d artifacts || mkdir artifacts
+rm -rf dist-util
+mv dist dist-util
+tar cvfjh artifacts/dist-util.tar.bz2 dist-util
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/check_abi.sh b/nss-3.88/nss/automation/taskcluster/scripts/check_abi.sh
new file mode 100755
index 0000000..0bd8d96
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/check_abi.sh
@@ -0,0 +1,180 @@
+#! /bin/bash
+
+set_env()
+{
+  cd /home/worker
+  HGDIR=/home/worker
+  OUTPUTDIR=$(pwd)$(echo "/output")
+  DATE=$(date "+TB [%Y-%m-%d %H:%M:%S]")
+
+  if [ ! -d "${OUTPUTDIR}" ]; then
+    echo "Creating output dir"
+    mkdir "${OUTPUTDIR}"
+  fi
+
+  if [ ! -d "nspr" ]; then
+    for i in 0 2 5; do
+      sleep $i
+      hg clone -r "default" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/nspr" && break
+      rm -rf nspr
+    done
+  fi
+
+  if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+    pushd nspr
+    cat ../nss/nspr.patch | patch -p1
+    popd
+  fi
+
+  cd nss
+  ./build.sh -v -c
+  cd ..
+}
+
+check_abi()
+{
+  set_env
+  set +e #reverses set -e from build.sh to allow possible hg clone failures
+  if [[ "$1" != --nobuild ]]; then # Start nobuild block
+
+    echo "######## NSS ABI CHECK ########"
+    echo "######## creating temporary HG clones ########"
+
+    rm -rf ${HGDIR}/baseline
+    mkdir ${HGDIR}/baseline
+    BASE_NSS=`cat ${HGDIR}/nss/automation/abi-check/previous-nss-release`  #Reads the version number of the last release from the respective file
+    NSS_CLONE_RESULT=0
+    for i in 0 2 5; do
+        sleep $i
+        hg clone -u "${BASE_NSS}" "https://hg.mozilla.org/projects/nss" "${HGDIR}/baseline/nss"
+        if [ $? -eq 0 ]; then
+          NSS_CLONE_RESULT=0
+          break
+        fi
+        rm -rf "${HGDIR}/baseline/nss"
+        NSS_CLONE_RESULT=1
+    done
+    if [ ${NSS_CLONE_RESULT} -ne 0 ]; then
+      echo "invalid tag in automation/abi-check/previous-nss-release"
+      return 1
+    fi
+
+    BASE_NSPR=NSPR_$(head -1 ${HGDIR}/baseline/nss/automation/release/nspr-version.txt | cut -d . -f 1-2 | tr . _)_BRANCH
+    hg clone -u "${BASE_NSPR}" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/baseline/nspr"
+    NSPR_CLONE_RESULT=$?
+
+    if [ ${NSPR_CLONE_RESULT} -ne 0 ]; then
+      rm -rf "${HGDIR}/baseline/nspr"
+      for i in 0 2 5; do
+          sleep $i
+          hg clone -u "default" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/baseline/nspr" && break
+          rm -rf "${HGDIR}/baseline/nspr"
+      done
+      echo "Nonexisting tag ${BASE_NSPR} derived from ${BASE_NSS} automation/release/nspr-version.txt"
+      echo "Using default branch instead."
+    fi
+
+    echo "######## building baseline NSPR/NSS ########"
+    echo "${HGDIR}/baseline/nss/build.sh"
+    cd ${HGDIR}/baseline/nss
+    ./build.sh -v -c
+    cd ${HGDIR}
+  else  # Else nobuild block
+    echo "######## using existing baseline NSPR/NSS build ########"
+  fi # End nobuild block
+
+  set +e #reverses set -e from build.sh to allow abidiff failures
+
+  echo "######## Starting abidiff procedure ########"
+  abi_diff
+}
+
+#Slightly modified from build.sh in this directory
+abi_diff()
+{
+  ABI_PROBLEM_FOUND=0
+  ABI_REPORT=${OUTPUTDIR}/abi-diff.txt
+  rm -f ${ABI_REPORT}
+  PREVDIST=${HGDIR}/baseline/dist
+  NEWDIST=${HGDIR}/dist
+  # libnssdbm3.so isn't built by default anymore, skip it.
+  ALL_SOs="libfreebl3.so libfreeblpriv3.so libnspr4.so libnss3.so libnssckbi.so libnsssysinit.so libnssutil3.so libplc4.so libplds4.so libsmime3.so libsoftokn3.so libssl3.so"
+  for SO in ${ALL_SOs}; do
+      if [ ! -f ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt ]; then
+          touch ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt
+      fi
+      abidiff --hd1 $PREVDIST/public/ --hd2 $NEWDIST/public \
+          $PREVDIST/*/lib/$SO $NEWDIST/*/lib/$SO \
+          > ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt
+      RET=$?
+      cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \
+          | grep -v "^Functions changes summary:" \
+          | grep -v "^Variables changes summary:" \
+          | sed -e 's/__anonymous_enum__[0-9]*/__anonymous_enum__/g' \
+          > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt
+      rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt
+
+      ABIDIFF_ERROR=$((($RET & 0x01) != 0))
+      ABIDIFF_USAGE_ERROR=$((($RET & 0x02) != 0))
+      ABIDIFF_ABI_CHANGE=$((($RET & 0x04) != 0))
+      ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$((($RET & 0x08) != 0))
+      ABIDIFF_UNKNOWN_BIT_SET=$((($RET & 0xf0) != 0))
+
+      # If abidiff reports an error, or a usage error, or if it sets a result
+      # bit value this script doesn't know yet about, we'll report failure.
+      # For ABI changes, we don't yet report an error. We'll compare the
+      # result report with our allowlist. This allows us to silence changes
+      # that we're already aware of and have been declared acceptable.
+
+      REPORT_RET_AS_FAILURE=0
+      if [ $ABIDIFF_ERROR -ne 0 ]; then
+          echo "abidiff reported ABIDIFF_ERROR."
+          REPORT_RET_AS_FAILURE=1
+      fi
+      if [ $ABIDIFF_USAGE_ERROR -ne 0 ]; then
+          echo "abidiff reported ABIDIFF_USAGE_ERROR."
+          REPORT_RET_AS_FAILURE=1
+      fi
+      if [ $ABIDIFF_UNKNOWN_BIT_SET -ne 0 ]; then
+          echo "abidiff reported ABIDIFF_UNKNOWN_BIT_SET."
+          REPORT_RET_AS_FAILURE=1
+      fi
+
+      if [ $ABIDIFF_ABI_CHANGE -ne 0 ]; then
+          echo "Ignoring abidiff result ABI_CHANGE, instead we'll check for non-allowlisted differences."
+      fi
+      if [ $ABIDIFF_ABI_INCOMPATIBLE_CHANGE -ne 0 ]; then
+          echo "Ignoring abidiff result ABIDIFF_ABI_INCOMPATIBLE_CHANGE, instead we'll check for non-allowlisted differences."
+      fi
+
+      if [ $REPORT_RET_AS_FAILURE -ne 0 ]; then
+          ABI_PROBLEM_FOUND=1
+          echo "abidiff {$PREVDIST , $NEWDIST} for $SO FAILED with result $RET, or failed writing to ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt"
+      fi
+      if [ ! -f ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt ]; then
+          ABI_PROBLEM_FOUND=1
+          echo "FAILED to access report file: ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt"
+      fi
+
+      diff -wB -u ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt \
+              ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt >> ${ABI_REPORT}
+      if [ ! -f ${ABI_REPORT} ]; then
+          ABI_PROBLEM_FOUND=1
+          echo "FAILED to compare exepcted and new report: ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt"
+      fi
+  done
+
+  if [ -s ${ABI_REPORT} ]; then
+      echo "FAILED: there are new unexpected ABI changes"
+      cat ${ABI_REPORT}
+      return 1
+  elif [ $ABI_PROBLEM_FOUND -ne 0 ]; then
+      echo "FAILED: failure executing the ABI checks"
+      cat ${ABI_REPORT}
+      return 1
+  fi
+
+  return 0
+}
+
+check_abi $1
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/extend_task_graph.sh b/nss-3.88/nss/automation/taskcluster/scripts/extend_task_graph.sh
new file mode 100755
index 0000000..ade84cd
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/extend_task_graph.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+source $(dirname "$0")/tools.sh
+
+mkdir -p /home/worker/artifacts
+
+# Install Node.JS dependencies.
+cd nss/automation/taskcluster/graph/ && npm install
+
+# Extend the task graph.
+node lib/index.js
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/fuzz.sh b/nss-3.88/nss/automation/taskcluster/scripts/fuzz.sh
new file mode 100755
index 0000000..75851ff
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/fuzz.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+source $(dirname "$0")/tools.sh
+
+type="$1"
+shift
+
+# Fetch artifact if needed.
+fetch_dist
+
+# Clone corpus.
+./nss/fuzz/config/clone_corpus.sh
+
+# Ensure we have a corpus.
+if [ ! -d "nss/fuzz/corpus/$type" ]; then
+  mkdir -p nss/fuzz/corpus/$type
+
+  set +x
+
+  # Create a corpus out of what we have.
+  for f in $(find nss/fuzz/corpus -type f); do
+    cp $f "nss/fuzz/corpus/$type"
+  done
+
+  set -x
+fi
+
+# Fetch objdir name.
+objdir=$(cat dist/latest)
+
+# Run nssfuzz.
+dist/$objdir/bin/nssfuzz-"$type" "$@"
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/gen_certs.sh b/nss-3.88/nss/automation/taskcluster/scripts/gen_certs.sh
new file mode 100755
index 0000000..c03db7e
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/gen_certs.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+source $(dirname "$0")/tools.sh
+
+# Fetch artifact if needed.
+fetch_dist
+
+# Generate certificates.
+NSS_TESTS=cert NSS_CYCLES="standard pkix sharedb" $(dirname $0)/run_tests.sh
+
+# Reset test counter so that test runs pick up our certificates.
+echo 1 > tests_results/security/localhost
+
+# Package.
+if [[ $(uname) = "Darwin" ]]; then
+  mkdir -p public
+  tar cvfjh public/dist.tar.bz2 dist tests_results
+else
+  mkdir artifacts
+  tar cvfjh artifacts/dist.tar.bz2 dist tests_results
+fi
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/gen_coverage_report.sh b/nss-3.88/nss/automation/taskcluster/scripts/gen_coverage_report.sh
new file mode 100755
index 0000000..dc7d77d
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/gen_coverage_report.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+source $(dirname "$0")/tools.sh
+
+# Clone NSPR.
+hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
+
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
+out=/home/worker/artifacts
+mkdir -p $out
+
+# Generate coverage report.
+cd nss && ./mach coverage --outdir=$out ssl_gtests
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/run_hacl.sh b/nss-3.88/nss/automation/taskcluster/scripts/run_hacl.sh
new file mode 100755
index 0000000..7b82c91
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/run_hacl.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+if [[ $(id -u) -eq 0 ]]; then
+    # Drop privileges by re-running this script.
+    # Note: this mangles arguments, better to avoid running scripts as root.
+    exec su worker -c "$0 $*"
+fi
+
+set -e -x -v
+
+# The docker image this is running in has NSS sources.
+# Get the HACL* source, containing a snapshot of the C code, extracted on the
+# HACL CI.
+# When bug 1593647 is resolved, extract the code on CI again.
+git clone -q "https://github.com/project-everest/hacl-star" ~/hacl-star
+git -C ~/hacl-star checkout -q c95ab70fcb2bc21025d8845281bc4bc8987ca683
+
+# Format the C snapshot.
+cd ~/hacl-star/dist/mozilla
+cp ~/nss/.clang-format .
+find . -type f -name '*.[ch]' -exec clang-format -i {} \+
+cd ~/hacl-star/dist/kremlin
+cp ~/nss/.clang-format .
+find . -type f -name '*.[ch]' -exec clang-format -i {} \+
+
+# These diff commands will return 1 if there are differences and stop the script.
+files=($(find ~/nss/lib/freebl/verified/ -type f -name '*.[ch]'))
+for f in "${files[@]}"; do
+    file_name=$(basename "$f")
+    hacl_file=($(find ~/hacl-star/dist/mozilla/ ~/hacl-star/dist/kremlin/ -type f -name $file_name))
+    diff $hacl_file $f
+done
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/run_scan_build.sh b/nss-3.88/nss/automation/taskcluster/scripts/run_scan_build.sh
new file mode 100755
index 0000000..0e4fcbd
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/run_scan_build.sh
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+
+source $(dirname "$0")/tools.sh
+
+# Clone NSPR if needed.
+if [ ! -d "nspr" ]; then
+    hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
+
+    if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+      pushd nspr
+      cat ../nss/nspr.patch | patch -p1
+      popd
+    fi
+fi
+
+# Build.
+cd nss
+make nss_build_all
+
+# What we want to scan.
+# key: directory to scan
+# value: number of errors expected in that directory
+declare -A scan=( \
+        [lib/base]=0 \
+        [lib/certdb]=0 \
+        [lib/certhigh]=0 \
+        [lib/ckfw]=0 \
+        [lib/crmf]=0 \
+        [lib/cryptohi]=0 \
+        [lib/dev]=0 \
+        [lib/freebl]=0 \
+        [lib/nss]=0 \
+        [lib/ssl]=0 \
+        [lib/util]=0 \
+    )
+
+# remove .OBJ directories to force a rebuild of just the select few
+for i in "${!scan[@]}"; do
+   find "$i" -name "*.OBJ" -exec rm -rf {} \+
+done
+
+# run scan-build (only building affected directories)
+scan-build-5.0 -o /home/worker/artifacts --use-cc=$CC --use-c++=$CCC make nss_build_all && cd ..
+
+# print errors we found
+set +v +x
+STATUS=0
+for i in "${!scan[@]}"; do
+   n=$(grep -Rn "$i" /home/worker/artifacts/*/report-*.html | wc -l)
+   if [ $n -ne ${scan[$i]} ]; then
+     STATUS=1
+     echo "$(date '+%T') WARNING - TEST-UNEXPECTED-FAIL: $i contains $n scan-build errors"
+   elif [ $n -ne 0 ]; then
+     echo "$(date '+%T') WARNING - TEST-EXPECTED-FAIL: $i contains $n scan-build errors"
+   fi
+done
+exit $STATUS
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/run_tests.sh b/nss-3.88/nss/automation/taskcluster/scripts/run_tests.sh
new file mode 100755
index 0000000..b8e2676
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/run_tests.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+source $(dirname "$0")/tools.sh
+
+# Fetch artifact if needed.
+fetch_dist
+
+# Run tests.
+cd nss/tests && ./all.sh
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/split.sh b/nss-3.88/nss/automation/taskcluster/scripts/split.sh
new file mode 100644
index 0000000..d4ed4cc
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/split.sh
@@ -0,0 +1,147 @@
+copy_top()
+{
+  srcdir_="$1"
+  dstdir_="$2"
+  files=`find "$srcdir_" -maxdepth 1 -mindepth 1 -type f`
+  for f in $files; do
+    cp -p "$f" "$dstdir_"
+  done
+}
+
+split_util() {
+  nssdir="$1"
+  dstdir="$2"
+
+  # Prepare a source tree only containing files to build nss-util:
+  #
+  #   nss/dbm                     full directory
+  #   nss/coreconf                full directory
+  #   nss                         top files only
+  #   nss/lib                     top files only
+  #   nss/lib/util                full directory
+
+  # Copy everything.
+  cp -R $nssdir $dstdir
+
+  # Remove subdirectories that we don't want.
+  rm -rf $dstdir/cmd
+  rm -rf $dstdir/lib
+  rm -rf $dstdir/automation
+  rm -rf $dstdir/doc
+
+  # Start with an empty cmd lib directories to be filled selectively.
+  mkdir $dstdir/cmd
+  cp $nssdir/cmd/Makefile $dstdir/cmd
+  cp $nssdir/cmd/manifest.mn $dstdir/cmd
+  cp $nssdir/cmd/platlibs.mk $dstdir/cmd
+  cp $nssdir/cmd/platrules.mk $dstdir/cmd
+
+  # Copy some files at the top and the util subdirectory recursively.
+  mkdir $dstdir/lib
+  cp $nssdir/lib/Makefile $dstdir/lib
+  cp -R $nssdir/lib/util $dstdir/lib/util
+}
+
+split_softoken() {
+  nssdir="$1"
+  dstdir="$2"
+
+  # Prepare a source tree only containing files to build nss-softoken:
+  #
+  #   nss/dbm                     full directory
+  #   nss/coreconf                full directory
+  #   nss                         top files only
+  #   nss/lib                     top files only
+  #   nss/lib/freebl              full directory
+  #   nss/lib/softoken            full directory
+  #   nss/lib/softoken/dbm        full directory
+
+  # Copy everything.
+  cp -R $nssdir $dstdir
+
+  # Skip gtests when building.
+  sed '/^DIRS = /s/ cpputil gtests$//' $nssdir/manifest.mn > $dstdir/manifest.mn-t && mv $dstdir/manifest.mn-t $dstdir/manifest.mn
+
+  # Remove subdirectories that we don't want.
+  rm -rf $dstdir/cmd
+  rm -rf $dstdir/tests
+  rm -rf $dstdir/lib
+  rm -rf $dstdir/pkg
+  rm -rf $dstdir/automation
+  rm -rf $dstdir/gtests
+  rm -rf $dstdir/cpputil
+  rm -rf $dstdir/doc
+
+  # Start with an empty lib directory and copy only what we need.
+  mkdir $dstdir/lib
+  copy_top $nssdir/lib $dstdir/lib
+  cp -R $nssdir/lib/dbm $dstdir/lib/dbm
+  cp -R $nssdir/lib/freebl $dstdir/lib/freebl
+  cp -R $nssdir/lib/softoken $dstdir/lib/softoken
+  cp -R $nssdir/lib/sqlite $dstdir/lib/sqlite
+
+  mkdir $dstdir/cmd
+  copy_top $nssdir/cmd $dstdir/cmd
+  cp -R $nssdir/cmd/bltest $dstdir/cmd/bltest
+  cp -R $nssdir/cmd/ecperf $dstdir/cmd/ecperf
+  cp -R $nssdir/cmd/fbectest $dstdir/cmd/fbectest
+  cp -R $nssdir/cmd/fipstest $dstdir/cmd/fipstest
+  cp -R $nssdir/cmd/lib $dstdir/cmd/lib
+  cp -R $nssdir/cmd/lowhashtest $dstdir/cmd/lowhashtest
+  cp -R $nssdir/cmd/shlibsign $dstdir/cmd/shlibsign
+
+  mkdir $dstdir/tests
+  copy_top $nssdir/tests $dstdir/tests
+
+  cp -R $nssdir/tests/cipher $dstdir/tests/cipher
+  cp -R $nssdir/tests/common $dstdir/tests/common
+  cp -R $nssdir/tests/ec $dstdir/tests/ec
+  cp -R $nssdir/tests/lowhash $dstdir/tests/lowhash
+
+  cp $nssdir/lib/util/verref.h $dstdir/lib/freebl
+  cp $nssdir/lib/util/verref.h $dstdir/lib/softoken
+  cp $nssdir/lib/util/verref.h $dstdir/lib/softoken/legacydb
+}
+
+split_nss() {
+  nssdir="$1"
+  dstdir="$2"
+
+  # Prepare a source tree only containing files to build nss:
+  #
+  #   nss/dbm                     full directory
+  #   nss/coreconf                full directory
+  #   nss                         top files only
+  #   nss/lib                     top files only
+  #   nss/lib/freebl              full directory
+  #   nss/lib/softoken            full directory
+  #   nss/lib/softoken/dbm        full directory
+
+  # Copy everything.
+  cp -R $nssdir $dstdir
+
+  # Remove subdirectories that we don't want.
+  rm -rf $dstdir/lib/freebl
+  rm -rf $dstdir/lib/softoken
+  rm -rf $dstdir/lib/util
+  rm -rf $dstdir/cmd/bltest
+  rm -rf $dstdir/cmd/fipstest
+  rm -rf $dstdir/cmd/rsaperf_low
+
+  # Copy these headers until the upstream bug is accepted
+  # Upstream https://bugzilla.mozilla.org/show_bug.cgi?id=820207
+  cp $nssdir/lib/softoken/lowkeyi.h $dstdir/cmd/rsaperf
+  cp $nssdir/lib/softoken/lowkeyti.h $dstdir/cmd/rsaperf
+
+  # Copy verref.h which will be needed later during the build phase.
+  cp $nssdir/lib/util/verref.h $dstdir/lib/ckfw/builtins/verref.h
+  cp $nssdir/lib/util/verref.h $dstdir/lib/nss/verref.h
+  cp $nssdir/lib/util/verref.h $dstdir/lib/smime/verref.h
+  cp $nssdir/lib/util/verref.h $dstdir/lib/ssl/verref.h
+  cp $nssdir/lib/util/templates.c $dstdir/lib/nss/templates.c
+
+  # FIXME: Skip util_gtest because it links with libnssutil.a.  Note
+  # that we can't use libnssutil3.so instead, because util_gtest
+  # depends on internal symbols not exported from the shared library.
+  sed '/	util_gtest \\/d' $dstdir/gtests/manifest.mn > $dstdir/gtests/manifest.mn-t && mv $dstdir/gtests/manifest.mn-t $dstdir/gtests/manifest.mn
+}
diff --git a/nss-3.88/nss/automation/taskcluster/scripts/tools.sh b/nss-3.88/nss/automation/taskcluster/scripts/tools.sh
new file mode 100644
index 0000000..81563f5
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/scripts/tools.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+# Assert that we're not running as root.
+if [[ $(id -u) -eq 0 ]]; then
+    # This exec is still needed until aarch64 images are updated (Bug 1488325).
+    # Remove when images are updated.  Until then, assert that things are good.
+    [[ $(uname -m) == aarch64 ]]
+    exec su worker -c "$0 $*"
+fi
+
+export PATH="${PATH}:/home/worker/.cargo/bin/:/usr/lib/go-1.6/bin"
+
+# Usage: hg_clone repo dir [revision=@]
+hg_clone() {
+    repo=$1
+    dir=$2
+    rev=${3:-@}
+    if [ -d "$dir" ]; then
+        hg pull -R "$dir" -ur "$rev" "$repo" && return
+        rm -rf "$dir"
+    fi
+    for i in 0 2 5; do
+        sleep $i
+        hg clone -r "$rev" "$repo" "$dir" && return
+        rm -rf "$dir"
+    done
+    exit 1
+}
+
+fetch_dist() {
+    if [ "$TASKCLUSTER_ROOT_URL" = "https://taskcluster.net" ] || [ -z "$TASKCLUSTER_ROOT_URL" ]; then
+        url=https://queue.taskcluster.net/v1/task/$TC_PARENT_TASK_ID/artifacts/public/dist.tar.bz2
+    else
+        url=$TASKCLUSTER_ROOT_URL/api/queue/v1/task/$TC_PARENT_TASK_ID/artifacts/public/dist.tar.bz2
+    fi
+    if [ ! -d "dist" ]; then
+        for i in 0 2 5; do
+            sleep $i
+            curl --retry 3 -Lo dist.tar.bz2 $url && tar xvjf dist.tar.bz2 && return
+            rm -fr dist.tar.bz2 dist
+        done
+        exit 1
+    fi
+}
diff --git a/nss-3.88/nss/automation/taskcluster/windows/build.sh b/nss-3.88/nss/automation/taskcluster/windows/build.sh
new file mode 100644
index 0000000..f878a3d
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/windows/build.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [[ "$USE_64" == 1 ]]; then
+    m=x64
+else
+    m=x86
+fi
+source "$(dirname "$0")/setup.sh"
+
+# Clone NSPR.
+hg_clone https://hg.mozilla.org/projects/nspr nspr default
+
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
+# Build.
+make -C nss nss_build_all
+
+# Package.
+7z a public/build/dist.7z dist
diff --git a/nss-3.88/nss/automation/taskcluster/windows/build_gyp.sh b/nss-3.88/nss/automation/taskcluster/windows/build_gyp.sh
new file mode 100644
index 0000000..d7072eb
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/windows/build_gyp.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+# Parse for the -t option.
+m=x64
+for i in "$@"; do
+    case "$i" in
+        -t|--target) m= ;;
+        --target=*) m="${i#*=}" ;;
+        *) [[ -z "$m" ]] && m="$i" ;;
+    esac
+done
+[[ "$m" == "ia32" ]] && m=x86
+source "$(dirname "$0")/setup.sh"
+
+# Install GYP.
+pushd gyp
+python -m virtualenv test-env
+test-env/Scripts/python setup.py install
+test-env/Scripts/python -m pip install --upgrade pip
+test-env/Scripts/pip install --upgrade 'setuptools<45.0.0'
+# Fool GYP.
+touch "${VSPATH}/VC/vcvarsall.bat"
+export GYP_MSVS_OVERRIDE_PATH="${VSPATH}"
+export GYP_MSVS_VERSION=2015
+popd
+
+export PATH="${PATH}:${PWD}/ninja/bin:${PWD}/gyp/test-env/Scripts"
+
+# Clone NSPR.
+hg_clone https://hg.mozilla.org/projects/nspr nspr default
+
+if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
+  pushd nspr
+  cat ../nss/nspr.patch | patch -p1
+  popd
+fi
+
+# Build with gyp.
+./nss/build.sh -g -v --enable-libpkix -Denable_draft_hpke=1 "$@"
+
+# Package.
+7z a public/build/dist.7z dist
diff --git a/nss-3.88/nss/automation/taskcluster/windows/gen_certs.sh b/nss-3.88/nss/automation/taskcluster/windows/gen_certs.sh
new file mode 100644
index 0000000..594112b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/windows/gen_certs.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+# Set up the toolchain.
+source $(dirname $0)/setup.sh
+
+# Fetch artifact.
+if [ "$TASKCLUSTER_ROOT_URL" = "https://taskcluster.net" ] || [ -z "$TASKCLUSTER_ROOT_URL" ]; then
+    url=https://queue.taskcluster.net/v1/task/$TC_PARENT_TASK_ID/artifacts/public/build/dist.7z
+else
+    url=$TASKCLUSTER_ROOT_URL/api/queue/v1/task/$TC_PARENT_TASK_ID/artifacts/public/build/dist.7z
+fi
+
+wget -t 3 --retry-connrefused -w 5 --random-wait $url -O dist.7z
+7z x dist.7z
+
+# Generate certificates.
+NSS_TESTS=cert NSS_CYCLES="standard pkix sharedb" nss/tests/all.sh
+
+# Reset test counter so that test runs pick up our certificates.
+echo 1 > tests_results/security/localhost
+
+# Package.
+7z a public/build/dist.7z dist tests_results
diff --git a/nss-3.88/nss/automation/taskcluster/windows/releng.manifest b/nss-3.88/nss/automation/taskcluster/windows/releng.manifest
new file mode 100644
index 0000000..d571c54
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/windows/releng.manifest
@@ -0,0 +1,26 @@
+[
+  {
+    "version": "Visual Studio 2017 15.4.2 / SDK 10.0.15063.0",
+    "size": 303146863,
+    "digest": "18700889e6b5e81613b9cf57ce4e0d46a6ee45bb4c5c33bae2604a5275326128775b8a032a1eb178c5db973746d565340c4e36d98375789e1d5bd836ab16ba58",
+    "algorithm": "sha512",
+    "filename": "vs2017_15.4.2.zip",
+    "unpack": true
+  },
+  {
+    "version": "Ninja 1.7.1",
+    "size": 184821,
+    "digest": "e4f9a1ae624a2630e75264ba37d396d9c7407d6e6aea3763056210ba6e1387908bd31cf4037a6a3661a418e86c4d2761e0c333e6a3bd0d66549d2b0d72d3f43b",
+    "algorithm": "sha512",
+    "filename": "ninja171.zip",
+    "unpack": true
+  },
+  {
+    "size": 13063963,
+    "visibility": "public",
+    "digest": "47a19f8f863eab3414abab2b9e9bd901ab896c799b3d9254b456b2f59374b085b99de805e21069a0819f01eecb3f43f7e2395a8c644c04bcbfa5711261cca29d",
+    "algorithm": "sha512",
+    "filename": "gyp-2017-05-23.zip",
+    "unpack": true
+  }
+]
diff --git a/nss-3.88/nss/automation/taskcluster/windows/run_tests.sh b/nss-3.88/nss/automation/taskcluster/windows/run_tests.sh
new file mode 100644
index 0000000..2392559
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/windows/run_tests.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+# Set up the toolchain.
+source $(dirname $0)/setup.sh
+
+# Fetch artifact.
+if [ "$TASKCLUSTER_ROOT_URL" = "https://taskcluster.net" ] || [ -z "$TASKCLUSTER_ROOT_URL" ]; then
+    url=https://queue.taskcluster.net/v1/task/$TC_PARENT_TASK_ID/artifacts/public/build/dist.7z
+else
+    url=$TASKCLUSTER_ROOT_URL/api/queue/v1/task/$TC_PARENT_TASK_ID/artifacts/public/build/dist.7z
+fi
+
+wget -t 3 --retry-connrefused -w 5 --random-wait $url -O dist.7z
+7z x dist.7z
+
+# Run tests.
+cd nss/tests && ./all.sh
diff --git a/nss-3.88/nss/automation/taskcluster/windows/setup.sh b/nss-3.88/nss/automation/taskcluster/windows/setup.sh
new file mode 100644
index 0000000..d5bed3b
--- /dev/null
+++ b/nss-3.88/nss/automation/taskcluster/windows/setup.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+# Usage: hg_clone repo dir [revision=@]
+hg_clone() {
+    repo=$1
+    dir=$2
+    rev=${3:-@}
+    for i in 0 2 5; do
+        sleep $i
+        hg clone -r "$rev" "$repo" "$dir" && return
+        rm -rf "$dir"
+    done
+    exit 1
+}
+
+hg_clone https://hg.mozilla.org/build/tools tools b8d7c263dfc3
+tools/scripts/tooltool/tooltool_wrapper.sh \
+    $(dirname $0)/releng.manifest http://taskcluster/tooltool.mozilla-releng.net/ \
+    non-existant-file.sh /c/mozilla-build/python/python.exe \
+    /c/builds/tooltool.py \
+    -c /c/builds/tooltool_cache
+
+# This needs $m to be set.
+[[ -n "$m" ]]
+
+# Setup MSVC paths.
+export VSPATH="${PWD}/vs2017_15.4.2"
+UCRTVersion="10.0.15063.0"
+
+export WINDOWSSDKDIR="${VSPATH}/SDK"
+export VS90COMNTOOLS="${VSPATH}/VC"
+export WIN32_REDIST_DIR="${VSPATH}/VC/redist/${m}/Microsoft.VC141.CRT"
+export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/${m}"
+
+if [ "$m" == "x86" ]; then
+    PATH="${PATH}:${VSPATH}/VC/bin/Hostx64/x86"
+    PATH="${PATH}:${VSPATH}/VC/bin/Hostx64/x64"
+fi
+PATH="${PATH}:${VSPATH}/VC/bin/Host${m}/${m}"
+PATH="${PATH}:${WIN32_REDIST_DIR}"
+PATH="${PATH}:${WIN_UCRT_REDIST_DIR}"
+PATH="${PATH}:${VSPATH}/SDK/bin/${UCRTVersion}/x64"
+export PATH
+
+LIB="${LIB}:${VSPATH}/VC/lib/${m}"
+LIB="${LIB}:${VSPATH}/SDK/lib/${UCRTVersion}/ucrt/${m}"
+LIB="${LIB}:${VSPATH}/SDK/lib/${UCRTVersion}/um/${m}"
+export LIB
+
+INCLUDE="${INCLUDE}:${VSPATH}/VC/include"
+INCLUDE="${INCLUDE}:${VSPATH}/SDK/Include/${UCRTVersion}/ucrt"
+INCLUDE="${INCLUDE}:${VSPATH}/SDK/Include/${UCRTVersion}/shared"
+INCLUDE="${INCLUDE}:${VSPATH}/SDK/Include/${UCRTVersion}/um"
+export INCLUDE